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

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 2013 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 #include "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 color.
39 const SkColor kScrollerThumbColor = SkColorSetARGB(0x38, 0, 0, 0);
40
41 // Scroller track colors.
42 const SkColor kScrollerTrackGradientColors[] = {
43 SkColorSetRGB(0xEF, 0xEF, 0xEF),
44 SkColorSetRGB(0xF9, 0xF9, 0xF9),
45 SkColorSetRGB(0xFD, 0xFD, 0xFD),
46 SkColorSetRGB(0xF6, 0xF6, 0xF6) };
47 const SkColor kScrollerTrackInnerBorderColor = SkColorSetRGB(0xE4, 0xE4, 0xE4);
48 const SkColor kScrollerTrackOuterBorderColor = SkColorSetRGB(0xEF, 0xEF, 0xEF);
49
50
51 //////////////////////////////////////////////////////////////////
52 // CocoaScrollBarThumb
53
54 class CocoaScrollBarThumb : public BaseScrollBarThumb {
55 public:
56 explicit CocoaScrollBarThumb(CocoaScrollBar* scroll_bar);
57 ~CocoaScrollBarThumb() override;
58
59 protected:
60 // View overrides:
61 gfx::Size GetPreferredSize() const override;
62 void OnPaint(gfx::Canvas* canvas) override;
63 void OnMouseEntered(const ui::MouseEvent& event) override;
64 void OnMouseExited(const ui::MouseEvent& event) override;
65
66 private:
67 DISALLOW_COPY_AND_ASSIGN(CocoaScrollBarThumb);
68 };
69
70 CocoaScrollBarThumb::CocoaScrollBarThumb(CocoaScrollBar* scroll_bar)
71 : BaseScrollBarThumb(scroll_bar) {
72 // This is necessary, otherwise the thumb will be rendered below the views if
73 // those views paint to their own layers.
74 SetPaintToLayer(true);
75 SetFillsBoundsOpaquely(false);
76 }
77
78 CocoaScrollBarThumb::~CocoaScrollBarThumb() {}
79
80 gfx::Size CocoaScrollBarThumb::GetPreferredSize() const {
81 return gfx::Size(kScrollbarThumbWidth, kScrollbarThumbWidth);
82 }
83
84 void CocoaScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
85 gfx::Rect local_bounds(GetLocalBounds());
86 SkPaint paint;
87 paint.setStyle(SkPaint::kFill_Style);
88 paint.setColor(kScrollerThumbColor);
89 const SkScalar radius = std::min(local_bounds.width(), local_bounds.height());
90 canvas->DrawRoundRect(local_bounds, radius, paint);
91 }
92
93 void CocoaScrollBarThumb::OnMouseEntered(const ui::MouseEvent& event) {
94 BaseScrollBarThumb::OnMouseEntered(event);
95 CocoaScrollBar* scrollbar = static_cast<CocoaScrollBar*>(scroll_bar());
96 scrollbar->OnMouseEnteredScrollbarThumb(event);
97 }
98
99 void CocoaScrollBarThumb::OnMouseExited(const ui::MouseEvent& event) {
100 BaseScrollBarThumb::OnMouseExited(event);
101 CocoaScrollBar* scrollbar = static_cast<CocoaScrollBar*>(scroll_bar());
102 scrollbar->OnMouseExitedScrollbarThumb(event);
103 }
104
105 } // namespace
106
107 //////////////////////////////////////////////////////////////////
108 // CocoaScrollBar class
109
110 CocoaScrollBar::CocoaScrollBar(bool horizontal)
111 : BaseScrollBar(horizontal, new CocoaScrollBarThumb(this)),
112 is_hovering_(false) {
113 bridge_.reset([[ViewsScrollbarBridge alloc] init]);
114 [bridge_ setDelegate:this];
115
116 scroller_style_ = [ViewsScrollbarBridge getPreferredScrollerStyle];
117
118 SetPaintToLayer(true);
119 has_scrolltrack_ = scroller_style_ == NSScrollerStyleLegacy;
120 layer()->SetOpacity(scroller_style_ == NSScrollerStyleOverlay ? 0.0 : 1.0);
121 }
122
123 CocoaScrollBar::~CocoaScrollBar() {
124 [bridge_ setDelegate:nullptr];
125 }
126
127 //////////////////////////////////////////////////////////////////
128 // CocoaScrollBar, BaseScrollBar:
129
130 gfx::Rect CocoaScrollBar::GetTrackBounds() const {
131 gfx::Rect local_bounds(GetLocalBounds());
132 local_bounds.Inset(kScrollbarThumbInset, kScrollbarThumbInset);
133
134 gfx::Size track_size = local_bounds.size();
135 track_size.SetToMax(GetThumb()->size());
136 local_bounds.set_size(track_size);
137 return local_bounds;
138 }
139
140 //////////////////////////////////////////////////////////////////
141 // CocoaScrollBar, ScrollBar:
142
143 int CocoaScrollBar::GetLayoutSize() const {
144 return 0;
145 }
146
147 int CocoaScrollBar::GetContentOverlapSize() const {
148 return kScrollbarWidth;
149 }
150
151 //////////////////////////////////////////////////////////////////
152 // CocoaScrollBar::Views:
153
154 gfx::Size CocoaScrollBar::GetPreferredSize() const {
155 return gfx::Size();
156 }
157
158 void CocoaScrollBar::OnPaint(gfx::Canvas* canvas) {
159 if (!has_scrolltrack_)
160 return;
161 // Paint the scrollbar track background.
162 gfx::Rect track_rect = GetLocalBounds();
163
164 SkPoint gradient_bounds[2];
165 if (IsHorizontal()) {
166 gradient_bounds[0].set(track_rect.x(), track_rect.y());
167 gradient_bounds[1].set(track_rect.x(), track_rect.bottom());
168 } else {
169 gradient_bounds[0].set(track_rect.x(), track_rect.y());
170 gradient_bounds[1].set(track_rect.right(), track_rect.y());
171 }
172 skia::RefPtr<SkShader> shader = skia::AdoptRef(
173 SkGradientShader::CreateLinear(gradient_bounds,
174 kScrollerTrackGradientColors,
175 NULL,
176 arraysize(kScrollerTrackGradientColors),
177 SkShader::kClamp_TileMode));
178 SkPaint gradient;
179 gradient.setShader(shader.get());
180 canvas->DrawRect(track_rect, gradient);
181
182 // Draw the inner border: top if horizontal, left if vertical.
183 SkPaint paint;
184 paint.setColor(kScrollerTrackInnerBorderColor);
185 gfx::Rect inner_border(track_rect);
186 if (IsHorizontal())
187 inner_border.set_height(kScrollerTrackBorderWidth);
188 else
189 inner_border.set_width(kScrollerTrackBorderWidth);
190 canvas->DrawRect(inner_border, paint);
191
192 // Draw the outer border: bottom if horizontal, right if veritcal.
193 paint.setColor(kScrollerTrackOuterBorderColor);
194 gfx::Rect outer_border(inner_border);
195 if (IsHorizontal())
196 outer_border.set_y(track_rect.bottom());
197 else
198 outer_border.set_x(track_rect.right());
199 canvas->DrawRect(outer_border, paint);
200 }
201
202 void CocoaScrollBar::OnMouseEnteredScrollbarThumb(const ui::MouseEvent& event) {
203 if (scroller_style_ != NSScrollerStyleOverlay)
204 return;
205 hide_scrollbar_timer_.Stop();
206 is_hovering_ = true;
207 if (layer()->opacity()) {
208 ShowScrollbar();
209 }
210 }
211
212 void CocoaScrollBar::OnMouseExitedScrollbarThumb(const ui::MouseEvent& event) {
213 if (scroller_style_ != NSScrollerStyleOverlay)
214 return;
215 is_hovering_ = false;
216 ResetTimer();
217 }
218
219 //////////////////////////////////////////////////////////////////
220 // CocoaScrollBar::ScrollDelegate:
221
222 bool CocoaScrollBar::OnScroll(float dx, float dy) {
223 bool did_scroll = BaseScrollBar::OnScroll(dx, dy);
224 if (did_scroll && scroller_style_ == NSScrollerStyleOverlay) {
225 if (layer()->opacity() < 1.0)
226 ShowScrollbar();
227 ResetTimer();
228 }
229 return did_scroll;
230 }
231
232 //////////////////////////////////////////////////////////////////
233 // CocoaScrollBar::ViewsScrollbarBridge:
234
235 void CocoaScrollBar::OnScrollerStyleChanged() {
236 NSScrollerStyle scroller_style =
237 [ViewsScrollbarBridge getPreferredScrollerStyle];
238 if (scroller_style_ == scroller_style)
239 return;
240 scroller_style_ = scroller_style;
241 if (scroller_style_ == NSScrollerStyleOverlay) {
242 HideScrollbar();
243 } else {
244 ShowScrollbar();
245 }
246 }
247
248 //////////////////////////////////////////////////////////////////
249 // CocoaScrollBar, private:
250
251 void CocoaScrollBar::HideScrollbar() {
252 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
253 animation.SetTransitionDuration(
254 base::TimeDelta::FromMilliseconds(kFadeDurationMs));
255 layer()->SetOpacity(0.0);
256 }
257
258 void CocoaScrollBar::ShowScrollbar() {
259 // Updates the scrolltrack and repaint it, if necessary.
260 bool has_scrolltrack =
261 scroller_style_ == NSScrollerStyleLegacy || is_hovering_;
262 if (has_scrolltrack_ != has_scrolltrack) {
263 has_scrolltrack_ = has_scrolltrack;
264 SchedulePaint();
265 }
266
267 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
268 animation.SetTransitionDuration(base::TimeDelta::TimeDelta());
tapted 2016/02/16 23:32:57 does it behave if we skip these lines? Since there
spqchan 2016/02/17 00:05:29 Just checked, yes it can be omitted. Removed
269 layer()->SetOpacity(1.0);
270 }
271
272 void CocoaScrollBar::ResetTimer() {
273 if (hide_scrollbar_timer_.IsRunning()) {
274 hide_scrollbar_timer_.Reset();
275 } else {
276 hide_scrollbar_timer_.Start(
277 FROM_HERE, base::TimeDelta::FromMilliseconds(kScrollbarHideTimeoutMs),
278 this, &CocoaScrollBar::HideScrollbar);
279 }
280 }
281
282 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698