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

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: 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.
tapted 2016/02/22 04:42:15 // TODO(spqchan): Add an alpha channel for the ove
spqchan 2016/02/22 19:01:37 Done.
43 const SkColor kScrollerTrackGradientColors[] = {
44 SkColorSetRGB(0xEF, 0xEF, 0xEF), SkColorSetRGB(0xF9, 0xF9, 0xF9),
45 SkColorSetRGB(0xFD, 0xFD, 0xFD), SkColorSetRGB(0xF6, 0xF6, 0xF6)};
46 const SkColor kScrollerTrackInnerBorderColor = SkColorSetRGB(0xE4, 0xE4, 0xE4);
47 const SkColor kScrollerTrackOuterBorderColor = SkColorSetRGB(0xEF, 0xEF, 0xEF);
48
49 //////////////////////////////////////////////////////////////////
50 // CocoaScrollBarThumb
51
52 class CocoaScrollBarThumb : public BaseScrollBarThumb {
53 public:
54 explicit CocoaScrollBarThumb(CocoaScrollBar* scroll_bar);
55 ~CocoaScrollBarThumb() override;
56
57 // Returns true if the thumb is in hover or pressed state.
58 bool IsStateHoverOrPressed();
59
60 protected:
61 // View:
62 gfx::Size GetPreferredSize() const override;
63 void OnPaint(gfx::Canvas* canvas) override;
64 void OnMouseEntered(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 DCHECK(scroll_bar);
73
74 // This is necessary, otherwise the thumb will be rendered below the views if
75 // those views paint to their own layers.
76 SetPaintToLayer(true);
77 SetFillsBoundsOpaquely(false);
78 }
79
80 CocoaScrollBarThumb::~CocoaScrollBarThumb() {}
81
82 bool CocoaScrollBarThumb::IsStateHoverOrPressed() {
83 CustomButton::ButtonState state = GetState();
84 return state == CustomButton::STATE_HOVERED ||
85 state == CustomButton::STATE_PRESSED;
86 }
87
88 gfx::Size CocoaScrollBarThumb::GetPreferredSize() const {
89 return gfx::Size(kScrollbarThumbWidth, kScrollbarThumbWidth);
90 }
91
92 void CocoaScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
93 CocoaScrollBar* scrollbar = static_cast<CocoaScrollBar*>(scroll_bar());
94 DCHECK(scrollbar);
95
96 SkColor thumb_color = kScrollerDefaultThumbColor;
97 if (scrollbar->GetScrollerStyle() == NSScrollerStyleOverlay ||
98 IsStateHoverOrPressed())
99 thumb_color = kScrollerHoverThumbColor;
100
101 gfx::Rect local_bounds(GetLocalBounds());
102 SkPaint paint;
103 paint.setAntiAlias(true);
104 paint.setStyle(SkPaint::kFill_Style);
105 paint.setColor(thumb_color);
106 const SkScalar radius = std::min(local_bounds.width(), local_bounds.height());
107 canvas->DrawRoundRect(local_bounds, radius, paint);
108 }
109
110 void CocoaScrollBarThumb::OnMouseEntered(const ui::MouseEvent& event) {
111 BaseScrollBarThumb::OnMouseEntered(event);
112 CocoaScrollBar* scrollbar = static_cast<CocoaScrollBar*>(scroll_bar());
113 scrollbar->OnMouseEnteredScrollbarThumb(event);
114 }
115
116 } // namespace
117
118 //////////////////////////////////////////////////////////////////
119 // CocoaScrollBar class
120
121 CocoaScrollBar::CocoaScrollBar(bool horizontal)
122 : BaseScrollBar(horizontal, new CocoaScrollBarThumb(this)),
123 hide_scrollbar_timer_(
124 FROM_HERE,
125 base::TimeDelta::FromMilliseconds(kScrollbarHideTimeoutMs),
126 base::Bind(&CocoaScrollBar::HideScrollbar, base::Unretained(this)),
127 false) {
128 bridge_.reset([[ViewsScrollbarBridge alloc] init]);
129 [bridge_ setDelegate:this];
130
131 scroller_style_ = [ViewsScrollbarBridge getPreferredScrollerStyle];
132
133 SetPaintToLayer(true);
134 has_scrolltrack_ = scroller_style_ == NSScrollerStyleLegacy;
135 layer()->SetOpacity(scroller_style_ == NSScrollerStyleOverlay ? 0.0 : 1.0);
136 }
137
138 CocoaScrollBar::~CocoaScrollBar() {
139 [bridge_ setDelegate:nullptr];
140 }
141
142 //////////////////////////////////////////////////////////////////
143 // CocoaScrollBar, BaseScrollBar:
144
145 gfx::Rect CocoaScrollBar::GetTrackBounds() const {
146 gfx::Rect local_bounds(GetLocalBounds());
147 local_bounds.Inset(kScrollbarThumbInset, kScrollbarThumbInset);
148
149 gfx::Size track_size = local_bounds.size();
150 track_size.SetToMax(GetThumb()->size());
151 local_bounds.set_size(track_size);
152 return local_bounds;
153 }
154
155 //////////////////////////////////////////////////////////////////
156 // CocoaScrollBar, ScrollBar:
157
158 int CocoaScrollBar::GetLayoutSize() const {
159 return scroller_style_ == NSScrollerStyleOverlay ? 0 : kScrollbarWidth;
160 }
161
162 int CocoaScrollBar::GetContentOverlapSize() const {
163 return scroller_style_ == NSScrollerStyleLegacy ? 0 : kScrollbarWidth;
164 }
165
166 //////////////////////////////////////////////////////////////////
167 // CocoaScrollBar::Views:
168
169 gfx::Size CocoaScrollBar::GetPreferredSize() const {
170 return gfx::Size();
171 }
172
173 void CocoaScrollBar::OnPaint(gfx::Canvas* canvas) {
174 if (!has_scrolltrack_)
175 return;
176
177 // Paint the scrollbar track background.
178 gfx::Rect track_rect = GetLocalBounds();
179
180 SkPoint gradient_bounds[2];
181 if (IsHorizontal()) {
182 gradient_bounds[0].set(track_rect.x(), track_rect.y());
183 gradient_bounds[1].set(track_rect.x(), track_rect.bottom());
184 } else {
185 gradient_bounds[0].set(track_rect.x(), track_rect.y());
186 gradient_bounds[1].set(track_rect.right(), track_rect.y());
187 }
188 skia::RefPtr<SkShader> shader = skia::AdoptRef(SkGradientShader::CreateLinear(
189 gradient_bounds, kScrollerTrackGradientColors, nullptr,
190 arraysize(kScrollerTrackGradientColors), SkShader::kClamp_TileMode));
191 SkPaint gradient;
192 gradient.setShader(shader.get());
193 canvas->DrawRect(track_rect, gradient);
194
195 // Draw the inner border: top if horizontal, left if vertical.
196 SkPaint paint;
197 paint.setColor(kScrollerTrackInnerBorderColor);
198 gfx::Rect inner_border(track_rect);
199 if (IsHorizontal())
200 inner_border.set_height(kScrollerTrackBorderWidth);
201 else
202 inner_border.set_width(kScrollerTrackBorderWidth);
203 canvas->DrawRect(inner_border, paint);
204
205 // Draw the outer border: bottom if horizontal, right if veritcal.
206 paint.setColor(kScrollerTrackOuterBorderColor);
207 gfx::Rect outer_border(inner_border);
208 if (IsHorizontal())
209 outer_border.set_y(track_rect.bottom());
210 else
211 outer_border.set_x(track_rect.right());
212 canvas->DrawRect(outer_border, paint);
213 }
214
215 void CocoaScrollBar::OnMouseEnteredScrollbarThumb(const ui::MouseEvent& event) {
216 if (scroller_style_ != NSScrollerStyleOverlay)
217 return;
218
219 // If the scrollbar thumb has not compeletely faded away, then reshow it when
220 // the mouse enters the scrollbar thumb.
221 if (layer()->opacity())
222 ShowScrollbar();
223
224 hide_scrollbar_timer_.Reset();
225 }
226
227 //////////////////////////////////////////////////////////////////
228 // CocoaScrollBar::ScrollDelegate:
229
230 bool CocoaScrollBar::OnScroll(float dx, float dy) {
231 bool did_scroll = BaseScrollBar::OnScroll(dx, dy);
232 if (did_scroll && scroller_style_ == NSScrollerStyleOverlay) {
233 ShowScrollbar();
234 hide_scrollbar_timer_.Reset();
235 }
236 return did_scroll;
237 }
238
239 //////////////////////////////////////////////////////////////////
240 // CocoaScrollBar::ViewsScrollbarBridge:
241
242 void CocoaScrollBar::OnScrollerStyleChanged() {
243 NSScrollerStyle scroller_style =
244 [ViewsScrollbarBridge getPreferredScrollerStyle];
245 if (scroller_style_ == scroller_style)
246 return;
247
248 scroller_style_ = scroller_style;
249
250 // Ensure that the ScrollView updates the scrollbar's layout.
251 if (parent())
252 parent()->Layout();
253
254 if (scroller_style_ == NSScrollerStyleOverlay)
255 HideScrollbar();
tapted 2016/02/22 04:42:15 This shouldn't fade out (to be consistent with App
spqchan 2016/02/22 19:01:37 Done.
256 else
257 ShowScrollbar();
258 }
259
260 //////////////////////////////////////////////////////////////////
261 // CocoaScrollBar, private:
262
263 void CocoaScrollBar::HideScrollbar() {
264 DCHECK(scroller_style_ == NSScrollerStyleOverlay);
265
266 // If the thumb is in a hover or pressed state, we don't want the scrollbar
267 // to disappear. As such, we should reset the timer.
268 CocoaScrollBarThumb* thumb = static_cast<CocoaScrollBarThumb*>(GetThumb());
269 if (thumb->IsStateHoverOrPressed()) {
270 hide_scrollbar_timer_.Reset();
271 return;
272 }
273
274 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
275 animation.SetTransitionDuration(
276 base::TimeDelta::FromMilliseconds(kFadeDurationMs));
277 layer()->SetOpacity(0.0);
278 }
279
280 void CocoaScrollBar::ShowScrollbar() {
281 // Updates the scrolltrack and repaint it, if necessary.
282 CocoaScrollBarThumb* thumb = static_cast<CocoaScrollBarThumb*>(GetThumb());
283 bool has_scrolltrack = scroller_style_ == NSScrollerStyleLegacy ||
284 thumb->IsStateHoverOrPressed();
285 if (has_scrolltrack_ != has_scrolltrack) {
286 has_scrolltrack_ = has_scrolltrack;
287 SchedulePaint();
288 }
289
290 layer()->SetOpacity(1.0);
291 hide_scrollbar_timer_.Stop();
292 }
293
294 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698