Commit 5f02ed6a authored by Andrew Xu's avatar Andrew Xu Committed by Commit Bot

Separate the edge padding into two parts

Edge padding of scrollable shelf logically consists of two parts:
the minimum gap between scrollable shelf and other components
(such as status area widget) and the gap decided by centering strategy
(display centering, view centering or overflow). This CL separates the
edge padding into those two parts. It improves the code readability.

In addition, currently the shelf view does not notify the parent view
of the added icon. This CL also fixes it.

Change-Id: Id10263b7b532230539cac5d179d7534ca050ef87
Bug: 1041702
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2052593
Commit-Queue: Andrew Xu <andrewxu@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#745522}
parent 170129c9
...@@ -479,6 +479,7 @@ ScrollableShelfView::ScrollableShelfView(ShelfModel* model, Shelf* shelf) ...@@ -479,6 +479,7 @@ ScrollableShelfView::ScrollableShelfView(ShelfModel* model, Shelf* shelf)
shelf, shelf,
/*drag_and_drop_host=*/this, /*drag_and_drop_host=*/this,
/*shelf_button_delegate=*/this)), /*shelf_button_delegate=*/this)),
base_padding_(ShelfConfig::Get()->app_icon_group_margin()),
page_flip_time_threshold_(kShelfPageFlipDelay), page_flip_time_threshold_(kShelfPageFlipDelay),
animation_metrics_reporter_( animation_metrics_reporter_(
std::make_unique<ScrollableShelfAnimationMetricsReporter>()) { std::make_unique<ScrollableShelfAnimationMetricsReporter>()) {
...@@ -597,10 +598,13 @@ bool ScrollableShelfView::ShouldAdaptToRTL() const { ...@@ -597,10 +598,13 @@ bool ScrollableShelfView::ShouldAdaptToRTL() const {
gfx::Rect ScrollableShelfView::GetTargetScreenBoundsOfItemIcon( gfx::Rect ScrollableShelfView::GetTargetScreenBoundsOfItemIcon(
const ShelfID& id) const { const ShelfID& id) const {
// Calculates the available space for child views based on the target bounds. // Calculates the available space for child views based on the target bounds.
const gfx::Insets edge_padding = const gfx::Insets target_extra_edge_padding =
CalculateEdgePadding(/*use_target_bounds=*/true); CalculateExtraEdgePadding(/*use_target_bounds=*/true);
const gfx::Insets target_base_edge_padding = CalculateBaseEdgePadding();
const gfx::Insets target_total_edge_padding =
target_extra_edge_padding + target_base_edge_padding;
gfx::Rect target_space = GetAvailableLocalBounds(/*use_target_bounds=*/true); gfx::Rect target_space = GetAvailableLocalBounds(/*use_target_bounds=*/true);
target_space.Inset(edge_padding); target_space.Inset(target_total_edge_padding);
const int target_scroll_offset = const int target_scroll_offset =
CalculateScrollOffsetForTargetAvailableSpace(target_space); CalculateScrollOffsetForTargetAvailableSpace(target_space);
...@@ -608,13 +612,19 @@ gfx::Rect ScrollableShelfView::GetTargetScreenBoundsOfItemIcon( ...@@ -608,13 +612,19 @@ gfx::Rect ScrollableShelfView::GetTargetScreenBoundsOfItemIcon(
gfx::Rect icon_bounds = shelf_view_->view_model()->ideal_bounds( gfx::Rect icon_bounds = shelf_view_->view_model()->ideal_bounds(
shelf_view_->model()->ItemIndexByID(id)); shelf_view_->model()->ItemIndexByID(id));
icon_bounds.Offset(edge_padding.left() - padding_insets_.left(), 0); icon_bounds.Offset(
target_total_edge_padding.left() - GetTotalEdgePadding().left(), 0);
// Transforms |icon_bounds| from shelf view's coordinates to scrollable shelf // Transforms |icon_bounds| from shelf view's coordinates to scrollable shelf
// view's coordinates manually. // view's coordinates manually.
const bool is_horizontal_alignment = GetShelf()->IsHorizontalAlignment();
const int shelf_view_offset = ShelfConfig::Get()->GetAppIconEndPadding();
const int shelf_view_container_offset =
is_horizontal_alignment ? shelf_container_view_->bounds().x()
: shelf_container_view_->bounds().y();
const int delta = const int delta =
-target_scroll_offset + ShelfConfig::Get()->GetAppIconEndPadding(); -target_scroll_offset + shelf_view_container_offset + shelf_view_offset;
const gfx::Vector2d bounds_offset = GetShelf()->IsHorizontalAlignment() const gfx::Vector2d bounds_offset = is_horizontal_alignment
? gfx::Vector2d(delta, 0) ? gfx::Vector2d(delta, 0)
: gfx::Vector2d(0, delta); : gfx::Vector2d(0, delta);
icon_bounds.Offset(bounds_offset); icon_bounds.Offset(bounds_offset);
...@@ -771,30 +781,6 @@ ScrollableShelfView::CalculateLayoutStrategy(float scroll_distance_on_main_axis, ...@@ -771,30 +781,6 @@ ScrollableShelfView::CalculateLayoutStrategy(float scroll_distance_on_main_axis,
return kShowButtons; return kShowButtons;
} }
bool ScrollableShelfView::ShouldApplyDisplayCentering(
bool use_target_bounds) const {
if (!CanFitAllAppsWithoutScrolling(use_target_bounds))
return false;
const gfx::Rect display_bounds =
screen_util::GetDisplayBoundsWithShelf(GetWidget()->GetNativeWindow());
const int display_size_primary = GetShelf()->PrimaryAxisValue(
display_bounds.width(), display_bounds.height());
const int status_widget_size =
GetStatusWidgetSizeOnPrimaryAxis(use_target_bounds);
// An easy way to check whether the apps fit at the exact center of the
// screen is to imagine that we have another status widget on the other
// side (the status widget is always bigger than the home button plus
// the back button if applicable) and see if the apps can fit in the middle
int available_space_for_screen_centering =
display_size_primary -
2 * (status_widget_size + ShelfConfig::Get()->app_icon_group_margin());
return available_space_for_screen_centering >
shelf_view_->GetSizeOfAppIcons(shelf_view_->number_of_visible_apps(),
false);
}
Shelf* ScrollableShelfView::GetShelf() { Shelf* ScrollableShelfView::GetShelf() {
return const_cast<Shelf*>( return const_cast<Shelf*>(
const_cast<const ScrollableShelfView*>(this)->GetShelf()); const_cast<const ScrollableShelfView*>(this)->GetShelf());
...@@ -810,14 +796,15 @@ gfx::Size ScrollableShelfView::CalculatePreferredSize() const { ...@@ -810,14 +796,15 @@ gfx::Size ScrollableShelfView::CalculatePreferredSize() const {
void ScrollableShelfView::Layout() { void ScrollableShelfView::Layout() {
gfx::Rect shelf_container_bounds = gfx::Rect(size()); gfx::Rect shelf_container_bounds = gfx::Rect(size());
gfx::Size arrow_button_size(kArrowButtonSize, shelf_container_bounds.Inset(base_padding_insets_);
shelf_container_bounds.height());
// Transpose and layout as if it is horizontal. // Transpose and layout as if it is horizontal.
const bool is_horizontal = GetShelf()->IsHorizontalAlignment(); const bool is_horizontal = GetShelf()->IsHorizontalAlignment();
if (!is_horizontal) if (!is_horizontal)
shelf_container_bounds.Transpose(); shelf_container_bounds.Transpose();
gfx::Size arrow_button_size(kArrowButtonSize,
shelf_container_bounds.height());
gfx::Size arrow_button_group_size(kArrowButtonGroupWidth, gfx::Size arrow_button_group_size(kArrowButtonGroupWidth,
shelf_container_bounds.height()); shelf_container_bounds.height());
...@@ -826,16 +813,18 @@ void ScrollableShelfView::Layout() { ...@@ -826,16 +813,18 @@ void ScrollableShelfView::Layout() {
gfx::Rect left_arrow_bounds; gfx::Rect left_arrow_bounds;
gfx::Rect right_arrow_bounds; gfx::Rect right_arrow_bounds;
const int before_padding = const int before_padding = is_horizontal ? extra_padding_insets_.left()
is_horizontal ? padding_insets_.left() : padding_insets_.top(); : extra_padding_insets_.top();
const int after_padding = const int after_padding = is_horizontal ? extra_padding_insets_.right()
is_horizontal ? padding_insets_.right() : padding_insets_.bottom(); : extra_padding_insets_.bottom();
// Calculates the bounds of the left arrow button. If the left arrow button // Calculates the bounds of the left arrow button. If the left arrow button
// should not show, |left_arrow_bounds| should be empty. // should not show, |left_arrow_bounds| should be empty.
if (layout_strategy_ == kShowLeftArrowButton || if (layout_strategy_ == kShowLeftArrowButton ||
layout_strategy_ == kShowButtons) { layout_strategy_ == kShowButtons) {
left_arrow_bounds = gfx::Rect(arrow_button_group_size); gfx::Point left_arrow_start_point(shelf_container_bounds.x(), 0);
left_arrow_bounds =
gfx::Rect(left_arrow_start_point, arrow_button_group_size);
left_arrow_bounds.Offset(before_padding, 0); left_arrow_bounds.Offset(before_padding, 0);
left_arrow_bounds.Inset(kArrowButtonEndPadding, 0, kDistanceToArrowButton, left_arrow_bounds.Inset(kArrowButtonEndPadding, 0, kDistanceToArrowButton,
0); 0);
...@@ -941,14 +930,14 @@ void ScrollableShelfView::OnBoundsChanged(const gfx::Rect& previous_bounds) { ...@@ -941,14 +930,14 @@ void ScrollableShelfView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
gradient_layer_delegate_->layer()->SetBounds(layer()->bounds()); gradient_layer_delegate_->layer()->SetBounds(layer()->bounds());
} }
const gfx::Insets old_padding_insets = padding_insets_; const gfx::Insets old_extra_padding_insets = extra_padding_insets_;
const gfx::Vector2dF old_scroll_offset = scroll_offset_; const gfx::Vector2dF old_scroll_offset = scroll_offset_;
// The changed view bounds may lead to update on the available space. // The changed view bounds may lead to update on the available space.
UpdateAvailableSpaceAndScroll(); UpdateAvailableSpaceAndScroll();
// Relayout shelf items if the preferred padding changed. // Relayout shelf items if the preferred padding changed.
if (old_padding_insets != padding_insets_) if (old_extra_padding_insets != extra_padding_insets_)
shelf_view_->OnBoundsChanged(shelf_view_->GetBoundsInScreen()); shelf_view_->OnBoundsChanged(shelf_view_->GetBoundsInScreen());
// Avoids calling AdjustOffset() when the scrollable shelf view is // Avoids calling AdjustOffset() when the scrollable shelf view is
...@@ -1329,31 +1318,40 @@ bool ScrollableShelfView::ShouldShowRightArrow() const { ...@@ -1329,31 +1318,40 @@ bool ScrollableShelfView::ShouldShowRightArrow() const {
(layout_strategy_ == kShowButtons); (layout_strategy_ == kShowButtons);
} }
gfx::Insets ScrollableShelfView::CalculateEdgePadding( gfx::Insets ScrollableShelfView::CalculateBaseEdgePadding() const {
if (GetShelf()->IsHorizontalAlignment())
return gfx::Insets(0, base_padding_, 0, base_padding_);
return gfx::Insets(base_padding_, 0, base_padding_, 0);
}
gfx::Insets ScrollableShelfView::CalculateExtraEdgePadding(
bool use_target_bounds) const { bool use_target_bounds) const {
// Display centering alignment // Tries display centering strategy.
if (ShouldApplyDisplayCentering(use_target_bounds)) const gfx::Insets display_centering_edge_padding =
return CalculatePaddingForDisplayCentering(use_target_bounds); CalculatePaddingForDisplayCentering(use_target_bounds);
if (!display_centering_edge_padding.IsEmpty()) {
// Returns early if the value is legal.
return display_centering_edge_padding;
}
const int icons_size = shelf_view_->GetSizeOfAppIcons( const int icons_size = shelf_view_->GetSizeOfAppIcons(
shelf_view_->number_of_visible_apps(), false) + shelf_view_->number_of_visible_apps(), false) +
2 * ShelfConfig::Get()->GetAppIconEndPadding(); 2 * ShelfConfig::Get()->GetAppIconEndPadding();
const int base_padding = ShelfConfig::Get()->app_icon_group_margin();
const gfx::Rect available_local_bounds = const gfx::Rect available_local_bounds =
GetAvailableLocalBounds(use_target_bounds); GetAvailableLocalBounds(use_target_bounds);
const int available_size_for_app_icons = const int available_size_for_app_icons =
GetShelf()->PrimaryAxisValue(available_local_bounds.width(), GetShelf()->PrimaryAxisValue(available_local_bounds.width(),
available_local_bounds.height()) - available_local_bounds.height()) -
2 * ShelfConfig::Get()->app_icon_group_margin(); 2 * base_padding_;
int gap = CanFitAllAppsWithoutScrolling(use_target_bounds) int gap = CanFitAllAppsWithoutScrolling(use_target_bounds)
? available_size_for_app_icons - icons_size // shelf centering ? available_size_for_app_icons - icons_size // shelf centering
: 0; // overflow : 0; // overflow
// Calculates the paddings before/after the visible area of scrollable shelf. // Calculates the paddings before/after the visible area of scrollable shelf.
const int before_padding = base_padding + gap / 2; const int before_padding = gap / 2;
const int after_padding = base_padding + (gap % 2 ? gap / 2 + 1 : gap / 2); const int after_padding = (gap % 2 ? gap / 2 + 1 : gap / 2);
gfx::Insets padding_insets; gfx::Insets padding_insets;
if (GetShelf()->IsHorizontalAlignment()) { if (GetShelf()->IsHorizontalAlignment()) {
...@@ -1367,6 +1365,10 @@ gfx::Insets ScrollableShelfView::CalculateEdgePadding( ...@@ -1367,6 +1365,10 @@ gfx::Insets ScrollableShelfView::CalculateEdgePadding(
return padding_insets; return padding_insets;
} }
gfx::Insets ScrollableShelfView::GetTotalEdgePadding() const {
return extra_padding_insets_ + base_padding_insets_;
}
int ScrollableShelfView::GetStatusWidgetSizeOnPrimaryAxis( int ScrollableShelfView::GetStatusWidgetSizeOnPrimaryAxis(
bool use_target_bounds) const { bool use_target_bounds) const {
const gfx::Size status_widget_size = const gfx::Size status_widget_size =
...@@ -1403,14 +1405,22 @@ gfx::Insets ScrollableShelfView::CalculatePaddingForDisplayCentering( ...@@ -1403,14 +1405,22 @@ gfx::Insets ScrollableShelfView::CalculatePaddingForDisplayCentering(
const gfx::Rect screen_bounds = const gfx::Rect screen_bounds =
use_target_bounds ? GetShelf()->hotseat_widget()->GetTargetBounds() use_target_bounds ? GetShelf()->hotseat_widget()->GetTargetBounds()
: GetBoundsInScreen(); : GetBoundsInScreen();
const int before_padding = gap - GetShelf()->PrimaryAxisValue( int before_padding = gap - GetShelf()->PrimaryAxisValue(
screen_bounds.x() - display_bounds.x(), screen_bounds.x() - display_bounds.x(),
screen_bounds.y() - display_bounds.y()); screen_bounds.y() - display_bounds.y());
const int after_padding = int after_padding =
gap - GetShelf()->PrimaryAxisValue( gap - GetShelf()->PrimaryAxisValue(
display_bounds.right() - screen_bounds.right(), display_bounds.right() - screen_bounds.right(),
display_bounds.bottom() - screen_bounds.bottom()); display_bounds.bottom() - screen_bounds.bottom());
before_padding -= base_padding_;
after_padding -= base_padding_;
// Checks whether there is enough space to ensure |base_padding_|. Returns
// empty insets if not.
if (before_padding < 0 || after_padding < 0)
return gfx::Insets();
gfx::Insets padding_insets; gfx::Insets padding_insets;
if (GetShelf()->IsHorizontalAlignment()) { if (GetShelf()->IsHorizontalAlignment()) {
padding_insets = padding_insets =
...@@ -1994,9 +2004,12 @@ int ScrollableShelfView::CalculateScrollDistanceAfterAdjustment( ...@@ -1994,9 +2004,12 @@ int ScrollableShelfView::CalculateScrollDistanceAfterAdjustment(
} }
void ScrollableShelfView::UpdateAvailableSpace() { void ScrollableShelfView::UpdateAvailableSpace() {
padding_insets_ = CalculateEdgePadding(/*use_target_bounds=*/false); extra_padding_insets_ =
CalculateExtraEdgePadding(/*use_target_bounds=*/false);
base_padding_insets_ = CalculateBaseEdgePadding();
available_space_ = GetLocalBounds(); available_space_ = GetLocalBounds();
available_space_.Inset(padding_insets_); available_space_.Inset(GetTotalEdgePadding());
// The hotseat uses |available_space_| to determine where to show its // The hotseat uses |available_space_| to determine where to show its
// background, so notify it when it is recalculated. // background, so notify it when it is recalculated.
...@@ -2008,11 +2021,13 @@ void ScrollableShelfView::UpdateAvailableSpace() { ...@@ -2008,11 +2021,13 @@ void ScrollableShelfView::UpdateAvailableSpace() {
// Paddings are within the shelf view. It makes sure that |shelf_view_|'s // Paddings are within the shelf view. It makes sure that |shelf_view_|'s
// bounds are not changed by adding/removing the shelf icon under the same // bounds are not changed by adding/removing the shelf icon under the same
// layout strategy. // layout strategy.
const int horizontal_inset = const int horizontal_inset = ShouldAdaptToRTL()
ShouldAdaptToRTL() ? padding_insets_.right() : padding_insets_.left(); ? extra_padding_insets_.right()
: extra_padding_insets_.left();
shelf_view_->set_app_icons_layout_offset(GetShelf()->IsHorizontalAlignment() shelf_view_->set_app_icons_layout_offset(GetShelf()->IsHorizontalAlignment()
? horizontal_inset ? horizontal_inset
: padding_insets_.top()); : extra_padding_insets_.top());
} }
gfx::Rect ScrollableShelfView::CalculateVisibleSpace( gfx::Rect ScrollableShelfView::CalculateVisibleSpace(
...@@ -2198,8 +2213,15 @@ void ScrollableShelfView::UpdateScrollOffset(float target_offset) { ...@@ -2198,8 +2213,15 @@ void ScrollableShelfView::UpdateScrollOffset(float target_offset) {
InvalidateLayout(); InvalidateLayout();
} }
// |visible_space_| is in local coordinates. It should be transformed into
// |shelf_container_view_|'s coordinates for layer clip.
visible_space_ = CalculateVisibleSpace(layout_strategy_); visible_space_ = CalculateVisibleSpace(layout_strategy_);
shelf_container_view_->layer()->SetClipRect(visible_space_); gfx::RectF visible_space_in_shelf_container_coordinates(visible_space_);
views::View::ConvertRectToTarget(
this, shelf_container_view_,
&visible_space_in_shelf_container_coordinates);
shelf_container_view_->layer()->SetClipRect(
gfx::ToEnclosedRect(visible_space_in_shelf_container_coordinates));
if (scroll_status_ != kAlongMainAxisScroll) if (scroll_status_ != kAlongMainAxisScroll)
UpdateTappableIconIndices(); UpdateTappableIconIndices();
......
...@@ -186,11 +186,6 @@ class ASH_EXPORT ScrollableShelfView : public views::AccessiblePaneView, ...@@ -186,11 +186,6 @@ class ASH_EXPORT ScrollableShelfView : public views::AccessiblePaneView,
int space_for_icons, int space_for_icons,
bool use_target_bounds) const; bool use_target_bounds) const;
// Returns whether the app icon layout should be centering alignment.
// |use_target_bounds| indicates which view bounds are used for
// calculation: actual view bounds or target view bounds.
bool ShouldApplyDisplayCentering(bool use_target_bounds) const;
Shelf* GetShelf(); Shelf* GetShelf();
const Shelf* GetShelf() const; const Shelf* GetShelf() const;
...@@ -261,13 +256,19 @@ class ASH_EXPORT ScrollableShelfView : public views::AccessiblePaneView, ...@@ -261,13 +256,19 @@ class ASH_EXPORT ScrollableShelfView : public views::AccessiblePaneView,
bool ShouldShowLeftArrow() const; bool ShouldShowLeftArrow() const;
bool ShouldShowRightArrow() const; bool ShouldShowRightArrow() const;
// Returns the padding inset. Different Padding strategies for three scenarios // Returns the padding insets which guarantee the minimum gap between
// (1) display centering alignment // scrollable shelf and other components (like status area widget).
// (2) scrollable shelf centering alignment gfx::Insets CalculateBaseEdgePadding() const;
// (3) overflow mode
// |use_target_bounds| indicates which view bounds are used for // Returns the extra padding inset which is influenced by the padding
// calculation: actual view bounds or target view bounds. // strategy. There are three strategies: (1) display centering alignment (2)
gfx::Insets CalculateEdgePadding(bool use_target_bounds) const; // scrollable shelf centering alignment (3) overflow mode
// |use_target_bounds| indicates which view bounds are used for calculation:
// actual view bounds or target view bounds.
gfx::Insets CalculateExtraEdgePadding(bool use_target_bounds) const;
// Returns the sum of the base padding and the extra padding.
gfx::Insets GetTotalEdgePadding() const;
int GetStatusWidgetSizeOnPrimaryAxis(bool use_target_bounds) const; int GetStatusWidgetSizeOnPrimaryAxis(bool use_target_bounds) const;
...@@ -441,16 +442,23 @@ class ASH_EXPORT ScrollableShelfView : public views::AccessiblePaneView, ...@@ -441,16 +442,23 @@ class ASH_EXPORT ScrollableShelfView : public views::AccessiblePaneView,
// shelf under RTL. // shelf under RTL.
gfx::Rect available_space_; gfx::Rect available_space_;
// Paddings before and after shelf icons, including the app icon group margin. ShelfView* shelf_view_ = nullptr;
gfx::Insets padding_insets_;
// Padding insets based on |base_padding_| and shelf alignment.
gfx::Insets base_padding_insets_;
// Extra insets decided by the current padding strategy.
gfx::Insets extra_padding_insets_;
// Minimum gap between scrollable shelf and other components (like status area
// widget) in DIPs.
const int base_padding_;
// Visible space of |shelf_container_view| in ScrollableShelfView's local // Visible space of |shelf_container_view| in ScrollableShelfView's local
// coordinates. Different from |available_space_|, |visible_space_| only // coordinates. Different from |available_space_|, |visible_space_| only
// contains app icons and is mirrored for horizontal shelf under RTL. // contains app icons and is mirrored for horizontal shelf under RTL.
gfx::Rect visible_space_; gfx::Rect visible_space_;
ShelfView* shelf_view_ = nullptr;
gfx::Vector2dF scroll_offset_; gfx::Vector2dF scroll_offset_;
ScrollStatus scroll_status_ = kNotInScroll; ScrollStatus scroll_status_ = kNotInScroll;
......
...@@ -778,6 +778,36 @@ TEST_F(ScrollableShelfViewTest, VerifyScrollEvent) { ...@@ -778,6 +778,36 @@ TEST_F(ScrollableShelfViewTest, VerifyScrollEvent) {
scrollable_shelf_view_->layout_strategy_for_test()); scrollable_shelf_view_->layout_strategy_for_test());
} }
// Verifies that right-click on the last shelf icon should open the icon's
// context menu instead of the shelf's (https://crbug.com/1041702).
TEST_F(ScrollableShelfViewTest, ClickAtLastIcon) {
AddAppShortcutsUntilOverflow();
ASSERT_EQ(ScrollableShelfView::kShowRightArrowButton,
scrollable_shelf_view_->layout_strategy_for_test());
// Taps at the right arrow. Hotseat layout should show the left arrow.
gfx::Rect right_arrow =
scrollable_shelf_view_->right_arrow()->GetBoundsInScreen();
GetEventGenerator()->GestureTapAt(right_arrow.CenterPoint());
ASSERT_EQ(ScrollableShelfView::kShowLeftArrowButton,
scrollable_shelf_view_->layout_strategy_for_test());
// Right-click on the edge of the last icon.
const views::View* last_icon = shelf_view_->view_model()->view_at(
scrollable_shelf_view_->last_tappable_app_index());
gfx::Point click_point = last_icon->GetBoundsInScreen().right_center();
click_point.Offset(-1, 0);
GetEventGenerator()->MoveMouseTo(click_point);
GetEventGenerator()->ClickRightButton();
// Verifies that the context menu of |last_icon| should show.
EXPECT_TRUE(shelf_view_->IsShowingMenuForView(last_icon));
// Verfies that after left-click, the context menu should be closed.
GetEventGenerator()->ClickLeftButton();
EXPECT_FALSE(shelf_view_->IsShowingMenuForView(last_icon));
}
// Tests scrollable shelf's features under both LTR and RTL. // Tests scrollable shelf's features under both LTR and RTL.
class ScrollableShelfViewRTLTest : public ScrollableShelfViewTest, class ScrollableShelfViewRTLTest : public ScrollableShelfViewTest,
public testing::WithParamInterface<bool> { public testing::WithParamInterface<bool> {
......
...@@ -195,11 +195,35 @@ class ShelfFocusSearch : public views::FocusSearch { ...@@ -195,11 +195,35 @@ class ShelfFocusSearch : public views::FocusSearch {
DISALLOW_COPY_AND_ASSIGN(ShelfFocusSearch); DISALLOW_COPY_AND_ASSIGN(ShelfFocusSearch);
}; };
// Returns the id of the display on which |view| is shown.
int64_t GetDisplayIdForView(const View* view) {
aura::Window* window = view->GetWidget()->GetNativeWindow();
return display::Screen::GetScreen()->GetDisplayNearestWindow(window).id();
}
// Whether |item_view| is a ShelfAppButton and its state is STATE_DRAGGING.
bool ShelfButtonIsInDrag(const ShelfItemType item_type,
const views::View* item_view) {
switch (item_type) {
case TYPE_PINNED_APP:
case TYPE_BROWSER_SHORTCUT:
case TYPE_APP:
return static_cast<const ShelfAppButton*>(item_view)->state() &
ShelfAppButton::STATE_DRAGGING;
case TYPE_DIALOG:
case TYPE_UNDEFINED:
return false;
}
}
} // namespace
// AnimationDelegate used when inserting a new item. This steadily increases the // AnimationDelegate used when inserting a new item. This steadily increases the
// opacity of the layer as the animation progress. // opacity of the layer as the animation progress.
class FadeInAnimationDelegate : public gfx::AnimationDelegate { class ShelfView::FadeInAnimationDelegate : public gfx::AnimationDelegate {
public: public:
explicit FadeInAnimationDelegate(views::View* view) : view_(view) {} explicit FadeInAnimationDelegate(ShelfView* host, views::View* view)
: shelf_view_(host), view_(view) {}
~FadeInAnimationDelegate() override = default; ~FadeInAnimationDelegate() override = default;
// AnimationDelegate overrides: // AnimationDelegate overrides:
...@@ -210,6 +234,7 @@ class FadeInAnimationDelegate : public gfx::AnimationDelegate { ...@@ -210,6 +234,7 @@ class FadeInAnimationDelegate : public gfx::AnimationDelegate {
void AnimationEnded(const Animation* animation) override { void AnimationEnded(const Animation* animation) override {
view_->layer()->SetOpacity(1.0f); view_->layer()->SetOpacity(1.0f);
view_->layer()->ScheduleDraw(); view_->layer()->ScheduleDraw();
shelf_view_->OnFadeInAnimationEnded();
} }
void AnimationCanceled(const Animation* animation) override { void AnimationCanceled(const Animation* animation) override {
view_->layer()->SetOpacity(1.0f); view_->layer()->SetOpacity(1.0f);
...@@ -217,34 +242,12 @@ class FadeInAnimationDelegate : public gfx::AnimationDelegate { ...@@ -217,34 +242,12 @@ class FadeInAnimationDelegate : public gfx::AnimationDelegate {
} }
private: private:
ShelfView* shelf_view_ = nullptr;
views::View* view_; views::View* view_;
DISALLOW_COPY_AND_ASSIGN(FadeInAnimationDelegate); DISALLOW_COPY_AND_ASSIGN(FadeInAnimationDelegate);
}; };
// Returns the id of the display on which |view| is shown.
int64_t GetDisplayIdForView(const View* view) {
aura::Window* window = view->GetWidget()->GetNativeWindow();
return display::Screen::GetScreen()->GetDisplayNearestWindow(window).id();
}
// Whether |item_view| is a ShelfAppButton and its state is STATE_DRAGGING.
bool ShelfButtonIsInDrag(const ShelfItemType item_type,
const views::View* item_view) {
switch (item_type) {
case TYPE_PINNED_APP:
case TYPE_BROWSER_SHORTCUT:
case TYPE_APP:
return static_cast<const ShelfAppButton*>(item_view)->state() &
ShelfAppButton::STATE_DRAGGING;
case TYPE_DIALOG:
case TYPE_UNDEFINED:
return false;
}
}
} // namespace
// AnimationDelegate used when deleting an item. This steadily decreased the // AnimationDelegate used when deleting an item. This steadily decreased the
// opacity of the layer as the animation progress. // opacity of the layer as the animation progress.
class ShelfView::FadeOutAnimationDelegate : public gfx::AnimationDelegate { class ShelfView::FadeOutAnimationDelegate : public gfx::AnimationDelegate {
...@@ -1568,7 +1571,7 @@ void ShelfView::FadeIn(views::View* view) { ...@@ -1568,7 +1571,7 @@ void ShelfView::FadeIn(views::View* view) {
AnimateToIdealBounds(); AnimateToIdealBounds();
bounds_animator_->SetAnimationDelegate( bounds_animator_->SetAnimationDelegate(
view, std::unique_ptr<gfx::AnimationDelegate>( view, std::unique_ptr<gfx::AnimationDelegate>(
new FadeInAnimationDelegate(view))); new FadeInAnimationDelegate(this, view)));
} }
void ShelfView::PrepareForDrag(Pointer pointer, const ui::LocatedEvent& event) { void ShelfView::PrepareForDrag(Pointer pointer, const ui::LocatedEvent& event) {
...@@ -2067,6 +2070,13 @@ std::pair<int, int> ShelfView::GetDragRange(int index) { ...@@ -2067,6 +2070,13 @@ std::pair<int, int> ShelfView::GetDragRange(int index) {
return std::pair<int, int>(min_index, max_index); return std::pair<int, int>(min_index, max_index);
} }
void ShelfView::OnFadeInAnimationEnded() {
// Call PreferredSizeChanged() to notify container to re-layout at the end
// of fade-in animation.
if (chromeos::switches::ShouldShowScrollableShelf())
PreferredSizeChanged();
}
void ShelfView::OnFadeOutAnimationEnded() { void ShelfView::OnFadeOutAnimationEnded() {
// Call PreferredSizeChanged() to notify container to re-layout at the end // Call PreferredSizeChanged() to notify container to re-layout at the end
// of removal animation. // of removal animation.
......
...@@ -362,6 +362,7 @@ class ASH_EXPORT ShelfView : public views::AccessiblePaneView, ...@@ -362,6 +362,7 @@ class ASH_EXPORT ShelfView : public views::AccessiblePaneView,
private: private:
friend class ShelfViewTestAPI; friend class ShelfViewTestAPI;
class FadeInAnimationDelegate;
class FadeOutAnimationDelegate; class FadeOutAnimationDelegate;
class StartFadeAnimationDelegate; class StartFadeAnimationDelegate;
...@@ -496,6 +497,9 @@ class ASH_EXPORT ShelfView : public views::AccessiblePaneView, ...@@ -496,6 +497,9 @@ class ASH_EXPORT ShelfView : public views::AccessiblePaneView,
// * In the overflow mode, returns only bubble's bounds. // * In the overflow mode, returns only bubble's bounds.
gfx::Rect GetBoundsForDragInsertInScreen(); gfx::Rect GetBoundsForDragInsertInScreen();
// Invoked after the fading in animation for item addition is ended.
void OnFadeInAnimationEnded();
// Invoked after the fading out animation for item deletion is ended. // Invoked after the fading out animation for item deletion is ended.
void OnFadeOutAnimationEnded(); void OnFadeOutAnimationEnded();
......
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