KickJava   Java API By Example, From Geeks To Geeks.

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


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 this class are selectable user interface
21  * objects that represent a range of positive, numeric values.
22  * <p>
23  * At any given moment, a given slider will have a
24  * single 'selection' that is considered to be its
25  * value, which is constrained to be within the range of
26  * values the slider represents (that is, between its
27  * <em>minimum</em> and <em>maximum</em> values).
28  * </p><p>
29  * Typically, sliders will be made up of five areas:
30  * <ol>
31  * <li>an arrow button for decrementing the value</li>
32  * <li>a page decrement area for decrementing the value by a larger amount</li>
33  * <li>a <em>thumb</em> for modifying the value by mouse dragging</li>
34  * <li>a page increment area for incrementing the value by a larger amount</li>
35  * <li>an arrow button for incrementing the value</li>
36  * </ol>
37  * Based on their style, sliders are either <code>HORIZONTAL</code>
38  * (which have a left facing button for decrementing the value and a
39  * right facing button for incrementing it) or <code>VERTICAL</code>
40  * (which have an upward facing button for decrementing the value
41  * and a downward facing buttons for incrementing it).
42  * </p><p>
43  * On some platforms, the size of the slider's thumb can be
44  * varied relative to the magnitude of the range of values it
45  * represents (that is, relative to the difference between its
46  * maximum and minimum values). Typically, this is used to
47  * indicate some proportional value such as the ratio of the
48  * visible area of a document to the total amount of space that
49  * it would take to display it. SWT supports setting the thumb
50  * size even if the underlying platform does not, but in this
51  * case the appearance of the slider will not change.
52  * </p>
53  * <dl>
54  * <dt><b>Styles:</b></dt>
55  * <dd>HORIZONTAL, VERTICAL</dd>
56  * <dt><b>Events:</b></dt>
57  * <dd>Selection</dd>
58  * </dl>
59  * <p>
60  * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
61  * </p><p>
62  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
63  * </p>
64  *
65  * @see ScrollBar
66  */

