Update path of checkdeps to buildtools checkout
[chromium-blink-merge.git] / ui / message_center / views / notifier_settings_view.cc
blob5a46f48cd6337d799b5eb4a9cdf033af92dbb022
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"
7 #include <set>
8 #include <string>
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "grit/ui_resources.h"
13 #include "grit/ui_strings.h"
14 #include "skia/ext/image_operations.h"
15 #include "third_party/skia/include/core/SkColor.h"
16 #include "ui/base/l10n/l10n_util.h"
17 #include "ui/base/models/simple_menu_model.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/events/keycodes/keyboard_codes.h"
20 #include "ui/gfx/canvas.h"
21 #include "ui/gfx/image/image.h"
22 #include "ui/gfx/size.h"
23 #include "ui/message_center/message_center_style.h"
24 #include "ui/message_center/views/message_center_view.h"
25 #include "ui/views/background.h"
26 #include "ui/views/border.h"
27 #include "ui/views/controls/button/checkbox.h"
28 #include "ui/views/controls/button/custom_button.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 {
45 namespace settings {
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
70 namespace {
72 // The amount of built-in padding for the notifier group switcher.
73 const int kButtonPainterInsets = 5;
75 // Menu button metrics to make the text line up.
76 const int kMenuButtonInnateMargin = 2;
77 const int kMenuButtonLeftPadding = 12;
78 const int kMenuButtonRightPadding = 13;
79 const int kMenuButtonVerticalPadding = 9;
81 // Used to place the context menu correctly.
82 const int kMenuWhitespaceOffset = 2;
84 // The innate vertical blank space in the label for the title of the settings
85 // pane.
86 const int kInnateTitleBottomMargin = 1;
87 const int kInnateTitleTopMargin = 7;
89 // The innate top blank space in the label for the description of the settings
90 // pane.
91 const int kInnateDescriptionTopMargin = 2;
93 // Checkboxes have some built-in right padding blank space.
94 const int kInnateCheckboxRightPadding = 2;
96 // Spec defines the checkbox size; the innate padding throws this measurement
97 // off so we need to compute a slightly different area for the checkbox to
98 // inhabit.
99 const int kComputedCheckboxSize =
100 settings::kCheckboxSizeWithPadding - kInnateCheckboxRightPadding;
102 // The menubutton has innate margin, so we need to compensate for that when
103 // figuring the margin of the title area.
104 const int kComputedContentsTitleMargin = 0 - kMenuButtonInnateMargin;
106 // The spec doesn't include the bottom blank area of the title bar or the innate
107 // blank area in the description label, so we'll use this as the space between
108 // the title and description.
109 const int kComputedTitleBottomMargin = settings::kDescriptionToSwitcherSpace -
110 kInnateTitleBottomMargin -
111 kInnateDescriptionTopMargin;
113 // The blank space above the title needs to be adjusted by the amount of blank
114 // space included in the title label.
115 const int kComputedTitleTopMargin =
116 settings::kTopMargin - kInnateTitleTopMargin;
118 // The switcher has a lot of blank space built in so we should include that when
119 // spacing the title area vertically.
120 const int kComputedTitleElementSpacing =
121 settings::kDescriptionToSwitcherSpace - kButtonPainterInsets - 1;
123 // A function to create a focus border.
124 scoped_ptr<views::Painter> CreateFocusPainter() {
125 return views::Painter::CreateSolidFocusPainter(kFocusBorderColor,
126 gfx::Insets(1, 2, 3, 2));
129 // EntryView ------------------------------------------------------------------
131 // The view to guarantee the 48px height and place the contents at the
132 // middle. It also guarantee the left margin.
133 class EntryView : public views::View {
134 public:
135 explicit EntryView(views::View* contents);
136 virtual ~EntryView();
138 // views::View:
139 virtual void Layout() OVERRIDE;
140 virtual gfx::Size GetPreferredSize() const OVERRIDE;
141 virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
142 virtual void OnFocus() OVERRIDE;
143 virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
144 virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE;
145 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
146 virtual void OnBlur() OVERRIDE;
148 private:
149 scoped_ptr<views::Painter> focus_painter_;
151 DISALLOW_COPY_AND_ASSIGN(EntryView);
154 EntryView::EntryView(views::View* contents)
155 : focus_painter_(CreateFocusPainter()) {
156 AddChildView(contents);
159 EntryView::~EntryView() {}
161 void EntryView::Layout() {
162 DCHECK_EQ(1, child_count());
163 views::View* content = child_at(0);
164 int content_width = width();
165 int content_height = content->GetHeightForWidth(content_width);
166 int y = std::max((height() - content_height) / 2, 0);
167 content->SetBounds(0, y, content_width, content_height);
170 gfx::Size EntryView::GetPreferredSize() const {
171 DCHECK_EQ(1, child_count());
172 gfx::Size size = child_at(0)->GetPreferredSize();
173 size.SetToMax(gfx::Size(settings::kWidth, settings::kEntryHeight));
174 return size;
177 void EntryView::GetAccessibleState(ui::AXViewState* state) {
178 DCHECK_EQ(1, child_count());
179 child_at(0)->GetAccessibleState(state);
182 void EntryView::OnFocus() {
183 views::View::OnFocus();
184 ScrollRectToVisible(GetLocalBounds());
185 // We render differently when focused.
186 SchedulePaint();
189 bool EntryView::OnKeyPressed(const ui::KeyEvent& event) {
190 return child_at(0)->OnKeyPressed(event);
193 bool EntryView::OnKeyReleased(const ui::KeyEvent& event) {
194 return child_at(0)->OnKeyReleased(event);
197 void EntryView::OnPaint(gfx::Canvas* canvas) {
198 View::OnPaint(canvas);
199 views::Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
202 void EntryView::OnBlur() {
203 View::OnBlur();
204 // We render differently when focused.
205 SchedulePaint();
208 } // namespace
211 // NotifierGroupMenuModel -----------------------------------------------------
213 class NotifierGroupMenuModel : public ui::SimpleMenuModel,
214 public ui::SimpleMenuModel::Delegate {
215 public:
216 NotifierGroupMenuModel(NotifierSettingsProvider* notifier_settings_provider);
217 virtual ~NotifierGroupMenuModel();
219 // ui::SimpleMenuModel::Delegate:
220 virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
221 virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
222 virtual bool GetAcceleratorForCommandId(
223 int command_id,
224 ui::Accelerator* accelerator) OVERRIDE;
225 virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
227 private:
228 NotifierSettingsProvider* notifier_settings_provider_;
230 DISALLOW_COPY_AND_ASSIGN(NotifierGroupMenuModel);
233 NotifierGroupMenuModel::NotifierGroupMenuModel(
234 NotifierSettingsProvider* notifier_settings_provider)
235 : ui::SimpleMenuModel(this),
236 notifier_settings_provider_(notifier_settings_provider) {
237 if (!notifier_settings_provider_)
238 return;
240 size_t num_menu_items = notifier_settings_provider_->GetNotifierGroupCount();
241 for (size_t i = 0; i < num_menu_items; ++i) {
242 const NotifierGroup& group =
243 notifier_settings_provider_->GetNotifierGroupAt(i);
245 AddCheckItem(i, group.login_info.empty() ? group.name : group.login_info);
249 NotifierGroupMenuModel::~NotifierGroupMenuModel() {}
251 bool NotifierGroupMenuModel::IsCommandIdChecked(int command_id) const {
252 // If there's no provider, assume only one notifier group - the active one.
253 return !notifier_settings_provider_ ||
254 notifier_settings_provider_->IsNotifierGroupActiveAt(command_id);
257 bool NotifierGroupMenuModel::IsCommandIdEnabled(int command_id) const {
258 return true;
261 bool NotifierGroupMenuModel::GetAcceleratorForCommandId(
262 int command_id,
263 ui::Accelerator* accelerator) {
264 return false;
267 void NotifierGroupMenuModel::ExecuteCommand(int command_id, int event_flags) {
268 if (!notifier_settings_provider_)
269 return;
271 size_t notifier_group_index = static_cast<size_t>(command_id);
272 size_t num_notifier_groups =
273 notifier_settings_provider_->GetNotifierGroupCount();
274 if (notifier_group_index >= num_notifier_groups)
275 return;
277 notifier_settings_provider_->SwitchToNotifierGroup(notifier_group_index);
281 // NotifierSettingsView::NotifierButton ---------------------------------------
283 // We do not use views::Checkbox class directly because it doesn't support
284 // showing 'icon'.
285 NotifierSettingsView::NotifierButton::NotifierButton(
286 NotifierSettingsProvider* provider,
287 Notifier* notifier,
288 views::ButtonListener* listener)
289 : views::CustomButton(listener),
290 provider_(provider),
291 notifier_(notifier),
292 icon_view_(new views::ImageView()),
293 name_view_(new views::Label(notifier_->name)),
294 checkbox_(new views::Checkbox(base::string16())),
295 learn_more_(NULL) {
296 DCHECK(provider);
297 DCHECK(notifier);
299 // Since there may never be an icon (but that could change at a later time),
300 // we own the icon view here.
301 icon_view_->set_owned_by_client();
303 checkbox_->SetChecked(notifier_->enabled);
304 checkbox_->set_listener(this);
305 checkbox_->SetFocusable(false);
306 checkbox_->SetAccessibleName(notifier_->name);
308 if (ShouldHaveLearnMoreButton()) {
309 // Create a more-info button that will be right-aligned.
310 learn_more_ = new views::ImageButton(this);
311 learn_more_->SetFocusPainter(CreateFocusPainter());
312 learn_more_->set_request_focus_on_press(false);
313 learn_more_->SetFocusable(true);
315 ui::ResourceBundle& rb = ResourceBundle::GetSharedInstance();
316 learn_more_->SetImage(
317 views::Button::STATE_NORMAL,
318 rb.GetImageSkiaNamed(IDR_NOTIFICATION_ADVANCED_SETTINGS));
319 learn_more_->SetImage(
320 views::Button::STATE_HOVERED,
321 rb.GetImageSkiaNamed(IDR_NOTIFICATION_ADVANCED_SETTINGS_HOVER));
322 learn_more_->SetImage(
323 views::Button::STATE_PRESSED,
324 rb.GetImageSkiaNamed(IDR_NOTIFICATION_ADVANCED_SETTINGS_PRESSED));
325 learn_more_->SetState(views::Button::STATE_NORMAL);
326 int learn_more_border_width =
327 (settings::kLearnMoreTargetWidth - settings::kLearnMoreSize) / 2;
328 int learn_more_border_height =
329 (settings::kLearnMoreTargetHeight - settings::kLearnMoreSize) / 2;
330 // The image itself is quite small, this large invisible border creates a
331 // much bigger click target.
332 learn_more_->SetBorder(
333 views::Border::CreateEmptyBorder(learn_more_border_height,
334 learn_more_border_width,
335 learn_more_border_height,
336 learn_more_border_width));
337 learn_more_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
338 views::ImageButton::ALIGN_MIDDLE);
341 UpdateIconImage(notifier_->icon);
344 NotifierSettingsView::NotifierButton::~NotifierButton() {
347 void NotifierSettingsView::NotifierButton::UpdateIconImage(
348 const gfx::Image& icon) {
349 bool has_icon_view = false;
351 notifier_->icon = icon;
352 if (!icon.IsEmpty()) {
353 icon_view_->SetImage(icon.ToImageSkia());
354 icon_view_->SetImageSize(
355 gfx::Size(settings::kEntryIconSize, settings::kEntryIconSize));
356 has_icon_view = true;
358 GridChanged(ShouldHaveLearnMoreButton(), has_icon_view);
361 void NotifierSettingsView::NotifierButton::SetChecked(bool checked) {
362 checkbox_->SetChecked(checked);
363 notifier_->enabled = checked;
366 bool NotifierSettingsView::NotifierButton::checked() const {
367 return checkbox_->checked();
370 bool NotifierSettingsView::NotifierButton::has_learn_more() const {
371 return learn_more_ != NULL;
374 const Notifier& NotifierSettingsView::NotifierButton::notifier() const {
375 return *notifier_.get();
378 void NotifierSettingsView::NotifierButton::SendLearnMorePressedForTest() {
379 if (learn_more_ == NULL)
380 return;
381 gfx::Point point(110, 120);
382 ui::MouseEvent pressed(
383 ui::ET_MOUSE_PRESSED, point, point, ui::EF_LEFT_MOUSE_BUTTON,
384 ui::EF_LEFT_MOUSE_BUTTON);
385 ButtonPressed(learn_more_, pressed);
388 void NotifierSettingsView::NotifierButton::ButtonPressed(
389 views::Button* button,
390 const ui::Event& event) {
391 if (button == checkbox_) {
392 // The checkbox state has already changed at this point, but we'll update
393 // the state on NotifierSettingsView::ButtonPressed() too, so here change
394 // back to the previous state.
395 checkbox_->SetChecked(!checkbox_->checked());
396 CustomButton::NotifyClick(event);
397 } else if (button == learn_more_) {
398 DCHECK(provider_);
399 provider_->OnNotifierAdvancedSettingsRequested(notifier_->notifier_id,
400 NULL);
404 void NotifierSettingsView::NotifierButton::GetAccessibleState(
405 ui::AXViewState* state) {
406 static_cast<views::View*>(checkbox_)->GetAccessibleState(state);
409 bool NotifierSettingsView::NotifierButton::ShouldHaveLearnMoreButton() const {
410 if (!provider_)
411 return false;
413 return provider_->NotifierHasAdvancedSettings(notifier_->notifier_id);
416 void NotifierSettingsView::NotifierButton::GridChanged(bool has_learn_more,
417 bool has_icon_view) {
418 using views::ColumnSet;
419 using views::GridLayout;
421 GridLayout* layout = new GridLayout(this);
422 SetLayoutManager(layout);
423 ColumnSet* cs = layout->AddColumnSet(0);
424 // Add a column for the checkbox.
425 cs->AddPaddingColumn(0, kInnateCheckboxRightPadding);
426 cs->AddColumn(GridLayout::CENTER,
427 GridLayout::CENTER,
429 GridLayout::FIXED,
430 kComputedCheckboxSize,
432 cs->AddPaddingColumn(0, settings::kInternalHorizontalSpacing);
434 if (has_icon_view) {
435 // Add a column for the icon.
436 cs->AddColumn(GridLayout::CENTER,
437 GridLayout::CENTER,
439 GridLayout::FIXED,
440 settings::kEntryIconSize,
442 cs->AddPaddingColumn(0, settings::kInternalHorizontalSpacing);
445 // Add a column for the name.
446 cs->AddColumn(
447 GridLayout::LEADING, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0);
449 // Add a padding column which contains expandable blank space.
450 cs->AddPaddingColumn(1, 0);
452 // Add a column for the learn more button if necessary.
453 if (has_learn_more) {
454 cs->AddPaddingColumn(0, settings::kInternalHorizontalSpacing);
455 cs->AddColumn(
456 GridLayout::CENTER, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0);
459 layout->StartRow(0, 0);
460 layout->AddView(checkbox_);
461 if (has_icon_view)
462 layout->AddView(icon_view_.get());
463 layout->AddView(name_view_);
464 if (has_learn_more)
465 layout->AddView(learn_more_);
467 Layout();
471 // NotifierSettingsView -------------------------------------------------------
473 NotifierSettingsView::NotifierSettingsView(NotifierSettingsProvider* provider)
474 : title_arrow_(NULL),
475 title_label_(NULL),
476 notifier_group_selector_(NULL),
477 scroller_(NULL),
478 provider_(provider) {
479 // |provider_| may be NULL in tests.
480 if (provider_)
481 provider_->AddObserver(this);
483 SetFocusable(true);
484 set_background(
485 views::Background::CreateSolidBackground(kMessageCenterBackgroundColor));
486 SetPaintToLayer(true);
488 title_label_ = new views::Label(
489 l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_SETTINGS_BUTTON_LABEL),
490 ui::ResourceBundle::GetSharedInstance().GetFontList(
491 ui::ResourceBundle::MediumFont));
492 title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
493 title_label_->SetMultiLine(true);
494 title_label_->SetBorder(
495 views::Border::CreateEmptyBorder(kComputedTitleTopMargin,
496 settings::kTitleMargin,
497 kComputedTitleBottomMargin,
498 settings::kTitleMargin));
500 AddChildView(title_label_);
502 scroller_ = new views::ScrollView();
503 scroller_->SetVerticalScrollBar(new views::OverlayScrollBar(false));
504 AddChildView(scroller_);
506 std::vector<Notifier*> notifiers;
507 if (provider_)
508 provider_->GetNotifierList(&notifiers);
510 UpdateContentsView(notifiers);
513 NotifierSettingsView::~NotifierSettingsView() {
514 // |provider_| may be NULL in tests.
515 if (provider_)
516 provider_->RemoveObserver(this);
519 bool NotifierSettingsView::IsScrollable() {
520 return scroller_->height() < scroller_->contents()->height();
523 void NotifierSettingsView::UpdateIconImage(const NotifierId& notifier_id,
524 const gfx::Image& icon) {
525 for (std::set<NotifierButton*>::iterator iter = buttons_.begin();
526 iter != buttons_.end();
527 ++iter) {
528 if ((*iter)->notifier().notifier_id == notifier_id) {
529 (*iter)->UpdateIconImage(icon);
530 return;
535 void NotifierSettingsView::NotifierGroupChanged() {
536 std::vector<Notifier*> notifiers;
537 if (provider_)
538 provider_->GetNotifierList(&notifiers);
540 UpdateContentsView(notifiers);
543 void NotifierSettingsView::NotifierEnabledChanged(const NotifierId& notifier_id,
544 bool enabled) {}
546 void NotifierSettingsView::UpdateContentsView(
547 const std::vector<Notifier*>& notifiers) {
548 buttons_.clear();
550 views::View* contents_view = new views::View();
551 contents_view->SetLayoutManager(new views::BoxLayout(
552 views::BoxLayout::kVertical, settings::kHorizontalMargin, 0, 0));
554 views::View* contents_title_view = new views::View();
555 contents_title_view->SetLayoutManager(
556 new views::BoxLayout(views::BoxLayout::kVertical,
557 kComputedContentsTitleMargin,
559 kComputedTitleElementSpacing));
561 bool need_account_switcher =
562 provider_ && provider_->GetNotifierGroupCount() > 1;
563 int top_label_resource_id =
564 need_account_switcher ? IDS_MESSAGE_CENTER_SETTINGS_DESCRIPTION_MULTIUSER
565 : IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION;
567 views::Label* top_label =
568 new views::Label(l10n_util::GetStringUTF16(top_label_resource_id));
570 top_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
571 top_label->SetMultiLine(true);
572 top_label->SetBorder(views::Border::CreateEmptyBorder(
574 settings::kTitleMargin + kMenuButtonInnateMargin,
576 settings::kTitleMargin + kMenuButtonInnateMargin));
577 contents_title_view->AddChildView(top_label);
579 if (need_account_switcher) {
580 const NotifierGroup& active_group = provider_->GetActiveNotifierGroup();
581 base::string16 notifier_group_text = active_group.login_info.empty() ?
582 active_group.name : active_group.login_info;
583 notifier_group_selector_ =
584 new views::MenuButton(NULL, notifier_group_text, this, true);
585 scoped_ptr<views::TextButtonDefaultBorder> selector_border(
586 new views::TextButtonDefaultBorder());
587 ui::ResourceBundle* rb = &ResourceBundle::GetSharedInstance();
588 gfx::Insets painter_insets(kButtonPainterInsets, kButtonPainterInsets,
589 kButtonPainterInsets, kButtonPainterInsets);
590 selector_border->set_normal_painter(views::Painter::CreateImagePainter(
591 *rb->GetImageSkiaNamed(IDR_BUTTON_NORMAL), painter_insets));
592 selector_border->set_hot_painter(views::Painter::CreateImagePainter(
593 *rb->GetImageSkiaNamed(IDR_BUTTON_HOVER), painter_insets));
594 selector_border->set_pushed_painter(views::Painter::CreateImagePainter(
595 *rb->GetImageSkiaNamed(IDR_BUTTON_PRESSED), painter_insets));
596 selector_border->SetInsets(gfx::Insets(
597 kMenuButtonVerticalPadding, kMenuButtonLeftPadding,
598 kMenuButtonVerticalPadding, kMenuButtonRightPadding));
599 notifier_group_selector_->SetBorder(
600 selector_border.PassAs<views::Border>());
601 notifier_group_selector_->SetFocusPainter(scoped_ptr<views::Painter>());
602 notifier_group_selector_->set_animate_on_state_change(false);
603 notifier_group_selector_->SetFocusable(true);
604 contents_title_view->AddChildView(notifier_group_selector_);
607 contents_view->AddChildView(contents_title_view);
609 size_t notifier_count = notifiers.size();
610 for (size_t i = 0; i < notifier_count; ++i) {
611 NotifierButton* button = new NotifierButton(provider_, notifiers[i], this);
612 EntryView* entry = new EntryView(button);
614 // This code emulates separators using borders. We will create an invisible
615 // border on the last notifier, as the spec leaves a space for it.
616 scoped_ptr<views::Border> entry_border;
617 if (i == notifier_count - 1) {
618 entry_border = views::Border::CreateEmptyBorder(
619 0, 0, settings::kEntrySeparatorHeight, 0);
620 } else {
621 entry_border =
622 views::Border::CreateSolidSidedBorder(0,
624 settings::kEntrySeparatorHeight,
626 settings::kEntrySeparatorColor);
628 entry->SetBorder(entry_border.Pass());
629 entry->SetFocusable(true);
630 contents_view->AddChildView(entry);
631 buttons_.insert(button);
634 scroller_->SetContents(contents_view);
636 contents_view->SetBoundsRect(gfx::Rect(contents_view->GetPreferredSize()));
637 InvalidateLayout();
640 void NotifierSettingsView::Layout() {
641 int title_height = title_label_->GetHeightForWidth(width());
642 title_label_->SetBounds(settings::kTitleMargin,
644 width() - settings::kTitleMargin * 2,
645 title_height);
647 views::View* contents_view = scroller_->contents();
648 int content_width = width();
649 int content_height = contents_view->GetHeightForWidth(content_width);
650 if (title_height + content_height > height()) {
651 content_width -= scroller_->GetScrollBarWidth();
652 content_height = contents_view->GetHeightForWidth(content_width);
654 contents_view->SetBounds(0, 0, content_width, content_height);
655 scroller_->SetBounds(0, title_height, width(), height() - title_height);
658 gfx::Size NotifierSettingsView::GetMinimumSize() const {
659 gfx::Size size(settings::kWidth, settings::kMinimumHeight);
660 int total_height = title_label_->GetPreferredSize().height() +
661 scroller_->contents()->GetPreferredSize().height();
662 if (total_height > settings::kMinimumHeight)
663 size.Enlarge(scroller_->GetScrollBarWidth(), 0);
664 return size;
667 gfx::Size NotifierSettingsView::GetPreferredSize() const {
668 gfx::Size preferred_size;
669 gfx::Size title_size = title_label_->GetPreferredSize();
670 gfx::Size content_size = scroller_->contents()->GetPreferredSize();
671 return gfx::Size(std::max(title_size.width(), content_size.width()),
672 title_size.height() + content_size.height());
675 bool NotifierSettingsView::OnKeyPressed(const ui::KeyEvent& event) {
676 if (event.key_code() == ui::VKEY_ESCAPE) {
677 GetWidget()->Close();
678 return true;
681 return scroller_->OnKeyPressed(event);
684 bool NotifierSettingsView::OnMouseWheel(const ui::MouseWheelEvent& event) {
685 return scroller_->OnMouseWheel(event);
688 void NotifierSettingsView::ButtonPressed(views::Button* sender,
689 const ui::Event& event) {
690 if (sender == title_arrow_) {
691 MessageCenterView* center_view = static_cast<MessageCenterView*>(parent());
692 center_view->SetSettingsVisible(!center_view->settings_visible());
693 return;
696 std::set<NotifierButton*>::iterator iter =
697 buttons_.find(static_cast<NotifierButton*>(sender));
699 if (iter == buttons_.end())
700 return;
702 (*iter)->SetChecked(!(*iter)->checked());
703 if (provider_)
704 provider_->SetNotifierEnabled((*iter)->notifier(), (*iter)->checked());
707 void NotifierSettingsView::OnMenuButtonClicked(views::View* source,
708 const gfx::Point& point) {
709 notifier_group_menu_model_.reset(new NotifierGroupMenuModel(provider_));
710 notifier_group_menu_runner_.reset(
711 new views::MenuRunner(notifier_group_menu_model_.get()));
712 gfx::Rect menu_anchor = source->GetBoundsInScreen();
713 menu_anchor.Inset(
714 gfx::Insets(0, kMenuWhitespaceOffset, 0, kMenuWhitespaceOffset));
715 if (views::MenuRunner::MENU_DELETED ==
716 notifier_group_menu_runner_->RunMenuAt(GetWidget(),
717 notifier_group_selector_,
718 menu_anchor,
719 views::MENU_ANCHOR_BUBBLE_ABOVE,
720 ui::MENU_SOURCE_MOUSE,
721 views::MenuRunner::CONTEXT_MENU))
722 return;
723 MessageCenterView* center_view = static_cast<MessageCenterView*>(parent());
724 center_view->OnSettingsChanged();
727 } // namespace message_center