blob: e3a291c0723215a7b320f7900613a1fe257d2c07 [file] [log] [blame]
package org.eclipse.swt.widgets;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.motif.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.events.*;
/**
* Instances of this class represent a selectable user interface object
* that represents a button in a tool bar.
* <p>
* <dl>
* <dt><b>Styles:</b></dt>
* <dd>PUSH, CHECK, RADIO, SEPARATOR, DROP_DOWN</dd>
* <dt><b>Events:</b></dt>
* <dd>Selection</dd>
* </dl>
* </p>
* IMPORTANT: This class is <em>not</em> intended to be subclassed.
*/
public /*final*/ class ToolItem extends Item {
ToolBar parent;
Image hotImage, disabledImage;
String toolTipText;
Control control;
boolean set;
/**
* Creates a new instance of the widget.
*/
public ToolItem (ToolBar parent, int style) {
super (parent, checkStyle (style));
this.parent = parent;
parent.createItem (this, parent.getItemCount ());
parent.relayout ();
}
/**
* Creates a new instance of the widget.
*/
public ToolItem (ToolBar parent, int style, int index) {
super (parent, checkStyle (style));
this.parent = parent;
parent.createItem (this, index);
parent.relayout ();
}
/**
* Adds the listener to the collection of listeners who will
* be notified when the control is selected, by sending
* it one of the messages defined in the <code>SelectionListener</code>
* interface.
* <p>
* When <code>widgetSelected</code> is called when the mouse is over the arrow portion of a drop-down tool,
* the event object detail field contains the value <code>SWT.ARROW</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) {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
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.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.DROP_DOWN, 0);
}
protected void checkSubclass () {
if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
}
void createHandle (int index) {
state |= HANDLE;
int parentHandle = parent.handle;
if ((style & SWT.SEPARATOR) != 0) {
int [] argList = {
OS.XmNwidth, 8,
OS.XmNheight, 5,
OS.XmNrecomputeSize, 0,
OS.XmNpositionIndex, index,
OS.XmNmappedWhenManaged, 0,
OS.XmNancestorSensitive, 1,
};
handle = OS.XmCreateDrawnButton (parentHandle, null, argList, argList.length / 2);
if (handle == 0) error (SWT.ERROR_NO_HANDLES);
return;
}
int [] argList = {
OS.XmNwidth, 24,
OS.XmNheight, 22,
OS.XmNrecomputeSize, 0,
OS.XmNhighlightThickness, 0,
OS.XmNmarginWidth, 2,
OS.XmNmarginHeight, 1,
OS.XmNtraversalOn, 0,
OS.XmNpositionIndex, index,
OS.XmNshadowType, OS.XmSHADOW_OUT,
OS.XmNancestorSensitive, 1,
};
handle = OS.XmCreateDrawnButton (parentHandle, null, argList, argList.length / 2);
if (handle == 0) error (SWT.ERROR_NO_HANDLES);
}
Point computeSize () {
if ((style & SWT.SEPARATOR) != 0) {
int [] argList = {
OS.XmNwidth, 0,
OS.XmNheight, 0,
};
OS.XtGetValues (handle, argList, argList.length / 2);
int width = argList [1], height = argList [3];
return new Point(width, height);
}
int [] argList = {
OS.XmNmarginHeight, 0,
OS.XmNmarginWidth, 0,
OS.XmNshadowThickness, 0,
};
OS.XtGetValues (handle, argList, argList.length / 2);
int marginHeight = argList [1], marginWidth = argList [3];
int shadowThickness = argList [5];
if ((parent.style & SWT.FLAT) != 0) {
Display display = getDisplay ();
shadowThickness = Math.min (2, display.buttonShadowThickness);
}
int textWidth = 0, textHeight = 0;
if (text.length () != 0) {
GC gc = new GC (parent);
Point textExtent = gc.textExtent (text);
textWidth = textExtent.x;
textHeight = textExtent.y;
gc.dispose ();
}
int imageWidth = 0, imageHeight = 0;
if (image != null) {
Rectangle rect = image.getBounds ();
imageWidth = rect.width;
imageHeight = rect.height;
}
int width = 0, height = 0;
if ((parent.style & SWT.RIGHT) != 0) {
width = imageWidth + textWidth;
height = Math.max (imageHeight, textHeight);
if (imageWidth != 0 && textWidth != 0) width += 2;
} else {
height = imageHeight + textHeight;
if (imageHeight != 0 && textHeight != 0) height += 2;
width = Math.max (imageWidth, textWidth);
}
if ((style & SWT.DROP_DOWN) != 0) width += 12;
/* The 24 and 22 values come from Windows */
if (width != 0) {
width += (marginWidth + shadowThickness) * 2 + 2;
} else {
width = 24;
}
if (height != 0) {
height += (marginHeight + shadowThickness) * 2 + 2;
} else {
height = 22;
}
return new Point (width, height);
}
void createWidget (int index) {
super.createWidget (index);
toolTipText = "";
parent.relayout ();
}
public void dispose () {
if (!isValidWidget ()) return;
ToolBar parent = this.parent;
super.dispose ();
parent.relayout ();
}
/**
* Returns a rectangle describing the receiver's size and location
* relative to its parent.
*
* @return the receiver's bounding rectangle
*
* @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 Rectangle getBounds () {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
int [] argList = {OS.XmNx, 0, OS.XmNy, 0, OS.XmNwidth, 0, OS.XmNheight, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
return new Rectangle ((short) argList [1], (short) argList [3], argList [5], argList [7]);
}
/**
* Returns the control that is used to fill the bounds of
* the item when the items is a <code>SEPARATOR</code>.
*
* @return the control
*
* @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 Control getControl () {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
return control;
}
/**
* Gets the disabled image.
* <p>
* @return the image
*
* @exception SWTError(ERROR_THREAD_INVALID_ACCESS)
* when called from the wrong thread
* @exception SWTError(ERROR_WIDGET_DISPOSED)
* when the widget has been disposed
*/
public Image getDisabledmage () {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
return disabledImage;
}
/**
* Returns <code>true</code> if the receiver is enabled, and
* <code>false</code> otherwise.
* <p>
* A disabled control is typically not selectable from the
* user interface and draws with an inactive or "grayed" look.
* </p>
*
* @return the receiver's enabled state
*
* @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 boolean getEnabled () {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
int [] argList = {OS.XmNsensitive, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
return argList [1] != 0;
}
public Display getDisplay () {
Composite parent = this.parent;
if (parent == null) error (SWT.ERROR_WIDGET_DISPOSED);
return parent.getDisplay ();
}
/**
* Returns the receiver's hot image if it has one, or null
* if it does not.
* <p>
* The hot image is displayed when the mouse enters the receiver.
* </p>
*
* @return the receiver's hot image
*
* @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 Image getHotImage () {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
return hotImage;
}
/**
* Returns the receiver's parent, which must be a <code>ToolBar</code>.
*
* @return the receiver's parent
*
* @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 ToolBar getParent () {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
return parent;
}
/**
* Returns <code>true</code> if the receiver is selected,
* and false otherwise.
* <p>
* When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
* it is selected when it is checked. When it is of type <code>TOGGLE</code>,
* it is selected when it is pushed.
* </p>
*
* @return the selection state
*
* @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 boolean getSelection () {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false;
return set;
}
/**
* Returns the receiver's tool tip text, or null if it has not been set.
*
* @return the receiver's tool tip text
*
* @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 String getToolTipText () {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
return toolTipText;
}
/**
* Gets the width of the receiver.
*
* @return the width
*
* @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 getWidth () {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
int [] argList = {OS.XmNwidth, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
return argList [1];
}
boolean hasCursor () {
int [] unused = new int [1], buffer = new int [1];
int xDisplay = OS.XtDisplay (handle);
int xWindow, xParent = OS.XDefaultRootWindow (xDisplay);
do {
if (OS.XQueryPointer (
xDisplay, xParent, unused, buffer,
unused, unused, unused, unused, unused) == 0) return false;
if ((xWindow = buffer [0]) != 0) xParent = xWindow;
} while (xWindow != 0);
return handle == OS.XtWindowToWidget (xDisplay, xParent);
}
void hookEvents () {
super.hookEvents ();
if ((style & SWT.SEPARATOR) != 0) return;
int windowProc = getDisplay ().windowProc;
OS.XtAddCallback (handle, OS.XmNexposeCallback, windowProc, SWT.Paint);
OS.XtAddEventHandler (handle, OS.ButtonPressMask, false, windowProc, SWT.MouseDown);
OS.XtAddEventHandler (handle, OS.ButtonReleaseMask, false, windowProc, SWT.MouseUp);
OS.XtAddEventHandler (handle, OS.PointerMotionMask, false, windowProc, SWT.MouseMove);
OS.XtAddEventHandler (handle, OS.EnterWindowMask, false, windowProc, SWT.MouseEnter);
OS.XtAddEventHandler (handle, OS.LeaveWindowMask, false, windowProc, SWT.MouseExit);
}
/**
* Returns <code>true</code> if the receiver is enabled, and
* <code>false</code> otherwise.
* <p>
* A disabled control is typically not selectable from the
* user interface and draws with an inactive or "grayed" look.
* </p>
*
* @return the receiver's enabled state
*
* @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 boolean isEnabled () {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
return getEnabled () && parent.isEnabled ();
}
void manageChildren () {
OS.XtManageChild (handle);
}
void redraw () {
int display = OS.XtDisplay (handle);
if (display == 0) return;
int window = OS.XtWindow (handle);
if (window == 0) return;
OS.XClearArea (display, window, 0, 0, 0, 0, true);
}
void releaseChild () {
super.releaseChild ();
parent.destroyItem (this);
}
void releaseWidget () {
Display display = getDisplay ();
display.releaseToolTipHandle (handle);
super.releaseWidget ();
parent = null;
control = null;
toolTipText = null;
image = disabledImage = hotImage = null;
}
/**
* Removes the listener from the collection of listeners who will
* be notified when the control is selected.
*
* @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 #addSelectionListener
*/
public void removeSelectionListener(SelectionListener listener) {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
if (eventTable == null) return;
eventTable.unhook(SWT.Selection, listener);
eventTable.unhook(SWT.DefaultSelection,listener);
}
void selectRadio () {
this.setSelection (true);
ToolItem [] items = parent.getItems ();
int index = 0;
while (index < items.length && items [index] != this) index++;
ToolItem item;
int i = index;
while (--i >= 0 && ((item = items [i]).style & SWT.RADIO) != 0) {
item.setSelection (false);
}
i = index;
while (++i < items.length && ((item = items [i]).style & SWT.RADIO) != 0) {
item.setSelection (false);
}
}
void setBounds (int x, int y, int width, int height) {
if (control != null) control.setBounds(x, y, width, height);
/*
* Feature in Motif. Motif will not allow a window
* to have a zero width or zero height. The fix is
* to ensure these values are never zero.
*/
int newWidth = Math.max (width, 1), newHeight = Math.max (height, 1);
OS.XtConfigureWidget (handle, x, y, newWidth, newHeight, 0);
}
/**
* Sets the control that is used to fill the bounds of
* the item when the items is a <code>SEPARATOR</code>.
*
* @param control the new control
*
* @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 setControl (Control control) {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
if (control != null && control.parent != parent) {
error (SWT.ERROR_INVALID_PARENT);
}
if ((style & SWT.SEPARATOR) == 0) return;
this.control = control;
if (control != null && !control.isDisposed ()) {
control.setBounds (getBounds ());
}
}
/**
* Enables the receiver if the argument is <code>true</code>,
* and disables it otherwise.
* <p>
* A disabled control is typically
* not selectable from the user interface and draws with an
* inactive or "grayed" look.
* </p>
*
* @param enabled the new enabled state
*
* @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 setEnabled (boolean enabled) {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
int [] argList = {OS.XmNsensitive, enabled ? 1 : 0};
OS.XtSetValues (handle, argList, argList.length / 2);
}
/**
* Sets the receiver's disabled image to the argument, which may be
* null indicating that no disabled image should be displayed.
* <p>
* The disbled image is displayed when the receiver is disabled.
* </p>
*
* @param image the hot image to display on the receiver (may be null)
*
* @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 setDisabledImage (Image image) {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
if ((style & SWT.SEPARATOR) != 0) return;
disabledImage = image;
if (!getEnabled ()) redraw ();
}
/**
* Sets the receiver's hot image to the argument, which may be
* null indicating that no hot image should be displayed.
* <p>
* The hot image is displayed when the mouse enters the receiver.
* </p>
*
* @param image the hot image to display on the receiver (may be null)
*
* @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 setHotImage (Image image) {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
if ((style & SWT.SEPARATOR) != 0) return;
hotImage = image;
if ((parent.style & SWT.FLAT) != 0) redraw ();
}
public void setImage (Image image) {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
if ((style & SWT.SEPARATOR) != 0) return;
super.setImage (image);
Point size = computeSize ();
setSize (size.x, size.y);
redraw ();
}
/**
* Sets the selection state of the receiver.
* <p>
* When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
* it is selected when it is checked. When it is of type <code>TOGGLE</code>,
* it is selected when it is pushed.
* </p>
*
* @param selected the new selection state
*
* @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 (boolean selected) {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return;
if (selected == set) return;
set = selected;
setDrawPressed (set);
}
void setSize (int width, int height) {
int [] argList = {OS.XmNwidth, 0, OS.XmNheight, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
if (argList [1] != width || argList [3] != height) {
OS.XtResizeWidget (handle, width, height, 0);
parent.relayout ();
}
}
public void setText (String string) {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
if ((style & SWT.SEPARATOR) != 0) return;
super.setText (string);
Point size = computeSize ();
setSize (size.x, size.y);
redraw ();
}
/**
* Sets the receiver's tool tip text to the argument, which
* may be null indicating that no tool tip text should be shown.
*
* @param string the new tool tip text (or null)
*
* @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 setToolTipText (String string) {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
toolTipText = string;
}
/**
* Sets the width of the receiver.
*
* @param width the new width
*
* @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 setWidth (int width) {
if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);
if ((style & SWT.SEPARATOR) == 0) return;
if (width < 0) return;
int [] argList = {OS.XmNheight, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
setSize (width, argList [1]);
if (control != null && !control.isDisposed ()) {
control.setBounds (getBounds ());
}
}
void setDrawPressed (boolean value) {
int shadowType = value ? OS.XmSHADOW_IN : OS.XmSHADOW_OUT;
int [] argList = {OS.XmNshadowType, shadowType};
OS.XtSetValues(handle, argList, argList.length / 2);
}
int processMouseDown (int callData) {
Display display = getDisplay ();
display.hideToolTip ();
XButtonEvent xEvent = new XButtonEvent ();
OS.memmove (xEvent, callData, XButtonEvent.sizeof);
if (xEvent.button == 1) {
if (!set && (style & SWT.RADIO) == 0) {
setDrawPressed (!set);
}
}
/*
* Forward the mouse event to the parent.
* This is necessary so that mouse listeners
* in the parent will be called, despite the
* fact that the event did not really occur
* in X in the parent. This is done to be
* compatible with Windows.
*/
int [] argList = {OS.XmNx, 0, OS.XmNy, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
xEvent.window = OS.XtWindow (parent.handle);
xEvent.x += argList [1]; xEvent.y += argList [3];
OS.memmove (callData, xEvent, XButtonEvent.sizeof);
parent.processMouseDown (callData);
return 0;
}
int processMouseEnter (int callData) {
XCrossingEvent xEvent = new XCrossingEvent ();
OS.memmove (xEvent, callData, XCrossingEvent.sizeof);
if ((xEvent.state & OS.Button1Mask) != 0) setDrawPressed (!set);
else if ((parent.style & SWT.FLAT) != 0) redraw ();
return 0;
}
int processMouseExit (int callData) {
Display display = getDisplay ();
display.removeMouseHoverTimeOut ();
display.hideToolTip ();
XCrossingEvent xEvent = new XCrossingEvent ();
OS.memmove (xEvent, callData, XCrossingEvent.sizeof);
if ((xEvent.state & OS.Button1Mask) != 0) setDrawPressed (set);
else if ((parent.style & SWT.FLAT) != 0) redraw ();
return 0;
}
Point toControl (Point point) {
short [] root_x = new short [1], root_y = new short [1];
OS.XtTranslateCoords (handle, (short) 0, (short) 0, root_x, root_y);
return new Point (point.x - root_x [0], point.y - root_y [0]);
}
int processMouseHover (int id) {
Display display = getDisplay ();
Point local = toControl (display.getCursorLocation ());
display.showToolTip (handle, toolTipText);
return 0;
}
int processMouseMove (int callData) {
Display display = getDisplay ();
display.addMouseHoverTimeOut (handle);
/*
* Forward the mouse event to the parent.
* This is necessary so that mouse listeners
* in the parent will be called, despite the
* fact that the event did not really occur
* in X in the parent. This is done to be
* compatible with Windows.
*/
XButtonEvent xEvent = new XButtonEvent ();
OS.memmove (xEvent, callData, XButtonEvent.sizeof);
int [] argList = {OS.XmNx, 0, OS.XmNy, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
xEvent.window = OS.XtWindow (parent.handle);
xEvent.x += argList [1]; xEvent.y += argList [3];
/*
* This code is intentionally commented.
* Currently, the implementation of the
* mouse move code in the parent interferes
* with tool tips for tool items.
*/
// OS.memmove (callData, xEvent, XButtonEvent.sizeof);
// parent.processMouseMove (callData);
parent.sendMouseEvent (SWT.MouseMove, 0, xEvent.state, xEvent);
return 0;
}
int processMouseUp (int callData) {
Display display = getDisplay ();
display.hideToolTip();
XButtonEvent xEvent = new XButtonEvent ();
OS.memmove (xEvent, callData, XButtonEvent.sizeof);
if (xEvent.button == 1) {
int [] argList = {OS.XmNwidth, 0, OS.XmNheight, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
int width = argList [1], height = argList [3];
if (0 <= xEvent.x && xEvent.x < width && 0 <= xEvent.y && xEvent.y < height) {
if ((style & SWT.RADIO) != 0) {
selectRadio ();
} else {
if ((style & SWT.CHECK) != 0) setSelection(!set);
}
Event event = new Event ();
if ((style & SWT.DROP_DOWN) != 0) {
if (xEvent.x > width - 12) event.detail = SWT.ARROW;
}
postEvent (SWT.Selection, event);
}
setDrawPressed(set);
}
/*
* Forward the mouse event to the parent.
* This is necessary so that mouse listeners
* in the parent will be called, despite the
* fact that the event did not really occur
* in X in the parent. This is done to be
* compatible with Windows.
*/
int [] argList = {OS.XmNx, 0, OS.XmNy, 0};
OS.XtGetValues (handle, argList, argList.length / 2);
xEvent.window = OS.XtWindow (parent.handle);
xEvent.x += argList [1]; xEvent.y += argList [3];
OS.memmove (callData, xEvent, XButtonEvent.sizeof);
parent.processMouseUp (callData);
return 0;
}
int processPaint (int callData) {
if ((style & SWT.SEPARATOR) != 0) return 0;
int xDisplay = OS.XtDisplay (handle);
if (xDisplay == 0) return 0;
int xWindow = OS.XtWindow (handle);
if (xWindow == 0) return 0;
int [] argList = {
OS.XmNcolormap, 0,
OS.XmNwidth, 0,
OS.XmNheight, 0,
};
OS.XtGetValues (handle, argList, argList.length / 2);
int width = argList [3], height = argList [5];
Image currentImage = image;
boolean enabled = getEnabled();
if ((parent.style & SWT.FLAT) != 0) {
Display display = getDisplay ();
boolean hasCursor = hasCursor ();
/* Set the shadow thickness */
int thickness = 0;
if (set || (hasCursor && enabled)) {
thickness = Math.min (2, display.buttonShadowThickness);
}
argList = new int [] {OS.XmNshadowThickness, thickness};
OS.XtSetValues (handle, argList, argList.length / 2);
/* Determine if hot image should be used */
if (enabled && hasCursor && hotImage != null) {
currentImage = hotImage;
}
}
ToolDrawable wrapper = new ToolDrawable ();
wrapper.device = getDisplay ();
wrapper.display = xDisplay;
wrapper.drawable = xWindow;
wrapper.fontList = parent.getFontList ();
wrapper.colormap = argList [1];
GC gc = new GC (wrapper);
XmAnyCallbackStruct cb = new XmAnyCallbackStruct ();
OS.memmove (cb, callData, XmAnyCallbackStruct.sizeof);
if (cb.event != 0) {
XExposeEvent xEvent = new XExposeEvent ();
OS.memmove (xEvent, cb.event, XExposeEvent.sizeof);
Rectangle rect = new Rectangle (xEvent.x, xEvent.y, xEvent.width, xEvent.height);
gc.setClipping (rect);
}
if (!enabled) {
Display display = getDisplay ();
currentImage = disabledImage;
if (currentImage == null) {
currentImage = new Image (display, image, SWT.IMAGE_DISABLE);
}
Color disabledColor = display.getSystemColor (SWT.COLOR_WIDGET_NORMAL_SHADOW);
gc.setForeground (disabledColor);
} else {
gc.setForeground (parent.getForeground ());
}
gc.setBackground (parent.getBackground ());
int textX = 0, textY = 0, textWidth = 0, textHeight = 0;
if (text.length () != 0) {
Point textExtent = gc.textExtent (text);
textWidth = textExtent.x;
textHeight = textExtent.y;
}
int imageX = 0, imageY = 0, imageWidth = 0, imageHeight = 0;
if (currentImage != null) {
Rectangle imageBounds = currentImage.getBounds ();
imageWidth = imageBounds.width;
imageHeight = imageBounds.height;
}
int spacing = 0;
if (textWidth != 0 && imageWidth != 0) spacing = 2;
if ((parent.style & SWT.RIGHT) != 0) {
imageX = (width - imageWidth - textWidth - spacing) / 2;
imageY = (height - imageHeight) / 2;
textX = spacing + imageX + imageWidth;
textY = (height - textHeight) / 2;
} else {
imageX = (width - imageWidth) / 2;
imageY = (height - imageHeight - textHeight - spacing) / 2;
textX = (width - textWidth) / 2;
textY = spacing + imageY + imageHeight;
}
if ((style & SWT.DROP_DOWN) != 0) {
textX -= 6; imageX -=6;
}
if (textWidth > 0) gc.drawText(text, textX, textY, false);
if (imageWidth > 0) gc.drawImage(currentImage, imageX, imageY);
if ((style & SWT.DROP_DOWN) != 0) {
int startX = width - 12, startY = (height - 2) / 2;
int [] arrow = {startX, startY, startX + 3, startY + 3, startX + 6, startY};
gc.setBackground (parent.getForeground ());
gc.fillPolygon (arrow);
gc.drawPolygon (arrow);
}
gc.dispose ();
if (!enabled && disabledImage == null) {
if (currentImage != null) currentImage.dispose ();
}
return 0;
}
}