Mercurial > projects > dwt-mac
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 } |