Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 "ui/compositor/layer.h" | |
| 10 #include "ui/compositor/layer_animator.h" | |
| 11 #include "ui/gfx/canvas.h" | |
| 12 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h" | |
| 13 | |
| 14 namespace views { | |
| 15 | |
| 16 namespace { | |
| 17 | |
| 18 // How long we should wait before hiding the scrollbar. | |
| 19 const int kScrollbarHideTimeoutMs = 500; | |
| 20 | |
| 21 // The width of the scrollbar. | |
| 22 const int kScrollbarWidth = 15; | |
| 23 | |
| 24 // The width of the scrollbar thumb. | |
| 25 const int kScrollbarThumbWidth = 10; | |
| 26 | |
| 27 // The width of the scroller track border. | |
| 28 const int kScrollerTrackBorderWidth = 1; | |
| 29 | |
| 30 // The amount the thumb is inset from both the ends and the sides of the track. | |
| 31 const int kScrollbarThumbInset = 3; | |
| 32 | |
| 33 // Scrollbar thumb color. | |
| 34 const SkColor kScrollerThumbColor = SkColorSetARGB(0x38, 0, 0, 0); | |
| 35 | |
| 36 // Scroller track colors. | |
| 37 const SkColor kScrollerTrackColor = SkColorSetRGB(0xF9, 0xF9, 0xF9); | |
| 38 const SkColor kScrollerTrackInnerBorderColor = SkColorSetRGB(0xE4, 0xE4, 0xE4); | |
| 39 const SkColor kScrollerTrackOuterBorderColor = SkColorSetRGB(0xEF, 0xEF, 0xEF); | |
| 40 | |
| 41 // The length of the fade animation. | |
| 42 static const int kFadeDurationMs = 240; | |
|
tapted
2016/02/16 06:47:58
nit: not static
Also perhaps move this up next to
spqchan
2016/02/16 23:18:19
Done.
| |
| 43 | |
| 44 ////////////////////////////////////////////////////////////////// | |
| 45 // CocoaScrollBarThumb | |
| 46 | |
| 47 class CocoaScrollBarThumb : public BaseScrollBarThumb { | |
| 48 public: | |
| 49 explicit CocoaScrollBarThumb(CocoaScrollBar* scroll_bar); | |
| 50 ~CocoaScrollBarThumb() override; | |
| 51 | |
| 52 protected: | |
| 53 // View overrides: | |
| 54 gfx::Size GetPreferredSize() const override; | |
| 55 void OnPaint(gfx::Canvas* canvas) override; | |
| 56 void OnMouseEntered(const ui::MouseEvent& event) override; | |
| 57 void OnMouseExited(const ui::MouseEvent& event) override; | |
| 58 | |
| 59 private: | |
| 60 DISALLOW_COPY_AND_ASSIGN(CocoaScrollBarThumb); | |
| 61 }; | |
| 62 | |
| 63 CocoaScrollBarThumb::CocoaScrollBarThumb(CocoaScrollBar* scroll_bar) | |
| 64 : BaseScrollBarThumb(scroll_bar) { | |
| 65 // This is necessary, otherwise the thumb will be rendered below the views if | |
| 66 // those views paint to their own layers. | |
| 67 SetPaintToLayer(true); | |
| 68 SetFillsBoundsOpaquely(false); | |
| 69 } | |
| 70 | |
| 71 CocoaScrollBarThumb::~CocoaScrollBarThumb() {} | |
| 72 | |
| 73 gfx::Size CocoaScrollBarThumb::GetPreferredSize() const { | |
| 74 return gfx::Size(kScrollbarThumbWidth, kScrollbarThumbWidth); | |
| 75 } | |
| 76 | |
| 77 void CocoaScrollBarThumb::OnPaint(gfx::Canvas* canvas) { | |
| 78 gfx::Rect local_bounds(GetLocalBounds()); | |
| 79 SkPaint paint; | |
| 80 paint.setStyle(SkPaint::kFill_Style); | |
| 81 paint.setColor(kScrollerThumbColor); | |
| 82 const SkScalar radius = std::min(local_bounds.width(), local_bounds.height()); | |
| 83 canvas->DrawRoundRect(local_bounds, radius, paint); | |
| 84 } | |
| 85 | |
| 86 void CocoaScrollBarThumb::OnMouseEntered(const ui::MouseEvent& event) { | |
| 87 BaseScrollBarThumb::OnMouseEntered(event); | |
| 88 CocoaScrollBar* scrollbar = static_cast<CocoaScrollBar*>(scroll_bar()); | |
| 89 scrollbar->OnMouseEnteredScrollbarThumb(event); | |
| 90 } | |
| 91 | |
| 92 void CocoaScrollBarThumb::OnMouseExited(const ui::MouseEvent& event) { | |
| 93 BaseScrollBarThumb::OnMouseExited(event); | |
| 94 CocoaScrollBar* scrollbar = static_cast<CocoaScrollBar*>(scroll_bar()); | |
| 95 scrollbar->OnMouseExitedScrollbarThumb(event); | |
| 96 } | |
| 97 | |
| 98 } // namespace | |
| 99 | |
| 100 ////////////////////////////////////////////////////////////////// | |
| 101 // CocoaScrollBar class | |
| 102 | |
| 103 CocoaScrollBar::CocoaScrollBar(bool horizontal) | |
| 104 : BaseScrollBar(horizontal, new CocoaScrollBarThumb(this)), | |
| 105 is_hovering_(false) { | |
| 106 bridge_.reset([[ViewsScrollbarBridge alloc] init]); | |
| 107 [bridge_ setDelegate:this]; | |
| 108 | |
| 109 scroller_style_ = [ViewsScrollbarBridge getPreferredScrollerStyle]; | |
| 110 | |
| 111 SetPaintToLayer(true); | |
| 112 has_scrolltrack_ = scroller_style_ == NSScrollerStyleLegacy; | |
| 113 layer()->SetOpacity(scroller_style_ == NSScrollerStyleOverlay ? 0.0 : 1.0); | |
| 114 } | |
| 115 | |
| 116 CocoaScrollBar::~CocoaScrollBar() { | |
| 117 [bridge_ setDelegate:nullptr]; | |
| 118 } | |
| 119 | |
| 120 ////////////////////////////////////////////////////////////////// | |
| 121 // CocoaScrollBar, BaseScrollBar: | |
| 122 | |
| 123 gfx::Rect CocoaScrollBar::GetTrackBounds() const { | |
| 124 gfx::Rect local_bounds(GetLocalBounds()); | |
| 125 local_bounds.Inset(kScrollbarThumbInset, kScrollbarThumbInset); | |
| 126 | |
| 127 gfx::Size track_size = local_bounds.size(); | |
| 128 track_size.SetToMax(GetThumb()->size()); | |
| 129 local_bounds.set_size(track_size); | |
| 130 return local_bounds; | |
| 131 } | |
| 132 | |
| 133 ////////////////////////////////////////////////////////////////// | |
| 134 // CocoaScrollBar, ScrollBar: | |
| 135 | |
| 136 int CocoaScrollBar::GetLayoutSize() const { | |
| 137 return 0; | |
| 138 } | |
| 139 | |
| 140 int CocoaScrollBar::GetContentOverlapSize() const { | |
| 141 // TODO: (spqchan) Figure out what to do when we have a corner. | |
| 142 return kScrollbarWidth; | |
| 143 } | |
| 144 | |
| 145 ////////////////////////////////////////////////////////////////// | |
| 146 // CocoaScrollBar::Views: | |
| 147 | |
| 148 gfx::Size CocoaScrollBar::GetPreferredSize() const { | |
| 149 return gfx::Size(); | |
|
tapted
2016/02/16 06:47:58
Does this need to change based on scroller_style_?
spqchan
2016/02/16 23:18:18
This most likely will have to change later, especi
spqchan
2016/02/16 23:22:49
Oh shoot, I see what you mean. I'll look into this
| |
| 150 } | |
| 151 | |
| 152 void CocoaScrollBar::Layout() { | |
|
tapted
2016/02/16 06:47:58
I wonder if this could go in BaseScrollBar.... Of
spqchan
2016/02/16 23:18:18
Yeah, that would work.
| |
| 153 gfx::Rect thumb_bounds = GetTrackBounds(); | |
| 154 BaseScrollBarThumb* thumb = GetThumb(); | |
| 155 if (IsHorizontal()) { | |
| 156 thumb_bounds.set_x(thumb->x()); | |
| 157 thumb_bounds.set_width(thumb->width()); | |
| 158 } else { | |
| 159 thumb_bounds.set_y(thumb->y()); | |
| 160 thumb_bounds.set_height(thumb->height()); | |
| 161 } | |
| 162 thumb->SetBoundsRect(thumb_bounds); | |
| 163 } | |
| 164 | |
| 165 void CocoaScrollBar::OnPaint(gfx::Canvas* canvas) { | |
| 166 if (!has_scrolltrack_) | |
| 167 return; | |
| 168 | |
| 169 // Paint the scrollbar track background. | |
| 170 gfx::Rect track_rect = GetLocalBounds(); | |
| 171 SkPaint paint; | |
| 172 paint.setColor(kScrollerTrackColor); | |
| 173 canvas->DrawRect(track_rect, paint); | |
| 174 | |
| 175 // Paint the inner and outer borders. | |
| 176 // Note: Unless there's a possibility of wanting borders | |
| 177 // to be more than 1px wide, we might want to use drawLine | |
| 178 if (IsHorizontal()) { | |
| 179 // Draw the top border. | |
| 180 SkPaint paint; | |
| 181 paint.setColor(kScrollerTrackInnerBorderColor); | |
| 182 gfx::Rect top_border(track_rect); | |
| 183 top_border.set_height(kScrollerTrackBorderWidth); | |
| 184 canvas->DrawRect(top_border, paint); | |
| 185 | |
| 186 // Draw the bottom border. | |
| 187 paint.setColor(kScrollerTrackOuterBorderColor); | |
| 188 gfx::Rect bottom_border(top_border); | |
| 189 bottom_border.set_y(track_rect.bottom()); | |
| 190 canvas->DrawRect(bottom_border, paint); | |
| 191 } else { | |
| 192 // Draw the left border. | |
| 193 SkPaint paint; | |
| 194 paint.setColor(kScrollerTrackInnerBorderColor); | |
| 195 gfx::Rect left_border(track_rect); | |
| 196 left_border.set_width(kScrollerTrackBorderWidth); | |
|
tapted
2016/02/16 06:47:58
do these look any better merged? I think only the
spqchan
2016/02/16 23:18:18
I kept it separate because I thought it would be e
| |
| 197 canvas->DrawRect(left_border, paint); | |
| 198 | |
| 199 // Draw the right border. | |
| 200 paint.setColor(kScrollerTrackOuterBorderColor); | |
| 201 gfx::Rect right_border(left_border); | |
| 202 right_border.set_x(track_rect.right()); | |
| 203 canvas->DrawRect(right_border, paint); | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 void CocoaScrollBar::OnMouseEnteredScrollbarThumb(const ui::MouseEvent& event) { | |
| 208 if (scroller_style_ != NSScrollerStyleOverlay) | |
| 209 return; | |
| 210 | |
| 211 hide_scrollbar_timer_.Stop(); | |
| 212 is_hovering_ = true; | |
| 213 if (layer()->opacity()) { | |
| 214 ShowScrollbar(); | |
| 215 } | |
| 216 } | |
| 217 | |
| 218 void CocoaScrollBar::OnMouseExitedScrollbarThumb(const ui::MouseEvent& event) { | |
| 219 if (scroller_style_ != NSScrollerStyleOverlay) | |
| 220 return; | |
|
tapted
2016/02/16 06:47:58
nit: blank line after return
spqchan
2016/02/16 23:18:18
We can't have blank lines after return?
TIL, I'll
tapted
2016/02/16 23:32:57
Ah, no the opposite :). There *should* be a line b
| |
| 221 is_hovering_ = false; | |
| 222 ResetTimer(); | |
| 223 } | |
| 224 | |
| 225 ////////////////////////////////////////////////////////////////// | |
| 226 // CocoaScrollBar::ScrollDelegate: | |
| 227 | |
| 228 bool CocoaScrollBar::OnScroll(float dx, float dy) { | |
| 229 bool did_scroll = BaseScrollBar::OnScroll(dx, dy); | |
| 230 if (did_scroll && scroller_style_ == NSScrollerStyleOverlay) { | |
| 231 if (layer()->opacity() < 1.0) | |
| 232 ShowScrollbar(); | |
| 233 ResetTimer(); | |
| 234 } | |
| 235 return did_scroll; | |
| 236 } | |
| 237 | |
| 238 ////////////////////////////////////////////////////////////////// | |
| 239 // CocoaScrollBar::ViewsScrollbarBridge: | |
| 240 | |
| 241 void CocoaScrollBar::OnScrollerStyleChanged() { | |
| 242 NSScrollerStyle scroller_style = | |
| 243 [ViewsScrollbarBridge getPreferredScrollerStyle]; | |
| 244 if (scroller_style_ == scroller_style) | |
| 245 return; | |
| 246 | |
| 247 scroller_style_ = scroller_style; | |
| 248 if (scroller_style_ == NSScrollerStyleOverlay) { | |
| 249 HideScrollbar(); | |
| 250 } else { | |
| 251 ShowScrollbar(); | |
| 252 } | |
| 253 } | |
| 254 | |
| 255 ////////////////////////////////////////////////////////////////// | |
| 256 // CocoaScrollBar, private: | |
| 257 | |
| 258 void CocoaScrollBar::HideScrollbar() { | |
| 259 layer()->GetAnimator()->SetTransitionDuration( | |
| 260 base::TimeDelta::FromMilliseconds(kFadeDurationMs)); | |
| 261 layer()->SetOpacity(0.0); | |
| 262 } | |
| 263 | |
| 264 void CocoaScrollBar::ShowScrollbar() { | |
| 265 // Updates the scrolltrack and repaint it, if necessary. | |
| 266 bool has_scrolltrack = | |
| 267 scroller_style_ == NSScrollerStyleLegacy || is_hovering_; | |
| 268 if (has_scrolltrack_ != has_scrolltrack) { | |
| 269 has_scrolltrack_ = has_scrolltrack; | |
| 270 SchedulePaint(); | |
| 271 } | |
| 272 | |
| 273 layer()->GetAnimator()->SetTransitionDuration( | |
| 274 base::TimeDelta::FromMilliseconds(0)); | |
|
tapted
2016/02/16 06:47:58
this line probably won't be needed with the Scoped
spqchan
2016/02/16 23:18:18
Done.
| |
| 275 layer()->SetOpacity(1.0); | |
| 276 } | |
| 277 | |
| 278 void CocoaScrollBar::ResetTimer() { | |
| 279 if (hide_scrollbar_timer_.IsRunning()) { | |
| 280 hide_scrollbar_timer_.Reset(); | |
| 281 } else { | |
| 282 hide_scrollbar_timer_.Start( | |
| 283 FROM_HERE, base::TimeDelta::FromMilliseconds(kScrollbarHideTimeoutMs), | |
| 284 this, &CocoaScrollBar::HideScrollbar); | |
| 285 } | |
| 286 } | |
| 287 | |
| 288 } // namespace views | |
| OLD | NEW |