Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 // Add an alpha channel for the overlay-style scroll track. | |
|
tapted
2016/02/22 22:34:57
Should say 'TODO' in the comment
spqchan
2016/02/22 23:26:03
Done.
| |
| 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 } | |
| 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 void CocoaScrollBar::Layout() { | |
| 170 GetThumb()->SetBoundsRect(GetTrackBounds()); | |
| 171 } | |
| 172 | |
| 173 gfx::Size CocoaScrollBar::GetPreferredSize() const { | |
| 174 return gfx::Size(); | |
| 175 } | |
| 176 | |
| 177 void CocoaScrollBar::OnPaint(gfx::Canvas* canvas) { | |
| 178 if (!has_scrolltrack_) | |
| 179 return; | |
| 180 | |
| 181 // Paint the scrollbar track background. | |
| 182 gfx::Rect track_rect = GetLocalBounds(); | |
| 183 | |
| 184 SkPoint gradient_bounds[2]; | |
| 185 if (IsHorizontal()) { | |
| 186 gradient_bounds[0].set(track_rect.x(), track_rect.y()); | |
| 187 gradient_bounds[1].set(track_rect.x(), track_rect.bottom()); | |
| 188 } else { | |
| 189 gradient_bounds[0].set(track_rect.x(), track_rect.y()); | |
| 190 gradient_bounds[1].set(track_rect.right(), track_rect.y()); | |
| 191 } | |
| 192 skia::RefPtr<SkShader> shader = skia::AdoptRef(SkGradientShader::CreateLinear( | |
| 193 gradient_bounds, kScrollerTrackGradientColors, nullptr, | |
| 194 arraysize(kScrollerTrackGradientColors), SkShader::kClamp_TileMode)); | |
| 195 SkPaint gradient; | |
| 196 gradient.setShader(shader.get()); | |
| 197 canvas->DrawRect(track_rect, gradient); | |
| 198 | |
| 199 // Draw the inner border: top if horizontal, left if vertical. | |
| 200 SkPaint paint; | |
| 201 paint.setColor(kScrollerTrackInnerBorderColor); | |
| 202 gfx::Rect inner_border(track_rect); | |
| 203 if (IsHorizontal()) | |
| 204 inner_border.set_height(kScrollerTrackBorderWidth); | |
| 205 else | |
| 206 inner_border.set_width(kScrollerTrackBorderWidth); | |
| 207 canvas->DrawRect(inner_border, paint); | |
| 208 | |
| 209 // Draw the outer border: bottom if horizontal, right if veritcal. | |
| 210 paint.setColor(kScrollerTrackOuterBorderColor); | |
| 211 gfx::Rect outer_border(inner_border); | |
| 212 if (IsHorizontal()) | |
| 213 outer_border.set_y(track_rect.bottom()); | |
| 214 else | |
| 215 outer_border.set_x(track_rect.right()); | |
| 216 canvas->DrawRect(outer_border, paint); | |
| 217 } | |
| 218 | |
| 219 void CocoaScrollBar::OnMouseEnteredScrollbarThumb(const ui::MouseEvent& event) { | |
| 220 if (scroller_style_ != NSScrollerStyleOverlay) | |
| 221 return; | |
| 222 | |
| 223 // If the scrollbar thumb has not compeletely faded away, then reshow it when | |
| 224 // the mouse enters the scrollbar thumb. | |
| 225 if (layer()->opacity()) | |
| 226 ShowScrollbar(); | |
| 227 | |
| 228 hide_scrollbar_timer_.Reset(); | |
| 229 } | |
| 230 | |
| 231 ////////////////////////////////////////////////////////////////// | |
| 232 // CocoaScrollBar::ScrollDelegate: | |
| 233 | |
| 234 bool CocoaScrollBar::OnScroll(float dx, float dy) { | |
| 235 bool did_scroll = BaseScrollBar::OnScroll(dx, dy); | |
| 236 if (did_scroll && scroller_style_ == NSScrollerStyleOverlay) { | |
| 237 ShowScrollbar(); | |
| 238 hide_scrollbar_timer_.Reset(); | |
| 239 } | |
| 240 return did_scroll; | |
| 241 } | |
| 242 | |
| 243 ////////////////////////////////////////////////////////////////// | |
| 244 // CocoaScrollBar::ViewsScrollbarBridge: | |
| 245 | |
| 246 void CocoaScrollBar::OnScrollerStyleChanged() { | |
| 247 NSScrollerStyle scroller_style = | |
| 248 [ViewsScrollbarBridge getPreferredScrollerStyle]; | |
| 249 if (scroller_style_ == scroller_style) | |
| 250 return; | |
| 251 | |
| 252 scroller_style_ = scroller_style; | |
| 253 | |
| 254 // Ensure that the ScrollView updates the scrollbar's layout. | |
| 255 if (parent()) | |
| 256 parent()->Layout(); | |
| 257 | |
| 258 if (scroller_style_ == NSScrollerStyleOverlay) | |
| 259 layer()->SetOpacity(0.0); // Don't fade out | |
|
tapted
2016/02/22 22:34:57
nit: full stop after comment.
spqchan
2016/02/22 23:26:03
Done.
| |
| 260 else | |
| 261 ShowScrollbar(); | |
| 262 } | |
| 263 | |
| 264 ////////////////////////////////////////////////////////////////// | |
| 265 // CocoaScrollBar, private: | |
| 266 | |
| 267 void CocoaScrollBar::HideScrollbar() { | |
| 268 DCHECK_EQ(scroller_style_, NSScrollerStyleOverlay); | |
| 269 | |
| 270 // If the thumb is in a hover or pressed state, we don't want the scrollbar | |
| 271 // to disappear. As such, we should reset the timer. | |
| 272 CocoaScrollBarThumb* thumb = static_cast<CocoaScrollBarThumb*>(GetThumb()); | |
| 273 if (thumb->IsStateHoverOrPressed()) { | |
| 274 hide_scrollbar_timer_.Reset(); | |
| 275 return; | |
| 276 } | |
| 277 | |
| 278 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); | |
| 279 animation.SetTransitionDuration( | |
| 280 base::TimeDelta::FromMilliseconds(kFadeDurationMs)); | |
| 281 layer()->SetOpacity(0.0); | |
| 282 } | |
| 283 | |
| 284 void CocoaScrollBar::ShowScrollbar() { | |
| 285 // Updates the scrolltrack and repaint it, if necessary. | |
| 286 CocoaScrollBarThumb* thumb = static_cast<CocoaScrollBarThumb*>(GetThumb()); | |
| 287 bool has_scrolltrack = scroller_style_ == NSScrollerStyleLegacy || | |
| 288 thumb->IsStateHoverOrPressed(); | |
| 289 if (has_scrolltrack_ != has_scrolltrack) { | |
| 290 has_scrolltrack_ = has_scrolltrack; | |
| 291 SchedulePaint(); | |
| 292 } | |
| 293 | |
| 294 layer()->SetOpacity(1.0); | |
| 295 hide_scrollbar_timer_.Stop(); | |
| 296 } | |
| 297 | |
| 298 } // namespace views | |
| OLD | NEW |