diff options
author | mukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-20 17:13:58 +0000 |
---|---|---|
committer | mukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-20 17:13:58 +0000 |
commit | 940c2ba4b46ca1c2f9e0667c3d9b24df3bf0cb11 (patch) | |
tree | 5f7acce00663f51e8b2004fad5f7edbfdae546a8 /ui/message_center/views | |
parent | 8d7cea57d5969811a59125d201d7bb6bd02967cd (diff) | |
download | chromium_src-940c2ba4b46ca1c2f9e0667c3d9b24df3bf0cb11.zip chromium_src-940c2ba4b46ca1c2f9e0667c3d9b24df3bf0cb11.tar.gz chromium_src-940c2ba4b46ca1c2f9e0667c3d9b24df3bf0cb11.tar.bz2 |
Introduces a new settings UI in the center.
BUG=245869
R=dewittj@chromium.org, rsesek@chromium.org
TEST=manually / don't break existing tests
Review URL: https://chromiumcodereview.appspot.com/16867003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207466 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/message_center/views')
18 files changed, 378 insertions, 187 deletions
diff --git a/ui/message_center/views/message_bubble_base.cc b/ui/message_center/views/message_bubble_base.cc index edded47..11a6e3b 100644 --- a/ui/message_center/views/message_bubble_base.cc +++ b/ui/message_center/views/message_bubble_base.cc @@ -22,8 +22,10 @@ namespace message_center { const SkColor MessageBubbleBase::kBackgroundColor = SkColorSetRGB(0xfe, 0xfe, 0xfe); -MessageBubbleBase::MessageBubbleBase(MessageCenter* message_center) +MessageBubbleBase::MessageBubbleBase(MessageCenter* message_center, + MessageCenterTray* tray) : message_center_(message_center), + tray_(tray), bubble_view_(NULL), weak_ptr_factory_(this), max_height_(kMessageBubbleBaseDefaultMaxHeight) { diff --git a/ui/message_center/views/message_bubble_base.h b/ui/message_center/views/message_bubble_base.h index 47656c2..27d2e51 100644 --- a/ui/message_center/views/message_bubble_base.h +++ b/ui/message_center/views/message_bubble_base.h @@ -11,10 +11,11 @@ #include "ui/views/bubble/tray_bubble_view.h" namespace message_center { +class MessageCenterTray; class MESSAGE_CENTER_EXPORT MessageBubbleBase { public: - explicit MessageBubbleBase(MessageCenter* message_center); + MessageBubbleBase(MessageCenter* message_center, MessageCenterTray* tray); virtual ~MessageBubbleBase(); @@ -60,12 +61,14 @@ class MESSAGE_CENTER_EXPORT MessageBubbleBase { views::TrayBubbleView::InitParams GetDefaultInitParams( views::TrayBubbleView::AnchorAlignment anchor_alignment); MessageCenter* message_center() { return message_center_; } + MessageCenterTray* tray() { return tray_; } void set_bubble_view(views::TrayBubbleView* bubble_view) { bubble_view_ = bubble_view; } private: MessageCenter* message_center_; + MessageCenterTray* tray_; views::TrayBubbleView* bubble_view_; base::WeakPtrFactory<MessageBubbleBase> weak_ptr_factory_; int max_height_; diff --git a/ui/message_center/views/message_center_bubble.cc b/ui/message_center/views/message_center_bubble.cc index a0d8646..8ef7a72 100644 --- a/ui/message_center/views/message_center_bubble.cc +++ b/ui/message_center/views/message_center_bubble.cc @@ -57,14 +57,23 @@ void ContentsView::ChildPreferredSizeChanged(View* child) { // MessageCenterBubble ///////////////////////////////////////////////////////// -MessageCenterBubble::MessageCenterBubble(MessageCenter* message_center) - : MessageBubbleBase(message_center), - message_center_view_(NULL) { +MessageCenterBubble::MessageCenterBubble(MessageCenter* message_center, + MessageCenterTray* tray) + : MessageBubbleBase(message_center, tray), + message_center_view_(NULL), + initially_settings_visible_(false) { } MessageCenterBubble::~MessageCenterBubble() { } +void MessageCenterBubble::SetSettingsVisible() { + if (message_center_view_) + message_center_view_->SetSettingsVisible(true); + else + initially_settings_visible_ = true; +} + views::TrayBubbleView::InitParams MessageCenterBubble::GetInitParams( views::TrayBubbleView::AnchorAlignment anchor_alignment) { views::TrayBubbleView::InitParams init_params = @@ -81,7 +90,8 @@ views::TrayBubbleView::InitParams MessageCenterBubble::GetInitParams( void MessageCenterBubble::InitializeContents( views::TrayBubbleView* new_bubble_view) { set_bubble_view(new_bubble_view); - message_center_view_ = new MessageCenterView(message_center(), max_height()); + message_center_view_ = new MessageCenterView( + message_center(), tray(), max_height(), initially_settings_visible_); bubble_view()->AddChildView(new ContentsView(this, message_center_view_)); // Resize the content of the bubble view to the given bubble size. This is // necessary in case of the bubble border forcing a bigger size then the diff --git a/ui/message_center/views/message_center_bubble.h b/ui/message_center/views/message_center_bubble.h index f5b3850..5b67c21 100644 --- a/ui/message_center/views/message_center_bubble.h +++ b/ui/message_center/views/message_center_bubble.h @@ -18,10 +18,12 @@ class MESSAGE_CENTER_EXPORT MessageCenterBubble : public MessageBubbleBase, public base::SupportsWeakPtr<MessageCenterBubble> { public: - explicit MessageCenterBubble(MessageCenter* message_center); + MessageCenterBubble(MessageCenter* message_center, MessageCenterTray* tray); virtual ~MessageCenterBubble(); + void SetSettingsVisible(); + // Overridden from MessageBubbleBase: virtual views::TrayBubbleView::InitParams GetInitParams( views::TrayBubbleView::AnchorAlignment anchor_alignment) OVERRIDE; @@ -39,6 +41,9 @@ class MESSAGE_CENTER_EXPORT MessageCenterBubble // The maximum height int max_height_; + // Use settings view as the initially visible content if true. + bool initially_settings_visible_; + DISALLOW_COPY_AND_ASSIGN(MessageCenterBubble); }; diff --git a/ui/message_center/views/message_center_view.cc b/ui/message_center/views/message_center_view.cc index b9a7b90..227c227 100644 --- a/ui/message_center/views/message_center_view.cc +++ b/ui/message_center/views/message_center_view.cc @@ -9,6 +9,7 @@ #include "base/stl_util.h" #include "grit/ui_resources.h" #include "grit/ui_strings.h" +#include "ui/base/animation/multi_animation.h" #include "ui/base/animation/slide_animation.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -20,9 +21,11 @@ #include "ui/gfx/text_constants.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_style.h" +#include "ui/message_center/message_center_tray.h" #include "ui/message_center/message_center_util.h" #include "ui/message_center/views/message_view.h" #include "ui/message_center/views/notification_view.h" +#include "ui/message_center/views/notifier_settings_view.h" #include "ui/views/animation/bounds_animator.h" #include "ui/views/animation/bounds_animator_observer.h" #include "ui/views/background.h" @@ -51,6 +54,9 @@ const SkColor kTransparentColor = SkColorSetARGB(0, 0, 0, 0); const SkColor kButtonTextHighlightColor = SkColorSetRGB(0x2a, 0x2a, 0x2a); const SkColor kButtonTextHoverColor = SkColorSetRGB(0x2a, 0x2a, 0x2a); +static const int kDefaultFrameRateHz = 60; +static const int kDefaultAnimationDurationMs = 120; + // PoorMessageCenterButtonBar ////////////////////////////////////////////////// // The view for the buttons at the bottom of the message center window used @@ -181,12 +187,11 @@ class RichMessageCenterButtonBar : public MessageCenterButtonBar, RichMessageCenterButtonBar::RichMessageCenterButtonBar( MessageCenter* message_center) - : MessageCenterButtonBar(message_center) { + : MessageCenterButtonBar(message_center) { + if (get_use_acceleration_when_possible()) + SetPaintToLayer(true); set_background(views::Background::CreateSolidBackground( kMessageCenterBackgroundColor)); - set_border(views::Border::CreateSolidSidedBorder( - 1, 0, 0, 0, kFooterDelimiterColor)); - views::Label* notification_label = new views::Label(l10n_util::GetStringUTF16( IDS_MESSAGE_CENTER_FOOTER_TITLE)); @@ -262,8 +267,8 @@ void RichMessageCenterButtonBar::ButtonPressed(views::Button* sender, if (sender == close_all_button()) { message_center()->RemoveAllNotifications(true); // Action by user. } else if (sender == settings_button_) { - message_center()->ShowNotificationSettingsDialog( - GetWidget()->GetNativeView()); + MessageCenterView* center_view = static_cast<MessageCenterView*>(parent()); + center_view->SetSettingsVisible(!center_view->settings_visible()); } else if (sender == quiet_mode_button_) { if (message_center()->IsQuietMode()) message_center()->SetQuietMode(false); @@ -739,14 +744,16 @@ void MessageCenterButtonBar::SetCloseAllVisible(bool visible) { // MessageCenterView /////////////////////////////////////////////////////////// MessageCenterView::MessageCenterView(MessageCenter* message_center, - int max_height) - : message_center_(message_center) { + MessageCenterTray* tray, + int max_height, + bool initially_settings_visible) + : message_center_(message_center), + tray_(tray), + settings_visible_(initially_settings_visible) { message_center_->AddObserver(this); set_notify_enter_exit_on_child(true); - int between_child = IsRichNotificationEnabled() ? 0 : 1; - SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, between_child)); - + set_background(views::Background::CreateSolidBackground( + kMessageCenterBackgroundColor)); if (IsRichNotificationEnabled()) button_bar_ = new RichMessageCenterButtonBar(message_center); @@ -772,7 +779,16 @@ MessageCenterView::MessageCenterView(MessageCenter* message_center, message_list_view_->AddChildView(no_notifications_message_view_); scroller_->SetContents(message_list_view_); + settings_view_ = new NotifierSettingsView( + message_center_->GetNotifierSettingsProvider()); + + if (initially_settings_visible) + scroller_->SetVisible(false); + else + settings_view_->SetVisible(false); + AddChildView(scroller_); + AddChildView(settings_view_); AddChildView(button_bar_); } @@ -795,17 +811,127 @@ void MessageCenterView::SetNotifications( scroller_->RequestFocus(); } +void MessageCenterView::SetSettingsVisible(bool visible) { + if (visible == settings_visible_) + return; + + settings_visible_ = visible; + + if (visible) { + source_view_ = scroller_; + target_view_ = settings_view_; + } else { + source_view_ = settings_view_; + target_view_ = scroller_; + } + source_height_ = source_view_->GetHeightForWidth(width()); + target_height_ = target_view_->GetHeightForWidth(width()); + + ui::MultiAnimation::Parts parts; + // First part: slide resize animation. + parts.push_back(ui::MultiAnimation::Part( + (source_height_ == target_height_) ? 0 : kDefaultAnimationDurationMs, + ui::Tween::EASE_OUT)); + // Second part: fade-out the source_view. + if (source_view_->layer()) { + parts.push_back(ui::MultiAnimation::Part( + kDefaultAnimationDurationMs, ui::Tween::LINEAR)); + } else { + parts.push_back(ui::MultiAnimation::Part()); + } + // Third part: fade-in the target_view. + if (target_view_->layer()) { + parts.push_back(ui::MultiAnimation::Part( + kDefaultAnimationDurationMs, ui::Tween::LINEAR)); + target_view_->layer()->SetOpacity(0); + target_view_->SetVisible(true); + } else { + parts.push_back(ui::MultiAnimation::Part()); + } + settings_transition_animation_.reset(new ui::MultiAnimation( + parts, base::TimeDelta::FromMicroseconds(1000000 / kDefaultFrameRateHz))); + settings_transition_animation_->set_delegate(this); + settings_transition_animation_->set_continuous(false); + settings_transition_animation_->Start(); +} + size_t MessageCenterView::NumMessageViewsForTest() const { return message_list_view_->child_count(); } void MessageCenterView::Layout() { - scroller_->SetBounds(0, 0, width(), scroller_->GetHeightForWidth(width())); - views::View::Layout(); + int between_child = IsRichNotificationEnabled() ? 0 : 1; + int button_height = button_bar_->GetHeightForWidth(width()); + // Skip unnecessary re-layout of contents during the resize animation. + if (settings_transition_animation_ && + settings_transition_animation_->is_animating() && + settings_transition_animation_->current_part_index() == 0) { + button_bar_->SetBounds(0, height() - button_height, width(), button_height); + return; + } + + scroller_->SetBounds(0, 0, width(), height() - button_height - between_child); + settings_view_->SetBounds( + 0, 0, width(), height() - button_height - between_child); + + bool is_scrollable = false; + if (scroller_->visible()) + is_scrollable = scroller_->height() < message_list_view_->height(); + else + is_scrollable = settings_view_->IsScrollable(); + + if (is_scrollable && !button_bar_->border()) { + button_bar_->set_border(views::Border::CreateSolidSidedBorder( + 1, 0, 0, 0, kFooterDelimiterColor)); + button_bar_->SchedulePaint(); + } else if (!is_scrollable && button_bar_->border()) { + button_bar_->set_border(NULL); + button_bar_->SchedulePaint(); + } + + button_bar_->SetBounds(0, height() - button_height, width(), button_height); if (GetWidget()) GetWidget()->GetRootView()->SchedulePaint(); } +gfx::Size MessageCenterView::GetPreferredSize() { + if (settings_transition_animation_ && + settings_transition_animation_->is_animating()) { + int content_width = std::max(source_view_->GetPreferredSize().width(), + target_view_->GetPreferredSize().width()); + int width = std::max(content_width, + button_bar_->GetPreferredSize().width()); + return gfx::Size(width, GetHeightForWidth(width)); + } + + int width = 0; + for (int i = 0; i < child_count(); ++i) { + views::View* child = child_at(0); + if (child->visible()) + width = std::max(width, child->GetPreferredSize().width()); + } + return gfx::Size(width, GetHeightForWidth(width)); +} + +int MessageCenterView::GetHeightForWidth(int width) { + if (settings_transition_animation_ && + settings_transition_animation_->is_animating()) { + int content_height = target_height_; + if (settings_transition_animation_->current_part_index() == 0) { + content_height = settings_transition_animation_->CurrentValueBetween( + source_height_, target_height_); + } + return button_bar_->GetHeightForWidth(width) + content_height; + } + + int content_height = 0; + if (scroller_->visible()) + content_height += scroller_->GetHeightForWidth(width); + else + content_height += settings_view_->GetHeightForWidth(width); + return button_bar_->GetHeightForWidth(width) + content_height; +} + bool MessageCenterView::OnMouseWheel(const ui::MouseWheelEvent& event) { // Do not rely on the default scroll event handler of ScrollView because // the scroll happens only when the focus is on the ScrollView. The @@ -882,6 +1008,7 @@ void MessageCenterView::OnNotificationUpdated(const std::string& id) { MessageView* view = NotificationView::Create(*(*iter), message_center_, + tray_, true, // Create expanded. false); // Not creating a top-level // notification. @@ -894,6 +1021,41 @@ void MessageCenterView::OnNotificationUpdated(const std::string& id) { } } +void MessageCenterView::AnimationEnded(const ui::Animation* animation) { + DCHECK_EQ(animation, settings_transition_animation_.get()); + + source_view_->SetVisible(false); + target_view_->SetVisible(true); + if (source_view_->layer()) + source_view_->layer()->SetOpacity(1.0); + if (target_view_->layer()) + target_view_->layer()->SetOpacity(1.0); + settings_transition_animation_.reset(); + PreferredSizeChanged(); + Layout(); +} + +void MessageCenterView::AnimationProgressed(const ui::Animation* animation) { + DCHECK_EQ(animation, settings_transition_animation_.get()); + PreferredSizeChanged(); + if (settings_transition_animation_->current_part_index() == 1 && + source_view_->layer()) { + source_view_->layer()->SetOpacity( + 1.0 - settings_transition_animation_->GetCurrentValue()); + SchedulePaint(); + } else if (settings_transition_animation_->current_part_index() == 2 && + target_view_->layer()) { + target_view_->layer()->SetOpacity( + settings_transition_animation_->GetCurrentValue()); + SchedulePaint(); + } +} + +void MessageCenterView::AnimationCanceled(const ui::Animation* animation) { + DCHECK_EQ(animation, settings_transition_animation_.get()); + AnimationEnded(animation); +} + void MessageCenterView::AddNotificationAt(const Notification& notification, int index) { // NotificationViews are expanded by default here until @@ -901,6 +1063,7 @@ void MessageCenterView::AddNotificationAt(const Notification& notification, MessageView* view = NotificationView::Create(notification, message_center_, + tray_, true, // Create expanded. false); // Not creating a top-level // notification. diff --git a/ui/message_center/views/message_center_view.h b/ui/message_center/views/message_center_view.h index aa8b2e4..aa6d44d 100644 --- a/ui/message_center/views/message_center_view.h +++ b/ui/message_center/views/message_center_view.h @@ -2,15 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_VIEWS_H_ -#define UI_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_VIEWS_H_ +#ifndef UI_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_VIEW_H_ +#define UI_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_VIEW_H_ #include "ui/views/view.h" +#include "ui/base/animation/animation_delegate.h" #include "ui/message_center/message_center_export.h" #include "ui/message_center/message_center_observer.h" #include "ui/message_center/notification_list.h" +namespace ui { +class MultiAnimation; +} // namespace ui + namespace views { class Button; } // namespace views @@ -19,8 +24,10 @@ namespace message_center { class MessageCenter; class MessageCenterBubble; +class MessageCenterTray; class MessageView; class MessageListView; +class NotifierSettingsView; // MessageCenterButtonBar ////////////////////////////////////////////////////// @@ -34,7 +41,9 @@ class MessageCenterButtonBar : public views::View { void SetCloseAllVisible(bool visible); protected: + MessageCenter* message_center() { return message_center_; } + MessageCenterTray* tray() { return tray_; } views::Button* close_all_button() { return close_all_button_; } void set_close_all_button(views::Button* button) { close_all_button_ = button; @@ -42,6 +51,7 @@ class MessageCenterButtonBar : public views::View { private: MessageCenter* message_center_; // Weak reference. + MessageCenterTray* tray_; // Weak reference. views::Button* close_all_button_; DISALLOW_COPY_AND_ASSIGN(MessageCenterButtonBar); @@ -50,18 +60,27 @@ class MessageCenterButtonBar : public views::View { // MessageCenterView /////////////////////////////////////////////////////////// class MESSAGE_CENTER_EXPORT MessageCenterView : public views::View, - public MessageCenterObserver { + public MessageCenterObserver, + public ui::AnimationDelegate { public: - MessageCenterView(MessageCenter* message_center, int max_height); + MessageCenterView(MessageCenter* message_center, + MessageCenterTray* tray, + int max_height, + bool initially_settings_visible); virtual ~MessageCenterView(); void SetNotifications(const NotificationList::Notifications& notifications); size_t NumMessageViewsForTest() const; + void SetSettingsVisible(bool visible); + bool settings_visible() const { return settings_visible_; } + protected: // Overridden from views::View: virtual void Layout() OVERRIDE; + virtual gfx::Size GetPreferredSize() OVERRIDE; + virtual int GetHeightForWidth(int width) OVERRIDE; virtual bool OnMouseWheel(const ui::MouseWheelEvent& event) OVERRIDE; virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; @@ -71,6 +90,11 @@ class MESSAGE_CENTER_EXPORT MessageCenterView : public views::View, bool by_user) OVERRIDE; virtual void OnNotificationUpdated(const std::string& id) OVERRIDE; + // Overridden from ui::AnimationDelegate: + virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; + virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; + virtual void AnimationCanceled(const ui::Animation* animation) OVERRIDE; + private: friend class MessageCenterViewTest; @@ -79,15 +103,25 @@ class MESSAGE_CENTER_EXPORT MessageCenterView : public views::View, void SetNotificationViewForTest(views::View* view); MessageCenter* message_center_; // Weak reference. + MessageCenterTray* tray_; // Weak reference. std::vector<MessageView*> message_views_; views::ScrollView* scroller_; MessageListView* message_list_view_; + NotifierSettingsView* settings_view_; MessageCenterButtonBar* button_bar_; views::View* no_notifications_message_view_; + // Data for transition animation between settings view and message list. + bool settings_visible_; + views::View* source_view_; + views::View* target_view_; + int source_height_; + int target_height_; + scoped_ptr<ui::MultiAnimation> settings_transition_animation_; + DISALLOW_COPY_AND_ASSIGN(MessageCenterView); }; } // namespace message_center -#endif // UI_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_VIEWS_H_ +#endif // UI_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_VIEW_H_ diff --git a/ui/message_center/views/message_center_view_unittest.cc b/ui/message_center/views/message_center_view_unittest.cc index e7bb7bf..449503d 100644 --- a/ui/message_center/views/message_center_view_unittest.cc +++ b/ui/message_center/views/message_center_view_unittest.cc @@ -59,7 +59,7 @@ MockNotificationView::MockNotificationView(const Notification& notification, MessageCenter* message_center, Test* test, int view_id) - : NotificationView(notification, message_center, true), + : NotificationView(notification, message_center, NULL, true), test_(test), id_(view_id) { } @@ -142,7 +142,8 @@ void MessageCenterViewTest::SetUp() { notifications.insert(¬ification); // Then create a new MessageCenterView with that single notification. - message_center_view_.reset(new MessageCenterView(&message_center_, 100)); + message_center_view_.reset(new MessageCenterView( + &message_center_, NULL, 100, false)); message_center_view_->SetNotifications(notifications); // Remove and delete the NotificationView now owned by the MessageCenterView's diff --git a/ui/message_center/views/message_popup_bubble.cc b/ui/message_center/views/message_popup_bubble.cc index 55f0f7a5..81bfd18 100644 --- a/ui/message_center/views/message_popup_bubble.cc +++ b/ui/message_center/views/message_popup_bubble.cc @@ -67,6 +67,7 @@ void PopupBubbleContentsView::Update( content_->AddChildView( NotificationView::Create(*(*iter), message_center_, + NULL, true, // Create expanded. false)); // Not creating a top-level // notification. @@ -130,7 +131,7 @@ void MessagePopupBubble::AutocloseTimer::Suspend() { // MessagePopupBubble MessagePopupBubble::MessagePopupBubble(MessageCenter* message_center) - : MessageBubbleBase(message_center), + : MessageBubbleBase(message_center, NULL), contents_view_(NULL) { } diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc index e5c3e0c..c546a61 100644 --- a/ui/message_center/views/message_popup_collection.cc +++ b/ui/message_center/views/message_popup_collection.cc @@ -43,9 +43,11 @@ const int kToastMargin = kMarginBetweenItems; } // namespace. MessagePopupCollection::MessagePopupCollection(gfx::NativeView parent, - MessageCenter* message_center) + MessageCenter* message_center, + MessageCenterTray* tray) : parent_(parent), message_center_(message_center), + tray_(tray), defer_counter_(0), latest_toast_entered_(NULL), user_is_closing_toasts_by_clicking_(false) { @@ -98,6 +100,7 @@ void MessagePopupCollection::UpdateWidgets() { MessageView* view = NotificationView::Create(*(*iter), message_center_, + tray_, true, // Create expanded. true); // Create top-level notification. int view_height = ToastContentsView::GetToastSizeForView(view).height(); @@ -292,6 +295,7 @@ void MessagePopupCollection::OnNotificationUpdated( MessageView* view = NotificationView::Create(*(*iter), message_center_, + tray_, true, // Create expanded. true); // Create top-level notification. (*toast_iter)->SetContents(view); diff --git a/ui/message_center/views/message_popup_collection.h b/ui/message_center/views/message_popup_collection.h index c4a6594..0e978b2 100644 --- a/ui/message_center/views/message_popup_collection.h +++ b/ui/message_center/views/message_popup_collection.h @@ -38,6 +38,7 @@ class MessagePopupCollectionWidgetsTest; } class MessageCenter; +class MessageCenterTray; class ToastContentsView; // Container for popup toasts. Because each toast is a frameless window rather @@ -52,7 +53,8 @@ class MESSAGE_CENTER_EXPORT MessagePopupCollection // |parent| specifies the parent widget of the toast windows. The default // parent will be used for NULL. MessagePopupCollection(gfx::NativeView parent, - MessageCenter* message_center); + MessageCenter* message_center, + MessageCenterTray* tray); virtual ~MessagePopupCollection(); // Called by ToastContentsView when its window is closed. @@ -126,6 +128,7 @@ class MESSAGE_CENTER_EXPORT MessagePopupCollection gfx::NativeView parent_; MessageCenter* message_center_; + MessageCenterTray* tray_; Toasts toasts_; gfx::Rect work_area_; diff --git a/ui/message_center/views/message_popup_collection_unittest.cc b/ui/message_center/views/message_popup_collection_unittest.cc index 7bfb802..311651d 100644 --- a/ui/message_center/views/message_popup_collection_unittest.cc +++ b/ui/message_center/views/message_popup_collection_unittest.cc @@ -25,7 +25,7 @@ class MessagePopupCollectionTest : public views::ViewsTestBase { views::ViewsTestBase::SetUp(); MessageCenter::Initialize(); collection_.reset( - new MessagePopupCollection(GetContext(), MessageCenter::Get())); + new MessagePopupCollection(GetContext(), MessageCenter::Get(), NULL)); // This size fits test machines resolution and also can keep a few toasts // w/o ill effects of hitting the screen overflow. This allows us to assume // and verify normal layout of the toast stack. diff --git a/ui/message_center/views/message_simple_view.cc b/ui/message_center/views/message_simple_view.cc index 41a87b4..5f51c50 100644 --- a/ui/message_center/views/message_simple_view.cc +++ b/ui/message_center/views/message_simple_view.cc @@ -23,7 +23,7 @@ const SkColor kNotificationReadColor = SkColorSetRGB(0xfa, 0xfa, 0xfa); MessageSimpleView::MessageSimpleView(const Notification& notification, MessageCenter* message_center) - : MessageView(notification, message_center, false) { + : MessageView(notification, message_center, NULL, false) { set_focusable(true); views::ImageButton* close = new views::ImageButton(this); close->SetImage( diff --git a/ui/message_center/views/message_view.cc b/ui/message_center/views/message_view.cc index 382124c..18f146c 100644 --- a/ui/message_center/views/message_view.cc +++ b/ui/message_center/views/message_view.cc @@ -16,6 +16,7 @@ #include "ui/gfx/skia_util.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_style.h" +#include "ui/message_center/message_center_tray.h" #include "ui/message_center/message_center_util.h" #include "ui/views/context_menu_controller.h" #include "ui/views/controls/button/image_button.h" @@ -203,6 +204,7 @@ class MenuModel : public ui::SimpleMenuModel, public ui::SimpleMenuModel::Delegate { public: MenuModel(message_center::MessageCenter* message_center, + message_center::MessageCenterTray* tray, const std::string& notification_id, const string16& display_source, const std::string& extension_id); @@ -219,17 +221,20 @@ class MenuModel : public ui::SimpleMenuModel, private: message_center::MessageCenter* message_center_; // Weak reference. + message_center::MessageCenterTray* tray_; // Weak reference. std::string notification_id_; DISALLOW_COPY_AND_ASSIGN(MenuModel); }; MenuModel::MenuModel(message_center::MessageCenter* message_center, + message_center::MessageCenterTray* tray, const std::string& notification_id, const string16& display_source, const std::string& extension_id) : ui::SimpleMenuModel(this), message_center_(message_center), + tray_(tray), notification_id_(notification_id) { // Add 'disable notifications' menu item. if (!extension_id.empty() && !display_source.empty()) { @@ -277,8 +282,9 @@ void MenuModel::ExecuteCommand(int command_id, int event_flags) { message_center_->DisableNotificationsByUrl(notification_id_); break; case kShowSettingsCommand: - if (message_center::IsRichNotificationEnabled()) - message_center_->ShowNotificationSettingsDialog(NULL); + // |tray_| may be NULL in tests. + if (message_center::IsRichNotificationEnabled() && tray_) + tray_->ShowNotifierSettingsBubble(); else message_center_->ShowNotificationSettings(notification_id_); break; @@ -294,7 +300,8 @@ namespace message_center { class MessageViewContextMenuController : public views::ContextMenuController { public: MessageViewContextMenuController( - message_center::MessageCenter* message_center, + MessageCenter* message_center, + MessageCenterTray* tray, const Notification& notification); virtual ~MessageViewContextMenuController(); @@ -304,16 +311,19 @@ class MessageViewContextMenuController : public views::ContextMenuController { const gfx::Point& point, ui::MenuSourceType source_type) OVERRIDE; - message_center::MessageCenter* message_center_; + MessageCenter* message_center_; // Weak reference. + MessageCenterTray* tray_; // Weak reference. std::string notification_id_; string16 display_source_; std::string extension_id_; }; MessageViewContextMenuController::MessageViewContextMenuController( - message_center::MessageCenter* message_center, + MessageCenter* message_center, + MessageCenterTray* tray, const Notification& notification) : message_center_(message_center), + tray_(tray), notification_id_(notification.id()), display_source_(notification.display_source()), extension_id_(notification.extension_id()) { @@ -326,7 +336,7 @@ void MessageViewContextMenuController::ShowContextMenuForView( views::View* source, const gfx::Point& point, ui::MenuSourceType source_type) { - MenuModel menu_model(message_center_, notification_id_, + MenuModel menu_model(message_center_, tray_, notification_id_, display_source_, extension_id_); if (menu_model.GetItemCount() == 0) return; @@ -344,11 +354,12 @@ void MessageViewContextMenuController::ShowContextMenuForView( MessageView::MessageView(const Notification& notification, MessageCenter* message_center, + MessageCenterTray* tray, bool expanded) : message_center_(message_center), notification_id_(notification.id()), context_menu_controller_(new MessageViewContextMenuController( - message_center, notification)), + message_center, tray, notification)), scroller_(NULL), is_expanded_(expanded) { set_focusable(true); diff --git a/ui/message_center/views/message_view.h b/ui/message_center/views/message_view.h index 5eb91fd..637a9d8 100644 --- a/ui/message_center/views/message_view.h +++ b/ui/message_center/views/message_view.h @@ -20,6 +20,7 @@ class ScrollView; namespace message_center { class MessageCenter; +class MessageCenterTray; class MessageViewContextMenuController; // Individual notifications constants. @@ -34,6 +35,7 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::SlideOutView, public: MessageView(const Notification& notification, MessageCenter* message_center, + MessageCenterTray* tray, bool expanded); virtual ~MessageView(); diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc index 3cf1fb9..a8e9213f 100644 --- a/ui/message_center/views/notification_view.cc +++ b/ui/message_center/views/notification_view.cc @@ -338,6 +338,7 @@ namespace message_center { // static MessageView* NotificationView::Create(const Notification& notification, MessageCenter* message_center, + MessageCenterTray* tray, bool expanded, bool top_level) { // Use MessageSimpleView for simple notifications unless rich style @@ -366,7 +367,7 @@ MessageView* NotificationView::Create(const Notification& notification, // Currently all roads lead to the generic NotificationView. MessageView* notification_view = - new NotificationView(notification, message_center, expanded); + new NotificationView(notification, message_center, tray, expanded); #if defined(OS_LINUX) && !defined(OS_CHROMEOS) // Don't create shadows for notification toasts on linux wih aura. @@ -382,8 +383,9 @@ MessageView* NotificationView::Create(const Notification& notification, NotificationView::NotificationView(const Notification& notification, MessageCenter* message_center, + MessageCenterTray* tray, bool expanded) - : MessageView(notification, message_center, expanded) { + : MessageView(notification, message_center, tray, expanded) { std::vector<string16> accessible_lines; // Create the opaque background that's above the view's shadow. diff --git a/ui/message_center/views/notification_view.h b/ui/message_center/views/notification_view.h index 87b6ac9..d70baaa 100644 --- a/ui/message_center/views/notification_view.h +++ b/ui/message_center/views/notification_view.h @@ -29,6 +29,7 @@ class MESSAGE_CENTER_EXPORT NotificationView : public MessageView { // notifications on Linux with Aura. static MessageView* Create(const Notification& notification, MessageCenter* message_center, + MessageCenterTray* tray, bool expanded, bool top_level); @@ -51,6 +52,7 @@ class MESSAGE_CENTER_EXPORT NotificationView : public MessageView { protected: NotificationView(const Notification& notification, MessageCenter* message_center, + MessageCenterTray* tray, bool expanded); private: diff --git a/ui/message_center/views/notifier_settings_view.cc b/ui/message_center/views/notifier_settings_view.cc index ba8c50b..610727c 100644 --- a/ui/message_center/views/notifier_settings_view.cc +++ b/ui/message_center/views/notifier_settings_view.cc @@ -4,6 +4,11 @@ #include "ui/message_center/views/notifier_settings_view.h" +#include <set> +#include <string> + +#include "base/strings/string16.h" +#include "grit/ui_resources.h" #include "grit/ui_strings.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/keycodes/keyboard_codes.h" @@ -13,6 +18,7 @@ #include "ui/gfx/image/image.h" #include "ui/gfx/size.h" #include "ui/message_center/message_center_style.h" +#include "ui/message_center/views/message_center_view.h" #include "ui/views/background.h" #include "ui/views/border.h" #include "ui/views/controls/button/checkbox.h" @@ -22,6 +28,7 @@ #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/grid_layout.h" #include "ui/views/widget/widget.h" #if defined(USE_AURA) @@ -36,9 +43,6 @@ const int kMarginWidth = 16; const int kMinimumWindowWidth = 320; const int kMinimumWindowHeight = 480; const int kEntryHeight = kMinimumWindowHeight / 10; -const SkColor kSeparatorColor = SkColorSetRGB(0xcc, 0xcc, 0xcc); - -NotifierSettingsView* settings_view_ = NULL; // The view to guarantee the 48px height and place the contents at the // middle. It also guarantee the left margin. @@ -108,54 +112,8 @@ bool EntryView::OnKeyReleased(const ui::KeyEvent& event) { return child_at(0)->OnKeyReleased(event); } -// The separator line between the title and the scroll view. Currently -// it is achieved as a top border of the scroll view. -class Separator : public views::Border { - public: - Separator(); - virtual ~Separator(); - - // Overridden from views::Border: - virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE; - virtual gfx::Insets GetInsets() const OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(Separator); -}; - -Separator::Separator() { -} - -Separator::~Separator() { -} - -void Separator::Paint(const views::View& view, gfx::Canvas* canvas) { - gfx::Rect bounds(view.GetLocalBounds()); - bounds.Inset(kMarginWidth, 0); - canvas->DrawLine(bounds.origin(), bounds.top_right(), kSeparatorColor); -} - -gfx::Insets Separator::GetInsets() const { - // Do not set the insets for the separator. This means that the separater will - // overlap with the top of the scroll contents, otherwise the scroll view will - // create a scroll bar if the contents height is exactly same as the height of - // the window. - return gfx::Insets(); -} - } // namespace -NotifierSettingsDelegate* ShowSettings(NotifierSettingsProvider* provider, - gfx::NativeView context) { - if (!settings_view_) { - settings_view_ = NotifierSettingsView::Create(provider, context); - } else { - settings_view_->GetWidget()->StackAtTop(); - settings_view_->GetWidget()->Activate(); - } - return settings_view_; -} - // We do not use views::Checkbox class directly because it doesn't support // showing 'icon'. class NotifierSettingsView::NotifierButton : public views::CustomButton, @@ -231,53 +189,39 @@ class NotifierSettingsView::NotifierButton : public views::CustomButton, DISALLOW_COPY_AND_ASSIGN(NotifierButton); }; -// static -NotifierSettingsView* NotifierSettingsView::Create( - NotifierSettingsProvider* delegate, - gfx::NativeView context) { - NotifierSettingsView* view = new NotifierSettingsView(delegate); - views::Widget* widget = new views::Widget; - views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); - params.delegate = view; - params.context = context; - widget->Init(params); - widget->CenterWindow(widget->GetWindowBoundsInScreen().size()); - widget->Show(); - - return view; -} +NotifierSettingsView::NotifierSettingsView(NotifierSettingsProvider* provider) + : provider_(provider) { + DCHECK(provider_); + provider_->AddObserver(this); -void NotifierSettingsView::UpdateIconImage(const std::string& id, - const gfx::Image& icon) { - for (std::set<NotifierButton*>::iterator iter = buttons_.begin(); - iter != buttons_.end(); ++iter) { - if ((*iter)->notifier().id == id) { - (*iter)->UpdateIconImage(icon); - return; - } - } -} - -void NotifierSettingsView::UpdateFavicon(const GURL& url, - const gfx::Image& icon) { - for (std::set<NotifierButton*>::iterator iter = buttons_.begin(); - iter != buttons_.end(); ++iter) { - if ((*iter)->notifier().url == url) { - (*iter)->UpdateIconImage(icon); - return; - } - } -} - -NotifierSettingsView::NotifierSettingsView( - NotifierSettingsProvider* delegate) - : delegate_(delegate) { - DCHECK(delegate_); - - set_background(views::Background::CreateSolidBackground(SK_ColorWHITE)); set_focusable(true); set_focus_border(NULL); - + set_background(views::Background::CreateSolidBackground( + kMessageCenterBackgroundColor)); + if (get_use_acceleration_when_possible()) + SetPaintToLayer(true); + + ResourceBundle& bundle = ResourceBundle::GetSharedInstance(); + + views::View* title_container = new views::View; + // The title_arrow and title_label aren't aligned well in Windows for the + // horizontal BoxLayout. That's why GridLayout with vertical alignment is + // used here. + views::GridLayout* title_layout = new views::GridLayout(title_container); + title_container->SetLayoutManager(title_layout); + views::ColumnSet* columns = title_layout->AddColumnSet(0); + columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, + 0, views::GridLayout::USE_PREF, 0, 0); + columns->AddPaddingColumn(0, kMarginWidth); + columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, + 1, views::GridLayout::USE_PREF, 0, 0); + title_arrow_ = new views::ImageButton(this); + title_arrow_->SetImage(views::Button::STATE_NORMAL, bundle.GetImageSkiaNamed( + IDR_NOTIFICATION_ARROW)); + title_arrow_->SetImage(views::Button::STATE_HOVERED, bundle.GetImageSkiaNamed( + IDR_NOTIFICATION_ARROW_HOVER)); + title_arrow_->SetImage(views::Button::STATE_PRESSED, bundle.GetImageSkiaNamed( + IDR_NOTIFICATION_ARROW_PRESSED)); gfx::Font title_font = ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont); views::Label* title_label = new views::Label( @@ -285,11 +229,13 @@ NotifierSettingsView::NotifierSettingsView( title_font); title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); title_label->SetMultiLine(true); - title_entry_ = new EntryView(title_label); + title_layout->StartRow(0, 0); + title_layout->AddView(title_arrow_); + title_layout->AddView(title_label); + title_entry_ = new EntryView(title_container); AddChildView(title_entry_); scroller_ = new views::ScrollView(); - scroller_->set_border(new Separator()); scroller_->SetVerticalScrollBar(new views::OverlayScrollBar(false)); AddChildView(scroller_); @@ -305,7 +251,7 @@ NotifierSettingsView::NotifierSettingsView( contents_view->AddChildView(new EntryView(top_label)); std::vector<Notifier*> notifiers; - delegate_->GetNotifierList(¬ifiers); + provider_->GetNotifierList(¬ifiers); views::View* first_view = NULL; views::View* last_view = NULL; for (size_t i = 0; i < notifiers.size(); ++i) { @@ -326,33 +272,43 @@ NotifierSettingsView::NotifierSettingsView( } NotifierSettingsView::~NotifierSettingsView() { - settings_view_ = NULL; -} - -views::View* NotifierSettingsView::GetInitiallyFocusedView() { - return this; + provider_->RemoveObserver(this); } -void NotifierSettingsView::WindowClosing() { - if (delegate_) - delegate_->OnNotifierSettingsClosing(); +bool NotifierSettingsView::IsScrollable() { + return scroller_->height() < scroller_->contents()->height(); } -views::View* NotifierSettingsView::GetContentsView() { - return this; +void NotifierSettingsView::UpdateIconImage(const std::string& id, + const gfx::Image& icon) { + for (std::set<NotifierButton*>::iterator iter = buttons_.begin(); + iter != buttons_.end(); ++iter) { + if ((*iter)->notifier().id == id) { + (*iter)->UpdateIconImage(icon); + return; + } + } } -bool NotifierSettingsView::CanResize() const { - return true; +void NotifierSettingsView::UpdateFavicon(const GURL& url, + const gfx::Image& icon) { + for (std::set<NotifierButton*>::iterator iter = buttons_.begin(); + iter != buttons_.end(); ++iter) { + if ((*iter)->notifier().url == url) { + (*iter)->UpdateIconImage(icon); + return; + } + } } void NotifierSettingsView::Layout() { - int title_height = title_entry_->GetPreferredSize().height(); + int title_height = title_entry_->GetHeightForWidth(width()); title_entry_->SetBounds(0, 0, width(), title_height); + views::View* contents_view = scroller_->contents(); int content_width = width(); int content_height = contents_view->GetHeightForWidth(content_width); - if (title_height + content_height > kMinimumWindowHeight) { + if (title_height + content_height > height()) { content_width -= scroller_->GetScrollBarWidth(); content_height = contents_view->GetHeightForWidth(content_width); } @@ -370,7 +326,12 @@ gfx::Size NotifierSettingsView::GetMinimumSize() { } gfx::Size NotifierSettingsView::GetPreferredSize() { - return GetMinimumSize(); + gfx::Size preferred_size; + std::vector<gfx::Size> child_sizes; + gfx::Size title_size = title_entry_->GetPreferredSize(); + gfx::Size content_size = scroller_->contents()->GetPreferredSize(); + return gfx::Size(std::max(title_size.width(), content_size.width()), + title_size.height() + content_size.height()); } bool NotifierSettingsView::OnKeyPressed(const ui::KeyEvent& event) { @@ -388,13 +349,19 @@ bool NotifierSettingsView::OnMouseWheel(const ui::MouseWheelEvent& event) { void NotifierSettingsView::ButtonPressed(views::Button* sender, const ui::Event& event) { + if (sender == title_arrow_) { + MessageCenterView* center_view = static_cast<MessageCenterView*>(parent()); + center_view->SetSettingsVisible(!center_view->settings_visible()); + return; + } + std::set<NotifierButton*>::iterator iter = buttons_.find( static_cast<NotifierButton*>(sender)); DCHECK(iter != buttons_.end()); (*iter)->SetChecked(!(*iter)->checked()); - if (delegate_) - delegate_->SetNotifierEnabled((*iter)->notifier(), (*iter)->checked()); + if (provider_) + provider_->SetNotifierEnabled((*iter)->notifier(), (*iter)->checked()); } } // namespace message_center diff --git a/ui/message_center/views/notifier_settings_view.h b/ui/message_center/views/notifier_settings_view.h index f1b1e7f..f9fd7b1 100644 --- a/ui/message_center/views/notifier_settings_view.h +++ b/ui/message_center/views/notifier_settings_view.h @@ -5,58 +5,38 @@ #ifndef UI_MESSAGE_CENTER_VIEWS_NOTIFIER_SETTINGS_VIEW_H_ #define UI_MESSAGE_CENTER_VIEWS_NOTIFIER_SETTINGS_VIEW_H_ -#include <set> -#include <string> - -#include "base/strings/string16.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/gfx/native_widget_types.h" #include "ui/message_center/message_center_export.h" #include "ui/message_center/notifier_settings.h" -#include "ui/views/controls/button/button.h" -#include "ui/views/widget/widget_delegate.h" - -namespace views { -class ScrollView; -} +#include "ui/message_center/views/message_bubble_base.h" +#include "ui/views/controls/button/image_button.h" +#include "ui/views/view.h" namespace message_center { // A class to show the list of notifier extensions / URL patterns and allow // users to customize the settings. class MESSAGE_CENTER_EXPORT NotifierSettingsView - : public NotifierSettingsDelegate, - public views::WidgetDelegateView, + : public NotifierSettingsObserver, + public views::View, public views::ButtonListener { public: - // Create a new widget of the notifier settings and returns it. Note that - // the widget and the view is self-owned. It'll be deleted when it's closed - // or the chrome's shutdown. - static NotifierSettingsView* Create(NotifierSettingsProvider* delegate, - gfx::NativeView context); + explicit NotifierSettingsView(NotifierSettingsProvider* provider); + virtual ~NotifierSettingsView(); + + bool IsScrollable(); // Overridden from NotifierSettingsDelegate: virtual void UpdateIconImage(const std::string& id, const gfx::Image& icon) OVERRIDE; virtual void UpdateFavicon(const GURL& url, const gfx::Image& icon) OVERRIDE; - void set_delegate(NotifierSettingsProvider* new_delegate) { - delegate_ = new_delegate; + void set_provider(NotifierSettingsProvider* new_provider) { + provider_ = new_provider; } private: class NotifierButton; - NotifierSettingsView(NotifierSettingsProvider* delegate); - virtual ~NotifierSettingsView(); - - // Overridden from views::WidgetDelegate: - virtual views::View* GetInitiallyFocusedView() OVERRIDE; - virtual void WindowClosing() OVERRIDE; - virtual views::View* GetContentsView() OVERRIDE; - virtual bool CanResize() const OVERRIDE; - // Overridden from views::View: virtual void Layout() OVERRIDE; virtual gfx::Size GetMinimumSize() OVERRIDE; @@ -68,9 +48,10 @@ class MESSAGE_CENTER_EXPORT NotifierSettingsView virtual void ButtonPressed(views::Button* sender, const ui::Event& event) OVERRIDE; + views::ImageButton* title_arrow_; views::View* title_entry_; views::ScrollView* scroller_; - NotifierSettingsProvider* delegate_; + NotifierSettingsProvider* provider_; std::set<NotifierButton*> buttons_; DISALLOW_COPY_AND_ASSIGN(NotifierSettingsView); |