summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-23 22:30:16 +0000
committeroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-23 22:30:16 +0000
commit34e32cf2dda2b1f4d5221749ddaac10690b8a63f (patch)
tree989cbf8baf6c21d21a0880b3a8d6ad7a12c3c985
parent42ecb863ac38c351dd79f4b49f501f4bbd667cac (diff)
downloadchromium_src-34e32cf2dda2b1f4d5221749ddaac10690b8a63f.zip
chromium_src-34e32cf2dda2b1f4d5221749ddaac10690b8a63f.tar.gz
chromium_src-34e32cf2dda2b1f4d5221749ddaac10690b8a63f.tar.bz2
Refactor window impl of scroll bar for future linux implementation.
- Changed NativeScrollBar to use native wrapper - Added NativeScrollBarWapper for NativeScrollBar to delegate operations to native control. - Moved window specific impl in NativeScrollBar to NativeScrollBarWin class which is a native wrapper. - Fixed a bug in native_control_win. need to call Layout when view visibility is changed after native contol is created. BUG=none TEST=none Review URL: http://codereview.chromium.org/214048 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27013 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--views/controls/native_control_win.cc7
-rw-r--r--views/controls/scrollbar/native_scroll_bar.cc340
-rw-r--r--views/controls/scrollbar/native_scroll_bar.h68
-rw-r--r--views/controls/scrollbar/native_scroll_bar_win.cc346
-rw-r--r--views/controls/scrollbar/native_scroll_bar_win.h62
-rw-r--r--views/controls/scrollbar/native_scroll_bar_wrapper.h42
-rw-r--r--views/controls/scrollbar/scroll_bar.h3
-rw-r--r--views/views.gyp3
8 files changed, 544 insertions, 327 deletions
diff --git a/views/controls/native_control_win.cc b/views/controls/native_control_win.cc
index 406b470..9f4d2d6 100644
--- a/views/controls/native_control_win.cc
+++ b/views/controls/native_control_win.cc
@@ -78,7 +78,12 @@ void NativeControlWin::VisibilityChanged(View* starting_from, bool is_visible) {
Detach();
DestroyWindow(hwnd);
} else if (!native_view()) {
- CreateNativeControl();
+ if (GetWidget())
+ CreateNativeControl();
+ } else {
+ // The view becomes visible after native control is created.
+ // Layout now.
+ Layout();
}
}
diff --git a/views/controls/scrollbar/native_scroll_bar.cc b/views/controls/scrollbar/native_scroll_bar.cc
index 5ec60f3..39a9120 100644
--- a/views/controls/scrollbar/native_scroll_bar.cc
+++ b/views/controls/scrollbar/native_scroll_bar.cc
@@ -8,326 +8,94 @@
#include <string>
#include "base/message_loop.h"
-#include "base/window_impl.h"
-#include "views/controls/native/native_view_host.h"
+#include "views/controls/scrollbar/native_scroll_bar_wrapper.h"
#include "views/widget/widget.h"
namespace views {
-/////////////////////////////////////////////////////////////////////////////
-//
-// ScrollBarContainer
-//
-// Since windows scrollbars only send notifications to their parent hwnd, we
-// use instances of this class to wrap native scrollbars.
-//
-/////////////////////////////////////////////////////////////////////////////
-class ScrollBarContainer : public base::WindowImpl {
- public:
- explicit ScrollBarContainer(ScrollBar* parent) : parent_(parent),
- scrollbar_(NULL) {
- set_window_style(WS_CHILD);
- Init(parent->GetWidget()->GetNativeView(), gfx::Rect());
- ShowWindow(hwnd(), SW_SHOW);
- }
-
- virtual ~ScrollBarContainer() {
- }
-
- BEGIN_MSG_MAP_EX(ScrollBarContainer);
- MSG_WM_CREATE(OnCreate);
- MSG_WM_ERASEBKGND(OnEraseBkgnd);
- MSG_WM_PAINT(OnPaint);
- MSG_WM_SIZE(OnSize);
- MSG_WM_HSCROLL(OnHorizScroll);
- MSG_WM_VSCROLL(OnVertScroll);
- END_MSG_MAP();
-
- HWND GetScrollBarHWND() {
- return scrollbar_;
- }
-
- // Invoked when the scrollwheel is used
- void ScrollWithOffset(int o) {
- SCROLLINFO si;
- si.cbSize = sizeof(si);
- si.fMask = SIF_POS;
- GetScrollInfo(scrollbar_, SB_CTL, &si);
- int pos = si.nPos - o;
-
- if (pos < parent_->GetMinPosition())
- pos = parent_->GetMinPosition();
- else if (pos > parent_->GetMaxPosition())
- pos = parent_->GetMaxPosition();
-
- ScrollBarController* sbc = parent_->GetController();
- sbc->ScrollToPosition(parent_, pos);
-
- si.nPos = pos;
- si.fMask = SIF_POS;
- SetScrollInfo(scrollbar_, SB_CTL, &si, TRUE);
- }
-
- private:
-
- LRESULT OnCreate(LPCREATESTRUCT create_struct) {
- scrollbar_ = CreateWindow(L"SCROLLBAR", L"",
- WS_CHILD | (parent_->IsHorizontal() ?
- SBS_HORZ : SBS_VERT),
- 0, 0, parent_->width(), parent_->height(),
- hwnd(), NULL, NULL, NULL);
- ShowWindow(scrollbar_, SW_SHOW);
- return 1;
- }
-
- LRESULT OnEraseBkgnd(HDC dc) {
- return 1;
- }
-
- void OnPaint(HDC ignore) {
- PAINTSTRUCT ps;
- HDC dc = BeginPaint(hwnd(), &ps);
- EndPaint(hwnd(), &ps);
- }
-
- void OnSize(int type, const CSize& sz) {
- SetWindowPos(scrollbar_,
- 0, 0, 0, sz.cx, sz.cy,
- SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOCOPYBITS |
- SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER);
- }
-
- void OnScroll(int code, HWND source, bool is_horizontal) {
- int pos;
-
- if (code == SB_ENDSCROLL) {
- return;
- }
-
- // If we receive an event from the scrollbar, make the view
- // component focused so we actually get mousewheel events.
- if (source != NULL) {
- Widget* widget = parent_->GetWidget();
- if (widget && widget->GetNativeView() != GetFocus()) {
- parent_->RequestFocus();
- }
- }
-
- SCROLLINFO si;
- si.cbSize = sizeof(si);
- si.fMask = SIF_POS | SIF_TRACKPOS;
- GetScrollInfo(scrollbar_, SB_CTL, &si);
- pos = si.nPos;
-
- ScrollBarController* sbc = parent_->GetController();
-
- switch (code) {
- case SB_BOTTOM: // case SB_RIGHT:
- pos = parent_->GetMaxPosition();
- break;
- case SB_TOP: // case SB_LEFT:
- pos = parent_->GetMinPosition();
- break;
- case SB_LINEDOWN: // case SB_LINERIGHT:
- pos += sbc->GetScrollIncrement(parent_, false, true);
- pos = std::min(parent_->GetMaxPosition(), pos);
- break;
- case SB_LINEUP: // case SB_LINELEFT:
- pos -= sbc->GetScrollIncrement(parent_, false, false);
- pos = std::max(parent_->GetMinPosition(), pos);
- break;
- case SB_PAGEDOWN: // case SB_PAGERIGHT:
- pos += sbc->GetScrollIncrement(parent_, true, true);
- pos = std::min(parent_->GetMaxPosition(), pos);
- break;
- case SB_PAGEUP: // case SB_PAGELEFT:
- pos -= sbc->GetScrollIncrement(parent_, true, false);
- pos = std::max(parent_->GetMinPosition(), pos);
- break;
- case SB_THUMBPOSITION:
- case SB_THUMBTRACK:
- pos = si.nTrackPos;
- if (pos < parent_->GetMinPosition())
- pos = parent_->GetMinPosition();
- else if (pos > parent_->GetMaxPosition())
- pos = parent_->GetMaxPosition();
- break;
- default:
- break;
- }
-
- sbc->ScrollToPosition(parent_, pos);
-
- si.nPos = pos;
- si.fMask = SIF_POS;
- SetScrollInfo(scrollbar_, SB_CTL, &si, TRUE);
-
- // Note: the system scrollbar modal loop doesn't give a chance
- // to our message_loop so we need to call DidProcessMessage()
- // manually.
- //
- // Sadly, we don't know what message has been processed. We may
- // want to remove the message from DidProcessMessage()
- MSG dummy;
- dummy.hwnd = NULL;
- dummy.message = 0;
- MessageLoopForUI::current()->DidProcessMessage(dummy);
- }
-
- // note: always ignore 2nd param as it is 16 bits
- void OnHorizScroll(int n_sb_code, int ignore, HWND source) {
- OnScroll(n_sb_code, source, true);
- }
+// static
+const char NativeScrollBar::kViewClassName[] = "views/NativeScrollBar";
- // note: always ignore 2nd param as it is 16 bits
- void OnVertScroll(int n_sb_code, int ignore, HWND source) {
- OnScroll(n_sb_code, source, false);
- }
+////////////////////////////////////////////////////////////////////////////////
+// NativeScrollBar, public:
+NativeScrollBar::NativeScrollBar(bool is_horizontal)
+ : ScrollBar(is_horizontal),
+ native_wrapper_(NULL) {
+}
+NativeScrollBar::~NativeScrollBar() {
+}
+// static
+int NativeScrollBar::GetHorizontalScrollBarHeight() {
+ return NativeScrollBarWrapper::GetHorizontalScrollBarHeight();
+}
- ScrollBar* parent_;
- HWND scrollbar_;
-};
+// static
+int NativeScrollBar::GetVerticalScrollBarWidth() {
+ return NativeScrollBarWrapper::GetVerticalScrollBarWidth();
+}
-NativeScrollBar::NativeScrollBar(bool is_horiz)
- : sb_view_(NULL),
- sb_container_(NULL),
- ScrollBar(is_horiz) {
+////////////////////////////////////////////////////////////////////////////////
+// NativeScrollBar, View overrides:
+gfx::Size NativeScrollBar::GetPreferredSize() {
+ if (native_wrapper_)
+ return native_wrapper_->GetView()->GetPreferredSize();
+ return gfx::Size();
}
-NativeScrollBar::~NativeScrollBar() {
- if (sb_container_) {
- // We always destroy the scrollbar container explicitly to cover all
- // cases including when the container is no longer connected to a
- // widget tree.
- DestroyWindow(sb_container_->hwnd());
- delete sb_container_;
- }
+void NativeScrollBar::Layout() {
+ if (native_wrapper_)
+ native_wrapper_->GetView()->Layout();
}
void NativeScrollBar::ViewHierarchyChanged(bool is_add, View *parent,
View *child) {
Widget* widget;
- if (is_add && (widget = GetWidget()) && !sb_view_) {
- sb_view_ = new NativeViewHost;
- AddChildView(sb_view_);
- sb_container_ = new ScrollBarContainer(this);
- sb_view_->Attach(sb_container_->hwnd());
- Layout();
+ if (is_add && !native_wrapper_ && (widget = GetWidget())) {
+ native_wrapper_ = NativeScrollBarWrapper::CreateWrapper(this);
+ AddChildView(native_wrapper_->GetView());
}
}
-void NativeScrollBar::Layout() {
- if (sb_view_)
- sb_view_->SetBounds(GetLocalBounds(true));
+std::string NativeScrollBar::GetClassName() const {
+ return kViewClassName;
}
-gfx::Size NativeScrollBar::GetPreferredSize() {
- if (IsHorizontal())
- return gfx::Size(0, GetLayoutSize());
- return gfx::Size(GetLayoutSize(), 0);
+// Overridden from View for keyboard UI.
+bool NativeScrollBar::OnKeyPressed(const KeyEvent& event) {
+ if (!native_wrapper_)
+ return false;
+ return native_wrapper_->GetView()->OnKeyPressed(event);
+}
+
+bool NativeScrollBar::OnMouseWheel(const MouseWheelEvent& event) {
+ if (!native_wrapper_)
+ return false;
+ return native_wrapper_->GetView()->OnMouseWheel(event);
}
+////////////////////////////////////////////////////////////////////////////////
+// NativeScrollBar, ScrollBar overrides:
void NativeScrollBar::Update(int viewport_size,
int content_size,
int current_pos) {
ScrollBar::Update(viewport_size, content_size, current_pos);
- if (!sb_container_)
- return;
- if (content_size < 0)
- content_size = 0;
-
- if (current_pos < 0)
- current_pos = 0;
-
- if (current_pos > content_size)
- current_pos = content_size;
-
- SCROLLINFO si;
- si.cbSize = sizeof(si);
- si.fMask = SIF_DISABLENOSCROLL | SIF_POS | SIF_RANGE | SIF_PAGE;
- si.nMin = 0;
- si.nMax = content_size;
- si.nPos = current_pos;
- si.nPage = viewport_size;
- SetScrollInfo(sb_container_->GetScrollBarHWND(), SB_CTL, &si, TRUE);
+ if (native_wrapper_)
+ native_wrapper_->Update(viewport_size, content_size, current_pos);
}
int NativeScrollBar::GetLayoutSize() const {
- return GetSystemMetrics(IsHorizontal() ? SM_CYHSCROLL : SM_CYVSCROLL);
+ return IsHorizontal() ?
+ GetHorizontalScrollBarHeight() : GetVerticalScrollBarWidth();
}
int NativeScrollBar::GetPosition() const {
- SCROLLINFO si;
- si.cbSize = sizeof(si);
- si.fMask = SIF_POS;
- GetScrollInfo(sb_container_->GetScrollBarHWND(), SB_CTL, &si);
- return si.nPos;
-}
-
-bool NativeScrollBar::OnMouseWheel(const MouseWheelEvent& e) {
- if (!sb_container_) {
- return false;
- }
-
- sb_container_->ScrollWithOffset(e.GetOffset());
- return true;
-}
-
-bool NativeScrollBar::OnKeyPressed(const KeyEvent& event) {
- if (!sb_container_) {
- return false;
- }
- int code = -1;
- switch (event.GetCharacter()) {
- case VK_UP:
- if (!IsHorizontal())
- code = SB_LINEUP;
- break;
- case VK_PRIOR:
- code = SB_PAGEUP;
- break;
- case VK_NEXT:
- code = SB_PAGEDOWN;
- break;
- case VK_DOWN:
- if (!IsHorizontal())
- code = SB_LINEDOWN;
- break;
- case VK_HOME:
- code = SB_TOP;
- break;
- case VK_END:
- code = SB_BOTTOM;
- break;
- case VK_LEFT:
- if (IsHorizontal())
- code = SB_LINELEFT;
- break;
- case VK_RIGHT:
- if (IsHorizontal())
- code = SB_LINERIGHT;
- break;
- }
- if (code != -1) {
- SendMessage(sb_container_->hwnd(),
- IsHorizontal() ? WM_HSCROLL : WM_VSCROLL,
- MAKELONG(static_cast<WORD>(code), 0), 0L);
- return true;
- }
- return false;
-}
-
-// static
-int NativeScrollBar::GetHorizontalScrollBarHeight() {
- return GetSystemMetrics(SM_CYHSCROLL);
-}
-
-// static
-int NativeScrollBar::GetVerticalScrollBarWidth() {
- return GetSystemMetrics(SM_CXVSCROLL);
+ if (!native_wrapper_)
+ return 0;
+ return native_wrapper_->GetPosition();
}
} // namespace views
+
diff --git a/views/controls/scrollbar/native_scroll_bar.h b/views/controls/scrollbar/native_scroll_bar.h
index 85a0453..6595a09 100644
--- a/views/controls/scrollbar/native_scroll_bar.h
+++ b/views/controls/scrollbar/native_scroll_bar.h
@@ -1,67 +1,57 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-2009 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.
-#ifndef VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLLBAR_H_
-#define VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLLBAR_H_
+#ifndef VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLL_BAR_H_
+#define VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLL_BAR_H_
-#include "build/build_config.h"
+#include <string>
#include "views/controls/scrollbar/scroll_bar.h"
+#include "views/view.h"
namespace views {
-class NativeViewHost;
-class ScrollBarContainer;
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// NativeScrollBar
-//
-// A View subclass that wraps a Native Windows scrollbar control.
-//
-// A scrollbar is either horizontal or vertical.
-//
-/////////////////////////////////////////////////////////////////////////////
+class NativeScrollBarWrapper;
+
+// The NativeScrollBar class is a scrollbar that uses platform's
+// native control.
class NativeScrollBar : public ScrollBar {
public:
+ // The scroll-bar's class name.
+ static const char kViewClassName[];
- // Create new scrollbar, either horizontal or vertical
+ // Create new scrollbar, either horizontal or vertical.
explicit NativeScrollBar(bool is_horiz);
virtual ~NativeScrollBar();
- // Overridden for layout purpose
- virtual void Layout();
+ // Return the system sizes.
+ static int GetHorizontalScrollBarHeight();
+ static int GetVerticalScrollBarWidth();
+
+ private:
+ // Overridden from View.
virtual gfx::Size GetPreferredSize();
+ virtual void Layout();
+ virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
+ virtual std::string GetClassName() const;
- // Overridden for keyboard UI purpose
+ // Overrideen from View for keyboard UI purpose.
virtual bool OnKeyPressed(const KeyEvent& event);
virtual bool OnMouseWheel(const MouseWheelEvent& e);
- virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child);
-
- // Overridden from ScrollBar
+ // Overridden from ScrollBar.
virtual void Update(int viewport_size, int content_size, int current_pos);
- virtual int GetLayoutSize() const;
virtual int GetPosition() const;
+ virtual int GetLayoutSize() const;
- // Return the system sizes
- static int GetHorizontalScrollBarHeight();
- static int GetVerticalScrollBarWidth();
+ // init border
+ NativeScrollBarWrapper* native_wrapper_;
- private:
-#if defined(OS_WIN)
- // The sb_view_ takes care of keeping sb_container in sync with the
- // view hierarchy
- NativeViewHost* sb_view_;
-#endif // defined(OS_WIN)
-
- // sb_container_ is a custom hwnd that we use to wrap the real
- // windows scrollbar. We need to do this to get the scroll events
- // without having to do anything special in the high level hwnd.
- ScrollBarContainer* sb_container_;
+ DISALLOW_COPY_AND_ASSIGN(NativeScrollBar);
};
} // namespace views
-#endif // #ifndef VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLLBAR_H_
+#endif // VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLL_BAR_H_
+
diff --git a/views/controls/scrollbar/native_scroll_bar_win.cc b/views/controls/scrollbar/native_scroll_bar_win.cc
new file mode 100644
index 0000000..b15be33
--- /dev/null
+++ b/views/controls/scrollbar/native_scroll_bar_win.cc
@@ -0,0 +1,346 @@
+// Copyright (c) 2009 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.
+
+#include "views/controls/scrollbar/native_scroll_bar_win.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/message_loop.h"
+#include "base/window_impl.h"
+#include "views/controls/scrollbar/native_scroll_bar.h"
+#include "views/controls/scrollbar/scroll_bar.h"
+#include "views/widget/widget.h"
+
+namespace views {
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// ScrollBarContainer
+//
+// Since windows scrollbars only send notifications to their parent hwnd, we
+// use instances of this class to wrap native scrollbars.
+//
+/////////////////////////////////////////////////////////////////////////////
+class ScrollBarContainer : public base::WindowImpl {
+ public:
+ explicit ScrollBarContainer(ScrollBar* parent)
+ : parent_(parent),
+ scrollbar_(NULL) {
+ set_window_style(WS_CHILD);
+ Init(parent->GetWidget()->GetNativeView(), gfx::Rect());
+ ShowWindow(hwnd(), SW_SHOW);
+ }
+
+ virtual ~ScrollBarContainer() {
+ }
+
+ BEGIN_MSG_MAP_EX(ScrollBarContainer);
+ MSG_WM_CREATE(OnCreate);
+ MSG_WM_ERASEBKGND(OnEraseBkgnd);
+ MSG_WM_PAINT(OnPaint);
+ MSG_WM_SIZE(OnSize);
+ MSG_WM_HSCROLL(OnHorizScroll);
+ MSG_WM_VSCROLL(OnVertScroll);
+ END_MSG_MAP();
+
+ HWND GetScrollBarHWND() {
+ return scrollbar_;
+ }
+
+ // Invoked when the scrollwheel is used
+ void ScrollWithOffset(int o) {
+ SCROLLINFO si;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ GetScrollInfo(scrollbar_, SB_CTL, &si);
+ int pos = si.nPos - o;
+
+ if (pos < parent_->GetMinPosition())
+ pos = parent_->GetMinPosition();
+ else if (pos > parent_->GetMaxPosition())
+ pos = parent_->GetMaxPosition();
+
+ ScrollBarController* sbc = parent_->GetController();
+ sbc->ScrollToPosition(parent_, pos);
+
+ si.nPos = pos;
+ si.fMask = SIF_POS;
+ SetScrollInfo(scrollbar_, SB_CTL, &si, TRUE);
+ }
+
+ private:
+
+ LRESULT OnCreate(LPCREATESTRUCT create_struct) {
+ scrollbar_ = CreateWindow(L"SCROLLBAR", L"",
+ WS_CHILD | (parent_->IsHorizontal() ?
+ SBS_HORZ : SBS_VERT),
+ 0, 0, parent_->width(), parent_->height(),
+ hwnd(), NULL, NULL, NULL);
+ ShowWindow(scrollbar_, SW_SHOW);
+ return 1;
+ }
+
+ LRESULT OnEraseBkgnd(HDC dc) {
+ return 1;
+ }
+
+ void OnPaint(HDC ignore) {
+ PAINTSTRUCT ps;
+ HDC dc = BeginPaint(hwnd(), &ps);
+ EndPaint(hwnd(), &ps);
+ }
+
+ void OnSize(int type, const CSize& sz) {
+ SetWindowPos(scrollbar_,
+ 0, 0, 0, sz.cx, sz.cy,
+ SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOCOPYBITS |
+ SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER);
+ }
+
+ void OnScroll(int code, HWND source, bool is_horizontal) {
+ int pos;
+
+ if (code == SB_ENDSCROLL) {
+ return;
+ }
+
+ // If we receive an event from the scrollbar, make the view
+ // component focused so we actually get mousewheel events.
+ if (source != NULL) {
+ Widget* widget = parent_->GetWidget();
+ if (widget && widget->GetNativeView() != GetFocus()) {
+ parent_->RequestFocus();
+ }
+ }
+
+ SCROLLINFO si;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS | SIF_TRACKPOS;
+ GetScrollInfo(scrollbar_, SB_CTL, &si);
+ pos = si.nPos;
+
+ ScrollBarController* sbc = parent_->GetController();
+
+ switch (code) {
+ case SB_BOTTOM: // case SB_RIGHT:
+ pos = parent_->GetMaxPosition();
+ break;
+ case SB_TOP: // case SB_LEFT:
+ pos = parent_->GetMinPosition();
+ break;
+ case SB_LINEDOWN: // case SB_LINERIGHT:
+ pos += sbc->GetScrollIncrement(parent_, false, true);
+ pos = std::min(parent_->GetMaxPosition(), pos);
+ break;
+ case SB_LINEUP: // case SB_LINELEFT:
+ pos -= sbc->GetScrollIncrement(parent_, false, false);
+ pos = std::max(parent_->GetMinPosition(), pos);
+ break;
+ case SB_PAGEDOWN: // case SB_PAGERIGHT:
+ pos += sbc->GetScrollIncrement(parent_, true, true);
+ pos = std::min(parent_->GetMaxPosition(), pos);
+ break;
+ case SB_PAGEUP: // case SB_PAGELEFT:
+ pos -= sbc->GetScrollIncrement(parent_, true, false);
+ pos = std::max(parent_->GetMinPosition(), pos);
+ break;
+ case SB_THUMBPOSITION:
+ case SB_THUMBTRACK:
+ pos = si.nTrackPos;
+ if (pos < parent_->GetMinPosition())
+ pos = parent_->GetMinPosition();
+ else if (pos > parent_->GetMaxPosition())
+ pos = parent_->GetMaxPosition();
+ break;
+ default:
+ break;
+ }
+
+ sbc->ScrollToPosition(parent_, pos);
+
+ si.nPos = pos;
+ si.fMask = SIF_POS;
+ SetScrollInfo(scrollbar_, SB_CTL, &si, TRUE);
+
+ // Note: the system scrollbar modal loop doesn't give a chance
+ // to our message_loop so we need to call DidProcessMessage()
+ // manually.
+ //
+ // Sadly, we don't know what message has been processed. We may
+ // want to remove the message from DidProcessMessage()
+ MSG dummy;
+ dummy.hwnd = NULL;
+ dummy.message = 0;
+ MessageLoopForUI::current()->DidProcessMessage(dummy);
+ }
+
+ // note: always ignore 2nd param as it is 16 bits
+ void OnHorizScroll(int n_sb_code, int ignore, HWND source) {
+ OnScroll(n_sb_code, source, true);
+ }
+
+ // note: always ignore 2nd param as it is 16 bits
+ void OnVertScroll(int n_sb_code, int ignore, HWND source) {
+ OnScroll(n_sb_code, source, false);
+ }
+
+ ScrollBar* parent_;
+ HWND scrollbar_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScrollBarContainer);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeScrollBarWin, public:
+
+NativeScrollBarWin::NativeScrollBarWin(NativeScrollBar* scroll_bar)
+ : native_scroll_bar_(scroll_bar),
+ sb_container_(NULL) {
+ set_focus_view(scroll_bar);
+}
+
+NativeScrollBarWin::~NativeScrollBarWin() {
+ if (sb_container_) {
+ // We always destroy the scrollbar container explicitly to cover all
+ // cases including when the container is no longer connected to a
+ // widget tree.
+ DestroyWindow(sb_container_->hwnd());
+ delete sb_container_;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeScrollBarWin, View overrides:
+
+void NativeScrollBarWin::Layout() {
+ SetBounds(native_scroll_bar_->GetLocalBounds(true));
+ NativeControlWin::Layout();
+}
+
+gfx::Size NativeScrollBarWin::GetPreferredSize() {
+ if (native_scroll_bar_->IsHorizontal())
+ return gfx::Size(0, GetHorizontalScrollBarHeight());
+ return gfx::Size(GetVerticalScrollBarWidth(), 0);
+}
+
+bool NativeScrollBarWin::OnKeyPressed(const KeyEvent& event) {
+ if (!sb_container_)
+ return false;
+ int code = -1;
+ switch (event.GetCharacter()) {
+ case VK_UP:
+ if (!native_scroll_bar_->IsHorizontal())
+ code = SB_LINEUP;
+ break;
+ case VK_PRIOR:
+ code = SB_PAGEUP;
+ break;
+ case VK_NEXT:
+ code = SB_PAGEDOWN;
+ break;
+ case VK_DOWN:
+ if (!native_scroll_bar_->IsHorizontal())
+ code = SB_LINEDOWN;
+ break;
+ case VK_HOME:
+ code = SB_TOP;
+ break;
+ case VK_END:
+ code = SB_BOTTOM;
+ break;
+ case VK_LEFT:
+ if (native_scroll_bar_->IsHorizontal())
+ code = SB_LINELEFT;
+ break;
+ case VK_RIGHT:
+ if (native_scroll_bar_->IsHorizontal())
+ code = SB_LINERIGHT;
+ break;
+ }
+ if (code != -1) {
+ SendMessage(sb_container_->hwnd(),
+ native_scroll_bar_->IsHorizontal() ? WM_HSCROLL : WM_VSCROLL,
+ MAKELONG(static_cast<WORD>(code), 0), 0L);
+ return true;
+ }
+ return false;
+}
+
+bool NativeScrollBarWin::OnMouseWheel(const MouseWheelEvent& e) {
+ if (!sb_container_)
+ return false;
+ sb_container_->ScrollWithOffset(e.GetOffset());
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeScrollBarWin, NativeControlWin overrides:
+
+void NativeScrollBarWin::CreateNativeControl() {
+ sb_container_ = new ScrollBarContainer(native_scroll_bar_);
+ NativeControlCreated(sb_container_->hwnd());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeScrollBarWin, NativeScrollBarWrapper overrides:
+
+int NativeScrollBarWin::GetPosition() const {
+ SCROLLINFO si;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ GetScrollInfo(sb_container_->GetScrollBarHWND(), SB_CTL, &si);
+ return si.nPos;
+}
+
+View* NativeScrollBarWin::GetView() {
+ return this;
+}
+
+void NativeScrollBarWin::Update(int viewport_size,
+ int content_size,
+ int current_pos) {
+ if (!sb_container_)
+ return;
+
+ if (content_size < 0)
+ content_size = 0;
+
+ if (current_pos < 0)
+ current_pos = 0;
+
+ if (current_pos > content_size)
+ current_pos = content_size;
+
+ SCROLLINFO si;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_DISABLENOSCROLL | SIF_POS | SIF_RANGE | SIF_PAGE;
+ si.nMin = 0;
+ si.nMax = content_size;
+ si.nPos = current_pos;
+ si.nPage = viewport_size;
+ SetScrollInfo(sb_container_->GetScrollBarHWND(), SB_CTL, &si, TRUE);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativewScrollBarWrapper, public:
+
+// static
+NativeScrollBarWrapper* NativeScrollBarWrapper::CreateWrapper(
+ NativeScrollBar* scroll_bar) {
+ return new NativeScrollBarWin(scroll_bar);
+}
+
+// static
+int NativeScrollBarWrapper::GetHorizontalScrollBarHeight() {
+ return GetSystemMetrics(SM_CYHSCROLL);
+}
+
+// static
+int NativeScrollBarWrapper::GetVerticalScrollBarWidth() {
+ return GetSystemMetrics(SM_CXVSCROLL);
+}
+
+} // namespace views
+
diff --git a/views/controls/scrollbar/native_scroll_bar_win.h b/views/controls/scrollbar/native_scroll_bar_win.h
new file mode 100644
index 0000000..566f036
--- /dev/null
+++ b/views/controls/scrollbar/native_scroll_bar_win.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2009 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.
+
+#ifndef VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLL_BAR_WIN_H_
+#define VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLL_BAR_WIN_H_
+
+#include "views/controls/native_control_win.h"
+#include "views/controls/scrollbar/native_scroll_bar_wrapper.h"
+
+namespace views {
+
+class ScrollBarContainer;
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// NativeScrollBarWin
+//
+// A View subclass that wraps a Native Windows scrollbar control.
+//
+// A scrollbar is either horizontal or vertical.
+//
+/////////////////////////////////////////////////////////////////////////////
+class NativeScrollBarWin : public NativeControlWin,
+ public NativeScrollBarWrapper {
+ public:
+ // Create new scrollbar, either horizontal or vertical.
+ explicit NativeScrollBarWin(NativeScrollBar* native_scroll_bar);
+ virtual ~NativeScrollBarWin();
+
+ private:
+ // Overridden from View for layout purpose.
+ virtual void Layout();
+ virtual gfx::Size GetPreferredSize();
+
+ // Overridden from View for keyboard UI purpose.
+ virtual bool OnKeyPressed(const KeyEvent& event);
+ virtual bool OnMouseWheel(const MouseWheelEvent& e);
+
+ // Overridden from NativeControlWin.
+ virtual void CreateNativeControl();
+
+ // Overridden from ScrollBarWrapper.
+ virtual int GetPosition() const;
+ virtual View* GetView();
+ virtual void Update(int viewport_size, int content_size, int current_pos);
+
+ // The NativeScrollBar we are bound to.
+ NativeScrollBar* native_scroll_bar_;
+
+ // sb_container_ is a custom hwnd that we use to wrap the real
+ // windows scrollbar. We need to do this to get the scroll events
+ // without having to do anything special in the high level hwnd.
+ ScrollBarContainer* sb_container_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeScrollBarWin);
+};
+
+} // namespace views
+
+#endif // #ifndef VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLL_BAR_WIN_H_
+
diff --git a/views/controls/scrollbar/native_scroll_bar_wrapper.h b/views/controls/scrollbar/native_scroll_bar_wrapper.h
new file mode 100644
index 0000000..6fb68ea
--- /dev/null
+++ b/views/controls/scrollbar/native_scroll_bar_wrapper.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2009 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.
+
+#ifndef VIEWS_CONTROLS_NATIVE_SCROLL_BAR_WRAPPER_H_
+#define VIEWS_CONTROLS_NATIVE_SCROLL_BAR_WRAPPER_H_
+
+namespace views {
+
+class NativeScrollBar;
+class View;
+
+// A specialization of NativeControlWrapper that hosts a platform-native
+// scroll bar.
+class NativeScrollBarWrapper {
+ public:
+ virtual ~NativeScrollBarWrapper() {}
+
+ // Updates the scroll bar appearance given a viewport size, content size and
+ // current position.
+ virtual void Update(int viewport_size,
+ int content_size,
+ int current_pos) = 0;
+
+ // Retrieves the views::View that hosts the native control.
+ virtual View* GetView() = 0;
+
+ // Returns the position of the scrollbar.
+ virtual int GetPosition() const = 0;
+
+ // Creates an appropriate NativeScrollBarWrapper for the platform.
+ static NativeScrollBarWrapper* CreateWrapper(NativeScrollBar* button);
+
+ // Returns the system sizes of vertical/horizontal scroll bars.
+ static int GetVerticalScrollBarWidth();
+ static int GetHorizontalScrollBarHeight();
+};
+
+} // namespace views
+
+#endif // VIEWS_CONTROLS_NATIVE_SCROLL_BAR_WRAPPER_H_
+
diff --git a/views/controls/scrollbar/scroll_bar.h b/views/controls/scrollbar/scroll_bar.h
index 36a9d2e..9354fcb 100644
--- a/views/controls/scrollbar/scroll_bar.h
+++ b/views/controls/scrollbar/scroll_bar.h
@@ -5,8 +5,8 @@
#ifndef VIEWS_CONTROLS_SCROLLBAR_SCROLLBAR_H_
#define VIEWS_CONTROLS_SCROLLBAR_SCROLLBAR_H_
-#include "views/view.h"
#include "views/event.h"
+#include "views/view.h"
namespace views {
@@ -100,3 +100,4 @@ class ScrollBar : public View {
} // namespace views
#endif // #ifndef VIEWS_CONTROLS_SCROLLBAR_SCROLLBAR_H_
+
diff --git a/views/views.gyp b/views/views.gyp
index e9456e6..e1277cb 100644
--- a/views/views.gyp
+++ b/views/views.gyp
@@ -159,6 +159,9 @@
'controls/scroll_view.h',
'controls/scrollbar/bitmap_scroll_bar.cc',
'controls/scrollbar/bitmap_scroll_bar.h',
+ 'controls/scrollbar/native_scroll_bar_wrapper.h',
+ 'controls/scrollbar/native_scroll_bar_win.cc',
+ 'controls/scrollbar/native_scroll_bar_win.h',
'controls/scrollbar/native_scroll_bar.cc',
'controls/scrollbar/native_scroll_bar.h',
'controls/scrollbar/scroll_bar.cc',