| 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 "ash/common/system/web_notification/web_notification_tray.h" | 5 #include "ash/common/system/web_notification/web_notification_tray.h" |
| 6 | 6 |
| 7 #include "ash/common/ash_switches.h" | 7 #include "ash/common/ash_switches.h" |
| 8 #include "ash/common/material_design/material_design_controller.h" | 8 #include "ash/common/material_design/material_design_controller.h" |
| 9 #include "ash/common/session/session_state_delegate.h" | 9 #include "ash/common/session/session_state_delegate.h" |
| 10 #include "ash/common/shelf/shelf_constants.h" | 10 #include "ash/common/shelf/shelf_constants.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 } | 55 } |
| 56 | 56 |
| 57 } // namespace message_center | 57 } // namespace message_center |
| 58 | 58 |
| 59 #endif // defined(OS_CHROMEOS) | 59 #endif // defined(OS_CHROMEOS) |
| 60 | 60 |
| 61 namespace ash { | 61 namespace ash { |
| 62 namespace { | 62 namespace { |
| 63 | 63 |
| 64 // Menu commands | 64 // Menu commands |
| 65 const int kToggleQuietMode = 0; | 65 constexpr int kToggleQuietMode = 0; |
| 66 const int kEnableQuietModeDay = 2; | 66 constexpr int kEnableQuietModeDay = 2; |
| 67 |
| 68 constexpr int kMaximumSmallIconCount = 3; |
| 69 |
| 70 constexpr gfx::Size kTrayItemInnerIconSize(16, 16); |
| 71 constexpr gfx::Size kTrayItemInnerBellIconSize(18, 18); |
| 72 constexpr gfx::Size kTrayItemOuterSize(26, 26); |
| 73 constexpr gfx::Insets kTrayItemInsets(3, 3); |
| 74 |
| 75 constexpr int kTrayItemAnimationDurationMS = 200; |
| 76 |
| 77 constexpr size_t kMaximumNotificationNumber = 99; |
| 78 |
| 79 // Flag to disable animation. Only for testing. |
| 80 bool disable_animations_for_test = false; |
| 67 } | 81 } |
| 68 | 82 |
| 69 namespace { | 83 namespace { |
| 70 | 84 |
| 71 const SkColor kWebNotificationColorNoUnread = | 85 const SkColor kWebNotificationColorNoUnread = |
| 72 SkColorSetARGB(128, 255, 255, 255); | 86 SkColorSetARGB(128, 255, 255, 255); |
| 73 const SkColor kWebNotificationColorWithUnread = SK_ColorWHITE; | 87 const SkColor kWebNotificationColorWithUnread = SK_ColorWHITE; |
| 74 const int kNoUnreadIconSize = 18; | 88 const int kNoUnreadIconSize = 18; |
| 75 } | 89 } |
| 76 | 90 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 107 // Convenience accessors. | 121 // Convenience accessors. |
| 108 views::TrayBubbleView* bubble_view() const { return bubble_->bubble_view(); } | 122 views::TrayBubbleView* bubble_view() const { return bubble_->bubble_view(); } |
| 109 | 123 |
| 110 private: | 124 private: |
| 111 std::unique_ptr<message_center::MessageBubbleBase> bubble_; | 125 std::unique_ptr<message_center::MessageBubbleBase> bubble_; |
| 112 std::unique_ptr<TrayBubbleWrapper> bubble_wrapper_; | 126 std::unique_ptr<TrayBubbleWrapper> bubble_wrapper_; |
| 113 | 127 |
| 114 DISALLOW_COPY_AND_ASSIGN(WebNotificationBubbleWrapper); | 128 DISALLOW_COPY_AND_ASSIGN(WebNotificationBubbleWrapper); |
| 115 }; | 129 }; |
| 116 | 130 |
| 117 class WebNotificationIcon : public views::View { | 131 class WebNotificationItem : public views::View, public gfx::AnimationDelegate { |
| 118 public: | 132 public: |
| 119 WebNotificationIcon() : is_bubble_visible_(false), unread_count_(0) { | 133 WebNotificationItem(gfx::AnimationContainer* container, |
| 134 WebNotificationTray* tray) |
| 135 : tray_(tray) { |
| 136 SetPaintToLayer(true); |
| 137 layer()->SetFillsBoundsOpaquely(false); |
| 138 views::View::SetVisible(false); |
| 139 set_owned_by_client(); |
| 140 |
| 120 SetLayoutManager(new views::FillLayout); | 141 SetLayoutManager(new views::FillLayout); |
| 121 | 142 |
| 122 gfx::ImageSkia image; | 143 animation_.reset(new gfx::SlideAnimation(this)); |
| 123 if (MaterialDesignController::IsShelfMaterial()) { | 144 animation_->SetContainer(container); |
| 124 image = CreateVectorIcon(gfx::VectorIconId::SHELF_NOTIFICATIONS, | 145 animation_->SetSlideDuration(kTrayItemAnimationDurationMS); |
| 125 kShelfIconColor); | 146 animation_->SetTweenType(gfx::Tween::LINEAR); |
| 126 } else { | 147 } |
| 127 image = | 148 |
| 128 CreateVectorIcon(gfx::VectorIconId::NOTIFICATIONS, kNoUnreadIconSize, | 149 void SetVisible(bool set_visible) override { |
| 129 kWebNotificationColorNoUnread); | 150 if (!GetWidget() || disable_animations_for_test) { |
| 151 views::View::SetVisible(set_visible); |
| 152 return; |
| 130 } | 153 } |
| 131 | 154 |
| 132 no_unread_icon_.SetImage(image); | 155 if (!set_visible) { |
| 133 no_unread_icon_.set_owned_by_client(); | 156 animation_->Hide(); |
| 134 | 157 AnimationProgressed(animation_.get()); |
| 135 unread_label_.set_owned_by_client(); | 158 } else { |
| 136 SetupLabelForTray(&unread_label_); | 159 animation_->Show(); |
| 137 | 160 AnimationProgressed(animation_.get()); |
| 138 AddChildView(&no_unread_icon_); | 161 views::View::SetVisible(true); |
| 162 } |
| 139 } | 163 } |
| 140 | 164 |
| 141 void SetBubbleVisible(bool visible) { | 165 void HideAndDelete() { |
| 142 if (visible == is_bubble_visible_) | 166 SetVisible(false); |
| 143 return; | |
| 144 | 167 |
| 145 is_bubble_visible_ = visible; | 168 if (!visible() && !animation_->is_animating()) { |
| 146 UpdateIconVisibility(); | 169 if (parent()) |
| 147 } | 170 parent()->RemoveChildView(this); |
| 148 | 171 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); |
| 149 void SetUnreadCount(int unread_count) { | 172 } else { |
| 150 // base::FormatNumber doesn't convert to arabic numeric characters. | 173 delete_after_animation_ = true; |
| 151 // TODO(mukai): use ICU to support conversion for such locales. | 174 } |
| 152 unread_count_ = unread_count; | |
| 153 UpdateIconVisibility(); | |
| 154 } | 175 } |
| 155 | 176 |
| 156 protected: | 177 protected: |
| 157 // Overridden from views::View: | 178 // Overridden from views::View: |
| 158 gfx::Size GetPreferredSize() const override { | 179 gfx::Size GetPreferredSize() const override { |
| 159 const int size = GetTrayConstant(TRAY_ITEM_HEIGHT_LEGACY); | 180 if (!animation_.get() || !animation_->is_animating()) |
| 160 return gfx::Size(size, size); | 181 return kTrayItemOuterSize; |
| 182 |
| 183 // Animate the width (or height) when this item shows (or hides) so that |
| 184 // the icons on the left are shifted with the animation. |
| 185 // Note that TrayItemView does the same thing. |
| 186 gfx::Size size = kTrayItemOuterSize; |
| 187 if (IsHorizontalLayout()) { |
| 188 size.set_width(std::max( |
| 189 1, gfx::ToRoundedInt(size.width() * animation_->GetCurrentValue()))); |
| 190 } else { |
| 191 size.set_height(std::max( |
| 192 1, gfx::ToRoundedInt(size.height() * animation_->GetCurrentValue()))); |
| 193 } |
| 194 return size; |
| 161 } | 195 } |
| 162 | 196 |
| 163 int GetHeightForWidth(int width) const override { | 197 int GetHeightForWidth(int width) const override { |
| 164 return GetPreferredSize().height(); | 198 return GetPreferredSize().height(); |
| 165 } | 199 } |
| 166 | 200 |
| 201 bool IsHorizontalLayout() const { |
| 202 return IsHorizontalAlignment(tray_->shelf_alignment()); |
| 203 } |
| 204 |
| 167 private: | 205 private: |
| 168 void UpdateIconVisibility() { | 206 // gfx::AnimationDelegate: |
| 169 if (unread_count_ == 0) { | 207 void AnimationProgressed(const gfx::Animation* animation) override { |
| 170 if (!Contains(&no_unread_icon_)) { | 208 gfx::Transform transform; |
| 171 RemoveAllChildViews(false /* delete_children */); | 209 if (IsHorizontalLayout()) { |
| 172 AddChildView(&no_unread_icon_); | 210 transform.Translate(0, animation->CurrentValueBetween( |
| 173 } | 211 static_cast<double>(height()) / 2., 0.)); |
| 174 } else { | 212 } else { |
| 175 if (!Contains(&unread_label_)) { | 213 transform.Translate( |
| 176 RemoveAllChildViews(false /* delete_children */); | 214 animation->CurrentValueBetween(static_cast<double>(width() / 2.), 0.), |
| 177 AddChildView(&unread_label_); | 215 0); |
| 178 } | 216 } |
| 217 transform.Scale(animation->GetCurrentValue(), animation->GetCurrentValue()); |
| 218 layer()->SetTransform(transform); |
| 219 PreferredSizeChanged(); |
| 220 } |
| 221 void AnimationEnded(const gfx::Animation* animation) override { |
| 222 if (animation->GetCurrentValue() < 0.1) |
| 223 views::View::SetVisible(false); |
| 179 | 224 |
| 180 // TODO(mukai): move NINE_PLUS message to ui_strings, it doesn't need to | 225 if (delete_after_animation_) { |
| 181 // be in ash_strings. | 226 if (parent()) |
| 182 unread_label_.SetText( | 227 parent()->RemoveChildView(this); |
| 183 (unread_count_ > 9) ? l10n_util::GetStringUTF16( | 228 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); |
| 184 IDS_ASH_NOTIFICATION_UNREAD_COUNT_NINE_PLUS) | |
| 185 : base::FormatNumber(unread_count_)); | |
| 186 unread_label_.SetEnabledColor((unread_count_ > 0) | |
| 187 ? kWebNotificationColorWithUnread | |
| 188 : kWebNotificationColorNoUnread); | |
| 189 } | 229 } |
| 230 } |
| 231 void AnimationCanceled(const gfx::Animation* animation) override { |
| 232 AnimationEnded(animation); |
| 233 } |
| 234 |
| 235 std::unique_ptr<gfx::SlideAnimation> animation_; |
| 236 bool delete_after_animation_ = false; |
| 237 WebNotificationTray* tray_; |
| 238 |
| 239 DISALLOW_COPY_AND_ASSIGN(WebNotificationItem); |
| 240 }; |
| 241 |
| 242 class WebNotificationImage : public WebNotificationItem { |
| 243 public: |
| 244 WebNotificationImage(const gfx::ImageSkia& image, |
| 245 gfx::Size size, |
| 246 gfx::AnimationContainer* container, |
| 247 WebNotificationTray* tray) |
| 248 : WebNotificationItem(container, tray) { |
| 249 view_ = new views::ImageView(); |
| 250 view_->SetImage(image); |
| 251 view_->SetImageSize(size); |
| 252 AddChildView(view_); |
| 253 } |
| 254 |
| 255 private: |
| 256 views::ImageView* view_; |
| 257 |
| 258 DISALLOW_COPY_AND_ASSIGN(WebNotificationImage); |
| 259 }; |
| 260 |
| 261 class WebNotificationLabel : public WebNotificationItem { |
| 262 public: |
| 263 WebNotificationLabel(gfx::AnimationContainer* container, |
| 264 WebNotificationTray* tray) |
| 265 : WebNotificationItem(container, tray) { |
| 266 view_ = new views::Label(); |
| 267 SetupLabelForTray(view_); |
| 268 AddChildView(view_); |
| 269 } |
| 270 |
| 271 void SetNotificationCount(bool small_icons_exist, size_t notification_count) { |
| 272 notification_count = std::min(notification_count, |
| 273 kMaximumNotificationNumber); // cap with 99 |
| 274 |
| 275 // TODO(yoshiki): Use a string for "99" and "+99". |
| 276 |
| 277 base::string16 str = base::FormatNumber(notification_count); |
| 278 if (small_icons_exist) { |
| 279 if (!base::i18n::IsRTL()) |
| 280 str = base::ASCIIToUTF16("+") + str; |
| 281 else |
| 282 str = str + base::ASCIIToUTF16("+"); |
| 283 } |
| 284 |
| 285 view_->SetText(str); |
| 286 view_->SetEnabledColor(kWebNotificationColorWithUnread); |
| 190 SchedulePaint(); | 287 SchedulePaint(); |
| 191 } | 288 } |
| 192 | 289 |
| 193 bool is_bubble_visible_; | 290 private: |
| 194 int unread_count_; | 291 views::Label* view_; |
| 195 | 292 |
| 196 views::ImageView no_unread_icon_; | 293 DISALLOW_COPY_AND_ASSIGN(WebNotificationLabel); |
| 197 views::Label unread_label_; | |
| 198 | |
| 199 DISALLOW_COPY_AND_ASSIGN(WebNotificationIcon); | |
| 200 }; | 294 }; |
| 201 | 295 |
| 202 WebNotificationTray::WebNotificationTray(WmShelf* shelf, | 296 WebNotificationTray::WebNotificationTray(WmShelf* shelf, |
| 203 WmWindow* status_area_window, | 297 WmWindow* status_area_window, |
| 204 SystemTray* system_tray) | 298 SystemTray* system_tray) |
| 205 : TrayBackgroundView(shelf), | 299 : TrayBackgroundView(shelf), |
| 206 status_area_window_(status_area_window), | 300 status_area_window_(status_area_window), |
| 207 system_tray_(system_tray), | 301 system_tray_(system_tray), |
| 208 icon_(new WebNotificationIcon), | |
| 209 show_message_center_on_unlock_(false), | 302 show_message_center_on_unlock_(false), |
| 210 should_update_tray_content_(false), | 303 should_update_tray_content_(false), |
| 211 should_block_shelf_auto_hide_(false) { | 304 should_block_shelf_auto_hide_(false) { |
| 212 DCHECK(shelf); | 305 DCHECK(shelf); |
| 213 DCHECK(status_area_window_); | 306 DCHECK(status_area_window_); |
| 214 DCHECK(system_tray_); | 307 DCHECK(system_tray_); |
| 215 | 308 |
| 216 tray_container()->AddChildView(icon_); | 309 gfx::ImageSkia bell_image; |
| 310 if (MaterialDesignController::IsShelfMaterial()) { |
| 311 bell_image = CreateVectorIcon(gfx::VectorIconId::SHELF_NOTIFICATIONS, |
| 312 kShelfIconColor); |
| 313 } else { |
| 314 bell_image = |
| 315 CreateVectorIcon(gfx::VectorIconId::NOTIFICATIONS, kNoUnreadIconSize, |
| 316 kWebNotificationColorNoUnread); |
| 317 } |
| 318 bell_icon_.reset(new WebNotificationImage(bell_image, |
| 319 kTrayItemInnerBellIconSize, |
| 320 animation_container_.get(), this)); |
| 321 tray_container()->AddChildView(bell_icon_.get()); |
| 322 |
| 323 counter_.reset(new WebNotificationLabel(animation_container_.get(), this)); |
| 324 tray_container()->AddChildView(counter_.get()); |
| 325 |
| 217 SetContentsBackground(); | 326 SetContentsBackground(); |
| 218 tray_container()->SetBorder(views::Border::NullBorder()); | 327 tray_container()->SetBorder(views::Border::NullBorder()); |
| 219 message_center_tray_.reset(new message_center::MessageCenterTray( | 328 message_center_tray_.reset(new message_center::MessageCenterTray( |
| 220 this, message_center::MessageCenter::Get())); | 329 this, message_center::MessageCenter::Get())); |
| 221 popup_alignment_delegate_.reset(new AshPopupAlignmentDelegate(shelf)); | 330 popup_alignment_delegate_.reset(new AshPopupAlignmentDelegate(shelf)); |
| 222 popup_collection_.reset(new message_center::MessagePopupCollection( | 331 popup_collection_.reset(new message_center::MessagePopupCollection( |
| 223 message_center(), message_center_tray_.get(), | 332 message_center(), message_center_tray_.get(), |
| 224 popup_alignment_delegate_.get())); | 333 popup_alignment_delegate_.get())); |
| 225 const display::Display& display = | 334 const display::Display& display = |
| 226 status_area_window_->GetDisplayNearestWindow(); | 335 status_area_window_->GetDisplayNearestWindow(); |
| 227 popup_alignment_delegate_->StartObserving(display::Screen::GetScreen(), | 336 popup_alignment_delegate_->StartObserving(display::Screen::GetScreen(), |
| 228 display); | 337 display); |
| 229 OnMessageCenterTrayChanged(); | 338 OnMessageCenterTrayChanged(); |
| 339 |
| 340 tray_container()->SetMargin(kTrayItemInsets); |
| 230 } | 341 } |
| 231 | 342 |
| 232 WebNotificationTray::~WebNotificationTray() { | 343 WebNotificationTray::~WebNotificationTray() { |
| 233 // Release any child views that might have back pointers before ~View(). | 344 // Release any child views that might have back pointers before ~View(). |
| 234 message_center_bubble_.reset(); | 345 message_center_bubble_.reset(); |
| 235 popup_alignment_delegate_.reset(); | 346 popup_alignment_delegate_.reset(); |
| 236 popup_collection_.reset(); | 347 popup_collection_.reset(); |
| 237 } | 348 } |
| 238 | 349 |
| 350 // static |
| 351 void WebNotificationTray::DisableAnimationsForTest(bool disable) { |
| 352 disable_animations_for_test = disable; |
| 353 } |
| 354 |
| 239 // Public methods. | 355 // Public methods. |
| 240 | 356 |
| 241 bool WebNotificationTray::ShowMessageCenterInternal(bool show_settings) { | 357 bool WebNotificationTray::ShowMessageCenterInternal(bool show_settings) { |
| 242 if (!ShouldShowMessageCenter()) | 358 if (!ShouldShowMessageCenter()) |
| 243 return false; | 359 return false; |
| 244 | 360 |
| 245 should_block_shelf_auto_hide_ = true; | 361 should_block_shelf_auto_hide_ = true; |
| 246 message_center::MessageCenterBubble* message_center_bubble = | 362 message_center::MessageCenterBubble* message_center_bubble = |
| 247 new message_center::MessageCenterBubble(message_center(), | 363 new message_center::MessageCenterBubble(message_center(), |
| 248 message_center_tray_.get(), true); | 364 message_center_tray_.get(), true); |
| 249 | 365 |
| 250 int max_height; | 366 int max_height; |
| 251 if (IsHorizontalAlignment(shelf()->GetAlignment())) { | 367 if (IsHorizontalAlignment(shelf_alignment())) { |
| 252 max_height = shelf()->GetIdealBounds().y(); | 368 max_height = shelf()->GetIdealBounds().y(); |
| 253 } else { | 369 } else { |
| 254 // Assume the status area and bubble bottoms are aligned when vertical. | 370 // Assume the status area and bubble bottoms are aligned when vertical. |
| 255 gfx::Rect bounds_in_root = | 371 gfx::Rect bounds_in_root = |
| 256 status_area_window_->GetRootWindow()->ConvertRectFromScreen( | 372 status_area_window_->GetRootWindow()->ConvertRectFromScreen( |
| 257 status_area_window_->GetBoundsInScreen()); | 373 status_area_window_->GetBoundsInScreen()); |
| 258 max_height = bounds_in_root.bottom(); | 374 max_height = bounds_in_root.bottom(); |
| 259 } | 375 } |
| 260 message_center_bubble->SetMaxHeight( | 376 message_center_bubble->SetMaxHeight( |
| 261 std::max(0, max_height - GetTrayConstant(TRAY_SPACING))); | 377 std::max(0, max_height - GetTrayConstant(TRAY_SPACING))); |
| 262 if (show_settings) | 378 if (show_settings) |
| 263 message_center_bubble->SetSettingsVisible(); | 379 message_center_bubble->SetSettingsVisible(); |
| 264 message_center_bubble_.reset( | 380 message_center_bubble_.reset( |
| 265 new WebNotificationBubbleWrapper(this, message_center_bubble)); | 381 new WebNotificationBubbleWrapper(this, message_center_bubble)); |
| 266 | 382 |
| 267 system_tray_->SetHideNotifications(true); | 383 system_tray_->SetHideNotifications(true); |
| 268 shelf()->UpdateAutoHideState(); | 384 shelf()->UpdateAutoHideState(); |
| 269 icon_->SetBubbleVisible(true); | |
| 270 SetDrawBackgroundAsActive(true); | 385 SetDrawBackgroundAsActive(true); |
| 271 return true; | 386 return true; |
| 272 } | 387 } |
| 273 | 388 |
| 274 bool WebNotificationTray::ShowMessageCenter() { | 389 bool WebNotificationTray::ShowMessageCenter() { |
| 275 return ShowMessageCenterInternal(false /* show_settings */); | 390 return ShowMessageCenterInternal(false /* show_settings */); |
| 276 } | 391 } |
| 277 | 392 |
| 278 void WebNotificationTray::HideMessageCenter() { | 393 void WebNotificationTray::HideMessageCenter() { |
| 279 if (!message_center_bubble()) | 394 if (!message_center_bubble()) |
| 280 return; | 395 return; |
| 281 SetDrawBackgroundAsActive(false); | 396 SetDrawBackgroundAsActive(false); |
| 282 message_center_bubble_.reset(); | 397 message_center_bubble_.reset(); |
| 283 should_block_shelf_auto_hide_ = false; | 398 should_block_shelf_auto_hide_ = false; |
| 284 show_message_center_on_unlock_ = false; | 399 show_message_center_on_unlock_ = false; |
| 285 system_tray_->SetHideNotifications(false); | 400 system_tray_->SetHideNotifications(false); |
| 286 shelf()->UpdateAutoHideState(); | 401 shelf()->UpdateAutoHideState(); |
| 287 icon_->SetBubbleVisible(false); | |
| 288 } | 402 } |
| 289 | 403 |
| 290 void WebNotificationTray::SetTrayBubbleHeight(int height) { | 404 void WebNotificationTray::SetTrayBubbleHeight(int height) { |
| 291 popup_alignment_delegate_->SetTrayBubbleHeight(height); | 405 popup_alignment_delegate_->SetTrayBubbleHeight(height); |
| 292 } | 406 } |
| 293 | 407 |
| 294 int WebNotificationTray::tray_bubble_height_for_test() const { | 408 int WebNotificationTray::tray_bubble_height_for_test() const { |
| 295 return popup_alignment_delegate_->tray_bubble_height_for_test(); | 409 return popup_alignment_delegate_->tray_bubble_height_for_test(); |
| 296 } | 410 } |
| 297 | 411 |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 base::ThreadTaskRunnerHandle::Get()->PostTask( | 577 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 464 FROM_HERE, | 578 FROM_HERE, |
| 465 base::Bind(&WebNotificationTray::UpdateTrayContent, AsWeakPtr())); | 579 base::Bind(&WebNotificationTray::UpdateTrayContent, AsWeakPtr())); |
| 466 } | 580 } |
| 467 | 581 |
| 468 void WebNotificationTray::UpdateTrayContent() { | 582 void WebNotificationTray::UpdateTrayContent() { |
| 469 if (!should_update_tray_content_) | 583 if (!should_update_tray_content_) |
| 470 return; | 584 return; |
| 471 should_update_tray_content_ = false; | 585 should_update_tray_content_ = false; |
| 472 | 586 |
| 587 std::unordered_set<std::string> notification_ids; |
| 588 for (auto pair : visible_small_icons_) |
| 589 notification_ids.insert(pair.first); |
| 590 |
| 591 // Add small icons (up to kMaximumSmallIconCount = 3). |
| 473 message_center::MessageCenter* message_center = | 592 message_center::MessageCenter* message_center = |
| 474 message_center_tray_->message_center(); | 593 message_center_tray_->message_center(); |
| 475 icon_->SetUnreadCount(message_center->UnreadNotificationCount()); | 594 size_t visible_small_icon_count = 0; |
| 595 for (const auto* notification : message_center->GetVisibleNotifications()) { |
| 596 gfx::Image image = notification->small_image(); |
| 597 if (image.IsEmpty()) |
| 598 continue; |
| 599 |
| 600 if (visible_small_icon_count >= kMaximumSmallIconCount) |
| 601 break; |
| 602 visible_small_icon_count++; |
| 603 |
| 604 notification_ids.erase(notification->id()); |
| 605 if (visible_small_icons_.count(notification->id()) != 0) |
| 606 continue; |
| 607 |
| 608 auto* item = |
| 609 new WebNotificationImage(image.AsImageSkia(), kTrayItemInnerIconSize, |
| 610 animation_container_.get(), this); |
| 611 visible_small_icons_.insert(std::make_pair(notification->id(), item)); |
| 612 |
| 613 tray_container()->AddChildViewAt(item, 0); |
| 614 item->SetVisible(true); |
| 615 } |
| 616 |
| 617 // Remove unnecessary icons. |
| 618 for (const std::string& id : notification_ids) { |
| 619 WebNotificationImage* item = visible_small_icons_[id]; |
| 620 visible_small_icons_.erase(id); |
| 621 item->HideAndDelete(); |
| 622 } |
| 623 |
| 624 // Show or hide the bell icon. |
| 625 size_t visible_notification_count = message_center->NotificationCount(); |
| 626 bell_icon_->SetVisible(visible_notification_count == 0); |
| 627 |
| 628 // Show or hide the counter. |
| 629 size_t hidden_icon_count = |
| 630 visible_notification_count - visible_small_icon_count; |
| 631 if (hidden_icon_count != 0) { |
| 632 counter_->SetVisible(true); |
| 633 counter_->SetNotificationCount( |
| 634 (visible_small_icon_count != 0), // small_icons_exist |
| 635 hidden_icon_count); |
| 636 } else { |
| 637 counter_->SetVisible(false); |
| 638 } |
| 476 | 639 |
| 477 SetVisible(IsLoggedIn()); | 640 SetVisible(IsLoggedIn()); |
| 641 PreferredSizeChanged(); |
| 478 Layout(); | 642 Layout(); |
| 479 SchedulePaint(); | 643 SchedulePaint(); |
| 480 if (IsLoggedIn()) | 644 if (IsLoggedIn()) |
| 481 system_tray_->SetNextFocusableView(this); | 645 system_tray_->SetNextFocusableView(this); |
| 482 } | 646 } |
| 483 | 647 |
| 484 void WebNotificationTray::ClickedOutsideBubble() { | 648 void WebNotificationTray::ClickedOutsideBubble() { |
| 485 // Only hide the message center | 649 // Only hide the message center |
| 486 if (!message_center_bubble()) | 650 if (!message_center_bubble()) |
| 487 return; | 651 return; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 508 | 672 |
| 509 message_center::MessageCenterBubble* | 673 message_center::MessageCenterBubble* |
| 510 WebNotificationTray::GetMessageCenterBubbleForTest() { | 674 WebNotificationTray::GetMessageCenterBubbleForTest() { |
| 511 if (!message_center_bubble()) | 675 if (!message_center_bubble()) |
| 512 return NULL; | 676 return NULL; |
| 513 return static_cast<message_center::MessageCenterBubble*>( | 677 return static_cast<message_center::MessageCenterBubble*>( |
| 514 message_center_bubble()->bubble()); | 678 message_center_bubble()->bubble()); |
| 515 } | 679 } |
| 516 | 680 |
| 517 } // namespace ash | 681 } // namespace ash |
| OLD | NEW |