KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > widgets > Scale


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 package org.eclipse.swt.widgets;
12
13  
14 import org.eclipse.swt.internal.win32.*;
15 import org.eclipse.swt.*;
16 import org.eclipse.swt.graphics.*;
17 import org.eclipse.swt.events.*;
18
19 /**
20  * Instances of the receiver represent a selectable user
21  * interface object that present a range of continuous
22  * numeric values.
23  * <dl>
24  * <dt><b>Styles:</b></dt>
25  * <dd>HORIZONTAL, VERTICAL</dd>
26  * <dt><b>Events:</b></dt>
27  * <dd>Selection</dd>
28  * </dl>
29  * <p>
30  * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
31  * </p><p>
32  * <p>
33  * IMPORTANT: This class is intended to be subclassed <em>only</em>
34  * within the SWT implementation.
35  * </p>
36  */

37
38 public class Scale extends Control {
39     boolean ignoreResize;
40     static final int TrackBarProc;
41     static final TCHAR TrackBarClass = new TCHAR (0, OS.TRACKBAR_CLASS, true);
42     static {
43         WNDCLASS lpWndClass = new WNDCLASS ();
44         OS.GetClassInfo (0, TrackBarClass, lpWndClass);
45         TrackBarProc = lpWndClass.lpfnWndProc;
46         /*
47         * Feature in Windows. The track bar window class
48         * does not include CS_DBLCLKS. This mean that these
49         * controls will not get double click messages such as
50         * WM_LBUTTONDBLCLK. The fix is to register a new
51         * window class with CS_DBLCLKS.
52         *
53         * NOTE: Screen readers look for the exact class name
54         * of the control in order to provide the correct kind
55         * of assistance. Therefore, it is critical that the
56         * new window class have the same name. It is possible
57         * to register a local window class with the same name
58         * as a global class. Since bits that affect the class
59         * are being changed, it is possible that other native
60         * code, other than SWT, could create a control with
61         * this class name, and fail unexpectedly.
62         */

63         int hInstance = OS.GetModuleHandle (null);
64         int hHeap = OS.GetProcessHeap ();
65         lpWndClass.hInstance = hInstance;
66         lpWndClass.style &= ~OS.CS_GLOBALCLASS;
67         lpWndClass.style |= OS.CS_DBLCLKS;
68         int byteCount = TrackBarClass.length () * TCHAR.sizeof;
69         int lpszClassName = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
70         OS.MoveMemory (lpszClassName, TrackBarClass, byteCount);
71         lpWndClass.lpszClassName = lpszClassName;
72         OS.RegisterClass (lpWndClass);
73         OS.HeapFree (hHeap, 0, lpszClassName);
74     }
75
76 /**
77  * Constructs a new instance of this class given its parent
78  * and a style value describing its behavior and appearance.
79  * <p>
80  * The style value is either one of the style constants defined in
81  * class <code>SWT</code> which is applicable to instances of this
82  * class, or must be built by <em>bitwise OR</em>'ing together
83  * (that is, using the <code>int</code> "|" operator) two or more
84  * of those <code>SWT</code> style constants. The class description
85  * lists the style constants that are applicable to the class.
86  * Style bits are also inherited from superclasses.
87  * </p>
88  *
89  * @param parent a composite control which will be the parent of the new instance (cannot be null)
90  * @param style the style of control to construct
91  *
92  * @exception IllegalArgumentException <ul>
93  * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
94  * </ul>
95  * @exception SWTException <ul>
96  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
97  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
98  * </ul>
99  *
100  * @see SWT#HORIZONTAL
101  * @see SWT#VERTICAL
102  * @see Widget#checkSubclass
103  * @see Widget#getStyle
104  */

105 public Scale (Composite parent, int style) {
106     super (parent, checkStyle (style));
107 }
108
109 /**
110  * Adds the listener to the collection of listeners who will
111  * be notified when the user changes the receiver's value, by sending
112  * it one of the messages defined in the <code>SelectionListener</code>
113  * interface.
114  * <p>
115  * <code>widgetSelected</code> is called when the user changes the receiver's value.
116  * <code>widgetDefaultSelected</code> is not called.
117  * </p>
118  *
119  * @param listener the listener which should be notified
120  *
121  * @exception IllegalArgumentException <ul>
122  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
123  * </ul>
124  * @exception SWTException <ul>
125  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
126  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
127  * </ul>
128  *
129  * @see SelectionListener
130  * @see #removeSelectionListener
131  */

132 public void addSelectionListener(SelectionListener listener) {
133     checkWidget ();
134     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
135     TypedListener typedListener = new TypedListener (listener);
136     addListener (SWT.Selection,typedListener);
137     addListener (SWT.DefaultSelection,typedListener);
138 }
139
140 int callWindowProc (int hwnd, int msg, int wParam, int lParam) {
141     if (handle == 0) return 0;
142     return OS.CallWindowProc (TrackBarProc, hwnd, msg, wParam, lParam);
143 }
144
145 static int checkStyle (int style) {
146     return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
147 }
148
149 public Point computeSize (int wHint, int hHint, boolean changed) {
150     checkWidget ();
151     int border = getBorderWidth ();
152     int width = border * 2, height = border * 2;
153     RECT rect = new RECT ();
154     OS.SendMessage (handle, OS.TBM_GETTHUMBRECT, 0, rect);
155     if ((style & SWT.HORIZONTAL) != 0) {
156         width += OS.GetSystemMetrics (OS.SM_CXHSCROLL) * 10;
157         int scrollY = OS.GetSystemMetrics (OS.SM_CYHSCROLL);
158         height += (rect.top * 2) + scrollY + (scrollY / 3);
159     } else {
160         int scrollX = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
161         width += (rect.left * 2) + scrollX + (scrollX / 3);
162         height += OS.GetSystemMetrics (OS.SM_CYVSCROLL) * 10;
163     }
164     if (wHint != SWT.DEFAULT) width = wHint + (border * 2);
165     if (hHint != SWT.DEFAULT) height = hHint + (border * 2);
166     return new Point (width, height);
167 }
168
169 void createHandle () {
170     super.createHandle ();
171     state |= THEME_BACKGROUND | DRAW_BACKGROUND;
172     OS.SendMessage (handle, OS.TBM_SETRANGEMAX, 0, 100);
173     OS.SendMessage (handle, OS.TBM_SETPAGESIZE, 0, 10);
174     OS.SendMessage (handle, OS.TBM_SETTICFREQ, 10, 0);
175 }
176
177 int defaultForeground () {
178     return OS.GetSysColor (OS.COLOR_BTNFACE);
179 }
180
181 /**
182  * Returns the amount that the receiver's value will be
183  * modified by when the up/down (or right/left) arrows
184  * are pressed.
185  *
186  * @return the increment
187  *
188  * @exception SWTException <ul>
189  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
190  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
191  * </ul>
192  */

193 public int getIncrement () {
194     checkWidget ();
195     return OS.SendMessage (handle, OS.TBM_GETLINESIZE, 0, 0);
196 }
197
198 /**
199  * Returns the maximum value which the receiver will allow.
200  *
201  * @return the maximum
202  *
203  * @exception SWTException <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 getMaximum () {
209     checkWidget ();
210     return OS.SendMessage (handle, OS.TBM_GETRANGEMAX, 0, 0);
211 }
212
213 /**
214  * Returns the minimum value which the receiver will allow.
215  *
216  * @return the minimum
217  *
218  * @exception SWTException <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 getMinimum () {
224     checkWidget ();
225     return OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
226 }
227
228 /**
229  * Returns the amount that the receiver's value will be
230  * modified by when the page increment/decrement areas
231  * are selected.
232  *
233  * @return the page increment
234  *
235  * @exception SWTException <ul>
236  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
237  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
238  * </ul>
239  */

240 public int getPageIncrement () {
241     checkWidget ();
242     return OS.SendMessage (handle, OS.TBM_GETPAGESIZE, 0, 0);
243 }
244
245 /**
246  * Returns the 'selection', which is the receiver's position.
247  *
248  * @return the selection
249  *
250  * @exception SWTException <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 getSelection () {
256     checkWidget ();
257     return OS.SendMessage (handle, OS.TBM_GETPOS, 0, 0);
258 }
259
260 /**
261  * Removes the listener from the collection of listeners who will
262  * be notified when the user changes the receiver's value.
263  *
264  * @param listener the listener which should no longer be notified
265  *
266  * @exception IllegalArgumentException <ul>
267  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
268  * </ul>
269  * @exception SWTException <ul>
270  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
271  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
272  * </ul>
273  *
274  * @see SelectionListener
275  * @see #addSelectionListener
276  */

277 public void removeSelectionListener(SelectionListener listener) {
278     checkWidget ();
279     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
280     if (eventTable == null) return;
281     eventTable.unhook (SWT.Selection, listener);
282     eventTable.unhook (SWT.DefaultSelection,listener);
283 }
284
285 void setBackgroundImage (int hImage) {
286     super.setBackgroundImage (hImage);
287     /*
288     * Bug in Windows. Changing the background color of the Scale
289     * widget and calling InvalidateRect() still draws with the old
290     * color. The fix is to send a fake WM_SIZE event to cause
291     * it to redraw with the new background color.
292     */

293     ignoreResize = true;
294     OS.SendMessage (handle, OS.WM_SIZE, 0, 0);
295     ignoreResize = false;
296 }
297
298 void setBackgroundPixel (int pixel) {
299     super.setBackgroundPixel (pixel);
300     /*
301     * Bug in Windows. Changing the background color of the Scale
302     * widget and calling InvalidateRect() still draws with the old
303     * color. The fix is to send a fake WM_SIZE event to cause
304     * it to redraw with the new background color.
305     */

306     ignoreResize = true;
307     OS.SendMessage (handle, OS.WM_SIZE, 0, 0);
308     ignoreResize = false;
309 }
310
311 /**
312  * Sets the amount that the receiver's value will be
313  * modified by when the up/down (or right/left) arrows
314  * are pressed to the argument, which must be at least
315  * one.
316  *
317  * @param increment the new increment (must be greater than zero)
318  *
319  * @exception SWTException <ul>
320  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
321  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
322  * </ul>
323  */

324 public void setIncrement (int increment) {
325     checkWidget ();
326     if (increment < 1) return;
327     int minimum = OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
328     int maximum = OS.SendMessage (handle, OS.TBM_GETRANGEMAX, 0, 0);
329     if (increment > maximum - minimum) return;
330     OS.SendMessage (handle, OS.TBM_SETLINESIZE, 0, increment);
331 }
332
333 /**
334  * Sets the maximum value that the receiver will allow. This new
335  * value will be ignored if it is not greater than the receiver's current
336  * minimum value. If the new maximum is applied then the receiver's
337  * selection value will be adjusted if necessary to fall within its new range.
338  *
339  * @param value the new maximum, which must be greater than the current minimum
340  *
341  * @exception SWTException <ul>
342  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
343  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
344  * </ul>
345  */

346 public void setMaximum (int value) {
347     checkWidget ();
348     int minimum = OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
349     if (0 <= minimum && minimum < value) {
350         OS.SendMessage (handle, OS.TBM_SETRANGEMAX, 1, value);
351     }
352 }
353
354 /**
355  * Sets the minimum value that the receiver will allow. This new
356  * value will be ignored if it is negative or is not less than the receiver's
357  * current maximum value. If the new minimum is applied then the receiver's
358  * selection value will be adjusted if necessary to fall within its new range.
359  *
360  * @param value the new minimum, which must be nonnegative and less than the current maximum
361  *
362  * @exception SWTException <ul>
363  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
364  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
365  * </ul>
366  */

367 public void setMinimum (int value) {
368     checkWidget ();
369     int maximum = OS.SendMessage (handle, OS.TBM_GETRANGEMAX, 0, 0);
370     if (0 <= value && value < maximum) {
371         OS.SendMessage (handle, OS.TBM_SETRANGEMIN, 1, value);
372     }
373 }
374
375 /**
376  * Sets the amount that the receiver's value will be
377  * modified by when the page increment/decrement areas
378  * are selected to the argument, which must be at least
379  * one.
380  *
381  * @param pageIncrement the page increment (must be greater than zero)
382  *
383  * @exception SWTException <ul>
384  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
385  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
386  * </ul>
387  */

388 public void setPageIncrement (int pageIncrement) {
389     checkWidget ();
390     if (pageIncrement < 1) return;
391     int minimum = OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
392     int maximum = OS.SendMessage (handle, OS.TBM_GETRANGEMAX, 0, 0);
393     if (pageIncrement > maximum - minimum) return;
394     OS.SendMessage (handle, OS.TBM_SETPAGESIZE, 0, pageIncrement);
395     OS.SendMessage (handle, OS.TBM_SETTICFREQ, pageIncrement, 0);
396 }
397
398 /**
399  * Sets the 'selection', which is the receiver's value,
400  * to the argument which must be greater than or equal to zero.
401  *
402  * @param value the new selection (must be zero or greater)
403  *
404  * @exception SWTException <ul>
405  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
406  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
407  * </ul>
408  */

409 public void setSelection (int value) {
410     checkWidget ();
411     OS.SendMessage (handle, OS.TBM_SETPOS, 1, value);
412 }
413
414 int widgetStyle () {
415     int bits = super.widgetStyle () | OS.WS_TABSTOP | OS.TBS_BOTH | OS.TBS_AUTOTICKS;
416     if ((style & SWT.HORIZONTAL) != 0) return bits | OS.TBS_HORZ | OS.TBS_DOWNISLEFT;
417     return bits | OS.TBS_VERT;
418 }
419
420 TCHAR windowClass () {
421     return TrackBarClass;
422 }
423
424 int windowProc () {
425     return TrackBarProc;
426 }
427
428 LRESULT WM_PAINT (int wParam, int lParam) {
429     /*
430     * Bug in Windows. For some reason, when WM_CTLCOLORSTATIC
431     * is used to implement transparency and returns a NULL brush,
432     * Windows doesn't always draw the track bar. It seems that
433     * it is drawn correctly the first time. It is possible that
434     * Windows double buffers the control and the double buffer
435     * strategy fails when WM_CTLCOLORSTATIC returns unexpected
436     * results. The fix is to send a fake WM_SIZE to force it
437     * to redraw every time there is a WM_PAINT.
438     */

439     boolean fixPaint = findBackgroundControl () != null;
440     if (!fixPaint) {
441         if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
442             Control control = findThemeControl ();
443             fixPaint = control != null;
444         }
445     }
446     if (fixPaint) {
447         boolean redraw = drawCount == 0 && OS.IsWindowVisible (handle);
448         if (redraw) OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
449         ignoreResize = true;
450         OS.SendMessage (handle, OS.WM_SIZE, 0, 0);
451         ignoreResize = false;
452         if (redraw) {
453             OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
454             OS.InvalidateRect (handle, null, false);
455         }
456     }
457     return super.WM_PAINT (wParam, lParam);
458 }
459
460 LRESULT WM_SIZE (int wParam, int lParam) {
461     if (ignoreResize) return null;
462     return super.WM_SIZE (wParam, lParam);
463 }
464
465 LRESULT wmScrollChild (int wParam, int lParam) {
466     
467     /* Do nothing when scrolling is ending */
468     int code = wParam & 0xFFFF;
469     switch (code) {
470         case OS.TB_ENDTRACK:
471         case OS.TB_THUMBPOSITION:
472             return null;
473     }
474
475     Event event = new Event ();
476     /*
477     * This code is intentionally commented. The event
478     * detail field is not currently supported on all
479     * platforms.
480     */

481 // switch (code) {
482
// case OS.TB_TOP: event.detail = SWT.HOME; break;
483
// case OS.TB_BOTTOM: event.detail = SWT.END; break;
484
// case OS.TB_LINEDOWN: event.detail = SWT.ARROW_DOWN; break;
485
// case OS.TB_LINEUP: event.detail = SWT.ARROW_UP; break;
486
// case OS.TB_PAGEDOWN: event.detail = SWT.PAGE_DOWN; break;
487
// case OS.TB_PAGEUP: event.detail = SWT.PAGE_UP; break;
488
// }
489

490     /*
491     * Send the event because WM_HSCROLL and WM_VSCROLL
492     * are sent from a modal message loop in windows that
493     * is active when the user is scrolling.
494     */

495     sendEvent (SWT.Selection, event);
496     // widget could be disposed at this point
497
return null;
498 }
499
500 }
501
Popular Tags