summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/wx/ScrollViewWx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/wx/ScrollViewWx.cpp')
-rw-r--r--WebCore/platform/wx/ScrollViewWx.cpp466
1 files changed, 466 insertions, 0 deletions
diff --git a/WebCore/platform/wx/ScrollViewWx.cpp b/WebCore/platform/wx/ScrollViewWx.cpp
new file mode 100644
index 0000000..b6c5ae4
--- /dev/null
+++ b/WebCore/platform/wx/ScrollViewWx.cpp
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScrollView.h"
+
+#include "FloatRect.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+#include "PlatformWheelEvent.h"
+#include "ScrollBar.h"
+
+#include <algorithm>
+#include <stdio.h>
+
+#include <wx/defs.h>
+#include <wx/scrolwin.h>
+#include <wx/event.h>
+
+using namespace std;
+
+namespace WebCore {
+
+class ScrollView::ScrollViewPrivate : public wxEvtHandler {
+
+public:
+ ScrollViewPrivate(ScrollView* scrollView)
+ : wxEvtHandler()
+ , m_scrollView(scrollView)
+ , hasStaticBackground(false)
+ , suppressScrollbars(false)
+ , vScrollbarMode(ScrollbarAuto)
+ , hScrollbarMode(ScrollbarAuto)
+ , viewStart(0, 0)
+ {
+ }
+
+ void bindEvents(wxWindow* win)
+ {
+ // TODO: is there an easier way to Connect to a range of events? these are contiguous.
+ win->Connect(wxEVT_SCROLLWIN_TOP, wxScrollWinEventHandler(ScrollViewPrivate::OnScrollWinEvents), NULL, this);
+ win->Connect(wxEVT_SCROLLWIN_BOTTOM, wxScrollWinEventHandler(ScrollViewPrivate::OnScrollWinEvents), NULL, this);
+ win->Connect(wxEVT_SCROLLWIN_LINEUP, wxScrollWinEventHandler(ScrollViewPrivate::OnScrollWinEvents), NULL, this);
+ win->Connect(wxEVT_SCROLLWIN_LINEDOWN, wxScrollWinEventHandler(ScrollViewPrivate::OnScrollWinEvents), NULL, this);
+ win->Connect(wxEVT_SCROLLWIN_PAGEUP, wxScrollWinEventHandler(ScrollViewPrivate::OnScrollWinEvents), NULL, this);
+ win->Connect(wxEVT_SCROLLWIN_PAGEDOWN, wxScrollWinEventHandler(ScrollViewPrivate::OnScrollWinEvents), NULL, this);
+ win->Connect(wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEventHandler(ScrollViewPrivate::OnScrollWinEvents), NULL, this);
+ win->Connect(wxEVT_SCROLLWIN_THUMBRELEASE, wxScrollWinEventHandler(ScrollViewPrivate::OnScrollWinEvents), NULL, this);
+ win->Connect(wxEVT_SCROLLWIN_TOP, wxScrollWinEventHandler(ScrollViewPrivate::OnScrollWinEvents), NULL, this);
+ }
+
+ void OnScrollWinEvents(wxScrollWinEvent& e)
+ {
+ wxEventType scrollType(e.GetEventType());
+ bool horiz = e.GetOrientation() == wxHORIZONTAL;
+
+ wxPoint pos(viewStart);
+
+ if (scrollType == wxEVT_SCROLLWIN_THUMBTRACK || scrollType == wxEVT_SCROLLWIN_THUMBRELEASE) {
+ if (horiz)
+ pos.x = e.GetPosition();
+ else
+ pos.y = e.GetPosition();
+ }
+ else if ( scrollType == wxEVT_SCROLLWIN_LINEDOWN ) {
+ if (horiz)
+ pos.x += LINE_STEP;
+ else
+ pos.y += LINE_STEP;
+ }
+ else if ( scrollType == wxEVT_SCROLLWIN_LINEUP ) {
+ if (horiz)
+ pos.x -= LINE_STEP;
+ else
+ pos.y -= LINE_STEP;
+ }
+ else
+ return e.Skip();
+
+ m_scrollView->setContentsPos(pos.x, pos.y);
+ m_scrollView->update();
+ }
+
+ ScrollView* m_scrollView;
+
+ HashSet<Widget*> m_children;
+ bool hasStaticBackground;
+ bool suppressScrollbars;
+ ScrollbarMode vScrollbarMode;
+ ScrollbarMode hScrollbarMode;
+ wxPoint viewStart;
+};
+
+ScrollView::ScrollView()
+{
+ m_data = new ScrollViewPrivate(this);
+}
+
+void ScrollView::setNativeWindow(wxWindow* win)
+{
+ Widget::setNativeWindow(win);
+ m_data->bindEvents(win);
+}
+
+ScrollView::~ScrollView()
+{
+ delete m_data;
+}
+
+void ScrollView::updateContents(const IntRect& updateRect, bool now)
+{
+ // we need to convert coordinates to scrolled position
+ wxRect contentsRect = updateRect;
+ contentsRect.Offset(-contentsX(), -contentsY());
+ wxWindow* win = nativeWindow();
+ if (win) {
+ win->RefreshRect(contentsRect, true);
+ if (now)
+ win->Update();
+ }
+}
+
+void ScrollView::update()
+{
+ wxWindow* win = nativeWindow();
+ if (win)
+ win->Update();
+}
+
+int ScrollView::visibleWidth() const
+{
+ int width = 0;
+ wxWindow* win = nativeWindow();
+ if (win)
+ win->GetClientSize(&width, NULL);
+
+ ASSERT(width >= 0);
+ return width;
+}
+
+int ScrollView::visibleHeight() const
+{
+ int height = 0;
+ wxWindow* win = nativeWindow();
+ if (win)
+ win->GetClientSize(NULL, &height);
+
+ ASSERT(height >= 0);
+ return height;
+}
+
+FloatRect ScrollView::visibleContentRect() const
+{
+ return FloatRect(contentsX(),contentsY(),visibleWidth(),visibleHeight());
+}
+
+void ScrollView::setContentsPos(int newX, int newY)
+{
+ int dx = newX - contentsX();
+ int dy = newY - contentsY();
+ scrollBy(dx, dy);
+}
+
+void ScrollView::scrollBy(int dx, int dy)
+{
+ wxWindow* win = nativeWindow();
+ if (!win)
+ return;
+
+ wxPoint scrollOffset = m_data->viewStart;
+ wxPoint orig(scrollOffset);
+ wxPoint newScrollOffset = scrollOffset + wxPoint(dx, dy);
+
+ wxRect vRect(win->GetVirtualSize());
+ wxRect cRect(win->GetClientSize());
+
+ // clamp to scroll area
+ if (newScrollOffset.x < 0)
+ newScrollOffset.x = 0;
+ else if (newScrollOffset.x + cRect.width > vRect.width)
+ newScrollOffset.x = max(0, vRect.width - cRect.width - 1);
+
+ if (newScrollOffset.y < 0)
+ newScrollOffset.y = 0;
+ else if (newScrollOffset.y + cRect.height > vRect.height)
+ newScrollOffset.y = max(0, vRect.height - cRect.height - 1);
+
+ if (newScrollOffset == scrollOffset)
+ return;
+
+ m_data->viewStart = newScrollOffset;
+
+ wxPoint delta(orig - newScrollOffset);
+
+ if (m_data->hasStaticBackground)
+ win->Refresh();
+ else
+ win->ScrollWindow(delta.x, delta.y);
+
+ adjustScrollbars();
+}
+
+void ScrollView::resizeContents(int w,int h)
+{
+ wxWindow* win = nativeWindow();
+ if (win) {
+ win->SetVirtualSize(w, h);
+ adjustScrollbars();
+ }
+}
+
+int ScrollView::contentsX() const
+{
+ ASSERT(m_data->viewStart.x >= 0);
+ return m_data->viewStart.x;
+}
+
+int ScrollView::contentsY() const
+{
+ ASSERT(m_data->viewStart.y >= 0);
+ return m_data->viewStart.y;
+}
+
+int ScrollView::contentsWidth() const
+{
+ int width = 0;
+ wxWindow* win = nativeWindow();
+ if (win)
+ win->GetVirtualSize(&width, NULL);
+ ASSERT(width >= 0);
+ return width;
+}
+
+int ScrollView::contentsHeight() const
+{
+ int height = 0;
+ wxWindow* win = nativeWindow();
+ if (win)
+ win->GetVirtualSize(NULL, &height);
+ ASSERT(height >= 0);
+ return height;
+}
+
+FloatRect ScrollView::visibleContentRectConsideringExternalScrollers() const
+{
+ // FIXME: clip this rect if parent scroll views cut off the visible
+ // area.
+ return visibleContentRect();
+}
+
+IntSize ScrollView::scrollOffset() const
+{
+ return IntSize(contentsX(), contentsY());
+}
+
+void ScrollView::adjustScrollbars(int x, int y, bool refresh)
+{
+ wxWindow* win = nativeWindow();
+ if (!win)
+ return;
+
+ wxRect crect(win->GetClientRect()), vrect(win->GetVirtualSize());
+
+ if (x == -1) x = m_data->viewStart.x;
+ if (y == -1) y = m_data->viewStart.y;
+
+ long style = win->GetWindowStyle();
+
+ // by setting the wxALWAYS_SHOW_SB wxWindow flag before
+ // each SetScrollbar call, we can control the scrollbars
+ // visibility individually.
+
+ // horizontal scrollbar
+ switch (m_data->hScrollbarMode) {
+ case ScrollbarAlwaysOff:
+ win->SetWindowStyleFlag(style & ~wxALWAYS_SHOW_SB);
+ win->SetScrollbar(wxHORIZONTAL, 0, 0, 0, refresh);
+ break;
+
+ case ScrollbarAuto:
+ win->SetWindowStyleFlag(style & ~wxALWAYS_SHOW_SB);
+ win->SetScrollbar(wxHORIZONTAL, x, crect.width, vrect.width, refresh);
+ break;
+
+ default: // ScrollbarAlwaysOn
+ win->SetWindowStyleFlag(style | wxALWAYS_SHOW_SB);
+ win->SetScrollbar(wxHORIZONTAL, x, crect.width, vrect.width, refresh);
+ break;
+ }
+
+ // vertical scrollbar
+ switch (m_data->vScrollbarMode) {
+ case ScrollbarAlwaysOff:
+ win->SetWindowStyleFlag(style & ~wxALWAYS_SHOW_SB);
+ win->SetScrollbar(wxVERTICAL, 0, 0, 0, refresh);
+ break;
+
+ case ScrollbarAlwaysOn:
+ win->SetWindowStyleFlag(style | wxALWAYS_SHOW_SB);
+ win->SetScrollbar(wxVERTICAL, y, crect.height, vrect.height, refresh);
+ break;
+
+ default: // case ScrollbarAuto:
+ win->SetWindowStyleFlag(style & ~wxALWAYS_SHOW_SB);
+ win->SetScrollbar(wxVERTICAL, y, crect.height, vrect.height, refresh);
+ }
+}
+
+WebCore::ScrollbarMode ScrollView::hScrollbarMode() const
+{
+ return m_data->hScrollbarMode;
+}
+
+WebCore::ScrollbarMode ScrollView::vScrollbarMode() const
+{
+ return m_data->vScrollbarMode;
+}
+
+void ScrollView::setScrollbarsMode(ScrollbarMode newMode)
+{
+ bool needsAdjust = false;
+
+ if (m_data->hScrollbarMode != newMode) {
+ m_data->hScrollbarMode = newMode;
+ needsAdjust = true;
+ }
+
+ if (m_data->vScrollbarMode != newMode) {
+ m_data->vScrollbarMode = newMode;
+ adjustScrollbars();
+ needsAdjust = true;
+ }
+
+ if (needsAdjust)
+ adjustScrollbars();
+}
+
+void ScrollView::setHScrollbarMode(ScrollbarMode newMode)
+{
+ if (m_data->hScrollbarMode != newMode) {
+ m_data->hScrollbarMode = newMode;
+ adjustScrollbars();
+ }
+}
+
+void ScrollView::setVScrollbarMode(ScrollbarMode newMode)
+{
+ if (m_data->vScrollbarMode != newMode) {
+ m_data->vScrollbarMode = newMode;
+ adjustScrollbars();
+ }
+}
+
+void ScrollView::setStaticBackground(bool flag)
+{
+ m_data->hasStaticBackground = flag;
+}
+
+void ScrollView::suppressScrollbars(bool suppressed, bool repaintOnSuppress)
+{
+ if ( m_data->suppressScrollbars != suppressed )
+ m_data->suppressScrollbars = suppressed;
+}
+
+IntPoint ScrollView::contentsToWindow(const IntPoint& point) const
+{
+ return point - scrollOffset();
+}
+
+IntPoint ScrollView::windowToContents(const IntPoint& point) const
+{
+ return point + scrollOffset();
+}
+
+bool ScrollView::inWindow() const
+{
+ // NB: This is called from RenderObject::willRenderImage
+ // and really seems to be more of a "is the window in a valid state" test,
+ // despite the API name.
+ return nativeWindow() != NULL;
+}
+
+void ScrollView::wheelEvent(PlatformWheelEvent& e)
+{
+ // Determine how much we want to scroll. If we can move at all, we will accept the event.
+ IntSize maxScrollDelta = maximumScroll();
+ if ((e.deltaX() < 0 && maxScrollDelta.width() > 0) ||
+ (e.deltaX() > 0 && scrollOffset().width() > 0) ||
+ (e.deltaY() < 0 && maxScrollDelta.height() > 0) ||
+ (e.deltaY() > 0 && scrollOffset().height() > 0)) {
+ e.accept();
+ scrollBy(-e.deltaX() * LINE_STEP, -e.deltaY() * LINE_STEP);
+ }
+}
+
+// used for subframes support
+void ScrollView::addChild(Widget* widget)
+{
+ m_data->m_children.add(widget);
+
+ // NB: In all cases I'm aware of,
+ // by the time this is called the ScrollView is already a child
+ // of its parent Widget by wx port APIs, so I don't think
+ // we need to do anything here.
+}
+
+void ScrollView::removeChild(Widget* widget)
+{
+ m_data->m_children.remove(widget);
+
+ if (nativeWindow() && widget->nativeWindow()) {
+ nativeWindow()->RemoveChild(widget->nativeWindow());
+ // FIXME: Is this the right place to do deletion? I see
+ // detachFromParent2/3/4, initiated by FrameLoader::detachFromParent,
+ // but I'm not sure if it's better to handle there or not.
+ widget->nativeWindow()->Destroy();
+ }
+}
+
+HashSet<Widget*>* ScrollView::children()
+{
+ return &(m_data->m_children);
+}
+
+void ScrollView::scrollRectIntoViewRecursively(const IntRect& rect)
+{
+ setContentsPos(rect.x(), rect.y());
+}
+
+PlatformScrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent)
+{
+ // AFAICT this is only used for platforms that provide
+ // feedback when mouse is hovered over.
+ return 0;
+}
+
+IntSize ScrollView::maximumScroll() const
+{
+ IntSize delta = (IntSize(contentsWidth(), contentsHeight()) - IntSize(visibleWidth(), visibleHeight())) - scrollOffset();
+ delta.clampNegativeToZero();
+ return delta;
+}
+
+}