Skip to content

Commit

Permalink
Add new empty state view to message center.
Browse files Browse the repository at this point in the history
As a part of message center restyling, this CL adds a new view for
message center when there are no notifications.

Previously, button bar text "You have no notifications" was used.

Screenshot (before): http://screen/5JCCD7uyxwd
Screenshot (after): http://screen/TTtSP0rbj4T
Mock: https://crbug.com/726246#c17

TEST=ash_unittests
BUG=726246

Change-Id: Id64eb2e1cdaeb29c1477d65b2a79602b00b0896a
Reviewed-on: https://chromium-review.googlesource.com/700215
Reviewed-by: Yoshiki Iguchi <yoshiki@chromium.org>
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Commit-Queue: Tetsui Ohkubo <tetsui@chromium.org>
Cr-Commit-Position: refs/heads/master@{#507889}
  • Loading branch information
Tetsui Ohkubo authored and Commit Bot committed Oct 11, 2017
1 parent 1009aff commit 632bc49
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 21 deletions.
2 changes: 1 addition & 1 deletion ash/ash_strings.grd
Original file line number Diff line number Diff line change
Expand Up @@ -1177,7 +1177,7 @@ Subsequent notifications, windows and dialogs may be split between desktops.
Unlock device to view your notifications
</message>
<message name="IDS_ASH_MESSAGE_CENTER_NO_MESSAGES" desc="The message displayed in the message center when there are no notifications.">
You have no notifications
All done
</message>
</messages>
</release>
Expand Down
85 changes: 74 additions & 11 deletions ash/message_center/message_center_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
#include <map>

#include "ash/message_center/message_center_button_bar.h"
#include "ash/message_center/message_center_style.h"
#include "ash/message_center/notifier_settings_view.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
Expand All @@ -34,6 +36,7 @@
#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"

Expand All @@ -57,16 +60,56 @@ bool MessageCenterView::disable_animation_for_testing = false;

namespace {

const int kDefaultAnimationDurationMs = 120;
const int kDefaultFrameRateHz = 60;
const int kMinScrollViewHeight = 77;
constexpr int kDefaultAnimationDurationMs = 120;
constexpr int kDefaultFrameRateHz = 60;
constexpr int kMinScrollViewHeight = 77;
constexpr int kEmptyViewHeight = 96;
constexpr gfx::Insets kEmptyViewPadding(0, 0, 24, 0);
constexpr SkColor kEmptyViewColor = SkColorSetARGB(0x8A, 0x0, 0x0, 0x0);
constexpr gfx::Insets kAllDoneIconPadding(0, 0, 4, 0);
constexpr int kAllDoneIconSize = 24;
constexpr int kEmptyLabelSize = 12;

void SetViewHierarchyEnabled(views::View* view, bool enabled) {
for (int i = 0; i < view->child_count(); i++)
SetViewHierarchyEnabled(view->child_at(i), enabled);
view->SetEnabled(enabled);
}

// View that is shown when there are no notifications.
class EmptyNotificationView : public views::View {
public:
EmptyNotificationView() {
views::BoxLayout* layout =
new views::BoxLayout(views::BoxLayout::kVertical, kEmptyViewPadding, 0);
layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_END);
layout->set_cross_axis_alignment(
views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
SetLayoutManager(layout);

views::ImageView* icon = new views::ImageView();
icon->SetImage(gfx::CreateVectorIcon(kNotificationCenterAllDoneIcon,
kAllDoneIconSize, kEmptyViewColor));
icon->SetBorder(views::CreateEmptyBorder(kAllDoneIconPadding));
AddChildView(icon);

views::Label* label = new views::Label(
l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_NO_MESSAGES));
label->SetEnabledColor(kEmptyViewColor);
// "Roboto-Medium, 12sp" is specified in the mock.
label->SetFontList(message_center_style::GetFontListForSizeAndWeight(
kEmptyLabelSize, gfx::Font::Weight::MEDIUM));
label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
AddChildView(label);
}

// views::View:
int GetHeightForWidth(int w) const override { return kEmptyViewHeight; }

private:
DISALLOW_COPY_AND_ASSIGN(EmptyNotificationView);
};

} // namespace

