comparison dwt/widgets/Slider.d @ 0:380af2bdd8e5

Upload of whole dwt tree
author Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com>
date Sat, 09 Aug 2008 17:00:02 +0200
parents
children 649b8e223d5a
comparison
equal deleted inserted replaced
-1:000000000000 0:380af2bdd8e5
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.Slider;
12
13 import dwt.dwthelper.utils;
14
15
16 import dwt.DWT;
17 import dwt.DWTException;
18 import dwt.events.SelectionEvent;
19 import dwt.events.SelectionListener;
20 import dwt.graphics.Point;
21 import dwt.internal.cocoa.NSRect;
22 import dwt.internal.cocoa.NSScroller;
23 import dwt.internal.cocoa.OS;
24 import dwt.internal.cocoa.SWTScroller;
25
26 /**
27 * Instances of this class are selectable user interface
28 * objects that represent a range of positive, numeric values.
29 * <p>
30 * At any given moment, a given slider will have a
31 * single 'selection' that is considered to be its
32 * value, which is constrained to be within the range of
33 * values the slider represents (that is, between its
34 * <em>minimum</em> and <em>maximum</em> values).
35 * </p><p>
36 * Typically, sliders will be made up of five areas:
37 * <ol>
38 * <li>an arrow button for decrementing the value</li>
39 * <li>a page decrement area for decrementing the value by a larger amount</li>
40 * <li>a <em>thumb</em> for modifying the value by mouse dragging</li>
41 * <li>a page increment area for incrementing the value by a larger amount</li>
42 * <li>an arrow button for incrementing the value</li>
43 * </ol>
44 * Based on their style, sliders are either <code>HORIZONTAL</code>
45 * (which have a left facing button for decrementing the value and a
46 * right facing button for incrementing it) or <code>VERTICAL</code>
47 * (which have an upward facing button for decrementing the value
48 * and a downward facing buttons for incrementing it).
49 * </p><p>
50 * On some platforms, the size of the slider's thumb can be
51 * varied relative to the magnitude of the range of values it
52 * represents (that is, relative to the difference between its
53 * maximum and minimum values). Typically, this is used to
54 * indicate some proportional value such as the ratio of the
55 * visible area of a document to the total amount of space that
56 * it would take to display it. DWT supports setting the thumb
57 * size even if the underlying platform does not, but in this
58 * case the appearance of the slider will not change.
59 * </p>
60 * <dl>
61 * <dt><b>Styles:</b></dt>
62 * <dd>HORIZONTAL, VERTICAL</dd>
63 * <dt><b>Events:</b></dt>
64 * <dd>Selection</dd>
65 * </dl>
66 * <p>
67 * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
68 * </p><p>
69 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
70 * </p>
71 *
72 * @see ScrollBar
73 */
74 public class Slider extends Control {
75 bool dragging;
76 int minimum, maximum, thumb;
77 int increment = 1;
78 int pageIncrement = 10;
79
80 /**
81 * Constructs a new instance of this class given its parent
82 * and a style value describing its behavior and appearance.
83 * <p>
84 * The style value is either one of the style constants defined in
85 * class <code>DWT</code> which is applicable to instances of this
86 * class, or must be built by <em>bitwise OR</em>'ing together
87 * (that is, using the <code>int</code> "|" operator) two or more
88 * of those <code>DWT</code> style constants. The class description
89 * lists the style constants that are applicable to the class.
90 * Style bits are also inherited from superclasses.
91 * </p>
92 *
93 * @param parent a composite control which will be the parent of the new instance (cannot be null)
94 * @param style the style of control to construct
95 *
96 * @exception IllegalArgumentException <ul>
97 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
98 * </ul>
99 * @exception DWTException <ul>
100 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
101 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
102 * </ul>
103 *
104 * @see DWT#HORIZONTAL
105 * @see DWT#VERTICAL
106 * @see Widget#checkSubclass
107 * @see Widget#getStyle
108 */
109 public Slider (Composite parent, int style) {
110 super (parent, checkStyle (style));
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>DWT.NONE</code> - for the end of a drag.
121 * <code>DWT.DRAG</code>.
122 * <code>DWT.HOME</code>.
123 * <code>DWT.END</code>.
124 * <code>DWT.ARROW_DOWN</code>.
125 * <code>DWT.ARROW_UP</code>.
126 * <code>DWT.PAGE_DOWN</code>.
127 * <code>DWT.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 DWTException <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 (DWT.ERROR_NULL_ARGUMENT);
148 TypedListener typedListener = new TypedListener(listener);
149 addListener(DWT.Selection,typedListener);
150 addListener(DWT.DefaultSelection,typedListener);
151 }
152
153 static int checkStyle (int style) {
154 return checkBits (style, DWT.HORIZONTAL, DWT.VERTICAL, 0, 0, 0, 0);
155 }
156
157 public Point computeSize (int wHint, int hHint, bool changed) {
158 checkWidget();
159 int width = 0, height = 0;
160 if ((style & DWT.HORIZONTAL) !is 0) {
161 height = (int)NSScroller.scrollerWidth();
162 width = height * 10;
163 } else {
164 width = (int)NSScroller.scrollerWidth();
165 height = width * 10;
166 }
167 if (wHint !is DWT.DEFAULT) width = wHint;
168 if (hHint !is DWT.DEFAULT) height = hHint;
169 return new Point (width, height);
170 }
171
172 void createHandle () {
173 NSScroller widget = (NSScroller)new SWTScroller().alloc();
174 NSRect rect = new NSRect();
175 if ((style & DWT.HORIZONTAL) !is 0) {
176 rect.width = 1;
177 } else {
178 rect.height = 1;
179 }
180 widget.initWithFrame(rect);
181 widget.setEnabled(true);
182 widget.setTarget(widget);
183 widget.setAction(OS.sel_sendSelection);
184 widget.setTag(jniRef);
185 view = widget;
186 parent.contentView().addSubview_(widget);
187 updateBar(0, minimum, maximum, thumb);
188 }
189
190 void createWidget () {
191 maximum = 100;
192 thumb = 10;
193 super.createWidget();
194 }
195
196 /**
197 * Returns the amount that the receiver's value will be
198 * modified by when the up/down (or right/left) arrows
199 * are pressed.
200 *
201 * @return the increment
202 *
203 * @exception DWTException <ul>
204 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
205 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
206 * </ul>
207 */
208 public int getIncrement () {
209 checkWidget();
210 return increment;
211 }
212
213 /**
214 * Returns the maximum value which the receiver will allow.
215 *
216 * @return the maximum
217 *
218 * @exception DWTException <ul>
219 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
220 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
221 * </ul>
222 */
223 public int getMaximum () {
224 checkWidget();
225 return maximum;
226 }
227
228 /**
229 * Returns the minimum value which the receiver will allow.
230 *
231 * @return the minimum
232 *
233 * @exception DWTException <ul>
234 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
235 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
236 * </ul>
237 */
238 public int getMinimum () {
239 checkWidget();
240 return minimum;
241 }
242
243 /**
244 * Returns the amount that the receiver's value will be
245 * modified by when the page increment/decrement areas
246 * are selected.
247 *
248 * @return the page increment
249 *
250 * @exception DWTException <ul>
251 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
252 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
253 * </ul>
254 */
255 public int getPageIncrement () {
256 checkWidget();
257 return pageIncrement;
258 }
259
260 /**
261 * Returns the 'selection', which is the receiver's value.
262 *
263 * @return the selection
264 *
265 * @exception DWTException <ul>
266 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
267 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
268 * </ul>
269 */
270 public int getSelection () {
271 checkWidget();
272 NSScroller widget = (NSScroller)view;
273 float value = widget.floatValue();
274 return (int)((maximum - thumb - minimum) * value + minimum);
275 }
276
277 /**
278 * Returns the size of the receiver's thumb relative to the
279 * difference between its maximum and minimum values.
280 *
281 * @return the thumb value
282 *
283 * @exception DWTException <ul>
284 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
285 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
286 * </ul>
287 */
288 public int getThumb () {
289 checkWidget();
290 return thumb;
291 }
292
293 /**
294 * Removes the listener from the collection of listeners who will
295 * be notified when the user changes the receiver's value.
296 *
297 * @param listener the listener which should no longer be notified
298 *
299 * @exception IllegalArgumentException <ul>
300 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
301 * </ul>
302 * @exception DWTException <ul>
303 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
304 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
305 * </ul>
306 *
307 * @see SelectionListener
308 * @see #addSelectionListener
309 */
310 public void removeSelectionListener(SelectionListener listener) {
311 checkWidget();
312 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
313 if (eventTable is null) return;
314 eventTable.unhook(DWT.Selection, listener);
315 eventTable.unhook(DWT.DefaultSelection,listener);
316 }
317
318 void sendSelection () {
319 Event event = new Event();
320 int hitPart = ((NSScroller)view).hitPart();
321 int value = getSelection ();
322 switch (hitPart) {
323 case OS.NSScrollerDecrementLine:
324 event.detail = DWT.ARROW_UP;
325 value -= increment;
326 break;
327 case OS.NSScrollerDecrementPage:
328 value -= pageIncrement;
329 event.detail = DWT.PAGE_UP;
330 break;
331 case OS.NSScrollerIncrementLine:
332 value += increment;
333 event.detail = DWT.PAGE_DOWN;
334 break;
335 case OS.NSScrollerIncrementPage:
336 value += pageIncrement;
337 event.detail = DWT.ARROW_DOWN;
338 break;
339 case OS.NSScrollerKnob:
340 event.detail = DWT.DRAG;
341 break;
342 }
343 if (event.detail !is DWT.DRAG) {
344 setSelection(value);
345 }
346 sendEvent(DWT.Selection, event);
347 }
348
349 /**
350 * Sets the amount that the receiver's value will be
351 * modified by when the up/down (or right/left) arrows
352 * are pressed to the argument, which must be at least
353 * one.
354 *
355 * @param value the new increment (must be greater than zero)
356 *
357 * @exception DWTException <ul>
358 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
359 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
360 * </ul>
361 */
362 public void setIncrement (int value) {
363 checkWidget();
364 if (value < 1) return;
365 increment = value;
366 }
367
368 /**
369 * Sets the maximum. If this value is negative or less than or
370 * equal to the minimum, the value is ignored. If necessary, first
371 * the thumb and then the selection are adjusted to fit within the
372 * new range.
373 *
374 * @param value the new maximum, which must be greater than the current minimum
375 *
376 * @exception DWTException <ul>
377 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
378 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
379 * </ul>
380 */
381 public void setMaximum (int value) {
382 checkWidget();
383 if (value < 0) return;
384 if (value <= minimum) return;
385 if (value - minimum < thumb) {
386 thumb = value - minimum;
387 }
388 int selection = Math.max(minimum, Math.min (getSelection (), value - thumb));
389 this.maximum = value;
390 updateBar(selection, minimum, value, thumb);
391 }
392
393 /**
394 * Sets the minimum value. If this value is negative or greater
395 * than or equal to the maximum, the value is ignored. If necessary,
396 * first the thumb and then the selection are adjusted to fit within
397 * the new range.
398 *
399 * @param value the new minimum
400 *
401 * @exception DWTException <ul>
402 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
403 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
404 * </ul>
405 */
406 public void setMinimum (int value) {
407 checkWidget();
408 if (value < 0) return;
409 if (value >= maximum) return;
410 if (maximum - value < thumb) {
411 thumb = maximum - value;
412 }
413 int selection = Math.min(maximum - thumb, Math.max (getSelection (), value));
414 this.minimum = value;
415 updateBar(selection, value, maximum, thumb);
416 }
417
418 /**
419 * Sets the amount that the receiver's value will be
420 * modified by when the page increment/decrement areas
421 * are selected to the argument, which must be at least
422 * one.
423 *
424 * @param value the page increment (must be greater than zero)
425 *
426 * @exception DWTException <ul>
427 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
428 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
429 * </ul>
430 */
431 public void setPageIncrement (int value) {
432 checkWidget();
433 if (value < 1) return;
434 pageIncrement = value;
435 }
436
437 /**
438 * Sets the 'selection', which is the receiver's
439 * value, to the argument which must be greater than or equal
440 * to zero.
441 *
442 * @param value the new selection (must be zero or greater)
443 *
444 * @exception DWTException <ul>
445 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
446 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
447 * </ul>
448 */
449 public void setSelection (int value) {
450 checkWidget();
451 updateBar(value, minimum, maximum, thumb);
452 }
453
454 void updateBar(int selection, int minimum, int maximum, int thumb) {
455 NSScroller widget = (NSScroller)view;
456 selection = Math.max(minimum, Math.min(maximum - thumb, selection));
457 float fraction = minimum is maximum ? 1 : (float)(selection - minimum) / (maximum - thumb - minimum);
458 float knob = minimum is maximum ? 1 : (float)(thumb - minimum) / (maximum - minimum);
459 widget.setFloatValue(fraction, knob);
460 }
461
462 /**
463 * Sets the size of the receiver's thumb relative to the
464 * difference between its maximum and minimum values. This new
465 * value will be ignored if it is less than one, and will be
466 * clamped if it exceeds the receiver's current range.
467 *
468 * @param value the new thumb value, which must be at least one and not
469 * larger than the size of the current range
470 *
471 * @exception DWTException <ul>
472 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
473 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
474 * </ul>
475 */
476 public void setThumb (int value) {
477 checkWidget();
478 if (value < 1) return;
479 value = Math.min (value, maximum - minimum);
480 this.thumb = value;
481 updateBar(getSelection(), minimum, maximum, value);
482 }
483
484 /**
485 * Sets the receiver's selection, minimum value, maximum
486 * value, thumb, increment and page increment all at once.
487 * <p>
488 * Note: This is similar to setting the values individually
489 * using the appropriate methods, but may be implemented in a
490 * more efficient fashion on some platforms.
491 * </p>
492 *
493 * @param selection the new selection value
494 * @param minimum the new minimum value
495 * @param maximum the new maximum value
496 * @param thumb the new thumb value
497 * @param increment the new increment value
498 * @param pageIncrement the new pageIncrement value
499 *
500 * @exception DWTException <ul>
501 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
502 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
503 * </ul>
504 */
505 public void setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) {
506 checkWidget();
507 if (minimum < 0) return;
508 if (maximum < 0) return;
509 if (thumb < 1) return;
510 if (increment < 1) return;
511 if (pageIncrement < 1) return;
512 thumb = Math.min (thumb, maximum - minimum);
513 this.increment = increment;
514 this.pageIncrement = pageIncrement;
515 updateBar(selection, minimum, maximum, thumb);
516 }
517
518 }