Mercurial > projects > dwt-linux
annotate dwt/widgets/Scrollable.d @ 34:3a3e3aa76b66
Composite
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Thu, 10 Jan 2008 03:51:48 +0100 |
parents | 27324bbbac70 |
children | a5c274fa5af9 |
rev | line source |
---|---|
31 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2007 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 *******************************************************************************/ | |
11 module dwt.widgets.Scrollable; | |
12 | |
13 | |
14 import dwt.SWT; | |
15 import dwt.internal.gtk.OS; | |
16 import dwt.graphics.Rectangle; | |
17 import dwt.widgets.Composite; | |
18 import dwt.widgets.Control; | |
19 import dwt.widgets.Display; | |
20 import dwt.widgets.ScrollBar; | |
21 import dwt.widgets.Widget; | |
22 | |
23 import tango.stdc.string; | |
24 import tango.stdc.stringz; | |
25 | |
26 /** | |
27 * This class is the abstract superclass of all classes which | |
28 * represent controls that have standard scroll bars. | |
29 * <dl> | |
30 * <dt><b>Styles:</b></dt> | |
31 * <dd>H_SCROLL, V_SCROLL</dd> | |
32 * <dt><b>Events:</b> | |
33 * <dd>(none)</dd> | |
34 * </dl> | |
35 * <p> | |
36 * IMPORTANT: This class is intended to be subclassed <em>only</em> | |
37 * within the SWT implementation. | |
38 * </p> | |
39 */ | |
40 public abstract class Scrollable : Control { | |
34 | 41 GtkWidget* scrolledHandle; |
31 | 42 ScrollBar horizontalBar, verticalBar; |
43 | |
44 /** | |
45 * Prevents uninitialized instances from being created outside the package. | |
46 */ | |
47 this () {} | |
48 | |
49 /** | |
50 * Constructs a new instance of this class given its parent | |
51 * and a style value describing its behavior and appearance. | |
52 * <p> | |
53 * The style value is either one of the style constants defined in | |
54 * class <code>SWT</code> which is applicable to instances of this | |
55 * class, or must be built by <em>bitwise OR</em>'ing together | |
56 * (that is, using the <code>int</code> "|" operator) two or more | |
57 * of those <code>SWT</code> style constants. The class description | |
58 * lists the style constants that are applicable to the class. | |
59 * Style bits are also inherited from superclasses. | |
60 * </p> | |
61 * | |
62 * @param parent a composite control which will be the parent of the new instance (cannot be null) | |
63 * @param style the style of control to construct | |
64 * | |
65 * @exception IllegalArgumentException <ul> | |
66 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
67 * </ul> | |
68 * @exception SWTException <ul> | |
69 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
70 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
71 * </ul> | |
72 * | |
73 * @see SWT#H_SCROLL | |
74 * @see SWT#V_SCROLL | |
75 * @see Widget#checkSubclass | |
76 * @see Widget#getStyle | |
77 */ | |
78 public this (Composite parent, int style) { | |
79 super (parent, style); | |
80 } | |
81 | |
82 GtkWidget* clientHandle () { | |
83 return handle; | |
84 } | |
85 | |
86 /** | |
87 * Given a desired <em>client area</em> for the receiver | |
88 * (as described by the arguments), returns the bounding | |
89 * rectangle which would be required to produce that client | |
90 * area. | |
91 * <p> | |
92 * In other words, it returns a rectangle such that, if the | |
93 * receiver's bounds were set to that rectangle, the area | |
94 * of the receiver which is capable of displaying data | |
95 * (that is, not covered by the "trimmings") would be the | |
96 * rectangle described by the arguments (relative to the | |
97 * receiver's parent). | |
98 * </p> | |
99 * | |
100 * @param x the desired x coordinate of the client area | |
101 * @param y the desired y coordinate of the client area | |
102 * @param width the desired width of the client area | |
103 * @param height the desired height of the client area | |
104 * @return the required bounds to produce the given client area | |
105 * | |
106 * @exception SWTException <ul> | |
107 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
108 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
109 * </ul> | |
110 * | |
111 * @see #getClientArea | |
112 */ | |
113 public Rectangle computeTrim (int x, int y, int width, int height) { | |
114 checkWidget(); | |
115 int border = 0; | |
116 if (fixedHandle !is null) border += OS.gtk_container_get_border_width (cast(GtkContainer*)fixedHandle); | |
117 if (scrolledHandle !is null) border += OS.gtk_container_get_border_width (cast(GtkContainer*)scrolledHandle); | |
118 int trimX = x - border, trimY = y - border; | |
119 int trimWidth = width + (border * 2), trimHeight = height + (border * 2); | |
120 trimHeight += hScrollBarWidth (); | |
121 trimWidth += vScrollBarWidth (); | |
122 if (scrolledHandle !is null) { | |
123 if (OS.gtk_scrolled_window_get_shadow_type (cast(GtkScrolledWindow*)scrolledHandle) !is OS.GTK_SHADOW_NONE) { | |
124 auto style = OS.gtk_widget_get_style (cast(GtkWidget*)scrolledHandle); | |
125 int xthickness = OS.gtk_style_get_xthickness (style); | |
126 int ythickness = OS.gtk_style_get_ythickness (style); | |
127 trimX -= xthickness; | |
128 trimY -= ythickness; | |
129 trimWidth += xthickness * 2; | |
130 trimHeight += ythickness * 2; | |
131 } | |
132 } | |
133 return new Rectangle (trimX, trimY, trimWidth, trimHeight); | |
134 } | |
135 | |
136 ScrollBar createScrollBar (int style) { | |
137 if (scrolledHandle is null) return null; | |
138 ScrollBar bar = new ScrollBar (); | |
139 bar.parent = this; | |
140 bar.style = style; | |
141 bar.display = display; | |
142 bar.state |= HANDLE; | |
143 if ((style & SWT.H_SCROLL) !is 0) { | |
34 | 144 bar.handle = OS.GTK_SCROLLED_WINDOW_HSCROLLBAR (cast(GtkScrolledWindow*)scrolledHandle); |
145 bar.adjustmentHandle = OS.gtk_scrolled_window_get_hadjustment (cast(GtkScrolledWindow*)scrolledHandle); | |
31 | 146 } else { |
34 | 147 bar.handle = OS.GTK_SCROLLED_WINDOW_VSCROLLBAR (cast(GtkScrolledWindow*)scrolledHandle); |
31 | 148 bar.adjustmentHandle = OS.gtk_scrolled_window_get_vadjustment (cast(GtkScrolledWindow*)scrolledHandle); |
149 } | |
150 bar.hookEvents (); | |
151 bar.register (); | |
152 return bar; | |
153 } | |
154 | |
155 void createWidget (int index) { | |
156 super.createWidget (index); | |
157 if ((style & SWT.H_SCROLL) !is 0) horizontalBar = createScrollBar (SWT.H_SCROLL); | |
158 if ((style & SWT.V_SCROLL) !is 0) verticalBar = createScrollBar (SWT.V_SCROLL); | |
159 } | |
160 | |
161 void deregister () { | |
162 super.deregister (); | |
163 if (scrolledHandle !is null) display.removeWidget (cast(GtkWidget*)scrolledHandle); | |
164 } | |
165 | |
166 public int getBorderWidth () { | |
167 checkWidget(); | |
168 int border = 0; | |
169 if (fixedHandle !is null) border += OS.gtk_container_get_border_width (cast(GtkContainer*)fixedHandle); | |
170 if (scrolledHandle !is null) { | |
171 border += OS.gtk_container_get_border_width (cast(GtkContainer*)scrolledHandle); | |
172 if (OS.gtk_scrolled_window_get_shadow_type (cast(GtkScrolledWindow*)scrolledHandle) !is OS.GTK_SHADOW_NONE) { | |
173 border += OS.gtk_style_get_xthickness (OS.gtk_widget_get_style (cast(GtkWidget*)scrolledHandle)); | |
174 } | |
175 } | |
176 return border; | |
177 } | |
178 | |
179 /** | |
180 * Returns a rectangle which describes the area of the | |
181 * receiver which is capable of displaying data (that is, | |
182 * not covered by the "trimmings"). | |
183 * | |
184 * @return the client area | |
185 * | |
186 * @exception SWTException <ul> | |
187 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
188 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
189 * </ul> | |
190 * | |
191 * @see #computeTrim | |
192 */ | |
193 public Rectangle getClientArea () { | |
194 checkWidget (); | |
195 forceResize (); | |
196 auto clientHandle = clientHandle (); | |
197 int x = OS.GTK_WIDGET_X (clientHandle); | |
198 int y = OS.GTK_WIDGET_Y (clientHandle); | |
199 int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (clientHandle); | |
200 int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (clientHandle); | |
201 return new Rectangle (x, y, width, height); | |
202 } | |
203 /** | |
204 * Returns the receiver's horizontal scroll bar if it has | |
205 * one, and null if it does not. | |
206 * | |
207 * @return the horizontal scroll bar (or null) | |
208 * | |
209 * @exception SWTException <ul> | |
210 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
211 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
212 * </ul> | |
213 */ | |
214 public ScrollBar getHorizontalBar () { | |
215 checkWidget (); | |
216 return horizontalBar; | |
217 } | |
218 /** | |
219 * Returns the receiver's vertical scroll bar if it has | |
220 * one, and null if it does not. | |
221 * | |
222 * @return the vertical scroll bar (or null) | |
223 * | |
224 * @exception SWTException <ul> | |
225 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
226 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
227 * </ul> | |
228 */ | |
229 public ScrollBar getVerticalBar () { | |
230 checkWidget (); | |
231 return verticalBar; | |
232 } | |
233 | |
234 int /*long*/ gtk_scroll_event (GtkWidget* widget, GdkEventScroll* eventPtr) { | |
235 auto result = super.gtk_scroll_event (widget, eventPtr); | |
236 | |
237 /* | |
238 * Feature in GTK. Scrolled windows do not scroll if the scrollbars | |
239 * are hidden. This is not a bug, but is inconsistent with other platforms. | |
240 * The fix is to set the adjustment values directly. | |
241 */ | |
242 if ((state & CANVAS) !is 0) { | |
243 ScrollBar scrollBar; | |
244 GdkEventScroll* gdkEvent = new GdkEventScroll (); | |
245 memmove (gdkEvent, eventPtr, GdkEventScroll.sizeof); | |
246 if (gdkEvent.direction is OS.GDK_SCROLL_UP || gdkEvent.direction is OS.GDK_SCROLL_DOWN) { | |
247 scrollBar = verticalBar; | |
248 } else { | |
249 scrollBar = horizontalBar; | |
250 } | |
251 if (scrollBar !is null && !OS.GTK_WIDGET_VISIBLE (scrollBar.handle) && scrollBar.getEnabled()) { | |
252 GtkAdjustment* adjustment = new GtkAdjustment (); | |
253 memmove (adjustment, scrollBar.adjustmentHandle, GtkAdjustment.sizeof ); | |
254 /* Calculate wheel delta to match GTK+ 2.4 and higher */ | |
255 int wheel_delta = cast(int) Math.pow(adjustment.page_size, 2.0 / 3.0); | |
256 if (gdkEvent.direction is OS.GDK_SCROLL_UP || gdkEvent.direction is OS.GDK_SCROLL_LEFT) | |
257 wheel_delta = -wheel_delta; | |
258 int value = cast(int) Math.max(adjustment.lower, | |
259 Math.min(adjustment.upper - adjustment.page_size, adjustment.value + wheel_delta)); | |
260 OS.gtk_adjustment_set_value (scrollBar.adjustmentHandle, value); | |
261 return 1; | |
262 } | |
263 } | |
264 return result; | |
265 } | |
266 | |
267 int hScrollBarWidth() { | |
268 if (horizontalBar is null) return 0; | |
34 | 269 auto hBarHandle = OS.GTK_SCROLLED_WINDOW_HSCROLLBAR(cast(GtkScrolledWindow*)scrolledHandle); |
31 | 270 if (hBarHandle is null) return 0; |
271 GtkRequisition* requisition = new GtkRequisition(); | |
272 OS.gtk_widget_size_request(cast(GtkWidget*)hBarHandle, requisition); | |
34 | 273 int spacing = OS.GTK_SCROLLED_WINDOW_SCROLLBAR_SPACING(cast(GtkScrolledWindow*)scrolledHandle); |
31 | 274 return requisition.height + spacing; |
275 } | |
276 | |
277 bool sendLeaveNotify () { | |
278 return scrolledHandle !is null; | |
279 } | |
280 | |
281 void setOrientation () { | |
282 super.setOrientation (); | |
283 if ((style & SWT.RIGHT_TO_LEFT) !is 0) { | |
284 if (scrolledHandle !is null) { | |
33
27324bbbac70
changed to regenerated BCD bindings
Frank Benoit <benoit@tionex.de>
parents:
31
diff
changeset
|
285 OS.gtk_widget_set_direction (cast(GtkWidget*)scrolledHandle, OS.GTK_TEXT_DIR_RTL); |
31 | 286 } |
287 } | |
288 } | |
289 | |
290 bool setScrollBarVisible (ScrollBar bar, bool visible) { | |
291 if (scrolledHandle is null) return false; | |
33
27324bbbac70
changed to regenerated BCD bindings
Frank Benoit <benoit@tionex.de>
parents:
31
diff
changeset
|
292 int hsp, vsp; |
34 | 293 OS.gtk_scrolled_window_get_policy (cast(GtkScrolledWindow*)scrolledHandle, &hsp, &vsp); |
33
27324bbbac70
changed to regenerated BCD bindings
Frank Benoit <benoit@tionex.de>
parents:
31
diff
changeset
|
294 int policy = visible ? OS.GTK_POLICY_ALWAYS : OS.GTK_POLICY_NEVER; |
31 | 295 if ((bar.style & SWT.HORIZONTAL) !is 0) { |
296 if (hsp is policy) return false; | |
297 hsp = policy; | |
298 } else { | |
299 if (vsp is policy) return false; | |
300 vsp = policy; | |
301 } | |
34 | 302 OS.gtk_scrolled_window_set_policy (cast(GtkScrolledWindow*)scrolledHandle, hsp, vsp); |
31 | 303 bar.sendEvent (visible ? SWT.Show : SWT.Hide); |
304 sendEvent (SWT.Resize); | |
305 return true; | |
306 } | |
307 | |
308 void redrawBackgroundImage () { | |
309 } | |
310 | |
311 void redrawWidget (int x, int y, int width, int height, bool redrawAll, bool all, bool trim) { | |
312 super.redrawWidget (x, y, width, height, redrawAll, all, trim); | |
313 if ((OS.GTK_WIDGET_FLAGS (handle) & OS.GTK_REALIZED) is 0) return; | |
314 if (!trim) return; | |
315 auto topHandle = topHandle (), paintHandle = paintHandle (); | |
316 if (topHandle is paintHandle) return; | |
317 auto window = OS.GTK_WIDGET_WINDOW (topHandle); | |
318 GdkRectangle* rect = new GdkRectangle (); | |
319 if (redrawAll) { | |
320 rect.width = OS.GTK_WIDGET_WIDTH (topHandle); | |
321 rect.height = OS.GTK_WIDGET_HEIGHT (topHandle); | |
322 } else { | |
323 int destX, destY; | |
324 OS.gtk_widget_translate_coordinates (cast(GtkWidget*)paintHandle, topHandle, x, y, &destX, &destY); | |
325 rect.x = destX; | |
326 rect.y = destY; | |
327 rect.width = width; | |
328 rect.height = height; | |
329 } | |
330 OS.gdk_window_invalidate_rect (window, rect, all); | |
331 } | |
332 | |
333 void register () { | |
334 super.register (); | |
335 if (scrolledHandle !is null) display.addWidget (cast(GtkWidget*)scrolledHandle, this); | |
336 } | |
337 | |
338 void releaseHandle () { | |
339 super.releaseHandle (); | |
340 scrolledHandle = null; | |
341 } | |
342 | |
343 void releaseChildren (bool destroy) { | |
344 if (horizontalBar !is null) { | |
345 horizontalBar.release (false); | |
346 horizontalBar = null; | |
347 } | |
348 if (verticalBar !is null) { | |
349 verticalBar.release (false); | |
350 verticalBar = null; | |
351 } | |
352 super.releaseChildren (destroy); | |
353 } | |
354 | |
355 void resizeHandle (int width, int height) { | |
356 if (fixedHandle !is null) OS.gtk_widget_set_size_request (cast(GtkWidget*)fixedHandle, width, height); | |
357 OS.gtk_widget_set_size_request (scrolledHandle !is null ? cast(GtkWidget*)scrolledHandle : handle, width, height); | |
358 } | |
359 | |
360 void showWidget () { | |
361 super.showWidget (); | |
362 if (scrolledHandle !is null) OS.gtk_widget_show (cast(GtkWidget*)scrolledHandle); | |
363 } | |
364 | |
365 GtkWidget* topHandle () { | |
366 if (fixedHandle !is null) return fixedHandle; | |
34 | 367 if (scrolledHandle !is null) return scrolledHandle; |
31 | 368 return super.topHandle (); |
369 } | |
370 | |
371 void updateScrollBarValue (ScrollBar bar) { | |
372 redrawBackgroundImage (); | |
373 } | |
374 | |
375 int vScrollBarWidth() { | |
376 if (verticalBar is null) return 0; | |
34 | 377 auto vBarHandle = OS.GTK_SCROLLED_WINDOW_VSCROLLBAR(cast(GtkScrolledWindow*)scrolledHandle); |
31 | 378 if (vBarHandle is null) return 0; |
379 GtkRequisition* requisition = new GtkRequisition(); | |
380 OS.gtk_widget_size_request (cast(GtkWidget*)vBarHandle, requisition); | |
34 | 381 int spacing = OS.GTK_SCROLLED_WINDOW_SCROLLBAR_SPACING(cast(GtkScrolledWindow*)scrolledHandle); |
31 | 382 return requisition.width + spacing; |
383 } | |
384 } |