permission_selector_view.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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::MenuButton.
49  virtual gfx::Size GetPreferredSize() const OVERRIDE;
50
51  // Overridden from views::TextButton.
52  virtual void SetText(const base::string16& text) OVERRIDE;
53
54  // Overridden from views::View.
55  virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
56
57 private:
58  // Overridden from views::MenuButtonListener.
59  virtual void OnMenuButtonClicked(View* source,
60                                   const gfx::Point& point) OVERRIDE;
61
62  PermissionMenuModel* menu_model_;  // Owned by |PermissionSelectorView|.
63  scoped_ptr<views::MenuRunner> menu_runner_;
64
65  DISALLOW_COPY_AND_ASSIGN(PermissionMenuButton);
66};
67
68///////////////////////////////////////////////////////////////////////////////
69// PermissionMenuButton
70///////////////////////////////////////////////////////////////////////////////
71
72PermissionMenuButton::PermissionMenuButton(const base::string16& text,
73                                           PermissionMenuModel* model,
74                                           bool show_menu_marker)
75    : MenuButton(NULL, text, this, show_menu_marker),
76      menu_model_(model) {
77  SetEnabledColor(GetNativeTheme()->GetSystemColor(
78      ui::NativeTheme::kColorId_LabelEnabledColor));
79  SetHoverColor(GetNativeTheme()->GetSystemColor(
80      ui::NativeTheme::kColorId_LabelEnabledColor));
81  SetDisabledColor(GetNativeTheme()->GetSystemColor(
82      ui::NativeTheme::kColorId_LabelDisabledColor));
83}
84
85PermissionMenuButton::~PermissionMenuButton() {
86}
87
88gfx::Size PermissionMenuButton::GetPreferredSize() const {
89  gfx::Insets insets = GetInsets();
90  // Scale the button to the current text size.
91  gfx::Size prefsize(text_size_.width() + insets.width(),
92                     text_size_.height() + insets.height());
93  if (max_width_ > 0)
94    prefsize.set_width(std::min(max_width_, prefsize.width()));
95  if (show_menu_marker()) {
96    prefsize.Enlarge(menu_marker()->width() +
97                         views::MenuButton::kMenuMarkerPaddingLeft +
98                         views::MenuButton::kMenuMarkerPaddingRight,
99                     0);
100  }
101  return prefsize;
102}
103
104void PermissionMenuButton::SetText(const base::string16& text) {
105  MenuButton::SetText(text);
106  SizeToPreferredSize();
107}
108
109void PermissionMenuButton::GetAccessibleState(ui::AXViewState* state) {
110  MenuButton::GetAccessibleState(state);
111  state->value = text();
112}
113
114void PermissionMenuButton::OnMenuButtonClicked(View* source,
115                                               const gfx::Point& point) {
116  menu_runner_.reset(new views::MenuRunner(menu_model_));
117
118  gfx::Point p(point);
119  p.Offset(-source->width(), 0);
120  if (menu_runner_->RunMenuAt(source->GetWidget()->GetTopLevelWidget(),
121                              this,
122                              gfx::Rect(p, gfx::Size()),
123                              views::MENU_ANCHOR_TOPLEFT,
124                              ui::MENU_SOURCE_NONE,
125                              views::MenuRunner::HAS_MNEMONICS) ==
126      views::MenuRunner::MENU_DELETED) {
127    return;
128  }
129}
130
131}  // namespace internal
132
133///////////////////////////////////////////////////////////////////////////////
134// PermissionSelectorView
135///////////////////////////////////////////////////////////////////////////////
136
137PermissionSelectorView::PermissionSelectorView(
138    const GURL& url,
139    const WebsiteSettingsUI::PermissionInfo& permission)
140    : icon_(NULL), menu_button_(NULL) {
141  views::GridLayout* layout = new views::GridLayout(this);
142  SetLayoutManager(layout);
143  const int column_set_id = 0;
144  views::ColumnSet* column_set = layout->AddColumnSet(column_set_id);
145  column_set->AddColumn(views::GridLayout::FILL,
146                        views::GridLayout::FILL,
147                        1,
148                        views::GridLayout::FIXED,
149                        kPermissionIconColumnWidth,
150                        0);
151  column_set->AddPaddingColumn(0, kPermissionIconMarginLeft);
152  column_set->AddColumn(views::GridLayout::FILL,
153                        views::GridLayout::FILL,
154                        1,
155                        views::GridLayout::USE_PREF,
156                        0,
157                        0);
158  column_set->AddColumn(views::GridLayout::FILL,
159                        views::GridLayout::FILL,
160                        1,
161                        views::GridLayout::USE_PREF,
162                        0,
163                        0);
164
165  layout->StartRow(1, column_set_id);
166  // Create the permission icon.
167  icon_ = new views::ImageView();
168  const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(permission);
169  icon_->SetImage(image.ToImageSkia());
170  layout->AddView(icon_,
171                  1,
172                  1,
173                  views::GridLayout::CENTER,
174                  views::GridLayout::CENTER);
175  // Create the label that displays the permission type.
176  views::Label* label = new views::Label(l10n_util::GetStringFUTF16(
177      IDS_WEBSITE_SETTINGS_PERMISSION_TYPE,
178      WebsiteSettingsUI::PermissionTypeToUIString(permission.type)));
179  layout->AddView(label,
180                  1,
181                  1,
182                  views::GridLayout::LEADING,
183                  views::GridLayout::CENTER);
184  // Create the menu model.
185  menu_model_.reset(new PermissionMenuModel(
186      url,
187      permission,
188      base::Bind(&PermissionSelectorView::PermissionChanged,
189                 base::Unretained(this))));
190  // Create the permission menu button.
191  bool button_enabled =
192      permission.source == content_settings::SETTING_SOURCE_USER;
193  menu_button_ = new internal::PermissionMenuButton(
194      WebsiteSettingsUI::PermissionActionToUIString(
195          permission.setting, permission.default_setting, permission.source),
196      menu_model_.get(),
197      button_enabled);
198  menu_button_->SetEnabled(button_enabled);
199  menu_button_->SetFocusable(button_enabled);
200  menu_button_->SetAccessibleName(
201      WebsiteSettingsUI::PermissionTypeToUIString(permission.type));
202  layout->AddView(menu_button_);
203}
204
205void PermissionSelectorView::AddObserver(
206    PermissionSelectorViewObserver* observer) {
207  observer_list_.AddObserver(observer);
208}
209
210void PermissionSelectorView::ChildPreferredSizeChanged(View* child) {
211  SizeToPreferredSize();
212  // FIXME: The parent is only a plain |View| that is used as a
213  // container/box/panel. The SizeToPreferredSize method of the parent is
214  // called here directly in order not to implement a custom |View| class with
215  // its own implementation of the ChildPreferredSizeChanged method.
216  parent()->SizeToPreferredSize();
217}
218
219PermissionSelectorView::~PermissionSelectorView() {
220}
221
222void PermissionSelectorView::PermissionChanged(
223    const WebsiteSettingsUI::PermissionInfo& permission) {
224  // Change the permission icon to reflect the selected setting.
225  const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(permission);
226  icon_->SetImage(image.ToImageSkia());
227
228  // Update the menu button text to reflect the new setting.
229  menu_button_->SetText(WebsiteSettingsUI::PermissionActionToUIString(
230      permission.setting,
231      permission.default_setting,
232      content_settings::SETTING_SOURCE_USER));
233
234  FOR_EACH_OBSERVER(PermissionSelectorViewObserver,
235                    observer_list_,
236                    OnPermissionChanged(permission));
237}
238