| 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/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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |