permission_selector_view.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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 "chrome/browser/ui/views/website_settings/permission_selector_view.h" 6 7#include "base/strings/utf_string_conversions.h" 8#include "chrome/browser/ui/website_settings/website_settings_ui.h" 9#include "grit/generated_resources.h" 10#include "ui/base/accessibility/accessible_view_state.h" 11#include "ui/base/l10n/l10n_util.h" 12#include "ui/base/models/simple_menu_model.h" 13#include "ui/gfx/image/image.h" 14#include "ui/views/controls/button/menu_button.h" 15#include "ui/views/controls/image_view.h" 16#include "ui/views/controls/label.h" 17#include "ui/views/controls/menu/menu_runner.h" 18#include "ui/views/layout/grid_layout.h" 19#include "ui/views/view.h" 20#include "ui/views/widget/widget.h" 21 22namespace { 23 24// Left icon margin. 25const int kPermissionIconMarginLeft = 6; 26// The width of the column that contains the permissions icons. 27const int kPermissionIconColumnWidth = 20; 28 29ContentSetting CommandIdToContentSetting(int command_id) { 30 switch (command_id) { 31 case PermissionMenuModel::COMMAND_SET_TO_DEFAULT: 32 return CONTENT_SETTING_DEFAULT; 33 case PermissionMenuModel::COMMAND_SET_TO_ALLOW: 34 return CONTENT_SETTING_ALLOW; 35 case PermissionMenuModel::COMMAND_SET_TO_BLOCK: 36 return CONTENT_SETTING_BLOCK; 37 default: 38 NOTREACHED(); 39 return CONTENT_SETTING_DEFAULT; 40 } 41} 42 43} // namespace 44 45namespace internal { 46 47// The |PermissionMenuButton| provides a menu for selecting a setting a 48// permissions type. 49class PermissionMenuButton : public views::MenuButton, 50 public views::MenuButtonListener { 51 public: 52 // Creates a new |PermissionMenuButton| with the passed |text|. The ownership 53 // of the |model| remains with the caller and is not transfered to the 54 // |PermissionMenuButton|. If the |show_menu_marker| flag is true, then a 55 // small icon is be displayed next to the button |text|, indicating that the 56 // button opens a drop down menu. 57 PermissionMenuButton(const string16& text, 58 PermissionMenuModel* model, 59 bool show_menu_marker); 60 virtual ~PermissionMenuButton(); 61 62 // Overridden from views::MenuButton. 63 virtual gfx::Size GetPreferredSize() OVERRIDE; 64 65 // Overridden from views::TextButton. 66 virtual void SetText(const string16& text) OVERRIDE; 67 68 // Overridden from views::View. 69 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; 70 71 private: 72 // Overridden from views::MenuButtonListener. 73 virtual void OnMenuButtonClicked(View* source, 74 const gfx::Point& point) OVERRIDE; 75 76 PermissionMenuModel* menu_model_; // Owned by |PermissionSelectorView|. 77 scoped_ptr<views::MenuRunner> menu_runner_; 78 79 DISALLOW_COPY_AND_ASSIGN(PermissionMenuButton); 80}; 81 82/////////////////////////////////////////////////////////////////////////////// 83// PermissionMenuButton 84/////////////////////////////////////////////////////////////////////////////// 85 86PermissionMenuButton::PermissionMenuButton(const string16& text, 87 PermissionMenuModel* model, 88 bool show_menu_marker) 89 : MenuButton(NULL, text, this, show_menu_marker), 90 menu_model_(model) { 91 SetEnabledColor(GetNativeTheme()->GetSystemColor( 92 ui::NativeTheme::kColorId_LabelEnabledColor)); 93 SetHoverColor(GetNativeTheme()->GetSystemColor( 94 ui::NativeTheme::kColorId_LabelEnabledColor)); 95 SetDisabledColor(GetNativeTheme()->GetSystemColor( 96 ui::NativeTheme::kColorId_LabelDisabledColor)); 97} 98 99PermissionMenuButton::~PermissionMenuButton() { 100} 101 102gfx::Size PermissionMenuButton::GetPreferredSize() { 103 gfx::Insets insets = GetInsets(); 104 // Scale the button to the current text size. 105 gfx::Size prefsize(text_size_.width() + insets.width(), 106 text_size_.height() + insets.height()); 107 if (max_width_ > 0) 108 prefsize.set_width(std::min(max_width_, prefsize.width())); 109 if (show_menu_marker()) { 110 prefsize.Enlarge(menu_marker()->width() + 111 views::MenuButton::kMenuMarkerPaddingLeft + 112 views::MenuButton::kMenuMarkerPaddingRight, 113 0); 114 } 115 return prefsize; 116} 117 118void PermissionMenuButton::SetText(const string16& text) { 119 MenuButton::SetText(text); 120 SizeToPreferredSize(); 121} 122 123void PermissionMenuButton::GetAccessibleState(ui::AccessibleViewState* state) { 124 MenuButton::GetAccessibleState(state); 125 state->value = text(); 126} 127 128void PermissionMenuButton::OnMenuButtonClicked(View* source, 129 const gfx::Point& point) { 130 menu_runner_.reset(new views::MenuRunner(menu_model_)); 131 132 gfx::Point p(point); 133 p.Offset(-source->width(), 0); 134 if (menu_runner_->RunMenuAt( 135 source->GetWidget()->GetTopLevelWidget(), 136 this, 137 gfx::Rect(p, gfx::Size()), 138 views::MenuItemView::TOPLEFT, 139 views::MenuRunner::HAS_MNEMONICS) == views::MenuRunner::MENU_DELETED) 140 return; 141} 142 143} // namespace internal 144 145/////////////////////////////////////////////////////////////////////////////// 146// PermissionSelectorView 147/////////////////////////////////////////////////////////////////////////////// 148 149PermissionSelectorView::PermissionSelectorView( 150 const GURL& url, 151 ContentSettingsType type, 152 ContentSetting default_setting, 153 ContentSetting current_setting, 154 content_settings::SettingSource source) 155 : icon_(NULL), 156 menu_button_(NULL), 157 type_(type), 158 default_setting_(default_setting), 159 current_setting_(current_setting) { 160 views::GridLayout* layout = new views::GridLayout(this); 161 SetLayoutManager(layout); 162 const int column_set_id = 0; 163 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); 164 column_set->AddColumn(views::GridLayout::FILL, 165 views::GridLayout::FILL, 166 1, 167 views::GridLayout::FIXED, 168 kPermissionIconColumnWidth, 169 0); 170 column_set->AddPaddingColumn(0, kPermissionIconMarginLeft); 171 column_set->AddColumn(views::GridLayout::FILL, 172 views::GridLayout::FILL, 173 1, 174 views::GridLayout::USE_PREF, 175 0, 176 0); 177 column_set->AddColumn(views::GridLayout::FILL, 178 views::GridLayout::FILL, 179 1, 180 views::GridLayout::USE_PREF, 181 0, 182 0); 183 184 layout->StartRow(1, column_set_id); 185 // Create the permission icon. 186 icon_ = new views::ImageView(); 187 ContentSetting setting = current_setting; 188 if (setting == CONTENT_SETTING_DEFAULT) 189 setting = default_setting; 190 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(type, setting); 191 icon_->SetImage(image.ToImageSkia()); 192 layout->AddView(icon_, 193 1, 194 1, 195 views::GridLayout::CENTER, 196 views::GridLayout::CENTER); 197 // Create the label that displays the permission type. 198 views::Label* label = new views::Label( 199 l10n_util::GetStringFUTF16( 200 IDS_WEBSITE_SETTINGS_PERMISSION_TYPE, 201 WebsiteSettingsUI::PermissionTypeToUIString(type))); 202 layout->AddView(label, 203 1, 204 1, 205 views::GridLayout::LEADING, 206 views::GridLayout::CENTER); 207 // Create the permission menu button. 208 menu_button_model_.reset(new PermissionMenuModel( 209 this, url, type, default_setting, current_setting)); 210 bool button_enabled = source == content_settings::SETTING_SOURCE_USER; 211 menu_button_ = new internal::PermissionMenuButton( 212 WebsiteSettingsUI::PermissionActionToUIString(current_setting, 213 default_setting, 214 source), 215 menu_button_model_.get(), 216 button_enabled); 217 menu_button_->SetEnabled(button_enabled); 218 menu_button_->set_focusable(button_enabled); 219 menu_button_->SetAccessibleName( 220 WebsiteSettingsUI::PermissionTypeToUIString(type)); 221 layout->AddView(menu_button_); 222} 223 224void PermissionSelectorView::AddObserver( 225 PermissionSelectorViewObserver* observer) { 226 observer_list_.AddObserver(observer); 227} 228 229void PermissionSelectorView::ChildPreferredSizeChanged(View* child) { 230 SizeToPreferredSize(); 231 // FIXME: The parent is only a plain |View| that is used as a 232 // container/box/panel. The SizeToPreferredSize method of the parent is 233 // called here directly in order not to implement a custom |View| class with 234 // its own implementation of the ChildPreferredSizeChanged method. 235 parent()->SizeToPreferredSize(); 236} 237 238PermissionSelectorView::~PermissionSelectorView() { 239} 240 241void PermissionSelectorView::ExecuteCommand(int command_id) { 242 current_setting_ = CommandIdToContentSetting(command_id); 243 244 // Change the permission icon to reflect the selected setting. 245 ContentSetting effective_setting = current_setting_; 246 if (effective_setting == CONTENT_SETTING_DEFAULT) 247 effective_setting = default_setting_; 248 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon( 249 type_, effective_setting); 250 icon_->SetImage(image.ToImageSkia()); 251 252 // Update the menu button text to reflect the new setting. 253 menu_button_->SetText(WebsiteSettingsUI::PermissionActionToUIString( 254 current_setting_, 255 default_setting_, 256 content_settings::SETTING_SOURCE_USER)); 257 258 FOR_EACH_OBSERVER(PermissionSelectorViewObserver, 259 observer_list_, 260 OnPermissionChanged(this)); 261} 262 263bool PermissionSelectorView::IsCommandIdChecked(int command_id) { 264 return current_setting_ == CommandIdToContentSetting(command_id); 265} 266