#include "ui/message_center/message_center_tray.h"
#include "ui/message_center/message_center_types.h"
#include "ui/message_center/message_center_util.h"
+#include "ui/message_center/views/bounded_scroll_view.h"
#include "ui/message_center/views/message_center_button_bar.h"
#include "ui/message_center/views/message_view.h"
#include "ui/message_center/views/message_view_context_menu_controller.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/label.h"
-#include "ui/views/controls/scroll_view.h"
-#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/widget.h"
const SkColor kTransparentColor = SkColorSetARGB(0, 0, 0, 0);
#endif
const int kAnimateClearingNextNotificationDelayMS = 40;
-const int kMinScrollViewHeight = 100;
const int kDefaultAnimationDurationMs = 120;
const int kDefaultFrameRateHz = 60;
} // namespace
-// BoundedScrollView ///////////////////////////////////////////////////////////
-
-// A custom scroll view whose height has a minimum and maximum value and whose
-// scroll bar disappears when not needed.
-class BoundedScrollView : public views::ScrollView {
- public:
- BoundedScrollView(int min_height, int max_height);
-
- // Overridden from views::View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual int GetHeightForWidth(int width) OVERRIDE;
- virtual void Layout() OVERRIDE;
-
- private:
- int min_height_;
- int max_height_;
-
- DISALLOW_COPY_AND_ASSIGN(BoundedScrollView);
-};
-
-BoundedScrollView::BoundedScrollView(int min_height, int max_height)
- : min_height_(min_height),
- max_height_(max_height) {
- set_notify_enter_exit_on_child(true);
- set_background(
- views::Background::CreateSolidBackground(kMessageCenterBackgroundColor));
- SetVerticalScrollBar(new views::OverlayScrollBar(false));
-}
-
-gfx::Size BoundedScrollView::GetPreferredSize() {
- gfx::Size size = contents()->GetPreferredSize();
- size.SetToMax(gfx::Size(size.width(), min_height_));
- size.SetToMin(gfx::Size(size.width(), max_height_));
- gfx::Insets insets = GetInsets();
- size.Enlarge(insets.width(), insets.height());
- return size;
-}
-
-int BoundedScrollView::GetHeightForWidth(int width) {
- gfx::Insets insets = GetInsets();
- width = std::max(0, width - insets.width());
- int height = contents()->GetHeightForWidth(width) + insets.height();
- return std::min(std::max(height, min_height_), max_height_);
-}
-
-void BoundedScrollView::Layout() {
- int content_width = width();
- int content_height = contents()->GetHeightForWidth(content_width);
- if (content_height > height()) {
- content_width = std::max(content_width - GetScrollBarWidth(), 0);
- content_height = contents()->GetHeightForWidth(content_width);
- }
- if (contents()->bounds().size() != gfx::Size(content_width, content_height))
- contents()->SetBounds(0, 0, content_width, content_height);
- views::ScrollView::Layout();
-}
-
class NoNotificationMessageView : public views::View {
public:
NoNotificationMessageView();
virtual ~MessageListView();
void AddNotificationAt(MessageView* view, int i);
- void RemoveNotificationAt(int i);
- void UpdateNotificationAt(MessageView* view, int i);
+ void RemoveNotification(MessageView* view);
+ void UpdateNotification(MessageView* view, MessageView* new_view);
void SetRepositionTarget(const gfx::Rect& target_rect);
void ResetRepositionSession();
void ClearAllNotifications(const gfx::Rect& visible_scroll_rect);
virtual void OnBoundsAnimatorDone(views::BoundsAnimator* animator) OVERRIDE;
private:
- // Returns the actual index for child of |index|.
- // MessageListView allows to slide down upper notifications, which means
- // that the upper ones should come above the lower ones if top_down is not
- // enabled. To achieve this, inversed order is adopted. The top most
- // notification is the last child, and the bottom most notification is the
- // first child.
- int GetActualIndex(int index);
bool IsValidChild(views::View* child);
void DoUpdateIfPossible();
}
}
-void MessageListView::AddNotificationAt(MessageView* view, int i) {
- AddChildViewAt(view, GetActualIndex(i));
+void MessageListView::AddNotificationAt(MessageView* view, int index) {
+ // |index| refers to a position in a subset of valid children. |real_index|
+ // in a list includes the invalid children, so we compute the real index by
+ // walking the list until |index| number of valid children are encountered,
+ // or to the end of the list.
+ int real_index = 0;
+ while (real_index < child_count()) {
+ if (IsValidChild(child_at(real_index))) {
+ --index;
+ if (index < 0)
+ break;
+ }
+ ++real_index;
+ }
+
+ AddChildViewAt(view, real_index);
if (GetContentsBounds().IsEmpty())
return;
DoUpdateIfPossible();
}
-void MessageListView::RemoveNotificationAt(int i) {
- views::View* child = child_at(GetActualIndex(i));
+void MessageListView::RemoveNotification(MessageView* view) {
+ DCHECK_EQ(view->parent(), this);
if (GetContentsBounds().IsEmpty()) {
- delete child;
+ delete view;
} else {
- if (child->layer()) {
- deleting_views_.insert(child);
+ if (view->layer()) {
+ deleting_views_.insert(view);
} else {
if (animator_.get())
- animator_->StopAnimatingView(child);
- delete child;
+ animator_->StopAnimatingView(view);
+ delete view;
}
DoUpdateIfPossible();
}
}
-void MessageListView::UpdateNotificationAt(MessageView* view, int i) {
- int actual_index = GetActualIndex(i);
- views::View* child = child_at(actual_index);
+void MessageListView::UpdateNotification(MessageView* view,
+ MessageView* new_view) {
+ int index = GetIndexOf(view);
+ DCHECK_LE(0, index); // GetIndexOf is negative if not a child.
+
if (animator_.get())
- animator_->StopAnimatingView(child);
- gfx::Rect old_bounds = child->bounds();
- if (deleting_views_.find(child) != deleting_views_.end())
- deleting_views_.erase(child);
- if (deleted_when_done_.find(child) != deleted_when_done_.end())
- deleted_when_done_.erase(child);
- delete child;
- AddChildViewAt(view, actual_index);
- view->SetBounds(old_bounds.x(), old_bounds.y(), old_bounds.width(),
- view->GetHeightForWidth(old_bounds.width()));
+ animator_->StopAnimatingView(view);
+ gfx::Rect old_bounds = view->bounds();
+ if (deleting_views_.find(view) != deleting_views_.end())
+ deleting_views_.erase(view);
+ if (deleted_when_done_.find(view) != deleted_when_done_.end())
+ deleted_when_done_.erase(view);
+ delete view;
+ AddChildViewAt(new_view, index);
+ new_view->SetBounds(old_bounds.x(),
+ old_bounds.y(),
+ old_bounds.width(),
+ new_view->GetHeightForWidth(old_bounds.width()));
DoUpdateIfPossible();
}
GetWidget()->SynthesizeMouseMoveEvent();
}
-int MessageListView::GetActualIndex(int index) {
- for (int i = 0; i < child_count() && i <= index; ++i)
- index += IsValidChild(child_at(i)) ? 0 : 1;
- return std::min(index, child_count());
-}
-
bool MessageListView::IsValidChild(views::View* child) {
return child->visible() &&
deleting_views_.find(child) == deleting_views_.end() &&
return;
NotificationView* view = view_iter->second;
int index = message_list_view_->GetIndexOf(view);
+ DCHECK_LE(0, index);
if (by_user) {
message_list_view_->SetRepositionTarget(view->bounds());
// Moves the keyboard focus to the next notification if the removed
}
}
}
- message_list_view_->RemoveNotificationAt(index);
+ message_list_view_->RemoveNotification(view);
notification_views_.erase(view_iter);
NotificationsChanged();
}
if (view_iter == notification_views_.end())
return;
NotificationView* view = view_iter->second;
- size_t index = message_list_view_->GetIndexOf(view);
- DCHECK(index >= 0);
// TODO(dimich): add MessageCenter::GetVisibleNotificationById(id)
const NotificationList::Notifications& notifications =
message_center_->GetVisibleNotifications();
for (NotificationList::Notifications::const_iterator iter =
notifications.begin(); iter != notifications.end(); ++iter) {
if ((*iter)->id() == id) {
- bool expanded = true;
- if (IsExperimentalNotificationUIEnabled())
- expanded = (*iter)->is_expanded();
- NotificationView* view =
+ NotificationView* new_view =
NotificationView::Create(this,
*(*iter),
- expanded,
false); // Not creating a top-level
// notification.
- view->set_context_menu_controller(context_menu_controller_.get());
- view->set_scroller(scroller_);
- message_list_view_->UpdateNotificationAt(view, index);
- notification_views_[id] = view;
+ new_view->set_context_menu_controller(context_menu_controller_.get());
+ new_view->set_scroller(scroller_);
+ message_list_view_->UpdateNotification(view, new_view);
+ notification_views_[id] = new_view;
NotificationsChanged();
break;
}
message_center_->ClickOnNotificationButton(notification_id, button_index);
}
-void MessageCenterView::ExpandNotification(const std::string& notification_id) {
- message_center_->ExpandNotification(notification_id);
-}
-
void MessageCenterView::AnimationEnded(const gfx::Animation* animation) {
DCHECK_EQ(animation, settings_transition_animation_.get());
AnimationEnded(animation);
}
-
-void MessageCenterView::AddMessageViewAt(MessageView* view, int index) {
- view->set_scroller(scroller_);
- message_list_view_->AddNotificationAt(view, index);
-}
-
void MessageCenterView::AddNotificationAt(const Notification& notification,
int index) {
- // NotificationViews are expanded by default here until
- // http://crbug.com/217902 is fixed. TODO(dharcourt): Fix.
- bool expanded = true;
- if (IsExperimentalNotificationUIEnabled())
- expanded = notification.is_expanded();
NotificationView* view =
- NotificationView::Create(this,
- notification,
- expanded,
- false); // Not creating a top-level
- // notification.
+ NotificationView::Create(this, notification, false); // Not top-level.
view->set_context_menu_controller(context_menu_controller_.get());
notification_views_[notification.id()] = view;
- AddMessageViewAt(view, index);
+ view->set_scroller(scroller_);
+ message_list_view_->AddNotificationAt(view, index);
}
void MessageCenterView::NotificationsChanged() {