Commit 81e5f8c9 authored by Andrew Xu's avatar Andrew Xu Committed by Commit Bot

part4_scrollableshelf

Add the gradient zone to the scrollable shelf. The zone's location
is based on the layout strategy according to the new spec.

Bug: 973481
Change-Id: I2949ca70bea6219dd2df3a7cf377050f5cb8b3fe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1764765
Commit-Queue: Andrew Xu <andrewxu@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#690144}
parent 0123bd2c
...@@ -309,12 +309,13 @@ class AppsGridView::FadeoutLayerDelegate : public ui::LayerDelegate { ...@@ -309,12 +309,13 @@ class AppsGridView::FadeoutLayerDelegate : public ui::LayerDelegate {
flags.setBlendMode(SkBlendMode::kSrc); flags.setBlendMode(SkBlendMode::kSrc);
flags.setAntiAlias(false); flags.setAntiAlias(false);
flags.setShader(gfx::CreateGradientShader( flags.setShader(gfx::CreateGradientShader(
0, kFadeoutZoneHeight, SK_ColorTRANSPARENT, SK_ColorBLACK)); gfx::Point(), gfx::Point(0, kFadeoutZoneHeight), SK_ColorTRANSPARENT,
SK_ColorBLACK));
canvas->DrawRect(top_rect, flags); canvas->DrawRect(top_rect, flags);
// Draw bottom gradient zone. // Draw bottom gradient zone.
flags.setShader(gfx::CreateGradientShader( flags.setShader(gfx::CreateGradientShader(
size.height() - kFadeoutZoneHeight, size.height(), SK_ColorBLACK, gfx::Point(0, size.height() - kFadeoutZoneHeight),
SK_ColorTRANSPARENT)); gfx::Point(0, size.height()), SK_ColorBLACK, SK_ColorTRANSPARENT));
canvas->DrawRect(bottom_rect, flags); canvas->DrawRect(bottom_rect, flags);
} }
void OnDeviceScaleFactorChanged(float old_device_scale_factor, void OnDeviceScaleFactorChanged(float old_device_scale_factor,
......
...@@ -6,9 +6,11 @@ ...@@ -6,9 +6,11 @@
#include "ash/shelf/shelf_constants.h" #include "ash/shelf/shelf_constants.h"
#include "ash/shelf/shelf_widget.h" #include "ash/shelf/shelf_widget.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/vector2d_conversions.h" #include "ui/gfx/geometry/vector2d_conversions.h"
#include "ui/gfx/skia_paint_util.h"
namespace ash { namespace ash {
...@@ -42,6 +44,11 @@ int GetUnit() { ...@@ -42,6 +44,11 @@ int GetUnit() {
return ShelfConstants::button_size() + ShelfConstants::button_spacing(); return ShelfConstants::button_size() + ShelfConstants::button_spacing();
} }
// Length of the fade in/out zone.
int GetFadeZoneLength() {
return GetUnit() - kArrowButtonGroupWidth;
}
// Decides whether the current first visible shelf icon of the scrollable shelf // Decides whether the current first visible shelf icon of the scrollable shelf
// should be hidden or fully shown when gesture scroll ends. // should be hidden or fully shown when gesture scroll ends.
int GetGestureDragThreshold() { int GetGestureDragThreshold() {
...@@ -57,6 +64,80 @@ int CalculateOverflowPadding(int available_size) { ...@@ -57,6 +64,80 @@ int CalculateOverflowPadding(int available_size) {
} // namespace } // namespace
////////////////////////////////////////////////////////////////////////////////
// GradientLayerDelegate
class ScrollableShelfView::GradientLayerDelegate : public ui::LayerDelegate {
public:
struct FadeZone {
// Bounds of the fade in/out zone.
gfx::Rect zone_rect;
// Specifies the type of FadeZone: fade in or fade out.
bool fade_in = false;
// Indicates the drawing direction.
bool is_horizontal = false;
};
GradientLayerDelegate() : layer_(ui::LAYER_TEXTURED) {
layer_.set_delegate(this);
layer_.SetFillsBoundsOpaquely(false);
}
~GradientLayerDelegate() override { layer_.set_delegate(nullptr); }
void set_fade_zone(const FadeZone& fade_zone) { fade_zone_ = fade_zone; }
ui::Layer* layer() { return &layer_; }
private:
// ui::LayerDelegate:
void OnPaintLayer(const ui::PaintContext& context) override {
const gfx::Size size = layer()->size();
views::PaintInfo paint_info =
views::PaintInfo::CreateRootPaintInfo(context, size);
const auto& paint_recording_size = paint_info.paint_recording_size();
// Pass the scale factor when constructing PaintRecorder so the MaskLayer
// size is not incorrectly rounded (see https://crbug.com/921274).
ui::PaintRecorder recorder(
context, paint_info.paint_recording_size(),
static_cast<float>(paint_recording_size.width()) / size.width(),
static_cast<float>(paint_recording_size.height()) / size.height(),
nullptr);
gfx::Point start_point;
gfx::Point end_point;
if (fade_zone_.is_horizontal) {
start_point = gfx::Point(fade_zone_.zone_rect.x(), 0);
end_point = gfx::Point(fade_zone_.zone_rect.right(), 0);
} else {
start_point = gfx::Point(0, fade_zone_.zone_rect.y());
end_point = gfx::Point(0, fade_zone_.zone_rect.bottom());
}
gfx::Canvas* canvas = recorder.canvas();
canvas->DrawColor(SK_ColorBLACK, SkBlendMode::kSrc);
cc::PaintFlags flags;
flags.setBlendMode(SkBlendMode::kSrc);
flags.setAntiAlias(false);
flags.setShader(gfx::CreateGradientShader(
start_point, end_point,
fade_zone_.fade_in ? SK_ColorTRANSPARENT : SK_ColorBLACK,
fade_zone_.fade_in ? SK_ColorBLACK : SK_ColorTRANSPARENT));
canvas->DrawRect(fade_zone_.zone_rect, flags);
}
void OnDeviceScaleFactorChanged(float old_device_scale_factor,
float new_device_scale_factor) override {}
ui::Layer layer_;
FadeZone fade_zone_;
DISALLOW_COPY_AND_ASSIGN(GradientLayerDelegate);
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// ScrollableShelfView // ScrollableShelfView
...@@ -91,6 +172,9 @@ void ScrollableShelfView::Init() { ...@@ -91,6 +172,9 @@ void ScrollableShelfView::Init() {
shelf_container_view_ = shelf_container_view_ =
AddChildView(std::make_unique<ShelfContainerView>(shelf_view_)); AddChildView(std::make_unique<ShelfContainerView>(shelf_view_));
shelf_container_view_->Initialize(); shelf_container_view_->Initialize();
gradient_layer_delegate_ = std::make_unique<GradientLayerDelegate>();
layer()->SetMaskLayer(gradient_layer_delegate_->layer());
} }
views::View* ScrollableShelfView::GetShelfContainerViewForTest() { views::View* ScrollableShelfView::GetShelfContainerViewForTest() {
...@@ -246,6 +330,11 @@ void ScrollableShelfView::Layout() { ...@@ -246,6 +330,11 @@ void ScrollableShelfView::Layout() {
shelf_container_bounds.Transpose(); shelf_container_bounds.Transpose();
} }
// Check the change in |right_arrow_|'s bounds or the visibility.
const bool is_right_arrow_changed =
(right_arrow_->bounds() != right_arrow_bounds) ||
(!right_arrow_bounds.IsEmpty() && !right_arrow_->GetVisible());
// Layout |left_arrow| if it should show. // Layout |left_arrow| if it should show.
left_arrow_->SetVisible(!left_arrow_bounds.IsEmpty()); left_arrow_->SetVisible(!left_arrow_bounds.IsEmpty());
if (left_arrow_->GetVisible()) if (left_arrow_->GetVisible())
...@@ -256,6 +345,11 @@ void ScrollableShelfView::Layout() { ...@@ -256,6 +345,11 @@ void ScrollableShelfView::Layout() {
if (right_arrow_->GetVisible()) if (right_arrow_->GetVisible())
right_arrow_->SetBoundsRect(right_arrow_bounds); right_arrow_->SetBoundsRect(right_arrow_bounds);
// Bounds of the gradient zone are relative to the location of arrow buttons.
// So updates the gradient zone after the bounds of arrow buttons are set.
if (is_right_arrow_changed)
UpdateGradientZone();
// Layout |shelf_container_view_|. // Layout |shelf_container_view_|.
shelf_container_view_->SetBoundsRect(shelf_container_bounds); shelf_container_view_->SetBoundsRect(shelf_container_bounds);
...@@ -516,4 +610,39 @@ float ScrollableShelfView::CalculatePageScrollingOffset(bool forward) const { ...@@ -516,4 +610,39 @@ float ScrollableShelfView::CalculatePageScrollingOffset(bool forward) const {
return offset; return offset;
} }
void ScrollableShelfView::UpdateGradientZone() {
gfx::Rect zone_rect;
bool fade_in;
const int zone_length = GetFadeZoneLength();
const bool is_horizontal_alignment = GetShelf()->IsHorizontalAlignment();
// Calculates the bounds of the gradient zone based on the arrow buttons'
// location.
if (right_arrow_->GetVisible()) {
const gfx::Rect right_arrow_bounds = right_arrow_->bounds();
zone_rect = is_horizontal_alignment
? gfx::Rect(right_arrow_bounds.x() - zone_length, 0,
zone_length, height())
: gfx::Rect(0, right_arrow_bounds.y() - zone_length,
width(), zone_length);
fade_in = false;
} else if (left_arrow_->GetVisible()) {
const gfx::Rect left_arrow_bounds = left_arrow_->bounds();
zone_rect =
is_horizontal_alignment
? gfx::Rect(left_arrow_bounds.right(), 0, zone_length, height())
: gfx::Rect(0, left_arrow_bounds.bottom(), width(), zone_length);
fade_in = true;
} else {
zone_rect = gfx::Rect();
fade_in = false;
}
GradientLayerDelegate::FadeZone fade_zone = {zone_rect, fade_in,
is_horizontal_alignment};
gradient_layer_delegate_->set_fade_zone(fade_zone);
gradient_layer_delegate_->layer()->SetBounds(layer()->bounds());
SchedulePaint();
}
} // namespace ash } // namespace ash
...@@ -54,6 +54,8 @@ class ASH_EXPORT ScrollableShelfView : public views::View, ...@@ -54,6 +54,8 @@ class ASH_EXPORT ScrollableShelfView : public views::View,
static constexpr int kEndPadding = 4; static constexpr int kEndPadding = 4;
private: private:
class GradientLayerDelegate;
// Returns the maximum scroll distance. // Returns the maximum scroll distance.
int CalculateScrollUpperBound() const; int CalculateScrollUpperBound() const;
...@@ -118,6 +120,9 @@ class ASH_EXPORT ScrollableShelfView : public views::View, ...@@ -118,6 +120,9 @@ class ASH_EXPORT ScrollableShelfView : public views::View,
// |forward| indicates whether the next page or previous page is shown. // |forward| indicates whether the next page or previous page is shown.
float CalculatePageScrollingOffset(bool forward) const; float CalculatePageScrollingOffset(bool forward) const;
// Updates the gradient zone.
void UpdateGradientZone();
LayoutStrategy layout_strategy_ = kNotShowArrowButtons; LayoutStrategy layout_strategy_ = kNotShowArrowButtons;
// Child views Owned by views hierarchy. // Child views Owned by views hierarchy.
...@@ -145,6 +150,8 @@ class ASH_EXPORT ScrollableShelfView : public views::View, ...@@ -145,6 +150,8 @@ class ASH_EXPORT ScrollableShelfView : public views::View,
LayoutStrategy layout_strategy_before_main_axis_scrolling_ = LayoutStrategy layout_strategy_before_main_axis_scrolling_ =
kNotShowArrowButtons; kNotShowArrowButtons;
std::unique_ptr<GradientLayerDelegate> gradient_layer_delegate_;
DISALLOW_COPY_AND_ASSIGN(ScrollableShelfView); DISALLOW_COPY_AND_ASSIGN(ScrollableShelfView);
}; };
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/effects/SkGradientShader.h"
#include "third_party/skia/include/effects/SkLayerDrawLooper.h" #include "third_party/skia/include/effects/SkLayerDrawLooper.h"
#include "ui/gfx/image/image_skia_rep.h" #include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/switches.h" #include "ui/gfx/switches.h"
namespace gfx { namespace gfx {
...@@ -56,14 +57,13 @@ sk_sp<cc::PaintShader> CreateImageRepShaderForScale( ...@@ -56,14 +57,13 @@ sk_sp<cc::PaintShader> CreateImageRepShaderForScale(
} }
} }
sk_sp<cc::PaintShader> CreateGradientShader(int start_point, sk_sp<cc::PaintShader> CreateGradientShader(const gfx::Point& start_point,
int end_point, const gfx::Point& end_point,
SkColor start_color, SkColor start_color,
SkColor end_color) { SkColor end_color) {
SkColor grad_colors[2] = {start_color, end_color}; SkColor grad_colors[2] = {start_color, end_color};
SkPoint grad_points[2]; SkPoint grad_points[2] = {gfx::PointToSkPoint(start_point),
grad_points[0].iset(0, start_point); gfx::PointToSkPoint(end_point)};
grad_points[1].iset(0, end_point);
return cc::PaintShader::MakeLinearGradient(grad_points, grad_colors, nullptr, return cc::PaintShader::MakeLinearGradient(grad_points, grad_colors, nullptr,
2, SkTileMode::kClamp); 2, SkTileMode::kClamp);
......
...@@ -40,12 +40,12 @@ GFX_EXPORT sk_sp<cc::PaintShader> CreateImageRepShaderForScale( ...@@ -40,12 +40,12 @@ GFX_EXPORT sk_sp<cc::PaintShader> CreateImageRepShaderForScale(
const SkMatrix& local_matrix, const SkMatrix& local_matrix,
SkScalar scale); SkScalar scale);
// Creates a vertical gradient shader. The caller owns the shader. // Creates a gradient shader. The caller owns the shader.
// Example usage to avoid leaks: GFX_EXPORT sk_sp<cc::PaintShader> CreateGradientShader(
GFX_EXPORT sk_sp<cc::PaintShader> CreateGradientShader(int start_point, const gfx::Point& start_point,
int end_point, const gfx::Point& end_point,
SkColor start_color, SkColor start_color,
SkColor end_color); SkColor end_color);
// Creates a draw looper to generate |shadows|. The caller owns the draw looper. // Creates a draw looper to generate |shadows|. The caller owns the draw looper.
// NULL is returned if |shadows| is empty since no draw looper is needed in // NULL is returned if |shadows| is empty since no draw looper is needed in
......
...@@ -52,8 +52,8 @@ class ScrollViewExample::ScrollableView : public View { ...@@ -52,8 +52,8 @@ class ScrollViewExample::ScrollableView : public View {
void OnPaintBackground(gfx::Canvas* canvas) override { void OnPaintBackground(gfx::Canvas* canvas) override {
cc::PaintFlags flags; cc::PaintFlags flags;
flags.setShader( flags.setShader(gfx::CreateGradientShader(
gfx::CreateGradientShader(0, height(), from_color_, to_color_)); gfx::Point(), gfx::Point(0, height()), from_color_, to_color_));
flags.setStyle(cc::PaintFlags::kFill_Style); flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->DrawRect(GetLocalBounds(), flags); canvas->DrawRect(GetLocalBounds(), flags);
} }
......
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