OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "views/controls/scrollbar/bitmap_scroll_bar.h" | 5 #include "views/controls/scrollbar/bitmap_scroll_bar.h" |
6 | 6 |
7 #if defined(OS_LINUX) | 7 #if defined(OS_LINUX) |
8 #include "views/screen.h" | 8 #include "views/screen.h" |
9 #endif | 9 #endif |
10 | 10 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 }; | 90 }; |
91 | 91 |
92 /////////////////////////////////////////////////////////////////////////////// | 92 /////////////////////////////////////////////////////////////////////////////// |
93 // | 93 // |
94 // BitmapScrollBarThumb | 94 // BitmapScrollBarThumb |
95 // | 95 // |
96 // A view that acts as the thumb in the scroll bar track that the user can | 96 // A view that acts as the thumb in the scroll bar track that the user can |
97 // drag to scroll the associated contents view within the viewport. | 97 // drag to scroll the associated contents view within the viewport. |
98 // | 98 // |
99 /////////////////////////////////////////////////////////////////////////////// | 99 /////////////////////////////////////////////////////////////////////////////// |
100 class BitmapScrollBarThumb : public View { | 100 class BitmapScrollBarThumb : public BaseScrollBarThumb { |
101 public: | 101 public: |
102 explicit BitmapScrollBarThumb(BitmapScrollBar* scroll_bar) | 102 explicit BitmapScrollBarThumb(BitmapScrollBar* scroll_bar) |
103 : scroll_bar_(scroll_bar), | 103 : BaseScrollBarThumb(scroll_bar), |
104 drag_start_position_(-1), | 104 scroll_bar_(scroll_bar) { |
105 mouse_offset_(-1), | |
106 state_(CustomButton::BS_NORMAL) { | |
107 } | 105 } |
108 virtual ~BitmapScrollBarThumb() { } | 106 virtual ~BitmapScrollBarThumb() { } |
109 | 107 |
110 // Sets the size (width or height) of the thumb to the specified value. | |
111 void SetSize(int size) { | |
112 // Make sure the thumb is never sized smaller than its minimum possible | |
113 // display size. | |
114 gfx::Size prefsize = GetPreferredSize(); | |
115 size = std::max(size, scroll_bar_->IsHorizontal() ? prefsize.width() : | |
116 prefsize.height()); | |
117 gfx::Rect thumb_bounds = bounds(); | |
118 if (scroll_bar_->IsHorizontal()) { | |
119 thumb_bounds.set_width(size); | |
120 } else { | |
121 thumb_bounds.set_height(size); | |
122 } | |
123 SetBoundsRect(thumb_bounds); | |
124 } | |
125 | |
126 // Retrieves the size (width or height) of the thumb. | |
127 int GetSize() const { | |
128 if (scroll_bar_->IsHorizontal()) | |
129 return width(); | |
130 return height(); | |
131 } | |
132 | |
133 // Sets the position of the thumb on the x or y axis. | |
134 void SetPosition(int position) { | |
135 gfx::Rect thumb_bounds = bounds(); | |
136 gfx::Rect track_bounds = scroll_bar_->GetTrackBounds(); | |
137 if (scroll_bar_->IsHorizontal()) { | |
138 thumb_bounds.set_x(track_bounds.x() + position); | |
139 } else { | |
140 thumb_bounds.set_y(track_bounds.y() + position); | |
141 } | |
142 SetBoundsRect(thumb_bounds); | |
143 } | |
144 | |
145 // Gets the position of the thumb on the x or y axis. | |
146 int GetPosition() const { | |
147 gfx::Rect track_bounds = scroll_bar_->GetTrackBounds(); | |
148 if (scroll_bar_->IsHorizontal()) | |
149 return x() - track_bounds.x(); | |
150 return y() - track_bounds.y(); | |
151 } | |
152 | |
153 // View overrides: | 108 // View overrides: |
154 virtual gfx::Size GetPreferredSize() OVERRIDE { | 109 virtual gfx::Size GetPreferredSize() OVERRIDE { |
155 return gfx::Size(background_bitmap()->width(), | 110 return gfx::Size(background_bitmap()->width(), |
156 start_cap_bitmap()->height() + | 111 start_cap_bitmap()->height() + |
157 end_cap_bitmap()->height() + | 112 end_cap_bitmap()->height() + |
158 grippy_bitmap()->height()); | 113 grippy_bitmap()->height()); |
159 } | 114 } |
160 | 115 |
161 protected: | 116 protected: |
162 // View overrides: | 117 // View overrides: |
163 virtual void Paint(gfx::Canvas* canvas) OVERRIDE { | 118 virtual void Paint(gfx::Canvas* canvas) OVERRIDE { |
164 canvas->DrawBitmapInt(*start_cap_bitmap(), 0, 0); | 119 canvas->DrawBitmapInt(*start_cap_bitmap(), 0, 0); |
165 int top_cap_height = start_cap_bitmap()->height(); | 120 int top_cap_height = start_cap_bitmap()->height(); |
166 int bottom_cap_height = end_cap_bitmap()->height(); | 121 int bottom_cap_height = end_cap_bitmap()->height(); |
167 int thumb_body_height = height() - top_cap_height - bottom_cap_height; | 122 int thumb_body_height = height() - top_cap_height - bottom_cap_height; |
168 canvas->TileImageInt(*background_bitmap(), 0, top_cap_height, | 123 canvas->TileImageInt(*background_bitmap(), 0, top_cap_height, |
169 background_bitmap()->width(), thumb_body_height); | 124 background_bitmap()->width(), thumb_body_height); |
170 canvas->DrawBitmapInt(*end_cap_bitmap(), 0, | 125 canvas->DrawBitmapInt(*end_cap_bitmap(), 0, |
171 height() - bottom_cap_height); | 126 height() - bottom_cap_height); |
172 | 127 |
173 // Paint the grippy over the track. | 128 // Paint the grippy over the track. |
174 int grippy_x = (width() - grippy_bitmap()->width()) / 2; | 129 int grippy_x = (width() - grippy_bitmap()->width()) / 2; |
175 int grippy_y = (thumb_body_height - grippy_bitmap()->height()) / 2; | 130 int grippy_y = (thumb_body_height - grippy_bitmap()->height()) / 2; |
176 canvas->DrawBitmapInt(*grippy_bitmap(), grippy_x, grippy_y); | 131 canvas->DrawBitmapInt(*grippy_bitmap(), grippy_x, grippy_y); |
177 } | 132 } |
178 | 133 |
179 virtual void OnMouseEntered(const MouseEvent& event) OVERRIDE { | |
180 SetState(CustomButton::BS_HOT); | |
181 } | |
182 | |
183 virtual void OnMouseExited(const MouseEvent& event) OVERRIDE { | |
184 SetState(CustomButton::BS_NORMAL); | |
185 } | |
186 | |
187 virtual bool OnMousePressed(const MouseEvent& event) OVERRIDE { | |
188 mouse_offset_ = scroll_bar_->IsHorizontal() ? event.x() : event.y(); | |
189 drag_start_position_ = GetPosition(); | |
190 SetState(CustomButton::BS_PUSHED); | |
191 return true; | |
192 } | |
193 | |
194 virtual bool OnMouseDragged(const MouseEvent& event) OVERRIDE { | |
195 // If the user moves the mouse more than |kScrollThumbDragOutSnap| outside | |
196 // the bounds of the thumb, the scrollbar will snap the scroll back to the | |
197 // point it was at before the drag began. | |
198 if (scroll_bar_->IsHorizontal()) { | |
199 if ((event.y() < y() - kScrollThumbDragOutSnap) || | |
200 (event.y() > (y() + height() + kScrollThumbDragOutSnap))) { | |
201 scroll_bar_->ScrollToThumbPosition(drag_start_position_, false); | |
202 return true; | |
203 } | |
204 } else { | |
205 if ((event.x() < x() - kScrollThumbDragOutSnap) || | |
206 (event.x() > (x() + width() + kScrollThumbDragOutSnap))) { | |
207 scroll_bar_->ScrollToThumbPosition(drag_start_position_, false); | |
208 return true; | |
209 } | |
210 } | |
211 if (scroll_bar_->IsHorizontal()) { | |
212 int thumb_x = event.x() - mouse_offset_; | |
213 scroll_bar_->ScrollToThumbPosition(x() + thumb_x, false); | |
214 } else { | |
215 int thumb_y = event.y() - mouse_offset_; | |
216 scroll_bar_->ScrollToThumbPosition(y() + thumb_y, false); | |
217 } | |
218 return true; | |
219 } | |
220 | |
221 virtual void OnMouseReleased(const MouseEvent& event) OVERRIDE { | |
222 OnMouseCaptureLost(); | |
223 } | |
224 | |
225 virtual void OnMouseCaptureLost() OVERRIDE { | |
226 SetState(CustomButton::BS_HOT); | |
227 } | |
228 | |
229 private: | 134 private: |
230 // Returns the bitmap rendered at the start of the thumb. | 135 // Returns the bitmap rendered at the start of the thumb. |
231 SkBitmap* start_cap_bitmap() const { | 136 SkBitmap* start_cap_bitmap() const { |
232 return scroll_bar_->images_[BitmapScrollBar::THUMB_START_CAP][state_]; | 137 return scroll_bar_->images_[BitmapScrollBar::THUMB_START_CAP][GetState()]; |
233 } | 138 } |
234 | 139 |
235 // Returns the bitmap rendered at the end of the thumb. | 140 // Returns the bitmap rendered at the end of the thumb. |
236 SkBitmap* end_cap_bitmap() const { | 141 SkBitmap* end_cap_bitmap() const { |
237 return scroll_bar_->images_[BitmapScrollBar::THUMB_END_CAP][state_]; | 142 return scroll_bar_->images_[BitmapScrollBar::THUMB_END_CAP][GetState()]; |
238 } | 143 } |
239 | 144 |
240 // Returns the bitmap that is tiled in the background of the thumb between | 145 // Returns the bitmap that is tiled in the background of the thumb between |
241 // the start and the end caps. | 146 // the start and the end caps. |
242 SkBitmap* background_bitmap() const { | 147 SkBitmap* background_bitmap() const { |
243 return scroll_bar_->images_[BitmapScrollBar::THUMB_MIDDLE][state_]; | 148 return scroll_bar_->images_[BitmapScrollBar::THUMB_MIDDLE][GetState()]; |
244 } | 149 } |
245 | 150 |
246 // Returns the bitmap that is rendered in the middle of the thumb | 151 // Returns the bitmap that is rendered in the middle of the thumb |
247 // transparently over the background bitmap. | 152 // transparently over the background bitmap. |
248 SkBitmap* grippy_bitmap() const { | 153 SkBitmap* grippy_bitmap() const { |
249 return scroll_bar_->images_[BitmapScrollBar::THUMB_GRIPPY] | 154 return scroll_bar_->images_[BitmapScrollBar::THUMB_GRIPPY] |
250 [CustomButton::BS_NORMAL]; | 155 [CustomButton::BS_NORMAL]; |
251 } | 156 } |
252 | 157 |
253 // Update our state and schedule a repaint when the mouse moves over us. | |
254 void SetState(CustomButton::ButtonState state) { | |
255 state_ = state; | |
256 SchedulePaint(); | |
257 } | |
258 | |
259 // The BitmapScrollBar that owns us. | 158 // The BitmapScrollBar that owns us. |
260 BitmapScrollBar* scroll_bar_; | 159 BitmapScrollBar* scroll_bar_; |
261 | 160 |
262 int drag_start_position_; | |
263 | |
264 // The position of the mouse on the scroll axis relative to the top of this | |
265 // View when the drag started. | |
266 int mouse_offset_; | |
267 | |
268 // The current state of the thumb button. | |
269 CustomButton::ButtonState state_; | |
270 | |
271 DISALLOW_COPY_AND_ASSIGN(BitmapScrollBarThumb); | 161 DISALLOW_COPY_AND_ASSIGN(BitmapScrollBarThumb); |
272 }; | 162 }; |
273 | 163 |
274 } // anonymous namespace | 164 } // anonymous namespace |
275 | 165 |
276 /////////////////////////////////////////////////////////////////////////////// | 166 /////////////////////////////////////////////////////////////////////////////// |
277 // BitmapScrollBar, public: | 167 // BitmapScrollBar, public: |
278 | 168 |
279 BitmapScrollBar::BitmapScrollBar(bool horizontal, bool show_scroll_buttons) | 169 BitmapScrollBar::BitmapScrollBar(bool horizontal, bool show_scroll_buttons) |
280 : contents_size_(0), | 170 : BaseScrollBar(horizontal, new BitmapScrollBarThumb(this)), |
281 contents_scroll_offset_(0), | 171 contents_scroll_offset_(0), |
282 ALLOW_THIS_IN_INITIALIZER_LIST(prev_button_(new AutorepeatButton(this))), | 172 ALLOW_THIS_IN_INITIALIZER_LIST(prev_button_(new AutorepeatButton(this))), |
283 ALLOW_THIS_IN_INITIALIZER_LIST(next_button_(new AutorepeatButton(this))), | 173 ALLOW_THIS_IN_INITIALIZER_LIST(next_button_(new AutorepeatButton(this))), |
284 ALLOW_THIS_IN_INITIALIZER_LIST(thumb_(new BitmapScrollBarThumb(this))), | |
285 thumb_track_state_(CustomButton::BS_NORMAL), | 174 thumb_track_state_(CustomButton::BS_NORMAL), |
286 last_scroll_amount_(SCROLL_NONE), | 175 last_scroll_amount_(SCROLL_NONE), |
287 ALLOW_THIS_IN_INITIALIZER_LIST(repeater_( | 176 ALLOW_THIS_IN_INITIALIZER_LIST(repeater_( |
288 NewCallback<BitmapScrollBar>(this, | 177 NewCallback<BitmapScrollBar>(this, |
289 &BitmapScrollBar::TrackClicked))), | 178 &BitmapScrollBar::TrackClicked))), |
290 context_menu_mouse_position_(0), | 179 context_menu_mouse_position_(0), |
291 show_scroll_buttons_(show_scroll_buttons), | 180 show_scroll_buttons_(show_scroll_buttons), |
292 ScrollBar(horizontal) { | 181 ScrollBar(horizontal) { |
293 if (!show_scroll_buttons_) { | 182 if (!show_scroll_buttons_) { |
294 prev_button_->SetVisible(false); | 183 prev_button_->SetVisible(false); |
295 next_button_->SetVisible(false); | 184 next_button_->SetVisible(false); |
296 } | 185 } |
297 | 186 |
298 AddChildView(prev_button_); | 187 AddChildView(prev_button_); |
299 AddChildView(next_button_); | 188 AddChildView(next_button_); |
300 AddChildView(thumb_); | |
301 | 189 |
302 set_context_menu_controller(this); | 190 set_context_menu_controller(this); |
303 prev_button_->set_context_menu_controller(this); | 191 prev_button_->set_context_menu_controller(this); |
304 next_button_->set_context_menu_controller(this); | 192 next_button_->set_context_menu_controller(this); |
305 thumb_->set_context_menu_controller(this); | |
306 } | |
307 | |
308 gfx::Rect BitmapScrollBar::GetTrackBounds() const { | |
309 gfx::Size prefsize = prev_button_->GetPreferredSize(); | |
310 if (IsHorizontal()) { | |
311 if (!show_scroll_buttons_) | |
312 prefsize.set_width(0); | |
313 int new_width = | |
314 std::max(0, width() - (prefsize.width() * 2)); | |
315 gfx::Rect track_bounds(prefsize.width(), 0, new_width, prefsize.height()); | |
316 return track_bounds; | |
317 } | |
318 if (!show_scroll_buttons_) | |
319 prefsize.set_height(0); | |
320 gfx::Rect track_bounds(0, prefsize.height(), prefsize.width(), | |
321 std::max(0, height() - (prefsize.height() * 2))); | |
322 return track_bounds; | |
323 } | 193 } |
324 | 194 |
325 void BitmapScrollBar::SetImage(ScrollBarPart part, | 195 void BitmapScrollBar::SetImage(ScrollBarPart part, |
326 CustomButton::ButtonState state, | 196 CustomButton::ButtonState state, |
327 SkBitmap* bitmap) { | 197 SkBitmap* bitmap) { |
328 DCHECK(part < PART_COUNT); | 198 DCHECK(part < PART_COUNT); |
329 DCHECK(state < CustomButton::BS_COUNT); | 199 DCHECK(state < CustomButton::BS_COUNT); |
330 switch (part) { | 200 switch (part) { |
331 case PREV_BUTTON: | 201 case PREV_BUTTON: |
332 prev_button_->SetImage(state, bitmap); | 202 prev_button_->SetImage(state, bitmap); |
333 break; | 203 break; |
334 case NEXT_BUTTON: | 204 case NEXT_BUTTON: |
335 next_button_->SetImage(state, bitmap); | 205 next_button_->SetImage(state, bitmap); |
336 break; | 206 break; |
337 case THUMB_START_CAP: | 207 case THUMB_START_CAP: |
338 case THUMB_MIDDLE: | 208 case THUMB_MIDDLE: |
339 case THUMB_END_CAP: | 209 case THUMB_END_CAP: |
340 case THUMB_GRIPPY: | 210 case THUMB_GRIPPY: |
341 case THUMB_TRACK: | 211 case THUMB_TRACK: |
342 images_[part][state] = bitmap; | 212 images_[part][state] = bitmap; |
343 break; | 213 break; |
344 } | 214 } |
345 } | 215 } |
346 | 216 |
347 void BitmapScrollBar::ScrollByAmount(ScrollAmount amount) { | 217 int BaseScrollBar::GetLayoutSize() const { |
348 ScrollBarController* controller = GetController(); | 218 gfx::Size prefsize = prev_button_->GetPreferredSize(); |
349 int offset = contents_scroll_offset_; | 219 return IsHorizontal() ? prefsize.height() : prefsize.width(); |
350 switch (amount) { | |
351 case SCROLL_START: | |
352 offset = GetMinPosition(); | |
353 break; | |
354 case SCROLL_END: | |
355 offset = GetMaxPosition(); | |
356 break; | |
357 case SCROLL_PREV_LINE: | |
358 offset -= controller->GetScrollIncrement(this, false, false); | |
359 offset = std::max(GetMinPosition(), offset); | |
360 break; | |
361 case SCROLL_NEXT_LINE: | |
362 offset += controller->GetScrollIncrement(this, false, true); | |
363 offset = std::min(GetMaxPosition(), offset); | |
364 break; | |
365 case SCROLL_PREV_PAGE: | |
366 offset -= controller->GetScrollIncrement(this, true, false); | |
367 offset = std::max(GetMinPosition(), offset); | |
368 break; | |
369 case SCROLL_NEXT_PAGE: | |
370 offset += controller->GetScrollIncrement(this, true, true); | |
371 offset = std::min(GetMaxPosition(), offset); | |
372 break; | |
373 } | |
374 contents_scroll_offset_ = offset; | |
375 ScrollContentsToOffset(); | |
376 } | 220 } |
377 | 221 |
378 void BitmapScrollBar::ScrollToThumbPosition(int thumb_position, | 222 gfx::Rect BaseScrollBar::GetTrackBounds() const { |
379 bool scroll_to_middle) { | 223 gfx::Size prefsize = prev_button_->GetPreferredSize(); |
380 contents_scroll_offset_ = | 224 if (IsHorizontal()) { |
381 CalculateContentsOffset(thumb_position, scroll_to_middle); | 225 if (!show_scroll_buttons_) |
382 if (contents_scroll_offset_ < GetMinPosition()) { | 226 prefsize.set_width(0); |
383 contents_scroll_offset_ = GetMinPosition(); | 227 int new_width = |
384 } else if (contents_scroll_offset_ > GetMaxPosition()) { | 228 std::max(0, width() - (prefsize.width() * 2)); |
385 contents_scroll_offset_ = GetMaxPosition(); | 229 gfx::Rect track_bounds(prefsize.width(), 0, new_width, prefsize.height()); |
| 230 return track_bounds; |
386 } | 231 } |
387 ScrollContentsToOffset(); | 232 if (!show_scroll_buttons_) |
388 SchedulePaint(); | 233 prefsize.set_height(0); |
389 } | 234 gfx::Rect track_bounds(0, prefsize.height(), prefsize.width(), |
390 | 235 std::max(0, height() - (prefsize.height() * 2))); |
391 void BitmapScrollBar::ScrollByContentsOffset(int contents_offset) { | 236 return track_bounds; |
392 contents_scroll_offset_ -= contents_offset; | |
393 if (contents_scroll_offset_ < GetMinPosition()) { | |
394 contents_scroll_offset_ = GetMinPosition(); | |
395 } else if (contents_scroll_offset_ > GetMaxPosition()) { | |
396 contents_scroll_offset_ = GetMaxPosition(); | |
397 } | |
398 ScrollContentsToOffset(); | |
399 } | 237 } |
400 | 238 |
401 /////////////////////////////////////////////////////////////////////////////// | 239 /////////////////////////////////////////////////////////////////////////////// |
402 // BitmapScrollBar, View implementation: | 240 // BaseScrollBar, View implementation: |
403 | 241 |
404 gfx::Size BitmapScrollBar::GetPreferredSize() { | 242 gfx::Size BaseScrollBar::GetPreferredSize() { |
405 // In this case, we're returning the desired width of the scrollbar and its | 243 // In this case, we're returning the desired width of the scrollbar and its |
406 // minimum allowable height. | 244 // minimum allowable height. |
407 gfx::Size button_prefsize = prev_button_->GetPreferredSize(); | 245 gfx::Size button_prefsize = prev_button_->GetPreferredSize(); |
408 return gfx::Size(button_prefsize.width(), button_prefsize.height() * 2); | 246 return gfx::Size(button_prefsize.width(), button_prefsize.height() * 2); |
409 } | 247 } |
410 | 248 |
411 void BitmapScrollBar::Layout() { | 249 void BaseScrollBar::Layout() { |
412 // Size and place the two scroll buttons. | 250 // Size and place the two scroll buttons. |
413 if (show_scroll_buttons_) { | 251 if (show_scroll_buttons_) { |
414 gfx::Size prefsize = prev_button_->GetPreferredSize(); | 252 gfx::Size prefsize = prev_button_->GetPreferredSize(); |
415 prev_button_->SetBounds(0, 0, prefsize.width(), prefsize.height()); | 253 prev_button_->SetBounds(0, 0, prefsize.width(), prefsize.height()); |
416 prefsize = next_button_->GetPreferredSize(); | 254 prefsize = next_button_->GetPreferredSize(); |
417 if (IsHorizontal()) { | 255 if (IsHorizontal()) { |
418 next_button_->SetBounds(width() - prefsize.width(), 0, prefsize.width(), | 256 next_button_->SetBounds(width() - prefsize.width(), 0, prefsize.width(), |
419 prefsize.height()); | 257 prefsize.height()); |
420 } else { | 258 } else { |
421 next_button_->SetBounds(0, height() - prefsize.height(), prefsize.width(), | 259 next_button_->SetBounds(0, height() - prefsize.height(), prefsize.width(), |
422 prefsize.height()); | 260 prefsize.height()); |
423 } | 261 } |
424 } else { | 262 } else { |
425 prev_button_->SetBounds(0, 0, 0, 0); | 263 prev_button_->SetBounds(0, 0, 0, 0); |
426 next_button_->SetBounds(0, 0, 0, 0); | 264 next_button_->SetBounds(0, 0, 0, 0); |
427 } | 265 } |
428 | 266 |
| 267 BaseScrollBarThumb* thumb = GetThumb(); |
429 // Size and place the thumb | 268 // Size and place the thumb |
430 gfx::Size thumb_prefsize = thumb_->GetPreferredSize(); | 269 gfx::Size thumb_prefsize = thumb->GetPreferredSize(); |
431 gfx::Rect track_bounds = GetTrackBounds(); | 270 gfx::Rect track_bounds = GetTrackBounds(); |
432 | 271 |
433 // Preserve the height/width of the thumb (depending on orientation) as set | 272 // Preserve the height/width of the thumb (depending on orientation) as set |
434 // by the last call to |Update|, but coerce the width/height to be the | 273 // by the last call to |Update|, but coerce the width/height to be the |
435 // appropriate value for the bitmaps provided. | 274 // appropriate value for the bitmaps provided. |
436 if (IsHorizontal()) { | 275 if (IsHorizontal()) { |
437 thumb_->SetBounds(thumb_->x(), thumb_->y(), thumb_->width(), | 276 thumb->SetBounds(thumb->x(), thumb->y(), thumb->width(), |
438 thumb_prefsize.height()); | 277 thumbprefsize.height()); |
439 } else { | 278 } else { |
440 thumb_->SetBounds(thumb_->x(), thumb_->y(), thumb_prefsize.width(), | 279 thumb->SetBounds(thumb->x(), thumb->y(), thumbprefsize.width(), |
441 thumb_->height()); | 280 thumb->height()); |
442 } | 281 } |
443 | 282 |
444 // Hide the thumb if the track isn't tall enough to display even a tiny | 283 // Hide the thumb if the track isn't tall enough to display even a tiny |
445 // thumb. The user can only use the mousewheel, scroll buttons or keyboard | 284 // thumb. The user can only use the mousewheel, scroll buttons or keyboard |
446 // in this scenario. | 285 // in this scenario. |
447 if ((IsHorizontal() && (track_bounds.width() < thumb_prefsize.width()) || | 286 if ((IsHorizontal() && (track_bounds.width() < thumb_prefsize.width()) || |
448 (!IsHorizontal() && (track_bounds.height() < thumb_prefsize.height())))) { | 287 (!IsHorizontal() && (track_bounds.height() < thumb_prefsize.height())))) { |
449 thumb_->SetVisible(false); | 288 thumb->SetVisible(false); |
450 } else if (!thumb_->IsVisible()) { | 289 } else if (!thumb->IsVisible()) { |
451 thumb_->SetVisible(true); | 290 thumb->SetVisible(true); |
452 } | 291 } |
453 } | 292 } |
454 | 293 |
455 bool BitmapScrollBar::OnMousePressed(const MouseEvent& event) { | |
456 if (event.IsOnlyLeftMouseButton()) { | |
457 SetThumbTrackState(CustomButton::BS_PUSHED); | |
458 gfx::Rect thumb_bounds = thumb_->bounds(); | |
459 if (IsHorizontal()) { | |
460 if (event.x() < thumb_bounds.x()) { | |
461 last_scroll_amount_ = SCROLL_PREV_PAGE; | |
462 } else if (event.x() > thumb_bounds.right()) { | |
463 last_scroll_amount_ = SCROLL_NEXT_PAGE; | |
464 } | |
465 } else { | |
466 if (event.y() < thumb_bounds.y()) { | |
467 last_scroll_amount_ = SCROLL_PREV_PAGE; | |
468 } else if (event.y() > thumb_bounds.bottom()) { | |
469 last_scroll_amount_ = SCROLL_NEXT_PAGE; | |
470 } | |
471 } | |
472 TrackClicked(); | |
473 repeater_.Start(); | |
474 } | |
475 return true; | |
476 } | |
477 | |
478 void BitmapScrollBar::OnMouseReleased(const MouseEvent& event) { | |
479 OnMouseCaptureLost(); | |
480 } | |
481 | |
482 void BitmapScrollBar::OnMouseCaptureLost() { | |
483 SetThumbTrackState(CustomButton::BS_NORMAL); | |
484 repeater_.Stop(); | |
485 } | |
486 | |
487 bool BitmapScrollBar::OnKeyPressed(const KeyEvent& event) { | |
488 ScrollAmount amount = SCROLL_NONE; | |
489 switch (event.key_code()) { | |
490 case ui::VKEY_UP: | |
491 if (!IsHorizontal()) | |
492 amount = SCROLL_PREV_LINE; | |
493 break; | |
494 case ui::VKEY_DOWN: | |
495 if (!IsHorizontal()) | |
496 amount = SCROLL_NEXT_LINE; | |
497 break; | |
498 case ui::VKEY_LEFT: | |
499 if (IsHorizontal()) | |
500 amount = SCROLL_PREV_LINE; | |
501 break; | |
502 case ui::VKEY_RIGHT: | |
503 if (IsHorizontal()) | |
504 amount = SCROLL_NEXT_LINE; | |
505 break; | |
506 case ui::VKEY_PRIOR: | |
507 amount = SCROLL_PREV_PAGE; | |
508 break; | |
509 case ui::VKEY_NEXT: | |
510 amount = SCROLL_NEXT_PAGE; | |
511 break; | |
512 case ui::VKEY_HOME: | |
513 amount = SCROLL_START; | |
514 break; | |
515 case ui::VKEY_END: | |
516 amount = SCROLL_END; | |
517 break; | |
518 } | |
519 if (amount != SCROLL_NONE) { | |
520 ScrollByAmount(amount); | |
521 return true; | |
522 } | |
523 return false; | |
524 } | |
525 | |
526 bool BitmapScrollBar::OnMouseWheel(const MouseWheelEvent& event) { | |
527 ScrollByContentsOffset(event.offset()); | |
528 return true; | |
529 } | |
530 | |
531 /////////////////////////////////////////////////////////////////////////////// | |
532 // BitmapScrollBar, ContextMenuController implementation: | |
533 | |
534 enum ScrollBarContextMenuCommands { | |
535 ScrollBarContextMenuCommand_ScrollHere = 1, | |
536 ScrollBarContextMenuCommand_ScrollStart, | |
537 ScrollBarContextMenuCommand_ScrollEnd, | |
538 ScrollBarContextMenuCommand_ScrollPageUp, | |
539 ScrollBarContextMenuCommand_ScrollPageDown, | |
540 ScrollBarContextMenuCommand_ScrollPrev, | |
541 ScrollBarContextMenuCommand_ScrollNext | |
542 }; | |
543 | |
544 void BitmapScrollBar::ShowContextMenuForView(View* source, | |
545 const gfx::Point& p, | |
546 bool is_mouse_gesture) { | |
547 Widget* widget = GetWidget(); | |
548 gfx::Rect widget_bounds = widget->GetWindowScreenBounds(); | |
549 gfx::Point temp_pt(p.x() - widget_bounds.x(), p.y() - widget_bounds.y()); | |
550 View::ConvertPointFromWidget(this, &temp_pt); | |
551 context_menu_mouse_position_ = IsHorizontal() ? temp_pt.x() : temp_pt.y(); | |
552 | |
553 scoped_ptr<Menu> menu( | |
554 Menu::Create(this, Menu::TOPLEFT, GetWidget()->GetNativeView())); | |
555 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollHere); | |
556 menu->AppendSeparator(); | |
557 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollStart); | |
558 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollEnd); | |
559 menu->AppendSeparator(); | |
560 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPageUp); | |
561 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPageDown); | |
562 menu->AppendSeparator(); | |
563 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPrev); | |
564 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollNext); | |
565 menu->RunMenuAt(p.x(), p.y()); | |
566 } | |
567 | |
568 /////////////////////////////////////////////////////////////////////////////// | |
569 // BitmapScrollBar, Menu::Delegate implementation: | |
570 | |
571 std::wstring BitmapScrollBar::GetLabel(int id) const { | |
572 int ids_value = 0; | |
573 switch (id) { | |
574 case ScrollBarContextMenuCommand_ScrollHere: | |
575 ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLHERE; | |
576 break; | |
577 case ScrollBarContextMenuCommand_ScrollStart: | |
578 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFTEDGE | |
579 : IDS_APP_SCROLLBAR_CXMENU_SCROLLHOME; | |
580 break; | |
581 case ScrollBarContextMenuCommand_ScrollEnd: | |
582 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHTEDGE | |
583 : IDS_APP_SCROLLBAR_CXMENU_SCROLLEND; | |
584 break; | |
585 case ScrollBarContextMenuCommand_ScrollPageUp: | |
586 ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLPAGEUP; | |
587 break; | |
588 case ScrollBarContextMenuCommand_ScrollPageDown: | |
589 ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLPAGEDOWN; | |
590 break; | |
591 case ScrollBarContextMenuCommand_ScrollPrev: | |
592 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFT | |
593 : IDS_APP_SCROLLBAR_CXMENU_SCROLLUP; | |
594 break; | |
595 case ScrollBarContextMenuCommand_ScrollNext: | |
596 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHT | |
597 : IDS_APP_SCROLLBAR_CXMENU_SCROLLDOWN; | |
598 break; | |
599 default: | |
600 NOTREACHED() << "Invalid BitmapScrollBar Context Menu command!"; | |
601 } | |
602 | |
603 return ids_value ? UTF16ToWide(l10n_util::GetStringUTF16(ids_value)) : L""; | |
604 } | |
605 | |
606 bool BitmapScrollBar::IsCommandEnabled(int id) const { | |
607 switch (id) { | |
608 case ScrollBarContextMenuCommand_ScrollPageUp: | |
609 case ScrollBarContextMenuCommand_ScrollPageDown: | |
610 return !IsHorizontal(); | |
611 } | |
612 return true; | |
613 } | |
614 | |
615 void BitmapScrollBar::ExecuteCommand(int id) { | |
616 switch (id) { | |
617 case ScrollBarContextMenuCommand_ScrollHere: | |
618 ScrollToThumbPosition(context_menu_mouse_position_, true); | |
619 break; | |
620 case ScrollBarContextMenuCommand_ScrollStart: | |
621 ScrollByAmount(SCROLL_START); | |
622 break; | |
623 case ScrollBarContextMenuCommand_ScrollEnd: | |
624 ScrollByAmount(SCROLL_END); | |
625 break; | |
626 case ScrollBarContextMenuCommand_ScrollPageUp: | |
627 ScrollByAmount(SCROLL_PREV_PAGE); | |
628 break; | |
629 case ScrollBarContextMenuCommand_ScrollPageDown: | |
630 ScrollByAmount(SCROLL_NEXT_PAGE); | |
631 break; | |
632 case ScrollBarContextMenuCommand_ScrollPrev: | |
633 ScrollByAmount(SCROLL_PREV_LINE); | |
634 break; | |
635 case ScrollBarContextMenuCommand_ScrollNext: | |
636 ScrollByAmount(SCROLL_NEXT_LINE); | |
637 break; | |
638 } | |
639 } | |
640 | |
641 /////////////////////////////////////////////////////////////////////////////// | |
642 // BitmapScrollBar, ButtonListener implementation: | |
643 | |
644 void BitmapScrollBar::ButtonPressed(Button* sender, const views::Event& event) { | |
645 if (sender == prev_button_) { | |
646 ScrollByAmount(SCROLL_PREV_LINE); | |
647 } else if (sender == next_button_) { | |
648 ScrollByAmount(SCROLL_NEXT_LINE); | |
649 } | |
650 } | |
651 | |
652 /////////////////////////////////////////////////////////////////////////////// | |
653 // BitmapScrollBar, ScrollBar implementation: | |
654 | |
655 void BitmapScrollBar::Update(int viewport_size, int content_size, | |
656 int contents_scroll_offset) { | |
657 ScrollBar::Update(viewport_size, content_size, contents_scroll_offset); | |
658 | |
659 // Make sure contents_size is always > 0 to avoid divide by zero errors in | |
660 // calculations throughout this code. | |
661 contents_size_ = std::max(1, content_size); | |
662 | |
663 if (content_size < 0) | |
664 content_size = 0; | |
665 if (contents_scroll_offset < 0) | |
666 contents_scroll_offset = 0; | |
667 if (contents_scroll_offset > content_size) | |
668 contents_scroll_offset = content_size; | |
669 | |
670 // Thumb Height and Thumb Pos. | |
671 // The height of the thumb is the ratio of the Viewport height to the | |
672 // content size multiplied by the height of the thumb track. | |
673 double ratio = static_cast<double>(viewport_size) / contents_size_; | |
674 int thumb_size = static_cast<int>(ratio * GetTrackSize()); | |
675 thumb_->SetSize(thumb_size); | |
676 | |
677 int thumb_position = CalculateThumbPosition(contents_scroll_offset); | |
678 thumb_->SetPosition(thumb_position); | |
679 } | |
680 | |
681 int BitmapScrollBar::GetLayoutSize() const { | |
682 gfx::Size prefsize = prev_button_->GetPreferredSize(); | |
683 return IsHorizontal() ? prefsize.height() : prefsize.width(); | |
684 } | |
685 | |
686 int BitmapScrollBar::GetPosition() const { | |
687 return thumb_->GetPosition(); | |
688 } | |
689 | |
690 /////////////////////////////////////////////////////////////////////////////// | 294 /////////////////////////////////////////////////////////////////////////////// |
691 // BitmapScrollBar, View implementation: | 295 // BitmapScrollBar, View implementation: |
692 | 296 |
693 void BitmapScrollBar::OnPaint(gfx::Canvas* canvas) { | 297 void BitmapScrollBar::OnPaint(gfx::Canvas* canvas) { |
694 // Paint the track. | 298 // Paint the track. |
695 gfx::Rect track_bounds = GetTrackBounds(); | 299 gfx::Rect track_bounds = GetTrackBounds(); |
696 canvas->TileImageInt(*images_[THUMB_TRACK][thumb_track_state_], | 300 canvas->TileImageInt(*images_[THUMB_TRACK][thumb_track_state_], |
697 track_bounds.x(), track_bounds.y(), | 301 track_bounds.x(), track_bounds.y(), |
698 track_bounds.width(), track_bounds.height()); | 302 track_bounds.width(), track_bounds.height()); |
699 } | 303 } |
700 | 304 |
701 /////////////////////////////////////////////////////////////////////////////// | 305 /////////////////////////////////////////////////////////////////////////////// |
702 // BitmapScrollBar, private: | 306 // BaseScrollBar, ButtonListener implementation: |
703 | 307 |
704 void BitmapScrollBar::TrackClicked() { | 308 void BaseScrollBar::ButtonPressed(Button* sender, const views::Event& event) { |
705 if (last_scroll_amount_ != SCROLL_NONE) | 309 if (sender == prev_button_) { |
706 ScrollByAmount(last_scroll_amount_); | 310 ScrollByAmount(SCROLL_PREV_LINE); |
707 } | 311 } else if (sender == next_button_) { |
708 | 312 ScrollByAmount(SCROLL_NEXT_LINE); |
709 void BitmapScrollBar::ScrollContentsToOffset() { | 313 } |
710 GetController()->ScrollToPosition(this, contents_scroll_offset_); | |
711 thumb_->SetPosition(CalculateThumbPosition(contents_scroll_offset_)); | |
712 } | |
713 | |
714 int BitmapScrollBar::GetTrackSize() const { | |
715 gfx::Rect track_bounds = GetTrackBounds(); | |
716 return IsHorizontal() ? track_bounds.width() : track_bounds.height(); | |
717 } | |
718 | |
719 int BitmapScrollBar::CalculateThumbPosition(int contents_scroll_offset) const { | |
720 return (contents_scroll_offset * GetTrackSize()) / contents_size_; | |
721 } | |
722 | |
723 int BitmapScrollBar::CalculateContentsOffset(int thumb_position, | |
724 bool scroll_to_middle) const { | |
725 if (scroll_to_middle) | |
726 thumb_position = thumb_position - (thumb_->GetSize() / 2); | |
727 return (thumb_position * contents_size_) / GetTrackSize(); | |
728 } | |
729 | |
730 void BitmapScrollBar::SetThumbTrackState(CustomButton::ButtonState state) { | |
731 thumb_track_state_ = state; | |
732 SchedulePaint(); | |
733 } | 314 } |
734 | 315 |
735 } // namespace views | 316 } // namespace views |
OLD | NEW |