| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/gtk/website_settings/permission_selector.h" | 5 #include "chrome/browser/ui/gtk/website_settings/permission_selector.h" |
| 6 | 6 |
| 7 #include <gtk/gtk.h> | |
| 8 | |
| 9 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/i18n/rtl.h" |
| 9 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/browser/ui/gtk/gtk_theme_service.h" | 10 #include "chrome/browser/ui/gtk/gtk_theme_service.h" |
| 11 #include "chrome/browser/ui/gtk/gtk_util.h" | 11 #include "chrome/browser/ui/gtk/gtk_util.h" |
| 12 #include "chrome/browser/ui/gtk/menu_gtk.h" |
| 12 #include "chrome/browser/ui/website_settings/website_settings_ui.h" | 13 #include "chrome/browser/ui/website_settings/website_settings_ui.h" |
| 13 #include "grit/generated_resources.h" | 14 #include "grit/generated_resources.h" |
| 15 #include "grit/theme_resources.h" |
| 14 #include "ui/base/gtk/gtk_hig_constants.h" | 16 #include "ui/base/gtk/gtk_hig_constants.h" |
| 15 #include "ui/base/l10n/l10n_util.h" | 17 #include "ui/base/l10n/l10n_util.h" |
| 18 #include "ui/base/models/menu_model.h" |
| 19 #include "ui/base/resource/resource_bundle.h" |
| 16 #include "ui/gfx/image/image.h" | 20 #include "ui/gfx/image/image.h" |
| 17 | 21 |
| 18 namespace { | 22 namespace { |
| 19 | 23 |
| 20 GtkWidget* CreateTextLabel(const std::string& text, | 24 ContentSetting CommandIdToContentSetting(int command_id) { |
| 21 GtkThemeService* theme_service) { | 25 switch (command_id) { |
| 22 GtkWidget* label = theme_service->BuildLabel(text, ui::kGdkBlack); | 26 case PermissionMenuModel::COMMAND_SET_TO_DEFAULT: |
| 23 gtk_label_set_selectable(GTK_LABEL(label), TRUE); | 27 return CONTENT_SETTING_DEFAULT; |
| 24 gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR); | 28 case PermissionMenuModel::COMMAND_SET_TO_ALLOW: |
| 25 return label; | 29 return CONTENT_SETTING_ALLOW; |
| 30 case PermissionMenuModel::COMMAND_SET_TO_BLOCK: |
| 31 return CONTENT_SETTING_BLOCK; |
| 32 default: |
| 33 NOTREACHED(); |
| 34 return CONTENT_SETTING_DEFAULT; |
| 35 } |
| 26 } | 36 } |
| 27 | 37 |
| 28 } // namespace | 38 } // namespace |
| 29 | 39 |
| 30 PermissionSelector::PermissionSelector(GtkThemeService* theme_service, | 40 PermissionSelector::PermissionSelector(GtkThemeService* theme_service, |
| 31 ContentSettingsType type, | 41 ContentSettingsType type, |
| 32 ContentSetting setting, | 42 ContentSetting setting, |
| 33 ContentSetting default_setting) | 43 ContentSetting default_setting, |
| 34 : theme_service_(theme_service), | 44 content_settings::SettingSource source) |
| 45 : widget_(NULL), |
| 46 menu_button_(NULL), |
| 47 icon_(NULL), |
| 35 type_(type), | 48 type_(type), |
| 36 setting_(setting), | |
| 37 default_setting_(default_setting), | 49 default_setting_(default_setting), |
| 38 icon_(NULL) { | 50 setting_(setting) { |
| 39 DCHECK_NE(default_setting, CONTENT_SETTING_DEFAULT); | 51 DCHECK_NE(default_setting, CONTENT_SETTING_DEFAULT); |
| 52 |
| 53 // Create permission info box. |
| 54 const int kChildSpacing = 4; |
| 55 widget_ = gtk_hbox_new(FALSE, kChildSpacing); |
| 56 |
| 57 // Add permission type icon. |
| 58 ContentSetting effective_setting = setting; |
| 59 if (effective_setting == CONTENT_SETTING_DEFAULT) |
| 60 effective_setting = default_setting; |
| 61 GdkPixbuf* pixbuf = WebsiteSettingsUI::GetPermissionIcon( |
| 62 type, effective_setting).ToGdkPixbuf(); |
| 63 icon_ = gtk_image_new_from_pixbuf(pixbuf); |
| 64 gtk_box_pack_start(GTK_BOX(widget_), icon_, FALSE, FALSE, 0); |
| 65 |
| 66 // Add a label for the permission type. |
| 67 GtkWidget* label = theme_service->BuildLabel(l10n_util::GetStringFUTF8( |
| 68 IDS_WEBSITE_SETTINGS_PERMISSION_TYPE, |
| 69 WebsiteSettingsUI::PermissionTypeToUIString(type)), |
| 70 ui::kGdkBlack); |
| 71 gtk_label_set_selectable(GTK_LABEL(label), TRUE); |
| 72 gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR); |
| 73 |
| 74 gtk_box_pack_start(GTK_BOX(widget_), label, FALSE, FALSE, 0); |
| 75 |
| 76 // Add the menu button. |
| 77 menu_button_ = gtk_button_new_with_label( |
| 78 UTF16ToUTF8(WebsiteSettingsUI::PermissionActionToUIString( |
| 79 setting, default_setting, source)).c_str()); |
| 80 bool user_setting = source == content_settings::SETTING_SOURCE_USER; |
| 81 gtk_widget_set_sensitive(GTK_WIDGET(menu_button_), user_setting); |
| 82 if (user_setting) { |
| 83 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 84 pixbuf = rb.GetNativeImageNamed(IDR_APP_DROPARROW).ToGdkPixbuf(); |
| 85 GtkWidget* arrow = gtk_image_new_from_pixbuf(pixbuf); |
| 86 gtk_button_set_image(GTK_BUTTON(menu_button_), arrow); |
| 87 gtk_button_set_image_position(GTK_BUTTON(menu_button_), |
| 88 base::i18n::IsRTL() ? GTK_POS_LEFT |
| 89 : GTK_POS_RIGHT); |
| 90 } |
| 91 gtk_button_set_relief(GTK_BUTTON(menu_button_), GTK_RELIEF_NONE); |
| 92 gtk_box_pack_start(GTK_BOX(widget_), menu_button_, FALSE, FALSE, 0); |
| 93 |
| 94 menu_model_.reset(new PermissionMenuModel(this, type, default_setting, |
| 95 setting)); |
| 96 MenuGtk::Delegate* delegate = new MenuGtk::Delegate(); |
| 97 menu_.reset(new MenuGtk(delegate, menu_model_.get())); |
| 98 g_signal_connect(menu_button_, "button-press-event", |
| 99 G_CALLBACK(OnMenuButtonPressEventThunk), this); |
| 40 } | 100 } |
| 41 | 101 |
| 42 PermissionSelector::~PermissionSelector() { | 102 PermissionSelector::~PermissionSelector() { |
| 43 } | 103 } |
| 44 | 104 |
| 45 GtkWidget* PermissionSelector::CreateUI() { | |
| 46 // Create permission info box. | |
| 47 const int kChildSpacing = 4; | |
| 48 GtkWidget* hbox = gtk_hbox_new(FALSE, kChildSpacing); | |
| 49 | |
| 50 // Add permission type icon. | |
| 51 ContentSetting effective_setting = setting_; | |
| 52 if (effective_setting == CONTENT_SETTING_DEFAULT) | |
| 53 effective_setting = default_setting_; | |
| 54 GdkPixbuf* pixbuf = WebsiteSettingsUI::GetPermissionIcon( | |
| 55 type_, effective_setting).ToGdkPixbuf(); | |
| 56 icon_ = gtk_image_new_from_pixbuf(pixbuf); | |
| 57 gtk_box_pack_start(GTK_BOX(hbox), icon_, FALSE, FALSE, 0); | |
| 58 | |
| 59 // Add a label for the permission type. | |
| 60 GtkWidget* label = CreateTextLabel( | |
| 61 l10n_util::GetStringFUTF8( | |
| 62 IDS_WEBSITE_SETTINGS_PERMISSION_TYPE, | |
| 63 WebsiteSettingsUI::PermissionTypeToUIString(type_)), | |
| 64 theme_service_); | |
| 65 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
| 66 | |
| 67 GtkListStore* store = | |
| 68 gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); | |
| 69 GtkTreeIter iter; | |
| 70 // Add option for permission "Global Default" to the combobox model. | |
| 71 std::string setting_str = l10n_util::GetStringFUTF8( | |
| 72 IDS_WEBSITE_SETTINGS_DEFAULT_PERMISSION_LABEL, | |
| 73 WebsiteSettingsUI::PermissionValueToUIString(default_setting_)); | |
| 74 gtk_list_store_append(store, &iter); | |
| 75 gtk_list_store_set(store, &iter, 0, setting_str.c_str(), 1, | |
| 76 CONTENT_SETTING_DEFAULT, -1); | |
| 77 GtkWidget* combo_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); | |
| 78 // Add option for permission "Allow" to the combobox model. | |
| 79 setting_str = l10n_util::GetStringFUTF8( | |
| 80 IDS_WEBSITE_SETTINGS_PERMISSION_LABEL, | |
| 81 WebsiteSettingsUI::PermissionValueToUIString(CONTENT_SETTING_ALLOW)); | |
| 82 gtk_list_store_append(store, &iter); | |
| 83 gtk_list_store_set(store, &iter, 0, setting_str.c_str(), 1, | |
| 84 CONTENT_SETTING_ALLOW, -1); | |
| 85 // The content settings type fullscreen does not support the concept of | |
| 86 // blocking. | |
| 87 if (type_ != CONTENT_SETTINGS_TYPE_FULLSCREEN) { | |
| 88 // Add option for permission "BLOCK" to the combobox model. | |
| 89 setting_str = l10n_util::GetStringFUTF8( | |
| 90 IDS_WEBSITE_SETTINGS_PERMISSION_LABEL, | |
| 91 WebsiteSettingsUI::PermissionValueToUIString(CONTENT_SETTING_BLOCK)); | |
| 92 gtk_list_store_append(store, &iter); | |
| 93 gtk_list_store_set(store, &iter, 0, setting_str.c_str(), 1, | |
| 94 CONTENT_SETTING_BLOCK, -1); | |
| 95 } | |
| 96 // Remove reference to the store to prevent leaking. | |
| 97 g_object_unref(G_OBJECT(store)); | |
| 98 | |
| 99 GtkCellRenderer* cell = gtk_cell_renderer_text_new(); | |
| 100 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo_box), cell, TRUE ); | |
| 101 gtk_cell_layout_set_attributes( | |
| 102 GTK_CELL_LAYOUT(combo_box), cell, "text", 0, NULL); | |
| 103 | |
| 104 // Select the combobox entry for the currently configured permission value. | |
| 105 int active = -1; | |
| 106 switch (setting_) { | |
| 107 case CONTENT_SETTING_DEFAULT: active = 0; | |
| 108 break; | |
| 109 case CONTENT_SETTING_ALLOW: active = 1; | |
| 110 break; | |
| 111 case CONTENT_SETTING_BLOCK: active = 2; | |
| 112 break; | |
| 113 default: | |
| 114 NOTREACHED() << "Bad content setting:" << setting_; | |
| 115 break; | |
| 116 } | |
| 117 gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), active); | |
| 118 | |
| 119 // Add change listener to the combobox. | |
| 120 g_signal_connect(combo_box, "changed", | |
| 121 G_CALLBACK(OnPermissionChangedThunk), this); | |
| 122 // Once the popup (window) for a combobox is shown, the bubble container | |
| 123 // (window) loses it's focus. Therefore it necessary to reset the focus to | |
| 124 // the bubble container after the combobox popup is closed. | |
| 125 g_signal_connect(combo_box, "notify::popup-shown", | |
| 126 G_CALLBACK(OnComboBoxShownThunk), this); | |
| 127 gtk_box_pack_start(GTK_BOX(hbox), combo_box, FALSE, FALSE, 0); | |
| 128 | |
| 129 return hbox; | |
| 130 } | |
| 131 | |
| 132 void PermissionSelector::AddObserver(PermissionSelectorObserver* observer) { | 105 void PermissionSelector::AddObserver(PermissionSelectorObserver* observer) { |
| 133 observer_list_.AddObserver(observer); | 106 observer_list_.AddObserver(observer); |
| 134 } | 107 } |
| 135 | 108 |
| 136 void PermissionSelector::OnPermissionChanged(GtkWidget* widget) { | 109 ContentSetting PermissionSelector::GetSetting() const { |
| 137 // Get the selected setting. | 110 return setting_; |
| 138 GtkTreeIter it; | 111 } |
| 139 bool has_active = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &it); | |
| 140 DCHECK(has_active); | |
| 141 GtkTreeModel* store = | |
| 142 GTK_TREE_MODEL(gtk_combo_box_get_model(GTK_COMBO_BOX(widget))); | |
| 143 int value = -1; | |
| 144 gtk_tree_model_get(store, &it, 1, &value, -1); | |
| 145 setting_ = ContentSetting(value); | |
| 146 | 112 |
| 147 // Change the permission icon according the the selected setting. | 113 ContentSettingsType PermissionSelector::GetType() const { |
| 114 return type_; |
| 115 } |
| 116 |
| 117 gboolean PermissionSelector::OnMenuButtonPressEvent(GtkWidget* button, |
| 118 GdkEventButton* event) { |
| 119 if (event->button != 1) |
| 120 return FALSE; |
| 121 menu_->PopupForWidget(button, event->button, event->time); |
| 122 return TRUE; |
| 123 } |
| 124 |
| 125 void PermissionSelector::ExecuteCommand(int command_id) { |
| 126 setting_ = CommandIdToContentSetting(command_id); |
| 127 |
| 128 // Change the permission icon to reflect the selected setting. |
| 148 ContentSetting effective_setting = setting_; | 129 ContentSetting effective_setting = setting_; |
| 149 if (effective_setting == CONTENT_SETTING_DEFAULT) | 130 if (effective_setting == CONTENT_SETTING_DEFAULT) |
| 150 effective_setting = default_setting_; | 131 effective_setting = default_setting_; |
| 151 GdkPixbuf* pixbuf = WebsiteSettingsUI::GetPermissionIcon( | 132 GdkPixbuf* pixbuf = WebsiteSettingsUI::GetPermissionIcon( |
| 152 type_, effective_setting).ToGdkPixbuf(); | 133 type_, effective_setting).ToGdkPixbuf(); |
| 153 gtk_image_set_from_pixbuf(GTK_IMAGE(icon_), pixbuf); | 134 gtk_image_set_from_pixbuf(GTK_IMAGE(icon_), pixbuf); |
| 154 | 135 |
| 136 // Change the text of the menu button to reflect the selected setting. |
| 137 gtk_button_set_label(GTK_BUTTON(menu_button_), UTF16ToUTF8( |
| 138 WebsiteSettingsUI::PermissionActionToUIString( |
| 139 setting_, |
| 140 default_setting_, |
| 141 content_settings::SETTING_SOURCE_USER)).c_str()); |
| 142 |
| 155 FOR_EACH_OBSERVER(PermissionSelectorObserver, | 143 FOR_EACH_OBSERVER(PermissionSelectorObserver, |
| 156 observer_list_, | 144 observer_list_, |
| 157 OnPermissionChanged(this)); | 145 OnPermissionChanged(this)); |
| 158 } | 146 } |
| 159 | 147 |
| 160 void PermissionSelector::OnComboBoxShown(GtkWidget* widget, | 148 bool PermissionSelector::IsCommandIdChecked(int command_id) { |
| 161 GParamSpec* property) { | 149 return setting_ == CommandIdToContentSetting(command_id); |
| 162 // GtkComboBox grabs the keyboard and pointer when it displays its popup, | |
| 163 // which steals the grabs that BubbleGtk had installed. When the popup is | |
| 164 // hidden, we notify BubbleGtk so it can try to reacquire the grabs | |
| 165 // (otherwise, GTK won't activate our widgets when the user clicks in them). | |
| 166 // When then combobox popup is closed we notify the | |
| 167 // |PermissionSelectorObserver|s so that BubbleGtk can grab the keyboard and | |
| 168 // pointer. | |
| 169 gboolean popup_shown = FALSE; | |
| 170 g_object_get(G_OBJECT(GTK_COMBO_BOX(widget)), "popup-shown", &popup_shown, | |
| 171 NULL); | |
| 172 if (!popup_shown) { | |
| 173 FOR_EACH_OBSERVER(PermissionSelectorObserver, | |
| 174 observer_list_, | |
| 175 OnComboboxShown()); | |
| 176 } | |
| 177 } | 150 } |
| OLD | NEW |