diff --git a/chrome/browser/ui/views/download/download_item_view_md.cc b/chrome/browser/ui/views/download/download_item_view_md.cc index 676b1c8807fa7a..7f7dc351fa1a63 100644 --- a/chrome/browser/ui/views/download/download_item_view_md.cc +++ b/chrome/browser/ui/views/download/download_item_view_md.cc @@ -623,7 +623,7 @@ void DownloadItemViewMd::OnPaint(gfx::Canvas* canvas) { OnPaintBorder(canvas); if (HasFocus()) - views::MdTextButton::PaintMdFocusRing(canvas, this); + views::MdTextButton::PaintMdFocusRing(canvas, this, 1, SK_AlphaOPAQUE); } int DownloadItemViewMd::GetYForFilenameText() const { diff --git a/ui/views/animation/flood_fill_ink_drop_ripple.cc b/ui/views/animation/flood_fill_ink_drop_ripple.cc index 418b0c8f1d9842..3bad83e426243d 100644 --- a/ui/views/animation/flood_fill_ink_drop_ripple.cc +++ b/ui/views/animation/flood_fill_ink_drop_ripple.cc @@ -306,14 +306,15 @@ void FloodFillInkDropRipple::AnimateToOpacity( gfx::Transform FloodFillInkDropRipple::CalculateTransform( float target_radius) const { const float target_scale = target_radius / circle_layer_delegate_.radius(); - const gfx::Point drawn_center_point = - ToRoundedPoint(circle_layer_delegate_.GetCenterPoint()); gfx::Transform transform = gfx::Transform(); transform.Translate(center_point_.x() - root_layer_.bounds().x(), center_point_.y() - root_layer_.bounds().y()); transform.Scale(target_scale, target_scale); - transform.Translate(-drawn_center_point.x(), -drawn_center_point.y()); + + const gfx::Vector2dF drawn_center_offset = + circle_layer_delegate_.GetCenteringOffset(); + transform.Translate(-drawn_center_offset.x(), -drawn_center_offset.y()); return transform; } diff --git a/ui/views/animation/ink_drop_highlight.cc b/ui/views/animation/ink_drop_highlight.cc index c22341be99ede9..15ceac0ce7293a 100644 --- a/ui/views/animation/ink_drop_highlight.cc +++ b/ui/views/animation/ink_drop_highlight.cc @@ -9,6 +9,7 @@ #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_sequence.h" #include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/gfx/geometry/insets.h" #include "ui/views/animation/ink_drop_highlight_observer.h" #include "ui/views/animation/ink_drop_painted_layer_delegates.h" @@ -16,9 +17,6 @@ namespace views { namespace { -// The opacity of the highlight when it is visible. -const float kHighlightVisibleOpacity = 0.128f; - // The opacity of the highlight when it is not visible. const float kHiddenOpacity = 0.0f; @@ -36,27 +34,38 @@ std::string ToString(InkDropHighlight::AnimationType animation_type) { return std::string("UNKNOWN"); } -InkDropHighlight::InkDropHighlight(const gfx::Size& size, - int corner_radius, - const gfx::Point& center_point, - SkColor color) - : size_(size), - explode_size_(size), - center_point_(center_point), +InkDropHighlight::InkDropHighlight( + const gfx::Point& center_point, + std::unique_ptr layer_delegate) + : center_point_(center_point), + visible_opacity_(1.f), last_animation_initiated_was_fade_in_(false), - layer_delegate_( - new RoundedRectangleLayerDelegate(color, size, corner_radius)), + layer_delegate_(std::move(layer_delegate)), layer_(new ui::Layer()), observer_(nullptr) { - layer_->SetBounds(gfx::Rect(size)); + const gfx::Rect layer_bounds = layer_delegate_->GetPaintedBounds(); + size_ = explode_size_ = layer_bounds.size(); + + layer_->SetBounds(layer_bounds); layer_->SetFillsBoundsOpaquely(false); layer_->set_delegate(layer_delegate_.get()); layer_->SetVisible(false); - layer_->SetOpacity(kHighlightVisibleOpacity); layer_->SetMasksToBounds(false); layer_->set_name("InkDropHighlight:layer"); } +InkDropHighlight::InkDropHighlight(const gfx::Size& size, + int corner_radius, + const gfx::Point& center_point, + SkColor color) + : InkDropHighlight( + center_point, + std::unique_ptr( + new RoundedRectangleLayerDelegate(color, size, corner_radius))) { + visible_opacity_ = 0.128f; + layer_->SetOpacity(visible_opacity_); +} + InkDropHighlight::~InkDropHighlight() {} bool InkDropHighlight::IsFadingInOrVisible() const { @@ -102,7 +111,7 @@ void InkDropHighlight::AnimateFade(AnimationType animation_type, ui::LayerAnimationElement* opacity_element = ui::LayerAnimationElement::CreateOpacityElement( - animation_type == FADE_IN ? kHighlightVisibleOpacity : kHiddenOpacity, + animation_type == FADE_IN ? visible_opacity_ : kHiddenOpacity, duration); ui::LayerAnimationSequence* opacity_sequence = new ui::LayerAnimationSequence(opacity_element); @@ -127,8 +136,8 @@ gfx::Transform InkDropHighlight::CalculateTransform( gfx::Transform transform; transform.Translate(center_point_.x(), center_point_.y()); transform.Scale(size.width() / size_.width(), size.height() / size_.height()); - transform.Translate(-layer_delegate_->GetCenterPoint().x(), - -layer_delegate_->GetCenterPoint().y()); + gfx::Vector2dF layer_offset = layer_delegate_->GetCenteringOffset(); + transform.Translate(-layer_offset.x(), -layer_offset.y()); return transform; } diff --git a/ui/views/animation/ink_drop_highlight.h b/ui/views/animation/ink_drop_highlight.h index 43f67427b2b7e5..0a18e6f64e9b11 100644 --- a/ui/views/animation/ink_drop_highlight.h +++ b/ui/views/animation/ink_drop_highlight.h @@ -17,6 +17,10 @@ #include "ui/gfx/transform.h" #include "ui/views/views_export.h" +namespace gfx { +class Rect; +} + namespace ui { class Layer; class CallbackLayerAnimationObserver; @@ -27,7 +31,7 @@ namespace test { class InkDropHighlightTestApi; } // namespace test -class RoundedRectangleLayerDelegate; +class BasePaintedLayerDelegate; class InkDropHighlightObserver; // Manages fade in/out animations for a painted Layer that is used to provide @@ -37,6 +41,12 @@ class VIEWS_EXPORT InkDropHighlight { public: enum AnimationType { FADE_IN, FADE_OUT }; + // Creates a highlight with a specified painter. + InkDropHighlight(const gfx::Point& center_point, + std::unique_ptr layer_delegate); + + // Creates a highlight that paints a partially transparent roundrect with + // color |color|. InkDropHighlight(const gfx::Size& size, int corner_radius, const gfx::Point& center_point, @@ -104,12 +114,15 @@ class VIEWS_EXPORT InkDropHighlight { // space. gfx::PointF center_point_; + // The opacity for the fully visible state of the highlight. + float visible_opacity_; + // True if the last animation to be initiated was a FADE_IN, and false // otherwise. bool last_animation_initiated_was_fade_in_; // The LayerDelegate that paints the highlight |layer_|. - std::unique_ptr layer_delegate_; + std::unique_ptr layer_delegate_; // The visual highlight layer that is painted by |layer_delegate_|. std::unique_ptr layer_; diff --git a/ui/views/animation/ink_drop_painted_layer_delegates.cc b/ui/views/animation/ink_drop_painted_layer_delegates.cc index cb5f7c57053d0a..06622855714d75 100644 --- a/ui/views/animation/ink_drop_painted_layer_delegates.cc +++ b/ui/views/animation/ink_drop_painted_layer_delegates.cc @@ -4,11 +4,18 @@ #include "ui/views/animation/ink_drop_painted_layer_delegates.h" +#include "third_party/skia/include/core/SkDrawLooper.h" #include "third_party/skia/include/core/SkPaint.h" +#include "third_party/skia/include/core/SkPath.h" #include "ui/compositor/paint_recorder.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/color_palette.h" +#include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point_conversions.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" +#include "ui/gfx/skia_util.h" namespace views { @@ -22,6 +29,10 @@ BasePaintedLayerDelegate::BasePaintedLayerDelegate(SkColor color) BasePaintedLayerDelegate::~BasePaintedLayerDelegate() {} +gfx::Vector2dF BasePaintedLayerDelegate::GetCenteringOffset() const { + return gfx::RectF(GetPaintedBounds()).CenterPoint().OffsetFromOrigin(); +} + void BasePaintedLayerDelegate::OnDelegatedFrameDamage( const gfx::Rect& damage_rect_in_dip) {} @@ -42,8 +53,9 @@ CircleLayerDelegate::CircleLayerDelegate(SkColor color, int radius) CircleLayerDelegate::~CircleLayerDelegate() {} -gfx::PointF CircleLayerDelegate::GetCenterPoint() const { - return gfx::PointF(radius_, radius_); +gfx::Rect CircleLayerDelegate::GetPaintedBounds() const { + const int diameter = radius_ * 2; + return gfx::Rect(0, 0, diameter, diameter); } void CircleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) { @@ -52,10 +64,10 @@ void CircleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) { paint.setFlags(SkPaint::kAntiAlias_Flag); paint.setStyle(SkPaint::kFill_Style); - ui::PaintRecorder recorder(context, gfx::Size(2 * radius_, 2 * radius_)); + ui::PaintRecorder recorder(context, GetPaintedBounds().size()); gfx::Canvas* canvas = recorder.canvas(); - canvas->DrawCircle(ToRoundedPoint(GetCenterPoint()), radius_, paint); + canvas->DrawCircle(GetPaintedBounds().CenterPoint(), radius_, paint); } //////////////////////////////////////////////////////////////////////////////// @@ -68,8 +80,8 @@ RectangleLayerDelegate::RectangleLayerDelegate(SkColor color, gfx::Size size) RectangleLayerDelegate::~RectangleLayerDelegate() {} -gfx::PointF RectangleLayerDelegate::GetCenterPoint() const { - return gfx::PointF(size_.width() / 2.0f, size_.height() / 2.0f); +gfx::Rect RectangleLayerDelegate::GetPaintedBounds() const { + return gfx::Rect(size_); } void RectangleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) { @@ -80,7 +92,7 @@ void RectangleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) { ui::PaintRecorder recorder(context, size_); gfx::Canvas* canvas = recorder.canvas(); - canvas->DrawRect(gfx::Rect(size_), paint); + canvas->DrawRect(GetPaintedBounds(), paint); } //////////////////////////////////////////////////////////////////////////////// @@ -88,17 +100,18 @@ void RectangleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) { // RoundedRectangleLayerDelegate // -RoundedRectangleLayerDelegate::RoundedRectangleLayerDelegate(SkColor color, - gfx::Size size, - int corner_radius) +RoundedRectangleLayerDelegate::RoundedRectangleLayerDelegate( + SkColor color, + const gfx::Size& size, + int corner_radius) : BasePaintedLayerDelegate(color), size_(size), corner_radius_(corner_radius) {} RoundedRectangleLayerDelegate::~RoundedRectangleLayerDelegate() {} -gfx::PointF RoundedRectangleLayerDelegate::GetCenterPoint() const { - return gfx::RectF(gfx::SizeF(size_)).CenterPoint(); +gfx::Rect RoundedRectangleLayerDelegate::GetPaintedBounds() const { + return gfx::Rect(size_); } void RoundedRectangleLayerDelegate::OnPaintLayer( @@ -109,8 +122,59 @@ void RoundedRectangleLayerDelegate::OnPaintLayer( paint.setStyle(SkPaint::kFill_Style); ui::PaintRecorder recorder(context, size_); - gfx::Canvas* canvas = recorder.canvas(); - canvas->DrawRoundRect(gfx::Rect(size_), corner_radius_, paint); + recorder.canvas()->DrawRoundRect(GetPaintedBounds(), corner_radius_, paint); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// BorderShadowLayerDelegate +// + +BorderShadowLayerDelegate::BorderShadowLayerDelegate( + const std::vector& shadows, + const gfx::Rect& shadowed_area_bounds, + int corner_radius) + : BasePaintedLayerDelegate(gfx::kPlaceholderColor), + shadows_(shadows), + bounds_(shadowed_area_bounds), + corner_radius_(corner_radius) {} + +BorderShadowLayerDelegate::~BorderShadowLayerDelegate() {} + +gfx::Rect BorderShadowLayerDelegate::GetPaintedBounds() const { + gfx::Rect total_rect(bounds_); + total_rect.Inset(gfx::ShadowValue::GetMargin(shadows_)); + return total_rect; +} + +gfx::Vector2dF BorderShadowLayerDelegate::GetCenteringOffset() const { + return gfx::RectF(bounds_).CenterPoint().OffsetFromOrigin(); +} + +void BorderShadowLayerDelegate::OnPaintLayer(const ui::PaintContext& context) { + SkPaint paint; + paint.setLooper(gfx::CreateShadowDrawLooper(shadows_)); + paint.setStyle(SkPaint::kStrokeAndFill_Style); + paint.setAntiAlias(true); + paint.setColor(SK_ColorTRANSPARENT); + paint.setStrokeJoin(SkPaint::kRound_Join); + gfx::RectF bounds(bounds_); + bounds -= GetPaintedBounds().OffsetFromOrigin(); + gfx::RectF stroke_bounds = bounds; + stroke_bounds.Inset(-gfx::InsetsF(0.5f)); + + ui::PaintRecorder recorder(context, GetPaintedBounds().size()); + const SkScalar corner = SkFloatToScalar(corner_radius_); + SkPath path; + path.addRoundRect(gfx::RectFToSkRect(stroke_bounds), corner, corner, + SkPath::kCCW_Direction); + recorder.canvas()->DrawPath(path, paint); + + SkPaint clear_paint; + clear_paint.setAntiAlias(true); + clear_paint.setXfermodeMode(SkXfermode::kClear_Mode); + recorder.canvas()->sk_canvas()->drawRoundRect(gfx::RectFToSkRect(bounds), + corner, corner, clear_paint); } } // namespace views diff --git a/ui/views/animation/ink_drop_painted_layer_delegates.h b/ui/views/animation/ink_drop_painted_layer_delegates.h index 4c58b3bb4f5f79..56148d28015f74 100644 --- a/ui/views/animation/ink_drop_painted_layer_delegates.h +++ b/ui/views/animation/ink_drop_painted_layer_delegates.h @@ -9,9 +9,10 @@ #include "base/macros.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/compositor/layer_delegate.h" -#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/geometry/vector2d_f.h" +#include "ui/gfx/shadow_value.h" #include "ui/views/views_export.h" namespace views { @@ -22,10 +23,12 @@ class VIEWS_EXPORT BasePaintedLayerDelegate : public ui::LayerDelegate { public: ~BasePaintedLayerDelegate() override; - SkColor color() const { return color_; } + // Defines the bounds of the layer that the delegate will paint into. + virtual gfx::Rect GetPaintedBounds() const = 0; - // Returns the center point of the painted shape. - virtual gfx::PointF GetCenterPoint() const = 0; + // Defines how to place the layer by providing an offset from the origin of + // the parent to the visual center of the layer. + virtual gfx::Vector2dF GetCenteringOffset() const; // ui::LayerDelegate: void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; @@ -35,6 +38,8 @@ class VIEWS_EXPORT BasePaintedLayerDelegate : public ui::LayerDelegate { protected: explicit BasePaintedLayerDelegate(SkColor color); + SkColor color() const { return color_; } + private: // The color to paint. SkColor color_; @@ -52,7 +57,7 @@ class VIEWS_EXPORT CircleLayerDelegate : public BasePaintedLayerDelegate { int radius() const { return radius_; } // BasePaintedLayerDelegate: - gfx::PointF GetCenterPoint() const override; + gfx::Rect GetPaintedBounds() const override; void OnPaintLayer(const ui::PaintContext& context) override; private: @@ -72,7 +77,7 @@ class VIEWS_EXPORT RectangleLayerDelegate : public BasePaintedLayerDelegate { const gfx::Size& size() const { return size_; } // BasePaintedLayerDelegate: - gfx::PointF GetCenterPoint() const override; + gfx::Rect GetPaintedBounds() const override; void OnPaintLayer(const ui::PaintContext& context) override; private: @@ -88,14 +93,14 @@ class VIEWS_EXPORT RoundedRectangleLayerDelegate : public BasePaintedLayerDelegate { public: RoundedRectangleLayerDelegate(SkColor color, - gfx::Size size, + const gfx::Size& size, int corner_radius); ~RoundedRectangleLayerDelegate() override; const gfx::Size& size() const { return size_; } // BasePaintedLayerDelegate: - gfx::PointF GetCenterPoint() const override; + gfx::Rect GetPaintedBounds() const override; void OnPaintLayer(const ui::PaintContext& context) override; private: @@ -108,6 +113,33 @@ class VIEWS_EXPORT RoundedRectangleLayerDelegate DISALLOW_COPY_AND_ASSIGN(RoundedRectangleLayerDelegate); }; +// A BasePaintedLayerDelegate that paints a shadow around the outside of a +// specified roundrect. +class VIEWS_EXPORT BorderShadowLayerDelegate : public BasePaintedLayerDelegate { + public: + BorderShadowLayerDelegate(const std::vector& shadows, + const gfx::Rect& shadowed_area_bounds, + int corner_radius); + ~BorderShadowLayerDelegate() override; + + // BasePaintedLayerDelegate: + gfx::Rect GetPaintedBounds() const override; + gfx::Vector2dF GetCenteringOffset() const override; + void OnPaintLayer(const ui::PaintContext& context) override; + + private: + gfx::Rect GetTotalRect() const; + + const std::vector shadows_; + + // The bounds of the shadowed area. + gfx::Rect bounds_; + + int corner_radius_; + + DISALLOW_COPY_AND_ASSIGN(BorderShadowLayerDelegate); +}; + } // namespace views #endif // UI_VIEWS_ANIMATION_INK_DROP_PAINTED_LAYER_DELEGATES_H_ diff --git a/ui/views/animation/square_ink_drop_ripple.cc b/ui/views/animation/square_ink_drop_ripple.cc index c143edcf508326..a01bbfd12bb2ce 100644 --- a/ui/views/animation/square_ink_drop_ripple.cc +++ b/ui/views/animation/square_ink_drop_ripple.cc @@ -134,28 +134,28 @@ base::TimeDelta GetAnimationDuration(InkDropSubAnimations state) { } // Calculates a Transform for a circle layer. The transform will be set up to -// translate the |drawn_center_point| to the origin, scale, and then translate -// to the target point defined by |target_center_x| and |target_center_y|. -gfx::Transform CalculateCircleTransform(const gfx::Point& drawn_center_point, +// translate by -|center_offset|, scale, and then translate to the target point +// defined by |target_center_x| and |target_center_y|. +gfx::Transform CalculateCircleTransform(const gfx::Vector2dF& center_offset, float scale, float target_center_x, float target_center_y) { gfx::Transform transform; transform.Translate(target_center_x, target_center_y); transform.Scale(scale, scale); - transform.Translate(-drawn_center_point.x(), -drawn_center_point.y()); + transform.Translate(-center_offset.x(), -center_offset.y()); return transform; } // Calculates a Transform for a rectangle layer. The transform will be set up to -// translate the |drawn_center_point| to the origin and then scale by the -// |x_scale| and |y_scale| factors. -gfx::Transform CalculateRectTransform(const gfx::Point& drawn_center_point, +// translate by -|center_offset| and then scale by the |x_scale| and |y_scale| +// factors. +gfx::Transform CalculateRectTransform(const gfx::Vector2dF& center_offset, float x_scale, float y_scale) { gfx::Transform transform; transform.Scale(x_scale, y_scale); - transform.Translate(-drawn_center_point.x(), -drawn_center_point.y()); + transform.Translate(-center_offset.x(), -center_offset.y()); return transform; } @@ -477,35 +477,39 @@ void SquareInkDropRipple::CalculateRectTransforms( const float circle_target_x_offset = size.width() / 2.0f - corner_radius; const float circle_target_y_offset = size.height() / 2.0f - corner_radius; + const gfx::Vector2dF circle_center_offset = + circle_layer_delegate_->GetCenteringOffset(); (*transforms_out)[TOP_LEFT_CIRCLE] = CalculateCircleTransform( - ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale, - -circle_target_x_offset, -circle_target_y_offset); + circle_center_offset, circle_scale, -circle_target_x_offset, + -circle_target_y_offset); - (*transforms_out)[TOP_RIGHT_CIRCLE] = CalculateCircleTransform( - ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale, - circle_target_x_offset, -circle_target_y_offset); + (*transforms_out)[TOP_RIGHT_CIRCLE] = + CalculateCircleTransform(circle_center_offset, circle_scale, + circle_target_x_offset, -circle_target_y_offset); - (*transforms_out)[BOTTOM_RIGHT_CIRCLE] = CalculateCircleTransform( - ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale, - circle_target_x_offset, circle_target_y_offset); + (*transforms_out)[BOTTOM_RIGHT_CIRCLE] = + CalculateCircleTransform(circle_center_offset, circle_scale, + circle_target_x_offset, circle_target_y_offset); - (*transforms_out)[BOTTOM_LEFT_CIRCLE] = CalculateCircleTransform( - ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale, - -circle_target_x_offset, circle_target_y_offset); + (*transforms_out)[BOTTOM_LEFT_CIRCLE] = + CalculateCircleTransform(circle_center_offset, circle_scale, + -circle_target_x_offset, circle_target_y_offset); const float rect_delegate_width = static_cast(rect_layer_delegate_->size().width()); const float rect_delegate_height = static_cast(rect_layer_delegate_->size().height()); + const gfx::Vector2dF rect_center_offset = + rect_layer_delegate_->GetCenteringOffset(); (*transforms_out)[HORIZONTAL_RECT] = CalculateRectTransform( - ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()), + rect_center_offset, std::max(kMinimumRectScale, size.width() / rect_delegate_width), std::max(kMinimumRectScale, (size.height() - 2.0f * corner_radius) / rect_delegate_height)); (*transforms_out)[VERTICAL_RECT] = CalculateRectTransform( - ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()), + rect_center_offset, std::max(kMinimumRectScale, (size.width() - 2.0f * corner_radius) / rect_delegate_width), std::max(kMinimumRectScale, size.height() / rect_delegate_height)); diff --git a/ui/views/animation/test/flood_fill_ink_drop_ripple_test_api.cc b/ui/views/animation/test/flood_fill_ink_drop_ripple_test_api.cc index d71b60a220e365..44621e7c4c1143 100644 --- a/ui/views/animation/test/flood_fill_ink_drop_ripple_test_api.cc +++ b/ui/views/animation/test/flood_fill_ink_drop_ripple_test_api.cc @@ -28,8 +28,8 @@ void FloodFillInkDropRippleTestApi::TransformPoint(float radius, } gfx::Point FloodFillInkDropRippleTestApi::GetDrawnCenterPoint() const { - return ToRoundedPoint( - ink_drop_ripple()->circle_layer_delegate_.GetCenterPoint()); + return ToRoundedPoint(PointAtOffsetFromOrigin( + ink_drop_ripple()->circle_layer_delegate_.GetCenteringOffset())); } float FloodFillInkDropRippleTestApi::MaxDistanceToCorners( diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc index 57b87d65397755..cb593cf7539acc 100644 --- a/ui/views/controls/button/label_button.cc +++ b/ui/views/controls/button/label_button.cc @@ -213,7 +213,7 @@ void LabelButton::SetMaxSize(const gfx::Size& max_size) { } void LabelButton::SetIsDefault(bool is_default) { - DCHECK_EQ(STYLE_BUTTON, style_); + // TODO(estade): move this to MdTextButton once |style_| is removed. if (is_default == is_default_) return; diff --git a/ui/views/controls/button/md_text_button.cc b/ui/views/controls/button/md_text_button.cc index fd6822ad4114c3..d5dfd009db3ee9 100644 --- a/ui/views/controls/button/md_text_button.cc +++ b/ui/views/controls/button/md_text_button.cc @@ -9,6 +9,8 @@ #include "ui/gfx/canvas.h" #include "ui/gfx/color_utils.h" #include "ui/native_theme/native_theme.h" +#include "ui/views/animation/ink_drop_highlight.h" +#include "ui/views/animation/ink_drop_painted_layer_delegates.h" #include "ui/views/background.h" #include "ui/views/border.h" #include "ui/views/controls/button/blue_button.h" @@ -24,31 +26,13 @@ const int kHorizontalPadding = 16; // Minimum size to reserve for the button contents. const int kMinWidth = 48; -// The amount to enlarge the focus border in all directions relative to the -// button. -const int kFocusBorderOutset = -1; +// The stroke width of the focus border in normal and call to action mode. +const int kFocusBorderThickness = 1; +const int kFocusBorderThicknessCta = 2; // The corner radius of the focus border roundrect. const int kFocusBorderCornerRadius = 3; -class MdFocusRing : public views::View { - public: - MdFocusRing() { - SetPaintToLayer(true); - layer()->SetFillsBoundsOpaquely(false); - } - ~MdFocusRing() override {} - - bool CanProcessEventsWithinSubtree() const override { return false; } - - void OnPaint(gfx::Canvas* canvas) override { - MdTextButton::PaintMdFocusRing(canvas, this); - } - - private: - DISALLOW_COPY_AND_ASSIGN(MdFocusRing); -}; - LabelButton* CreateButton(ButtonListener* listener, const base::string16& text, bool md) { @@ -71,6 +55,34 @@ const gfx::FontList& GetMdFontList() { } // namespace +namespace internal { + +class MdFocusRing : public View { + public: + MdFocusRing() : thickness_(kFocusBorderThickness) { + SetPaintToLayer(true); + layer()->SetFillsBoundsOpaquely(false); + } + ~MdFocusRing() override {} + + int thickness() const { return thickness_; } + void set_thickness(int thickness) { thickness_ = thickness; } + + // View: + bool CanProcessEventsWithinSubtree() const override { return false; } + + void OnPaint(gfx::Canvas* canvas) override { + MdTextButton::PaintMdFocusRing(canvas, this, thickness_, 0x33); + } + + private: + int thickness_; + + DISALLOW_COPY_AND_ASSIGN(MdFocusRing); +}; + +} // namespace internal + // static LabelButton* MdTextButton::CreateStandardButton(ButtonListener* listener, const base::string16& text) { @@ -108,30 +120,36 @@ MdTextButton* MdTextButton::CreateMdButton(ButtonListener* listener, } // static -void MdTextButton::PaintMdFocusRing(gfx::Canvas* canvas, views::View* view) { +void MdTextButton::PaintMdFocusRing(gfx::Canvas* canvas, + views::View* view, + int thickness, + SkAlpha alpha) { SkPaint paint; paint.setAntiAlias(true); paint.setColor(SkColorSetA(view->GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_CallToActionColor), 0x33)); + ui::NativeTheme::kColorId_CallToActionColor), + alpha)); paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(1); + paint.setStrokeWidth(thickness); gfx::RectF rect(view->GetLocalBounds()); - rect.Inset(gfx::InsetsF(0.5)); + rect.Inset(gfx::InsetsF(thickness / 2.f)); canvas->DrawRoundRect(rect, kFocusBorderCornerRadius, paint); } void MdTextButton::SetCallToAction(bool cta) { - if (cta_ == cta) + if (is_cta_ == cta) return; - cta_ = cta; + is_cta_ = cta; + focus_ring_->set_thickness(cta ? kFocusBorderThicknessCta + : kFocusBorderThickness); UpdateColorsFromNativeTheme(); } void MdTextButton::Layout() { LabelButton::Layout(); gfx::Rect focus_bounds = GetLocalBounds(); - focus_bounds.Inset(gfx::Insets(kFocusBorderOutset)); + focus_bounds.Inset(gfx::Insets(-focus_ring_->thickness())); focus_ring_->SetBoundsRect(focus_bounds); } @@ -154,6 +172,28 @@ SkColor MdTextButton::GetInkDropBaseColor() const { return color_utils::DeriveDefaultIconColor(label()->enabled_color()); } +std::unique_ptr MdTextButton::CreateInkDropHighlight() + const { + if (!ShouldShowInkDropHighlight()) + return nullptr; + if (!is_cta_) + return LabelButton::CreateInkDropHighlight(); + + // The call to action hover effect is a shadow. + const int kYOffset = 2; + const int kSkiaBlurRadius = 2; + std::vector shadows; + // The notion of blur that gfx::ShadowValue uses is twice the skia value, + // which is a number of pixels outside of the shadowed area. + shadows.push_back(gfx::ShadowValue(gfx::Vector2d(0, kYOffset), + 2 * kSkiaBlurRadius, + SkColorSetA(SK_ColorBLACK, 0x3D))); + return base::WrapUnique(new InkDropHighlight( + GetLocalBounds().CenterPoint(), + base::WrapUnique(new BorderShadowLayerDelegate( + shadows, GetLocalBounds(), kInkDropSmallCornerRadius)))); +} + bool MdTextButton::ShouldShowInkDropForFocus() const { // These types of button use |focus_ring_|. return false; @@ -165,8 +205,8 @@ void MdTextButton::UpdateStyleToIndicateDefaultStatus() { MdTextButton::MdTextButton(ButtonListener* listener) : LabelButton(listener, base::string16()), - focus_ring_(new MdFocusRing()), - cta_(false) { + focus_ring_(new internal::MdFocusRing()), + is_cta_(false) { SetHasInkDrop(true); set_has_ink_drop_action_on_click(true); SetHorizontalAlignment(gfx::ALIGN_CENTER); @@ -204,22 +244,23 @@ MdTextButton::~MdTextButton() {} void MdTextButton::UpdateColorsFromNativeTheme() { ui::NativeTheme::ColorId fg_color_id = - cta_ ? ui::NativeTheme::kColorId_TextOnCallToActionColor - : ui::NativeTheme::kColorId_ButtonEnabledColor; + is_cta_ ? ui::NativeTheme::kColorId_TextOnCallToActionColor + : ui::NativeTheme::kColorId_ButtonEnabledColor; // When there's no call to action, respect a color override if one has // been set. For call to action styling, don't let individual buttons // specify a color. ui::NativeTheme* theme = GetNativeTheme(); - if (cta_ || !explicitly_set_normal_color()) + if (is_cta_ || !explicitly_set_normal_color()) SetEnabledTextColors(theme->GetSystemColor(fg_color_id)); SkColor text_color = label()->enabled_color(); SkColor bg_color = - cta_ ? theme->GetSystemColor(ui::NativeTheme::kColorId_CallToActionColor) - : is_default() - ? color_utils::BlendTowardOppositeLuma(text_color, 0xD8) - : SK_ColorTRANSPARENT; + is_cta_ + ? theme->GetSystemColor(ui::NativeTheme::kColorId_CallToActionColor) + : is_default() + ? color_utils::BlendTowardOppositeLuma(text_color, 0xD8) + : SK_ColorTRANSPARENT; SkColor stroke_color = SkColorSetA(SK_ColorBLACK, 0x1A); set_background(Background::CreateBackgroundPainter( true, Painter::CreateRoundRectWith1PxBorderPainter( diff --git a/ui/views/controls/button/md_text_button.h b/ui/views/controls/button/md_text_button.h index 1932a40dfd53d8..eaffa6efa2bd70 100644 --- a/ui/views/controls/button/md_text_button.h +++ b/ui/views/controls/button/md_text_button.h @@ -11,6 +11,10 @@ namespace views { +namespace internal { +class MdFocusRing; +} // namespace internal + // A button class that implements the Material Design text button spec. class VIEWS_EXPORT MdTextButton : public LabelButton { public: @@ -28,7 +32,10 @@ class VIEWS_EXPORT MdTextButton : public LabelButton { const base::string16& text); // Paint an MD-style focus ring on the given canvas at the given bounds. - static void PaintMdFocusRing(gfx::Canvas* canvas, View* view); + static void PaintMdFocusRing(gfx::Canvas* canvas, + View* view, + int thickness, + SkAlpha alpha); void SetCallToAction(bool cta); @@ -37,6 +44,8 @@ class VIEWS_EXPORT MdTextButton : public LabelButton { void OnFocus() override; void OnBlur() override; void OnNativeThemeChanged(const ui::NativeTheme* theme) override; + std::unique_ptr CreateInkDropHighlight() + const override; SkColor GetInkDropBaseColor() const override; bool ShouldShowInkDropForFocus() const override; void UpdateStyleToIndicateDefaultStatus() override; @@ -50,10 +59,10 @@ class VIEWS_EXPORT MdTextButton : public LabelButton { // The MD-style focus ring. This is not done via a FocusPainter // because it needs to paint to a layer so it can extend beyond the bounds of // |this|. - views::View* focus_ring_; + internal::MdFocusRing* focus_ring_; - // The call to action style for this button. - bool cta_; + // True if this button uses call-to-action styling. + bool is_cta_; DISALLOW_COPY_AND_ASSIGN(MdTextButton); }; diff --git a/ui/views/examples/BUILD.gn b/ui/views/examples/BUILD.gn index 0233311bebbbc1..0d3371ddb94253 100644 --- a/ui/views/examples/BUILD.gn +++ b/ui/views/examples/BUILD.gn @@ -104,6 +104,7 @@ executable("views_examples_exe") { ":views_examples_lib", "//base", "//base:i18n", + "//base/test:test_support", "//build/config/sanitizers:deps", "//build/win:default_exe_manifest", "//ui/base", diff --git a/ui/views/examples/examples_main.cc b/ui/views/examples/examples_main.cc index d3889a89a95e1f..bb074a0dabe1d0 100644 --- a/ui/views/examples/examples_main.cc +++ b/ui/views/examples/examples_main.cc @@ -14,6 +14,7 @@ #include "base/power_monitor/power_monitor.h" #include "base/power_monitor/power_monitor_device_source.h" #include "base/run_loop.h" +#include "base/test/test_discardable_memory_allocator.h" #include "build/build_config.h" #include "ui/base/ime/input_method_initializer.h" #include "ui/base/material_design/material_design_controller.h" @@ -44,6 +45,9 @@ #include "ui/gfx/x/x11_connection.h" // nogncheck #endif +base::LazyInstance + g_discardable_memory_allocator = LAZY_INSTANCE_INITIALIZER; + int main(int argc, char** argv) { #if defined(OS_WIN) ui::ScopedOleInitializer ole_initializer_; @@ -77,11 +81,14 @@ int main(int argc, char** argv) { CHECK(PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path)); ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path); + base::DiscardableMemoryAllocator::SetInstance( + g_discardable_memory_allocator.Pointer()); + base::PowerMonitor power_monitor( base::WrapUnique(new base::PowerMonitorDeviceSource)); #if defined(OS_WIN) - gfx::win::MaybeInitializeDirectWrite(); + gfx::win::MaybeInitializeDirectWrite(); #endif #if defined(USE_AURA)