OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ui/views/controls/combobox/native_combobox_gtk.h" | |
6 | |
7 #include <gtk/gtk.h> | |
8 | |
9 #include <algorithm> | |
10 | |
11 #include "base/message_loop.h" | |
12 #include "base/utf_string_conversions.h" | |
13 #include "ui/base/models/combobox_model.h" | |
14 #include "ui/views/controls/combobox/combobox.h" | |
15 #include "ui/views/controls/combobox/native_combobox_views.h" | |
16 #include "ui/views/views_delegate.h" | |
17 #include "ui/views/widget/widget.h" | |
18 | |
19 namespace views { | |
20 | |
21 //////////////////////////////////////////////////////////////////////////////// | |
22 // NativeComboboxGtk, public: | |
23 | |
24 NativeComboboxGtk::NativeComboboxGtk(Combobox* combobox) | |
25 : combobox_(combobox), | |
26 menu_(NULL) { | |
27 set_focus_view(combobox); | |
28 } | |
29 | |
30 NativeComboboxGtk::~NativeComboboxGtk() { | |
31 } | |
32 | |
33 //////////////////////////////////////////////////////////////////////////////// | |
34 // NativeComboboxGtk, NativeComboboxWrapper implementation: | |
35 | |
36 void NativeComboboxGtk::UpdateFromModel() { | |
37 if (!native_view()) | |
38 return; | |
39 | |
40 preferred_size_ = gfx::Size(); | |
41 | |
42 GtkListStore* store = | |
43 GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(native_view()))); | |
44 ui::ComboboxModel* model = combobox_->model(); | |
45 int count = model->GetItemCount(); | |
46 gtk_list_store_clear(store); | |
47 GtkTreeIter iter; | |
48 while (count-- > 0) { | |
49 gtk_list_store_prepend(store, &iter); | |
50 gtk_list_store_set(store, &iter, | |
51 0, UTF16ToUTF8(model->GetItemAt(count)).c_str(), | |
52 -1); | |
53 } | |
54 } | |
55 | |
56 void NativeComboboxGtk::UpdateSelectedItem() { | |
57 if (!native_view()) | |
58 return; | |
59 gtk_combo_box_set_active( | |
60 GTK_COMBO_BOX(native_view()), combobox_->selected_item()); | |
61 } | |
62 | |
63 void NativeComboboxGtk::UpdateEnabled() { | |
64 SetEnabled(combobox_->enabled()); | |
65 } | |
66 | |
67 int NativeComboboxGtk::GetSelectedItem() const { | |
68 if (!native_view()) | |
69 return 0; | |
70 return gtk_combo_box_get_active(GTK_COMBO_BOX(native_view())); | |
71 } | |
72 | |
73 bool NativeComboboxGtk::IsDropdownOpen() const { | |
74 if (!native_view()) | |
75 return false; | |
76 gboolean popup_shown; | |
77 g_object_get(G_OBJECT(native_view()), "popup-shown", &popup_shown, NULL); | |
78 return popup_shown; | |
79 } | |
80 | |
81 gfx::Size NativeComboboxGtk::GetPreferredSize() { | |
82 if (!native_view()) | |
83 return gfx::Size(); | |
84 | |
85 if (preferred_size_.IsEmpty()) { | |
86 GtkRequisition size_request = { 0, 0 }; | |
87 gtk_widget_size_request(native_view(), &size_request); | |
88 // TODO(oshima|scott): we may not need ::max to 29. revisit this. | |
89 preferred_size_.SetSize(size_request.width, | |
90 std::max(size_request.height, 29)); | |
91 } | |
92 return preferred_size_; | |
93 } | |
94 | |
95 View* NativeComboboxGtk::GetView() { | |
96 return this; | |
97 } | |
98 | |
99 void NativeComboboxGtk::SetFocus() { | |
100 OnFocus(); | |
101 } | |
102 | |
103 bool NativeComboboxGtk::HandleKeyPressed(const views::KeyEvent& event) { | |
104 return false; | |
105 } | |
106 | |
107 bool NativeComboboxGtk::HandleKeyReleased(const views::KeyEvent& event) { | |
108 return false; | |
109 } | |
110 | |
111 void NativeComboboxGtk::HandleFocus() { | |
112 } | |
113 | |
114 void NativeComboboxGtk::HandleBlur() { | |
115 } | |
116 | |
117 gfx::NativeView NativeComboboxGtk::GetTestingHandle() const { | |
118 return native_view(); | |
119 } | |
120 | |
121 | |
122 //////////////////////////////////////////////////////////////////////////////// | |
123 // NativeComboboxGtk, NativeControlGtk overrides: | |
124 void NativeComboboxGtk::CreateNativeControl() { | |
125 GtkListStore* store = gtk_list_store_new(1, G_TYPE_STRING); | |
126 GtkWidget* widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); | |
127 g_object_unref(G_OBJECT(store)); | |
128 | |
129 GtkCellRenderer* cell = gtk_cell_renderer_text_new(); | |
130 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), cell, TRUE); | |
131 gtk_cell_layout_set_attributes( | |
132 GTK_CELL_LAYOUT(widget), cell, "text", 0, NULL); | |
133 g_signal_connect(widget, "changed", | |
134 G_CALLBACK(CallChangedThunk), this); | |
135 g_signal_connect_after(widget, "popup", | |
136 G_CALLBACK(CallPopUpThunk), this); | |
137 | |
138 // Get the menu associated with the combo box and listen to events on it. | |
139 GList* menu_list = gtk_menu_get_for_attach_widget(widget); | |
140 if (menu_list) { | |
141 menu_ = reinterpret_cast<GtkMenu*>(menu_list->data); | |
142 g_signal_connect_after(menu_, "move-current", | |
143 G_CALLBACK(CallMenuMoveCurrentThunk), this); | |
144 } | |
145 | |
146 NativeControlCreated(widget); | |
147 } | |
148 | |
149 //////////////////////////////////////////////////////////////////////////////// | |
150 // NativeComboboxGtk, private: | |
151 void NativeComboboxGtk::SelectionChanged() { | |
152 combobox_->SelectionChanged(); | |
153 } | |
154 | |
155 void NativeComboboxGtk::FocusedMenuItemChanged() { | |
156 DCHECK(menu_); | |
157 GtkWidget* menu_item = GTK_MENU_SHELL(menu_)->active_menu_item; | |
158 if (!menu_item) | |
159 return; | |
160 | |
161 // Figure out the item index and total number of items. | |
162 GList* items = gtk_container_get_children(GTK_CONTAINER(menu_)); | |
163 guint count = g_list_length(items); | |
164 int index = g_list_index(items, static_cast<gconstpointer>(menu_item)); | |
165 | |
166 // Get the menu item's label. | |
167 std::string name; | |
168 GList* children = gtk_container_get_children(GTK_CONTAINER(menu_item)); | |
169 for (GList* l = g_list_first(children); l != NULL; l = g_list_next(l)) { | |
170 GtkWidget* child = static_cast<GtkWidget*>(l->data); | |
171 if (GTK_IS_CELL_VIEW(child)) { | |
172 GtkCellView* cell_view = GTK_CELL_VIEW(child); | |
173 GtkTreePath* path = gtk_cell_view_get_displayed_row(cell_view); | |
174 GtkTreeModel* model = NULL; | |
175 model = gtk_cell_view_get_model(cell_view); | |
176 GtkTreeIter iter; | |
177 if (model && gtk_tree_model_get_iter(model, &iter, path)) { | |
178 GValue value = { 0 }; | |
179 gtk_tree_model_get_value(model, &iter, 0, &value); | |
180 name = g_value_get_string(&value); | |
181 break; | |
182 } | |
183 } | |
184 } | |
185 | |
186 if (ViewsDelegate::views_delegate) { | |
187 ViewsDelegate::views_delegate->NotifyMenuItemFocused(string16(), | |
188 UTF8ToUTF16(name), | |
189 index, | |
190 count, | |
191 false); | |
192 } | |
193 } | |
194 | |
195 void NativeComboboxGtk::CallChanged(GtkWidget* widget) { | |
196 SelectionChanged(); | |
197 } | |
198 | |
199 gboolean NativeComboboxGtk::CallPopUp(GtkWidget* widget) { | |
200 FocusedMenuItemChanged(); | |
201 return false; | |
202 } | |
203 | |
204 void NativeComboboxGtk::CallMenuMoveCurrent( | |
205 GtkWidget* menu, GtkMenuDirectionType focus_direction) { | |
206 FocusedMenuItemChanged(); | |
207 } | |
208 | |
209 //////////////////////////////////////////////////////////////////////////////// | |
210 // NativeComboboxWrapper, public: | |
211 | |
212 // static | |
213 NativeComboboxWrapper* NativeComboboxWrapper::CreateWrapper( | |
214 Combobox* combobox) { | |
215 if (Widget::IsPureViews()) | |
216 return new NativeComboboxViews(combobox); | |
217 return new NativeComboboxGtk(combobox); | |
218 } | |
219 | |
220 } // namespace views | |
OLD | NEW |