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

Side by Side Diff: ui/message_center/message_center_bubble.cc

Issue 12326091: Made notification center notifications collapsed and expandable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 10 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 | Annotate | Revision Log
OLDNEW
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_center_bubble.h" 5 #include "ui/message_center/message_center_bubble.h"
6 6
7 #include "grit/ui_strings.h" 7 #include "grit/ui_strings.h"
8 #include "third_party/skia/include/core/SkPaint.h" 8 #include "third_party/skia/include/core/SkPaint.h"
9 #include "ui/base/l10n/l10n_util.h" 9 #include "ui/base/l10n/l10n_util.h"
10 #include "ui/base/resource/resource_bundle.h" 10 #include "ui/base/resource/resource_bundle.h"
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 else 229 else
230 NOTREACHED(); 230 NOTREACHED();
231 } 231 }
232 232
233 views::Label* notification_label_; 233 views::Label* notification_label_;
234 views::Button* settings_button_; 234 views::Button* settings_button_;
235 235
236 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView2); 236 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView2);
237 }; 237 };
238 238
239 // A custom scroll-view that has a specified size. 239 // A custom scroll view whose height has a minimum and maximum value and whose
240 class FixedSizedScrollView : public views::ScrollView { 240 // scroll bar disappears when not needed.
241 class BoundedScrollView : public views::ScrollView {
241 public: 242 public:
242 FixedSizedScrollView() { 243 BoundedScrollView(int min_height, int max_height)
244 : min_height_(min_height),
245 max_height_(max_height) {
243 set_focusable(true); 246 set_focusable(true);
244 set_notify_enter_exit_on_child(true); 247 set_notify_enter_exit_on_child(true);
245 if (IsRichNotificationEnabled()) { 248 if (IsRichNotificationEnabled()) {
246 set_background(views::Background::CreateSolidBackground( 249 set_background(views::Background::CreateSolidBackground(
247 kMessageCenterBackgroundColor)); 250 kMessageCenterBackgroundColor));
248 } 251 }
249 } 252 }
250 253
251 virtual ~FixedSizedScrollView() {} 254 virtual ~BoundedScrollView() {}
252
253 void SetFixedSize(const gfx::Size& size) {
254 if (fixed_size_ == size)
255 return;
256 fixed_size_ = size;
257 PreferredSizeChanged();
258 }
259 255
260 // views::View overrides. 256 // views::View overrides.
261 virtual gfx::Size GetPreferredSize() OVERRIDE { 257 virtual gfx::Size GetPreferredSize() OVERRIDE {
262 gfx::Size size = fixed_size_.IsEmpty() ? 258 gfx::Size size = contents()->GetPreferredSize();
263 contents()->GetPreferredSize() : fixed_size_; 259 size.ClampToMin(gfx::Size(size.width(), min_height_));
260 size.ClampToMax(gfx::Size(size.width(), max_height_));
264 gfx::Insets insets = GetInsets(); 261 gfx::Insets insets = GetInsets();
265 size.Enlarge(insets.width(), insets.height()); 262 size.Enlarge(insets.width(), insets.height());
266 return size; 263 return size;
267 } 264 }
268 265
269 virtual void Layout() OVERRIDE { 266 virtual void Layout() OVERRIDE {
270 gfx::Rect bounds = gfx::Rect(contents()->GetPreferredSize()); 267 // Lay out the view as if it will have a scroll bar.
271 bounds.set_width(std::max(0, width() - GetScrollBarWidth())); 268 gfx::Rect content_bounds = gfx::Rect(contents()->GetPreferredSize());
272 contents()->SetBoundsRect(bounds); 269 content_bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
270 contents()->SetBoundsRect(content_bounds);
271 views::ScrollView::Layout();
273 272
274 views::ScrollView::Layout(); 273 // But use the scroll bar space if no scroll bar is needed.
275 if (!vertical_scroll_bar()->visible()) { 274 if (!vertical_scroll_bar()->visible()) {
276 gfx::Rect bounds = contents()->bounds(); 275 content_bounds = contents()->bounds();
277 bounds.set_width(bounds.width() + GetScrollBarWidth()); 276 content_bounds.set_width(content_bounds.width() + GetScrollBarWidth());
278 contents()->SetBoundsRect(bounds); 277 contents()->SetBoundsRect(content_bounds);
279 } 278 }
280 } 279 }
281 280
282 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE { 281 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE {
283 gfx::Rect bounds = gfx::Rect(contents()->GetPreferredSize()); 282 // Make sure any content resizing takes into account the scroll bar.
284 bounds.set_width(std::max(0, width() - GetScrollBarWidth())); 283 gfx::Rect content_bounds = gfx::Rect(contents()->GetPreferredSize());
285 contents()->SetBoundsRect(bounds); 284 content_bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
285 contents()->SetBoundsRect(content_bounds);
286 } 286 }
287 287
288 private: 288 private:
289 gfx::Size fixed_size_; 289 int min_height_;
290 int max_height_;
290 291
291 DISALLOW_COPY_AND_ASSIGN(FixedSizedScrollView); 292 DISALLOW_COPY_AND_ASSIGN(BoundedScrollView);
292 }; 293 };
293 294
294 // Container for the messages. 295 // Container for the messages.
295 class ScrollContentView : public views::View { 296 class MessagesView : public views::View {
Jun Mukai 2013/02/26 02:23:30 I think it's too hard to distinguish this from mes
dharcourt 2013/02/26 03:23:30 Good point. What would you think of MessageListVie
296 public: 297 public:
297 ScrollContentView() { 298 MessagesView(views::View *message_center_view)
299 : message_center_view_(message_center_view) {
298 if (IsRichNotificationEnabled()) { 300 if (IsRichNotificationEnabled()) {
299 // Set the margin to 0 for the layout. BoxLayout assumes the same margin 301 // Set the margin to 0 for the layout. BoxLayout assumes the same margin
300 // for top and bottom, but the bottom margin here should be smaller 302 // for top and bottom, but the bottom margin here should be smaller
301 // because of the shadow of message view. Use an empty border instead 303 // because of the shadow of message view. Use an empty border instead
302 // to provide this margin. 304 // to provide this margin.
303 gfx::Insets shadow_insets = GetItemShadowInsets(); 305 gfx::Insets shadow_insets = GetItemShadowInsets();
304 SetLayoutManager( 306 SetLayoutManager(
305 new views::BoxLayout(views::BoxLayout::kVertical, 307 new views::BoxLayout(views::BoxLayout::kVertical,
306 0, 308 0,
307 0, 309 0,
308 kMarginBetweenItems - shadow_insets.bottom())); 310 kMarginBetweenItems - shadow_insets.bottom()));
309 set_background(views::Background::CreateSolidBackground( 311 set_background(views::Background::CreateSolidBackground(
310 kMessageCenterBackgroundColor)); 312 kMessageCenterBackgroundColor));
311 set_border(views::Border::CreateEmptyBorder( 313 set_border(views::Border::CreateEmptyBorder(
312 kMarginBetweenItems - shadow_insets.top(), /* top */ 314 kMarginBetweenItems - shadow_insets.top(), /* top */
313 kMarginBetweenItems - shadow_insets.left(), /* left */ 315 kMarginBetweenItems - shadow_insets.left(), /* left */
314 0, /* bottom */ 316 0, /* bottom */
315 kMarginBetweenItems - shadow_insets.right() /* right */ )); 317 kMarginBetweenItems - shadow_insets.right() /* right */ ));
316 } else { 318 } else {
317 views::BoxLayout* layout = 319 views::BoxLayout* layout =
318 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1); 320 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1);
319 layout->set_spread_blank_space(true); 321 layout->set_spread_blank_space(true);
320 SetLayoutManager(layout); 322 SetLayoutManager(layout);
321 } 323 }
322 } 324 }
323 325
324 virtual ~ScrollContentView() { 326 virtual ~MessagesView() {
325 } 327 }
326 328
327 virtual gfx::Size GetPreferredSize() OVERRIDE { 329 protected:
328 if (!preferred_size_.IsEmpty()) 330 // views::View overrides.
329 return preferred_size_; 331 virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE {
330 return views::View::GetPreferredSize(); 332 // Since the parent of this view is a Viewport and since Viewports ignore
333 // ChildPreferredSizeChanged() calls, ask the MessageCenterView directly
334 // to update its layout for the preferred size change.
335 message_center_view_->Layout();
331 } 336 }
332 337
333 void set_preferred_size(const gfx::Size& size) { preferred_size_ = size; } 338 private:
339 views::View *message_center_view_;
334 340
335 private: 341 DISALLOW_COPY_AND_ASSIGN(MessagesView);
336 gfx::Size preferred_size_;
337 DISALLOW_COPY_AND_ASSIGN(ScrollContentView);
338 }; 342 };
339 343
340 // A border to provide the shadow for each card. 344 // A border to provide the shadow for each card.
341 // Current shadow should look like css box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) 345 // Current shadow should look like css box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3)
342 class MessageViewShadowBorder : public views::Border { 346 class MessageViewShadowBorder : public views::Border {
343 public: 347 public:
344 MessageViewShadowBorder() : views::Border() {} 348 MessageViewShadowBorder() : views::Border() {}
345 virtual ~MessageViewShadowBorder() {} 349 virtual ~MessageViewShadowBorder() {}
346 350
347 protected: 351 protected:
(...skipping 13 matching lines...) Expand all
361 canvas->DrawRect(bounds, paint); 365 canvas->DrawRect(bounds, paint);
362 } 366 }
363 367
364 virtual gfx::Insets GetInsets() const OVERRIDE { 368 virtual gfx::Insets GetInsets() const OVERRIDE {
365 return GetItemShadowInsets(); 369 return GetItemShadowInsets();
366 } 370 }
367 }; 371 };
368 372
369 } // namespace 373 } // namespace
370 374
371 // Message Center contents. 375 // View that displays the whole message center.
372 class MessageCenterContentsView : public views::View { 376 class MessageCenterView : public views::View {
373 public: 377 public:
374 explicit MessageCenterContentsView(MessageCenterBubble* bubble, 378 explicit MessageCenterView(MessageCenterBubble* bubble,
375 NotificationList::Delegate* list_delegate) 379 NotificationList::Delegate* list_delegate)
376 : list_delegate_(list_delegate), 380 : list_delegate_(list_delegate),
377 bubble_(bubble) { 381 bubble_(bubble) {
378 int between_child = IsRichNotificationEnabled() ? 0 : 1; 382 int between_child = IsRichNotificationEnabled() ? 0 : 1;
379 SetLayoutManager( 383 SetLayoutManager(
380 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, between_child)); 384 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, between_child));
381 385
382 scroll_content_ = new ScrollContentView; 386
383 scroller_ = new FixedSizedScrollView; 387 if (IsRichNotificationEnabled())
384 scroller_->SetContents(scroll_content_); 388 button_view_ = new WebNotificationButtonView2(list_delegate);
385 AddChildView(scroller_); 389 else
390 button_view_ = new WebNotificationButtonView(list_delegate);
dharcourt 2013/02/23 04:32:00 Button creation had to be moved up in this method
391
392 const int button_height = button_view_->GetPreferredSize().height();
393 const int min_height = kMessageBubbleBaseMinHeight - button_height;
394 const int max_height = bubble_->max_height() - button_height;
395 scroller_ = new BoundedScrollView(min_height, max_height);
386 396
387 if (get_use_acceleration_when_possible()) { 397 if (get_use_acceleration_when_possible()) {
388 scroller_->SetPaintToLayer(true); 398 scroller_->SetPaintToLayer(true);
389 scroller_->SetFillsBoundsOpaquely(false); 399 scroller_->SetFillsBoundsOpaquely(false);
390 scroller_->layer()->SetMasksToBounds(true); 400 scroller_->layer()->SetMasksToBounds(true);
391 } 401 }
392 402
393 if (IsRichNotificationEnabled()) 403 messages_view_ = new MessagesView(this);
394 button_view_ = new WebNotificationButtonView2(list_delegate); 404 scroller_->SetContents(messages_view_);
395 else 405
396 button_view_ = new WebNotificationButtonView(list_delegate); 406 AddChildView(scroller_);
397 AddChildView(button_view_); 407 AddChildView(button_view_);
398 } 408 }
399 409
400 void FocusContents() { 410 void FocusContents() {
401 scroller_->RequestFocus(); 411 scroller_->RequestFocus();
402 } 412 }
403 413
404 void Update(const NotificationList::Notifications& notifications) { 414 void Update(const NotificationList::Notifications& notifications) {
405 scroll_content_->RemoveAllChildViews(true); 415 messages_view_->RemoveAllChildViews(true);
406 scroll_content_->set_preferred_size(gfx::Size());
407 size_t num_children = 0; 416 size_t num_children = 0;
408 for (NotificationList::Notifications::const_iterator iter = 417 for (NotificationList::Notifications::const_iterator iter =
409 notifications.begin(); iter != notifications.end(); ++iter) { 418 notifications.begin(); iter != notifications.end(); ++iter) {
410 MessageView* view = 419 MessageView* view =
411 NotificationView::ViewForNotification(*iter, list_delegate_); 420 NotificationView::ViewForNotification(*iter, list_delegate_);
412 view->set_scroller(scroller_); 421 view->set_scroller(scroller_);
dharcourt 2013/02/23 04:32:00 SetUpView() is now avoided as MessageView and all
413 view->SetUpView();
414 if (IsRichNotificationEnabled()) 422 if (IsRichNotificationEnabled())
415 view->set_border(new MessageViewShadowBorder()); 423 view->set_border(new MessageViewShadowBorder());
416 scroll_content_->AddChildView(view); 424 messages_view_->AddChildView(view);
417 if (++num_children >= 425 if (++num_children >=
418 NotificationList::kMaxVisibleMessageCenterNotifications) { 426 NotificationList::kMaxVisibleMessageCenterNotifications) {
419 break; 427 break;
420 } 428 }
421 } 429 }
422 if (num_children == 0) { 430 if (num_children == 0) {
423 views::Label* label = new views::Label(l10n_util::GetStringUTF16( 431 views::Label* label = new views::Label(l10n_util::GetStringUTF16(
424 IDS_MESSAGE_CENTER_NO_MESSAGES)); 432 IDS_MESSAGE_CENTER_NO_MESSAGES));
425 label->SetFont(label->font().DeriveFont(1)); 433 label->SetFont(label->font().DeriveFont(1));
426 label->SetEnabledColor(SK_ColorGRAY); 434 label->SetEnabledColor(SK_ColorGRAY);
427 // Set transparent background to ensure that subpixel rendering 435 // Set transparent background to ensure that subpixel rendering
428 // is disabled. See crbug.com/169056 436 // is disabled. See crbug.com/169056
429 label->SetBackgroundColor(kTransparentColor); 437 label->SetBackgroundColor(kTransparentColor);
430 scroll_content_->AddChildView(label); 438 messages_view_->AddChildView(label);
431 button_view_->SetCloseAllVisible(false); 439 button_view_->SetCloseAllVisible(false);
432 scroller_->set_focusable(false); 440 scroller_->set_focusable(false);
433 } else { 441 } else {
434 button_view_->SetCloseAllVisible(true); 442 button_view_->SetCloseAllVisible(true);
435 scroller_->set_focusable(true); 443 scroller_->set_focusable(true);
436 } 444 }
437 SizeScrollContent();
438 Layout(); 445 Layout();
439 if (GetWidget())
440 GetWidget()->GetRootView()->SchedulePaint();
441 } 446 }
442 447
443 size_t NumMessageViews() const { 448 size_t NumMessageViews() const {
444 return scroll_content_->child_count(); 449 return messages_view_->child_count();
450 }
451
452 protected:
453 // views::View overrides.
454 virtual void Layout() OVERRIDE {
455 scroller_->SizeToPreferredSize();
456 views::View::Layout();
457 if (GetWidget())
458 GetWidget()->GetRootView()->SchedulePaint();
459 bubble_->bubble_view()->UpdateBubble();
445 } 460 }
446 461
447 private: 462 private:
448 void SizeScrollContent() {
449 gfx::Size scroll_size = scroll_content_->GetPreferredSize();
450 const int button_height = button_view_->GetPreferredSize().height();
451 const int min_height = kMessageBubbleBaseMinHeight - button_height;
452 const int max_height = bubble_->max_height() - button_height;
453 int scroll_height = std::min(std::max(
454 scroll_size.height(), min_height), max_height);
455 scroll_size.set_height(scroll_height);
456 if (scroll_height == min_height)
457 scroll_content_->set_preferred_size(scroll_size);
458 else
459 scroll_content_->set_preferred_size(gfx::Size());
460 scroller_->SetFixedSize(scroll_size);
461 scroller_->SizeToPreferredSize();
462 scroll_content_->InvalidateLayout();
463 }
464
465 NotificationList::Delegate* list_delegate_; 463 NotificationList::Delegate* list_delegate_;
466 FixedSizedScrollView* scroller_; 464 BoundedScrollView* scroller_;
467 ScrollContentView* scroll_content_; 465 MessagesView* messages_view_;
468 WebNotificationButtonViewBase* button_view_; 466 WebNotificationButtonViewBase* button_view_;
469 MessageCenterBubble* bubble_; 467 MessageCenterBubble* bubble_;
470 468
471 DISALLOW_COPY_AND_ASSIGN(MessageCenterContentsView); 469 DISALLOW_COPY_AND_ASSIGN(MessageCenterView);
472 }; 470 };
473 471
474 // Message Center Bubble. 472 // Message Center Bubble.
475 MessageCenterBubble::MessageCenterBubble(NotificationList::Delegate* delegate) 473 MessageCenterBubble::MessageCenterBubble(NotificationList::Delegate* delegate)
476 : MessageBubbleBase(delegate), 474 : MessageBubbleBase(delegate),
477 contents_view_(NULL) { 475 contents_view_(NULL) {
478 } 476 }
479 477
480 MessageCenterBubble::~MessageCenterBubble() {} 478 MessageCenterBubble::~MessageCenterBubble() {}
481 479
482 views::TrayBubbleView::InitParams MessageCenterBubble::GetInitParams( 480 views::TrayBubbleView::InitParams MessageCenterBubble::GetInitParams(
483 views::TrayBubbleView::AnchorAlignment anchor_alignment) { 481 views::TrayBubbleView::AnchorAlignment anchor_alignment) {
484 views::TrayBubbleView::InitParams init_params = 482 views::TrayBubbleView::InitParams init_params =
485 GetDefaultInitParams(anchor_alignment); 483 GetDefaultInitParams(anchor_alignment);
486 if (IsRichNotificationEnabled()) { 484 if (IsRichNotificationEnabled()) {
487 init_params.min_width += kMarginBetweenItems * 2; 485 init_params.min_width += kMarginBetweenItems * 2;
488 init_params.max_width += kMarginBetweenItems * 2; 486 init_params.max_width += kMarginBetweenItems * 2;
489 } 487 }
490 init_params.max_height = max_height(); 488 init_params.max_height = max_height();
491 init_params.can_activate = true; 489 init_params.can_activate = true;
492 return init_params; 490 return init_params;
493 } 491 }
494 492
495 void MessageCenterBubble::InitializeContents( 493 void MessageCenterBubble::InitializeContents(
496 views::TrayBubbleView* new_bubble_view) { 494 views::TrayBubbleView* new_bubble_view) {
497 set_bubble_view(new_bubble_view); 495 set_bubble_view(new_bubble_view);
498 contents_view_ = new MessageCenterContentsView(this, list_delegate()); 496 contents_view_ = new MessageCenterView(this, list_delegate());
499 bubble_view()->AddChildView(contents_view_); 497 bubble_view()->AddChildView(contents_view_);
500 UpdateBubbleView(); 498 UpdateBubbleView();
501 contents_view_->FocusContents(); 499 contents_view_->FocusContents();
502 } 500 }
503 501
504 void MessageCenterBubble::OnBubbleViewDestroyed() { 502 void MessageCenterBubble::OnBubbleViewDestroyed() {
505 contents_view_ = NULL; 503 contents_view_ = NULL;
506 } 504 }
507 505
508 void MessageCenterBubble::UpdateBubbleView() { 506 void MessageCenterBubble::UpdateBubbleView() {
(...skipping 10 matching lines...) Expand all
519 } 517 }
520 518
521 void MessageCenterBubble::OnMouseExitedView() { 519 void MessageCenterBubble::OnMouseExitedView() {
522 } 520 }
523 521
524 size_t MessageCenterBubble::NumMessageViewsForTest() const { 522 size_t MessageCenterBubble::NumMessageViewsForTest() const {
525 return contents_view_->NumMessageViews(); 523 return contents_view_->NumMessageViews();
526 } 524 }
527 525
528 } // namespace message_center 526 } // namespace message_center
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698