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/permission_menu_model.h" 9#include "chrome/browser/ui/website_settings/website_settings_ui.h" 10#include "grit/generated_resources.h" 11#include "ui/accessibility/ax_view_state.h" 12#include "ui/base/l10n/l10n_util.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 29} // namespace 30 31namespace internal { 32 33// The |PermissionMenuButton| provides a menu for selecting a setting a 34// permissions type. 35class PermissionMenuButton : public views::MenuButton, 36 public views::MenuButtonListener { 37 public: 38 // Creates a new |PermissionMenuButton| with the passed |text|. The ownership 39 // of the |model| remains with the caller and is not transfered to the 40 // |PermissionMenuButton|. If the |show_menu_marker| flag is true, then a 41 // small icon is be displayed next to the button |text|, indicating that the 42 // button opens a drop down menu. 43 PermissionMenuButton(const base::string16& text, 44 PermissionMenuModel* model, 45 bool show_menu_marker); 46 virtual ~PermissionMenuButton(); 47 48 // Overridden from views::TextButton. 49 virtual void SetText(const base::string16& text) OVERRIDE; 50 51 // Overridden from views::View. 52 virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE; 53 virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE; 54 55 private: 56 // Overridden from views::MenuButtonListener. 57 virtual void OnMenuButtonClicked(View* source, 58 const gfx::Point& point) OVERRIDE; 59 60 PermissionMenuModel* menu_model_; // Owned by |PermissionSelectorView|. 61 scoped_ptr<views::MenuRunner> menu_runner_; 62 63 DISALLOW_COPY_AND_ASSIGN(PermissionMenuButton); 64}; 65 66/////////////////////////////////////////////////////////////////////////////// 67// PermissionMenuButton 68/////////////////////////////////////////////////////////////////////////////// 69 70PermissionMenuButton::PermissionMenuButton(const base::string16& text, 71 PermissionMenuModel* model, 72 bool show_menu_marker) 73 : MenuButton(NULL, text, this, show_menu_marker), 74 menu_model_(model) { 75} 76 77PermissionMenuButton::~PermissionMenuButton() { 78} 79 80void PermissionMenuButton::SetText(const base::string16& text) { 81 MenuButton::SetText(text); 82 SizeToPreferredSize(); 83} 84 85void PermissionMenuButton::GetAccessibleState(ui::AXViewState* state) { 86 MenuButton::GetAccessibleState(state); 87 state->value = GetText(); 88} 89 90void PermissionMenuButton::OnNativeThemeChanged(const ui::NativeTheme* theme) { 91 SetTextColor(views::Button::STATE_NORMAL, GetNativeTheme()->GetSystemColor( 92 ui::NativeTheme::kColorId_LabelEnabledColor)); 93 SetTextColor(views::Button::STATE_HOVERED, GetNativeTheme()->GetSystemColor( 94 ui::NativeTheme::kColorId_LabelEnabledColor)); 95 SetTextColor(views::Button::STATE_DISABLED, GetNativeTheme()->GetSystemColor( 96 ui::NativeTheme::kColorId_LabelDisabledColor)); 97} 98 99void PermissionMenuButton::OnMenuButtonClicked(View* source, 100 const gfx::Point& point) { 101 menu_runner_.reset(new views::MenuRunner(menu_model_)); 102 103 gfx::Point p(point); 104 p.Offset(-source->width(), 0); 105 if (menu_runner_->RunMenuAt(source->GetWidget()->GetTopLevelWidget(), 106 this, 107 gfx::Rect(p, gfx::Size()), 108 views::MENU_ANCHOR_TOPLEFT, 109 ui::MENU_SOURCE_NONE, 110 views::MenuRunner::HAS_MNEMONICS) == 111 views::MenuRunner::MENU_DELETED) { 112 return; 113 } 114} 115 116} // namespace internal 117 118/////////////////////////////////////////////////////////////////////////////// 119// PermissionSelectorView 120/////////////////////////////////////////////////////////////////////////////// 121 122PermissionSelectorView::PermissionSelectorView( 123 const GURL& url, 124 const WebsiteSettingsUI::PermissionInfo& permission) 125 : icon_(NULL), menu_button_(NULL) { 126 views::GridLayout* layout = new views::GridLayout(this); 127 SetLayoutManager(layout); 128 const int column_set_id = 0; 129 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); 130 column_set->AddColumn(views::GridLayout::FILL, 131 views::GridLayout::FILL, 132 1, 133 views::GridLayout::FIXED, 134 kPermissionIconColumnWidth, 135 0); 136 column_set->AddPaddingColumn(0, kPermissionIconMarginLeft); 137 column_set->AddColumn(views::GridLayout::FILL, 138 views::GridLayout::FILL, 139 1, 140 views::GridLayout::USE_PREF, 141 0, 142 0); 143 column_set->AddColumn(views::GridLayout::FILL, 144 views::GridLayout::FILL, 145 1, 146 views::GridLayout::USE_PREF, 147 0, 148 0); 149 150 layout->StartRow(1, column_set_id); 151 // Create the permission icon. 152 icon_ = new views::ImageView(); 153 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(permission); 154 icon_->SetImage(image.ToImageSkia()); 155 layout->AddView(icon_, 156 1, 157 1, 158 views::GridLayout::CENTER, 159 views::GridLayout::CENTER); 160 // Create the label that displays the permission type. 161 views::Label* label = new views::Label(l10n_util::GetStringFUTF16( 162 IDS_WEBSITE_SETTINGS_PERMISSION_TYPE, 163 WebsiteSettingsUI::PermissionTypeToUIString(permission.type))); 164 layout->AddView(label, 165 1, 166 1, 167 views::GridLayout::LEADING, 168 views::GridLayout::CENTER); 169 // Create the menu model. 170 menu_model_.reset(new PermissionMenuModel( 171 url, 172 permission, 173 base::Bind(&PermissionSelectorView::PermissionChanged, 174 base::Unretained(this)))); 175 // Create the permission menu button. 176 bool button_enabled = 177 permission.source == content_settings::SETTING_SOURCE_USER; 178 menu_button_ = new internal::PermissionMenuButton( 179 WebsiteSettingsUI::PermissionActionToUIString( 180 permission.setting, permission.default_setting, permission.source), 181 menu_model_.get(), 182 button_enabled); 183 menu_button_->SetEnabled(button_enabled); 184 menu_button_->SetFocusable(button_enabled); 185 menu_button_->SetAccessibleName( 186 WebsiteSettingsUI::PermissionTypeToUIString(permission.type)); 187 layout->AddView(menu_button_); 188} 189 190void PermissionSelectorView::AddObserver( 191 PermissionSelectorViewObserver* observer) { 192 observer_list_.AddObserver(observer); 193} 194 195void PermissionSelectorView::ChildPreferredSizeChanged(View* child) { 196 SizeToPreferredSize(); 197 // FIXME: The parent is only a plain |View| that is used as a 198 // container/box/panel. The SizeToPreferredSize method of the parent is 199 // called here directly in order not to implement a custom |View| class with 200 // its own implementation of the ChildPreferredSizeChanged method. 201 parent()->SizeToPreferredSize(); 202} 203 204PermissionSelectorView::~PermissionSelectorView() { 205} 206 207void PermissionSelectorView::PermissionChanged( 208 const WebsiteSettingsUI::PermissionInfo& permission) { 209 // Change the permission icon to reflect the selected setting. 210 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(permission); 211 icon_->SetImage(image.ToImageSkia()); 212 213 // Update the menu button text to reflect the new setting. 214 menu_button_->SetText(WebsiteSettingsUI::PermissionActionToUIString( 215 permission.setting, 216 permission.default_setting, 217 content_settings::SETTING_SOURCE_USER)); 218 219 FOR_EACH_OBSERVER(PermissionSelectorViewObserver, 220 observer_list_, 221 OnPermissionChanged(permission)); 222} 223