1 // Copyright (c) 2013 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.
5 #include "ui/message_center/views/notifier_settings_view.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "skia/ext/image_operations.h"
13 #include "third_party/skia/include/core/SkColor.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/base/models/simple_menu_model.h"
16 #include "ui/base/resource/resource_bundle.h"
17 #include "ui/events/event_utils.h"
18 #include "ui/events/keycodes/keyboard_codes.h"
19 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/geometry/size.h"
21 #include "ui/gfx/image/image.h"
22 #include "ui/message_center/message_center_style.h"
23 #include "ui/message_center/views/message_center_view.h"
24 #include "ui/resources/grit/ui_resources.h"
25 #include "ui/strings/grit/ui_strings.h"
26 #include "ui/views/background.h"
27 #include "ui/views/border.h"
28 #include "ui/views/controls/button/checkbox.h"
29 #include "ui/views/controls/button/label_button_border.h"
30 #include "ui/views/controls/button/menu_button.h"
31 #include "ui/views/controls/image_view.h"
32 #include "ui/views/controls/label.h"
33 #include "ui/views/controls/link.h"
34 #include "ui/views/controls/link_listener.h"
35 #include "ui/views/controls/menu/menu_runner.h"
36 #include "ui/views/controls/scroll_view.h"
37 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
38 #include "ui/views/layout/box_layout.h"
39 #include "ui/views/layout/fill_layout.h"
40 #include "ui/views/layout/grid_layout.h"
41 #include "ui/views/painter.h"
42 #include "ui/views/widget/widget.h"
44 namespace message_center
{
47 // Additional views-specific parameters.
49 // The width of the settings pane in pixels.
50 const int kWidth
= 360;
52 // The width of the learn more icon in pixels.
53 const int kLearnMoreSize
= 12;
55 // The width of the click target that contains the learn more button in pixels.
56 const int kLearnMoreTargetWidth
= 28;
58 // The height of the click target that contains the learn more button in pixels.
59 const int kLearnMoreTargetHeight
= 40;
61 // The minimum height of the settings pane in pixels.
62 const int kMinimumHeight
= 480;
64 // The horizontal margin of the title area of the settings pane in addition to
65 // the standard margin from settings::kHorizontalMargin.
66 const int kTitleMargin
= 10;
68 } // namespace settings
72 // Menu button metrics to make the text line up.
73 const int kMenuButtonInnateMargin
= 2;
75 // Used to place the context menu correctly.
76 const int kMenuWhitespaceOffset
= 2;
78 // The innate vertical blank space in the label for the title of the settings
80 const int kInnateTitleBottomMargin
= 1;
81 const int kInnateTitleTopMargin
= 7;
83 // The innate top blank space in the label for the description of the settings
85 const int kInnateDescriptionTopMargin
= 2;
87 // Checkboxes have some built-in right padding blank space.
88 const int kInnateCheckboxRightPadding
= 2;
90 // Spec defines the checkbox size; the innate padding throws this measurement
91 // off so we need to compute a slightly different area for the checkbox to
93 const int kComputedCheckboxSize
=
94 settings::kCheckboxSizeWithPadding
- kInnateCheckboxRightPadding
;
96 // The menubutton has innate margin, so we need to compensate for that when
97 // figuring the margin of the title area.
98 const int kComputedContentsTitleMargin
= 0 - kMenuButtonInnateMargin
;
100 // The spec doesn't include the bottom blank area of the title bar or the innate
101 // blank area in the description label, so we'll use this as the space between
102 // the title and description.
103 const int kComputedTitleBottomMargin
= settings::kDescriptionToSwitcherSpace
-
104 kInnateTitleBottomMargin
-
105 kInnateDescriptionTopMargin
;
107 // The blank space above the title needs to be adjusted by the amount of blank
108 // space included in the title label.
109 const int kComputedTitleTopMargin
=
110 settings::kTopMargin
- kInnateTitleTopMargin
;
112 // The switcher has a lot of blank space built in so we should include that when
113 // spacing the title area vertically.
114 const int kComputedTitleElementSpacing
=
115 settings::kDescriptionToSwitcherSpace
- 6;
117 // A function to create a focus border.
118 scoped_ptr
<views::Painter
> CreateFocusPainter() {
119 return views::Painter::CreateSolidFocusPainter(kFocusBorderColor
,
120 gfx::Insets(1, 2, 3, 2));
123 // EntryView ------------------------------------------------------------------
125 // The view to guarantee the 48px height and place the contents at the
126 // middle. It also guarantee the left margin.
127 class EntryView
: public views::View
{
129 explicit EntryView(views::View
* contents
);
130 ~EntryView() override
;
133 void Layout() override
;
134 gfx::Size
GetPreferredSize() const override
;
135 void GetAccessibleState(ui::AXViewState
* state
) override
;
136 void OnFocus() override
;
137 bool OnKeyPressed(const ui::KeyEvent
& event
) override
;
138 bool OnKeyReleased(const ui::KeyEvent
& event
) override
;
139 void OnPaint(gfx::Canvas
* canvas
) override
;
140 void OnBlur() override
;
143 scoped_ptr
<views::Painter
> focus_painter_
;
145 DISALLOW_COPY_AND_ASSIGN(EntryView
);
148 EntryView::EntryView(views::View
* contents
)
149 : focus_painter_(CreateFocusPainter()) {
150 AddChildView(contents
);
153 EntryView::~EntryView() {}
155 void EntryView::Layout() {
156 DCHECK_EQ(1, child_count());
157 views::View
* content
= child_at(0);
158 int content_width
= width();
159 int content_height
= content
->GetHeightForWidth(content_width
);
160 int y
= std::max((height() - content_height
) / 2, 0);
161 content
->SetBounds(0, y
, content_width
, content_height
);
164 gfx::Size
EntryView::GetPreferredSize() const {
165 DCHECK_EQ(1, child_count());
166 gfx::Size size
= child_at(0)->GetPreferredSize();
167 size
.SetToMax(gfx::Size(settings::kWidth
, settings::kEntryHeight
));
171 void EntryView::GetAccessibleState(ui::AXViewState
* state
) {
172 DCHECK_EQ(1, child_count());
173 child_at(0)->GetAccessibleState(state
);
176 void EntryView::OnFocus() {
177 views::View::OnFocus();
178 ScrollRectToVisible(GetLocalBounds());
179 // We render differently when focused.
183 bool EntryView::OnKeyPressed(const ui::KeyEvent
& event
) {
184 return child_at(0)->OnKeyPressed(event
);
187 bool EntryView::OnKeyReleased(const ui::KeyEvent
& event
) {
188 return child_at(0)->OnKeyReleased(event
);
191 void EntryView::OnPaint(gfx::Canvas
* canvas
) {
192 View::OnPaint(canvas
);
193 views::Painter::PaintFocusPainter(this, canvas
, focus_painter_
.get());
196 void EntryView::OnBlur() {
198 // We render differently when focused.
205 // NotifierGroupMenuModel -----------------------------------------------------
207 class NotifierGroupMenuModel
: public ui::SimpleMenuModel
,
208 public ui::SimpleMenuModel::Delegate
{
210 NotifierGroupMenuModel(NotifierSettingsProvider
* notifier_settings_provider
);
211 ~NotifierGroupMenuModel() override
;
213 // ui::SimpleMenuModel::Delegate:
214 bool IsCommandIdChecked(int command_id
) const override
;
215 bool IsCommandIdEnabled(int command_id
) const override
;
216 bool GetAcceleratorForCommandId(int command_id
,
217 ui::Accelerator
* accelerator
) override
;
218 void ExecuteCommand(int command_id
, int event_flags
) override
;
221 NotifierSettingsProvider
* notifier_settings_provider_
;
223 DISALLOW_COPY_AND_ASSIGN(NotifierGroupMenuModel
);
226 NotifierGroupMenuModel::NotifierGroupMenuModel(
227 NotifierSettingsProvider
* notifier_settings_provider
)
228 : ui::SimpleMenuModel(this),
229 notifier_settings_provider_(notifier_settings_provider
) {
230 if (!notifier_settings_provider_
)
233 size_t num_menu_items
= notifier_settings_provider_
->GetNotifierGroupCount();
234 for (size_t i
= 0; i
< num_menu_items
; ++i
) {
235 const NotifierGroup
& group
=
236 notifier_settings_provider_
->GetNotifierGroupAt(i
);
238 AddCheckItem(i
, group
.login_info
.empty() ? group
.name
: group
.login_info
);
242 NotifierGroupMenuModel::~NotifierGroupMenuModel() {}
244 bool NotifierGroupMenuModel::IsCommandIdChecked(int command_id
) const {
245 // If there's no provider, assume only one notifier group - the active one.
246 return !notifier_settings_provider_
||
247 notifier_settings_provider_
->IsNotifierGroupActiveAt(command_id
);
250 bool NotifierGroupMenuModel::IsCommandIdEnabled(int command_id
) const {
254 bool NotifierGroupMenuModel::GetAcceleratorForCommandId(
256 ui::Accelerator
* accelerator
) {
260 void NotifierGroupMenuModel::ExecuteCommand(int command_id
, int event_flags
) {
261 if (!notifier_settings_provider_
)
264 size_t notifier_group_index
= static_cast<size_t>(command_id
);
265 size_t num_notifier_groups
=
266 notifier_settings_provider_
->GetNotifierGroupCount();
267 if (notifier_group_index
>= num_notifier_groups
)
270 notifier_settings_provider_
->SwitchToNotifierGroup(notifier_group_index
);
274 // NotifierSettingsView::NotifierButton ---------------------------------------
276 // We do not use views::Checkbox class directly because it doesn't support
278 NotifierSettingsView::NotifierButton::NotifierButton(
279 NotifierSettingsProvider
* provider
,
281 views::ButtonListener
* listener
)
282 : views::CustomButton(listener
),
285 icon_view_(new views::ImageView()),
286 name_view_(new views::Label(notifier_
->name
)),
287 checkbox_(new views::Checkbox(base::string16())),
292 // Since there may never be an icon (but that could change at a later time),
293 // we own the icon view here.
294 icon_view_
->set_owned_by_client();
296 checkbox_
->SetChecked(notifier_
->enabled
);
297 checkbox_
->set_listener(this);
298 checkbox_
->SetFocusable(false);
299 checkbox_
->SetAccessibleName(notifier_
->name
);
301 if (ShouldHaveLearnMoreButton()) {
302 // Create a more-info button that will be right-aligned.
303 learn_more_
= new views::ImageButton(this);
304 learn_more_
->SetFocusPainter(CreateFocusPainter());
305 learn_more_
->set_request_focus_on_press(false);
306 learn_more_
->SetFocusable(true);
308 ui::ResourceBundle
& rb
= ResourceBundle::GetSharedInstance();
309 learn_more_
->SetImage(
310 views::Button::STATE_NORMAL
,
311 rb
.GetImageSkiaNamed(IDR_NOTIFICATION_ADVANCED_SETTINGS
));
312 learn_more_
->SetImage(
313 views::Button::STATE_HOVERED
,
314 rb
.GetImageSkiaNamed(IDR_NOTIFICATION_ADVANCED_SETTINGS_HOVER
));
315 learn_more_
->SetImage(
316 views::Button::STATE_PRESSED
,
317 rb
.GetImageSkiaNamed(IDR_NOTIFICATION_ADVANCED_SETTINGS_PRESSED
));
318 learn_more_
->SetState(views::Button::STATE_NORMAL
);
319 int learn_more_border_width
=
320 (settings::kLearnMoreTargetWidth
- settings::kLearnMoreSize
) / 2;
321 int learn_more_border_height
=
322 (settings::kLearnMoreTargetHeight
- settings::kLearnMoreSize
) / 2;
323 // The image itself is quite small, this large invisible border creates a
324 // much bigger click target.
325 learn_more_
->SetBorder(
326 views::Border::CreateEmptyBorder(learn_more_border_height
,
327 learn_more_border_width
,
328 learn_more_border_height
,
329 learn_more_border_width
));
330 learn_more_
->SetImageAlignment(views::ImageButton::ALIGN_CENTER
,
331 views::ImageButton::ALIGN_MIDDLE
);
334 UpdateIconImage(notifier_
->icon
);
337 NotifierSettingsView::NotifierButton::~NotifierButton() {
340 void NotifierSettingsView::NotifierButton::UpdateIconImage(
341 const gfx::Image
& icon
) {
342 bool has_icon_view
= false;
344 notifier_
->icon
= icon
;
345 if (!icon
.IsEmpty()) {
346 icon_view_
->SetImage(icon
.ToImageSkia());
347 icon_view_
->SetImageSize(
348 gfx::Size(settings::kEntryIconSize
, settings::kEntryIconSize
));
349 has_icon_view
= true;
351 GridChanged(ShouldHaveLearnMoreButton(), has_icon_view
);
354 void NotifierSettingsView::NotifierButton::SetChecked(bool checked
) {
355 checkbox_
->SetChecked(checked
);
356 notifier_
->enabled
= checked
;
359 bool NotifierSettingsView::NotifierButton::checked() const {
360 return checkbox_
->checked();
363 bool NotifierSettingsView::NotifierButton::has_learn_more() const {
364 return learn_more_
!= NULL
;
367 const Notifier
& NotifierSettingsView::NotifierButton::notifier() const {
368 return *notifier_
.get();
371 void NotifierSettingsView::NotifierButton::SendLearnMorePressedForTest() {
372 if (learn_more_
== NULL
)
374 gfx::Point
point(110, 120);
375 ui::MouseEvent
pressed(ui::ET_MOUSE_PRESSED
, point
, point
,
376 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
377 ui::EF_LEFT_MOUSE_BUTTON
);
378 ButtonPressed(learn_more_
, pressed
);
381 void NotifierSettingsView::NotifierButton::ButtonPressed(
382 views::Button
* button
,
383 const ui::Event
& event
) {
384 if (button
== checkbox_
) {
385 // The checkbox state has already changed at this point, but we'll update
386 // the state on NotifierSettingsView::ButtonPressed() too, so here change
387 // back to the previous state.
388 checkbox_
->SetChecked(!checkbox_
->checked());
389 CustomButton::NotifyClick(event
);
390 } else if (button
== learn_more_
) {
392 provider_
->OnNotifierAdvancedSettingsRequested(notifier_
->notifier_id
,
397 void NotifierSettingsView::NotifierButton::GetAccessibleState(
398 ui::AXViewState
* state
) {
399 static_cast<views::View
*>(checkbox_
)->GetAccessibleState(state
);
402 bool NotifierSettingsView::NotifierButton::ShouldHaveLearnMoreButton() const {
406 return provider_
->NotifierHasAdvancedSettings(notifier_
->notifier_id
);
409 void NotifierSettingsView::NotifierButton::GridChanged(bool has_learn_more
,
410 bool has_icon_view
) {
411 using views::ColumnSet
;
412 using views::GridLayout
;
414 GridLayout
* layout
= new GridLayout(this);
415 SetLayoutManager(layout
);
416 ColumnSet
* cs
= layout
->AddColumnSet(0);
417 // Add a column for the checkbox.
418 cs
->AddPaddingColumn(0, kInnateCheckboxRightPadding
);
419 cs
->AddColumn(GridLayout::CENTER
,
423 kComputedCheckboxSize
,
425 cs
->AddPaddingColumn(0, settings::kInternalHorizontalSpacing
);
428 // Add a column for the icon.
429 cs
->AddColumn(GridLayout::CENTER
,
433 settings::kEntryIconSize
,
435 cs
->AddPaddingColumn(0, settings::kInternalHorizontalSpacing
);
438 // Add a column for the name.
440 GridLayout::LEADING
, GridLayout::CENTER
, 0, GridLayout::USE_PREF
, 0, 0);
442 // Add a padding column which contains expandable blank space.
443 cs
->AddPaddingColumn(1, 0);
445 // Add a column for the learn more button if necessary.
446 if (has_learn_more
) {
447 cs
->AddPaddingColumn(0, settings::kInternalHorizontalSpacing
);
449 GridLayout::CENTER
, GridLayout::CENTER
, 0, GridLayout::USE_PREF
, 0, 0);
452 layout
->StartRow(0, 0);
453 layout
->AddView(checkbox_
);
455 layout
->AddView(icon_view_
.get());
456 layout
->AddView(name_view_
);
458 layout
->AddView(learn_more_
);
464 // NotifierSettingsView -------------------------------------------------------
466 NotifierSettingsView::NotifierSettingsView(NotifierSettingsProvider
* provider
)
467 : title_arrow_(NULL
),
469 notifier_group_selector_(NULL
),
471 provider_(provider
) {
472 // |provider_| may be NULL in tests.
474 provider_
->AddObserver(this);
478 views::Background::CreateSolidBackground(kMessageCenterBackgroundColor
));
479 SetPaintToLayer(true);
481 title_label_
= new views::Label(
482 l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_SETTINGS_BUTTON_LABEL
),
483 ui::ResourceBundle::GetSharedInstance().GetFontList(
484 ui::ResourceBundle::MediumFont
));
485 title_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
486 title_label_
->SetMultiLine(true);
487 title_label_
->SetBorder(
488 views::Border::CreateEmptyBorder(kComputedTitleTopMargin
,
489 settings::kTitleMargin
,
490 kComputedTitleBottomMargin
,
491 settings::kTitleMargin
));
493 AddChildView(title_label_
);
495 scroller_
= new views::ScrollView();
496 scroller_
->SetVerticalScrollBar(new views::OverlayScrollBar(false));
497 AddChildView(scroller_
);
499 std::vector
<Notifier
*> notifiers
;
501 provider_
->GetNotifierList(¬ifiers
);
503 UpdateContentsView(notifiers
);
506 NotifierSettingsView::~NotifierSettingsView() {
507 // |provider_| may be NULL in tests.
509 provider_
->RemoveObserver(this);
512 bool NotifierSettingsView::IsScrollable() {
513 return scroller_
->height() < scroller_
->contents()->height();
516 void NotifierSettingsView::UpdateIconImage(const NotifierId
& notifier_id
,
517 const gfx::Image
& icon
) {
518 for (std::set
<NotifierButton
*>::iterator iter
= buttons_
.begin();
519 iter
!= buttons_
.end();
521 if ((*iter
)->notifier().notifier_id
== notifier_id
) {
522 (*iter
)->UpdateIconImage(icon
);
528 void NotifierSettingsView::NotifierGroupChanged() {
529 std::vector
<Notifier
*> notifiers
;
531 provider_
->GetNotifierList(¬ifiers
);
533 UpdateContentsView(notifiers
);
536 void NotifierSettingsView::NotifierEnabledChanged(const NotifierId
& notifier_id
,
539 void NotifierSettingsView::UpdateContentsView(
540 const std::vector
<Notifier
*>& notifiers
) {
543 views::View
* contents_view
= new views::View();
544 contents_view
->SetLayoutManager(new views::BoxLayout(
545 views::BoxLayout::kVertical
, settings::kHorizontalMargin
, 0, 0));
547 views::View
* contents_title_view
= new views::View();
548 contents_title_view
->SetLayoutManager(
549 new views::BoxLayout(views::BoxLayout::kVertical
,
550 kComputedContentsTitleMargin
,
552 kComputedTitleElementSpacing
));
554 bool need_account_switcher
=
555 provider_
&& provider_
->GetNotifierGroupCount() > 1;
556 int top_label_resource_id
=
557 need_account_switcher
? IDS_MESSAGE_CENTER_SETTINGS_DESCRIPTION_MULTIUSER
558 : IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION
;
560 views::Label
* top_label
=
561 new views::Label(l10n_util::GetStringUTF16(top_label_resource_id
));
563 top_label
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
564 top_label
->SetMultiLine(true);
565 top_label
->SetBorder(views::Border::CreateEmptyBorder(
567 settings::kTitleMargin
+ kMenuButtonInnateMargin
,
569 settings::kTitleMargin
+ kMenuButtonInnateMargin
));
570 contents_title_view
->AddChildView(top_label
);
572 if (need_account_switcher
) {
573 const NotifierGroup
& active_group
= provider_
->GetActiveNotifierGroup();
574 base::string16 notifier_group_text
= active_group
.login_info
.empty() ?
575 active_group
.name
: active_group
.login_info
;
576 notifier_group_selector_
=
577 new views::MenuButton(NULL
, notifier_group_text
, this, true);
578 notifier_group_selector_
->SetBorder(scoped_ptr
<views::Border
>(
579 new views::LabelButtonBorder(views::Button::STYLE_BUTTON
)).Pass());
580 notifier_group_selector_
->SetFocusPainter(nullptr);
581 notifier_group_selector_
->set_animate_on_state_change(false);
582 notifier_group_selector_
->SetFocusable(true);
583 contents_title_view
->AddChildView(notifier_group_selector_
);
586 contents_view
->AddChildView(contents_title_view
);
588 size_t notifier_count
= notifiers
.size();
589 for (size_t i
= 0; i
< notifier_count
; ++i
) {
590 NotifierButton
* button
= new NotifierButton(provider_
, notifiers
[i
], this);
591 EntryView
* entry
= new EntryView(button
);
593 // This code emulates separators using borders. We will create an invisible
594 // border on the last notifier, as the spec leaves a space for it.
595 scoped_ptr
<views::Border
> entry_border
;
596 if (i
== notifier_count
- 1) {
597 entry_border
= views::Border::CreateEmptyBorder(
598 0, 0, settings::kEntrySeparatorHeight
, 0);
601 views::Border::CreateSolidSidedBorder(0,
603 settings::kEntrySeparatorHeight
,
605 settings::kEntrySeparatorColor
);
607 entry
->SetBorder(entry_border
.Pass());
608 entry
->SetFocusable(true);
609 contents_view
->AddChildView(entry
);
610 buttons_
.insert(button
);
613 scroller_
->SetContents(contents_view
);
615 contents_view
->SetBoundsRect(gfx::Rect(contents_view
->GetPreferredSize()));
619 void NotifierSettingsView::Layout() {
620 int title_height
= title_label_
->GetHeightForWidth(width());
621 title_label_
->SetBounds(settings::kTitleMargin
,
623 width() - settings::kTitleMargin
* 2,
626 views::View
* contents_view
= scroller_
->contents();
627 int content_width
= width();
628 int content_height
= contents_view
->GetHeightForWidth(content_width
);
629 if (title_height
+ content_height
> height()) {
630 content_width
-= scroller_
->GetScrollBarWidth();
631 content_height
= contents_view
->GetHeightForWidth(content_width
);
633 contents_view
->SetBounds(0, 0, content_width
, content_height
);
634 scroller_
->SetBounds(0, title_height
, width(), height() - title_height
);
637 gfx::Size
NotifierSettingsView::GetMinimumSize() const {
638 gfx::Size
size(settings::kWidth
, settings::kMinimumHeight
);
639 int total_height
= title_label_
->GetPreferredSize().height() +
640 scroller_
->contents()->GetPreferredSize().height();
641 if (total_height
> settings::kMinimumHeight
)
642 size
.Enlarge(scroller_
->GetScrollBarWidth(), 0);
646 gfx::Size
NotifierSettingsView::GetPreferredSize() const {
647 gfx::Size preferred_size
;
648 gfx::Size title_size
= title_label_
->GetPreferredSize();
649 gfx::Size content_size
= scroller_
->contents()->GetPreferredSize();
650 return gfx::Size(std::max(title_size
.width(), content_size
.width()),
651 title_size
.height() + content_size
.height());
654 bool NotifierSettingsView::OnKeyPressed(const ui::KeyEvent
& event
) {
655 if (event
.key_code() == ui::VKEY_ESCAPE
) {
656 GetWidget()->Close();
660 return scroller_
->OnKeyPressed(event
);
663 bool NotifierSettingsView::OnMouseWheel(const ui::MouseWheelEvent
& event
) {
664 return scroller_
->OnMouseWheel(event
);
667 void NotifierSettingsView::ButtonPressed(views::Button
* sender
,
668 const ui::Event
& event
) {
669 if (sender
== title_arrow_
) {
670 MessageCenterView
* center_view
= static_cast<MessageCenterView
*>(parent());
671 center_view
->SetSettingsVisible(!center_view
->settings_visible());
675 std::set
<NotifierButton
*>::iterator iter
=
676 buttons_
.find(static_cast<NotifierButton
*>(sender
));
678 if (iter
== buttons_
.end())
681 (*iter
)->SetChecked(!(*iter
)->checked());
683 provider_
->SetNotifierEnabled((*iter
)->notifier(), (*iter
)->checked());
686 void NotifierSettingsView::OnMenuButtonClicked(views::View
* source
,
687 const gfx::Point
& point
) {
688 notifier_group_menu_model_
.reset(new NotifierGroupMenuModel(provider_
));
689 notifier_group_menu_runner_
.reset(new views::MenuRunner(
690 notifier_group_menu_model_
.get(), views::MenuRunner::CONTEXT_MENU
));
691 gfx::Rect menu_anchor
= source
->GetBoundsInScreen();
693 gfx::Insets(0, kMenuWhitespaceOffset
, 0, kMenuWhitespaceOffset
));
694 if (views::MenuRunner::MENU_DELETED
==
695 notifier_group_menu_runner_
->RunMenuAt(GetWidget(),
696 notifier_group_selector_
,
698 views::MENU_ANCHOR_BUBBLE_ABOVE
,
699 ui::MENU_SOURCE_MOUSE
))
701 MessageCenterView
* center_view
= static_cast<MessageCenterView
*>(parent());
702 center_view
->OnSettingsChanged();
705 } // namespace message_center