// MessageCenterView ///////////////////////////////////////////////////////////
Expand All @@ -79,6 +122,7 @@ MessageCenterView::MessageCenterView(MessageCenter* message_center,
tray_(tray),
scroller_(nullptr),
settings_view_(nullptr),
no_notifications_view_(nullptr),
button_bar_(nullptr),
settings_visible_(initially_settings_visible),
source_view_(nullptr),
Expand All @@ -87,10 +131,14 @@ MessageCenterView::MessageCenterView(MessageCenter* message_center,
target_height_(0),
is_closing_(false),
is_locked_(message_center_->IsLockedState()),
mode_((!initially_settings_visible || is_locked_) ? Mode::BUTTONS_ONLY
: Mode::SETTINGS),
mode_(Mode::NO_NOTIFICATIONS),
context_menu_controller_(this),
focus_manager_(nullptr) {
if (is_locked_)
mode_ = Mode::LOCKED;
else if (initially_settings_visible)
mode_ = Mode::SETTINGS;

message_center_->AddObserver(this);
set_notify_enter_exit_on_child(true);
SetBackground(views::CreateSolidBackground(kBackgroundColor));
Expand Down Expand Up @@ -128,11 +176,15 @@ MessageCenterView::MessageCenterView(MessageCenter* message_center,

settings_view_ = new NotifierSettingsView(notifier_settings_provider);

no_notifications_view_ = new EmptyNotificationView();

scroller_->SetVisible(false); // Because it has no notifications at first.
settings_view_->SetVisible(mode_ == Mode::SETTINGS);
no_notifications_view_->SetVisible(mode_ == Mode::NO_NOTIFICATIONS);

AddChildView(scroller_);
AddChildView(settings_view_);
AddChildView(no_notifications_view_);
AddChildView(button_bar_);
}

Expand Down Expand Up @@ -256,8 +308,16 @@ void MessageCenterView::Layout() {
return;
}

// In order to keep the fix for https://crbug.com/767805 working,
// we have to always call SetBounds of scroller_.
// TODO(tetsui): Fix the bug above without calling SetBounds, as SetBounds
// invokes Layout() which is a heavy operation.
scroller_->SetBounds(0, 0, width(), height() - button_height);
settings_view_->SetBounds(0, 0, width(), height() - button_height);

if (settings_view_->visible())
settings_view_->SetBounds(0, 0, width(), height() - button_height);
if (no_notifications_view_->visible())
no_notifications_view_->SetBounds(0, 0, width(), kEmptyViewHeight);

bool is_scrollable = false;
if (scroller_->visible())
Expand Down Expand Up @@ -319,6 +379,8 @@ int MessageCenterView::GetHeightForWidth(int width) const {
content_height += scroller_->GetHeightForWidth(width);
else if (settings_view_->visible())
content_height += settings_view_->GetHeightForWidth(width);
else if (no_notifications_view_->visible())
content_height += no_notifications_view_->GetHeightForWidth(width);
return button_bar_->GetHeightForWidth(width) + content_height +
(button_border ? button_border->GetInsets().height() : 0);
}
Expand Down Expand Up @@ -546,21 +608,18 @@ base::string16 MessageCenterView::GetButtonBarTitle() const {
if (is_locked_)
return l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_FOOTER_LOCKSCREEN);

if (mode_ == Mode::BUTTONS_ONLY)
return l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_NO_MESSAGES);

return l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_FOOTER_TITLE);
}

