Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: ui/views/controls/scrollbar/cocoa_scroll_bar.mm

Issue 1671313002: MacViews: Overlay Scrollbars with Show/Hide Animations (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nit Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "ui/views/controls/scrollbar/cocoa_scroll_bar.h"
6
7 #import "base/mac/sdk_forward_declarations.h"
8 #include "third_party/skia/include/core/SkColor.h"
9 #include "third_party/skia/include/effects/SkGradientShader.h"
10 #include "ui/compositor/layer.h"
11 #include "ui/compositor/layer_animator.h"
12 #include "ui/compositor/scoped_layer_animation_settings.h"
13 #include "ui/gfx/canvas.h"
14 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
15
16 namespace views {
17
18 namespace {
19
20 // The length of the fade animation.
21 const int kFadeDurationMs = 240;
22
23 // How long we should wait before hiding the scrollbar.
24 const int kScrollbarHideTimeoutMs = 500;
25
26 // The width of the scrollbar.
27 const int kScrollbarWidth = 15;
28
29 // The width of the scrollbar thumb.
30 const int kScrollbarThumbWidth = 10;
31
32 // The width of the scroller track border.
33 const int kScrollerTrackBorderWidth = 1;
34
35 // The amount the thumb is inset from both the ends and the sides of the track.
36 const int kScrollbarThumbInset = 3;
37
38 // Scrollbar thumb colors.
39 const SkColor kScrollerDefaultThumbColor = SkColorSetARGB(0x38, 0, 0, 0);
40 const SkColor kScrollerHoverThumbColor = SkColorSetARGB(0x80, 0, 0, 0);
41
42 // Scroller track colors.
43 // TODO(spqchan): Add an alpha channel for the overlay-style scroll track.
44 const SkColor kScrollerTrackGradientColors[] = {
45 SkColorSetRGB(0xEF, 0xEF, 0xEF), SkColorSetRGB(0xF9, 0xF9, 0xF9),
46 SkColorSetRGB(0xFD, 0xFD, 0xFD), SkColorSetRGB(0xF6, 0xF6, 0xF6)};
47 const SkColor kScrollerTrackInnerBorderColor = SkColorSetRGB(0xE4, 0xE4, 0xE4);
48 const SkColor kScrollerTrackOuterBorderColor = SkColorSetRGB(0xEF, 0xEF, 0xEF);
49
50 //////////////////////////////////////////////////////////////////
51 // CocoaScrollBarThumb
52
53 class CocoaScrollBarThumb : public BaseScrollBarThumb {
54 public:
55 explicit CocoaScrollBarThumb(CocoaScrollBar* scroll_bar);
56 ~CocoaScrollBarThumb() override;
57
58 // Returns true if the thumb is in hover or pressed state.
59 bool IsStateHoverOrPressed();
60
61 protected:
62 // View:
63 gfx::Size GetPreferredSize() const override;
64 void OnPaint(gfx::Canvas* canvas) override;
65 void OnMouseEntered(const ui::MouseEvent& event) override;
66
67 private:
68 DISALLOW_COPY_AND_ASSIGN(CocoaScrollBarThumb);
69 };
70
71 CocoaScrollBarThumb::CocoaScrollBarThumb(CocoaScrollBar* scroll_bar)
72 : BaseScrollBarThumb(scroll_bar) {
73 DCHECK(scroll_bar);
74
75 // This is necessary, otherwise the thumb will be rendered below the views if
76 // those views paint to their own layers.
77 SetPaintToLayer(true);
78 SetFillsBoundsOpaquely(false);
79 }
80
81 CocoaScrollBarThumb::~CocoaScrollBarThumb() {}
82
83 bool CocoaScrollBarThumb::IsStateHoverOrPressed() {
84 CustomButton::ButtonState state = GetState();
85 return state == CustomButton::STATE_HOVERED ||
86 state == CustomButton::STATE_PRESSED;
87 }
88
89 gfx::Size CocoaScrollBarThumb::GetPreferredSize() const {
90 return gfx::Size(kScrollbarThumbWidth, kScrollbarThumbWidth);
91 }
92
93 void CocoaScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
94 CocoaScrollBar* scrollbar = static_cast<CocoaScrollBar*>(scroll_bar());
95 DCHECK(scrollbar);
96
97 SkColor thumb_color = kScrollerDefaultThumbColor;
98 if (scrollbar->GetScrollerStyle() == NSScrollerStyleOverlay ||
99 IsStateHoverOrPressed()) {
100 thumb_color = kScrollerHoverThumbColor;
101 }
102
103 gfx::Rect local_bounds(GetLocalBounds());
104 SkPaint paint;
105 paint.setAntiAlias(true);
106 paint.setStyle(SkPaint::kFill_Style);
107 paint.setColor(thumb_color);
108 const SkScalar radius = std::min(local_bounds.width(), local_bounds.height());
109 canvas->DrawRoundRect(local_bounds, radius, paint);
110 }
111
112 void CocoaScrollBarThumb::OnMouseEntered(const ui::MouseEvent& event) {
113 BaseScrollBarThumb::OnMouseEntered(event);
114 CocoaScrollBar* scrollbar = static_cast<CocoaScrollBar*>(scroll_bar());
115 scrollbar->OnMouseEnteredScrollbarThumb(event);
116 }
117
118 } // namespace
119
120 //////////////////////////////////////////////////////////////////
121 // CocoaScrollBar class
122
123 CocoaScrollBar::CocoaScrollBar(bool horizontal)
124 : BaseScrollBar(horizontal, new CocoaScrollBarThumb(this)),
125 hide_scrollbar_timer_(
126 FROM_HERE,
127 base::TimeDelta::FromMilliseconds(kScrollbarHideTimeoutMs),
128 base::Bind(&CocoaScrollBar::HideScrollbar, base::Unretained(this)),
129 false) {
130 bridge_.reset([[ViewsScrollbarBridge alloc] initWithDelegate:this]);
131
132 scroller_style_ = [ViewsScrollbarBridge getPreferredScrollerStyle];
133
134 SetPaintToLayer(true);
135 has_scrolltrack_ = scroller_style_ == NSScrollerStyleLegacy;
136 layer()->SetOpacity(scroller_style_ == NSScrollerStyleOverlay ? 0.0 : 1.0);
137 }
138
139 CocoaScrollBar::~CocoaScrollBar() {
140 [bridge_ clearDelegate];
141 }
142
143 //////////////////////////////////////////////////////////////////
144 // CocoaScrollBar, BaseScrollBar:
145
146 gfx::Rect CocoaScrollBar::GetTrackBounds() const {
147 gfx::Rect local_bounds(GetLocalBounds());
148 local_bounds.Inset(kScrollbarThumbInset, kScrollbarThumbInset);
149
150 gfx::Size track_size = local_bounds.size();
151 track_size.SetToMax(GetThumb()->size());
152 local_bounds.set_size(track_size);
153 return local_bounds;
154 }
155
156 //////////////////////////////////////////////////////////////////
157 // CocoaScrollBar, ScrollBar:
158
159 int CocoaScrollBar::GetLayoutSize() const {
160 return scroller_style_ == NSScrollerStyleOverlay ? 0 : kScrollbarWidth;
161 }
162
163 int CocoaScrollBar::GetContentOverlapSize() const {
164 return scroller_style_ == NSScrollerStyleLegacy ? 0 : kScrollbarWidth;
165 }
166
167 //////////////////////////////////////////////////////////////////
168 // CocoaScrollBar::Views:
169
170 void CocoaScrollBar::Layout() {
171 GetThumb()->SetBoundsRect(GetTrackBounds());
172 }
173
174 gfx::Size CocoaScrollBar::GetPreferredSize() const {
175 return gfx::Size();
176 }
177
178 void CocoaScrollBar::OnPaint(gfx::Canvas* canvas) {
179 if (!has_scrolltrack_)
180 return;
181
182 // Paint the scrollbar track background.
183 gfx::Rect track_rect = GetLocalBounds();
184
185 SkPoint gradient_bounds[2];
186 if (IsHorizontal()) {
187 gradient_bounds[0].set(track_rect.x(), track_rect.y());
188 gradient_bounds[1].set(track_rect.x(), track_rect.bottom());
189 } else {
190 gradient_bounds[0].set(track_rect.x(), track_rect.y());
191 gradient_bounds[1].set(track_rect.right(), track_rect.y());
192 }
193 skia::RefPtr<SkShader> shader = skia::AdoptRef(SkGradientShader::CreateLinear(
194 gradient_bounds, kScrollerTrackGradientColors, nullptr,
195 arraysize(kScrollerTrackGradientColors), SkShader::kClamp_TileMode));
196 SkPaint gradient;
197 gradient.setShader(shader.get());
198 canvas->DrawRect(track_rect, gradient);
199
200 // Draw the inner border: top if horizontal, left if vertical.
201 SkPaint paint;
202 paint.setColor(kScrollerTrackInnerBorderColor);
203 gfx::Rect inner_border(track_rect);
204 if (IsHorizontal())
205 inner_border.set_height(kScrollerTrackBorderWidth);
206 else
207 inner_border.set_width(kScrollerTrackBorderWidth);
208 canvas->DrawRect(inner_border, paint);
209
210 // Draw the outer border: bottom if horizontal, right if veritcal.
211 paint.setColor(kScrollerTrackOuterBorderColor);
212 gfx::Rect outer_border(inner_border);
213 if (IsHorizontal())
214 outer_border.set_y(track_rect.bottom());
215 else
216 outer_border.set_x(track_rect.right());
217 canvas->DrawRect(outer_border, paint);
218 }
219
220 void CocoaScrollBar::OnMouseEnteredScrollbarThumb(const ui::MouseEvent& event) {
221 if (scroller_style_ != NSScrollerStyleOverlay)
222 return;
223
224 // If the scrollbar thumb has not compeletely faded away, then reshow it when
225 // the mouse enters the scrollbar thumb.
226 if (layer()->opacity())
227 ShowScrollbar();
228
229 hide_scrollbar_timer_.Reset();
230 }
231
232 //////////////////////////////////////////////////////////////////
233 // CocoaScrollBar::ScrollDelegate:
234
235 bool CocoaScrollBar::OnScroll(float dx, float dy) {
236 bool did_scroll = BaseScrollBar::OnScroll(dx, dy);
237 if (did_scroll && scroller_style_ == NSScrollerStyleOverlay) {
238 ShowScrollbar();
239 hide_scrollbar_timer_.Reset();
240 }
241 return did_scroll;
242 }
243
244 //////////////////////////////////////////////////////////////////
245 // CocoaScrollBar::ViewsScrollbarBridge:
246
247 void CocoaScrollBar::OnScrollerStyleChanged() {
248 NSScrollerStyle scroller_style =
249 [ViewsScrollbarBridge getPreferredScrollerStyle];
250 if (scroller_style_ == scroller_style)
251 return;
252
253 scroller_style_ = scroller_style;
254
255 // Ensure that the ScrollView updates the scrollbar's layout.
256 if (parent())
257 parent()->Layout();
258
259 if (scroller_style_ == NSScrollerStyleOverlay)
260 // Hide the scrollbar, but don't fade out.
tapted 2016/02/22 23:41:56 nit: comments count towards the needs-curlies rule
spqchan 2016/02/23 17:56:27 Done.
261 layer()->SetOpacity(0.0);
262 else
263 ShowScrollbar();
264 }
265
266 //////////////////////////////////////////////////////////////////
267 // CocoaScrollBar, private:
268
269 void CocoaScrollBar::HideScrollbar() {
270 DCHECK_EQ(scroller_style_, NSScrollerStyleOverlay);
271
272 // If the thumb is in a hover or pressed state, we don't want the scrollbar
273 // to disappear. As such, we should reset the timer.
274 CocoaScrollBarThumb* thumb = static_cast<CocoaScrollBarThumb*>(GetThumb());
275 if (thumb->IsStateHoverOrPressed()) {
276 hide_scrollbar_timer_.Reset();
277 return;
278 }
279
280 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
281 animation.SetTransitionDuration(
282 base::TimeDelta::FromMilliseconds(kFadeDurationMs));
283 layer()->SetOpacity(0.0);
284 }
285
286 void CocoaScrollBar::ShowScrollbar() {
287 // Updates the scrolltrack and repaint it, if necessary.
288 CocoaScrollBarThumb* thumb = static_cast<CocoaScrollBarThumb*>(GetThumb());
289 bool has_scrolltrack = scroller_style_ == NSScrollerStyleLegacy ||
290 thumb->IsStateHoverOrPressed();
291 if (has_scrolltrack_ != has_scrolltrack) {
292 has_scrolltrack_ = has_scrolltrack;
293 SchedulePaint();
294 }
295
296 layer()->SetOpacity(1.0);
297 hide_scrollbar_timer_.Stop();
298 }
299
300 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698