| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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 "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/widget/widget.h" | |
| 15 #include "views/controls/combobox/combobox.h" | |
| 16 #include "views/controls/combobox/native_combobox_views.h" | |
| 17 #include "views/views_delegate.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_->IsEnabled()); | |
| 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 void NativeComboboxGtk::NativeControlCreated(GtkWidget* native_control) { | |
| 150 NativeControlGtk::NativeControlCreated(native_control); | |
| 151 // Set the initial state of the combobox. | |
| 152 UpdateFromModel(); | |
| 153 UpdateEnabled(); | |
| 154 UpdateSelectedItem(); | |
| 155 } | |
| 156 | |
| 157 //////////////////////////////////////////////////////////////////////////////// | |
| 158 // NativeComboboxGtk, private: | |
| 159 void NativeComboboxGtk::SelectionChanged() { | |
| 160 combobox_->SelectionChanged(); | |
| 161 } | |
| 162 | |
| 163 void NativeComboboxGtk::FocusedMenuItemChanged() { | |
| 164 DCHECK(menu_); | |
| 165 GtkWidget* menu_item = GTK_MENU_SHELL(menu_)->active_menu_item; | |
| 166 if (!menu_item) | |
| 167 return; | |
| 168 | |
| 169 // Figure out the item index and total number of items. | |
| 170 GList* items = gtk_container_get_children(GTK_CONTAINER(menu_)); | |
| 171 guint count = g_list_length(items); | |
| 172 int index = g_list_index(items, static_cast<gconstpointer>(menu_item)); | |
| 173 | |
| 174 // Get the menu item's label. | |
| 175 std::string name; | |
| 176 GList* children = gtk_container_get_children(GTK_CONTAINER(menu_item)); | |
| 177 for (GList* l = g_list_first(children); l != NULL; l = g_list_next(l)) { | |
| 178 GtkWidget* child = static_cast<GtkWidget*>(l->data); | |
| 179 if (GTK_IS_CELL_VIEW(child)) { | |
| 180 GtkCellView* cell_view = GTK_CELL_VIEW(child); | |
| 181 GtkTreePath* path = gtk_cell_view_get_displayed_row(cell_view); | |
| 182 GtkTreeModel* model = NULL; | |
| 183 model = gtk_cell_view_get_model(cell_view); | |
| 184 GtkTreeIter iter; | |
| 185 if (model && gtk_tree_model_get_iter(model, &iter, path)) { | |
| 186 GValue value = { 0 }; | |
| 187 gtk_tree_model_get_value(model, &iter, 0, &value); | |
| 188 name = g_value_get_string(&value); | |
| 189 break; | |
| 190 } | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 if (ViewsDelegate::views_delegate) { | |
| 195 ViewsDelegate::views_delegate->NotifyMenuItemFocused(string16(), | |
| 196 UTF8ToUTF16(name), | |
| 197 index, | |
| 198 count, | |
| 199 false); | |
| 200 } | |
| 201 } | |
| 202 | |
| 203 void NativeComboboxGtk::CallChanged(GtkWidget* widget) { | |
| 204 SelectionChanged(); | |
| 205 } | |
| 206 | |
| 207 gboolean NativeComboboxGtk::CallPopUp(GtkWidget* widget) { | |
| 208 FocusedMenuItemChanged(); | |
| 209 return false; | |
| 210 } | |
| 211 | |
| 212 void NativeComboboxGtk::CallMenuMoveCurrent( | |
| 213 GtkWidget* menu, GtkMenuDirectionType focus_direction) { | |
| 214 FocusedMenuItemChanged(); | |
| 215 } | |
| 216 | |
| 217 //////////////////////////////////////////////////////////////////////////////// | |
| 218 // NativeComboboxWrapper, public: | |
| 219 | |
| 220 // static | |
| 221 NativeComboboxWrapper* NativeComboboxWrapper::CreateWrapper( | |
| 222 Combobox* combobox) { | |
| 223 if (Widget::IsPureViews()) | |
| 224 return new NativeComboboxViews(combobox); | |
| 225 return new NativeComboboxGtk(combobox); | |
| 226 } | |
| 227 | |
| 228 } // namespace views | |
| OLD | NEW |