1// Copyright 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.
4
5#include "ui/message_center/views/message_center_button_bar.h"
6
7#include "ui/base/models/simple_menu_model.h"
8#include "ui/base/resource/resource_bundle.h"
9#include "ui/gfx/canvas.h"
10#include "ui/gfx/text_constants.h"
11#include "ui/message_center/message_center.h"
12#include "ui/message_center/message_center_style.h"
13#include "ui/message_center/message_center_tray.h"
14#include "ui/message_center/notifier_settings.h"
15#include "ui/message_center/views/message_center_view.h"
16#include "ui/resources/grit/ui_resources.h"
17#include "ui/strings/grit/ui_strings.h"
18#include "ui/views/controls/button/button.h"
19#include "ui/views/controls/button/image_button.h"
20#include "ui/views/controls/button/label_button.h"
21#include "ui/views/controls/button/menu_button.h"
22#include "ui/views/controls/button/menu_button_listener.h"
23#include "ui/views/controls/label.h"
24#include "ui/views/controls/menu/menu_runner.h"
25#include "ui/views/layout/box_layout.h"
26#include "ui/views/layout/grid_layout.h"
27#include "ui/views/painter.h"
28
29namespace message_center {
30
31namespace {
32const int kButtonSize = 40;
33const int kChevronWidth = 8;
34const int kFooterTopMargin = 6;
35const int kFooterBottomMargin = 3;
36const int kFooterLeftMargin = 20;
37const int kFooterRightMargin = 14;
38}  // namespace
39
40// NotificationCenterButton ////////////////////////////////////////////////////
41////////////////////////////////////////////////////////////////////////////////
42class NotificationCenterButton : public views::ToggleImageButton {
43 public:
44  NotificationCenterButton(views::ButtonListener* listener,
45                           int normal_id,
46                           int hover_id,
47                           int pressed_id,
48                           int text_id);
49  void set_size(gfx::Size size) { size_ = size; }
50
51 protected:
52  // Overridden from views::View:
53  virtual gfx::Size GetPreferredSize() const OVERRIDE;
54
55 private:
56  gfx::Size size_;
57
58  DISALLOW_COPY_AND_ASSIGN(NotificationCenterButton);
59};
60
61NotificationCenterButton::NotificationCenterButton(
62    views::ButtonListener* listener,
63    int normal_id,
64    int hover_id,
65    int pressed_id,
66    int text_id)
67    : views::ToggleImageButton(listener), size_(kButtonSize, kButtonSize) {
68  ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
69  SetImage(STATE_NORMAL, resource_bundle.GetImageSkiaNamed(normal_id));
70  SetImage(STATE_HOVERED, resource_bundle.GetImageSkiaNamed(hover_id));
71  SetImage(STATE_PRESSED, resource_bundle.GetImageSkiaNamed(pressed_id));
72  SetImageAlignment(views::ImageButton::ALIGN_CENTER,
73                    views::ImageButton::ALIGN_MIDDLE);
74  if (text_id)
75    SetTooltipText(resource_bundle.GetLocalizedString(text_id));
76
77  SetFocusable(true);
78  set_request_focus_on_press(false);
79
80  SetFocusPainter(views::Painter::CreateSolidFocusPainter(
81      kFocusBorderColor,
82      gfx::Insets(1, 2, 2, 2)));
83}
84
85gfx::Size NotificationCenterButton::GetPreferredSize() const { return size_; }
86
87// MessageCenterButtonBar /////////////////////////////////////////////////////
88///////////////////////////////////////////////////////////////////////////////
89MessageCenterButtonBar::MessageCenterButtonBar(
90    MessageCenterView* message_center_view,
91    MessageCenter* message_center,
92    NotifierSettingsProvider* notifier_settings_provider,
93    bool settings_initially_visible,
94    const base::string16& title)
95    : message_center_view_(message_center_view),
96      message_center_(message_center),
97#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
98      close_bubble_button_(NULL),
99#endif
100      title_arrow_(NULL),
101      notification_label_(NULL),
102      button_container_(NULL),
103      close_all_button_(NULL),
104      settings_button_(NULL),
105      quiet_mode_button_(NULL) {
106  SetPaintToLayer(true);
107  set_background(
108      views::Background::CreateSolidBackground(kMessageCenterBackgroundColor));
109
110  ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
111
112  title_arrow_ = new NotificationCenterButton(this,
113                                              IDR_NOTIFICATION_ARROW,
114                                              IDR_NOTIFICATION_ARROW_HOVER,
115                                              IDR_NOTIFICATION_ARROW_PRESSED,
116                                              0);
117  title_arrow_->set_size(gfx::Size(kChevronWidth, kButtonSize));
118
119  // Keyboardists can use the gear button to switch modes.
120  title_arrow_->SetFocusable(false);
121  AddChildView(title_arrow_);
122
123  notification_label_ = new views::Label(title);
124  notification_label_->SetAutoColorReadabilityEnabled(false);
125  notification_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
126  notification_label_->SetEnabledColor(kRegularTextColor);
127  AddChildView(notification_label_);
128
129  button_container_ = new views::View;
130  button_container_->SetLayoutManager(
131      new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
132  quiet_mode_button_ = new NotificationCenterButton(
133      this,
134      IDR_NOTIFICATION_DO_NOT_DISTURB,
135      IDR_NOTIFICATION_DO_NOT_DISTURB_HOVER,
136      IDR_NOTIFICATION_DO_NOT_DISTURB_PRESSED,
137      IDS_MESSAGE_CENTER_QUIET_MODE_BUTTON_TOOLTIP);
138  quiet_mode_button_->SetToggledImage(
139      views::Button::STATE_NORMAL,
140      resource_bundle.GetImageSkiaNamed(
141          IDR_NOTIFICATION_DO_NOT_DISTURB_PRESSED));
142  quiet_mode_button_->SetToggledImage(
143      views::Button::STATE_HOVERED,
144      resource_bundle.GetImageSkiaNamed(
145          IDR_NOTIFICATION_DO_NOT_DISTURB_PRESSED));
146  quiet_mode_button_->SetToggledImage(
147      views::Button::STATE_PRESSED,
148      resource_bundle.GetImageSkiaNamed(
149          IDR_NOTIFICATION_DO_NOT_DISTURB_PRESSED));
150  quiet_mode_button_->SetToggled(message_center->IsQuietMode());
151  button_container_->AddChildView(quiet_mode_button_);
152
153  close_all_button_ =
154      new NotificationCenterButton(this,
155                                   IDR_NOTIFICATION_CLEAR_ALL,
156                                   IDR_NOTIFICATION_CLEAR_ALL_HOVER,
157                                   IDR_NOTIFICATION_CLEAR_ALL_PRESSED,
158                                   IDS_MESSAGE_CENTER_CLEAR_ALL);
159  close_all_button_->SetImage(
160      views::Button::STATE_DISABLED,
161      resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_CLEAR_ALL_DISABLED));
162  button_container_->AddChildView(close_all_button_);
163
164  settings_button_ =
165      new NotificationCenterButton(this,
166                                   IDR_NOTIFICATION_SETTINGS,
167                                   IDR_NOTIFICATION_SETTINGS_HOVER,
168                                   IDR_NOTIFICATION_SETTINGS_PRESSED,
169                                   IDS_MESSAGE_CENTER_SETTINGS_BUTTON_LABEL);
170  button_container_->AddChildView(settings_button_);
171
172#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
173  close_bubble_button_ = new views::ImageButton(this);
174  close_bubble_button_->SetImage(
175      views::Button::STATE_NORMAL,
176      resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_BUBBLE_CLOSE));
177  close_bubble_button_->SetImage(
178      views::Button::STATE_HOVERED,
179      resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_BUBBLE_CLOSE_HOVER));
180  close_bubble_button_->SetImage(
181      views::Button::STATE_PRESSED,
182      resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_BUBBLE_CLOSE_PRESSED));
183  AddChildView(close_bubble_button_);
184#endif
185
186  SetCloseAllButtonEnabled(!settings_initially_visible);
187  SetBackArrowVisible(settings_initially_visible);
188  ViewVisibilityChanged();
189}
190
191void MessageCenterButtonBar::ViewVisibilityChanged() {
192  gfx::ImageSkia* settings_image =
193      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
194          IDR_NOTIFICATION_SETTINGS);
195  int image_margin = std::max(0, (kButtonSize - settings_image->width()) / 2);
196  views::GridLayout* layout = new views::GridLayout(this);
197  SetLayoutManager(layout);
198  layout->SetInsets(kFooterTopMargin,
199                    kFooterLeftMargin,
200                    kFooterBottomMargin,
201                    std::max(0, kFooterRightMargin - image_margin));
202  views::ColumnSet* column = layout->AddColumnSet(0);
203  if (title_arrow_->visible()) {
204    // Column for the left-arrow used to back out of settings.
205    column->AddColumn(views::GridLayout::LEADING,
206                      views::GridLayout::CENTER,
207                      0.0f,
208                      views::GridLayout::USE_PREF,
209                      0,
210                      0);
211
212    column->AddPaddingColumn(0.0f, 10);
213  }
214
215  // Column for the label "Notifications".
216  column->AddColumn(views::GridLayout::LEADING,
217                    views::GridLayout::CENTER,
218                    0.0f,
219                    views::GridLayout::USE_PREF,
220                    0,
221                    0);
222
223  // Fills in the remaining space between "Notifications" and buttons.
224  column->AddPaddingColumn(1.0f, image_margin);
225
226  // The button area column.
227  column->AddColumn(views::GridLayout::LEADING,
228                    views::GridLayout::CENTER,
229                    0.0f,
230                    views::GridLayout::USE_PREF,
231                    0,
232                    0);
233
234#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
235  // The close-bubble button.
236  column->AddColumn(views::GridLayout::LEADING,
237                    views::GridLayout::LEADING,
238                    0.0f,
239                    views::GridLayout::USE_PREF,
240                    0,
241                    0);
242#endif
243
244  layout->StartRow(0, 0);
245  if (title_arrow_->visible())
246    layout->AddView(title_arrow_);
247  layout->AddView(notification_label_);
248  layout->AddView(button_container_);
249#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
250  layout->AddView(close_bubble_button_);
251#endif
252}
253
254MessageCenterButtonBar::~MessageCenterButtonBar() {}
255
256void MessageCenterButtonBar::SetAllButtonsEnabled(bool enabled) {
257  if (close_all_button_)
258    close_all_button_->SetEnabled(enabled);
259  settings_button_->SetEnabled(enabled);
260  quiet_mode_button_->SetEnabled(enabled);
261}
262
263void MessageCenterButtonBar::SetCloseAllButtonEnabled(bool enabled) {
264  if (close_all_button_)
265    close_all_button_->SetEnabled(enabled);
266}
267
268void MessageCenterButtonBar::SetBackArrowVisible(bool visible) {
269  if (title_arrow_)
270    title_arrow_->SetVisible(visible);
271  ViewVisibilityChanged();
272  Layout();
273}
274
275void MessageCenterButtonBar::ChildVisibilityChanged(views::View* child) {
276  InvalidateLayout();
277}
278
279void MessageCenterButtonBar::ButtonPressed(views::Button* sender,
280                                           const ui::Event& event) {
281  if (sender == close_all_button_) {
282    message_center_view()->ClearAllNotifications();
283  } else if (sender == settings_button_ || sender == title_arrow_) {
284    MessageCenterView* center_view = message_center_view();
285    center_view->SetSettingsVisible(!center_view->settings_visible());
286  } else if (sender == quiet_mode_button_) {
287    if (message_center()->IsQuietMode())
288      message_center()->SetQuietMode(false);
289    else
290      message_center()->EnterQuietModeWithExpire(base::TimeDelta::FromDays(1));
291    quiet_mode_button_->SetToggled(message_center()->IsQuietMode());
292#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
293  } else if (sender == close_bubble_button_) {
294    message_center_view()->tray()->HideMessageCenterBubble();
295#endif
296  } else {
297    NOTREACHED();
298  }
299}
300
301}  // namespace message_center
302