67 public class Slider extends Control {
68     int increment, pageIncrement;
69     boolean ignoreFocus;
70     static final int ScrollBarProc;
71     static final TCHAR ScrollBarClass = new TCHAR (0, "SCROLLBAR", true);
72     static {
73         WNDCLASS lpWndClass = new WNDCLASS ();
74         OS.GetClassInfo (0, ScrollBarClass, lpWndClass);
75         ScrollBarProc = lpWndClass.lpfnWndProc;
76     }
77
78 /**
79  * Constructs a new instance of this class given its parent
80  * and a style value describing its behavior and appearance.
81  * <p>
82  * The style value is either one of the style constants defined in
83  * class <code>SWT</code> which is applicable to instances of this
84  * class, or must be built by <em>bitwise OR</em>'ing together
85  * (that is, using the <code>int</code> "|" operator) two or more
86  * of those <code>SWT</code> style constants. The class description
87  * lists the style constants that are applicable to the class.
88  * Style bits are also inherited from superclasses.
89  * </p>
90  *
91  * @param parent a composite control which will be the parent of the new instance (cannot be null)
92  * @param style the style of control to construct
93  *
94  * @exception IllegalArgumentException <ul>
95  * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
96  * </ul>
97  * @exception SWTException <ul>
98  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
99  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
100  * </ul>
101  *
102  * @see SWT#HORIZONTAL
103  * @see SWT#VERTICAL
104  * @see Widget#checkSubclass
105  * @see Widget#getStyle
106  */

107 public Slider (Composite parent, int style) {
108     super (parent, checkStyle (style));
109 }
110
111 /**
112  * Adds the listener to the collection of listeners who will
113  * be notified when the user changes the receiver's value, by sending
114  * it one of the messages defined in the <code>SelectionListener</code>
115  * interface.
116  * <p>
117  * When <code>widgetSelected</code> is called, the event object detail field contains one of the following values:
118  * <code>SWT.NONE</code> - for the end of a drag.
119  * <code>SWT.DRAG</code>.
120  * <code>SWT.HOME</code>.
121  * <code>SWT.END</code>.
122  * <code>SWT.ARROW_DOWN</code>.
123  * <code>SWT.ARROW_UP</code>.
124  * <code>SWT.PAGE_DOWN</code>.
125  * <code>SWT.PAGE_UP</code>.
126  * <code>widgetDefaultSelected</code> is not called.
127  * </p>
128  *
129  * @param listener the listener which should be notified when the user changes the receiver's value
130  *
131  * @exception IllegalArgumentException <ul>
132  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
133  * </ul>
134  * @exception SWTException <ul>
135  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
136  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
137  * </ul>
138  *
139  * @see SelectionListener
140  * @see #removeSelectionListener
141  * @see SelectionEvent
142  */

143 public void addSelectionListener (SelectionListener listener) {
144     checkWidget ();
145     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
146     TypedListener typedListener = new TypedListener(listener);
147     addListener (SWT.Selection,typedListener);
148     addListener (SWT.DefaultSelection,typedListener);
149 }
150
151 int callWindowProc (int hwnd, int msg, int wParam, int lParam) {
152     if (handle == 0) return 0;
153     /*
154     * Feature in Windows. Windows runs a modal message
155     * loop when the user drags a scroll bar. This means
156     * that mouse down events won't get delivered until
157     * after the loop finishes. The fix is to run any
158     * deferred messages, including mouse down messages
159     * before calling the scroll bar window proc.
160     */

161     switch (msg) {
162         case OS.WM_LBUTTONDOWN:
163         case OS.WM_LBUTTONDBLCLK:
164             display.runDeferredEvents ();
165     }
166     return OS.CallWindowProc (ScrollBarProc, hwnd, msg, wParam, lParam);
167 }
168
169 static int checkStyle (int style) {
170     return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
171 }
172
173 public Point computeSize (int wHint, int hHint, boolean changed) {
174     checkWidget ();
175     int border = getBorderWidth ();
176     int width = border * 2, height = border * 2;
177     if ((style & SWT.HORIZONTAL) != 0) {
178         width += OS.GetSystemMetrics (OS.SM_CXHSCROLL) * 10;
179         height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
180     } else {
181         width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
182         height += OS.GetSystemMetrics (OS.SM_CYVSCROLL) * 10;
183     }
184     if (wHint != SWT.DEFAULT) width = wHint + (border * 2);
185     if (hHint != SWT.DEFAULT) height = hHint + (border * 2);
186     return new Point (width, height);
187 }
188
189 void createWidget () {
190     super.createWidget ();
191     increment = 1;
192     pageIncrement = 10;
193     /*
194     * Set the initial values of the maximum
195     * to 100 and the thumb to 10. Note that
196     * info.nPage needs to be 11 in order to
197     * get a thumb that is 10.
198     */

199     SCROLLINFO info = new SCROLLINFO ();
200     info.cbSize = SCROLLINFO.sizeof;
201     info.fMask = OS.SIF_ALL;
202     info.nMax = 100;
203     info.nPage = 11;
204     OS.SetScrollInfo (handle, OS.SB_CTL, info, true);
205 }
206
207 int defaultBackground () {
208     return OS.GetSysColor (OS.COLOR_SCROLLBAR);
209 }
210
211 int defaultForeground () {
212     return OS.GetSysColor (OS.COLOR_BTNFACE);
213 }
214
215 void enableWidget (boolean enabled) {
216     super.enableWidget (enabled);
217     if (!OS.IsWinCE) {
218         int flags = enabled ? OS.ESB_ENABLE_BOTH : OS.ESB_DISABLE_BOTH;
219         OS.EnableScrollBar (handle, OS.SB_CTL, flags);
220     }
221     if (enabled) {
222         state &= ~DISABLED;
223     } else {
224         state |= DISABLED;
225     }
226 }
227
228 public boolean getEnabled () {
229     checkWidget ();
230     return (state & DISABLED) == 0;
231 }
232
233 /**
234  * Returns the amount that the receiver's value will be
235  * modified by when the up/down (or right/left) arrows
236  * are pressed.
237  *
238  * @return the increment
239  *
240  * @exception SWTException <ul>
241  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
242  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
243  * </ul>
244  */

245 public int getIncrement () {
246     checkWidget ();
247     return increment;
248 }
249
250 /**
251  * Returns the maximum value which the receiver will allow.
252  *
253  * @return the maximum
254  *
255  * @exception SWTException <ul>
256  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
257  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
258  * </ul>
259  */

260 public int getMaximum () {
261     checkWidget ();
262     SCROLLINFO info = new SCROLLINFO ();
263     info.cbSize = SCROLLINFO.sizeof;
264     info.fMask = OS.SIF_RANGE;
265     OS.GetScrollInfo (handle, OS.SB_CTL, info);
266     return info.nMax;
267 }
268
269 /**
270  * Returns the minimum value which the receiver will allow.
271  *
272  * @return the minimum
273  *
274  * @exception SWTException <ul>
275  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
276  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
277  * </ul>
278  */

279 public int getMinimum () {
280     checkWidget ();
281     SCROLLINFO info = new SCROLLINFO ();
282     info.cbSize = SCROLLINFO.sizeof;
283     info.fMask = OS.SIF_RANGE;
284     OS.GetScrollInfo (handle, OS.SB_CTL, info);
285     return info.nMin;
286 }
287
288 /**
289  * Returns the amount that the receiver's value will be
290  * modified by when the page increment/decrement areas
291  * are selected.
292  *
293  * @return the page increment
294  *
295  * @exception SWTException <ul>
296  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
297  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
298  * </ul>
299  */

300 public int getPageIncrement () {
301     checkWidget ();
302     return pageIncrement;
303 }
304
305 /**
306  * Returns the 'selection', which is the receiver's value.
307  *
308  * @return the selection
309  *
310  * @exception SWTException <ul>
311  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
312  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
313  * </ul>
314  */

315 public int getSelection () {
316     checkWidget ();
317     SCROLLINFO info = new SCROLLINFO ();
318     info.cbSize = SCROLLINFO.sizeof;
319     info.fMask = OS.SIF_POS;
320     OS.GetScrollInfo (handle, OS.SB_CTL, info);
321     return info.nPos;
322 }
323
324 /**
325  * Returns the size of the receiver's thumb relative to the
326  * difference between its maximum and minimum values.
327  *
328  * @return the thumb value
329  *
330  * @exception SWTException <ul>
331  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
332  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
333  * </ul>
334  */

335 public int getThumb () {
336     checkWidget ();
337     SCROLLINFO info = new SCROLLINFO ();
338     info.cbSize = SCROLLINFO.sizeof;
339     info.fMask = OS.SIF_PAGE;
340     OS.GetScrollInfo (handle, OS.SB_CTL, info);
341     if (info.nPage != 0) --info.nPage;
342     return info.nPage;
343 }
344
345 /**
346  * Removes the listener from the collection of listeners who will
347  * be notified when the user changes the receiver's value.
348  *
349  * @param listener the listener which should no longer be notified
350  *
351  * @exception IllegalArgumentException <ul>
352  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
353  * </ul>
354  * @exception SWTException <ul>
355  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
356  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
357  * </ul>
358  *
359  * @see SelectionListener
360  * @see #addSelectionListener
361  */

362 public void removeSelectionListener (SelectionListener listener) {
363     checkWidget ();
364     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
365     if (eventTable == null) return;
366     eventTable.unhook (SWT.Selection, listener);
367     eventTable.unhook (SWT.DefaultSelection,listener);
368 }
369
370 void setBounds (int x, int y, int width, int height, int flags) {
371     super.setBounds (x, y, width, height, flags);
372     /*
373     * Bug in Windows. If the scroll bar is resized when it has focus,
374     * the flashing cursor that is used to show that the scroll bar has
375     * focus is not moved. The fix is to send a fake WM_SETFOCUS to
376     * get the scroll bar to recompute the size of the flashing cursor.
377     */

378     if (OS.GetFocus () == handle) {
379         ignoreFocus = true;
380         OS.SendMessage (handle, OS.WM_SETFOCUS, 0, 0);
381         ignoreFocus = false;
382     }
383 }
384
385 /**
386  * Sets the amount that the receiver's value will be
387  * modified by when the up/down (or right/left) arrows
388  * are pressed to the argument, which must be at least
389  * one.
390  *
391  * @param value the new increment (must be greater than zero)
392  *
393  * @exception SWTException <ul>
394  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
395  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
396  * </ul>
397  */

398 public void setIncrement (int value) {
399     checkWidget ();
400     if (value < 1) return;
401     increment = value;
402 }
403
404 /**
405  * Sets the maximum. If this value is negative or less than or
406  * equal to the minimum, the value is ignored. If necessary, first
407  * the thumb and then the selection are adjusted to fit within the
408  * new range.
409  *
410  * @param value the new maximum, which must be greater than the current minimum
411  *
412  * @exception SWTException <ul>
413  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
414  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
415  * </ul>
416  */

417 public void setMaximum (int value) {
418     checkWidget ();
419     if (value < 0) return;
420     SCROLLINFO info = new SCROLLINFO ();
421     info.cbSize = SCROLLINFO.sizeof;
422     info.fMask = OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
423     OS.GetScrollInfo (handle, OS.SB_CTL, info);
424     if (value - info.nMin - info.nPage < 1) return;
425     info.nMax = value;
426     SetScrollInfo (handle, OS.SB_CTL, info, true);
427 }
428
429 /**
430  * Sets the minimum value. If this value is negative or greater
431  * than or equal to the maximum, the value is ignored. If necessary,
432  * first the thumb and then the selection are adjusted to fit within
433  * the new range.
434  *
435  * @param value the new minimum
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 public void setMinimum (int value) {
443     checkWidget ();
444     if (value < 0) return;
445     SCROLLINFO info = new SCROLLINFO ();
446     info.cbSize = SCROLLINFO.sizeof;
447     info.fMask = OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
448     OS.GetScrollInfo (handle, OS.SB_CTL, info);
449     if (info.nMax - value - info.nPage < 1) return;
450     info.nMin = value;
451     SetScrollInfo (handle, OS.SB_CTL, info, true);
452 }
453
454 /**
455  * Sets the amount that the receiver's value will be
456  * modified by when the page increment/decrement areas
457  * are selected to the argument, which must be at least
458  * one.
459  *
460  * @param value the page increment (must be greater than zero)
461  *
462  * @exception SWTException <ul>
463  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
464  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
465  * </ul>
466  */

467 public void setPageIncrement (int value) {
468     checkWidget ();
469     if (value < 1) return;
470     pageIncrement = value;
471 }
472
473 boolean SetScrollInfo (int hwnd, int flags, SCROLLINFO info, boolean fRedraw) {
474     /*
475     * Feature in Windows. Using SIF_DISABLENOSCROLL,
476     * SetScrollInfo () can change enabled and disabled
477     * state of the scroll bar causing a scroll bar that
478     * was disabled by the application to become enabled.
479     * The fix is to disable the scroll bar (again) when
480     * the application has disabled the scroll bar.
481     */

482     if ((state & DISABLED) != 0) fRedraw = false;
483     boolean result = OS.SetScrollInfo (hwnd, flags, info, fRedraw);
484     if ((state & DISABLED) != 0) {
485         OS.EnableWindow (handle, false);
486         if (!OS.IsWinCE) {
487             OS.EnableScrollBar (handle, OS.SB_CTL, OS.ESB_DISABLE_BOTH);
488         }
489     }
490     
491     /*
492     * Bug in Windows. If the thumb is resized when it has focus,
493     * the flashing cursor that is used to show that the scroll bar
494     * has focus is not moved. The fix is to send a fake WM_SETFOCUS
495     * to get the scroll bar to recompute the size of the flashing
496     * cursor.
497     */

498     if (OS.GetFocus () == handle) {
499         ignoreFocus = true;
500         OS.SendMessage (handle, OS.WM_SETFOCUS, 0, 0);
501         ignoreFocus = false;
502     }
503     return result;
504 }
505
506 /**
507  * Sets the 'selection', which is the receiver's
508  * value, to the argument which must be greater than or equal
509  * to zero.
510  *
511  * @param value the new selection (must be zero or greater)
512  *
513  * @exception SWTException <ul>
514  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
515  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
516  * </ul>
517  */

518 public void setSelection (int value) {
519     checkWidget ();
520     SCROLLINFO info = new SCROLLINFO ();
521     info.cbSize = SCROLLINFO.sizeof;
522     info.fMask = OS.SIF_POS;
523     info.nPos = value;
524     SetScrollInfo (handle, OS.SB_CTL, info, true);
525 }
526
527 /**
528  * Sets the size of the receiver's thumb relative to the
529  * difference between its maximum and minimum values. This new
530  * value will be ignored if it is less than one, and will be
531  * clamped if it exceeds the receiver's current range.
532  *
533  * @param value the new thumb value, which must be at least one and not
534  * larger than the size of the current range
535  *
536  * @exception SWTException <ul>
537  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
538  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
539  * </ul>
540  */

541 public void setThumb (int value) {
542     checkWidget ();
543     if (value < 1) return;
544     SCROLLINFO info = new SCROLLINFO ();
545     info.cbSize = SCROLLINFO.sizeof;
546     info.fMask = OS.SIF_PAGE | OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
547     OS.GetScrollInfo (handle, OS.SB_CTL, info);
548     info.nPage = value;
549     if (info.nPage != 0) info.nPage++;
550     SetScrollInfo (handle, OS.SB_CTL, info, true);
551 }
552
553 /**
554  * Sets the receiver's selection, minimum value, maximum
555  * value, thumb, increment and page increment all at once.
556  * <p>
557  * Note: This is similar to setting the values individually
558  * using the appropriate methods, but may be implemented in a
559  * more efficient fashion on some platforms.
560  * </p>
561  *
562  * @param selection the new selection value
563  * @param minimum the new minimum value
564  * @param maximum the new maximum value
565  * @param thumb the new thumb value
566  * @param increment the new increment value
567  * @param pageIncrement the new pageIncrement value
568  *
569  * @exception SWTException <ul>
570  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
571  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
572  * </ul>
573  */

574 public void setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) {
575     checkWidget ();
576     if (minimum < 0) return;
577     if (maximum < 0) return;
578     if (thumb < 1) return;
579     if (increment < 1) return;
580     if (pageIncrement < 1) return;
581     this.increment = increment;
582     this.pageIncrement = pageIncrement;
583     SCROLLINFO info = new SCROLLINFO ();
584     info.cbSize = SCROLLINFO.sizeof;
585     info.fMask = OS.SIF_POS | OS.SIF_PAGE | OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
586     info.nPos = selection;
587     info.nMin = minimum;
588     info.nMax = maximum;
589     info.nPage = thumb;
590     if (info.nPage != 0) info.nPage++;
591     SetScrollInfo (handle, OS.SB_CTL, info, true);
592 }
593
594 int widgetExtStyle () {
595     /*
596     * Bug in Windows. If a scroll bar control is given a border,
597     * dragging the scroll bar thumb eats away parts of the border
598     * while the thumb is dragged. The fix is to clear border for
599     * all scroll bars.
600     */

601     int bits = super.widgetExtStyle ();
602     if ((style & SWT.BORDER) != 0) bits &= ~OS.WS_EX_CLIENTEDGE;
603     return bits;
604 }
605
606 int widgetStyle () {
607     int bits = super.widgetStyle () | OS.WS_TABSTOP;
608     /*
609     * Bug in Windows. If a scroll bar control is given a border,
610     * dragging the scroll bar thumb eats away parts of the border
611     * while the thumb is dragged. The fix is to clear WS_BORDER.
612     */

613     if ((style & SWT.BORDER) != 0) bits &= ~OS.WS_BORDER;
614     if ((style & SWT.HORIZONTAL) != 0) return bits | OS.SBS_HORZ;
615     return bits | OS.SBS_VERT;
616 }
617
618 TCHAR windowClass () {
619     return ScrollBarClass;
620 }
621
622 int windowProc () {
623     return ScrollBarProc;
624 }
625
626 LRESULT WM_KEYDOWN (int wParam, int lParam) {
627     LRESULT result = super.WM_KEYDOWN (wParam, lParam);
628     if (result != null) return result;
629     if ((style & SWT.VERTICAL) != 0) return result;
630     /*
631     * Bug in Windows. When a horizontal scroll bar is mirrored,
632     * the native control does not correctly swap the arrow keys.
633     * The fix is to swap them before calling the scroll bar window
634     * proc.
635     *
636     * NOTE: This fix is not ideal. It breaks when the bug is fixed
637     * in the operating system.
638     */

639     if ((style & SWT.MIRRORED) != 0) {
640         switch (wParam) {
641             case OS.VK_LEFT:
642             case OS.VK_RIGHT: {
643                 int key = wParam == OS.VK_LEFT ? OS.VK_RIGHT : OS.VK_LEFT;
644                 int code = callWindowProc (handle, OS.WM_KEYDOWN, key, lParam);
645                 return new LRESULT (code);
646             }
647         }
648     }
649     return result;
650 }
651  
652 LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
653     /*
654     * Feature in Windows. Windows uses the WS_TABSTOP
655     * style for the scroll bar to decide that focus
656     * should be set during WM_LBUTTONDBLCLK. This is
657     * not the desired behavior. The fix is to clear
658     * and restore WS_TABSTOP so that Windows will not
659     * assign focus.
660     */

