Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Side by Side Diff: chrome/browser/ui/views/website_settings/permission_selector_row.cc

Issue 2748443005: Rename website_settings UI folders to permission_bubble. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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_row.h"
6
7 #include "base/i18n/rtl.h"
8 #include "base/macros.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/ui/page_info/website_settings_ui.h"
11 #include "chrome/browser/ui/views/page_info/non_accessible_image_view.h"
12 #include "chrome/browser/ui/views/page_info/website_settings_popup_view.h"
13 #include "chrome/browser/ui/website_settings/permission_menu_model.h"
14 #include "chrome/grit/generated_resources.h"
15 #include "ui/accessibility/ax_node_data.h"
16 #include "ui/base/material_design/material_design_controller.h"
17 #include "ui/base/models/combobox_model.h"
18 #include "ui/gfx/image/image.h"
19 #include "ui/views/controls/button/menu_button.h"
20 #include "ui/views/controls/combobox/combobox.h"
21 #include "ui/views/controls/combobox/combobox_listener.h"
22 #include "ui/views/controls/image_view.h"
23 #include "ui/views/controls/label.h"
24 #include "ui/views/controls/menu/menu_runner.h"
25 #include "ui/views/layout/grid_layout.h"
26 #include "ui/views/view.h"
27 #include "ui/views/widget/widget.h"
28
29 namespace {
30 // Minimum distance between the label and its corresponding menu.
31 const int kMinSeparationBetweenLabelAndMenu = 16;
32 } // namespace
33
34 namespace internal {
35
36 // The |PermissionMenuButton| provides a menu for selecting a setting a
37 // permissions type.
38 class PermissionMenuButton : public views::MenuButton,
39 public views::MenuButtonListener {
40 public:
41 // Creates a new |PermissionMenuButton| with the passed |text|. The ownership
42 // of the |model| remains with the caller and is not transfered to the
43 // |PermissionMenuButton|. If the |show_menu_marker| flag is true, then a
44 // small icon is be displayed next to the button |text|, indicating that the
45 // button opens a drop down menu.
46 PermissionMenuButton(const base::string16& text,
47 PermissionMenuModel* model,
48 bool show_menu_marker);
49 ~PermissionMenuButton() override;
50
51 // Overridden from views::View.
52 void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
53 void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
54
55 private:
56 // Overridden from views::MenuButtonListener.
57 void OnMenuButtonClicked(views::MenuButton* source,
58 const gfx::Point& point,
59 const ui::Event* event) override;
60
61 PermissionMenuModel* menu_model_; // Owned by |PermissionSelectorRow|.
62 std::unique_ptr<views::MenuRunner> menu_runner_;
63
64 bool is_rtl_display_;
65
66 DISALLOW_COPY_AND_ASSIGN(PermissionMenuButton);
67 };
68
69 ///////////////////////////////////////////////////////////////////////////////
70 // PermissionMenuButton
71 ///////////////////////////////////////////////////////////////////////////////
72
73 PermissionMenuButton::PermissionMenuButton(const base::string16& text,
74 PermissionMenuModel* model,
75 bool show_menu_marker)
76 : MenuButton(text, this, show_menu_marker), menu_model_(model) {
77 // Update the themed border before the NativeTheme is applied. Usually this
78 // happens in a call to LabelButton::OnNativeThemeChanged(). However, if
79 // PermissionMenuButton called that from its override, the NativeTheme would
80 // be available, and the button would get native GTK styling on Linux.
81 UpdateThemedBorder();
82
83 SetFocusForPlatform();
84 set_request_focus_on_press(true);
85 is_rtl_display_ =
86 base::i18n::RIGHT_TO_LEFT == base::i18n::GetStringDirection(text);
87 }
88
89 PermissionMenuButton::~PermissionMenuButton() {
90 }
91
92 void PermissionMenuButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
93 MenuButton::GetAccessibleNodeData(node_data);
94 node_data->SetValue(GetText());
95 }
96
97 void PermissionMenuButton::OnNativeThemeChanged(const ui::NativeTheme* theme) {
98 SetTextColor(views::Button::STATE_NORMAL, theme->GetSystemColor(
99 ui::NativeTheme::kColorId_LabelEnabledColor));
100 SetTextColor(views::Button::STATE_HOVERED, theme->GetSystemColor(
101 ui::NativeTheme::kColorId_LabelEnabledColor));
102 SetTextColor(views::Button::STATE_DISABLED, theme->GetSystemColor(
103 ui::NativeTheme::kColorId_LabelDisabledColor));
104 }
105
106 void PermissionMenuButton::OnMenuButtonClicked(views::MenuButton* source,
107 const gfx::Point& point,
108 const ui::Event* event) {
109 menu_runner_.reset(new views::MenuRunner(
110 menu_model_,
111 views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::ASYNC));
112
113 gfx::Point p(point);
114 p.Offset(is_rtl_display_ ? source->width() : -source->width(), 0);
115 menu_runner_->RunMenuAt(source->GetWidget()->GetTopLevelWidget(), this,
116 gfx::Rect(p, gfx::Size()), views::MENU_ANCHOR_TOPLEFT,
117 ui::MENU_SOURCE_NONE);
118 }
119
120 // This class adapts a |PermissionMenuModel| into a |ui::ComboboxModel| so that
121 // |PermissionCombobox| can use it.
122 class ComboboxModelAdapter : public ui::ComboboxModel {
123 public:
124 explicit ComboboxModelAdapter(PermissionMenuModel* model) : model_(model) {}
125 ~ComboboxModelAdapter() override {}
126
127 void OnPerformAction(int index);
128
129 // Returns the checked index of the underlying PermissionMenuModel, of which
130 // there must be exactly one. This is used to choose which index is selected
131 // in the PermissionCombobox.
132 int GetCheckedIndex();
133
134 // ui::ComboboxModel:
135 int GetItemCount() const override;
136 base::string16 GetItemAt(int index) override;
137
138 private:
139 PermissionMenuModel* model_;
140 };
141
142 void ComboboxModelAdapter::OnPerformAction(int index) {
143 model_->ExecuteCommand(index, 0);
144 }
145
146 int ComboboxModelAdapter::GetCheckedIndex() {
147 int checked_index = -1;
148 for (int i = 0; i < model_->GetItemCount(); ++i) {
149 if (model_->IsCommandIdChecked(i)) {
150 // This function keeps track of |checked_index| instead of returning early
151 // here so that it can DCHECK that there's exactly one selected item,
152 // which is not normally guaranteed by MenuModel, but *is* true of
153 // PermissionMenuModel.
154 DCHECK_EQ(checked_index, -1);
155 checked_index = i;
156 }
157 }
158 return checked_index;
159 }
160
161 int ComboboxModelAdapter::GetItemCount() const {
162 DCHECK(model_);
163 return model_->GetItemCount();
164 }
165
166 base::string16 ComboboxModelAdapter::GetItemAt(int index) {
167 return model_->GetLabelAt(index);
168 }
169
170 // The |PermissionCombobox| provides a combobox for selecting a permission type.
171 // This is only used on platforms where the permission dialog uses a combobox
172 // instead of a MenuButton (currently, Mac).
173 class PermissionCombobox : public views::Combobox,
174 public views::ComboboxListener {
175 public:
176 PermissionCombobox(ComboboxModelAdapter* model,
177 bool enabled,
178 bool use_default);
179 ~PermissionCombobox() override;
180
181 void UpdateSelectedIndex(bool use_default);
182
183 private:
184 // views::Combobox:
185 void OnPaintBorder(gfx::Canvas* canvas) override;
186
187 // views::ComboboxListener:
188 void OnPerformAction(Combobox* combobox) override;
189
190 ComboboxModelAdapter* model_;
191 };
192
193 PermissionCombobox::PermissionCombobox(ComboboxModelAdapter* model,
194 bool enabled,
195 bool use_default)
196 : views::Combobox(model), model_(model) {
197 set_listener(this);
198 SetEnabled(enabled);
199 UpdateSelectedIndex(use_default);
200 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) {
201 set_size_to_largest_label(false);
202 ModelChanged();
203 }
204 }
205
206 PermissionCombobox::~PermissionCombobox() {}
207
208 void PermissionCombobox::UpdateSelectedIndex(bool use_default) {
209 int index = model_->GetCheckedIndex();
210 if (use_default && index == -1)
211 index = 0;
212 SetSelectedIndex(index);
213 }
214
215 void PermissionCombobox::OnPaintBorder(gfx::Canvas* canvas) {
216 // No border except a focus indicator for MD mode.
217 if (ui::MaterialDesignController::IsSecondaryUiMaterial() && !HasFocus())
218 return;
219 Combobox::OnPaintBorder(canvas);
220 }
221
222 void PermissionCombobox::OnPerformAction(Combobox* combobox) {
223 model_->OnPerformAction(combobox->selected_index());
224 }
225
226 } // namespace internal
227
228 ///////////////////////////////////////////////////////////////////////////////
229 // PermissionSelectorRow
230 ///////////////////////////////////////////////////////////////////////////////
231
232 PermissionSelectorRow::PermissionSelectorRow(
233 Profile* profile,
234 const GURL& url,
235 const WebsiteSettingsUI::PermissionInfo& permission)
236 : profile_(profile), icon_(NULL), menu_button_(NULL), combobox_(NULL) {
237 views::GridLayout* layout = new views::GridLayout(this);
238 SetLayoutManager(layout);
239 const int column_set_id = 0;
240 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id);
241 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
242 views::GridLayout::FIXED, kPermissionIconColumnWidth,
243 0);
244 column_set->AddPaddingColumn(0, kPermissionIconMarginLeft);
245 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
246 views::GridLayout::USE_PREF, 0, 0);
247 column_set->AddPaddingColumn(1, kMinSeparationBetweenLabelAndMenu);
248 column_set->AddColumn(views::GridLayout::TRAILING, views::GridLayout::FILL, 0,
249 views::GridLayout::USE_PREF, 0, 0);
250
251 layout->StartRow(1, column_set_id);
252 // Create the permission icon.
253 icon_ = new NonAccessibleImageView();
254 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(permission);
255 icon_->SetImage(image.ToImageSkia());
256 layout->AddView(icon_,
257 1,
258 1,
259 views::GridLayout::CENTER,
260 views::GridLayout::CENTER);
261 // Create the label that displays the permission type.
262 views::Label* label = new views::Label(
263 WebsiteSettingsUI::PermissionTypeToUIString(permission.type));
264 layout->AddView(label,
265 1,
266 1,
267 views::GridLayout::LEADING,
268 views::GridLayout::CENTER);
269 // Create the menu model.
270 menu_model_.reset(new PermissionMenuModel(
271 profile, url, permission,
272 base::Bind(&PermissionSelectorRow::PermissionChanged,
273 base::Unretained(this))));
274
275 // Create the permission menu button.
276 #if defined(OS_MACOSX)
277 bool use_real_combobox = true;
278 #else
279 bool use_real_combobox =
280 ui::MaterialDesignController::IsSecondaryUiMaterial();
281 #endif
282 if (use_real_combobox)
283 InitializeComboboxView(layout, permission);
284 else
285 InitializeMenuButtonView(layout, permission);
286 }
287
288 void PermissionSelectorRow::AddObserver(
289 PermissionSelectorRowObserver* observer) {
290 observer_list_.AddObserver(observer);
291 }
292
293 void PermissionSelectorRow::ChildPreferredSizeChanged(View* child) {
294 Layout();
295 }
296
297 PermissionSelectorRow::~PermissionSelectorRow() {
298 // Gross. On paper the Combobox and the ComboboxModelAdapter are both owned by
299 // this class, but actually, the Combobox is owned by View and will be
300 // destroyed in ~View(), which runs *after* ~PermissionSelectorRow() is done,
301 // which means the Combobox gets destroyed after its ComboboxModel, which
302 // causes an explosion when the Combobox attempts to stop observing the
303 // ComboboxModel. This hack ensures the Combobox is deleted before its
304 // ComboboxModel.
305 //
306 // Technically, the MenuButton has the same problem, but MenuButton doesn't
307 // use its model in its destructor.
308 if (combobox_)
309 RemoveChildView(combobox_);
310 }
311
312 void PermissionSelectorRow::InitializeMenuButtonView(
313 views::GridLayout* layout,
314 const WebsiteSettingsUI::PermissionInfo& permission) {
315 bool button_enabled =
316 permission.source == content_settings::SETTING_SOURCE_USER;
317 menu_button_ = new internal::PermissionMenuButton(
318 WebsiteSettingsUI::PermissionActionToUIString(
319 profile_, permission.type, permission.setting,
320 permission.default_setting, permission.source),
321 menu_model_.get(), button_enabled);
322 menu_button_->SetEnabled(button_enabled);
323 menu_button_->SetAccessibleName(
324 WebsiteSettingsUI::PermissionTypeToUIString(permission.type));
325 layout->AddView(menu_button_);
326 }
327
328 void PermissionSelectorRow::InitializeComboboxView(
329 views::GridLayout* layout,
330 const WebsiteSettingsUI::PermissionInfo& permission) {
331 bool button_enabled =
332 permission.source == content_settings::SETTING_SOURCE_USER;
333 combobox_model_adapter_.reset(
334 new internal::ComboboxModelAdapter(menu_model_.get()));
335 combobox_ = new internal::PermissionCombobox(
336 combobox_model_adapter_.get(), button_enabled, true);
337 combobox_->SetEnabled(button_enabled);
338 combobox_->SetAccessibleName(
339 WebsiteSettingsUI::PermissionTypeToUIString(permission.type));
340 layout->AddView(combobox_);
341 }
342
343 void PermissionSelectorRow::PermissionChanged(
344 const WebsiteSettingsUI::PermissionInfo& permission) {
345 // Change the permission icon to reflect the selected setting.
346 const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(permission);
347 icon_->SetImage(image.ToImageSkia());
348
349 // Update the menu button text to reflect the new setting.
350 if (menu_button_) {
351 menu_button_->SetText(WebsiteSettingsUI::PermissionActionToUIString(
352 profile_, permission.type, permission.setting,
353 permission.default_setting, content_settings::SETTING_SOURCE_USER));
354 menu_button_->SizeToPreferredSize();
355 } else if (combobox_) {
356 bool use_default = permission.setting == CONTENT_SETTING_DEFAULT;
357 combobox_->UpdateSelectedIndex(use_default);
358 }
359
360 for (PermissionSelectorRowObserver& observer : observer_list_)
361 observer.OnPermissionChanged(permission);
362 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698