package org.eclipse.swt.widgets; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved | |
*/ | |
import org.eclipse.swt.internal.motif.*; | |
import org.eclipse.swt.*; | |
import org.eclipse.swt.events.*; | |
import org.eclipse.swt.graphics.*; | |
/** | |
* Instances of this class are selectable user interface | |
* objects that represent a range of positive, numeric values. | |
* <p> | |
* At any given moment, a given slider will have a | |
* single <em>selection</em> that is considered to be its | |
* value, which is constrained to be within the range of | |
* values the slider represents (that is, between its | |
* <em>minimum</em> and <em>maximum</em> values). | |
* </p><p> | |
* Typically, sliders will be made up of five areas: | |
* <ol> | |
* <li>an arrow button for decrementing the value</li> | |
* <li>a page decrement area for decrementing the value by a larger amount</li> | |
* <li>a <em>thumb</em> for modifying the value by mouse dragging</li> | |
* <li>a page increment area for incrementing the value by a larger amount</li> | |
* <li>an arrow button for incrementing the value</li> | |
* </ol> | |
* Based on their style, sliders are either <code>HORIZONTAL</code> | |
* (which have left and right facing buttons for incrementing and | |
* decrementing the value) or <code>VERTICAL</code> (which have | |
* up and down facing buttons for incrementing and decrementing | |
* the value). | |
* </p><p> | |
* On some platforms, the size of the slider's thumb can be | |
* varied relative to the magnitude of the range of values it | |
* represents (that is, relative to the difference between its | |
* maximum and minimum values). Typically, this is used to | |
* indicate some proportional value such as the ratio of the | |
* visible area of a document to the total amount of space that | |
* it would take to display it. SWT supports setting the thumb | |
* size even if the underlying platform does not, but in this | |
* case the appearance of the slider will not change. | |
* </p> | |
* <dl> | |
* <dt><b>Styles:</b></dt> | |
* <dd>HORIZONTAL, VERTICAL</dd> | |
* <dt><b>Events:</b></dt> | |
* <dd>Selection</dd> | |
* </dl> | |
* <p> | |
* IMPORTANT: This class is <em>not</em> intended to be subclassed. | |
* | |
* @see ScrollBar | |
*/ | |
public class Slider extends Control { | |
/** | |
* Constructs a new instance of this class given its parent | |
* and a style value describing its behavior and appearance. | |
* <p> | |
* The style value is either one of the style constants defined in | |
* class <code>SWT</code> which is applicable to instances of this | |
* class, or must be built by <em>bitwise OR</em>'ing together | |
* (that is, using the <code>int</code> "|" operator) two or more | |
* of those <code>SWT</code> style constants. The class description | |
* for all SWT widget classes should include a comment which | |
* describes the style constants which are applicable to the class. | |
* </p> | |
* | |
* @param parent a composite control which will be the parent of the new instance (cannot be null) | |
* @param style the style of control to construct | |
* | |
* @exception IllegalArgumentException <ul> | |
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
* </ul> | |
* @exception SWTException <ul> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
* <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
* </ul> | |
* | |
* @see SWT | |
* @see Widget#checkSubclass | |
* @see Widget#getStyle | |
*/ | |
public Slider (Composite parent, int style) { | |
super (parent, checkStyle (style)); | |
} | |
/** | |
* Adds the listener to the collection of listeners who will | |
* be notified when the receiver's value changes, by sending | |
* it one of the messages defined in the <code>SelectionListener</code> | |
* interface. | |
* <p> | |
* When <code>widgetSelected</code> is called, the event object detail field contains one of the following values: | |
* <code>0</code> - for the end of a drag. | |
* <code>SWT.DRAG</code>. | |
* <code>SWT.HOME</code>. | |
* <code>SWT.END</code>. | |
* <code>SWT.ARROW_DOWN</code>. | |
* <code>SWT.ARROW_UP</code>. | |
* <code>SWT.PAGE_DOWN</code>. | |
* <code>SWT.PAGE_UP</code>. | |
* <code>widgetDefaultSelected</code> is not called. | |
* </p> | |
* | |
* @param listener the listener which should be notified | |
* | |
* @exception IllegalArgumentException <ul> | |
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
* </ul> | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
* | |
* @see SelectionListener | |
* @see #removeSelectionListener | |
* @see SelectionEvent | |
*/ | |
public void addSelectionListener(SelectionListener listener) { | |
checkWidget(); | |
if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); | |
TypedListener typedListener = new TypedListener(listener); | |
addListener(SWT.Selection,typedListener); | |
addListener(SWT.DefaultSelection,typedListener); | |
} | |
static int checkStyle (int style) { | |
return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0); | |
} | |
public Point computeSize (int wHint, int hHint, boolean changed) { | |
checkWidget(); | |
int border = getBorderWidth (); | |
int width = border * 2, height = border * 2; | |
Display display = getDisplay (); | |
int hScroll = display.scrolledMarginX; | |
int vScroll = display.scrolledMarginY; | |
if ((style & SWT.HORIZONTAL) != 0) { | |
width += hScroll * 10; | |
height += vScroll; | |
} else { | |
width += hScroll; | |
height += vScroll * 10; | |
} | |
if (wHint != SWT.DEFAULT) width = wHint + (border * 2); | |
if (hHint != SWT.DEFAULT) height = hHint + (border * 2); | |
return new Point (width, height); | |
} | |
void createHandle (int index) { | |
state |= HANDLE; | |
Display display = getDisplay (); | |
int [] argList = { | |
OS.XmNancestorSensitive, 1, | |
OS.XmNhighlightThickness, display.textHighlightThickness, | |
OS.XmNborderWidth, (style & SWT.BORDER) != 0 ? 1 : 0, | |
OS.XmNorientation, ((style & SWT.H_SCROLL) != 0) ? OS.XmHORIZONTAL : OS.XmVERTICAL, | |
}; | |
int parentHandle = parent.handle; | |
handle = OS.XmCreateScrollBar (parentHandle, null, argList, argList.length / 2); | |
if (handle == 0) error (SWT.ERROR_NO_HANDLES); | |
} | |
/** | |
* Returns the amount that the receiver's value will be | |
* modified by when the up/down (or right/left) arrows | |
* are pressed. | |
* | |
* @return the increment | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public int getIncrement () { | |
checkWidget(); | |
int [] argList = {OS.XmNincrement, 0}; | |
OS.XtGetValues (handle, argList, argList.length / 2); | |
return argList [1]; | |
} | |
/** | |
* Returns the maximum value which the receiver will allow. | |
* | |
* @return the maximum | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public int getMaximum () { | |
checkWidget(); | |
int [] argList = {OS.XmNmaximum, 0}; | |
OS.XtGetValues (handle, argList, argList.length / 2); | |
return argList [1]; | |
} | |
/** | |
* Returns the minimum value which the receiver will allow. | |
* | |
* @return the minimum | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public int getMinimum () { | |
checkWidget(); | |
int [] argList = {OS.XmNminimum, 0}; | |
OS.XtGetValues (handle, argList, argList.length / 2); | |
return argList [1]; | |
} | |
/** | |
* Returns the amount that the receiver's value will be | |
* modified by when the page increment/decrement areas | |
* are selected. | |
* | |
* @return the page increment | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public int getPageIncrement () { | |
checkWidget(); | |
int [] argList = {OS.XmNpageIncrement, 0}; | |
OS.XtGetValues (handle, argList, argList.length / 2); | |
return argList [1]; | |
} | |
/** | |
* Returns the single <em>selection</em> that is the receiver's value. | |
* | |
* @return the selection | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public int getSelection () { | |
checkWidget(); | |
int [] argList = {OS.XmNvalue, 0}; | |
OS.XtGetValues (handle, argList, argList.length / 2); | |
return argList [1]; | |
} | |
/** | |
* Returns the size of the receiver's thumb relative to the | |
* difference between its maximum and minimum values. | |
* | |
* @return the thumb value | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public int getThumb () { | |
checkWidget(); | |
int [] argList = {OS.XmNsliderSize, 0}; | |
OS.XtGetValues (handle, argList, argList.length / 2); | |
return argList [1]; | |
} | |
void hookEvents () { | |
super.hookEvents (); | |
int windowProc = getDisplay ().windowProc; | |
OS.XtAddCallback (handle, OS.XmNvalueChangedCallback, windowProc, SWT.Selection); | |
OS.XtAddCallback (handle, OS.XmNdragCallback, windowProc, SWT.Selection); | |
OS.XtAddCallback (handle, OS.XmNtoBottomCallback, windowProc, SWT.Selection); | |
OS.XtAddCallback (handle, OS.XmNincrementCallback, windowProc, SWT.Selection); | |
OS.XtAddCallback (handle, OS.XmNdecrementCallback, windowProc, SWT.Selection); | |
OS.XtAddCallback (handle, OS.XmNpageIncrementCallback, windowProc, SWT.Selection); | |
OS.XtAddCallback (handle, OS.XmNpageDecrementCallback, windowProc, SWT.Selection); | |
OS.XtAddCallback (handle, OS.XmNtoTopCallback, windowProc, SWT.Selection); | |
} | |
int processSelection (int callData) { | |
XmAnyCallbackStruct struct = new XmAnyCallbackStruct (); | |
OS.memmove (struct, callData, XmAnyCallbackStruct.sizeof); | |
Event event = new Event (); | |
switch (struct.reason) { | |
case OS.XmCR_DRAG: event.detail = SWT.DRAG; break; | |
/* | |
* Do not set the detail field to SWT.DRAG | |
* to indicate that the dragging has ended. | |
*/ | |
// case OS.XmCR_VALUE_CHANGED: break; | |
case OS.XmCR_TO_TOP: event.detail = SWT.HOME; break; | |
case OS.XmCR_TO_BOTTOM: event.detail = SWT.END; break; | |
case OS.XmCR_DECREMENT: event.detail = SWT.ARROW_UP; break; | |
case OS.XmCR_INCREMENT: event.detail = SWT.ARROW_DOWN; break; | |
case OS.XmCR_PAGE_DECREMENT: event.detail = SWT.PAGE_UP; break; | |
case OS.XmCR_PAGE_INCREMENT: event.detail = SWT.PAGE_DOWN; break; | |
} | |
sendEvent (SWT.Selection, event); | |
return 0; | |
} | |
/** | |
* Removes the listener from the collection of listeners who will | |
* be notified when the receiver's value changes. | |
* | |
* @param listener the listener which should no longer be notified | |
* | |
* @exception IllegalArgumentException <ul> | |
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
* </ul> | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
* | |
* @see SelectionListener | |
* @see #addSelectionListener | |
*/ | |
public void removeSelectionListener(SelectionListener listener) { | |
checkWidget(); | |
if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); | |
if (eventTable == null) return; | |
eventTable.unhook(SWT.Selection, listener); | |
eventTable.unhook(SWT.DefaultSelection,listener); | |
} | |
/** | |
* Sets the amount that the receiver's value will be | |
* modified by when the up/down (or right/left) arrows | |
* are pressed to the argument, which must be at least | |
* one. | |
* | |
* @param value the new increment (must be greater than zero) | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public void setIncrement (int value) { | |
checkWidget(); | |
if (value < 1) return; | |
int [] argList = {OS.XmNincrement, value}; | |
OS.XtSetValues (handle, argList, argList.length / 2); | |
} | |
/** | |
* Sets the maximum value which the receiver will allow | |
* to be the argument which must be greater than or | |
* equal to zero. | |
* | |
* @param value the new maximum (must be zero or greater) | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public void setMaximum (int value) { | |
checkWidget(); | |
if (value < 0) return; | |
int [] argList = {OS.XmNmaximum, value}; | |
Display display = getDisplay (); | |
boolean warnings = display.getWarnings (); | |
display.setWarnings (false); | |
OS.XtSetValues (handle, argList, argList.length / 2); | |
display.setWarnings (warnings); | |
} | |
/** | |
* Sets the minimum value which the receiver will allow | |
* to be the argument which must be greater than or | |
* equal to zero. | |
* | |
* @param value the new minimum (must be zero or greater) | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public void setMinimum (int value) { | |
checkWidget(); | |
if (value < 0) return; | |
int [] argList = { | |
OS.XmNminimum, 0, | |
OS.XmNmaximum, 0, | |
OS.XmNsliderSize, 0, | |
}; | |
/* | |
* Feature in Motif. For some reason, when minimium | |
* is set to be greater than or equal to maximum, Motif | |
* does not set the minimum. Instead, the value is | |
* changed and the minimum stays the same. This behavior | |
* differs from setting the maximum where the slider size | |
* is always decreased to make room for the new maximum. | |
* The fix is to decrease the slider to make room for | |
* the new minimum. | |
*/ | |
OS.XtGetValues (handle, argList, argList.length / 2); | |
if (argList [3] - value - argList [5] < 0) { | |
argList [5] = argList [3] - value; | |
} | |
argList [1] = value; | |
Display display = getDisplay (); | |
boolean warnings = display.getWarnings (); | |
display.setWarnings (false); | |
OS.XtSetValues (handle, argList, argList.length / 2); | |
display.setWarnings (warnings); | |
} | |
/** | |
* Sets the amount that the receiver's value will be | |
* modified by when the page increment/decrement areas | |
* are selected to the argument, which must be at least | |
* one. | |
* | |
* @return the page increment (must be greater than zero) | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public void setPageIncrement (int value) { | |
checkWidget(); | |
if (value < 1) return; | |
int [] argList = {OS.XmNpageIncrement, value}; | |
OS.XtSetValues (handle, argList, argList.length / 2); | |
} | |
/** | |
* Sets the single <em>selection</em> that is the receiver's | |
* value to the argument which must be greater than or equal | |
* to zero. | |
* | |
* @param value the new selection (must be zero or greater) | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public void setSelection (int value) { | |
checkWidget(); | |
if (value < 0) return; | |
int [] argList = {OS.XmNvalue, value}; | |
Display display = getDisplay (); | |
boolean warnings = display.getWarnings (); | |
display.setWarnings (false); | |
OS.XtSetValues (handle, argList, argList.length / 2); | |
display.setWarnings (warnings); | |
} | |
/** | |
* Sets the size of the receiver's thumb relative to the | |
* difference between its maximum and minimum values to the | |
* argument which must be at least one. | |
* | |
* @param value the new thumb value (must be at least one) | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
* | |
* @see ScrollBar | |
*/ | |
public void setThumb (int value) { | |
checkWidget(); | |
if (value < 1) return; | |
int [] argList = {OS.XmNsliderSize, value}; | |
Display display = getDisplay (); | |
boolean warnings = display.getWarnings (); | |
display.setWarnings (false); | |
OS.XtSetValues (handle, argList, argList.length / 2); | |
display.setWarnings (warnings); | |
} | |
/** | |
* Sets the receiver's selection, minimum value, maximum | |
* value, thumb, increment and page increment all at once. | |
* <p> | |
* Note: This is equivalent to setting the values individually | |
* using the appropriate methods, but may be implemented in a | |
* more efficient fashion on some platforms. | |
* </p> | |
* | |
* @param selection the new selection value | |
* @param minimum the new minimum value | |
* @param maximum the new maximum value | |
* @param thumb the new thumb value | |
* @param increment the new increment value | |
* @param pageIncrement the new pageIncrement value | |
* | |
* @exception SWTException <ul> | |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
* </ul> | |
*/ | |
public void setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) { | |
checkWidget(); | |
if (selection < 0) return; | |
if (minimum < 0) return; | |
if (maximum < 0) return; | |
if (thumb < 1) return; | |
if (maximum - minimum - thumb < 0) return; | |
if (increment < 1) return; | |
if (pageIncrement < 1) return; | |
int [] argList = { | |
OS.XmNvalue, selection, | |
OS.XmNminimum, minimum, | |
OS.XmNmaximum, maximum, | |
OS.XmNsliderSize, thumb, | |
OS.XmNincrement, increment, | |
OS.XmNpageIncrement, pageIncrement, | |
}; | |
Display display = getDisplay (); | |
boolean warnings = display.getWarnings (); | |
display.setWarnings (false); | |
OS.XtSetValues (handle, argList, argList.length / 2); | |
display.setWarnings (warnings); | |
} | |
} |