661     int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
662     int newBits = oldBits & ~OS.WS_TABSTOP;
663     OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
664     LRESULT result = super.WM_LBUTTONDBLCLK (wParam, lParam);
665     if (isDisposed ()) return LRESULT.ZERO;
666     OS.SetWindowLong (handle, OS.GWL_STYLE, oldBits);
667     if (result == LRESULT.ZERO) return result;
668     
669     /*
670     * Feature in Windows. Windows runs a modal message loop
671     * when the user drags a scroll bar that terminates when
672     * it sees an WM_LBUTTONUP. Unfortunately the WM_LBUTTONUP
673     * is consumed. The fix is to send a fake mouse up and
674     * release the automatic capture.
675     */

676     if (!OS.IsWinCE) {
677         if (OS.GetCapture () == handle) OS.ReleaseCapture ();
678         if (!sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam)) {
679             return LRESULT.ZERO;
680         }
681     }
682     return result;
683 }
684
685 LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
686     /*
687     * Feature in Windows. Windows uses the WS_TABSTOP
688     * style for the scroll bar to decide that focus
689     * should be set during WM_LBUTTONDOWN. This is
690     * not the desired behavior. The fix is to clear
691     * and restore WS_TABSTOP so that Windows will not
692     * assign focus.
693     */

694     int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
695     int newBits = oldBits & ~OS.WS_TABSTOP;
696     OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
697     LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
698     if (isDisposed ()) return LRESULT.ZERO;
699     OS.SetWindowLong (handle, OS.GWL_STYLE, oldBits);
700     if (result == LRESULT.ZERO) return result;
701
702     /*
703     * Feature in Windows. Windows runs a modal message loop
704     * when the user drags a scroll bar that terminates when
705     * it sees an WM_LBUTTONUP. Unfortunately the WM_LBUTTONUP
706     * is consumed. The fix is to send a fake mouse up and
707     * release the automatic capture.
708     */

