1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module org.eclipse.swt.widgets.ScrollBar;
14 
15 import java.lang.all;
16 
17 import org.eclipse.swt.widgets.Control;
18 import org.eclipse.swt.widgets.Scrollable;
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.graphics.Point;
21 import org.eclipse.swt.internal.gtk.OS;
22 import org.eclipse.swt.events.SelectionListener;
23 import org.eclipse.swt.events.SelectionEvent;
24 import org.eclipse.swt.widgets.Scrollable;
25 import org.eclipse.swt.widgets.Widget;
26 import org.eclipse.swt.widgets.Event;
27 import org.eclipse.swt.widgets.TypedListener;
28 
29 
30 /**
31  * Instances of this class are selectable user interface
32  * objects that represent a range of positive, numeric values.
33  * <p>
34  * At any given moment, a given scroll bar will have a
35  * single 'selection' that is considered to be its
36  * value, which is constrained to be within the range of
37  * values the scroll bar represents (that is, between its
38  * <em>minimum</em> and <em>maximum</em> values).
39  * </p><p>
40  * Typically, scroll bars will be made up of five areas:
41  * <ol>
42  * <li>an arrow button for decrementing the value</li>
43  * <li>a page decrement area for decrementing the value by a larger amount</li>
44  * <li>a <em>thumb</em> for modifying the value by mouse dragging</li>
45  * <li>a page increment area for incrementing the value by a larger amount</li>
46  * <li>an arrow button for incrementing the value</li>
47  * </ol>
48  * Based on their style, scroll bars are either <code>HORIZONTAL</code>
49  * (which have a left facing button for decrementing the value and a
50  * right facing button for incrementing it) or <code>VERTICAL</code>
51  * (which have an upward facing button for decrementing the value
52  * and a downward facing buttons for incrementing it).
53  * </p><p>
54  * On some platforms, the size of the scroll bar's thumb can be
55  * varied relative to the magnitude of the range of values it
56  * represents (that is, relative to the difference between its
57  * maximum and minimum values). Typically, this is used to
58  * indicate some proportional value such as the ratio of the
59  * visible area of a document to the total amount of space that
60  * it would take to display it. SWT supports setting the thumb
61  * size even if the underlying platform does not, but in this
62  * case the appearance of the scroll bar will not change.
63  * </p><p>
64  * Scroll bars are created by specifying either <code>H_SCROLL</code>,
65  * <code>V_SCROLL</code> or both when creating a <code>Scrollable</code>.
66  * They are accessed from the <code>Scrollable</code> using
67  * <code>getHorizontalBar</code> and <code>getVerticalBar</code>.
68  * </p><p>
69  * Note: Scroll bars are not Controls.  On some platforms, scroll bars
70  * that appear as part of some standard controls such as a text or list
71  * have no operating system resources and are not children of the control.
72  * For this reason, scroll bars are treated specially.  To create a control
73  * that looks like a scroll bar but has operating system resources, use
74  * <code>Slider</code>.
75  * </p>
76  * <dl>
77  * <dt><b>Styles:</b></dt>
78  * <dd>HORIZONTAL, VERTICAL</dd>
79  * <dt><b>Events:</b></dt>
80  * <dd>Selection</dd>
81  * </dl>
82  * <p>
83  * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
84  * </p><p>
85  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
86  * </p>
87  *
88  * @see Slider
89  * @see Scrollable
90  * @see Scrollable#getHorizontalBar
91  * @see Scrollable#getVerticalBar
92  * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
93  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
94  */
95 public class ScrollBar : Widget {
96     Scrollable parent;
97     GtkAdjustment* adjustmentHandle;
98     int detail;
99     bool dragSent;
100 
101 this () {
102 }
103 
104 /**
105 * Creates a new instance of the widget.
106 */
107 this (Scrollable parent, int style) {
108     super (parent, checkStyle (style));
109     this.parent = parent;
110     createWidget (0);
111 }
112 
113 /**
114  * Adds the listener to the collection of listeners who will
115  * be notified when the user changes the receiver's value, by sending
116  * it one of the messages defined in the <code>SelectionListener</code>
117  * interface.
118  * <p>
119  * When <code>widgetSelected</code> is called, the event object detail field contains one of the following values:
120  * <code>SWT.NONE</code> - for the end of a drag.
121  * <code>SWT.DRAG</code>.
122  * <code>SWT.HOME</code>.
123  * <code>SWT.END</code>.
124  * <code>SWT.ARROW_DOWN</code>.
125  * <code>SWT.ARROW_UP</code>.
126  * <code>SWT.PAGE_DOWN</code>.
127  * <code>SWT.PAGE_UP</code>.
128  * <code>widgetDefaultSelected</code> is not called.
129  * </p>
130  *
131  * @param listener the listener which should be notified when the user changes the receiver's value
132  *
133  * @exception IllegalArgumentException <ul>
134  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
135  * </ul>
136  * @exception SWTException <ul>
137  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
138  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
139  * </ul>
140  *
141  * @see SelectionListener
142  * @see #removeSelectionListener
143  * @see SelectionEvent
144  */
145 public void addSelectionListener (SelectionListener listener) {
146     checkWidget ();
147     if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
148     TypedListener typedListener = new TypedListener (listener);
149     addListener (SWT.Selection,typedListener);
150     addListener (SWT.DefaultSelection,typedListener);
151 }
152 
153 static int checkStyle (int style) {
154     return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
155 }
156 
157 override void deregister () {
158     super.deregister ();
159     if (adjustmentHandle !is null) display.removeWidget (cast(GtkWidget*)adjustmentHandle);
160 }
161 
162 void destroyHandle () {
163     super.destroyWidget ();
164 }
165 
166 override
167 void destroyWidget () {
168     parent.destroyScrollBar (this);
169     releaseHandle ();
170     //parent.sendEvent (SWT.Resize);
171 }
172 
173 /**
174  * Returns <code>true</code> if the receiver is enabled, and
175  * <code>false</code> otherwise. A disabled control is typically
176  * not selectable from the user interface and draws with an
177  * inactive or "grayed" look.
178  *
179  * @return the receiver's enabled state
180  *
181  * @exception SWTException <ul>
182  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
183  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
184  * </ul>
185  *
186  * @see #isEnabled
187  */
188 public bool getEnabled () {
189     checkWidget ();
190     if (handle !is null) return OS.GTK_WIDGET_SENSITIVE (handle);
191     return true;
192 }
193 
194 /**
195  * Returns the amount that the receiver's value will be
196  * modified by when the up/down (or right/left) arrows
197  * are pressed.
198  *
199  * @return the increment
200  *
201  * @exception SWTException <ul>
202  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
203  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
204  * </ul>
205  */
206 public int getIncrement () {
207     checkWidget ();
208     return cast(int)adjustmentHandle.step_increment;
209 }
210 
211 /**
212  * Returns the maximum value which the receiver will allow.
213  *
214  * @return the maximum
215  *
216  * @exception SWTException <ul>
217  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
218  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
219  * </ul>
220  */
221 public int getMaximum () {
222     checkWidget ();
223     return cast(int)adjustmentHandle.upper;
224 }
225 
226 /**
227  * Returns the minimum value which the receiver will allow.
228  *
229  * @return the minimum
230  *
231  * @exception SWTException <ul>
232  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
233  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
234  * </ul>
235  */
236 public int getMinimum () {
237     checkWidget ();
238     return cast(int)adjustmentHandle.lower;
239 }
240 
241 /**
242  * Returns the amount that the receiver's value will be
243  * modified by when the page increment/decrement areas
244  * are selected.
245  *
246  * @return the page increment
247  *
248  * @exception SWTException <ul>
249  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
250  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
251  * </ul>
252  */
253 public int getPageIncrement () {
254     checkWidget ();
255     return cast(int)adjustmentHandle.page_increment;
256 }
257 
258 /**
259  * Returns the receiver's parent, which must be a Scrollable.
260  *
261  * @return the receiver's parent
262  *
263  * @exception SWTException <ul>
264  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
265  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
266  * </ul>
267  */
268 public Scrollable getParent () {
269     checkWidget ();
270     return parent;
271 }
272 
273 /**
274  * Returns the single 'selection' that is the receiver's value.
275  *
276  * @return the selection
277  *
278  * @exception SWTException <ul>
279  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
280  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
281  * </ul>
282  */
283 public int getSelection () {
284     checkWidget ();
285     return cast(int)adjustmentHandle.value;
286 }
287 
288 /**
289  * Returns a point describing the receiver's size. The
290  * x coordinate of the result is the width of the receiver.
291  * The y coordinate of the result is the height of the
292  * receiver.
293  *
294  * @return the receiver's size
295  *
296  * @exception SWTException <ul>
297  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
298  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
299  * </ul>
300  */
301 public Point getSize () {
302     checkWidget ();
303     if (handle is null) return new Point (0,0);
304     GtkRequisition requisition;
305     OS.gtk_widget_size_request (handle, &requisition);
306     return new Point (requisition.width, requisition.height);
307 }
308 
309 /**
310  * Returns the size of the receiver's thumb relative to the
311  * difference between its maximum and minimum values.
312  *
313  * @return the thumb value
314  *
315  * @exception SWTException <ul>
316  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
317  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
318  * </ul>
319  *
320  * @see ScrollBar
321  */
322 public int getThumb () {
323     checkWidget ();
324     return cast(int)adjustmentHandle.page_size;
325 }
326 
327 /**
328  * Returns <code>true</code> if the receiver is visible, and
329  * <code>false</code> otherwise.
330  * <p>
331  * If one of the receiver's ancestors is not visible or some
332  * other condition makes the receiver not visible, this method
333  * may still indicate that it is considered visible even though
334  * it may not actually be showing.
335  * </p>
336  *
337  * @return the receiver's visibility state
338  *
339  * @exception SWTException <ul>
340  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
341  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
342  * </ul>
343  */
344 public bool getVisible () {
345     checkWidget ();
346     auto scrolledHandle = parent.scrolledHandle;
347     int hsp, vsp;
348     OS.gtk_scrolled_window_get_policy (scrolledHandle, &hsp, &vsp);
349     if ((style & SWT.HORIZONTAL) !is 0) {
350         return hsp !is OS.GTK_POLICY_NEVER;
351     } else {
352         return vsp !is OS.GTK_POLICY_NEVER;
353     }
354 }
355 
356 override int gtk_button_press_event (GtkWidget* widget, GdkEventButton* eventPtr) {
357     auto result = super.gtk_button_press_event (widget, eventPtr);
358     if (result !is 0) return result;
359     detail = OS.GTK_SCROLL_NONE;
360     dragSent = false;
361     return result;
362 }
363 
364 override int gtk_change_value (GtkWidget* widget, int scroll, double value1, void* user_data) {
365     detail = scroll;
366     return 0;
367 }
368 
369 override int gtk_value_changed (int adjustment) {
370     Event event = new Event ();
371     dragSent = detail is OS.GTK_SCROLL_JUMP;
372     switch (detail) {
373         case OS.GTK_SCROLL_NONE:            event.detail = SWT.NONE; break;
374         case OS.GTK_SCROLL_JUMP:            event.detail = SWT.DRAG; break;
375         case OS.GTK_SCROLL_START:           event.detail = SWT.HOME; break;
376         case OS.GTK_SCROLL_END:             event.detail = SWT.END; break;
377         case OS.GTK_SCROLL_PAGE_DOWN:
378         case OS.GTK_SCROLL_PAGE_RIGHT:
379         case OS.GTK_SCROLL_PAGE_FORWARD:    event.detail = SWT.PAGE_DOWN; break;
380         case OS.GTK_SCROLL_PAGE_UP:
381         case OS.GTK_SCROLL_PAGE_LEFT:
382         case OS.GTK_SCROLL_PAGE_BACKWARD:   event.detail = SWT.PAGE_UP; break;
383         case OS.GTK_SCROLL_STEP_DOWN:
384         case OS.GTK_SCROLL_STEP_RIGHT:
385         case OS.GTK_SCROLL_STEP_FORWARD:    event.detail = SWT.ARROW_DOWN; break;
386         case OS.GTK_SCROLL_STEP_UP:
387         case OS.GTK_SCROLL_STEP_LEFT:
388         case OS.GTK_SCROLL_STEP_BACKWARD:   event.detail = SWT.ARROW_UP; break;
389         default:
390     }
391     detail = OS.GTK_SCROLL_NONE;
392     if (!dragSent) detail = OS.GTK_SCROLL_NONE;
393     postEvent (SWT.Selection, event);
394     parent.updateScrollBarValue (this);
395     return 0;
396 }
397 
398 override int gtk_event_after (GtkWidget* widget, GdkEvent* gdkEvent) {
399     switch (gdkEvent.type) {
400         case OS.GDK_BUTTON_RELEASE: {
401             GdkEventButton* gdkEventButton = cast(GdkEventButton*)gdkEvent;
402             if (gdkEventButton.button is 1 && detail is SWT.DRAG) {
403                 if (!dragSent) {
404                     Event event = new Event ();
405                     event.detail = SWT.DRAG;
406                     postEvent (SWT.Selection, event);
407                 }
408                 postEvent (SWT.Selection);
409             }
410             detail = OS.GTK_SCROLL_NONE;
411             dragSent = false;
412             break;
413         }
414         default:
415     }
416     return super.gtk_event_after (widget, gdkEvent);
417 }
418 
419 override void hookEvents () {
420     super.hookEvents ();
421     if (OS.GTK_VERSION >= OS.buildVERSION (2, 6, 0)) {
422         OS.g_signal_connect_closure (handle, OS.change_value.ptr, display.closures [CHANGE_VALUE], false);
423     }
424     OS.g_signal_connect_closure (adjustmentHandle, OS.value_changed.ptr, display.closures [VALUE_CHANGED], false);
425     OS.g_signal_connect_closure_by_id (handle, display.signalIds [EVENT_AFTER], 0, display.closures [EVENT_AFTER], false);
426     OS.g_signal_connect_closure_by_id (handle, display.signalIds [BUTTON_PRESS_EVENT], 0, display.closures [BUTTON_PRESS_EVENT], false);
427 }
428 
429 /**
430  * Returns <code>true</code> if the receiver is enabled and all
431  * of the receiver's ancestors are enabled, and <code>false</code>
432  * otherwise. A disabled control is typically not selectable from the
433  * user interface and draws with an inactive or "grayed" look.
434  *
435  * @return the receiver's enabled state
436  *
437  * @exception SWTException <ul>
438  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
439  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
440  * </ul>
441  *
442  * @see #getEnabled
443  */
444 public bool isEnabled () {
445     checkWidget ();
446     return getEnabled () && getParent ().getEnabled ();
447 }
448 
449 /**
450  * Returns <code>true</code> if the receiver is visible and all
451  * of the receiver's ancestors are visible and <code>false</code>
452  * otherwise.
453  *
454  * @return the receiver's visibility state
455  *
456  * @exception SWTException <ul>
457  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
458  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
459  * </ul>
460  *
461  * @see #getVisible
462  */
463 public bool isVisible () {
464     checkWidget ();
465     return getVisible () && getParent ().isVisible ();
466 }
467 
468 override void register () {
469     super.register ();
470     if (adjustmentHandle !is null) display.addWidget (cast(GtkWidget*)adjustmentHandle, this);
471 }
472 
473 override
474 void releaseHandle () {
475     super.releaseHandle ();
476     parent = null;
477 }
478 
479 override void releaseParent () {
480     super.releaseParent ();
481     if (parent.horizontalBar is this) parent.horizontalBar = null;
482     if (parent.verticalBar is this) parent.verticalBar = null;
483 }
484 
485 override void releaseWidget () {
486     super.releaseWidget ();
487     //parent = null;
488 }
489 
490 /**
491  * Removes the listener from the collection of listeners who will
492  * be notified when the user changes the receiver's value.
493  *
494  * @param listener the listener which should no longer be notified
495  *
496  * @exception IllegalArgumentException <ul>
497  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
498  * </ul>
499  * @exception SWTException <ul>
500  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
501  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
502  * </ul>
503  *
504  * @see SelectionListener
505  * @see #addSelectionListener
506  */
507 public void removeSelectionListener (SelectionListener listener) {
508     checkWidget ();
509     if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
510     if (eventTable is null) return;
511     eventTable.unhook (SWT.Selection, listener);
512     eventTable.unhook (SWT.DefaultSelection,listener);
513 }
514 
515 /**
516  * Enables the receiver if the argument is <code>true</code>,
517  * and disables it otherwise. A disabled control is typically
518  * not selectable from the user interface and draws with an
519  * inactive or "grayed" look.
520  *
521  * @param enabled the new enabled state
522  *
523  * @exception SWTException <ul>
524  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
525  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
526  * </ul>
527  */
528 public void setEnabled (bool enabled) {
529     checkWidget ();
530     if (handle !is null) OS.gtk_widget_set_sensitive (handle, enabled);
531 }
532 
533 /**
534  * Sets the amount that the receiver's value will be
535  * modified by when the up/down (or right/left) arrows
536  * are pressed to the argument, which must be at least
537  * one.
538  *
539  * @param value the new increment (must be greater than zero)
540  *
541  * @exception SWTException <ul>
542  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
543  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
544  * </ul>
545  */
546 public void setIncrement (int value) {
547     checkWidget ();
548     if (value < 1) return;
549     adjustmentHandle.step_increment = cast(float) value;
550     OS.g_signal_handlers_block_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
551     OS.gtk_adjustment_changed (adjustmentHandle);
552     OS.g_signal_handlers_unblock_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
553 }
554 
555 /**
556  * Sets the maximum. If this value is negative or less than or
557  * equal to the minimum, the value is ignored. If necessary, first
558  * the thumb and then the selection are adjusted to fit within the
559  * new range.
560  *
561  * @param value the new maximum
562  *
563  * @exception SWTException <ul>
564  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
565  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
566  * </ul>
567  */
568 public void setMaximum (int value) {
569     checkWidget ();
570     int minimum = cast(int)adjustmentHandle.lower;
571     if (value <= minimum) return;
572     adjustmentHandle.upper = value;
573     adjustmentHandle.page_size = Math.min (adjustmentHandle.page_size, value - minimum);
574     adjustmentHandle.value = Math.min (adjustmentHandle.value, (value - adjustmentHandle.page_size));
575     OS.g_signal_handlers_block_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
576     OS.gtk_adjustment_changed (adjustmentHandle);
577     OS.g_signal_handlers_unblock_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
578 }
579 
580 /**
581  * Sets the minimum value. If this value is negative or greater
582  * than or equal to the maximum, the value is ignored. If necessary,
583  * first the thumb and then the selection are adjusted to fit within
584  * the new range.
585  *
586  * @param value the new minimum
587  *
588  * @exception SWTException <ul>
589  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
590  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
591  * </ul>
592  */
593 public void setMinimum (int value) {
594     checkWidget ();
595     if (value < 0) return;
596     int maximum = cast(int)adjustmentHandle.upper;
597     if (value >= maximum) return;
598     adjustmentHandle.lower = value;
599     adjustmentHandle.page_size = Math.min (adjustmentHandle.page_size, maximum - value);
600     adjustmentHandle.value = Math.max (adjustmentHandle.value, value);
601     OS.g_signal_handlers_block_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
602     OS.gtk_adjustment_changed (adjustmentHandle);
603     OS.g_signal_handlers_unblock_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
604 }
605 
606 override
607 void setOrientation () {
608     super.setOrientation ();
609     if ((parent.style & SWT.MIRRORED) !is 0) {
610         if ((parent.state & CANVAS) !is 0) {
611             if ((style & SWT.HORIZONTAL) !is 0) {
612                 OS.gtk_range_set_inverted (handle, true);
613             }
614         }
615     }
616 }
617 
618 /**
619  * Sets the amount that the receiver's value will be
620  * modified by when the page increment/decrement areas
621  * are selected to the argument, which must be at least
622  * one.
623  *
624  * @param value the page increment (must be greater than zero)
625  *
626  * @exception SWTException <ul>
627  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
628  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
629  * </ul>
630  */
631 public void setPageIncrement (int value) {
632     checkWidget ();
633     if (value < 1) return;
634     adjustmentHandle.page_increment = cast(float) value;
635     OS.g_signal_handlers_block_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
636     OS.gtk_adjustment_changed (adjustmentHandle);
637     OS.g_signal_handlers_unblock_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
638 }
639 
640 /**
641  * Sets the single <em>selection</em> that is the receiver's
642  * value to the argument which must be greater than or equal
643  * to zero.
644  *
645  * @param selection the new selection (must be zero or greater)
646  *
647  * @exception SWTException <ul>
648  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
649  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
650  * </ul>
651  */
652 public void setSelection (int value) {
653     checkWidget ();
654     value = Math.min (value, getMaximum() - getThumb());
655     OS.g_signal_handlers_block_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
656     OS.gtk_adjustment_set_value (adjustmentHandle, value);
657     OS.g_signal_handlers_unblock_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
658 }
659 
660 /**
661  * Sets the size of the receiver's thumb relative to the
662  * difference between its maximum and minimum values.  This new
663  * value will be ignored if it is less than one, and will be
664  * clamped if it exceeds the receiver's current range.
665  *
666  * @param value the new thumb value, which must be at least one and not
667  * larger than the size of the current range
668  *
669  * @exception SWTException <ul>
670  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
671  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
672  * </ul>
673  */
674 public void setThumb (int value) {
675     checkWidget ();
676     if (value < 1) return;
677     value = Math.min (value, cast(int)(adjustmentHandle.upper - adjustmentHandle.lower));
678     adjustmentHandle.page_size = cast(double) value;
679     adjustmentHandle.value = Math.min (adjustmentHandle.value, (adjustmentHandle.upper - value));
680     OS.g_signal_handlers_block_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
681     OS.gtk_adjustment_changed (adjustmentHandle);
682     OS.g_signal_handlers_unblock_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
683 }
684 
685 /**
686  * Sets the receiver's selection, minimum value, maximum
687  * value, thumb, increment and page increment all at once.
688  * <p>
689  * Note: This is similar to setting the values individually
690  * using the appropriate methods, but may be implemented in a
691  * more efficient fashion on some platforms.
692  * </p>
693  *
694  * @param selection the new selection value
695  * @param minimum the new minimum value
696  * @param maximum the new maximum value
697  * @param thumb the new thumb value
698  * @param increment the new increment value
699  * @param pageIncrement the new pageIncrement value
700  *
701  * @exception SWTException <ul>
702  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
703  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
704  * </ul>
705  */
706 public void setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) {
707     checkWidget ();
708     if (minimum < 0) return;
709     if (maximum < 0) return;
710     if (thumb < 1) return;
711     if (increment < 1) return;
712     if (pageIncrement < 1) return;
713     thumb = Math.min (thumb, maximum - minimum);
714     adjustmentHandle.lower = minimum;
715     adjustmentHandle.upper = maximum;
716     adjustmentHandle.step_increment = increment;
717     adjustmentHandle.page_increment = pageIncrement;
718     adjustmentHandle.page_size = thumb;
719     adjustmentHandle.value = Math.min (Math.max (selection, minimum), maximum - thumb);
720     OS.g_signal_handlers_block_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
721     OS.gtk_adjustment_changed (adjustmentHandle);
722     OS.gtk_adjustment_value_changed (adjustmentHandle);
723     OS.g_signal_handlers_unblock_matched (adjustmentHandle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
724 }
725 
726 /**
727  * Marks the receiver as visible if the argument is <code>true</code>,
728  * and marks it invisible otherwise.
729  * <p>
730  * If one of the receiver's ancestors is not visible or some
731  * other condition makes the receiver not visible, marking
732  * it visible may not actually cause it to be displayed.
733  * </p>
734  *
735  * @param visible the new visibility state
736  *
737  * @exception SWTException <ul>
738  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
739  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
740  * </ul>
741  */
742 public void setVisible (bool visible) {
743     checkWidget ();
744     if (parent.setScrollBarVisible (this, visible)) {
745         sendEvent (visible ? SWT.Show : SWT.Hide);
746         parent.sendEvent (SWT.Resize);
747     }
748 }
749 
750 }