Commit 755193a0 authored by Tatsuhisa Yamaguchi's avatar Tatsuhisa Yamaguchi Committed by Commit Bot

Reland "Add a container view of MessageView to be used for swipe control."

This is a reland of 16ab50cc
https://chromium-review.googlesource.com/c/chromium/src/+/1184724
The original change was once reverted as it failed on
linux_chromium_chromeos_asan_rel_ng.

Original change's description:
> Add a container view of MessageView to be used for swipe control.
>
> This change adds a new container view between MessageListView and
> MessageView. The new view is intended to host buttons views for swipe
> control.
> This change also returns slided notifications when another notification
> swipe is started, so as to ensure only one swipe control can be opened.
>
> Bug: 840497
> Change-Id: Ica92933a8d3f5d92caa43a5c926252681873ede1
> Reviewed-on: https://chromium-review.googlesource.com/1184724
> Reviewed-by: Yoshiki Iguchi <yoshiki@chromium.org>
> Commit-Queue: Tatsuhisa Yamaguchi <yamaguchi@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#586198}

Bug: 840497,877983
Test: ash_unittests --gtest_filter=MessageCenterViewTest.*:MessageListViewTest.*:ArcNotificationContentViewTest.*
Change-Id: I0c53b727ab317364224894ed8e0853ae10125337
Reviewed-on: https://chromium-review.googlesource.com/1192468Reviewed-by: default avatarStefan Kuhne <skuhne@chromium.org>
Reviewed-by: default avatarEvan Stade <estade@chromium.org>
Reviewed-by: default avatarTetsui Ohkubo <tetsui@chromium.org>
Commit-Queue: Tatsuhisa Yamaguchi <yamaguchi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#587114}
parent 8a52e18e
......@@ -27,6 +27,7 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/skia_paint_util.h"
#include "ui/message_center/message_center.h"
......@@ -457,7 +458,9 @@ void MessageCenterView::OnNotificationRemoved(const std::string& id,
// We skip repositioning during clear-all anomation, since we don't need keep
// positions.
if (by_user && !is_clearing_all_notifications_) {
message_list_view_->SetRepositionTarget(view->bounds());
gfx::RectF rect_f(view->x(), view->y(), view->width(), view->height());
views::View::ConvertRectToTarget(view, message_list_view_.get(), &rect_f);
message_list_view_->SetRepositionTarget(gfx::ToNearestRect(rect_f));
// Moves the keyboard focus to the next notification if the removed
// notification is focused so that the user can dismiss notifications
// without re-focusing by tab key.
......
......@@ -498,11 +498,11 @@ TEST_F(MessageCenterViewTest, DISABLED_SizeAfterUpdate) {
TEST_F(MessageCenterViewTest, SizeAfterUpdateBelowWithRepositionTarget) {
EXPECT_EQ(2, GetMessageListView()->child_count());
// Make sure that notification 2 is placed above notification 1.
EXPECT_LT(GetNotificationView(kNotificationId2)->bounds().y(),
GetNotificationView(kNotificationId1)->bounds().y());
EXPECT_LT(GetNotificationView(kNotificationId2)->GetBoundsInScreen().y(),
GetNotificationView(kNotificationId1)->GetBoundsInScreen().y());
GetMessageListView()->SetRepositionTarget(
GetNotificationView(kNotificationId1)->bounds());
GetNotificationView(kNotificationId1)->GetBoundsInScreen());
std::unique_ptr<Notification> notification = std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
......@@ -528,11 +528,11 @@ TEST_F(MessageCenterViewTest, SizeAfterUpdateBelowWithRepositionTarget) {
TEST_F(MessageCenterViewTest, SizeAfterUpdateOfRepositionTarget) {
EXPECT_EQ(2, GetMessageListView()->child_count());
// Make sure that notification 2 is placed above notification 1.
EXPECT_LT(GetNotificationView(kNotificationId2)->bounds().y(),
GetNotificationView(kNotificationId1)->bounds().y());
EXPECT_LT(GetNotificationView(kNotificationId2)->GetBoundsInScreen().y(),
GetNotificationView(kNotificationId1)->GetBoundsInScreen().y());
GetMessageListView()->SetRepositionTarget(
GetNotificationView(kNotificationId1)->bounds());
GetNotificationView(kNotificationId1)->GetBoundsInScreen());
std::unique_ptr<Notification> notification = std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
......@@ -571,14 +571,14 @@ TEST_F(MessageCenterViewTest, SizeAfterRemove) {
TEST_F(MessageCenterViewTest, PositionAfterUpdate) {
// Make sure that the notification 2 is placed above the notification 1.
EXPECT_LT(GetNotificationView(kNotificationId2)->bounds().y(),
GetNotificationView(kNotificationId1)->bounds().y());
EXPECT_LT(GetNotificationView(kNotificationId2)->GetBoundsInScreen().y(),
GetNotificationView(kNotificationId1)->GetBoundsInScreen().y());
int previous_vertical_pos_from_bottom =
GetMessageListView()->height() -
GetNotificationView(kNotificationId1)->bounds().y();
GetNotificationView(kNotificationId1)->GetBoundsInScreen().y();
GetMessageListView()->SetRepositionTarget(
GetNotificationView(kNotificationId1)->bounds());
GetNotificationView(kNotificationId1)->parent()->bounds());
std::unique_ptr<Notification> notification = std::make_unique<Notification>(
NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
......@@ -594,21 +594,21 @@ TEST_F(MessageCenterViewTest, PositionAfterUpdate) {
// The vertical position of the target from bottom should be kept over change.
int current_vertical_pos_from_bottom =
GetMessageListView()->height() -
GetNotificationView(kNotificationId1)->bounds().y();
GetNotificationView(kNotificationId1)->GetBoundsInScreen().y();
EXPECT_EQ(previous_vertical_pos_from_bottom,
current_vertical_pos_from_bottom);
}
TEST_F(MessageCenterViewTest, PositionAfterRemove) {
// Make sure that the notification 2 is placed above the notification 1.
EXPECT_LT(GetNotificationView(kNotificationId2)->bounds().y(),
GetNotificationView(kNotificationId1)->bounds().y());
EXPECT_LT(GetNotificationView(kNotificationId2)->GetBoundsInScreen().y(),
GetNotificationView(kNotificationId1)->GetBoundsInScreen().y());
GetMessageListView()->SetRepositionTarget(
GetNotificationView(kNotificationId2)->bounds());
GetNotificationView(kNotificationId2)->parent()->bounds());
int previous_height = GetMessageListView()->height();
int previous_notification2_y =
GetNotificationView(kNotificationId2)->bounds().y();
GetNotificationView(kNotificationId2)->GetBoundsInScreen().y();
EXPECT_EQ(2, GetMessageListView()->child_count());
RemoveNotification(kNotificationId2, false);
......@@ -620,7 +620,7 @@ TEST_F(MessageCenterViewTest, PositionAfterRemove) {
// Confirm that notification 1 is moved up to the place on which the
// notification 2 was.
EXPECT_EQ(previous_notification2_y,
GetNotificationView(kNotificationId1)->bounds().y());
GetNotificationView(kNotificationId1)->GetBoundsInScreen().y());
// The size should be kept.
EXPECT_EQ(previous_height, GetMessageListView()->height());
......
......@@ -16,12 +16,14 @@
#include "ui/message_center/public/cpp/message_center_constants.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/message_center/views/message_view.h"
#include "ui/message_center/views/slidable_message_view.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"
using message_center::MessageView;
using message_center::SlidableMessageView;
using message_center::Notification;
namespace ash {
......@@ -68,7 +70,7 @@ void MessageListView::Layout() {
}
}
void MessageListView::AddNotificationAt(MessageView* view, int index) {
void MessageListView::AddNotificationAt(MessageView* message_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,
......@@ -84,24 +86,26 @@ void MessageListView::AddNotificationAt(MessageView* view, int index) {
}
if (real_index == 0)
ExpandSpecifiedNotificationAndCollapseOthers(view);
ExpandSpecifiedNotificationAndCollapseOthers(message_view);
AddChildViewAt(view, real_index);
SlidableMessageView* container = new SlidableMessageView(message_view);
AddChildViewAt(container, real_index);
if (GetContentsBounds().IsEmpty())
return;
adding_views_.insert(view);
adding_views_.insert(container);
DoUpdateIfPossible();
}
void MessageListView::RemoveNotification(MessageView* view) {
DCHECK_EQ(view->parent(), this);
void MessageListView::RemoveNotification(MessageView* message_view) {
views::View* container = message_view->parent();
DCHECK_EQ(container->parent(), this);
// TODO(yhananda): We should consider consolidating clearing_all_views_,
// deleting_views_ and deleted_when_done_.
if (base::ContainsValue(clearing_all_views_, view) ||
deleting_views_.find(view) != deleting_views_.end() ||
deleted_when_done_.find(view) != deleted_when_done_.end()) {
if (base::ContainsValue(clearing_all_views_, container) ||
deleting_views_.find(container) != deleting_views_.end() ||
deleted_when_done_.find(container) != deleted_when_done_.end()) {
// Let's skip deleting the view if it's already scheduled for deleting.
// Even if we check clearing_all_views_ here, we actualy have no idea
// whether the view is due to be removed or not because it could be in its
......@@ -112,63 +116,70 @@ void MessageListView::RemoveNotification(MessageView* view) {
}
if (GetContentsBounds().IsEmpty()) {
delete view;
delete container;
} else {
if (adding_views_.find(view) != adding_views_.end())
adding_views_.erase(view);
if (animator_.IsAnimating(view))
animator_.StopAnimatingView(view);
if (adding_views_.find(container) != adding_views_.end())
adding_views_.erase(container);
if (animator_.IsAnimating(container))
animator_.StopAnimatingView(container);
if (view->layer()) {
deleting_views_.insert(view);
if (container->layer()) {
deleting_views_.insert(container);
} else {
delete view;
delete container;
}
DoUpdateIfPossible();
}
int index = GetIndexOf(view);
int index = GetIndexOf(container);
if (index == 0)
ExpandTopNotificationAndCollapseOthers();
}
void MessageListView::UpdateNotification(MessageView* view,
void MessageListView::UpdateNotification(MessageView* message_view,
const Notification& notification) {
views::View* container = message_view->parent();
// Skip updating the notification being cleared.
if (base::ContainsValue(clearing_all_views_, view))
if (base::ContainsValue(clearing_all_views_, container))
return;
int index = GetIndexOf(view);
int index = GetIndexOf(container);
DCHECK_LE(0, index); // GetIndexOf is negative if not a child.
if (index == 0)
ExpandSpecifiedNotificationAndCollapseOthers(view);
animator_.StopAnimatingView(view);
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);
view->UpdateWithNotification(notification);
ExpandSpecifiedNotificationAndCollapseOthers(message_view);
animator_.StopAnimatingView(container);
if (deleting_views_.find(container) != deleting_views_.end())
deleting_views_.erase(container);
if (deleted_when_done_.find(container) != deleted_when_done_.end())
deleted_when_done_.erase(container);
message_view->UpdateWithNotification(notification);
DoUpdateIfPossible();
}
std::pair<int, MessageView*> MessageListView::GetNotificationById(
const std::string& id) {
for (int i = child_count() - 1; i >= 0; --i) {
MessageView* view = static_cast<MessageView*>(child_at(i));
if (view->notification_id() == id && IsValidChild(view))
return std::make_pair(i, view);
DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
child_at(i)->GetClassName());
SlidableMessageView* container =
static_cast<SlidableMessageView*>(child_at(i));
if (container->notification_id() == id && IsValidChild(container))
return std::make_pair(i, container->GetMessageView());
}
return std::make_pair(-1, nullptr);
}
MessageView* MessageListView::GetNotificationAt(int index) {
for (int i = child_count() - 1; i >= 0; --i) {
MessageView* view = static_cast<MessageView*>(child_at(i));
if (IsValidChild(view)) {
DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
child_at(i)->GetClassName());
SlidableMessageView* container =
static_cast<SlidableMessageView*>(child_at(i));
if (IsValidChild(container)) {
if (index == 0)
return view;
return container->GetMessageView();
index--;
}
}
......@@ -178,8 +189,9 @@ MessageView* MessageListView::GetNotificationAt(int index) {
size_t MessageListView::GetNotificationCount() const {
int count = 0;
for (int i = child_count() - 1; i >= 0; --i) {
const MessageView* view = static_cast<const MessageView*>(child_at(i));
if (IsValidChild(view))
const SlidableMessageView* container =
static_cast<const SlidableMessageView*>(child_at(i));
if (IsValidChild(container))
count++;
}
return count;
......@@ -287,8 +299,10 @@ void MessageListView::ResetRepositionSession() {
void MessageListView::ClearAllClosableNotifications(
const gfx::Rect& visible_scroll_rect) {
for (int i = 0; i < child_count(); ++i) {
// Safe cast since all views in MessageListView are MessageViews.
MessageView* child = static_cast<MessageView*>(child_at(i));
// Safe cast since all views in MessageListView are SlidableMessageViews.
DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
child_at(i)->GetClassName());
SlidableMessageView* child = static_cast<SlidableMessageView*>(child_at(i));
if (!child->visible())
continue;
if (gfx::IntersectRects(child->bounds(), visible_scroll_rect).IsEmpty())
......@@ -480,34 +494,41 @@ void MessageListView::ExpandSpecifiedNotificationAndCollapseOthers(
}
for (int i = 0; i < child_count(); ++i) {
MessageView* view = static_cast<MessageView*>(child_at(i));
DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
child_at(i)->GetClassName());
SlidableMessageView* container =
static_cast<SlidableMessageView*>(child_at(i));
// Target view is already processed above.
if (target_view == view)
if (target_view == container->GetMessageView())
continue;
// Skip if the view is invalid.
if (!IsValidChild(view))
if (!IsValidChild(container))
continue;
// We don't touch if the view has been manually expanded or collapsed.
if (view->IsManuallyExpandedOrCollapsed())
if (container->IsManuallyExpandedOrCollapsed())
continue;
// Otherwise, collapse the notification.
view->SetExpanded(false);
container->SetExpanded(false);
}
}
void MessageListView::ExpandTopNotificationAndCollapseOthers() {
MessageView* top_notification = nullptr;
SlidableMessageView* top_notification = nullptr;
for (int i = 0; i < child_count(); ++i) {
MessageView* view = static_cast<MessageView*>(child_at(i));
if (!IsValidChild(view))
DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
child_at(i)->GetClassName());
SlidableMessageView* container =
static_cast<SlidableMessageView*>(child_at(i));
if (!IsValidChild(container))
continue;
top_notification = view;
top_notification = container;
break;
}
if (top_notification != nullptr)
ExpandSpecifiedNotificationAndCollapseOthers(top_notification);
ExpandSpecifiedNotificationAndCollapseOthers(
top_notification->GetMessageView());
}
std::vector<int> MessageListView::ComputeRepositionOffsets(
......@@ -669,4 +690,19 @@ void MessageListView::AnimateClearingOneNotification() {
}
}
void MessageListView::OnSlideChanged(const std::string& notification_id) {
for (int i = 0; i < child_count(); ++i) {
DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
child_at(i)->GetClassName());
SlidableMessageView* container =
static_cast<SlidableMessageView*>(child_at(i));
MessageView* message = container->GetMessageView();
if (message->notification_id() == notification_id)
continue;
if (!IsValidChild(container))
continue;
container->CloseSwipeControl();
}
}
} // namespace ash
......@@ -14,6 +14,7 @@
#include "ui/compositor/paint_context.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/message_center/views/slidable_message_view.h"
#include "ui/views/animation/bounds_animator.h"
#include "ui/views/animation/bounds_animator_observer.h"
#include "ui/views/controls/scroll_view.h"
......@@ -24,6 +25,7 @@ class Layer;
}
namespace message_center {
class SlidableMessageView;
class MessageView;
class Notification;
} // namespace message_center
......@@ -33,8 +35,10 @@ namespace ash {
// Displays a list of messages for rich notifications. Functions as an array of
// MessageViews and animates them on transitions. It also supports
// repositioning.
class ASH_EXPORT MessageListView : public views::View,
public views::BoundsAnimatorObserver {
class ASH_EXPORT MessageListView
: public views::View,
public views::BoundsAnimatorObserver,
public message_center::MessageView::SlideObserver {
public:
class Observer {
public:
......@@ -44,9 +48,9 @@ class ASH_EXPORT MessageListView : public views::View,
MessageListView();
~MessageListView() override;
void AddNotificationAt(message_center::MessageView* view, int i);
void RemoveNotification(message_center::MessageView* view);
void UpdateNotification(message_center::MessageView* view,
void AddNotificationAt(message_center::MessageView* message_view, int i);
void RemoveNotification(message_center::MessageView* message_view);
void UpdateNotification(message_center::MessageView* message_view,
const message_center::Notification& notification);
std::pair<int, message_center::MessageView*> GetNotificationById(
const std::string& id);
......@@ -82,6 +86,9 @@ class ASH_EXPORT MessageListView : public views::View,
}
void set_scroller(views::ScrollView* scroller) { scroller_ = scroller; }
// Overridden from MessageView::SlideObserver
void OnSlideChanged(const std::string& notification_id) override;
protected:
// Overridden from views::View.
void Layout() override;
......@@ -121,7 +128,7 @@ class ASH_EXPORT MessageListView : public views::View,
// Schedules animation for a child to the specified position. Returns false
// if |child| will disappear after the animation.
bool AnimateChild(views::View* child,
bool AnimateChild(views::View* child, // message_center::SlidableMessageView
int top,
int height,
bool animate_even_on_move);
......
......@@ -17,11 +17,13 @@
#include "ui/message_center/notification_list.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/message_center/views/notification_view_md.h"
#include "ui/message_center/views/slidable_message_view.h"
#include "ui/views/test/views_test_base.h"
using ::testing::ElementsAre;
using message_center::Notification;
using message_center::NotificationViewMD;
using message_center::SlidableMessageView;
using message_center::NotifierId;
using message_center::NOTIFICATION_TYPE_SIMPLE;
......@@ -435,6 +437,19 @@ TEST_F(MessageListViewTest, ClearAllClosableNotifications) {
EXPECT_TRUE(is_on_all_notifications_cleared_called());
}
bool ContainsMessageView(MessageListView* message_list_view,
NotificationViewMD* notification_view) {
for (int i = 0; i < message_list_view->child_count(); i++) {
DCHECK_EQ(std::string(SlidableMessageView::kViewClassName),
message_list_view->child_at(i)->GetClassName());
if (static_cast<SlidableMessageView*>(message_list_view->child_at(i))
->GetMessageView() == notification_view) {
return true;
}
}
return false;
}
// Regression test for crbug.com/713983
TEST_F(MessageListViewTest, RemoveWhileClearAll) {
message_list_view()->SetBounds(0, 0, 800, 600);
......@@ -460,11 +475,11 @@ TEST_F(MessageListViewTest, RemoveWhileClearAll) {
RunPendingAnimations();
// Call RemoveNotification()
EXPECT_TRUE(message_list_view()->Contains(notification_view2));
EXPECT_TRUE(ContainsMessageView(message_list_view(), notification_view2));
message_list_view()->RemoveNotification(notification_view2);
// Call "Clear All" while notification_view2 is still in message_list_view.
EXPECT_TRUE(message_list_view()->Contains(notification_view2));
EXPECT_TRUE(ContainsMessageView(message_list_view(), notification_view2));
message_list_view()->ClearAllClosableNotifications(
message_list_view()->bounds());
......
......@@ -345,6 +345,7 @@ void UnifiedMessageCenterView::AddNotificationAt(
MessageView* view = message_center::MessageViewFactory::Create(
notification, /*top-level=*/false);
view->AddObserver(this);
view->AddSlideObserver(message_list_view_);
view->set_scroller(scroller_);
message_list_view_->AddNotificationAt(view, index);
}
......
......@@ -144,6 +144,8 @@ jumbo_component("message_center") {
"views/popup_alignment_delegate.h",
"views/proportional_image_view.cc",
"views/proportional_image_view.h",
"views/slidable_message_view.cc",
"views/slidable_message_view.h",
"views/slide_out_controller.cc",
"views/slide_out_controller.h",
]
......
......@@ -310,7 +310,15 @@ ui::Layer* MessageView::GetSlideOutLayer() {
return is_nested_ ? layer() : GetWidget()->GetLayer();
}
void MessageView::OnSlideChanged() {}
void MessageView::OnSlideChanged() {
for (auto* observer : slide_observers_) {
observer->OnSlideChanged(notification_id_);
}
}
void MessageView::AddSlideObserver(MessageView::SlideObserver* observer) {
slide_observers_.push_back(observer);
}
void MessageView::OnSlideOut() {
MessageCenter::Get()->RemoveNotification(notification_id_,
......@@ -358,10 +366,12 @@ void MessageView::OnCloseButtonPressed() {
}
void MessageView::OnSettingsButtonPressed(const ui::Event& event) {
slide_out_controller_.CloseSwipeControl();
MessageCenter::Get()->ClickOnSettingsButton(notification_id_);
}
void MessageView::OnSnoozeButtonPressed(const ui::Event& event) {
slide_out_controller_.CloseSwipeControl();
// No default implementation for snooze.
}
......
......@@ -42,6 +42,11 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::InkDropHostView,
public:
static const char kViewClassName[];
class SlideObserver {
public:
virtual void OnSlideChanged(const std::string& notification_id) = 0;
};
enum class Mode {
// Normal mode.
NORMAL = 0,
......@@ -117,6 +122,8 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::InkDropHostView,
void OnSlideChanged() override;
void OnSlideOut() override;
void AddSlideObserver(SlideObserver* observer);
Mode GetMode() const;
// Gets the current horizontal scroll offset of the view by slide gesture.
......@@ -166,6 +173,7 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::InkDropHostView,
std::unique_ptr<views::Painter> focus_painter_;
SlideOutController slide_out_controller_;
std::vector<SlideObserver*> slide_observers_;
// True if |this| is embedded in another view. Equivalent to |!top_level| in
// MessageViewFactory parlance.
......
......@@ -92,8 +92,10 @@ class NotificationTestDelegate : public NotificationDelegate {
DISALLOW_COPY_AND_ASSIGN(NotificationTestDelegate);
};
class NotificationViewMDTest : public views::ViewsTestBase,
public views::ViewObserver {
class NotificationViewMDTest
: public views::ViewsTestBase,
public views::ViewObserver,
public message_center::MessageView::SlideObserver {
public:
NotificationViewMDTest();
~NotificationViewMDTest() override;
......@@ -113,6 +115,9 @@ class NotificationViewMDTest : public views::ViewsTestBase,
return widget_;
}
// Overridden from message_center::MessageView::Observer:
void OnSlideChanged(const std::string& notification_id) override {}
protected:
const gfx::Image CreateTestImage(int width, int height) const;
const SkBitmap CreateBitmap(int width, int height) const;
......
// Copyright (c) 2018 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.
#include "ui/message_center/views/slidable_message_view.h"
#include "ui/message_center/public/cpp/features.h"
#include "ui/message_center/public/cpp/message_center_constants.h"
#include "ui/message_center/views/message_view.h"
#include "ui/views/background.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view.h"
namespace message_center {
SlidableMessageView::SlidableMessageView(MessageView* message_view)
: message_view_(message_view) {
SetFocusBehavior(views::View::FocusBehavior::NEVER);
// Draw on its own layer to allow bound animation.
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
if (base::FeatureList::IsEnabled(message_center::kNotificationSwipeControl))
SetBackground(views::CreateSolidBackground(kSwipeControlBackgroundColor));
SetLayoutManager(std::make_unique<views::FillLayout>());
// TODO(crbug.com/840497): Add button container child view.
message_view_->AddSlideObserver(this);
AddChildView(message_view);
}
SlidableMessageView::~SlidableMessageView() = default;
void SlidableMessageView::OnSlideChanged(const std::string& notification_id) {
// TODO(crbug.com/840497): Show/hide control buttons.
}
void SlidableMessageView::CloseSwipeControl() {
message_view_->CloseSwipeControl();
}
void SlidableMessageView::ChildPreferredSizeChanged(views::View* child) {
PreferredSizeChanged();
InvalidateLayout();
}
void SlidableMessageView::ChildVisibilityChanged(views::View* child) {
PreferredSizeChanged();
InvalidateLayout();
}
void SlidableMessageView::UpdateWithNotification(
const Notification& notification) {
message_view_->UpdateWithNotification(notification);
}
gfx::Size SlidableMessageView::CalculatePreferredSize() const {
return message_view_->GetPreferredSize();
}
int SlidableMessageView::GetHeightForWidth(int width) const {
return message_view_->GetHeightForWidth(width);
}
} // namespace message_center
// Copyright (c) 2018 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.
#ifndef UI_MESSAGE_CENTER_VIEWS_SLIDABLE_MESSAGE_VIEW_H_
#define UI_MESSAGE_CENTER_VIEWS_SLIDABLE_MESSAGE_VIEW_H_
#include "ui/message_center/views/message_view.h"
#include "ui/views/view.h"
namespace message_center {
class MESSAGE_CENTER_EXPORT SlidableMessageView
: public views::View,
public MessageView::SlideObserver {
public:
SlidableMessageView(message_center::MessageView* message_view);
~SlidableMessageView() override;
MessageView* GetMessageView() const { return message_view_; }
// MessageView::SlideObserver
void OnSlideChanged(const std::string& notification_id) override;
NotificationControlButtonsView* GetControlButtonsView() {
return message_view_->GetControlButtonsView();
}
void UpdateControlButtonsVisibility() {
return message_view_->UpdateControlButtonsVisibility();
}
void SetExpanded(bool expanded) {
return message_view_->SetExpanded(expanded);
}
bool IsExpanded() const { return message_view_->IsExpanded(); }
bool IsAutoExpandingAllowed() const {
return message_view_->IsAutoExpandingAllowed();
}
bool IsCloseButtonFocused() const {
return message_view_->IsCloseButtonFocused();
}
bool IsManuallyExpandedOrCollapsed() const {
return message_view_->IsManuallyExpandedOrCollapsed();
}
void SetManuallyExpandedOrCollapsed(bool value) {
return message_view_->SetManuallyExpandedOrCollapsed(value);
}
// Updates this view with the new data contained in the notification.
void UpdateWithNotification(const Notification& notification);
std::string notification_id() const {
return message_view_->notification_id();
}
MessageView::Mode GetMode() const { return message_view_->GetMode(); }
void CloseSwipeControl();
void StartDismissAnimation();
// views::View
void ChildPreferredSizeChanged(views::View* child) override;
void ChildVisibilityChanged(views::View* child) override;
gfx::Size CalculatePreferredSize() const override;
int GetHeightForWidth(int width) const override;
private:
MessageView* message_view_;
// TODO(crbug.com/840497): Add child view containing settings and snooze
// buttons.
};
} // namespace message_center
#endif // UI_MESSAGE_CENTER_VIEWS_SLIDABLE_MESSAGE_VIEW_H_q
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment