2007-07-16 Holger Hans Peter Freyther <zecke@selfish.org>
[WebKit-https.git] / WebCore / platform / gdk / ScrollViewGdk.cpp
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com 
4  * Copyright (C) 2007 Holger Hans Peter Freyther
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
28  */
29
30 #include "config.h"
31 #include "ScrollView.h"
32
33 #include "FloatRect.h"
34 #include "Frame.h"
35 #include "FrameView.h"
36 #include "GraphicsContext.h"
37 #include "IntRect.h"
38 #include "NotImplemented.h"
39 #include "RenderLayer.h"
40
41 #include <gdk/gdk.h>
42 #include <gtk/gtk.h>
43
44 using namespace std;
45
46 namespace WebCore {
47
48 class ScrollView::ScrollViewPrivate
49 {
50 public:
51     ScrollViewPrivate()
52         : hasStaticBackground(false)
53         , suppressScrollbars(false)
54         , vScrollbarMode(ScrollbarAuto)
55         , hScrollbarMode(ScrollbarAuto)
56         , layout(0)
57         , horizontalAdjustment(0)
58         , verticalAdjustment(0)
59         , scrollBarsNeedUpdate(false)
60     { }
61
62     bool hasStaticBackground;
63     bool suppressScrollbars;
64     ScrollbarMode vScrollbarMode;
65     ScrollbarMode hScrollbarMode;
66     GtkLayout *layout;
67     GtkAdjustment *horizontalAdjustment;
68     GtkAdjustment *verticalAdjustment;
69     IntSize contentsSize;
70     IntSize viewPortSize;
71     bool scrollBarsNeedUpdate;
72 };
73
74 ScrollView::ScrollView()
75     : m_data(new ScrollViewPrivate)
76 {}
77
78 ScrollView::~ScrollView()
79 {
80     delete m_data;
81 }
82
83 void ScrollView::updateView(const IntRect& updateRect, bool now)
84 {
85     GdkRectangle rect = { updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height() };
86     GdkDrawable* gdkdrawable = Widget::drawable();
87     if (GDK_IS_WINDOW(gdkdrawable)) {
88         GdkWindow* window = GDK_WINDOW(gdkdrawable);
89         gdk_window_invalidate_rect(window, &rect, true);
90         if (now)
91             gdk_window_process_updates(window, true);
92     }
93 }
94
95 void ScrollView::updateContents(const IntRect& updateRect, bool now)
96 {
97     updateView(updateRect, now);
98 }
99
100 void ScrollView::update()
101 {
102     ASSERT(gtkWidget());
103     gtk_widget_queue_draw(gtkWidget());
104
105     if (m_data->scrollBarsNeedUpdate)
106         updateScrollbars();
107 }
108
109 int ScrollView::visibleWidth() const
110 {
111     return m_data->viewPortSize.width();
112 }
113
114 int ScrollView::visibleHeight() const
115 {
116     return m_data->viewPortSize.height();
117 }
118
119 // Region of the content currently visible in the viewport in the content view's coordinate system.
120 FloatRect ScrollView::visibleContentRect() const
121 {
122     return FloatRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
123 }
124
125 FloatRect ScrollView::visibleContentRectConsideringExternalScrollers() const
126 {
127     // external scrollers not supported for now
128     return visibleContentRect();
129 }
130
131 void ScrollView::setContentsPos(int newX, int newY)
132 {
133     int dx = newX - contentsX();
134     int dy = newY - contentsY();
135     scrollBy(dx, dy);
136 }
137
138 void ScrollView::resizeContents(int w, int h)
139 {
140     IntSize newSize(w, h);
141     if (m_data->contentsSize == newSize)
142         return;
143
144     m_data->contentsSize = newSize;
145     
146     if (m_data->layout) {
147         gtk_layout_set_size(m_data->layout, w, h);
148         m_data->scrollBarsNeedUpdate = true;
149     }
150 }
151
152 int ScrollView::contentsX() const
153 {
154     g_return_val_if_fail(m_data->horizontalAdjustment, 0);
155     return static_cast<int>(gtk_adjustment_get_value(m_data->horizontalAdjustment));
156 }
157
158 int ScrollView::contentsY() const
159 {
160     g_return_val_if_fail(m_data->verticalAdjustment, 0);
161     return static_cast<int>(gtk_adjustment_get_value(m_data->verticalAdjustment));
162 }
163
164 int ScrollView::contentsWidth() const
165 {
166     return m_data->contentsSize.width();
167 }
168
169 int ScrollView::contentsHeight() const
170 {
171     return m_data->contentsSize.height();
172 }
173
174 IntSize ScrollView::scrollOffset() const
175 {
176     g_return_val_if_fail(m_data, IntSize());
177     return IntSize(contentsX(), contentsY());
178 }
179
180 void ScrollView::scrollBy(int dx, int dy)
181 {
182     g_return_if_fail(m_data->horizontalAdjustment);
183     g_return_if_fail(m_data->verticalAdjustment);
184
185     int current_x = contentsX();
186     int current_y = contentsY();
187
188     gtk_adjustment_set_value(m_data->horizontalAdjustment,
189                              CLAMP(current_x+dx, m_data->horizontalAdjustment->lower,
190                                    MAX(0.0, m_data->horizontalAdjustment->upper - m_data->horizontalAdjustment->page_size)));
191     gtk_adjustment_set_value(m_data->verticalAdjustment,
192                              CLAMP(current_y+dy, m_data->verticalAdjustment->lower,
193                                    MAX(0.0, m_data->verticalAdjustment->upper - m_data->verticalAdjustment->page_size)));
194 }
195
196 ScrollbarMode ScrollView::hScrollbarMode() const
197 {
198     return m_data->hScrollbarMode;
199 }
200
201 ScrollbarMode ScrollView::vScrollbarMode() const
202 {
203     return m_data->vScrollbarMode;
204 }
205
206 void ScrollView::suppressScrollbars(bool suppressed, bool repaintOnSuppress)
207 {
208     m_data->suppressScrollbars = suppressed;
209     if (repaintOnSuppress)
210         updateScrollbars();
211 }
212
213 void ScrollView::setHScrollbarMode(ScrollbarMode newMode)
214 {
215     if (m_data->hScrollbarMode != newMode) {
216         m_data->hScrollbarMode = newMode;
217         updateScrollbars();
218     }
219 }
220
221 void ScrollView::setVScrollbarMode(ScrollbarMode newMode)
222 {
223     if (m_data->vScrollbarMode != newMode) {
224         m_data->vScrollbarMode = newMode;
225         updateScrollbars();
226     }
227 }
228
229 void ScrollView::setScrollbarsMode(ScrollbarMode newMode)
230 {
231     m_data->hScrollbarMode = m_data->vScrollbarMode = newMode;
232     updateScrollbars();
233 }
234
235 void ScrollView::setStaticBackground(bool flag)
236 {
237     m_data->hasStaticBackground = flag;
238 }
239
240 /*
241  * only update the adjustments, the GtkLayout is doing the work
242  * for us (assuming it is in a box...).
243  */
244 void ScrollView::setFrameGeometry(const IntRect& r)
245 {
246     Widget::setFrameGeometry(r);
247     updateGeometry(r.width(), r.height());
248 }
249
250 void ScrollView::updateGeometry(int width, int height)
251 {
252     m_data->viewPortSize = IntSize(width,height);
253 }
254
255 void ScrollView::setGtkWidget(GtkLayout* layout)
256 {
257     g_return_if_fail(GTK_LAYOUT(layout));
258     m_data->layout = layout;
259     m_data->horizontalAdjustment = gtk_layout_get_hadjustment(layout);
260     m_data->verticalAdjustment = gtk_layout_get_vadjustment(layout);
261
262     Widget::setGtkWidget(GTK_WIDGET(layout));
263     if (!GDK_IS_WINDOW(drawable())) {
264         LOG_ERROR("image scrollview not supported");
265         return;
266     }
267 }
268
269 void ScrollView::addChild(Widget*)
270
271     notImplemented();
272 }
273
274 void ScrollView::removeChild(Widget*)
275 {
276     notImplemented();
277 }
278
279 void ScrollView::scrollRectIntoViewRecursively(const IntRect&)
280 {
281     notImplemented();
282 }
283
284 bool ScrollView::inWindow() const
285 {
286     notImplemented();
287     return true;
288 }
289
290 void ScrollView::wheelEvent(PlatformWheelEvent&)
291 {
292     notImplemented();
293 }
294
295 void ScrollView::updateScrollbars()
296 {
297     g_return_if_fail(m_data->horizontalAdjustment);
298     g_return_if_fail(m_data->verticalAdjustment);
299     
300     m_data->horizontalAdjustment->page_size = visibleWidth();
301     m_data->horizontalAdjustment->step_increment = 13;
302     
303     m_data->verticalAdjustment->page_size = visibleHeight();
304     m_data->verticalAdjustment->step_increment = 13;
305     
306     gtk_adjustment_changed(m_data->horizontalAdjustment);
307     gtk_adjustment_value_changed(m_data->horizontalAdjustment);
308     
309     gtk_adjustment_changed(m_data->verticalAdjustment);
310     gtk_adjustment_value_changed(m_data->verticalAdjustment);
311
312     m_data->scrollBarsNeedUpdate = false;
313 }
314
315 IntPoint ScrollView::windowToContents(const IntPoint& point) const
316
317     return point;
318 }
319
320 IntPoint ScrollView::contentsToWindow(const IntPoint& point) const
321 {
322     return point;
323 }
324
325 PlatformScrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent)
326
327     notImplemented();
328     return 0;
329 }
330
331 }