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

Side by Side Diff: ui/message_center/views/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: Rebase, rebase, and rebase again! Created 7 years, 9 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/views/message_center_bubble.h" 5 #include "ui/message_center/views/message_center_bubble.h"
6 6
7 #include <map>
8
7 #include "grit/ui_strings.h" 9 #include "grit/ui_strings.h"
8 #include "third_party/skia/include/core/SkPaint.h" 10 #include "third_party/skia/include/core/SkPaint.h"
9 #include "ui/base/l10n/l10n_util.h" 11 #include "ui/base/l10n/l10n_util.h"
10 #include "ui/base/resource/resource_bundle.h" 12 #include "ui/base/resource/resource_bundle.h"
11 #include "ui/gfx/canvas.h" 13 #include "ui/gfx/canvas.h"
12 #include "ui/gfx/insets.h" 14 #include "ui/gfx/insets.h"
13 #include "ui/gfx/point.h" 15 #include "ui/gfx/point.h"
14 #include "ui/gfx/rect.h" 16 #include "ui/gfx/rect.h"
15 #include "ui/gfx/size.h" 17 #include "ui/gfx/size.h"
16 #include "ui/gfx/text_constants.h" 18 #include "ui/gfx/text_constants.h"
(...skipping 25 matching lines...) Expand all
42 const SkColor kFooterDelimiterColor = SkColorSetRGB(0xcc, 0xcc, 0xcc); 44 const SkColor kFooterDelimiterColor = SkColorSetRGB(0xcc, 0xcc, 0xcc);
43 const SkColor kFooterTextColor = SkColorSetRGB(0x80, 0x80, 0x80); 45 const SkColor kFooterTextColor = SkColorSetRGB(0x80, 0x80, 0x80);
44 const SkColor kButtonTextHighlightColor = SkColorSetRGB(0x32, 0x32, 0x32); 46 const SkColor kButtonTextHighlightColor = SkColorSetRGB(0x32, 0x32, 0x32);
45 const SkColor kButtonTextHoverColor = SkColorSetRGB(0x32, 0x32, 0x32); 47 const SkColor kButtonTextHoverColor = SkColorSetRGB(0x32, 0x32, 0x32);
46 // The focus color and focus-border logic is copied from ash tray. 48 // The focus color and focus-border logic is copied from ash tray.
47 // TODO(mukai): unite those implementations. 49 // TODO(mukai): unite those implementations.
48 const SkColor kFocusBorderColor = SkColorSetRGB(0x40, 0x80, 0xfa); 50 const SkColor kFocusBorderColor = SkColorSetRGB(0x40, 0x80, 0xfa);
49 51
50 class WebNotificationButtonViewBase : public views::View { 52 class WebNotificationButtonViewBase : public views::View {
51 public: 53 public:
52 WebNotificationButtonViewBase(NotificationList::Delegate* list_delegate) 54 WebNotificationButtonViewBase(NotificationChangeObserver* observer)
53 : list_delegate_(list_delegate), 55 : observer_(observer),
54 close_all_button_(NULL) {} 56 close_all_button_(NULL) {}
55 57
56 void SetCloseAllVisible(bool visible) { 58 void SetCloseAllVisible(bool visible) {
57 if (close_all_button_) 59 if (close_all_button_)
58 close_all_button_->SetVisible(visible); 60 close_all_button_->SetVisible(visible);
59 } 61 }
60 62
61 void set_close_all_button(views::Button* button) { 63 void set_close_all_button(views::Button* button) {
62 close_all_button_ = button; 64 close_all_button_ = button;
63 } 65 }
64 66
65 protected: 67 protected:
66 NotificationList::Delegate* list_delegate() { return list_delegate_; } 68 NotificationChangeObserver* observer() { return observer_; }
67 views::Button* close_all_button() { return close_all_button_; } 69 views::Button* close_all_button() { return close_all_button_; }
68 70
69 private: 71 private:
70 NotificationList::Delegate* list_delegate_; 72 NotificationChangeObserver* observer_; // Weak reference.
71 views::Button* close_all_button_; 73 views::Button* close_all_button_;
72 74
73 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonViewBase); 75 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonViewBase);
74 }; 76 };
75 77
76 // The view for the buttons at the bottom of the web notification tray. 78 // The view for the buttons at the bottom of the web notification tray.
77 class WebNotificationButtonView : public WebNotificationButtonViewBase, 79 class WebNotificationButtonView : public WebNotificationButtonViewBase,
78 public views::ButtonListener { 80 public views::ButtonListener {
79 public: 81 public:
80 explicit WebNotificationButtonView(NotificationList::Delegate* list_delegate) 82 explicit WebNotificationButtonView(NotificationChangeObserver* observer)
81 : WebNotificationButtonViewBase(list_delegate) { 83 : WebNotificationButtonViewBase(observer) {
82 set_background(views::Background::CreateBackgroundPainter( 84 set_background(views::Background::CreateBackgroundPainter(
83 true, 85 true,
84 views::Painter::CreateVerticalGradient( 86 views::Painter::CreateVerticalGradient(
85 MessageBubbleBase::kHeaderBackgroundColorLight, 87 MessageBubbleBase::kHeaderBackgroundColorLight,
86 MessageBubbleBase::kHeaderBackgroundColorDark))); 88 MessageBubbleBase::kHeaderBackgroundColorDark)));
87 set_border(views::Border::CreateSolidSidedBorder( 89 set_border(views::Border::CreateSolidSidedBorder(
88 2, 0, 0, 0, kBorderDarkColor)); 90 2, 0, 0, 0, kBorderDarkColor));
89 91
90 views::GridLayout* layout = new views::GridLayout(this); 92 views::GridLayout* layout = new views::GridLayout(this);
91 SetLayoutManager(layout); 93 SetLayoutManager(layout);
(...skipping 12 matching lines...) Expand all
104 close_all_button->set_request_focus_on_press(false); 106 close_all_button->set_request_focus_on_press(false);
105 107
106 layout->AddPaddingRow(0, 4); 108 layout->AddPaddingRow(0, 4);
107 layout->StartRow(0, 0); 109 layout->StartRow(0, 0);
108 layout->AddView(close_all_button); 110 layout->AddView(close_all_button);
109 set_close_all_button(close_all_button); 111 set_close_all_button(close_all_button);
110 } 112 }
111 113
112 virtual ~WebNotificationButtonView() {} 114 virtual ~WebNotificationButtonView() {}
113 115
114 // Overridden from ButtonListener. 116 // Overridden from views::ButtonListener:
115 virtual void ButtonPressed(views::Button* sender, 117 virtual void ButtonPressed(views::Button* sender,
116 const ui::Event& event) OVERRIDE { 118 const ui::Event& event) OVERRIDE {
117 if (sender == close_all_button()) 119 if (sender == close_all_button())
118 list_delegate()->SendRemoveAllNotifications(true); // Action by user. 120 observer()->OnRemoveAllNotifications(true); // Action by user.
119 } 121 }
120 122
121 private: 123 private:
122 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView); 124 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView);
123 }; 125 };
124 126
125 class WebNotificationButton : public views::TextButton { 127 class WebNotificationButton : public views::TextButton {
126 public: 128 public:
127 WebNotificationButton(views::ButtonListener* listener, const string16& text) 129 WebNotificationButton(views::ButtonListener* listener, const string16& text)
128 : views::TextButton(listener, text) { 130 : views::TextButton(listener, text) {
129 set_border(views::Border::CreateEmptyBorder(0, 16, 0, 16)); 131 set_border(views::Border::CreateEmptyBorder(0, 16, 0, 16));
130 set_min_height(kFooterHeight); 132 set_min_height(kFooterHeight);
131 SetEnabledColor(kFooterTextColor); 133 SetEnabledColor(kFooterTextColor);
132 SetHighlightColor(kButtonTextHighlightColor); 134 SetHighlightColor(kButtonTextHighlightColor);
133 SetHoverColor(kButtonTextHoverColor); 135 SetHoverColor(kButtonTextHoverColor);
134 } 136 }
135 137
136 protected: 138 protected:
137 // views::View overrides: 139 // Overridden from views::View:
138 virtual gfx::Size GetPreferredSize() OVERRIDE { 140 virtual gfx::Size GetPreferredSize() OVERRIDE {
139 // Returns an empty size when invisible, to trim its space in the parent's 141 // Returns an empty size when invisible, to trim its space in the parent's
140 // GridLayout. 142 // GridLayout.
141 if (!visible()) 143 if (!visible())
142 return gfx::Size(); 144 return gfx::Size();
143 return views::TextButton::GetPreferredSize(); 145 return views::TextButton::GetPreferredSize();
144 } 146 }
145 147
146 virtual void OnPaintBorder(gfx::Canvas* canvas) OVERRIDE { 148 virtual void OnPaintBorder(gfx::Canvas* canvas) OVERRIDE {
147 // Just paint the left border. 149 // Just paint the left border.
148 canvas->DrawLine(gfx::Point(0, 0), gfx::Point(0, height()), 150 canvas->DrawLine(gfx::Point(0, 0), gfx::Point(0, height()),
149 kFooterDelimiterColor); 151 kFooterDelimiterColor);
150 } 152 }
151 153
152 virtual void OnPaintFocusBorder(gfx::Canvas* canvas) OVERRIDE { 154 virtual void OnPaintFocusBorder(gfx::Canvas* canvas) OVERRIDE {
153 if (HasFocus() && (focusable() || IsAccessibilityFocusable())) { 155 if (HasFocus() && (focusable() || IsAccessibilityFocusable())) {
154 canvas->DrawRect(gfx::Rect(2, 1, width() - 4, height() - 3), 156 canvas->DrawRect(gfx::Rect(2, 1, width() - 4, height() - 3),
155 kFocusBorderColor); 157 kFocusBorderColor);
156 } 158 }
157 } 159 }
158 160
159 DISALLOW_COPY_AND_ASSIGN(WebNotificationButton); 161 DISALLOW_COPY_AND_ASSIGN(WebNotificationButton);
160 }; 162 };
161 163
162 // TODO(mukai): remove the trailing '2' when the kEnableNewMessageCenterBubble 164 // TODO(mukai): remove the trailing '2' when the kEnableNewMessageCenterBubble
163 // flag disappears. 165 // flag disappears.
164 class WebNotificationButtonView2 : public WebNotificationButtonViewBase, 166 class WebNotificationButtonView2 : public WebNotificationButtonViewBase,
165 public views::ButtonListener { 167 public views::ButtonListener {
166 public: 168 public:
167 explicit WebNotificationButtonView2(NotificationList::Delegate* list_delegate) 169 explicit WebNotificationButtonView2(NotificationChangeObserver* observer)
168 : WebNotificationButtonViewBase(list_delegate) { 170 : WebNotificationButtonViewBase(observer) {
169 set_background(views::Background::CreateSolidBackground( 171 set_background(views::Background::CreateSolidBackground(
170 kMessageCenterBackgroundColor)); 172 kMessageCenterBackgroundColor));
171 set_border(views::Border::CreateSolidSidedBorder( 173 set_border(views::Border::CreateSolidSidedBorder(
172 1, 0, 0, 0, kFooterDelimiterColor)); 174 1, 0, 0, 0, kFooterDelimiterColor));
173 175
174 176
175 notification_label_ = new views::Label(l10n_util::GetStringUTF16( 177 notification_label_ = new views::Label(l10n_util::GetStringUTF16(
176 IDS_MESSAGE_CENTER_FOOTER_TITLE)); 178 IDS_MESSAGE_CENTER_FOOTER_TITLE));
177 notification_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 179 notification_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
178 notification_label_->SetElideBehavior(views::Label::ELIDE_AT_END); 180 notification_label_->SetElideBehavior(views::Label::ELIDE_AT_END);
(...skipping 20 matching lines...) Expand all
199 column->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 201 column->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL,
200 0, views::GridLayout::USE_PREF, 0, 0); 202 0, views::GridLayout::USE_PREF, 0, 0);
201 layout->StartRow(0, 0); 203 layout->StartRow(0, 0);
202 layout->AddView(notification_label_); 204 layout->AddView(notification_label_);
203 layout->AddView(settings_button_); 205 layout->AddView(settings_button_);
204 layout->AddView(close_all_button); 206 layout->AddView(close_all_button);
205 set_close_all_button(close_all_button); 207 set_close_all_button(close_all_button);
206 } 208 }
207 209
208 private: 210 private:
209 // views::ButtonListener overrides: 211 // Overridden from views::ButtonListener:
210 virtual void ButtonPressed(views::Button* sender, 212 virtual void ButtonPressed(views::Button* sender,
211 const ui::Event& event) OVERRIDE { 213 const ui::Event& event) OVERRIDE {
212 if (sender == close_all_button()) 214 if (sender == close_all_button())
213 list_delegate()->SendRemoveAllNotifications(true); // Action by user. 215 observer()->OnRemoveAllNotifications(true); // Action by user.
214 else if (sender == settings_button_) 216 else if (sender == settings_button_)
215 list_delegate()->ShowNotificationSettingsDialog( 217 observer()->OnShowNotificationSettingsDialog(
216 GetWidget()->GetNativeView()); 218 GetWidget()->GetNativeView());
217 else 219 else
218 NOTREACHED(); 220 NOTREACHED();
219 } 221 }
220 222
221 views::Label* notification_label_; 223 views::Label* notification_label_;
222 views::Button* settings_button_; 224 views::Button* settings_button_;
223 225
224 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView2); 226 DISALLOW_COPY_AND_ASSIGN(WebNotificationButtonView2);
225 }; 227 };
226 228
227 // A custom scroll-view that has a specified size. 229 // A custom scroll view whose height has a minimum and maximum value and whose
228 class FixedSizedScrollView : public views::ScrollView { 230 // scroll bar disappears when not needed.
231 class BoundedScrollView : public views::ScrollView {
229 public: 232 public:
230 FixedSizedScrollView() { 233 BoundedScrollView(int min_height, int max_height)
234 : min_height_(min_height),
235 max_height_(max_height) {
231 set_notify_enter_exit_on_child(true); 236 set_notify_enter_exit_on_child(true);
232 if (IsRichNotificationEnabled()) { 237 if (IsRichNotificationEnabled()) {
233 set_background(views::Background::CreateSolidBackground( 238 set_background(views::Background::CreateSolidBackground(
234 kMessageCenterBackgroundColor)); 239 kMessageCenterBackgroundColor));
235 } 240 }
236 } 241 }
237 242
238 virtual ~FixedSizedScrollView() {} 243 virtual ~BoundedScrollView() {}
239 244
240 void SetFixedSize(const gfx::Size& size) { 245 // Overridden from views::View:
241 if (fixed_size_ == size)
242 return;
243 fixed_size_ = size;
244 PreferredSizeChanged();
245 }
246
247 // views::View overrides.
248 virtual gfx::Size GetPreferredSize() OVERRIDE { 246 virtual gfx::Size GetPreferredSize() OVERRIDE {
249 gfx::Size size = fixed_size_.IsEmpty() ? 247 gfx::Size size = contents()->GetPreferredSize();
250 contents()->GetPreferredSize() : fixed_size_; 248 size.ClampToMin(gfx::Size(size.width(), min_height_));
249 size.ClampToMax(gfx::Size(size.width(), max_height_));
251 gfx::Insets insets = GetInsets(); 250 gfx::Insets insets = GetInsets();
252 size.Enlarge(insets.width(), insets.height()); 251 size.Enlarge(insets.width(), insets.height());
253 return size; 252 return size;
254 } 253 }
255 254
256 virtual void Layout() OVERRIDE { 255 virtual void Layout() OVERRIDE {
257 gfx::Rect bounds = gfx::Rect(contents()->GetPreferredSize()); 256 // Lay out the view as if it will have a scroll bar.
258 bounds.set_width(std::max(0, width() - GetScrollBarWidth())); 257 gfx::Rect content_bounds = gfx::Rect(contents()->GetPreferredSize());
259 contents()->SetBoundsRect(bounds); 258 content_bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
259 contents()->SetBoundsRect(content_bounds);
260 views::ScrollView::Layout();
260 261
261 views::ScrollView::Layout(); 262 // But use the scroll bar space if no scroll bar is needed.
262 if (!vertical_scroll_bar()->visible()) { 263 if (!vertical_scroll_bar()->visible()) {
263 gfx::Rect bounds = contents()->bounds(); 264 content_bounds = contents()->bounds();
264 bounds.set_width(bounds.width() + GetScrollBarWidth()); 265 content_bounds.set_width(content_bounds.width() + GetScrollBarWidth());
265 contents()->SetBoundsRect(bounds); 266 contents()->SetBoundsRect(content_bounds);
266 } 267 }
267 } 268 }
268 269
269 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE { 270 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE {
270 gfx::Rect bounds = gfx::Rect(contents()->GetPreferredSize()); 271 // Make sure any content resizing takes into account the scroll bar.
271 bounds.set_width(std::max(0, width() - GetScrollBarWidth())); 272 gfx::Rect content_bounds = gfx::Rect(contents()->GetPreferredSize());
272 contents()->SetBoundsRect(bounds); 273 content_bounds.set_width(std::max(0, width() - GetScrollBarWidth()));
274 contents()->SetBoundsRect(content_bounds);
273 } 275 }
274 276
275 private: 277 private:
276 gfx::Size fixed_size_; 278 int min_height_;
279 int max_height_;
277 280
278 DISALLOW_COPY_AND_ASSIGN(FixedSizedScrollView); 281 DISALLOW_COPY_AND_ASSIGN(BoundedScrollView);
279 }; 282 };
280 283
281 // Container for the messages. 284 // Displays a list of messages.
282 class ScrollContentView : public views::View { 285 class MessageListView : public views::View {
283 public: 286 public:
284 ScrollContentView() { 287 MessageListView() {
285 if (IsRichNotificationEnabled()) { 288 if (IsRichNotificationEnabled()) {
286 // Set the margin to 0 for the layout. BoxLayout assumes the same margin 289 // Set the margin to 0 for the layout. BoxLayout assumes the same margin
287 // for top and bottom, but the bottom margin here should be smaller 290 // for top and bottom, but the bottom margin here should be smaller
288 // because of the shadow of message view. Use an empty border instead 291 // because of the shadow of message view. Use an empty border instead
289 // to provide this margin. 292 // to provide this margin.
290 gfx::Insets shadow_insets = MessageView::GetShadowInsets(); 293 gfx::Insets shadow_insets = MessageView::GetShadowInsets();
291 SetLayoutManager( 294 SetLayoutManager(
292 new views::BoxLayout(views::BoxLayout::kVertical, 295 new views::BoxLayout(views::BoxLayout::kVertical,
293 0, 296 0,
294 0, 297 0,
295 kMarginBetweenItems - shadow_insets.bottom())); 298 kMarginBetweenItems - shadow_insets.bottom()));
296 set_background(views::Background::CreateSolidBackground( 299 set_background(views::Background::CreateSolidBackground(
297 kMessageCenterBackgroundColor)); 300 kMessageCenterBackgroundColor));
298 set_border(views::Border::CreateEmptyBorder( 301 set_border(views::Border::CreateEmptyBorder(
299 kMarginBetweenItems - shadow_insets.top(), /* top */ 302 kMarginBetweenItems - shadow_insets.top(), /* top */
300 kMarginBetweenItems - shadow_insets.left(), /* left */ 303 kMarginBetweenItems - shadow_insets.left(), /* left */
301 0, /* bottom */ 304 0, /* bottom */
302 kMarginBetweenItems - shadow_insets.right() /* right */ )); 305 kMarginBetweenItems - shadow_insets.right() /* right */ ));
303 } else { 306 } else {
304 views::BoxLayout* layout = 307 views::BoxLayout* layout =
305 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1); 308 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1);
306 layout->set_spread_blank_space(true); 309 layout->set_spread_blank_space(true);
307 SetLayoutManager(layout); 310 SetLayoutManager(layout);
308 } 311 }
309 } 312 }
310 313
311 virtual ~ScrollContentView() { 314 virtual ~MessageListView() {
312 } 315 }
313 316
314 virtual gfx::Size GetPreferredSize() OVERRIDE {
315 if (!preferred_size_.IsEmpty())
316 return preferred_size_;
317 return views::View::GetPreferredSize();
318 }
319
320 void set_preferred_size(const gfx::Size& size) { preferred_size_ = size; }
321
322 private: 317 private:
323 gfx::Size preferred_size_; 318 DISALLOW_COPY_AND_ASSIGN(MessageListView);
324 DISALLOW_COPY_AND_ASSIGN(ScrollContentView);
325 }; 319 };
326 320
327 } // namespace 321 } // namespace
328 322
329 // Message Center contents. 323 // View that displays the whole message center.
330 class MessageCenterContentsView : public views::View { 324 class MessageCenterView : public views::View {
331 public: 325 public:
332 explicit MessageCenterContentsView(MessageCenterBubble* bubble, 326 MessageCenterView(MessageCenterBubble* bubble) : bubble_(bubble) {
333 NotificationList::Delegate* list_delegate)
334 : list_delegate_(list_delegate),
335 bubble_(bubble) {
336 int between_child = IsRichNotificationEnabled() ? 0 : 1; 327 int between_child = IsRichNotificationEnabled() ? 0 : 1;
337 SetLayoutManager( 328 SetLayoutManager(
338 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, between_child)); 329 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, between_child));
339 330
340 scroll_content_ = new ScrollContentView; 331
341 scroller_ = new FixedSizedScrollView; 332 if (IsRichNotificationEnabled())
342 scroller_->SetContents(scroll_content_); 333 button_view_ = new WebNotificationButtonView2(bubble_);
343 AddChildView(scroller_); 334 else
335 button_view_ = new WebNotificationButtonView(bubble_);
336
337 const int button_height = button_view_->GetPreferredSize().height();
338 const int min_height = kMessageBubbleBaseMinHeight - button_height;
339 const int max_height = bubble_->max_height() - button_height;
340 scroller_ = new BoundedScrollView(min_height, max_height);
344 341
345 if (get_use_acceleration_when_possible()) { 342 if (get_use_acceleration_when_possible()) {
346 scroller_->SetPaintToLayer(true); 343 scroller_->SetPaintToLayer(true);
347 scroller_->SetFillsBoundsOpaquely(false); 344 scroller_->SetFillsBoundsOpaquely(false);
348 scroller_->layer()->SetMasksToBounds(true); 345 scroller_->layer()->SetMasksToBounds(true);
349 } 346 }
350 347
351 if (IsRichNotificationEnabled()) 348 message_list_view_ = new MessageListView();
352 button_view_ = new WebNotificationButtonView2(list_delegate); 349 scroller_->SetContents(message_list_view_);
353 else 350
354 button_view_ = new WebNotificationButtonView(list_delegate); 351 AddChildView(scroller_);
355 AddChildView(button_view_); 352 AddChildView(button_view_);
356 } 353 }
357 354
358 void FocusContents() { 355 void FocusContents() {
359 } 356 }
360 357
361 void Update(const NotificationList::Notifications& notifications) { 358 void UpdateAllNotifications(
362 scroll_content_->RemoveAllChildViews(true); 359 const NotificationList::Notifications& notifications) {
363 scroll_content_->set_preferred_size(gfx::Size()); 360 RemoveAllNotifications();
364 size_t num_children = 0;
365 for (NotificationList::Notifications::const_iterator iter = 361 for (NotificationList::Notifications::const_iterator iter =
366 notifications.begin(); iter != notifications.end(); ++iter) { 362 notifications.begin(); iter != notifications.end(); ++iter) {
367 MessageView* view = NotificationView::Create(*(*iter), list_delegate_); 363 AddNotification(*(*iter));
368 view->set_scroller(scroller_); 364 if (message_views_.size() >=
369 scroll_content_->AddChildView(view);
370 if (++num_children >=
371 NotificationList::kMaxVisibleMessageCenterNotifications) { 365 NotificationList::kMaxVisibleMessageCenterNotifications) {
372 break; 366 break;
373 } 367 }
374 } 368 }
375 if (num_children == 0) { 369 if (message_views_.empty()) {
376 views::Label* label = new views::Label(l10n_util::GetStringUTF16( 370 views::Label* label = new views::Label(l10n_util::GetStringUTF16(
377 IDS_MESSAGE_CENTER_NO_MESSAGES)); 371 IDS_MESSAGE_CENTER_NO_MESSAGES));
378 label->SetFont(label->font().DeriveFont(1)); 372 label->SetFont(label->font().DeriveFont(1));
379 label->SetEnabledColor(SK_ColorGRAY); 373 label->SetEnabledColor(SK_ColorGRAY);
380 // Set transparent background to ensure that subpixel rendering 374 // Set transparent background to ensure that subpixel rendering
381 // is disabled. See crbug.com/169056 375 // is disabled. See crbug.com/169056
382 label->SetBackgroundColor(kTransparentColor); 376 label->SetBackgroundColor(kTransparentColor);
383 scroll_content_->AddChildView(label); 377 message_list_view_->AddChildView(label);
384 button_view_->SetCloseAllVisible(false); 378 button_view_->SetCloseAllVisible(false);
385 scroller_->set_focusable(false); 379 scroller_->set_focusable(false);
386 } else { 380 } else {
387 button_view_->SetCloseAllVisible(true); 381 button_view_->SetCloseAllVisible(true);
388 scroller_->set_focusable(true); 382 scroller_->set_focusable(true);
389 } 383 }
390 SizeScrollContent();
391 Layout(); 384 Layout();
392 if (GetWidget()) 385 }
393 GetWidget()->GetRootView()->SchedulePaint(); 386
387 void UpdateOneNotification(const Notification& notification) {
388 // Update the corresponding message view if there is one and explicitly
389 // update this view's layout as this is not automatic in spite of the
390 // updated view's likely size change because ScrollView's Viewport breaks
391 // the ChildPreferredSizeChange() chain.
392 MessageView* view = message_views_[notification.id()];
393 if (view) {
394 view->Update(notification);
395 Layout();
396 }
394 } 397 }
395 398
396 size_t NumMessageViews() const { 399 size_t NumMessageViews() const {
397 return scroll_content_->child_count(); 400 return message_list_view_->child_count();
401 }
402
403 protected:
404 // Overridden from views::View:
405 virtual void Layout() OVERRIDE {
406 scroller_->SizeToPreferredSize();
407 views::View::Layout();
408 if (GetWidget())
409 GetWidget()->GetRootView()->SchedulePaint();
410 bubble_->bubble_view()->UpdateBubble();
398 } 411 }
399 412
400 private: 413 private:
401 void SizeScrollContent() { 414
402 gfx::Size scroll_size = scroll_content_->GetPreferredSize(); 415 void RemoveAllNotifications() {
403 const int button_height = button_view_->GetPreferredSize().height(); 416 message_views_.clear();
404 const int min_height = kMessageBubbleBaseMinHeight - button_height; 417 message_list_view_->RemoveAllChildViews(true);
405 const int max_height = bubble_->max_height() - button_height;
406 int scroll_height = std::min(std::max(
407 scroll_size.height(), min_height), max_height);
408 scroll_size.set_height(scroll_height);
409 if (scroll_height == min_height)
410 scroll_content_->set_preferred_size(scroll_size);
411 else
412 scroll_content_->set_preferred_size(gfx::Size());
413 scroller_->SetFixedSize(scroll_size);
414 scroller_->SizeToPreferredSize();
415 scroll_content_->InvalidateLayout();
416 } 418 }
417 419
418 NotificationList::Delegate* list_delegate_; 420 void AddNotification(const Notification& notification) {
419 FixedSizedScrollView* scroller_; 421 // Always expand the first (topmost) notification.
420 ScrollContentView* scroll_content_; 422 bool expand = (notification.is_expanded() || message_views_.empty());
423 MessageView* view = NotificationView::Create(notification, bubble_, expand);
424 view->set_scroller(scroller_);
425 message_views_[notification.id()] = view;
426 message_list_view_->AddChildView(view);
427 }
428
429 MessageCenterBubble* bubble_; // Weak reference.
430 std::map<std::string,MessageView*> message_views_;
431 BoundedScrollView* scroller_;
432 MessageListView* message_list_view_;
421 WebNotificationButtonViewBase* button_view_; 433 WebNotificationButtonViewBase* button_view_;
422 MessageCenterBubble* bubble_;
423 434
424 DISALLOW_COPY_AND_ASSIGN(MessageCenterContentsView); 435 DISALLOW_COPY_AND_ASSIGN(MessageCenterView);
425 }; 436 };
426 437
427 // Message Center Bubble. 438 // Message Center Bubble.
428 MessageCenterBubble::MessageCenterBubble(NotificationList::Delegate* delegate) 439 MessageCenterBubble::MessageCenterBubble(MessageCenter* message_center)
429 : MessageBubbleBase(delegate), 440 : MessageBubbleBase(message_center),
430 contents_view_(NULL) { 441 contents_view_(NULL) {
431 } 442 }
432 443
433 MessageCenterBubble::~MessageCenterBubble() {} 444 MessageCenterBubble::~MessageCenterBubble() {}
434 445
435 views::TrayBubbleView::InitParams MessageCenterBubble::GetInitParams( 446 views::TrayBubbleView::InitParams MessageCenterBubble::GetInitParams(
436 views::TrayBubbleView::AnchorAlignment anchor_alignment) { 447 views::TrayBubbleView::AnchorAlignment anchor_alignment) {
437 views::TrayBubbleView::InitParams init_params = 448 views::TrayBubbleView::InitParams init_params =
438 GetDefaultInitParams(anchor_alignment); 449 GetDefaultInitParams(anchor_alignment);
439 if (IsRichNotificationEnabled()) { 450 if (IsRichNotificationEnabled()) {
440 init_params.min_width += kMarginBetweenItems * 2; 451 init_params.min_width += kMarginBetweenItems * 2;
441 init_params.max_width += kMarginBetweenItems * 2; 452 init_params.max_width += kMarginBetweenItems * 2;
442 } 453 }
443 init_params.max_height = max_height(); 454 init_params.max_height = max_height();
444 init_params.can_activate = true; 455 init_params.can_activate = true;
445 return init_params; 456 return init_params;
446 } 457 }
447 458
448 void MessageCenterBubble::InitializeContents( 459 void MessageCenterBubble::InitializeContents(
449 views::TrayBubbleView* new_bubble_view) { 460 views::TrayBubbleView* new_bubble_view) {
450 set_bubble_view(new_bubble_view); 461 set_bubble_view(new_bubble_view);
451 contents_view_ = new MessageCenterContentsView(this, list_delegate()); 462 contents_view_ = new MessageCenterView(this);
452 bubble_view()->AddChildView(contents_view_); 463 bubble_view()->AddChildView(contents_view_);
453 // Resize the content of the bubble view to the given bubble size. This is 464 // Resize the content of the bubble view to the given bubble size. This is
454 // necessary in case of the bubble border forcing a bigger size then the 465 // necessary in case of the bubble border forcing a bigger size then the
455 // |new_bubble_view| actually wants. See crbug.com/169390. 466 // |new_bubble_view| actually wants. See crbug.com/169390.
456 bubble_view()->Layout(); 467 bubble_view()->Layout();
457 UpdateBubbleView(); 468 UpdateBubbleView();
458 contents_view_->FocusContents(); 469 contents_view_->FocusContents();
459 } 470 }
460 471
461 void MessageCenterBubble::OnBubbleViewDestroyed() { 472 void MessageCenterBubble::OnBubbleViewDestroyed() {
462 contents_view_ = NULL; 473 contents_view_ = NULL;
463 } 474 }
464 475
465 void MessageCenterBubble::UpdateBubbleView() { 476 void MessageCenterBubble::UpdateBubbleView() {
466 if (!bubble_view()) 477 if (!bubble_view())
467 return; // Could get called after view is closed 478 return; // Could get called after view is closed
468 const NotificationList::Notifications& notifications = 479 const NotificationList::Notifications& notifications =
469 list_delegate()->GetNotificationList()->GetNotifications(); 480 message_center()->notification_list()->GetNotifications();
470 contents_view_->Update(notifications); 481 contents_view_->UpdateAllNotifications(notifications);
471 bubble_view()->Show(); 482 bubble_view()->Show();
472 bubble_view()->UpdateBubble(); 483 bubble_view()->UpdateBubble();
473 } 484 }
474 485
475 void MessageCenterBubble::OnMouseEnteredView() { 486 void MessageCenterBubble::OnMouseEnteredView() {
476 } 487 }
477 488
478 void MessageCenterBubble::OnMouseExitedView() { 489 void MessageCenterBubble::OnMouseExitedView() {
479 } 490 }
480 491
492 void MessageCenterBubble::OnRemoveNotification(const std::string& id,
493 bool by_user) {
494 message_center()->OnRemoveNotification(id, by_user);
495 }
496
497 void MessageCenterBubble::OnRemoveAllNotifications(bool by_user) {
498 message_center()->OnRemoveAllNotifications(by_user);
499 }
500
501 void MessageCenterBubble::OnDisableNotificationsByExtension(
502 const std::string& id) {
503 message_center()->OnDisableNotificationsByExtension(id);
504 }
505
506 void MessageCenterBubble::OnDisableNotificationsByUrl(const std::string& id) {
507 message_center()->OnDisableNotificationsByUrl(id);
508 }
509
510 void MessageCenterBubble::OnShowNotificationSettings(const std::string& id) {
511 message_center()->OnShowNotificationSettings(id);
512 }
513
514 void MessageCenterBubble::OnShowNotificationSettingsDialog(
515 gfx::NativeView context) {
516 message_center()->OnShowNotificationSettingsDialog(context);
517 }
518
519 void MessageCenterBubble::OnClicked(const std::string& id) {
520 message_center()->OnClicked(id);
521 }
522
523 void MessageCenterBubble::OnButtonClicked(const std::string& id,
524 int button_index) {
525 message_center()->OnButtonClicked(id, button_index);
526 }
527
528 void MessageCenterBubble::OnExpanded(const std::string& id) {
529 message_center()->OnExpanded(id);
530
531 // Update the view corresponding to this notification.
532 const NotificationList::Notifications& notifications =
533 message_center()->notification_list()->GetNotifications();
534 for (NotificationList::Notifications::const_iterator iter =
535 notifications.begin(); iter != notifications.end(); ++iter) {
536 if ((*iter)->id() == id) {
537 contents_view_->UpdateOneNotification(*(*iter));
538 break;
539 }
540 }
541 }
542
481 size_t MessageCenterBubble::NumMessageViewsForTest() const { 543 size_t MessageCenterBubble::NumMessageViewsForTest() const {
482 return contents_view_->NumMessageViews(); 544 return contents_view_->NumMessageViews();
483 } 545 }
484 546
485 } // namespace message_center 547 } // namespace message_center
OLDNEW
« no previous file with comments | « ui/message_center/views/message_center_bubble.h ('k') | ui/message_center/views/message_popup_bubble.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698