OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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_view.h" | 5 #include "ui/message_center/views/message_center_view.h" |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 #include <map> | 8 #include <map> |
9 | 9 |
10 #include "base/memory/weak_ptr.h" | 10 #include "base/memory/weak_ptr.h" |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 int NoNotificationMessageView::GetHeightForWidth(int width) { | 152 int NoNotificationMessageView::GetHeightForWidth(int width) { |
153 return kMinScrollViewHeight; | 153 return kMinScrollViewHeight; |
154 } | 154 } |
155 | 155 |
156 void NoNotificationMessageView::Layout() { | 156 void NoNotificationMessageView::Layout() { |
157 int text_height = label_->GetHeightForWidth(width()); | 157 int text_height = label_->GetHeightForWidth(width()); |
158 int margin = (height() - text_height) / 2; | 158 int margin = (height() - text_height) / 2; |
159 label_->SetBounds(0, margin, width(), text_height); | 159 label_->SetBounds(0, margin, width(), text_height); |
160 } | 160 } |
161 | 161 |
162 // Displays a list of messages for rich notifications. It also supports | 162 // Displays a list of messages for rich notifications. Functions as an array of |
| 163 // MessageViews and animates them on transitions. It also supports |
163 // repositioning. | 164 // repositioning. |
164 class MessageListView : public views::View, | 165 class MessageListView : public views::View, |
165 public views::BoundsAnimatorObserver { | 166 public views::BoundsAnimatorObserver { |
166 public: | 167 public: |
167 explicit MessageListView(MessageCenterView* message_center_view, | 168 explicit MessageListView(MessageCenterView* message_center_view, |
168 bool top_down); | 169 bool top_down); |
169 virtual ~MessageListView(); | 170 virtual ~MessageListView(); |
170 | 171 |
171 void AddNotificationAt(views::View* view, int i); | 172 void AddNotificationAt(MessageView* view, int i); |
172 void RemoveNotificationAt(int i); | 173 void RemoveNotificationAt(int i); |
173 void UpdateNotificationAt(views::View* view, int i); | 174 void UpdateNotificationAt(MessageView* view, int i); |
174 void SetRepositionTarget(const gfx::Rect& target_rect); | 175 void SetRepositionTarget(const gfx::Rect& target_rect); |
175 void ResetRepositionSession(); | 176 void ResetRepositionSession(); |
176 void ClearAllNotifications(const gfx::Rect& visible_scroll_rect); | 177 void ClearAllNotifications(const gfx::Rect& visible_scroll_rect); |
177 | 178 |
178 protected: | 179 protected: |
179 // Overridden from views::View. | 180 // Overridden from views::View. |
180 virtual void Layout() OVERRIDE; | 181 virtual void Layout() OVERRIDE; |
181 virtual gfx::Size GetPreferredSize() OVERRIDE; | 182 virtual gfx::Size GetPreferredSize() OVERRIDE; |
182 virtual int GetHeightForWidth(int width) OVERRIDE; | 183 virtual int GetHeightForWidth(int width) OVERRIDE; |
183 virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE; | 184 virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 for (int i = 0; i < child_count(); ++i) { | 279 for (int i = 0; i < child_count(); ++i) { |
279 views::View* child = child_at(i); | 280 views::View* child = child_at(i); |
280 if (!child->visible()) | 281 if (!child->visible()) |
281 continue; | 282 continue; |
282 int height = child->GetHeightForWidth(child_area.width()); | 283 int height = child->GetHeightForWidth(child_area.width()); |
283 child->SetBounds(child_area.x(), top, child_area.width(), height); | 284 child->SetBounds(child_area.x(), top, child_area.width(), height); |
284 top += height + between_items; | 285 top += height + between_items; |
285 } | 286 } |
286 } | 287 } |
287 | 288 |
288 void MessageListView::AddNotificationAt(views::View* view, int i) { | 289 void MessageListView::AddNotificationAt(MessageView* view, int i) { |
289 AddChildViewAt(view, GetActualIndex(i)); | 290 AddChildViewAt(view, GetActualIndex(i)); |
290 if (GetContentsBounds().IsEmpty()) | 291 if (GetContentsBounds().IsEmpty()) |
291 return; | 292 return; |
292 | 293 |
293 adding_views_.insert(view); | 294 adding_views_.insert(view); |
294 DoUpdateIfPossible(); | 295 DoUpdateIfPossible(); |
295 } | 296 } |
296 | 297 |
297 void MessageListView::RemoveNotificationAt(int i) { | 298 void MessageListView::RemoveNotificationAt(int i) { |
298 views::View* child = child_at(GetActualIndex(i)); | 299 views::View* child = child_at(GetActualIndex(i)); |
299 if (GetContentsBounds().IsEmpty()) { | 300 if (GetContentsBounds().IsEmpty()) { |
300 delete child; | 301 delete child; |
301 } else { | 302 } else { |
302 if (child->layer()) { | 303 if (child->layer()) { |
303 deleting_views_.insert(child); | 304 deleting_views_.insert(child); |
304 } else { | 305 } else { |
305 if (animator_.get()) | 306 if (animator_.get()) |
306 animator_->StopAnimatingView(child); | 307 animator_->StopAnimatingView(child); |
307 delete child; | 308 delete child; |
308 } | 309 } |
309 DoUpdateIfPossible(); | 310 DoUpdateIfPossible(); |
310 } | 311 } |
311 } | 312 } |
312 | 313 |
313 void MessageListView::UpdateNotificationAt(views::View* view, int i) { | 314 void MessageListView::UpdateNotificationAt(MessageView* view, int i) { |
314 int actual_index = GetActualIndex(i); | 315 int actual_index = GetActualIndex(i); |
315 views::View* child = child_at(actual_index); | 316 views::View* child = child_at(actual_index); |
316 if (animator_.get()) | 317 if (animator_.get()) |
317 animator_->StopAnimatingView(child); | 318 animator_->StopAnimatingView(child); |
318 gfx::Rect old_bounds = child->bounds(); | 319 gfx::Rect old_bounds = child->bounds(); |
319 if (deleting_views_.find(child) != deleting_views_.end()) | 320 if (deleting_views_.find(child) != deleting_views_.end()) |
320 deleting_views_.erase(child); | 321 deleting_views_.erase(child); |
321 if (deleted_when_done_.find(child) != deleted_when_done_.end()) | 322 if (deleted_when_done_.find(child) != deleted_when_done_.end()) |
322 deleted_when_done_.erase(child); | 323 deleted_when_done_.erase(child); |
323 delete child; | 324 delete child; |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 MessageCenterView::~MessageCenterView() { | 657 MessageCenterView::~MessageCenterView() { |
657 if (!is_closing_) | 658 if (!is_closing_) |
658 message_center_->RemoveObserver(this); | 659 message_center_->RemoveObserver(this); |
659 } | 660 } |
660 | 661 |
661 void MessageCenterView::SetNotifications( | 662 void MessageCenterView::SetNotifications( |
662 const NotificationList::Notifications& notifications) { | 663 const NotificationList::Notifications& notifications) { |
663 if (is_closing_) | 664 if (is_closing_) |
664 return; | 665 return; |
665 | 666 |
666 message_views_.clear(); | 667 notification_views_.clear(); |
667 int index = 0; | 668 int index = 0; |
668 for (NotificationList::Notifications::const_iterator iter = | 669 for (NotificationList::Notifications::const_iterator iter = |
669 notifications.begin(); iter != notifications.end(); | 670 notifications.begin(); iter != notifications.end(); |
670 ++iter, ++index) { | 671 ++iter, ++index) { |
671 AddNotificationAt(*(*iter), index); | 672 AddNotificationAt(*(*iter), index); |
672 if (message_views_.size() >= kMaxVisibleMessageCenterNotifications) | 673 if (notification_views_.size() >= kMaxVisibleMessageCenterNotifications) |
673 break; | 674 break; |
674 } | 675 } |
675 NotificationsChanged(); | 676 NotificationsChanged(); |
676 scroller_->RequestFocus(); | 677 scroller_->RequestFocus(); |
677 } | 678 } |
678 | 679 |
679 void MessageCenterView::SetSettingsVisible(bool visible) { | 680 void MessageCenterView::SetSettingsVisible(bool visible) { |
680 if (is_closing_) | 681 if (is_closing_) |
681 return; | 682 return; |
682 | 683 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
872 int index = 0; | 873 int index = 0; |
873 const NotificationList::Notifications& notifications = | 874 const NotificationList::Notifications& notifications = |
874 message_center_->GetVisibleNotifications(); | 875 message_center_->GetVisibleNotifications(); |
875 for (NotificationList::Notifications::const_iterator iter = | 876 for (NotificationList::Notifications::const_iterator iter = |
876 notifications.begin(); iter != notifications.end(); | 877 notifications.begin(); iter != notifications.end(); |
877 ++iter, ++index) { | 878 ++iter, ++index) { |
878 if ((*iter)->id() == id) { | 879 if ((*iter)->id() == id) { |
879 AddNotificationAt(*(*iter), index); | 880 AddNotificationAt(*(*iter), index); |
880 break; | 881 break; |
881 } | 882 } |
882 if (message_views_.size() >= kMaxVisibleMessageCenterNotifications) | 883 if (notification_views_.size() >= kMaxVisibleMessageCenterNotifications) |
883 break; | 884 break; |
884 } | 885 } |
885 NotificationsChanged(); | 886 NotificationsChanged(); |
886 } | 887 } |
887 | 888 |
888 void MessageCenterView::OnNotificationRemoved(const std::string& id, | 889 void MessageCenterView::OnNotificationRemoved(const std::string& id, |
889 bool by_user) { | 890 bool by_user) { |
890 for (size_t i = 0; i < message_views_.size(); ++i) { | 891 NotificationViewsMap::iterator view_iter = notification_views_.find(id); |
891 if (message_views_[i]->notification_id() == id) { | 892 if (view_iter == notification_views_.end()) |
892 if (by_user) { | 893 return; |
893 message_list_view_->SetRepositionTarget(message_views_[i]->bounds()); | 894 NotificationView* view = view_iter->second; |
894 // Moves the keyboard focus to the next notification if the removed | 895 int index = message_list_view_->GetIndexOf(view); |
895 // notification is focused so that the user can dismiss notifications | 896 if (by_user) { |
896 // without re-focusing by tab key. | 897 message_list_view_->SetRepositionTarget(view->bounds()); |
897 if (message_views_.size() > 1) { | 898 // Moves the keyboard focus to the next notification if the removed |
898 views::View* focused_view = GetFocusManager()->GetFocusedView(); | 899 // notification is focused so that the user can dismiss notifications |
899 if (message_views_[i]->IsCloseButtonFocused() || | 900 // without re-focusing by tab key. |
900 focused_view == message_views_[i]) { | 901 if (view->IsCloseButtonFocused() || |
901 size_t next_index = i + 1; | 902 view == GetFocusManager()->GetFocusedView()) { |
902 if (next_index >= message_views_.size()) | 903 views::View* next_focused_view = NULL; |
903 next_index = message_views_.size() - 2; | 904 if (message_list_view_->child_count() > index + 1) |
904 if (focused_view == message_views_[i]) | 905 next_focused_view = message_list_view_->child_at(index + 1); |
905 message_views_[next_index]->RequestFocus(); | 906 else if (index > 0) |
906 else | 907 next_focused_view = message_list_view_->child_at(index - 1); |
907 message_views_[next_index]->RequestFocusOnCloseButton(); | 908 |
908 } | 909 if (next_focused_view) { |
909 } | 910 if (view->IsCloseButtonFocused()) |
| 911 // Safe cast since all views in MessageListView are MessageViews. |
| 912 static_cast<MessageView*>( |
| 913 next_focused_view)->RequestFocusOnCloseButton(); |
| 914 else |
| 915 next_focused_view->RequestFocus(); |
910 } | 916 } |
911 message_list_view_->RemoveNotificationAt(i); | |
912 message_views_.erase(message_views_.begin() + i); | |
913 NotificationsChanged(); | |
914 break; | |
915 } | 917 } |
916 } | 918 } |
| 919 message_list_view_->RemoveNotificationAt(index); |
| 920 notification_views_.erase(view_iter); |
| 921 NotificationsChanged(); |
917 } | 922 } |
918 | 923 |
919 void MessageCenterView::OnNotificationUpdated(const std::string& id) { | 924 void MessageCenterView::OnNotificationUpdated(const std::string& id) { |
| 925 NotificationViewsMap::const_iterator view_iter = notification_views_.find(id); |
| 926 if (view_iter == notification_views_.end()) |
| 927 return; |
| 928 NotificationView* view = view_iter->second; |
| 929 size_t index = message_list_view_->GetIndexOf(view); |
| 930 DCHECK(index >= 0); |
| 931 // TODO(dimich): add MessageCenter::GetVisibleNotificationById(id) |
920 const NotificationList::Notifications& notifications = | 932 const NotificationList::Notifications& notifications = |
921 message_center_->GetVisibleNotifications(); | 933 message_center_->GetVisibleNotifications(); |
922 size_t index = 0; | |
923 for (NotificationList::Notifications::const_iterator iter = | 934 for (NotificationList::Notifications::const_iterator iter = |
924 notifications.begin(); | 935 notifications.begin(); iter != notifications.end(); ++iter) { |
925 iter != notifications.end() && index < message_views_.size(); | |
926 ++iter, ++index) { | |
927 DCHECK((*iter)->id() == message_views_[index]->notification_id()); | |
928 if ((*iter)->id() == id) { | 936 if ((*iter)->id() == id) { |
929 bool expanded = true; | 937 bool expanded = true; |
930 if (IsExperimentalNotificationUIEnabled()) | 938 if (IsExperimentalNotificationUIEnabled()) |
931 expanded = (*iter)->is_expanded(); | 939 expanded = (*iter)->is_expanded(); |
932 MessageView* view = | 940 NotificationView* view = |
933 NotificationView::Create(*(*iter), | 941 NotificationView::Create(*(*iter), |
934 message_center_, | 942 message_center_, |
935 tray_, | 943 tray_, |
936 expanded, | 944 expanded, |
937 false); // Not creating a top-level | 945 false); // Not creating a top-level |
938 // notification. | 946 // notification. |
939 view->set_scroller(scroller_); | 947 view->set_scroller(scroller_); |
940 message_list_view_->UpdateNotificationAt(view, index); | 948 message_list_view_->UpdateNotificationAt(view, index); |
941 message_views_[index] = view; | 949 notification_views_[id] = view; |
942 NotificationsChanged(); | 950 NotificationsChanged(); |
943 break; | 951 break; |
944 } | 952 } |
945 } | 953 } |
946 } | 954 } |
947 | 955 |
948 void MessageCenterView::AnimationEnded(const gfx::Animation* animation) { | 956 void MessageCenterView::AnimationEnded(const gfx::Animation* animation) { |
949 DCHECK_EQ(animation, settings_transition_animation_.get()); | 957 DCHECK_EQ(animation, settings_transition_animation_.get()); |
950 | 958 |
951 Visibility visibility = target_view_ == settings_view_ | 959 Visibility visibility = target_view_ == settings_view_ |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 AnimationEnded(animation); | 993 AnimationEnded(animation); |
986 } | 994 } |
987 | 995 |
988 void MessageCenterView::AddNotificationAt(const Notification& notification, | 996 void MessageCenterView::AddNotificationAt(const Notification& notification, |
989 int index) { | 997 int index) { |
990 // NotificationViews are expanded by default here until | 998 // NotificationViews are expanded by default here until |
991 // http://crbug.com/217902 is fixed. TODO(dharcourt): Fix. | 999 // http://crbug.com/217902 is fixed. TODO(dharcourt): Fix. |
992 bool expanded = true; | 1000 bool expanded = true; |
993 if (IsExperimentalNotificationUIEnabled()) | 1001 if (IsExperimentalNotificationUIEnabled()) |
994 expanded = notification.is_expanded(); | 1002 expanded = notification.is_expanded(); |
995 MessageView* view = | 1003 NotificationView* view = |
996 NotificationView::Create(notification, | 1004 NotificationView::Create(notification, |
997 message_center_, | 1005 message_center_, |
998 tray_, | 1006 tray_, |
999 expanded, | 1007 expanded, |
1000 false); // Not creating a top-level | 1008 false); // Not creating a top-level |
1001 // notification. | 1009 // notification. |
1002 view->set_scroller(scroller_); | 1010 view->set_scroller(scroller_); |
1003 message_views_.insert(message_views_.begin() + index, view); | 1011 notification_views_[notification.id()] = view; |
1004 message_list_view_->AddNotificationAt(view, index); | 1012 message_list_view_->AddNotificationAt(view, index); |
1005 message_center_->DisplayedNotification(notification.id()); | 1013 message_center_->DisplayedNotification(notification.id()); |
1006 } | 1014 } |
1007 | 1015 |
1008 void MessageCenterView::NotificationsChanged() { | 1016 void MessageCenterView::NotificationsChanged() { |
1009 bool no_message_views = message_views_.empty(); | 1017 bool no_message_views = notification_views_.empty(); |
1010 // All the children of this view are owned by |this|. | 1018 // All the children of this view are owned by |this|. |
1011 scroller_->contents()->RemoveAllChildViews(/*delete_children=*/false); | 1019 scroller_->contents()->RemoveAllChildViews(/*delete_children=*/false); |
1012 scroller_->contents()->AddChildView( | 1020 scroller_->contents()->AddChildView( |
1013 no_message_views ? empty_list_view_.get() : message_list_view_.get()); | 1021 no_message_views ? empty_list_view_.get() : message_list_view_.get()); |
1014 | 1022 |
1015 button_bar_->SetCloseAllButtonEnabled(!no_message_views); | 1023 button_bar_->SetCloseAllButtonEnabled(!no_message_views); |
1016 scroller_->set_focusable(!no_message_views); | 1024 scroller_->set_focusable(!no_message_views); |
1017 | 1025 |
1018 scroller_->InvalidateLayout(); | 1026 scroller_->InvalidateLayout(); |
1019 PreferredSizeChanged(); | 1027 PreferredSizeChanged(); |
1020 Layout(); | 1028 Layout(); |
1021 } | 1029 } |
1022 | 1030 |
1023 void MessageCenterView::SetNotificationViewForTest(views::View* view) { | 1031 void MessageCenterView::SetNotificationViewForTest(MessageView* view) { |
1024 message_list_view_->AddNotificationAt(view, 0); | 1032 message_list_view_->AddNotificationAt(view, 0); |
1025 } | 1033 } |
1026 | 1034 |
1027 } // namespace message_center | 1035 } // namespace message_center |
OLD | NEW |