Java tutorial
/******************************************************************************* * Copyright (c) 2002, 2017 Innoopract Informationssysteme GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Innoopract Informationssysteme GmbH - initial API and implementation * EclipseSource - ongoing development ******************************************************************************/ package org.eclipse.swt.widgets; import static org.eclipse.swt.internal.widgets.MarkupUtil.isToolTipMarkupEnabledFor; import static org.eclipse.swt.internal.widgets.MarkupValidator.isValidationDisabledFor; import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.internal.lifecycle.RemoteAdapter; import org.eclipse.rap.rwt.internal.lifecycle.ReparentedControls; import org.eclipse.rap.rwt.internal.theme.ThemeAdapter; import org.eclipse.rap.rwt.internal.util.ActiveKeysUtil; import org.eclipse.rap.rwt.theme.BoxDimensions; import org.eclipse.rap.rwt.theme.ControlThemeAdapter; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.accessibility.Accessible; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.DragDetectListener; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.GestureListener; import org.eclipse.swt.events.HelpListener; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MenuDetectListener; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.TouchListener; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.Drawable; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.internal.widgets.ControlRemoteAdapter; import org.eclipse.swt.internal.widgets.IControlAdapter; import org.eclipse.swt.internal.widgets.IDisplayAdapter; import org.eclipse.swt.internal.widgets.MarkupValidator; /** * Control is the abstract superclass of all windowed user interface classes. * <p> * <dl> * <dt><b>Styles:</b> * <dd>BORDER</dd> * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd> * <dt><b>Events:</b> * <dd>FocusIn, FocusOut, Help, KeyDown, KeyUp, MouseDoubleClick, MouseDown, <!-- MouseEnter, --> * <!-- MouseExit, MouseHover, --> MouseUp, <!-- MouseMove,--> Move, <!-- Paint, --> Resize, Traverse, * <!-- DragDetect, --> MenuDetect</dd> * </dl> * </p><p> * IMPORTANT: This class is intended to be subclassed <em>only</em> * within the SWT implementation. * </p> * * @since 1.0 */ public abstract class Control extends Widget implements Drawable { private final class ControlAdapter implements IControlAdapter { @Override public Shell getShell() { return internalGetShell(); } @Override public int getTabIndex() { return tabIndex; } @Override public void setTabIndex(int index) { if (takesFocus()) { getRemoteAdapter().preserveTabIndex(tabIndex); tabIndex = index; } } private boolean takesFocus() { boolean result = (getStyle() & SWT.NO_FOCUS) == 0; result &= Control.this.getClass() != Composite.class; result &= Control.this.getClass() != ScrolledComposite.class; result &= Control.this.getClass() != SashForm.class; return result; } @Override public Font getUserFont() { return font; } @Override public Color getUserForeground() { return foreground; } @Override public Color getUserBackground() { return background; } @Override public Image getUserBackgroundImage() { return backgroundImage; } @Override public boolean getBackgroundTransparency() { return backgroundTransparency; } @Override public boolean isPacked() { return packed; } @Override public void clearPacked() { packed = false; } @Override /* provides direct access to the internal property in order to speed up preserving */ public Rectangle getBounds() { return bounds; } @Override public void setForeground(Color color) { foreground = color; } @Override public void setBackground(Color color) { background = color; } @Override public void setVisible(boolean visible) { internalSetVisible(visible); } @Override public void setEnabled(boolean enabled) { internalSetEnabled(enabled); } @Override public void setToolTipText(String toolTipText) { Control.this.toolTipText = toolTipText; } @Override public void setCursor(Cursor cursor) { Control.this.cursor = cursor; } } private transient IControlAdapter controlAdapter; private Composite parent; private int tabIndex; private Rectangle bounds; private Object layoutData; private String toolTipText; private Menu menu; private Listener menuDisposeListener; private Color foreground; private Color background; private Image backgroundImage; private boolean backgroundTransparency; private Font font; private Cursor cursor; private BoxDimensions bufferedPadding; private transient Accessible accessible; private boolean packed; Control(Composite parent) { // prevent instantiation from outside this package; only called by Shell // and its super-classes this.parent = parent; bounds = new Rectangle(0, 0, 0, 0); tabIndex = -1; } /** * 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 * lists the style constants that are applicable to the class. * Style bits are also inherited from superclasses. * </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#BORDER * @see Widget#checkSubclass * @see Widget#getStyle */ public Control(Composite parent, int style) { super(parent, style); this.parent = parent; controlAdapter = new ControlAdapter(); bounds = new Rectangle(0, 0, 0, 0); tabIndex = -1; parent.addChild(this); createWidget(); } void createWidget() { initState(); checkOrientation(parent); checkMirrored(); checkBackground(); updateBackground(); } void initState() { // by default let states empty } /** * Returns the receiver's parent, which must be a <code>Composite</code> * or null when the receiver is a shell that was created with null or * a display for a parent. * * @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 Composite getParent() { checkWidget(); return parent; } Composite _getParent() { return parent; } /** * Returns the receiver's shell. For all controls other than * shells, this simply returns the control's nearest ancestor * shell. Shells return themselves, even if they are children * of other shells. * * @return the receiver's shell * * @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 #getParent */ public Shell getShell() { checkWidget(); return internalGetShell(); } Shell internalGetShell() { return parent.internalGetShell(); } /** * Returns the receiver's monitor. * * @return the receiver's monitor * * @since 1.2 */ public Monitor getMonitor() { checkWidget(); return display.getPrimaryMonitor(); } ////////////// // Visibility /** * Marks the receiver as visible if the argument is <code>true</code>, * and marks it invisible otherwise. * <p> * If one of the receiver's ancestors is not visible or some * other condition makes the receiver not visible, marking * it visible may not actually cause it to be displayed. * </p> * * @param visible the new visibility 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 setVisible(boolean visible) { checkWidget(); if (hasState(HIDDEN) != !visible) { preserveState(HIDDEN); internalSetVisible(visible); } } private void internalSetVisible(boolean visible) { if (hasState(HIDDEN) != !visible) { if (visible) { notifyListeners(SWT.Show, null); } Control control = null; boolean fixFocus = false; if (!visible) { control = display.getFocusControl(); fixFocus = isFocusAncestor(control); } if (visible) { removeState(HIDDEN); } else { addState(HIDDEN); } if (!visible) { notifyListeners(SWT.Hide, null); } if (fixFocus) { fixFocus(control); } } } /** * Returns <code>true</code> if the receiver is visible and all * ancestors up to and including the receiver's nearest ancestor * shell are visible. Otherwise, <code>false</code> is returned. * * @return the receiver's visibility 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> * * @see #getVisible */ public boolean isVisible() { checkWidget(); return getVisible() && parent.isVisible(); } /** * Returns <code>true</code> if the receiver is visible, and * <code>false</code> otherwise. * <p> * If one of the receiver's ancestors is not visible or some * other condition makes the receiver not visible, this method * may still indicate that it is considered visible even though * it may not actually be showing. * </p> * * @return the receiver's visibility 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 getVisible() { checkWidget(); return !hasState(HIDDEN); } ////////////// // Enablement /** * Enables the receiver if the argument is <code>true</code>, * and disables it otherwise. A disabled control is typically * not selectable from the user interface and draws with an * inactive or "grayed" look. * * @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) { checkWidget(); if (hasState(DISABLED) != !enabled) { preserveState(DISABLED); internalSetEnabled(enabled); } } private void internalSetEnabled(boolean enabled) { if (hasState(DISABLED) != !enabled) { /* * Feature in Windows. If the receiver has focus, disabling * the receiver causes no window to have focus. The fix is * to assign focus to the first ancestor window that takes * focus. If no window will take focus, set focus to the * desktop. */ Control control = null; boolean fixFocus = false; if (!enabled) { control = display.getFocusControl(); fixFocus = isFocusAncestor(control); } if (enabled) { removeState(DISABLED); } else { addState(DISABLED); } if (fixFocus) { fixFocus(control); } } } /** * Returns <code>true</code> if the receiver is enabled, and * <code>false</code> otherwise. A disabled control is typically * not selectable from the user interface and draws with an * inactive or "grayed" look. * * @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> * * @see #isEnabled */ public boolean getEnabled() { checkWidget(); return !hasState(DISABLED); } /** * Returns <code>true</code> if the receiver is enabled and all * ancestors up to and including the receiver's nearest ancestor * shell are enabled. Otherwise, <code>false</code> is returned. * A disabled control is typically not selectable from the user * interface and draws with an inactive or "grayed" look. * * @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> * * @see #getEnabled */ public boolean isEnabled() { checkWidget(); return getEnabled() && parent.isEnabled(); } ///////// // Colors /** * Sets the receiver's background color to the color specified * by the argument, or to the default system color for the control * if the argument is null. * * @param color the new color (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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> */ public void setBackground(Color color) { checkWidget(); if (color != null && color.isDisposed()) { error(SWT.ERROR_INVALID_ARGUMENT); } getRemoteAdapter().preserveBackground(background, backgroundTransparency); background = color; updateBackground(); } /** * Returns the receiver's background color. * * @return the background color * * @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 Color getBackground() { checkWidget(); Control control = findBackgroundControl(); if (control == null) { control = this; } Color result = control.background; if (result == null) { result = getControlThemeAdapter().getBackground(control); } Shell shell = control.getShell(); control = control.parent; while (result == null && control != null) { result = control.getBackground(); control = control == shell ? null : control.parent; } if (result == null) { // Should never happen as the theming must prevent transparency for // shell background colors throw new IllegalStateException("Transparent shell background color"); } return result; } /** * Sets the receiver's background image to the image specified * by the argument, or to the default system color for the control * if the argument is null. The background image is tiled to fill * the available space. * <p> * Note: This operation is a hint and may be overridden by the platform. * For example, on Windows the background of a Button cannot be changed. * </p> * @param image the new image (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> * <!-- <li>ERROR_INVALID_ARGUMENT - if the argument is not a bitmap</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> * * @since 1.1 */ public void setBackgroundImage(Image image) { checkWidget(); if (image != null && image.isDisposed()) { error(SWT.ERROR_INVALID_ARGUMENT); } if (backgroundImage != image) { getRemoteAdapter().preserveBackgroundImage(backgroundImage); backgroundImage = image; } } /** * Returns the receiver's background image. * * @return the background 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> * * @since 1.1 */ public Image getBackgroundImage() { checkWidget(); Control control = findBackgroundControl(); if (control == null) { control = this; } return control.backgroundImage; } /** * Sets the receiver's foreground color to the color specified * by the argument, or to the default system color for the control * if the argument is null. * * @param color the new color (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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> */ public void setForeground(Color color) { checkWidget(); if (color != null && color.isDisposed()) { error(SWT.ERROR_INVALID_ARGUMENT); } getRemoteAdapter().preserveForeground(foreground); foreground = color; } /** * Returns the foreground color that the receiver will use to draw. * * @return the receiver's foreground color * * @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 Color getForeground() { checkWidget(); Color result = foreground; if (result == null) { result = getControlThemeAdapter().getForeground(this); } if (result == null) { // Should never happen as the theming must prevent transparency for // foreground colors throw new IllegalStateException("Transparent foreground color"); } return result; } void updateBackgroundMode() { boolean oldState = hasState(PARENT_BACKGROUND); checkBackground(); if (oldState != hasState(PARENT_BACKGROUND)) { updateBackground(); } } /* * Checks whether parent background should be applied to this control and and * sets PARENT_BACKGROUND state if so. */ // verbatim copy of SWT 3.7.0 GTK void checkBackground() { Shell shell = getShell(); if (this == shell) { return; } removeState(PARENT_BACKGROUND); Composite composite = parent; do { int mode = composite.backgroundMode; if (mode != SWT.INHERIT_NONE) { if (mode == SWT.INHERIT_DEFAULT) { Control control = this; do { if (!control.hasState(THEME_BACKGROUND)) { return; } control = control.parent; } while (control != composite); } addState(PARENT_BACKGROUND); return; } if (composite == shell) { break; } composite = composite._getParent(); } while (true); } /** * Applies the background according to PARENT_BACKGROUND state. */ private void updateBackground() { getRemoteAdapter().preserveBackground(background, backgroundTransparency); backgroundTransparency = background == null && backgroundImage == null && hasState(PARENT_BACKGROUND); } Control findBackgroundControl() { Control result = null; if (background != null || backgroundImage != null) { result = this; } else if (hasState(PARENT_BACKGROUND)) { result = parent.findBackgroundControl(); } return result; } void checkMirrored() { if ((style & SWT.RIGHT_TO_LEFT) != 0) { style |= SWT.MIRRORED; } } ///////// // Fonts /** * Sets the font that the receiver will use to paint textual information * to the font specified by the argument, or to the default font for that * kind of control if the argument is null. * * @param font the new font (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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> */ public void setFont(Font font) { checkWidget(); if (font != null && font.isDisposed()) { error(SWT.ERROR_INVALID_ARGUMENT); } getRemoteAdapter().preserveFont(this.font); this.font = font; } /** * Returns the font that the receiver will use to paint textual information. * * @return the receiver's font * * @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 Font getFont() { checkWidget(); Font result = font; if (result == null) { result = getControlThemeAdapter().getFont(this); } return result; } ///////// // Cursors /** * Sets the receiver's cursor to the cursor specified by the * argument, or to the default cursor for that kind of control * if the argument is null. * <p> * When the mouse pointer passes over a control its appearance * is changed to match the control's cursor. * </p> * * @param cursor the new cursor (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</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> * * @since 1.2 */ public void setCursor(Cursor cursor) { checkWidget(); if (cursor != null && cursor.isDisposed()) { error(SWT.ERROR_INVALID_ARGUMENT); } getRemoteAdapter().preserveCursor(this.cursor); this.cursor = cursor; } /** * Returns the receiver's cursor, or null if it has not been set. * <p> * When the mouse pointer passes over a control its appearance * is changed to match the control's cursor. * </p> * * @return the receiver's cursor or <code>null</code> * * @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> * * @since 1.2 */ public Cursor getCursor() { checkWidget(); return cursor; } ////////////////// // Focus handling /** * Causes the receiver to have the <em>keyboard focus</em>, * such that all keyboard events will be delivered to it. Focus * reassignment will respect applicable platform constraints. * * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to. * * @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 #forceFocus */ public boolean setFocus() { checkWidget(); boolean result = false; if ((style & SWT.NO_FOCUS) == 0) { result = forceFocus(); } return result; } /** * Forces the receiver to have the <em>keyboard focus</em>, causing * all keyboard events to be delivered to it. * * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to. * * @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 #setFocus */ public boolean forceFocus() { checkWidget(); // if (display.focusEvent == SWT.FocusOut) return false; Shell shell = getShell(); // was: Decorations shell = menuShell(); shell.setSavedFocus(this); if (!isEnabled() || !isVisible() || !isActive()) { return false; } if (isFocusControl()) { return true; } shell.setSavedFocus(null); setFocusControl(this); // was: OS.SetFocus( handle ); if (isDisposed()) { return false; } shell.setSavedFocus(this); return isFocusControl(); } /** * Returns <code>true</code> if the receiver has the user-interface * focus, and <code>false</code> otherwise. * * @return the receiver's focus 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 isFocusControl() { checkWidget(); return this == getDisplay().getFocusControl(); } boolean setSavedFocus() { return forceFocus(); } /////////////////////////////////////////////////////////////////////// // Methods to manipulate, transform and query the controls' dimensions /** * Returns a rectangle describing the receiver's size and location * relative to its parent (or its display if its parent is null), * unless the receiver is a shell. In this case, the location is * relative to the display. * * @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() { checkWidget(); return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); } /** * Sets the receiver's size and location to the rectangular * area specified by the argument. The <code>x</code> and * <code>y</code> fields of the rectangle are relative to * the receiver's parent (or its display if its parent is null). * <p> * Note: Attempting to set the width or height of the * receiver to a negative number will cause that * value to be set to zero instead. * </p> * * @param bounds the new bounds for the receiver * * @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 setBounds(Rectangle bounds) { checkWidget(); if (bounds == null) { SWT.error(SWT.ERROR_NULL_ARGUMENT); } setBounds(bounds, true); } /** * Sets the receiver's size and location to the rectangular * area specified by the arguments. The <code>x</code> and * <code>y</code> arguments are relative to the receiver's * parent (or its display if its parent is null), unless * the receiver is a shell. In this case, the <code>x</code> * and <code>y</code> arguments are relative to the display. * <p> * Note: Attempting to set the width or height of the * receiver to a negative number will cause that * value to be set to zero instead. * </p> * * @param x the new x coordinate for the receiver * @param y the new y coordinate for the receiver * @param width the new width for the receiver * @param height the new height for the receiver * * @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 setBounds(int x, int y, int width, int height) { setBounds(new Rectangle(x, y, width, height)); } /** * Sets the receiver's location to the point specified by * the arguments which are relative to the receiver's * parent (or its display if its parent is null), unless * the receiver is a shell. In this case, the point is * relative to the display. * * @param location the new location for the receiver * * @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 setLocation(Point location) { if (location == null) { SWT.error(SWT.ERROR_NULL_ARGUMENT); } Rectangle newBounds = new Rectangle(location.x, location.y, bounds.width, bounds.height); setBounds(newBounds); } /** * Sets the receiver's location to the point specified by * the arguments which are relative to the receiver's * parent (or its display if its parent is null), unless * the receiver is a shell. In this case, the point is * relative to the display. * * @param x the new x coordinate for the receiver * @param y the new y coordinate for the receiver * * @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 setLocation(int x, int y) { setLocation(new Point(x, y)); } /** * Returns a point describing the receiver's location relative * to its parent (or its display if its parent is null), unless * the receiver is a shell. In this case, the point is * relative to the display. * * @return the receiver's location * * @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 Point getLocation() { checkWidget(); return new Point(bounds.x, bounds.y); } /** * Sets the receiver's size to the point specified by the argument. * <p> * Note: Attempting to set the width or height of the * receiver to a negative number will cause them to be * set to zero instead. * </p> * * @param size the new size for the receiver * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the point 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> */ public void setSize(Point size) { if (size == null) { SWT.error(SWT.ERROR_NULL_ARGUMENT); } setBounds(new Rectangle(bounds.x, bounds.y, size.x, size.y)); } /** * Sets the receiver's size to the point specified by the arguments. * <p> * Note: Attempting to set the width or height of the * receiver to a negative number will cause that * value to be set to zero instead. * </p> * * @param width the new width for the receiver * @param height the new height for the receiver * * @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 setSize(int width, int height) { setSize(new Point(width, height)); } /** * Returns a point describing the receiver's size. The * x coordinate of the result is the width of the receiver. * The y coordinate of the result is the height of the * receiver. * * @return the receiver's size * * @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 Point getSize() { checkWidget(); return new Point(bounds.width, bounds.height); } /** * Returns the preferred size of the receiver. * <p> * The <em>preferred size</em> of a control is the size that it would * best be displayed at. The width hint and height hint arguments * allow the caller to ask a control questions such as "Given a particular * width, how high does the control need to be to show all of the contents?" * To indicate that the caller does not wish to constrain a particular * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint. * </p> * * @param wHint the width hint (can be <code>SWT.DEFAULT</code>) * @param hHint the height hint (can be <code>SWT.DEFAULT</code>) * @return the preferred size of 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> * * @see Layout * @see #getBorderWidth * @see #getBounds * @see #getSize * @see #pack(boolean) * @see "computeTrim, getClientArea for controls that implement them" */ public Point computeSize(int wHint, int hHint) { return computeSize(wHint, hHint, true); } /** * Returns the preferred size of the receiver. * <p> * The <em>preferred size</em> of a control is the size that it would * best be displayed at. The width hint and height hint arguments * allow the caller to ask a control questions such as "Given a particular * width, how high does the control need to be to show all of the contents?" * To indicate that the caller does not wish to constrain a particular * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint. * </p><p> * If the changed flag is <code>true</code>, it indicates that the receiver's * <em>contents</em> have changed, therefore any caches that a layout manager * containing the control may have been keeping need to be flushed. When the * control is resized, the changed flag will be <code>false</code>, so layout * manager caches can be retained. * </p> * * @param wHint the width hint (can be <code>SWT.DEFAULT</code>) * @param hHint the height hint (can be <code>SWT.DEFAULT</code>) * @param changed <code>true</code> if the control's contents have changed, and <code>false</code> otherwise * @return the preferred size of 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> * * @see Layout * @see #getBorderWidth * @see #getBounds * @see #getSize * @see #pack(boolean) * @see "computeTrim, getClientArea for controls that implement them" */ public Point computeSize(int wHint, int hHint, boolean changed) { checkWidget(); int width = DEFAULT_WIDTH; int height = DEFAULT_HEIGHT; if (wHint != SWT.DEFAULT) { width = wHint; } if (hHint != SWT.DEFAULT) { height = hHint; } BoxDimensions border = getBorder(); width += border.left + border.right; height += border.top + border.bottom; return new Point(width, height); } /** * Causes the receiver to be resized to its preferred size. * For a composite, this involves computing the preferred size * from its layout, if there is 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 #computeSize(int, int, boolean) */ public void pack() { checkWidget(); pack(true); } /** * Causes the receiver to be resized to its preferred size. * For a composite, this involves computing the preferred size * from its layout, if there is one. * <p> * If the changed flag is <code>true</code>, it indicates that the receiver's * <em>contents</em> have changed, therefore any caches that a layout manager * containing the control may have been keeping need to be flushed. When the * control is resized, the changed flag will be <code>false</code>, so layout * manager caches can be retained. * </p> * * @param changed whether or not the receiver's contents have changed * * @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 #computeSize(int, int, boolean) */ public void pack(boolean changed) { checkWidget(); setSize(computeSize(SWT.DEFAULT, SWT.DEFAULT, changed)); packed = true; } /** * Returns the receiver's border width. * Note: When the theming defines different border widths for the four edges, this method returns * the maximum border width. * * @return the border 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 getBorderWidth() { checkWidget(); BoxDimensions border = getBorder(); int max1 = Math.max(border.left, border.right); int max2 = Math.max(border.top, border.bottom); return Math.max(max1, max2); } BoxDimensions getBorder() { return getControlThemeAdapter().getBorder(this); } BoxDimensions getPadding() { if (bufferedPadding == null) { bufferedPadding = getControlThemeAdapter().getPadding(this); } return bufferedPadding; } private ControlThemeAdapter getControlThemeAdapter() { return getAdapter(ControlThemeAdapter.class); } /** * Returns a point which is the result of converting the * argument, which is specified in display relative coordinates, * to coordinates relative to the receiver. * <p> * @param x the x coordinate to be translated * @param y the y coordinate to be translated * @return the translated coordinates * * @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 Point toControl(int x, int y) { checkWidget(); return getDisplay().map(null, this, x, y); } /** * Returns a point which is the result of converting the * argument, which is specified in display relative coordinates, * to coordinates relative to the receiver. * <p> * @param point the point to be translated (must not be null) * @return the translated coordinates * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the point 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> */ public Point toControl(Point point) { checkWidget(); if (point == null) { error(SWT.ERROR_NULL_ARGUMENT); } return toControl(point.x, point.y); } /** * Returns a point which is the result of converting the * argument, which is specified in coordinates relative to * the receiver, to display relative coordinates. * <p> * @param x the x coordinate to be translated * @param y the y coordinate to be translated * @return the translated coordinates * * @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 Point toDisplay(int x, int y) { checkWidget(); return getDisplay().map(this, null, x, y); } /** * Returns a point which is the result of converting the * argument, which is specified in coordinates relative to * the receiver, to display relative coordinates. * <p> * @param point the point to be translated (must not be null) * @return the translated coordinates * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the point 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> */ public Point toDisplay(Point point) { checkWidget(); if (point == null) { error(SWT.ERROR_NULL_ARGUMENT); } return toDisplay(point.x, point.y); } /////////////////////////// // Layout related methods /** * Returns layout data which is associated with the receiver. * * @return the receiver's layout data * * @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 Object getLayoutData() { checkWidget(); return layoutData; } /** * Sets the layout data associated with the receiver to the argument. * * @param layoutData the new layout data for the receiver. * * @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 setLayoutData(Object layoutData) { checkWidget(); this.layoutData = layoutData; } @SuppressWarnings("unused") void markLayout(boolean changed, boolean all) { /* Do nothing */ } @SuppressWarnings("unused") void updateLayout(boolean resize, boolean all) { /* Do nothing */ } ///////////////////// // ToolTip operations /** * Sets the receiver's tool tip text to the argument, which * may be null indicating that no tool tip text should be shown. * * @param toolTipText 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 toolTipText) { checkWidget(); if (toolTipText != null && isToolTipMarkupEnabledFor(this) && !isValidationDisabledFor(this)) { MarkupValidator.getInstance().validate(toolTipText); } getRemoteAdapter().preserveToolTipText(this.toolTipText); this.toolTipText = toolTipText; } /** * 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() { checkWidget(); return toolTipText; } /////////////////// // Menu operations /** * Sets the receiver's pop up menu to the argument. * All controls may optionally have a pop up * menu that is displayed when the user requests one for * the control. The sequence of key strokes, button presses * and/or button releases that are used to request a pop up * menu is platform specific. * <p> * Note: Disposing of a control that has a pop up menu will * dispose of the menu. To avoid this behavior, set the * menu to null before the control is disposed. * </p> * * @param menu the new pop up menu * * @exception IllegalArgumentException <ul> * <li>ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu</li> * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li> * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</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> */ public void setMenu(Menu menu) { checkWidget(); if (this.menu != menu) { if (menu != null) { if (menu.isDisposed()) { SWT.error(SWT.ERROR_INVALID_ARGUMENT); } if ((menu.getStyle() & SWT.POP_UP) == 0) { SWT.error(SWT.ERROR_MENU_NOT_POP_UP); } if (menu.getParent() != getShell()) { SWT.error(SWT.ERROR_INVALID_PARENT); } } removeMenuDisposeListener(); _setMenu(menu); addMenuDisposeListener(); } } /** * Returns the receiver's pop up menu if it has one, or null * if it does not. All controls may optionally have a pop up * menu that is displayed when the user requests one for * the control. The sequence of key strokes, button presses * and/or button releases that are used to request a pop up * menu is platform specific. * * @return the receiver's menu * * @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 Menu getMenu() { checkWidget(); return menu; } /////////// // Z-Order /** * Moves the receiver above the specified control in the * drawing order. If the argument is null, then the receiver * is moved to the top of the drawing order. The control at * the top of the drawing order will not be covered by other * controls even if they occupy intersecting areas. * * @param control the sibling control (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</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 Control#moveBelow * @see Composite#getChildren */ public void moveAbove(Control control) { checkWidget(); if (control != null && control.isDisposed()) { error(SWT.ERROR_INVALID_ARGUMENT); } if (this instanceof Shell) { // TODO: add support for Shell reordering } else if (control == null || control.parent == parent && control != this) { parent.moveAbove(this, control); } } /** * Moves the receiver below the specified control in the * drawing order. If the argument is null, then the receiver * is moved to the bottom of the drawing order. The control at * the bottom of the drawing order will be covered by all other * controls which occupy intersecting areas. * * @param control the sibling control (or null) * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</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 Control#moveAbove * @see Composite#getChildren */ public void moveBelow(Control control) { checkWidget(); if (control != null && control.isDisposed()) { error(SWT.ERROR_INVALID_ARGUMENT); } if (this instanceof Shell) { // TODO: add support for Shell reordering } else if (control == null || control.parent == parent && control != this) { parent.moveBelow(this, control); } } @Override @SuppressWarnings("unchecked") public <T> T getAdapter(Class<T> adapter) { T result = null; if (adapter == IControlAdapter.class) { if (controlAdapter == null) { controlAdapter = new ControlAdapter(); } result = (T) controlAdapter; } else if (adapter == ControlThemeAdapter.class) { result = (T) super.getAdapter(ThemeAdapter.class); } else { result = super.getAdapter(adapter); } return result; } @Override RemoteAdapter createRemoteAdapter(Widget parent, String id) { ControlRemoteAdapter remoteAdapter = new ControlRemoteAdapter(id); remoteAdapter.setParent(parent); return remoteAdapter; } ////////////////////////////////// // Methods to add/remove listener /** * Adds the listener to the collection of listeners who will * be notified when the control is moved or resized, by sending * it one of the messages defined in the <code>ControlListener</code> * interface. * * @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 ControlListener * @see #removeControlListener */ public void addControlListener(ControlListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } TypedListener typedListener = new TypedListener(listener); addListener(SWT.Move, typedListener); addListener(SWT.Resize, typedListener); } /** * Removes the listener from the collection of listeners who will * be notified when the control is moved or resized. * * @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 ControlListener * @see #addControlListener */ public void removeControlListener(ControlListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } removeListener(SWT.Move, listener); removeListener(SWT.Resize, listener); } /** * Adds the listener to the collection of listeners who will * be notified when mouse buttons are pressed and released, by sending * it one of the messages defined in the <code>MouseListener</code> * interface. * * @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 MouseListener * @see #removeMouseListener * * @since 1.1 */ public void addMouseListener(MouseListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } TypedListener typedListener = new TypedListener(listener); addListener(SWT.MouseDown, typedListener); addListener(SWT.MouseUp, typedListener); addListener(SWT.MouseDoubleClick, typedListener); } /** * Removes the listener from the collection of listeners who will * be notified when mouse buttons are pressed and released. * * @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 MouseListener * @see #addMouseListener * * @since 1.1 */ public void removeMouseListener(MouseListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } removeListener(SWT.MouseDown, listener); removeListener(SWT.MouseUp, listener); removeListener(SWT.MouseDoubleClick, listener); } /** * Adds the listener to the collection of listeners who will * be notified when keys are pressed and released on the system keyboard, by sending * it one of the messages defined in the <code>KeyListener</code> * interface. * <!-- * TODO [rh] investigate whether this statements is true in RWT as well * <p> * When a key listener is added to a control, the control * will take part in widget traversal. By default, all * traversal keys (such as the tab key and so on) are * delivered to the control. In order for a control to take * part in traversal, it should listen for traversal events. * Otherwise, the user can traverse into a control but not * out. Note that native controls such as table and tree * implement key traversal in the operating system. It is * not necessary to add traversal listeners for these controls, * unless you want to override the default traversal. * </p> * --> * <!-- RAP specific --> * <p> * <strong>Note:</strong> the key events in RWT are not meant for * general purpose. * </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 KeyListener * @see #removeKeyListener * * @since 1.2 */ public void addKeyListener(KeyListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } TypedListener typedListener = new TypedListener(listener); addListener(SWT.KeyUp, typedListener); addListener(SWT.KeyDown, typedListener); } /** * Removes the listener from the collection of listeners who will * be notified when keys are pressed and released on the system keyboard. * * @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 KeyListener * @see #addKeyListener * * @since 1.2 */ public void removeKeyListener(KeyListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } removeListener(SWT.KeyUp, listener); removeListener(SWT.KeyDown, listener); } /** * Adds the listener to the collection of listeners who will * be notified when traversal events occur, by sending it * one of the messages defined in the <code>TraverseListener</code> * interface. * * @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 TraverseListener * @see #removeTraverseListener * * @since 1.2 */ public void addTraverseListener(TraverseListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } TypedListener typedListener = new TypedListener(listener); addListener(SWT.Traverse, typedListener); } /** * Removes the listener from the collection of listeners who will * be notified when traversal events occur. * * @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 TraverseListener * @see #addTraverseListener * * @since 1.2 */ public void removeTraverseListener(TraverseListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } removeListener(SWT.Traverse, listener); } /** * Adds the listener to the collection of listeners who will * be notified when the control gains or loses focus, by sending * it one of the messages defined in the <code>FocusListener</code> * interface. * * @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 FocusListener * @see #removeFocusListener */ public void addFocusListener(FocusListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } TypedListener typedListener = new TypedListener(listener); addListener(SWT.FocusIn, typedListener); addListener(SWT.FocusOut, typedListener); } /** * Removes the listener from the collection of listeners who will * be notified when the control gains or loses focus. * * @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 FocusListener * @see #addFocusListener */ public void removeFocusListener(FocusListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } removeListener(SWT.FocusIn, listener); removeListener(SWT.FocusOut, listener); } /** * Adds the listener to the collection of listeners who will * be notified when help events are generated for the control, * by sending it one of the messages defined in the * <code>HelpListener</code> interface. * * @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 HelpListener * @see #removeHelpListener * @since 1.3 */ public void addHelpListener(HelpListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } TypedListener typedListener = new TypedListener(listener); addListener(SWT.Help, typedListener); } /** * Removes the listener from the collection of listeners who will * be notified when the help events are generated for the control. * * @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 HelpListener * @see #addHelpListener * @since 1.3 */ public void removeHelpListener(HelpListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } removeListener(SWT.Help, listener); } /** * Adds the listener to the collection of listeners who will * be notified when a drag gesture occurs, by sending it * one of the messages defined in the <code>DragDetectListener</code> * interface. * * @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 DragDetectListener * @see #removeDragDetectListener * * @since 1.3 */ public void addDragDetectListener(DragDetectListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } TypedListener typedListener = new TypedListener(listener); addListener(SWT.DragDetect, typedListener); } /** * Removes the listener from the collection of listeners who will * be notified when a drag gesture occurs. * * @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 DragDetectListener * @see #addDragDetectListener * * @since 1.3 */ public void removeDragDetectListener(DragDetectListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } removeListener(SWT.DragDetect, listener); } /** * Adds the listener to the collection of listeners who will * be notified when the platform-specific context menu trigger * has occurred, by sending it one of the messages defined in * the <code>MenuDetectListener</code> interface. * * @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 MenuDetectListener * @see #removeMenuDetectListener * * @since 1.3 */ public void addMenuDetectListener(MenuDetectListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } TypedListener typedListener = new TypedListener(listener); addListener(SWT.MenuDetect, typedListener); } /** * Removes the listener from the collection of listeners who will * be notified when the platform-specific context menu trigger has * occurred. * * @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 MenuDetectListener * @see #addMenuDetectListener * * @since 1.3 */ public void removeMenuDetectListener(MenuDetectListener listener) { checkWidget(); if (listener == null) { error(SWT.ERROR_NULL_ARGUMENT); } removeListener(SWT.MenuDetect, listener); } /** * Requests that this control and all of its ancestors be repositioned * their layouts at the earliest opportunity. This should be invoked after * modifying the control in order to inform any dependent layouts of * the change. * <p> * The control will not be repositioned synchronously. This method is * fast-running and only marks the control for future participation in * a deferred layout. * <p> * Invoking this method multiple times before the layout occurs is an * inexpensive no-op. * * @since 3.1 */ public void requestLayout() { getShell().layout(new Control[] { this }, SWT.DEFER); } //////////////// // drawing (Note that we can't really force a redraw. This is just a // fake for event notifications that come on OS systems with redraws) /** * If the argument is <code>false</code>, causes subsequent drawing * operations in the receiver to be ignored. No drawing of any kind * can occur in the receiver until the flag is set to true. * Graphics operations that occurred while the flag was * <code>false</code> are lost. When the flag is set to <code>true</code>, * the entire widget is marked as needing to be redrawn. Nested calls * to this method are stacked. * <p> * Note: This operation is a hint and may not be supported on some * platforms or for some widgets. * </p> * <p> * Note: With RAP we can't really force a redraw. This is just a * fake to enable event notifications that come on OS systems * with redraws. * </p> * * @param redraw the new redraw 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 setRedraw(boolean redraw) { checkWidget(); internalSetRedraw(redraw); } /** * Causes the entire bounds of the receiver to be marked * as needing to be redrawn. * * <p> * Note: With RAP we can't really force a redraw. This is just a * fake to enable event notifications that come on OS systems * with redraws. * </p> * * @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 redraw() { checkWidget(); internalSetRedraw(true); } /** * Causes the rectangular area of the receiver specified by * the arguments to be marked as needing to be redrawn. * The next time a paint request is processed, that area of * the receiver will be painted, including the background. * If the <code>all</code> flag is <code>true</code>, any * children of the receiver which intersect with the specified * area will also paint their intersecting areas. If the * <code>all</code> flag is <code>false</code>, the children * will not be painted. * * @param x the x coordinate of the area to draw * @param y the y coordinate of the area to draw * @param width the width of the area to draw * @param height the height of the area to draw * @param all <code>true</code> if children should redraw, and <code>false</code> otherwise * * @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 #update() * @see PaintListener * @see SWT#NO_BACKGROUND * @see SWT#NO_REDRAW_RESIZE * @see SWT#NO_MERGE_PAINTS * @see SWT#DOUBLE_BUFFERED * @since 1.3 */ // * @see SWT#Paint public void redraw(int x, int y, int width, int height, boolean all) { checkWidget(); if (width > 0 && height > 0) { internalSetRedraw(true, x, y, width, height); } } void internalSetRedraw(boolean redraw) { display.redrawControl(this, redraw); } @SuppressWarnings("unused") void internalSetRedraw(boolean redraw, int x, int y, int width, int height) { display.redrawControl(this, redraw); } /** * Forces all outstanding paint requests for the widget * to be processed before this method returns. If there * are no outstanding paint request, this method does * nothing. * <p> * Note: This method does not cause a redraw. * </p> * * * @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> * * @since 1.3 */ public void update() { checkWidget(); } /** * Changes the parent of the widget to be the one provided if * the underlying operating system supports this feature. * Returns <code>true</code> if the parent is successfully changed. * * @param parent the new parent for the control. * @return <code>true</code> if the parent is changed and <code>false</code> otherwise. * * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> * <li>ERROR_NULL_ARGUMENT - if the parent is <code>null</code></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> * * @since 1.3 */ public boolean setParent(Composite parent) { checkWidget(); if (parent == null) { error(SWT.ERROR_NULL_ARGUMENT); } if (parent.isDisposed()) { error(SWT.ERROR_INVALID_ARGUMENT); } if (!isReparentable()) { return false; } if (this.parent != parent) { releaseParent(); Shell newShell = parent.getShell(); Shell oldShell = getShell(); Decorations newDecorations = parent.menuShell(); Decorations oldDecorations = menuShell(); if (oldShell != newShell || oldDecorations != newDecorations) { fixChildren(newShell, oldShell, newDecorations, oldDecorations); } getRemoteAdapter().preserveParent(this.parent); ReparentedControls.add(this); this.parent = parent; parent.addChild(this); } return true; } /** * Returns <code>true</code> if the underlying operating * system supports this reparenting, otherwise <code>false</code> * * @return <code>true</code> if the widget can be reparented, otherwise <code>false</code> * * @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> * * @since 1.3 */ public boolean isReparentable() { checkWidget(); return true; } /** * Sets the orientation of the receiver, which must be one * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>. * * @param orientation new orientation style * * @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> * * @since 1.4 */ public void setOrientation(int orientation) { checkWidget(); int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT; if ((orientation & flags) == 0 || (orientation & flags) == flags) { return; } getRemoteAdapter().preserveOrientation(style & flags); style &= ~SWT.MIRRORED; style &= ~flags; style |= orientation & flags; updateOrientation(); checkMirrored(); } /** * Returns the orientation of the receiver, which will be one of the * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>. * * @return the orientation style * * @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> * * @since 1.4 */ public int getOrientation() { checkWidget(); return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT); } void updateOrientation() { // subclasses may override } //////////////// // Accessibility /** * Returns the accessible object for the receiver. * <p> * If this is the first time this object is requested, * then the object is created and returned. The object * returned by getAccessible() does not need to be disposed. * </p> * * @return the accessible object * * @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 Accessible#addAccessibleListener * @see Accessible#addAccessibleControlListener * * @since 1.4 */ public Accessible getAccessible() { checkWidget(); if (accessible == null) { accessible = Accessible.internal_new_Accessible(this); } return accessible; } //////////////////// // Touch and Gesture /** * Adds the listener to the collection of listeners who will * be notified when gesture events are generated for the control, * by sending it one of the messages defined in the * <code>GestureListener</code> interface. * * @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 GestureListener * @see #removeGestureListener * * @since 1.4 */ public void addGestureListener(GestureListener listener) { checkWidget(); } /** * Removes the listener from the collection of listeners who will * be notified when gesture events are generated for the control. * * @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 GestureListener * @see #addGestureListener * * @since 1.4 */ public void removeGestureListener(GestureListener listener) { checkWidget(); } /** * Adds the listener to the collection of listeners who will * be notified when touch events occur, by sending it * one of the messages defined in the <code>TouchListener</code> * interface. * <p> * NOTE: You must also call <code>setTouchEnabled</code> to notify the * windowing toolkit that you want touch events to be generated. * </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 TouchListener * @see #removeTouchListener * * @since 1.4 */ public void addTouchListener(TouchListener listener) { checkWidget(); } /** * Removes the listener from the collection of listeners who will * be notified when touch events occur. * * @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 TouchListener * @see #addTouchListener * * @since 1.4 */ public void removeTouchListener(TouchListener listener) { checkWidget(); } /** * Sets whether the receiver should accept touch events. By default, a Control does not accept * touch events. No error or exception is thrown if the underlying hardware does not support touch * input. * * @param enabled the new touch-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> * * @since 1.4 */ public void setTouchEnabled(boolean enabled) { checkWidget(); } /** * Returns <code>true</code> if this control is receiving OS-level touch events, * otherwise <code>false</code> * <p> * Note that this method will return false if the current platform does not support touch-based * input. If this method does return true, gesture events will not be sent to the control. * * @return <code>true</code> if the widget is currently receiving touch events; <code>false</code> * otherwise. * * @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> * * @since 1.4 */ public boolean getTouchEnabled() { checkWidget(); return false; } @Override public void setData(String key, Object value) { if (RWT.TOOLTIP_MARKUP_ENABLED.equals(key) && isToolTipMarkupEnabledFor(this)) { // MARKUP_ENABLED cannot be changed once it is set return; } if (RWT.ACTIVE_KEYS.equals(key)) { if (value != null && !(value instanceof String[])) { String mesg = "Illegal value for RWT.ACTIVE_KEYS in data, must be a string array"; throw new IllegalArgumentException(mesg); } ActiveKeysUtil.preserveActiveKeys(this); } if (RWT.CANCEL_KEYS.equals(key)) { if (value != null && !(value instanceof String[])) { String mesg = "Illegal value for RWT.CANCEL_KEYS in data, must be a string array"; throw new IllegalArgumentException(mesg); } ActiveKeysUtil.preserveCancelKeys(this); } if (RWT.CUSTOM_VARIANT.equals(key)) { bufferedPadding = null; } super.setData(key, value); } //////////// // Disposal @Override void releaseParent() { if (parent != null) { parent.removeChild(this); } } @Override void releaseWidget() { if (menu != null) { removeMenuDisposeListener(); menu.dispose(); menu = null; } Shell shell = internalGetShell(); if (display.getFocusControl() == this) { Control focusControl = parent; while (focusControl != null && focusControl.isInDispose()) { focusControl = focusControl.getParent(); } if (focusControl != null && focusControl.internalGetShell() != shell) { focusControl = null; } setFocusControl(focusControl); } if (shell.getSavedFocus() == this) { shell.setSavedFocus(null); } internalSetRedraw(false); if (accessible != null) { accessible.internal_dispose_Accessible(); } accessible = null; super.releaseWidget(); } ///////////// // Tab order boolean isTabGroup() { Control[] tabList = parent._getTabList(); if (tabList != null) { for (int i = 0; i < tabList.length; i++) { if (tabList[i] == this) { return true; } } } return false; } //////////////////////////////// // Helping methods for setBounds void setBounds(Rectangle bounds, boolean updateMode) { Point oldLocation = getLocation(); Point oldSize = getSize(); _setBounds(new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height)); if (updateMode) { updateMode(); } clearPacked(oldSize); notifyMove(oldLocation); notifyResize(oldSize); } void _setBounds(Rectangle rectangle) { getRemoteAdapter().preserveBounds(bounds); bounds = rectangle; bounds.width = Math.max(0, bounds.width); bounds.height = Math.max(0, bounds.height); } private void _setMenu(Menu menu) { getRemoteAdapter().preserveMenu(this.menu); this.menu = menu; } void updateMode() { // subclasses may override } private void clearPacked(Point oldSize) { if (!oldSize.equals(getSize())) { packed = false; } } void notifyResize(Point oldSize) { if (!oldSize.equals(getSize())) { notifyListeners(SWT.Resize, new Event()); } } void notifyMove(Point oldLocation) { if (!oldLocation.equals(getLocation())) { notifyListeners(SWT.Move, new Event()); } } //////////////////////// // Focus helping methods private void setFocusControl(Control control) { if (control != null) { display.setActiveShell(control.getShell()); } // focus IDisplayAdapter displayAdapter = display.getAdapter(IDisplayAdapter.class); displayAdapter.setFocusControl(control, true); // active if (control != null) { Shell shell = control.getShell(); shell.setActiveControl(control); } } Control[] getPath() { int count = 0; Shell shell = getShell(); Control control = this; while (control != shell) { count++; control = control.parent; } control = this; Control[] result = new Control[count]; while (control != shell) { result[--count] = control; control = control.parent; } return result; } // Copied from SWT/win32 as is @SuppressWarnings("all") boolean isFocusAncestor(Control control) { while (control != null && control != this && !(control instanceof Shell)) { control = control.parent; } return control == this; } // Copied from SWT/win32 as is void fixFocus(Control focusControl) { Shell shell = getShell(); Control control = this; while (control != shell && (control = control.parent) != null) { if (control.setFixedFocus()) { return; } } shell.setSavedFocus(focusControl); // OS.SetFocus (0); // Replacement for OS.setFocus( 0 ) IDisplayAdapter displayAdapter = display.getAdapter(IDisplayAdapter.class); displayAdapter.setFocusControl(null, true); } // Copied from SWT/win32 as is boolean setFixedFocus() { if ((style & SWT.NO_FOCUS) != 0) { return false; } return forceFocus(); } boolean isActive() { Shell shell = getShell(); boolean result = shell.getEnabled(); Shell[] allShells = getDisplay().getShells(); int bits = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL | SWT.PRIMARY_MODAL; int shellIndex = allShells.length; for (int i = 0; i < allShells.length && result; i++) { if (allShells[i] == shell) { shellIndex = i; } if ((allShells[i].style & bits) != 0 && shellIndex < i) { result = false; } } return result; } Decorations menuShell() { return parent.menuShell(); } void fixChildren(Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations) { oldShell.fixShell(newShell, this); oldDecorations.fixDecorations(newDecorations, this); } private void preserveState(int flag) { if ((flag & DISABLED) != 0) { getRemoteAdapter().preserveEnabled(!hasState(DISABLED)); } if ((flag & HIDDEN) != 0) { getRemoteAdapter().preserveVisible(!hasState(HIDDEN)); } } private void addMenuDisposeListener() { if (menu != null) { if (menuDisposeListener == null) { menuDisposeListener = new Listener() { @Override public void handleEvent(Event event) { _setMenu(null); } }; } menu.addListener(SWT.Dispose, menuDisposeListener); } } private void removeMenuDisposeListener() { if (menu != null) { menu.removeListener(SWT.Dispose, menuDisposeListener); } } private ControlRemoteAdapter getRemoteAdapter() { return (ControlRemoteAdapter) getAdapter(RemoteAdapter.class); } }