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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: views/controls/scrollbar/base_scroll_bar.cc
diff --git a/views/controls/scrollbar/base_scroll_bar.cc b/views/controls/scrollbar/base_scroll_bar.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f0a125fc51c0e960956863609f0dcf85c59cc294
--- /dev/null
+++ b/views/controls/scrollbar/base_scroll_bar.cc
@@ -0,0 +1,380 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
Ben Goodger (Google) 2011/08/23 16:05:15 Is this code identical to BitmapScrollBar with the
+
+#include "views/controls/scrollbar/base_scroll_bar.h"
+
+#if defined(OS_LINUX)
+#include "ui/gfx/screen.h"
+#endif
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/message_loop.h"
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
+#include "grit/ui_strings.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/canvas.h"
+#include "views/controls/menu/menu.h"
+#include "views/controls/scrollbar/base_scroll_bar_thumb.h"
+#include "views/controls/scroll_view.h"
+#include "views/widget/widget.h"
+
+#undef min
+#undef max
+
+namespace views {
+
+///////////////////////////////////////////////////////////////////////////////
+// BaseScrollBar, public:
+
+BaseScrollBar::BaseScrollBar(bool horizontal, BaseScrollBarThumb* thumb)
+ : ScrollBar(horizontal),
+ thumb_(thumb),
+ contents_size_(0),
+ contents_scroll_offset_(0),
+ thumb_track_state_(CustomButton::BS_NORMAL),
+ last_scroll_amount_(SCROLL_NONE),
+ ALLOW_THIS_IN_INITIALIZER_LIST(repeater_(
+ NewCallback<BaseScrollBar>(this,
+ &BaseScrollBar::TrackClicked))),
+ context_menu_mouse_position_(0) {
+
+ AddChildView(thumb_);
+
+ set_context_menu_controller(this);
+ thumb_->set_context_menu_controller(this);
+}
+
+void BaseScrollBar::ScrollByAmount(ScrollAmount amount) {
+ int offset = contents_scroll_offset_;
+ switch (amount) {
+ case SCROLL_START:
+ offset = GetMinPosition();
+ break;
+ case SCROLL_END:
+ offset = GetMaxPosition();
+ break;
+ case SCROLL_PREV_LINE:
+ offset -= GetScrollIncrement(false, false);
+ offset = std::max(GetMinPosition(), offset);
+ break;
+ case SCROLL_NEXT_LINE:
+ offset += GetScrollIncrement(false, true);
+ offset = std::min(GetMaxPosition(), offset);
+ break;
+ case SCROLL_PREV_PAGE:
+ offset -= GetScrollIncrement(true, false);
+ offset = std::max(GetMinPosition(), offset);
+ break;
+ case SCROLL_NEXT_PAGE:
+ offset += GetScrollIncrement(true, true);
+ offset = std::min(GetMaxPosition(), offset);
+ break;
+ default:
+ break;
+ }
+ contents_scroll_offset_ = offset;
+ ScrollContentsToOffset();
+}
+
+void BaseScrollBar::ScrollToThumbPosition(int thumb_position,
+ bool scroll_to_middle) {
+ contents_scroll_offset_ =
+ CalculateContentsOffset(thumb_position, scroll_to_middle);
+ if (contents_scroll_offset_ < GetMinPosition()) {
+ contents_scroll_offset_ = GetMinPosition();
+ } else if (contents_scroll_offset_ > GetMaxPosition()) {
+ contents_scroll_offset_ = GetMaxPosition();
+ }
+ ScrollContentsToOffset();
+ SchedulePaint();
+}
+
+void BaseScrollBar::ScrollByContentsOffset(int contents_offset) {
+ contents_scroll_offset_ -= contents_offset;
+ if (contents_scroll_offset_ < GetMinPosition()) {
+ contents_scroll_offset_ = GetMinPosition();
+ } else if (contents_scroll_offset_ > GetMaxPosition()) {
+ contents_scroll_offset_ = GetMaxPosition();
+ }
+ ScrollContentsToOffset();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BaseScrollBar, View implementation:
+
+bool BaseScrollBar::OnMousePressed(const MouseEvent& event) {
+ if (event.IsOnlyLeftMouseButton()) {
+ SetThumbTrackState(CustomButton::BS_PUSHED);
+ gfx::Rect thumb_bounds = thumb_->bounds();
+ if (IsHorizontal()) {
+ if (event.x() < thumb_bounds.x()) {
+ last_scroll_amount_ = SCROLL_PREV_PAGE;
+ } else if (event.x() > thumb_bounds.right()) {
+ last_scroll_amount_ = SCROLL_NEXT_PAGE;
+ }
+ } else {
+ if (event.y() < thumb_bounds.y()) {
+ last_scroll_amount_ = SCROLL_PREV_PAGE;
+ } else if (event.y() > thumb_bounds.bottom()) {
+ last_scroll_amount_ = SCROLL_NEXT_PAGE;
+ }
+ }
+ TrackClicked();
+ repeater_.Start();
+ }
+ return true;
+}
+
+void BaseScrollBar::OnMouseReleased(const MouseEvent& event) {
+ OnMouseCaptureLost();
+}
+
+void BaseScrollBar::OnMouseCaptureLost() {
+ SetThumbTrackState(CustomButton::BS_NORMAL);
+ repeater_.Stop();
+}
+
+bool BaseScrollBar::OnKeyPressed(const KeyEvent& event) {
+ ScrollAmount amount = SCROLL_NONE;
+ switch (event.key_code()) {
+ case ui::VKEY_UP:
+ if (!IsHorizontal())
+ amount = SCROLL_PREV_LINE;
+ break;
+ case ui::VKEY_DOWN:
+ if (!IsHorizontal())
+ amount = SCROLL_NEXT_LINE;
+ break;
+ case ui::VKEY_LEFT:
+ if (IsHorizontal())
+ amount = SCROLL_PREV_LINE;
+ break;
+ case ui::VKEY_RIGHT:
+ if (IsHorizontal())
+ amount = SCROLL_NEXT_LINE;
+ break;
+ case ui::VKEY_PRIOR:
+ amount = SCROLL_PREV_PAGE;
+ break;
+ case ui::VKEY_NEXT:
+ amount = SCROLL_NEXT_PAGE;
+ break;
+ case ui::VKEY_HOME:
+ amount = SCROLL_START;
+ break;
+ case ui::VKEY_END:
+ amount = SCROLL_END;
+ break;
+ default:
+ break;
+ }
+ if (amount != SCROLL_NONE) {
+ ScrollByAmount(amount);
+ return true;
+ }
+ return false;
+}
+
+bool BaseScrollBar::OnMouseWheel(const MouseWheelEvent& event) {
+ ScrollByContentsOffset(event.offset());
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BaseScrollBar, ContextMenuController implementation:
+
+enum ScrollBarContextMenuCommands {
+ ScrollBarContextMenuCommand_ScrollHere = 1,
+ ScrollBarContextMenuCommand_ScrollStart,
+ ScrollBarContextMenuCommand_ScrollEnd,
+ ScrollBarContextMenuCommand_ScrollPageUp,
+ ScrollBarContextMenuCommand_ScrollPageDown,
+ ScrollBarContextMenuCommand_ScrollPrev,
+ ScrollBarContextMenuCommand_ScrollNext
+};
+
+void BaseScrollBar::ShowContextMenuForView(View* source,
+ const gfx::Point& p,
+ bool is_mouse_gesture) {
+ Widget* widget = GetWidget();
+ gfx::Rect widget_bounds = widget->GetWindowScreenBounds();
+ gfx::Point temp_pt(p.x() - widget_bounds.x(), p.y() - widget_bounds.y());
+ View::ConvertPointFromWidget(this, &temp_pt);
+ context_menu_mouse_position_ = IsHorizontal() ? temp_pt.x() : temp_pt.y();
+
+ scoped_ptr<Menu> menu(
+ Menu::Create(this, Menu::TOPLEFT, GetWidget()->GetNativeView()));
+ menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollHere);
+ menu->AppendSeparator();
+ menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollStart);
+ menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollEnd);
+ menu->AppendSeparator();
+ menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPageUp);
+ menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPageDown);
+ menu->AppendSeparator();
+ menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPrev);
+ menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollNext);
+ menu->RunMenuAt(p.x(), p.y());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BaseScrollBar, Menu::Delegate implementation:
+
+std::wstring BaseScrollBar::GetLabel(int id) const {
+ int ids_value = 0;
+ switch (id) {
+ case ScrollBarContextMenuCommand_ScrollHere:
+ ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLHERE;
+ break;
+ case ScrollBarContextMenuCommand_ScrollStart:
+ ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFTEDGE
+ : IDS_APP_SCROLLBAR_CXMENU_SCROLLHOME;
+ break;
+ case ScrollBarContextMenuCommand_ScrollEnd:
+ ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHTEDGE
+ : IDS_APP_SCROLLBAR_CXMENU_SCROLLEND;
+ break;
+ case ScrollBarContextMenuCommand_ScrollPageUp:
+ ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLPAGEUP;
+ break;
+ case ScrollBarContextMenuCommand_ScrollPageDown:
+ ids_value = IDS_APP_SCROLLBAR_CXMENU_SCROLLPAGEDOWN;
+ break;
+ case ScrollBarContextMenuCommand_ScrollPrev:
+ ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLLEFT
+ : IDS_APP_SCROLLBAR_CXMENU_SCROLLUP;
+ break;
+ case ScrollBarContextMenuCommand_ScrollNext:
+ ids_value = IsHorizontal() ? IDS_APP_SCROLLBAR_CXMENU_SCROLLRIGHT
+ : IDS_APP_SCROLLBAR_CXMENU_SCROLLDOWN;
+ break;
+ default:
+ NOTREACHED() << "Invalid BaseScrollBar Context Menu command!";
+ }
+
+ return ids_value ? UTF16ToWide(l10n_util::GetStringUTF16(ids_value)) : L"";
+}
+
+bool BaseScrollBar::IsCommandEnabled(int id) const {
+ switch (id) {
+ case ScrollBarContextMenuCommand_ScrollPageUp:
+ case ScrollBarContextMenuCommand_ScrollPageDown:
+ return !IsHorizontal();
+ }
+ return true;
+}
+
+void BaseScrollBar::ExecuteCommand(int id) {
+ switch (id) {
+ case ScrollBarContextMenuCommand_ScrollHere:
+ ScrollToThumbPosition(context_menu_mouse_position_, true);
+ break;
+ case ScrollBarContextMenuCommand_ScrollStart:
+ ScrollByAmount(SCROLL_START);
+ break;
+ case ScrollBarContextMenuCommand_ScrollEnd:
+ ScrollByAmount(SCROLL_END);
+ break;
+ case ScrollBarContextMenuCommand_ScrollPageUp:
+ ScrollByAmount(SCROLL_PREV_PAGE);
+ break;
+ case ScrollBarContextMenuCommand_ScrollPageDown:
+ ScrollByAmount(SCROLL_NEXT_PAGE);
+ break;
+ case ScrollBarContextMenuCommand_ScrollPrev:
+ ScrollByAmount(SCROLL_PREV_LINE);
+ break;
+ case ScrollBarContextMenuCommand_ScrollNext:
+ ScrollByAmount(SCROLL_NEXT_LINE);
+ break;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BaseScrollBar, ScrollBar implementation:
+
+void BaseScrollBar::Update(int viewport_size, int content_size,
+ int contents_scroll_offset) {
+ ScrollBar::Update(viewport_size, content_size, contents_scroll_offset);
+
+ // Make sure contents_size is always > 0 to avoid divide by zero errors in
+ // calculations throughout this code.
+ contents_size_ = std::max(1, content_size);
+
+ if (content_size < 0)
+ content_size = 0;
+ if (contents_scroll_offset < 0)
+ contents_scroll_offset = 0;
+ if (contents_scroll_offset > content_size)
+ contents_scroll_offset = content_size;
+
+ // Thumb Height and Thumb Pos.
+ // The height of the thumb is the ratio of the Viewport height to the
+ // content size multiplied by the height of the thumb track.
+ double ratio = static_cast<double>(viewport_size) / contents_size_;
+ int thumb_size = static_cast<int>(ratio * GetTrackSize());
+ thumb_->SetSize(thumb_size);
+
+ int thumb_position = CalculateThumbPosition(contents_scroll_offset);
+ thumb_->SetPosition(thumb_position);
+}
+
+int BaseScrollBar::GetPosition() const {
+ return thumb_->GetPosition();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BaseScrollBar, protected:
+
+BaseScrollBarThumb* BaseScrollBar::GetThumb() const {
+ return thumb_;
+}
+
+void BaseScrollBar::ScrollToPosition(int position) {
+ GetController()->ScrollToPosition(this, position);
+}
+
+int BaseScrollBar::GetScrollIncrement(bool is_page, bool is_positive) {
+ return GetController()->GetScrollIncrement(this, is_page, is_positive);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// BaseScrollBar, private:
+
+void BaseScrollBar::TrackClicked() {
+ if (last_scroll_amount_ != SCROLL_NONE)
+ ScrollByAmount(last_scroll_amount_);
+}
+
+void BaseScrollBar::ScrollContentsToOffset() {
+ ScrollToPosition(contents_scroll_offset_);
+ thumb_->SetPosition(CalculateThumbPosition(contents_scroll_offset_));
+}
+
+int BaseScrollBar::GetTrackSize() const {
+ gfx::Rect track_bounds = GetTrackBounds();
+ return IsHorizontal() ? track_bounds.width() : track_bounds.height();
+}
+
+int BaseScrollBar::CalculateThumbPosition(int contents_scroll_offset) const {
+ return (contents_scroll_offset * GetTrackSize()) / contents_size_;
+}
+
+int BaseScrollBar::CalculateContentsOffset(int thumb_position,
+ bool scroll_to_middle) const {
+ if (scroll_to_middle)
+ thumb_position = thumb_position - (thumb_->GetSize() / 2);
+ return (thumb_position * contents_size_) / GetTrackSize();
+}
+
+void BaseScrollBar::SetThumbTrackState(CustomButton::ButtonState state) {
+ thumb_track_state_ = state;
+ SchedulePaint();
+}
+
+} // namespace views

Powered by Google App Engine
This is Rietveld 408576698