void MessageCenterView::Update(bool animate) {
bool no_message_views = (message_list_view_->GetNotificationCount() == 0);

if (is_locked_)
SetVisibilityMode(Mode::BUTTONS_ONLY, animate);
SetVisibilityMode(Mode::LOCKED, animate);
else if (settings_visible_)
SetVisibilityMode(Mode::SETTINGS, animate);
else if (no_message_views)
SetVisibilityMode(Mode::BUTTONS_ONLY, animate);
SetVisibilityMode(Mode::NO_NOTIFICATIONS, animate);
else
SetVisibilityMode(Mode::NOTIFICATIONS, animate);

Expand Down Expand Up @@ -593,13 +652,17 @@ void MessageCenterView::SetVisibilityMode(Mode mode, bool animate) {
source_view_ = scroller_;
else if (mode_ == Mode::SETTINGS)
source_view_ = settings_view_;
else if (mode_ == Mode::NO_NOTIFICATIONS)
source_view_ = no_notifications_view_;
else
source_view_ = nullptr;

if (mode == Mode::NOTIFICATIONS)
target_view_ = scroller_;
else if (mode == Mode::SETTINGS)
target_view_ = settings_view_;
else if (mode == Mode::NO_NOTIFICATIONS)
target_view_ = no_notifications_view_;
else
target_view_ = nullptr;

Expand Down
11 changes: 9 additions & 2 deletions ash/message_center/message_center_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,13 @@ class ASH_EXPORT MessageCenterView
private:
friend class MessageCenterViewTest;

enum class Mode { NOTIFICATIONS, SETTINGS, BUTTONS_ONLY };
// NOTIFICATIONS: Normal notification list (MessageListView) is shown.
// There should be at least one notification.
// SETTINGS: Notifier settings (NotifierSettingsView) is shown.
// LOCKED: The computer is in the lock screen. No content view is shown.
// NO_NOTIFICATIONS: "All done" message (EmptyNotifcationView) is shown.
// There should be no notification.
enum class Mode { NOTIFICATIONS, SETTINGS, LOCKED, NO_NOTIFICATIONS };

static bool disable_animation_for_testing;

Expand All @@ -139,6 +145,7 @@ class ASH_EXPORT MessageCenterView
views::ScrollView* scroller_;
std::unique_ptr<MessageListView> message_list_view_;
NotifierSettingsView* settings_view_;
views::View* no_notifications_view_;
MessageCenterButtonBar* button_bar_;

// Data for transition animation between settings view and message list.
Expand All @@ -163,7 +170,7 @@ class ASH_EXPORT MessageCenterView
bool is_locked_ = false;

// Current view mode. During animation, it is the target mode.
Mode mode_ = Mode::BUTTONS_ONLY;
Mode mode_ = Mode::NO_NOTIFICATIONS;

message_center::MessageViewContextMenuController context_menu_controller_;

Expand Down
57 changes: 50 additions & 7 deletions ash/message_center/message_center_view_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ TEST_F(MessageCenterViewTest, CheckModeWithRemovingAndAddingNotifications) {

// Remove notifications.
RemoveDefaultNotifications();
EXPECT_EQ(Mode::BUTTONS_ONLY, GetMessageCenterViewInternalMode());
EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());

// Add a notification.
AddNotification(std::make_unique<Notification>(
Expand All @@ -811,13 +811,13 @@ TEST_F(MessageCenterViewTest, CheckModeWithSettingsVisibleAndHiddenOnEmpty) {
RemoveDefaultNotifications();

// Check the initial state.
EXPECT_EQ(Mode::BUTTONS_ONLY, GetMessageCenterViewInternalMode());
EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
// Show the settings.
GetMessageCenterView()->SetSettingsVisible(true);
EXPECT_EQ(Mode::SETTINGS, GetMessageCenterViewInternalMode());
// Hide the settings.
GetMessageCenterView()->SetSettingsVisible(false);
EXPECT_EQ(Mode::BUTTONS_ONLY, GetMessageCenterViewInternalMode());
EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
}

TEST_F(MessageCenterViewTest,
Expand All @@ -835,7 +835,7 @@ TEST_F(MessageCenterViewTest,

// Hide the settings.
GetMessageCenterView()->SetSettingsVisible(false);
EXPECT_EQ(Mode::BUTTONS_ONLY, GetMessageCenterViewInternalMode());
EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
}

TEST_F(MessageCenterViewTest,
Expand All @@ -844,7 +844,7 @@ TEST_F(MessageCenterViewTest,
RemoveDefaultNotifications();

// Check the initial state.
EXPECT_EQ(Mode::BUTTONS_ONLY, GetMessageCenterViewInternalMode());
EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());

// Show the settings.
GetMessageCenterView()->SetSettingsVisible(true);
Expand All @@ -865,6 +865,49 @@ TEST_F(MessageCenterViewTest,
EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());
}

TEST_F(MessageCenterViewTest, CheckModeWithLockingAndUnlocking) {
// Check the initial state.
EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());

// Lock!
SetLockedState(true);
EXPECT_EQ(Mode::LOCKED, GetMessageCenterViewInternalMode());

// Unlock!
SetLockedState(false);
EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());

// Remove all existing notifications.
RemoveDefaultNotifications();
EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());

// Lock!
SetLockedState(true);
EXPECT_EQ(Mode::LOCKED, GetMessageCenterViewInternalMode());

// Unlock!
SetLockedState(false);
EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
}

TEST_F(MessageCenterViewTest, CheckModeWithRemovingNotificationDuringLock) {
// Check the initial state.
EXPECT_EQ(Mode::NOTIFICATIONS, GetMessageCenterViewInternalMode());

// Lock!
SetLockedState(true);

EXPECT_EQ(Mode::LOCKED, GetMessageCenterViewInternalMode());

// Remove all existing notifications.
RemoveDefaultNotifications();

// Unlock!
SetLockedState(false);

EXPECT_EQ(Mode::NO_NOTIFICATIONS, GetMessageCenterViewInternalMode());
}

TEST_F(MessageCenterViewTest, LockScreen) {
// Plain button bar height (56) + border (2)
const int kLockedMessageCenterViewHeight = 58;
Expand Down Expand Up @@ -944,8 +987,8 @@ TEST_F(MessageCenterViewTest, LockScreen) {
}

TEST_F(MessageCenterViewTest, NoNotification) {
// Plain button bar height (56) + border (2)
const int kEmptyMessageCenterViewHeight = 58;
// Plain button bar height (56) + border (2) + Empty view (96)
const int kEmptyMessageCenterViewHeight = 154;

GetMessageCenterView()->SizeToPreferredSize();
EXPECT_NE(kEmptyMessageCenterViewHeight, GetMessageCenterView()->height());
Expand Down
1 change: 1 addition & 0 deletions ash/resources/vector_icons/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ aggregate_vector_icons("ash_vector_icons") {
"notification_bluetooth_battery_warning.icon",
"notification_bluetooth.icon",
"notification_capslock.icon",
"notification_center_all_done.icon",
"notification_center_clear_all.icon",
"notification_center_do_not_disturb_off.icon",
"notification_center_do_not_disturb_on.icon",
Expand Down
28 changes: 28 additions & 0 deletions ash/resources/vector_icons/notification_center_all_done.icon
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

CANVAS_DIMENSIONS, 48,
MOVE_TO, 33.28f, 6.28f,
LINE_TO, 30.28f, 9.28f,
CUBIC_TO, 28.35f, 8.46f, 26.23f, 8, 24, 8,
CUBIC_TO, 15.16f, 8, 8, 15.16f, 8, 24,
R_CUBIC_TO, 0, 8.84f, 7.16f, 16, 16, 16,
R_CUBIC_TO, 8.84f, 0, 16, -7.16f, 16, -16,
R_CUBIC_TO, 0, -0.58f, -0.03f, -1.16f, -0.09f, -1.72f,
R_LINE_TO, 3.42f, -3.42f,
R_CUBIC_TO, 0.44f, 1.64f, 0.67f, 3.37f, 0.67f, 5.15f,
R_CUBIC_TO, 0, 11.04f, -8.96f, 20, -20, 20,
CUBIC_TO_SHORTHAND, 4, 35.04f, 4, 24,
CUBIC_TO_SHORTHAND, 12.96f, 4, 24, 4,
R_CUBIC_TO, 3.35f, 0, 6.5f, 0.82f, 9.28f, 2.28f,
CLOSE,
R_MOVE_TO, 7.9f, 0.88f,
LINE_TO, 44, 10,
LINE_TO, 22, 32,
LINE_TO, 12, 22,
R_LINE_TO, 2.82f, -2.82f,
LINE_TO, 22, 26.34f,
LINE_TO, 41.18f, 7.16f,
CLOSE,
END

0 comments on commit 632bc49

Please sign in to comment.