709     if (!OS.IsWinCE) {
710         if (OS.GetCapture () == handle) OS.ReleaseCapture ();
711         if (!sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam)) {
712             return LRESULT.ONE;
713         }
714     }
715     return result;
716 }
717
718 LRESULT WM_SETFOCUS (int wParam, int lParam) {
719     if (ignoreFocus) return null;
720     return super.WM_SETFOCUS (wParam, lParam);
721 }
722
723 LRESULT wmScrollChild (int wParam, int lParam) {
724
725     /* Do nothing when scrolling is ending */
726     int code = wParam & 0xFFFF;
727     if (code == OS.SB_ENDSCROLL) return null;
728
729     /* Move the thumb */
730     Event event = new Event ();
731     SCROLLINFO info = new SCROLLINFO ();
732     info.cbSize = SCROLLINFO.sizeof;
733     info.fMask = OS.SIF_TRACKPOS | OS.SIF_POS | OS.SIF_RANGE;
734     OS.GetScrollInfo (handle, OS.SB_CTL, info);
735     info.fMask = OS.SIF_POS;
736     switch (code) {
737         case OS.SB_THUMBPOSITION:
738             event.detail = SWT.NONE;
739             info.nPos = info.nTrackPos;
740             break;
741         case OS.SB_THUMBTRACK:
742             event.detail = SWT.DRAG;
743             info.nPos = info.nTrackPos;
744             break;
745         case OS.SB_TOP:
746             event.detail = SWT.HOME;
747             info.nPos = info.nMin;
748             break;
749         case OS.SB_BOTTOM:
750             event.detail = SWT.END;
751             info.nPos = info.nMax;
752             break;
753         case OS.SB_LINEDOWN:
754             event.detail = SWT.ARROW_DOWN;
755             info.nPos += increment;
756             break;
757         case OS.SB_LINEUP:
758             event.detail = SWT.ARROW_UP;
759             info.nPos = Math.max (info.nMin, info.nPos - increment);
760             break;
761         case OS.SB_PAGEDOWN:
762             event.detail = SWT.PAGE_DOWN;
763             info.nPos += pageIncrement;
764             break;
765         case OS.SB_PAGEUP:
766             event.detail = SWT.PAGE_UP;
767             info.nPos = Math.max (info.nMin, info.nPos - pageIncrement);
768             break;
769     }
770     OS.SetScrollInfo (handle, OS.SB_CTL, info, true);
771     
772     /*
773     * Feature in Windows. Windows runs a modal message
774     * loop when the user drags a scroll bar. This means
775     * that selection event must be sent because WM_HSCROLL
776     * and WM_VSCROLL are sent from the modal message loop
777     * so that they are delivered during inside the loop.
778     */

779     sendEvent (SWT.Selection, event);
780     // the widget could be destroyed at this point
781
return null;
782 }
783
784 }
785
Popular Tags