OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/message_center/message_view.h" | 5 #include "ui/message_center/message_view.h" |
6 | 6 |
7 #include "grit/ui_resources.h" | 7 #include "grit/ui_resources.h" |
8 #include "grit/ui_strings.h" | 8 #include "grit/ui_strings.h" |
9 #include "ui/base/l10n/l10n_util.h" | 9 #include "ui/base/l10n/l10n_util.h" |
10 #include "ui/base/models/simple_menu_model.h" | 10 #include "ui/base/models/simple_menu_model.h" |
11 #include "ui/base/resource/resource_bundle.h" | 11 #include "ui/base/resource/resource_bundle.h" |
12 #include "ui/compositor/scoped_layer_animation_settings.h" | 12 #include "ui/compositor/scoped_layer_animation_settings.h" |
13 #include "ui/gfx/canvas.h" | 13 #include "ui/gfx/canvas.h" |
14 #include "ui/gfx/shadow_value.h" | 14 #include "ui/gfx/shadow_value.h" |
15 #include "ui/gfx/skia_util.h" | 15 #include "ui/gfx/skia_util.h" |
16 #include "ui/message_center/message_center_util.h" | 16 #include "ui/message_center/message_center_util.h" |
17 #include "ui/views/controls/button/image_button.h" | 17 #include "ui/views/controls/button/image_button.h" |
18 #include "ui/views/controls/menu/menu_model_adapter.h" | 18 #include "ui/views/controls/menu/menu_model_adapter.h" |
19 #include "ui/views/controls/menu/menu_runner.h" | 19 #include "ui/views/controls/menu/menu_runner.h" |
20 #include "ui/views/controls/scroll_view.h" | 20 #include "ui/views/controls/scroll_view.h" |
21 #include "ui/views/widget/widget.h" | 21 #include "ui/views/widget/widget.h" |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 const int kCloseButtonSize = 29; | 25 const int kControlButtonSize = 29; |
26 const int kCloseIconTopPadding = 5; | 26 const int kCloseIconTopPadding = 5; |
27 const int kCloseIconRightPadding = 5; | 27 const int kCloseIconRightPadding = 5; |
| 28 const int kExpandIconBottomPadding = 8; |
| 29 const int kExpandIconRightPadding = 11; |
| 30 |
28 const int kShadowOffset = 1; | 31 const int kShadowOffset = 1; |
29 const int kShadowBlur = 4; | 32 const int kShadowBlur = 4; |
30 | 33 |
31 const SkColor kShadowColor = SkColorSetARGB(0.3 * 255, 0, 0, 0); | 34 const SkColor kShadowColor = SkColorSetARGB(0.3 * 255, 0, 0, 0); |
32 const SkColor kTransparentColor = SkColorSetARGB(0, 0, 0, 0); | 35 const SkColor kTransparentColor = SkColorSetARGB(0, 0, 0, 0); |
33 | 36 |
34 // Menu constants | 37 // Menu constants |
35 const int kTogglePermissionCommand = 0; | 38 const int kTogglePermissionCommand = 0; |
36 const int kToggleExtensionCommand = 1; | 39 const int kToggleExtensionCommand = 1; |
37 const int kShowSettingsCommand = 2; | 40 const int kShowSettingsCommand = 2; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 resource_id)); | 100 resource_id)); |
98 } | 101 } |
99 | 102 |
100 void ControlButton::SetPressedImage(int resource_id) { | 103 void ControlButton::SetPressedImage(int resource_id) { |
101 SetImage(views::CustomButton::STATE_PRESSED, | 104 SetImage(views::CustomButton::STATE_PRESSED, |
102 ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | 105 ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
103 resource_id)); | 106 resource_id)); |
104 } | 107 } |
105 | 108 |
106 gfx::Size ControlButton::GetPreferredSize() { | 109 gfx::Size ControlButton::GetPreferredSize() { |
107 return gfx::Size(kCloseButtonSize, kCloseButtonSize); | 110 return gfx::Size(kControlButtonSize, kControlButtonSize); |
108 } | 111 } |
109 | 112 |
110 void ControlButton::OnPaint(gfx::Canvas* canvas) { | 113 void ControlButton::OnPaint(gfx::Canvas* canvas) { |
111 // This is the same implementation as ImageButton::OnPaint except | 114 // This is the same implementation as ImageButton::OnPaint except |
112 // that it calls ComputePaddedImagePaintPosition() instead of | 115 // that it calls ComputePaddedImagePaintPosition() instead of |
113 // ComputeImagePaintPosition(), in effect overriding that private method. | 116 // ComputeImagePaintPosition(), in effect overriding that private method. |
114 View::OnPaint(canvas); | 117 View::OnPaint(canvas); |
115 gfx::ImageSkia image = GetImageToPaint(); | 118 gfx::ImageSkia image = GetImageToPaint(); |
116 if (!image.isNull()) { | 119 if (!image.isNull()) { |
117 gfx::Point position = ComputePaddedImagePaintPosition(image); | 120 gfx::Point position = ComputePaddedImagePaintPosition(image); |
(...skipping 26 matching lines...) Expand all Loading... |
144 } | 147 } |
145 | 148 |
146 // A border to provide the shadow for each card. | 149 // A border to provide the shadow for each card. |
147 // Current shadow should look like css box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) | 150 // Current shadow should look like css box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) |
148 class ShadowBorder : public views::Border { | 151 class ShadowBorder : public views::Border { |
149 public: | 152 public: |
150 ShadowBorder() : views::Border() {} | 153 ShadowBorder() : views::Border() {} |
151 virtual ~ShadowBorder() {} | 154 virtual ~ShadowBorder() {} |
152 | 155 |
153 protected: | 156 protected: |
154 // views::Border overrides: | 157 // Overridden from views::Border: |
155 virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE; | 158 virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE; |
156 virtual gfx::Insets GetInsets() const OVERRIDE; | 159 virtual gfx::Insets GetInsets() const OVERRIDE; |
157 | 160 |
158 DISALLOW_COPY_AND_ASSIGN(ShadowBorder); | 161 DISALLOW_COPY_AND_ASSIGN(ShadowBorder); |
159 }; | 162 }; |
160 | 163 |
161 void ShadowBorder::Paint(const views::View& view, gfx::Canvas* canvas) { | 164 void ShadowBorder::Paint(const views::View& view, gfx::Canvas* canvas) { |
162 SkPaint paint; | 165 SkPaint paint; |
163 std::vector<gfx::ShadowValue> shadows; | 166 std::vector<gfx::ShadowValue> shadows; |
164 shadows.push_back(gfx::ShadowValue(gfx::Point(), kShadowBlur, kShadowColor)); | 167 shadows.push_back(gfx::ShadowValue(gfx::Point(), kShadowBlur, kShadowColor)); |
165 skia::RefPtr<SkDrawLooper> looper = gfx::CreateShadowDrawLooper(shadows); | 168 skia::RefPtr<SkDrawLooper> looper = gfx::CreateShadowDrawLooper(shadows); |
166 paint.setLooper(looper.get()); | 169 paint.setLooper(looper.get()); |
167 paint.setColor(kTransparentColor); | 170 paint.setColor(kTransparentColor); |
168 paint.setStrokeJoin(SkPaint::kRound_Join); | 171 paint.setStrokeJoin(SkPaint::kRound_Join); |
169 gfx::Rect bounds(view.size()); | 172 gfx::Rect bounds(view.size()); |
170 bounds.Inset(gfx::Insets(kShadowBlur / 2, kShadowBlur / 2, | 173 bounds.Inset(gfx::Insets(kShadowBlur / 2, kShadowBlur / 2, |
171 kShadowBlur / 2, kShadowBlur / 2)); | 174 kShadowBlur / 2, kShadowBlur / 2)); |
172 canvas->DrawRect(bounds, paint); | 175 canvas->DrawRect(bounds, paint); |
173 } | 176 } |
174 | 177 |
175 gfx::Insets ShadowBorder::GetInsets() const { | 178 gfx::Insets ShadowBorder::GetInsets() const { |
176 return message_center::MessageView::GetShadowInsets(); | 179 return message_center::MessageView::GetShadowInsets(); |
177 } | 180 } |
178 | 181 |
179 // A dropdown menu for notifications. | 182 // A dropdown menu for notifications. |
180 class MenuModel : public ui::SimpleMenuModel, | 183 class MenuModel : public ui::SimpleMenuModel, |
181 public ui::SimpleMenuModel::Delegate { | 184 public ui::SimpleMenuModel::Delegate { |
182 public: | 185 public: |
183 MenuModel(message_center::NotificationList::Delegate* list_delegate, | 186 MenuModel(message_center::NotificationList::Delegate* delegate, |
184 const std::string& notification_id, | 187 const std::string& notification_id, |
185 const string16& display_source, | 188 const string16& display_source, |
186 const std::string& extension_id); | 189 const std::string& extension_id); |
187 virtual ~MenuModel(); | 190 virtual ~MenuModel(); |
188 | 191 |
189 // Overridden from ui::SimpleMenuModel::Delegate: | 192 // Overridden from ui::SimpleMenuModel::Delegate: |
190 virtual bool IsItemForCommandIdDynamic(int command_id) const OVERRIDE; | 193 virtual bool IsItemForCommandIdDynamic(int command_id) const OVERRIDE; |
191 virtual bool IsCommandIdChecked(int command_id) const OVERRIDE; | 194 virtual bool IsCommandIdChecked(int command_id) const OVERRIDE; |
192 virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE; | 195 virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE; |
193 virtual bool GetAcceleratorForCommandId( | 196 virtual bool GetAcceleratorForCommandId( |
194 int command_id, | 197 int command_id, |
195 ui::Accelerator* accelerator) OVERRIDE; | 198 ui::Accelerator* accelerator) OVERRIDE; |
196 virtual void ExecuteCommand(int command_id) OVERRIDE; | 199 virtual void ExecuteCommand(int command_id) OVERRIDE; |
197 | 200 |
198 private: | 201 private: |
199 message_center::NotificationList::Delegate* list_delegate_; | 202 message_center::NotificationList::Delegate* delegate_; // Weak reference. |
200 // Weak, global MessageCenter | |
201 std::string notification_id_; | 203 std::string notification_id_; |
202 | 204 |
203 DISALLOW_COPY_AND_ASSIGN(MenuModel); | 205 DISALLOW_COPY_AND_ASSIGN(MenuModel); |
204 }; | 206 }; |
205 | 207 |
206 MenuModel::MenuModel(message_center::NotificationList::Delegate* list_delegate, | 208 MenuModel::MenuModel(message_center::NotificationList::Delegate* delegate, |
207 const std::string& notification_id, | 209 const std::string& notification_id, |
208 const string16& display_source, | 210 const string16& display_source, |
209 const std::string& extension_id) | 211 const std::string& extension_id) |
210 : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)), | 212 : ALLOW_THIS_IN_INITIALIZER_LIST(ui::SimpleMenuModel(this)), |
211 list_delegate_(list_delegate), | 213 delegate_(delegate), |
212 notification_id_(notification_id) { | 214 notification_id_(notification_id) { |
213 // Add 'disable notifications' menu item. | 215 // Add 'disable notifications' menu item. |
214 if (!extension_id.empty()) { | 216 if (!extension_id.empty()) { |
215 AddItem(kToggleExtensionCommand, | 217 AddItem(kToggleExtensionCommand, |
216 l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_EXTENSIONS_DISABLE)); | 218 l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_EXTENSIONS_DISABLE)); |
217 } else if (!display_source.empty()) { | 219 } else if (!display_source.empty()) { |
218 AddItem(kTogglePermissionCommand, | 220 AddItem(kTogglePermissionCommand, |
219 l10n_util::GetStringFUTF16(IDS_MESSAGE_CENTER_SITE_DISABLE, | 221 l10n_util::GetStringFUTF16(IDS_MESSAGE_CENTER_SITE_DISABLE, |
220 display_source)); | 222 display_source)); |
221 } | 223 } |
(...skipping 20 matching lines...) Expand all Loading... |
242 } | 244 } |
243 | 245 |
244 bool MenuModel::GetAcceleratorForCommandId(int command_id, | 246 bool MenuModel::GetAcceleratorForCommandId(int command_id, |
245 ui::Accelerator* accelerator) { | 247 ui::Accelerator* accelerator) { |
246 return false; | 248 return false; |
247 } | 249 } |
248 | 250 |
249 void MenuModel::ExecuteCommand(int command_id) { | 251 void MenuModel::ExecuteCommand(int command_id) { |
250 switch (command_id) { | 252 switch (command_id) { |
251 case kToggleExtensionCommand: | 253 case kToggleExtensionCommand: |
252 list_delegate_->DisableNotificationByExtension(notification_id_); | 254 delegate_->DisableNotificationByExtension(notification_id_); |
253 break; | 255 break; |
254 case kTogglePermissionCommand: | 256 case kTogglePermissionCommand: |
255 list_delegate_->DisableNotificationByUrl(notification_id_); | 257 delegate_->DisableNotificationByUrl(notification_id_); |
256 break; | 258 break; |
257 case kShowSettingsCommand: | 259 case kShowSettingsCommand: |
258 list_delegate_->ShowNotificationSettings(notification_id_); | 260 delegate_->ShowNotificationSettings(notification_id_); |
259 break; | 261 break; |
260 default: | 262 default: |
261 NOTREACHED(); | 263 NOTREACHED(); |
262 } | 264 } |
263 } | 265 } |
264 | 266 |
265 } // namespace | 267 } // namespace |
266 | 268 |
267 namespace message_center { | 269 namespace message_center { |
268 | 270 |
269 MessageView::MessageView(NotificationList::Delegate* list_delegate, | 271 MessageView::MessageView(const Notification& notification, |
270 const Notification& notification) | 272 NotificationList::Delegate* delegate, |
271 : list_delegate_(list_delegate), | 273 bool expanded) |
| 274 : delegate_(delegate), |
272 notification_id_(notification.id()), | 275 notification_id_(notification.id()), |
273 display_source_(notification.display_source()), | 276 display_source_(notification.display_source()), |
274 extension_id_(notification.extension_id()), | 277 extension_id_(notification.extension_id()), |
275 scroller_(NULL) { | 278 scroller_(NULL), |
| 279 is_expanded_(expanded) { |
276 ControlButton *close = new ControlButton(this); | 280 ControlButton *close = new ControlButton(this); |
277 close->SetPadding(-kCloseIconRightPadding, kCloseIconTopPadding); | 281 close->SetPadding(-kCloseIconRightPadding, kCloseIconTopPadding); |
278 close->SetNormalImage(IDR_NOTIFICATION_CLOSE); | 282 close->SetNormalImage(IDR_NOTIFICATION_CLOSE); |
279 close->SetHoveredImage(IDR_NOTIFICATION_CLOSE_HOVER); | 283 close->SetHoveredImage(IDR_NOTIFICATION_CLOSE_HOVER); |
280 close->SetPressedImage(IDR_NOTIFICATION_CLOSE_PRESSED); | 284 close->SetPressedImage(IDR_NOTIFICATION_CLOSE_PRESSED); |
| 285 close->set_owned_by_client(); |
281 close_button_.reset(close); | 286 close_button_.reset(close); |
| 287 |
| 288 ControlButton *expand = new ControlButton(this); |
| 289 expand->SetPadding(-kExpandIconRightPadding, -kExpandIconBottomPadding); |
| 290 expand->SetNormalImage(IDR_NOTIFICATIONS_EXPAND); |
| 291 expand->SetHoveredImage(IDR_NOTIFICATIONS_EXPAND_HOVER); |
| 292 expand->SetPressedImage(IDR_NOTIFICATIONS_EXPAND_PRESSED); |
| 293 expand->set_owned_by_client(); |
| 294 expand_button_.reset(expand); |
| 295 |
282 if (IsRichNotificationEnabled()) | 296 if (IsRichNotificationEnabled()) |
283 set_border(new ShadowBorder()); | 297 set_border(new ShadowBorder()); |
284 } | 298 } |
285 | 299 |
286 MessageView::MessageView() { | 300 MessageView::MessageView() { |
287 } | 301 } |
288 | 302 |
289 MessageView::~MessageView() { | 303 MessageView::~MessageView() { |
290 } | 304 } |
291 | 305 |
292 // static | 306 // static |
293 gfx::Insets MessageView::GetShadowInsets() { | 307 gfx::Insets MessageView::GetShadowInsets() { |
294 return gfx::Insets(kShadowBlur / 2 - kShadowOffset, | 308 return gfx::Insets(kShadowBlur / 2 - kShadowOffset, |
295 kShadowBlur / 2, | 309 kShadowBlur / 2, |
296 kShadowBlur / 2 + kShadowOffset, | 310 kShadowBlur / 2 + kShadowOffset, |
297 kShadowBlur / 2); | 311 kShadowBlur / 2); |
298 } | 312 } |
299 | 313 |
| 314 void MessageView::Update(const Notification& notification) { |
| 315 notification_id_ = notification.id(); |
| 316 display_source_ = notification.display_source(); |
| 317 extension_id_ = notification.extension_id(); |
| 318 } |
| 319 |
300 bool MessageView::OnMousePressed(const ui::MouseEvent& event) { | 320 bool MessageView::OnMousePressed(const ui::MouseEvent& event) { |
301 if (event.flags() & ui::EF_RIGHT_MOUSE_BUTTON) { | 321 if (event.flags() & ui::EF_RIGHT_MOUSE_BUTTON) { |
302 ShowMenu(event.location()); | 322 ShowMenu(event.location()); |
303 return true; | 323 return true; |
304 } | 324 } |
305 list_delegate_->OnNotificationClicked(notification_id_); | 325 delegate_->OnNotificationClicked(notification_id_); |
306 return true; | 326 return true; |
307 } | 327 } |
308 | 328 |
309 void MessageView::OnGestureEvent(ui::GestureEvent* event) { | 329 void MessageView::OnGestureEvent(ui::GestureEvent* event) { |
310 if (event->type() == ui::ET_GESTURE_TAP) { | 330 if (event->type() == ui::ET_GESTURE_TAP) { |
311 list_delegate_->OnNotificationClicked(notification_id_); | 331 delegate_->OnNotificationClicked(notification_id_); |
312 event->SetHandled(); | 332 event->SetHandled(); |
313 return; | 333 return; |
314 } | 334 } |
315 | 335 |
316 if (event->type() == ui::ET_GESTURE_LONG_PRESS) { | 336 if (event->type() == ui::ET_GESTURE_LONG_PRESS) { |
317 ShowMenu(event->location()); | 337 ShowMenu(event->location()); |
318 event->SetHandled(); | 338 event->SetHandled(); |
319 return; | 339 return; |
320 } | 340 } |
321 | 341 |
322 SlideOutView::OnGestureEvent(event); | 342 SlideOutView::OnGestureEvent(event); |
323 // Do not return here by checking handled(). SlideOutView calls SetHandled() | 343 // Do not return here by checking handled(). SlideOutView calls SetHandled() |
324 // even though the scroll gesture doesn't make no (or little) effects on the | 344 // even though the scroll gesture doesn't make no (or little) effects on the |
325 // slide-out behavior. See http://crbug.com/172991 | 345 // slide-out behavior. See http://crbug.com/172991 |
326 | 346 |
327 if (!event->IsScrollGestureEvent()) | 347 if (!event->IsScrollGestureEvent()) |
328 return; | 348 return; |
329 | 349 |
330 if (scroller_) | 350 if (scroller_) |
331 scroller_->OnGestureEvent(event); | 351 scroller_->OnGestureEvent(event); |
332 event->SetHandled(); | 352 event->SetHandled(); |
333 } | 353 } |
334 | 354 |
335 void MessageView::ButtonPressed(views::Button* sender, | 355 void MessageView::ButtonPressed(views::Button* sender, |
336 const ui::Event& event) { | 356 const ui::Event& event) { |
337 if (sender == close_button()) | 357 if (sender == close_button()) { |
338 list_delegate_->SendRemoveNotification(notification_id_, true); // By user. | 358 delegate_->SendRemoveNotification(notification_id_, true); // By user. |
| 359 } else if (sender == expand_button()) { |
| 360 is_expanded_ = true; |
| 361 delegate_->OnExpand(notification_id_); |
| 362 } |
339 } | 363 } |
340 | 364 |
341 void MessageView::ShowMenu(gfx::Point screen_location) { | 365 void MessageView::ShowMenu(gfx::Point screen_location) { |
342 MenuModel menu_model(list_delegate_, notification_id_, | 366 MenuModel menu_model(delegate_, notification_id_, |
343 display_source_, extension_id_); | 367 display_source_, extension_id_); |
344 if (menu_model.GetItemCount() == 0) | 368 if (menu_model.GetItemCount() == 0) |
345 return; | 369 return; |
346 | 370 |
347 views::MenuModelAdapter menu_model_adapter(&menu_model); | 371 views::MenuModelAdapter menu_model_adapter(&menu_model); |
348 views::MenuRunner menu_runner(menu_model_adapter.CreateMenu()); | 372 views::MenuRunner menu_runner(menu_model_adapter.CreateMenu()); |
349 | 373 |
350 views::View::ConvertPointToScreen(this, &screen_location); | 374 views::View::ConvertPointToScreen(this, &screen_location); |
351 ignore_result(menu_runner.RunMenuAt( | 375 ignore_result(menu_runner.RunMenuAt( |
352 GetWidget()->GetTopLevelWidget(), | 376 GetWidget()->GetTopLevelWidget(), |
353 NULL, | 377 NULL, |
354 gfx::Rect(screen_location, gfx::Size()), | 378 gfx::Rect(screen_location, gfx::Size()), |
355 views::MenuItemView::TOPRIGHT, | 379 views::MenuItemView::TOPRIGHT, |
356 views::MenuRunner::HAS_MNEMONICS)); | 380 views::MenuRunner::HAS_MNEMONICS)); |
357 } | 381 } |
358 | 382 |
359 void MessageView::OnSlideOut() { | 383 void MessageView::OnSlideOut() { |
360 list_delegate_->SendRemoveNotification(notification_id_, true); // By user. | 384 delegate_->SendRemoveNotification(notification_id_, true); // By user. |
361 } | 385 } |
362 | 386 |
363 } // namespace message_center | 387 } // namespace message_center |
OLD | NEW |