permission_selector_view.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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 ui::MENU_SOURCE_NONE, 140 views::MenuRunner::HAS_MNEMONICS) == views::MenuRunner::MENU_DELETED) 141 return; 142} 143 144} // namespace internal 145 146/////////////////////////////////////////////////////////////////////////////// 147// PermissionSelectorView 148/////////////////////////////////////////////////////////////////////////////// 149 150PermissionSelectorView::PermissionSelectorView( 151 const GURL& url, 152 ContentSettingsType type, 153 ContentSetting default_setting, 154 ContentSetting current_setting, 155 content_settings::SettingSource source) 156 : icon_(NULL), 157 menu_button_(NULL), 158 type_(type), 159 default_setting_(default_setting), 160 current_setting_(current_setting) { 161 views::GridLayout* layout = new views::GridLayout(this); 162 SetLayoutManager(layout); 163 const int column_set_id = 0; 164 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); 165 column_set->AddColumn(views::GridLayout::FILL, 166 views::GridLayout::FILL, 167 1, 168 views::GridLayout::FIXED, 169 kPermissionIconColumnWidth, 170 0); 171 column_set->AddPaddingColumn(0, kPermissionIconMarginLeft); 172 column_set->AddColumn(views::GridLayout::FILL, 173 views::GridLayout::FILL, 174 1, 175 views::GridLayout::USE_PREF, 176 0, 177 0); 178 column_set->AddColumn(views::GridLayout::FILL, 179 views::GridLayout::FILL, 180 1, 181 views::GridLayout::USE_PREF, 182 0, 183 0); 184 185 layout->StartRow(1, column_set_id); 186 // Create the permission icon. 187 icon_ = new views::ImageView(); 188 ContentSetting setting = current_setting; 189 if (setting == CONTENT_SETTING_DEFAULT) 190 setting = default_setting; 191 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(type, setting); 192 icon_->SetImage(image.ToImageSkia()); 193 layout->AddView(icon_, 194 1, 195 1, 196 views::GridLayout::CENTER, 197 views::GridLayout::CENTER); 198 // Create the label that displays the permission type. 199 views::Label* label = new views::Label( 200 l10n_util::GetStringFUTF16( 201 IDS_WEBSITE_SETTINGS_PERMISSION_TYPE, 202 WebsiteSettingsUI::PermissionTypeToUIString(type))); 203 layout->AddView(label, 204 1, 205 1, 206 views::GridLayout::LEADING, 207 views::GridLayout::CENTER); 208 // Create the permission menu button. 209 menu_button_model_.reset(new PermissionMenuModel( 210 this, url, type, default_setting, current_setting)); 211 bool button_enabled = source == content_settings::SETTING_SOURCE_USER; 212 menu_button_ = new internal::PermissionMenuButton( 213 WebsiteSettingsUI::PermissionActionToUIString(current_setting, 214 default_setting, 215 source), 216 menu_button_model_.get(), 217 button_enabled); 218 menu_button_->SetEnabled(button_enabled); 219 menu_button_->set_focusable(button_enabled); 220 menu_button_->SetAccessibleName( 221 WebsiteSettingsUI::PermissionTypeToUIString(type)); 222 layout->AddView(menu_button_); 223} 224 225void PermissionSelectorView::AddObserver( 226 PermissionSelectorViewObserver* observer) { 227 observer_list_.AddObserver(observer); 228} 229 230void PermissionSelectorView::ChildPreferredSizeChanged(View* child) { 231 SizeToPreferredSize(); 232 // FIXME: The parent is only a plain |View| that is used as a 233 // container/box/panel. The SizeToPreferredSize method of the parent is 234 // called here directly in order not to implement a custom |View| class with 235 // its own implementation of the ChildPreferredSizeChanged method. 236 parent()->SizeToPreferredSize(); 237} 238 239PermissionSelectorView::~PermissionSelectorView() { 240} 241 242void PermissionSelectorView::ExecuteCommand(int command_id) { 243 current_setting_ = CommandIdToContentSetting(command_id); 244 245 // Change the permission icon to reflect the selected setting. 246 ContentSetting effective_setting = current_setting_; 247 if (effective_setting == CONTENT_SETTING_DEFAULT) 248 effective_setting = default_setting_; 249 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon( 250 type_, effective_setting); 251 icon_->SetImage(image.ToImageSkia()); 252 253 // Update the menu button text to reflect the new setting. 254 menu_button_->SetText(WebsiteSettingsUI::PermissionActionToUIString( 255 current_setting_, 256 default_setting_, 257 content_settings::SETTING_SOURCE_USER)); 258 259 FOR_EACH_OBSERVER(PermissionSelectorViewObserver, 260 observer_list_, 261 OnPermissionChanged(this)); 262} 263 264bool PermissionSelectorView::IsCommandIdChecked(int command_id) { 265 return current_setting_ == CommandIdToContentSetting(command_id); 266} 267