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.Scale;
14 
15 import java.lang.all;
16 
17 
18 import org.eclipse.swt.widgets.Control;
19 import org.eclipse.swt.widgets.Composite;
20 import org.eclipse.swt.widgets.TypedListener;
21 import org.eclipse.swt.SWT;
22 import org.eclipse.swt.internal.gtk.OS;
23 import org.eclipse.swt.graphics.Point;
24 import org.eclipse.swt.events.SelectionListener;
25 
26 /**
27  * Instances of the receiver represent a selectable user
28  * interface object that present a range of continuous
29  * numeric values.
30  * <dl>
31  * <dt><b>Styles:</b></dt>
32  * <dd>HORIZONTAL, VERTICAL</dd>
33  * <dt><b>Events:</b></dt>
34  * <dd>Selection</dd>
35  * </dl>
36  * <p>
37  * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
38  * </p><p>
39  * <p>
40  * IMPORTANT: This class is intended to be subclassed <em>only</em>
41  * within the SWT implementation.
42  * </p>
43  *
44  * @see <a href="http://www.eclipse.org/swt/snippets/#scale">Scale snippets</a>
45  * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
46  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
47  */
48 public class Scale : Control {
49 
50     alias Control.computeSize computeSize;
51 
52 
53 /**
54  * Constructs a new instance of this class given its parent
55  * and a style value describing its behavior and appearance.
56  * <p>
57  * The style value is either one of the style constants defined in
58  * class <code>SWT</code> which is applicable to instances of this
59  * class, or must be built by <em>bitwise OR</em>'ing together
60  * (that is, using the <code>int</code> "|" operator) two or more
61  * of those <code>SWT</code> style constants. The class description
62  * lists the style constants that are applicable to the class.
63  * Style bits are also inherited from superclasses.
64  * </p>
65  *
66  * @param parent a composite control which will be the parent of the new instance (cannot be null)
67  * @param style the style of control to construct
68  *
69  * @exception IllegalArgumentException <ul>
70  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
71  * </ul>
72  * @exception SWTException <ul>
73  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
74  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
75  * </ul>
76  *
77  * @see SWT#HORIZONTAL
78  * @see SWT#VERTICAL
79  * @see Widget#checkSubclass
80  * @see Widget#getStyle
81  */
82 public this (Composite parent, int style) {
83     super (parent, checkStyle (style));
84 }
85 
86 /**
87  * Adds the listener to the collection of listeners who will
88  * be notified when the user changes the receiver's value, by sending
89  * it one of the messages defined in the <code>SelectionListener</code>
90  * interface.
91  * <p>
92  * <code>widgetSelected</code> is called when the user changes the receiver's value.
93  * <code>widgetDefaultSelected</code> is not called.
94  * </p>
95  *
96  * @param listener the listener which should be notified
97  *
98  * @exception IllegalArgumentException <ul>
99  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
100  * </ul>
101  * @exception SWTException <ul>
102  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
103  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
104  * </ul>
105  *
106  * @see SelectionListener
107  * @see #removeSelectionListener
108  */
109 public void addSelectionListener (SelectionListener listener) {
110     checkWidget ();
111     if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
112     TypedListener typedListener = new TypedListener (listener);
113     addListener (SWT.Selection,typedListener);
114     addListener (SWT.DefaultSelection,typedListener);
115 }
116 
117 static int checkStyle (int style) {
118     return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
119 }
120 
121 public override Point computeSize (int wHint, int hHint, bool changed) {
122     checkWidget();
123     if (wHint !is SWT.DEFAULT && wHint < 0) wHint = 0;
124     if (hHint !is SWT.DEFAULT && hHint < 0) hHint = 0;
125     Point size = computeNativeSize(handle, wHint, hHint, changed);
126     if ((style & SWT.HORIZONTAL) !is 0) {
127         if (wHint is SWT.DEFAULT) size.x = 2 * size.x;
128     } else {
129         if (hHint is SWT.DEFAULT) size.y = 2 * size.y;
130     }
131     return size;
132 }
133 
134 override void createHandle (int index) {
135     state |= HANDLE | THEME_BACKGROUND;
136     fixedHandle = cast(GtkWidget*)OS.g_object_new (display.gtk_fixed_get_type (), null);
137     if (fixedHandle is null) error (SWT.ERROR_NO_HANDLES);
138     OS.gtk_fixed_set_has_window (cast(GtkFixed*)fixedHandle, true);
139     auto hAdjustment = OS.gtk_adjustment_new (0, 0, 100, 1, 10, 0);
140     if (hAdjustment is null) error (SWT.ERROR_NO_HANDLES);
141     if ((style & SWT.HORIZONTAL) !is 0) {
142         handle = cast(GtkWidget*)OS.gtk_hscale_new (cast(GtkAdjustment*)hAdjustment);
143     } else {
144         handle = cast(GtkWidget*)OS.gtk_vscale_new (cast(GtkAdjustment*)hAdjustment);
145     }
146     if (handle is null) error (SWT.ERROR_NO_HANDLES);
147     OS.gtk_container_add (cast(GtkContainer*)fixedHandle, handle);
148     OS.gtk_scale_set_digits (cast(GtkScale*)handle, 0);
149     OS.gtk_scale_set_draw_value (cast(GtkScale*)handle, false);
150 }
151 
152 override void hookEvents () {
153     super.hookEvents ();
154     OS.g_signal_connect_closure (handle, OS.value_changed.ptr, display.closures [VALUE_CHANGED], false);
155 }
156 
157 /**
158  * Returns the amount that the receiver's value will be
159  * modified by when the up/down (or right/left) arrows
160  * are pressed.
161  *
162  * @return the increment
163  *
164  * @exception SWTException <ul>
165  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
166  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
167  * </ul>
168  */
169 public int getIncrement () {
170     checkWidget ();
171     auto hAdjustment = OS.gtk_range_get_adjustment (cast(GtkRange*)handle);
172     return cast(int) hAdjustment.step_increment;
173 }
174 
175 /**
176  * Returns the maximum value which the receiver will allow.
177  *
178  * @return the maximum
179  *
180  * @exception SWTException <ul>
181  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
182  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
183  * </ul>
184  */
185 public int getMaximum () {
186     checkWidget ();
187     auto hAdjustment = OS.gtk_range_get_adjustment (cast(GtkRange*)handle);
188     return cast(int) hAdjustment.upper;
189 }
190 
191 /**
192  * Returns the minimum value which the receiver will allow.
193  *
194  * @return the minimum
195  *
196  * @exception SWTException <ul>
197  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
198  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
199  * </ul>
200  */
201 public int getMinimum () {
202     checkWidget ();
203     auto hAdjustment = OS.gtk_range_get_adjustment (cast(GtkRange*)handle);
204     return cast(int) hAdjustment.lower;
205 }
206 
207 /**
208  * Returns the amount that the receiver's value will be
209  * modified by when the page increment/decrement areas
210  * are selected.
211  *
212  * @return the page increment
213  *
214  * @exception SWTException <ul>
215  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
216  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
217  * </ul>
218  */
219 public int getPageIncrement () {
220     checkWidget ();
221     auto hAdjustment = OS.gtk_range_get_adjustment (cast(GtkRange*)handle);
222     return cast(int) hAdjustment.page_increment;
223 }
224 
225 /**
226  * Returns the 'selection', which is the receiver's position.
227  *
228  * @return the selection
229  *
230  * @exception SWTException <ul>
231  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
232  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
233  * </ul>
234  */
235 public int getSelection () {
236     checkWidget ();
237     auto hAdjustment = OS.gtk_range_get_adjustment (cast(GtkRange*)handle);
238     return cast(int) hAdjustment.value;
239 }
240 
241 override
242 int gtk_value_changed (int adjustment) {
243     postEvent (SWT.Selection);
244     return 0;
245 }
246 
247 /**
248  * Removes the listener from the collection of listeners who will
249  * be notified when the user changes the receiver's value.
250  *
251  * @param listener the listener which should no longer be notified
252  *
253  * @exception IllegalArgumentException <ul>
254  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
255  * </ul>
256  * @exception SWTException <ul>
257  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
258  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
259  * </ul>
260  *
261  * @see SelectionListener
262  * @see #addSelectionListener
263  */
264 public void removeSelectionListener (SelectionListener listener) {
265     checkWidget ();
266     if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
267     if (eventTable is null) return;
268     eventTable.unhook (SWT.Selection, listener);
269     eventTable.unhook (SWT.DefaultSelection,listener);
270 }
271 
272 /**
273  * Sets the amount that the receiver's value will be
274  * modified by when the up/down (or right/left) arrows
275  * are pressed to the argument, which must be at least
276  * one.
277  *
278  * @param increment the new increment (must be greater than zero)
279  *
280  * @exception SWTException <ul>
281  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
282  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
283  * </ul>
284  */
285 public void setIncrement (int value) {
286     checkWidget ();
287     if (value < 1) return;
288     OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
289     OS.gtk_range_set_increments (cast(GtkRange*)handle, value, getPageIncrement ());
290     OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
291 }
292 
293 /**
294  * Sets the maximum value that the receiver will allow.  This new
295  * value will be ignored if it is not greater than the receiver's current
296  * minimum value.  If the new maximum is applied then the receiver's
297  * selection value will be adjusted if necessary to fall within its new range.
298  *
299  * @param value the new maximum, which must be greater than the current minimum
300  *
301  * @exception SWTException <ul>
302  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
303  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
304  * </ul>
305  */
306 public void setMaximum (int value) {
307     checkWidget ();
308     int minimum = getMinimum();
309     if (value <= minimum) return;
310     OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
311     OS.gtk_range_set_range (cast(GtkRange*)handle, minimum, value);
312     OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
313 }
314 
315 /**
316  * Sets the minimum value that the receiver will allow.  This new
317  * value will be ignored if it is negative or is not less than the receiver's
318  * current maximum value.  If the new minimum is applied then the receiver's
319  * selection value will be adjusted if necessary to fall within its new range.
320  *
321  * @param value the new minimum, which must be nonnegative and less than the current maximum
322  *
323  * @exception SWTException <ul>
324  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
325  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
326  * </ul>
327  */
328 public void setMinimum (int value) {
329     checkWidget ();
330     if (value < 0) return;
331     int maximum = getMaximum ();
332     if (value >= maximum) return;
333     OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
334     OS.gtk_range_set_range (cast(GtkRange*)handle, value, maximum);
335     OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
336 }
337 
338 /**
339  * Sets the amount that the receiver's value will be
340  * modified by when the page increment/decrement areas
341  * are selected to the argument, which must be at least
342  * one.
343  *
344  * @param pageIncrement the page increment (must be greater than zero)
345  *
346  * @exception SWTException <ul>
347  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
348  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
349  * </ul>
350  */
351 public void setPageIncrement (int value) {
352     checkWidget ();
353     if (value < 1) return;
354     OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
355     OS.gtk_range_set_increments (cast(GtkRange*)handle, getIncrement (), value);
356     OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
357 }
358 
359 /**
360  * Sets the 'selection', which is the receiver's value,
361  * to the argument which must be greater than or equal to zero.
362  *
363  * @param value the new selection (must be zero or greater)
364  *
365  * @exception SWTException <ul>
366  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
367  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
368  * </ul>
369  */
370 public void setSelection (int value) {
371     checkWidget ();
372     OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
373     OS.gtk_range_set_value (cast(GtkRange*)handle, value);
374     OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, udVALUE_CHANGED);
375 }
376 
377 }