Commit aec33eab authored by Andrew Xu's avatar Andrew Xu Committed by Commit Bot

Provide feedback for pinning app - part 1

To solve the issue 1012772, we need to implement an interface to
scroll the shelf view to show the icon for a given app id. This CL
provides the following helper functions:
(1) Calculates the offset distance of scrolling Shelf to the
previous/next page.
(2) Calculates the layout strategy for the given scroll distance.
(3) Calculates the first/last tappable app indices for the given
layout strategy and scroll offset.

No UI changes should be introduced by this CL.

Bug: 1012772
Change-Id: I3aa27d0fa035f9a9a3186bbe9963065afe465f89
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1762558Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Andrew Xu <andrewxu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#715870}
parent aa63b9ce
......@@ -487,7 +487,7 @@ void ScrollableShelfView::OnFocusRingActivationChanged(bool activated) {
}
void ScrollableShelfView::ScrollToNewPage(bool forward) {
float offset = CalculatePageScrollingOffset(forward);
const float offset = CalculatePageScrollingOffset(forward, layout_strategy_);
if (GetShelf()->IsHorizontalAlignment())
ScrollByXOffset(offset, /*animating=*/true);
else
......@@ -596,25 +596,25 @@ void ScrollableShelfView::StartShelfScrollAnimation(float scroll_distance) {
shelf_view_->layer()->SetTransform(current_transform);
}
void ScrollableShelfView::UpdateLayoutStrategy() {
if (CanFitAllAppsWithoutScrolling()) {
layout_strategy_ = kNotShowArrowButtons;
return;
}
ScrollableShelfView::LayoutStrategy
ScrollableShelfView::CalculateLayoutStrategy(
int scroll_distance_on_main_axis) const {
if (CanFitAllAppsWithoutScrolling())
return kNotShowArrowButtons;
int scroll_length = GetShelf()->IsHorizontalAlignment() ? scroll_offset_.x()
: scroll_offset_.y();
if (scroll_length == 0) {
if (scroll_distance_on_main_axis == 0) {
// No invisible shelf buttons at the left side. So hide the left button.
layout_strategy_ = kShowRightArrowButton;
} else if (scroll_length == CalculateScrollUpperBound()) {
return kShowRightArrowButton;
}
if (scroll_distance_on_main_axis == CalculateScrollUpperBound()) {
// If there is no invisible shelf button at the right side, hide the right
// button.
layout_strategy_ = kShowLeftArrowButton;
} else {
// There are invisible shelf buttons at both sides. So show two buttons.
layout_strategy_ = kShowButtons;
return kShowLeftArrowButton;
}
// There are invisible shelf buttons at both sides. So show two buttons.
return kShowButtons;
}
bool ScrollableShelfView::ShouldAdaptToRTL() const {
......@@ -681,7 +681,7 @@ void ScrollableShelfView::Layout() {
else
scroll_offset_.set_y(CalculateClampedScrollOffset(scroll_offset_.y()));
UpdateLayoutStrategy();
layout_strategy_ = CalculateLayoutStrategy(CalculateMainAxisScrollDistance());
gfx::Size arrow_button_size(kArrowButtonSize, kArrowButtonSize);
gfx::Rect shelf_container_bounds = gfx::Rect(size());
......@@ -1221,7 +1221,7 @@ bool ScrollableShelfView::ProcessGestureEvent(const ui::GestureEvent& event) {
? event.details().velocity_x()
: event.details().velocity_y();
float page_scrolling_offset =
CalculatePageScrollingOffset(scroll_velocity < 0);
CalculatePageScrollingOffset(scroll_velocity < 0, layout_strategy_);
if (is_horizontal_alignment) {
ScrollToXOffset(
scroll_offset_before_main_axis_scrolling_.x() + page_scrolling_offset,
......@@ -1277,11 +1277,13 @@ void ScrollableShelfView::HandleMouseWheelEvent(ui::MouseWheelEvent* event) {
// contents.
float max_absolute_offset =
abs(x_offset) > abs(y_offset) ? x_offset : y_offset;
ScrollByXOffset(CalculatePageScrollingOffset(max_absolute_offset < 0),
/*animating=*/true);
ScrollByXOffset(
CalculatePageScrollingOffset(max_absolute_offset < 0, layout_strategy_),
/*animating=*/true);
} else {
ScrollByYOffset(CalculatePageScrollingOffset(event->y_offset() < 0),
/*animating=*/true);
ScrollByYOffset(
CalculatePageScrollingOffset(event->y_offset() < 0, layout_strategy_),
/*animating=*/true);
}
}
......@@ -1316,8 +1318,15 @@ void ScrollableShelfView::ScrollToYOffset(float y_target_offset,
StartShelfScrollAnimation(diff);
}
float ScrollableShelfView::CalculatePageScrollingOffset(bool forward) const {
DCHECK_NE(kNotShowArrowButtons, layout_strategy_);
float ScrollableShelfView::CalculatePageScrollingOffset(
bool forward,
LayoutStrategy layout_strategy) const {
// Returns zero if inputs are invalid.
const bool invalid = (layout_strategy == kNotShowArrowButtons) ||
(layout_strategy == kShowLeftArrowButton && forward) ||
(layout_strategy == kShowRightArrowButton && !forward);
if (invalid)
return 0;
// Implement the arrow button handler in the same way with the gesture
// scrolling. The key is to calculate the suitable scroll distance.
......@@ -1327,7 +1336,7 @@ float ScrollableShelfView::CalculatePageScrollingOffset(bool forward) const {
// The available space for icons excluding the area taken by arrow button(s).
int space_excluding_arrow;
if (layout_strategy_ == kShowRightArrowButton) {
if (layout_strategy == kShowRightArrowButton) {
space_excluding_arrow = GetSpaceForIcons() - kArrowButtonGroupWidth;
// After scrolling, the left arrow button will show. Adapts the offset
......@@ -1337,15 +1346,15 @@ float ScrollableShelfView::CalculatePageScrollingOffset(bool forward) const {
const int mod = space_excluding_arrow % GetUnit();
offset = space_excluding_arrow - mod - offset_for_extra_arrow;
} else if (layout_strategy_ == kShowButtons ||
layout_strategy_ == kShowLeftArrowButton) {
} else if (layout_strategy == kShowButtons ||
layout_strategy == kShowLeftArrowButton) {
space_excluding_arrow = GetSpaceForIcons() - 2 * kArrowButtonGroupWidth;
const int mod = space_excluding_arrow % GetUnit();
offset = space_excluding_arrow - mod;
// Layout of kShowLeftArrowButton can be regarded as the layout of
// kShowButtons with extra offset.
if (layout_strategy_ == kShowLeftArrowButton) {
if (layout_strategy == kShowLeftArrowButton) {
const int extra_offset =
-ShelfConfig::Get()->button_spacing() -
(GetSpaceForIcons() - kArrowButtonGroupWidth) % GetUnit() +
......@@ -1464,46 +1473,57 @@ void ScrollableShelfView::UpdateGradientZoneState() {
}
int ScrollableShelfView::GetActualScrollOffset() const {
int scroll_distance = GetShelf()->IsHorizontalAlignment()
? scroll_offset_.x()
: scroll_offset_.y();
int scroll_distance = CalculateMainAxisScrollDistance();
if (left_arrow_->GetVisible())
scroll_distance += (kArrowButtonGroupWidth - GetAppIconEndPadding());
return scroll_distance;
}
void ScrollableShelfView::UpdateTappableIconIndices() {
if (layout_strategy_ == kNotShowArrowButtons) {
first_tappable_app_index_ = shelf_view_->first_visible_index();
last_tappable_app_index_ = shelf_view_->last_visible_index();
return;
const std::pair<int, int> tappable_indices = CalculateTappableIconIndices(
layout_strategy_, CalculateMainAxisScrollDistance());
first_tappable_app_index_ = tappable_indices.first;
last_tappable_app_index_ = tappable_indices.second;
}
std::pair<int, int> ScrollableShelfView::CalculateTappableIconIndices(
ScrollableShelfView::LayoutStrategy layout_strategy,
int scroll_distance_on_main_axis) const {
std::pair<int, int> tappable_icon_indices;
int& first_tappable_app_index = tappable_icon_indices.first;
int& last_tappable_app_index = tappable_icon_indices.second;
if (layout_strategy == ScrollableShelfView::kNotShowArrowButtons) {
first_tappable_app_index = shelf_view_->first_visible_index();
last_tappable_app_index = shelf_view_->last_visible_index();
return tappable_icon_indices;
}
const int scroll_distance_on_main_axis = GetShelf()->IsHorizontalAlignment()
? scroll_offset_.x()
: scroll_offset_.y();
const int visible_size = GetShelf()->IsHorizontalAlignment()
? visible_space_.width()
: visible_space_.height();
if (layout_strategy_ == kShowRightArrowButton ||
layout_strategy_ == kShowButtons) {
first_tappable_app_index_ = scroll_distance_on_main_axis / GetUnit() +
(layout_strategy_ == kShowButtons ? 1 : 0);
last_tappable_app_index_ =
first_tappable_app_index_ + visible_size / GetUnit();
if (layout_strategy == kShowRightArrowButton ||
layout_strategy == kShowButtons) {
first_tappable_app_index = scroll_distance_on_main_axis / GetUnit() +
(layout_strategy == kShowButtons ? 1 : 0);
last_tappable_app_index =
first_tappable_app_index + visible_size / GetUnit();
const int end_of_last_tappable_app = last_tappable_app_index_ * GetUnit() +
const int end_of_last_tappable_app = last_tappable_app_index * GetUnit() +
ShelfConfig::Get()->button_size() -
scroll_distance_on_main_axis;
if (end_of_last_tappable_app > visible_size)
last_tappable_app_index_--;
last_tappable_app_index--;
} else {
DCHECK_EQ(layout_strategy_, kShowLeftArrowButton);
last_tappable_app_index_ = shelf_view_->last_visible_index();
first_tappable_app_index_ =
last_tappable_app_index_ - visible_size / GetUnit() + 1;
DCHECK_EQ(layout_strategy, kShowLeftArrowButton);
last_tappable_app_index = shelf_view_->last_visible_index();
first_tappable_app_index =
last_tappable_app_index - visible_size / GetUnit() + 1;
}
return tappable_icon_indices;
}
views::View* ScrollableShelfView::FindFirstFocusableChild() {
......@@ -1576,9 +1596,7 @@ void ScrollableShelfView::AdjustOffset() {
int ScrollableShelfView::CalculateAdjustedOffset() const {
// Returns early when it does not need to adjust the shelf view's location.
const int scroll_distance = GetShelf()->IsHorizontalAlignment()
? scroll_offset_.x()
: scroll_offset_.y();
const int scroll_distance = CalculateMainAxisScrollDistance();
if (scroll_distance >= CalculateScrollUpperBound())
return 0;
......@@ -1713,4 +1731,9 @@ bool ScrollableShelfView::ShouldDelegateScrollToShelf(
return std::abs(main_offset) < std::abs(cross_offset);
}
float ScrollableShelfView::CalculateMainAxisScrollDistance() const {
return GetShelf()->IsHorizontalAlignment() ? scroll_offset_.x()
: scroll_offset_.y();
}
} // namespace ash
......@@ -150,8 +150,10 @@ class ASH_EXPORT ScrollableShelfView : public views::AccessiblePaneView,
// Creates the animation for scrolling shelf by |scroll_distance|.
void StartShelfScrollAnimation(float scroll_distance);
// Updates the layout strategy based on the available space.
void UpdateLayoutStrategy();
// Calculates the layout strategy based on the available space and scroll
// distance.
LayoutStrategy CalculateLayoutStrategy(
int scroll_distance_on_main_axis) const;
// Returns whether the view should adapt to RTL.
bool ShouldAdaptToRTL() const;
......@@ -246,9 +248,11 @@ class ASH_EXPORT ScrollableShelfView : public views::AccessiblePaneView,
void ScrollToXOffset(float x_target_offset, bool animating);
void ScrollToYOffset(float y_target_offset, bool animating);
// Calculates the distance of scrolling to show a new page of shelf icons.
// |forward| indicates whether the next page or previous page is shown.
float CalculatePageScrollingOffset(bool forward) const;
// Calculates the scroll distance to show a new page of shelf icons for
// the given layout strategy. |forward| indicates whether the next page or
// previous page is shown.
float CalculatePageScrollingOffset(bool forward,
LayoutStrategy layout_strategy) const;
// Updates the gradient zone.
void UpdateGradientZone();
......@@ -270,6 +274,14 @@ class ASH_EXPORT ScrollableShelfView : public views::AccessiblePaneView,
// Updates |first_tappable_app_index_| and |last_tappable_app_index_|.
void UpdateTappableIconIndices();
// Calculates the indices of the first/last tappable app under the given
// layout strategy and offset along the main axis (that is the x-axis when
// shelf is horizontally aligned or the y-axis if the shelf is vertically
// aligned).
std::pair<int, int> CalculateTappableIconIndices(
LayoutStrategy layout_strategy,
int scroll_distance_on_main_axis) const;
views::View* FindFirstFocusableChild();
views::View* FindLastFocusableChild();
......@@ -313,6 +325,9 @@ class ASH_EXPORT ScrollableShelfView : public views::AccessiblePaneView,
// to the shelf.
bool ShouldDelegateScrollToShelf(const ui::ScrollEvent& event) const;
// Calculates the scroll distance along the main axis.
float CalculateMainAxisScrollDistance() const;
LayoutStrategy layout_strategy_ = kNotShowArrowButtons;
// Child views Owned by views hierarchy.
......
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