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