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

Side by Side Diff: views/controls/scrollbar/base_scroll_bar.cc

Issue 7669028: Adding a Views scrollbar implementation. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Refactored the bitmap code to be shared with the native_scroll_bar_views Created 9 years, 4 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
Ben Goodger (Google) 2011/08/23 16:05:15 Is this code identical to BitmapScrollBar with the
4
5 #include "views/controls/scrollbar/base_scroll_bar.h"
6
7 #if defined(OS_LINUX)
8 #include "ui/gfx/screen.h"
9 #endif
10
11 #include "base/callback.h"
12 #include "base/compiler_specific.h"
13 #include "base/message_loop.h"
14 #include "base/string16.h"
15 #include "base/utf_string_conversions.h"
16 #include "grit/ui_strings.h"
17 #include "ui/base/keycodes/keyboard_codes.h"
18 #include "ui/base/l10n/l10n_util.h"
19 #include "ui/gfx/canvas.h"
20 #include "views/controls/menu/menu.h"
21 #include "views/controls/scrollbar/base_scroll_bar_thumb.h"
22 #include "views/controls/scroll_view.h"
23 #include "views/widget/widget.h"
24
25 #undef min
26 #undef max
27
28 namespace views {
29
30 ///////////////////////////////////////////////////////////////////////////////
31 // BaseScrollBar, public:
32
33 BaseScrollBar::BaseScrollBar(bool horizontal, BaseScrollBarThumb* thumb)
34 : ScrollBar(horizontal),
35 thumb_(thumb),
36 contents_size_(0),
37 contents_scroll_offset_(0),
38 thumb_track_state_(CustomButton::BS_NORMAL),
39 last_scroll_amount_(SCROLL_NONE),
40 ALLOW_THIS_IN_INITIALIZER_LIST(repeater_(
41 NewCallback<BaseScrollBar>(this,
42 &BaseScrollBar::TrackClicked))),
43 context_menu_mouse_position_(0) {
44
45 AddChildView(thumb_);
46
47 set_context_menu_controller(this);
48 thumb_->set_context_menu_controller(this);
49 }
50
51 void BaseScrollBar::ScrollByAmount(ScrollAmount amount) {
52 int offset = contents_scroll_offset_;
53 switch (amount) {
54 case SCROLL_START:
55 offset = GetMinPosition();
56 break;
57 case SCROLL_END:
58 offset = GetMaxPosition();
59 break;
60 case SCROLL_PREV_LINE:
61 offset -= GetScrollIncrement(false, false);
62 offset = std::max(GetMinPosition(), offset);
63 break;
64 case SCROLL_NEXT_LINE:
65 offset += GetScrollIncrement(false, true);
66 offset = std::min(GetMaxPosition(), offset);
67 break;
68 case SCROLL_PREV_PAGE:
69 offset -= GetScrollIncrement(true, false);
70 offset = std::max(GetMinPosition(), offset);
71 break;
72 case SCROLL_NEXT_PAGE:
73 offset += GetScrollIncrement(true, true);
74 offset = std::min(GetMaxPosition(), offset);
75 break;
76 default:
77 break;
78 }
79 contents_scroll_offset_ = offset;
80 ScrollContentsToOffset();
81 }
82
83 void BaseScrollBar::ScrollToThumbPosition(int thumb_position,
84 bool scroll_to_middle) {
85 contents_scroll_offset_ =
86 CalculateContentsOffset(thumb_position, scroll_to_middle);
87 if (contents_scroll_offset_ < GetMinPosition()) {
88 contents_scroll_offset_ = GetMinPosition();
89 } else if (contents_scroll_offset_ > GetMaxPosition()) {
90 contents_scroll_offset_ = GetMaxPosition();
91 }
92 ScrollContentsToOffset();
93 SchedulePaint();
94 }
95
96 void BaseScrollBar::ScrollByContentsOffset(int contents_offset) {
97 contents_scroll_offset_ -= contents_offset;
98 if (contents_scroll_offset_ < GetMinPosition()) {
99 contents_scroll_offset_ = GetMinPosition();
100 } else if (contents_scroll_offset_ > GetMaxPosition()) {
101 contents_scroll_offset_ = GetMaxPosition();
102 }
103 ScrollContentsToOffset();
104 }
105
106 ///////////////////////////////////////////////////////////////////////////////
107 // BaseScrollBar, View implementation:
108
109 bool BaseScrollBar::OnMousePressed(const MouseEvent& event) {
110 if (event.IsOnlyLeftMouseButton()) {
111 SetThumbTrackState(CustomButton::BS_PUSHED);
112 gfx::Rect thumb_bounds = thumb_->bounds();
113 if (IsHorizontal()) {
114 if (event.x() < thumb_bounds.x()) {
115 last_scroll_amount_ = SCROLL_PREV_PAGE;
116 } else if (event.x() > thumb_bounds.right()) {
117 last_scroll_amount_ = SCROLL_NEXT_PAGE;
118 }
119 } else {
120 if (event.y() < thumb_bounds.y()) {
121 last_scroll_amount_ = SCROLL_PREV_PAGE;
122 } else if (event.y() > thumb_bounds.bottom()) {
123 last_scroll_amount_ = SCROLL_NEXT_PAGE;
124 }
125 }
126 TrackClicked();
127 repeater_.Start();
128 }
129 return true;
130 }
131
132 void BaseScrollBar::OnMouseReleased(const MouseEvent& event) {
133 OnMouseCaptureLost();
134 }
135
136 void BaseScrollBar::OnMouseCaptureLost() {
137 SetThumbTrackState(CustomButton::BS_NORMAL);
138 repeater_.Stop();
139 }
140
141 bool BaseScrollBar::OnKeyPressed(const KeyEvent& event) {
142 ScrollAmount amount = SCROLL_NONE;
143 switch (event.key_code()) {
144 case ui::VKEY_UP:
145 if (!IsHorizontal())
146 amount = SCROLL_PREV_LINE;
147 break;
148 case ui::VKEY_DOWN:
149 if (!IsHorizontal())
150 amount = SCROLL_NEXT_LINE;
151 break;
152 case ui::VKEY_LEFT:
153 if (IsHorizontal())
154 amount = SCROLL_PREV_LINE;
155 break;
156 case ui::VKEY_RIGHT:
157 if (IsHorizontal())
158 amount = SCROLL_NEXT_LINE;
159 break;
160 case ui::VKEY_PRIOR:
161 amount = SCROLL_PREV_PAGE;
162 break;
163 case ui::VKEY_NEXT:
164 amount = SCROLL_NEXT_PAGE;
165 break;
166 case ui::VKEY_HOME:
167 amount = SCROLL_START;
168 break;
169 case ui::VKEY_END:
170 amount = SCROLL_END;
171 break;
172 default:
173 break;
174 }
175 if (amount != SCROLL_NONE) {
176 ScrollByAmount(amount);
177 return true;
178 }
179 return false;
180 }
181
182 bool BaseScrollBar::OnMouseWheel(const MouseWheelEvent& event) {
183 ScrollByContentsOffset(event.offset());
184 return true;
185 }
186
187 ///////////////////////////////////////////////////////////////////////////////
188 // BaseScrollBar, ContextMenuController implementation:
189
190 enum ScrollBarContextMenuCommands {
191 ScrollBarContextMenuCommand_ScrollHere = 1,
192 ScrollBarContextMenuCommand_ScrollStart,
193 ScrollBarContextMenuCommand_ScrollEnd,
194 ScrollBarContextMenuCommand_ScrollPageUp,
195 ScrollBarContextMenuCommand_ScrollPageDown,
196 ScrollBarContextMenuCommand_ScrollPrev,
197 ScrollBarContextMenuCommand_ScrollNext
198 };
199
200 void BaseScrollBar::ShowContextMenuForView(View* source,
201 const gfx::Point& p,
202 bool is_mouse_gesture) {
203 Widget* widget = GetWidget();
204 gfx::Rect widget_bounds = widget->GetWindowScreenBounds();
205 gfx::Point temp_pt(p.x() - widget_bounds.x(), p.y() - widget_bounds.y());
206 View::ConvertPointFromWidget(this, &temp_pt);
207 context_menu_mouse_position_ = IsHorizontal() ? temp_pt.x() : temp_pt.y();
208
209 scoped_ptr<Menu> menu(
210 Menu::Create(this, Menu::TOPLEFT, GetWidget()->GetNativeView()));
211 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollHere);
212 menu->AppendSeparator();
213 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollStart);
214 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollEnd);
215 menu->AppendSeparator();
216 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPageUp);
217 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPageDown);
218 menu->AppendSeparator();
219 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPrev);
220 menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollNext);
221 menu->RunMenuAt(p.x(), p.y());
222 }
223
224 ///////////////////////////////////////////////////////////////////////////////
225 // BaseScrollBar, Menu::Delegate implementation:
226
227 std::wstring BaseScrollBar::GetLabel(int id) const {
228 int ids_value = 0;
229 switch (id) {
230 case ScrollBarContextMenuCommand_ScrollHere:
231 ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLHERE;
232 break;
233 case ScrollBarContextMenuCommand_ScrollStart:
234 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFTEDGE
235 : IDS_APP_SCROLLBAR_CXMENU_SCROLLHOME;
236 break;
237 case ScrollBarContextMenuCommand_ScrollEnd:
238 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHTEDGE
239 : IDS_APP_SCROLLBAR_CXMENU_SCROLLEND;
240 break;
241 case ScrollBarContextMenuCommand_ScrollPageUp:
242 ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLPAGEUP;
243 break;
244 case ScrollBarContextMenuCommand_ScrollPageDown:
245 ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLPAGEDOWN;
246 break;
247 case ScrollBarContextMenuCommand_ScrollPrev:
248 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFT
249 : IDS_APP_SCROLLBAR_CXMENU_SCROLLUP;
250 break;
251 case ScrollBarContextMenuCommand_ScrollNext:
252 ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHT
253 : IDS_APP_SCROLLBAR_CXMENU_SCROLLDOWN;
254 break;
255 default:
256 NOTREACHED() << "Invalid BaseScrollBar Context Menu command!";
257 }
258
259 return ids_value ? UTF16ToWide(l10n_util::GetStringUTF16(ids_value)) : L"";
260 }
261
262 bool BaseScrollBar::IsCommandEnabled(int id) const {
263 switch (id) {
264 case ScrollBarContextMenuCommand_ScrollPageUp:
265 case ScrollBarContextMenuCommand_ScrollPageDown:
266 return !IsHorizontal();
267 }
268 return true;
269 }
270
271 void BaseScrollBar::ExecuteCommand(int id) {
272 switch (id) {
273 case ScrollBarContextMenuCommand_ScrollHere:
274 ScrollToThumbPosition(context_menu_mouse_position_, true);
275 break;
276 case ScrollBarContextMenuCommand_ScrollStart:
277 ScrollByAmount(SCROLL_START);
278 break;
279 case ScrollBarContextMenuCommand_ScrollEnd:
280 ScrollByAmount(SCROLL_END);
281 break;
282 case ScrollBarContextMenuCommand_ScrollPageUp:
283 ScrollByAmount(SCROLL_PREV_PAGE);
284 break;
285 case ScrollBarContextMenuCommand_ScrollPageDown:
286 ScrollByAmount(SCROLL_NEXT_PAGE);
287 break;
288 case ScrollBarContextMenuCommand_ScrollPrev:
289 ScrollByAmount(SCROLL_PREV_LINE);
290 break;
291 case ScrollBarContextMenuCommand_ScrollNext:
292 ScrollByAmount(SCROLL_NEXT_LINE);
293 break;
294 }
295 }
296
297 ///////////////////////////////////////////////////////////////////////////////
298 // BaseScrollBar, ScrollBar implementation:
299
300 void BaseScrollBar::Update(int viewport_size, int content_size,
301 int contents_scroll_offset) {
302 ScrollBar::Update(viewport_size, content_size, contents_scroll_offset);
303
304 // Make sure contents_size is always > 0 to avoid divide by zero errors in
305 // calculations throughout this code.
306 contents_size_ = std::max(1, content_size);
307
308 if (content_size < 0)
309 content_size = 0;
310 if (contents_scroll_offset < 0)
311 contents_scroll_offset = 0;
312 if (contents_scroll_offset > content_size)
313 contents_scroll_offset = content_size;
314
315 // Thumb Height and Thumb Pos.
316 // The height of the thumb is the ratio of the Viewport height to the
317 // content size multiplied by the height of the thumb track.
318 double ratio = static_cast<double>(viewport_size) / contents_size_;
319 int thumb_size = static_cast<int>(ratio * GetTrackSize());
320 thumb_->SetSize(thumb_size);
321
322 int thumb_position = CalculateThumbPosition(contents_scroll_offset);
323 thumb_->SetPosition(thumb_position);
324 }
325
326 int BaseScrollBar::GetPosition() const {
327 return thumb_->GetPosition();
328 }
329
330 ///////////////////////////////////////////////////////////////////////////////
331 // BaseScrollBar, protected:
332
333 BaseScrollBarThumb* BaseScrollBar::GetThumb() const {
334 return thumb_;
335 }
336
337 void BaseScrollBar::ScrollToPosition(int position) {
338 GetController()->ScrollToPosition(this, position);
339 }
340
341 int BaseScrollBar::GetScrollIncrement(bool is_page, bool is_positive) {
342 return GetController()->GetScrollIncrement(this, is_page, is_positive);
343 }
344
345
346 ///////////////////////////////////////////////////////////////////////////////
347 // BaseScrollBar, private:
348
349 void BaseScrollBar::TrackClicked() {
350 if (last_scroll_amount_ != SCROLL_NONE)
351 ScrollByAmount(last_scroll_amount_);
352 }
353
354 void BaseScrollBar::ScrollContentsToOffset() {
355 ScrollToPosition(contents_scroll_offset_);
356 thumb_->SetPosition(CalculateThumbPosition(contents_scroll_offset_));
357 }
358
359 int BaseScrollBar::GetTrackSize() const {
360 gfx::Rect track_bounds = GetTrackBounds();
361 return IsHorizontal() ? track_bounds.width() : track_bounds.height();
362 }
363
364 int BaseScrollBar::CalculateThumbPosition(int contents_scroll_offset) const {
365 return (contents_scroll_offset * GetTrackSize()) / contents_size_;
366 }
367
368 int BaseScrollBar::CalculateContentsOffset(int thumb_position,
369 bool scroll_to_middle) const {
370 if (scroll_to_middle)
371 thumb_position = thumb_position - (thumb_->GetSize() / 2);
372 return (thumb_position * contents_size_) / GetTrackSize();
373 }
374
375 void BaseScrollBar::SetThumbTrackState(CustomButton::ButtonState state) {
376 thumb_track_state_ = state;
377 SchedulePaint();
378 }
379
380 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698