+ *
+ * @since 3.2
+ */
+public static Frame getFrame (Composite parent) {
+ if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if ((parent.getStyle () & SWT.EMBEDDED) == 0) return null;
+ return (Frame)parent.getData(EMBEDDED_FRAME_KEY);
+}
+
+/**
+ * Creates a new java.awt.Frame. This frame is the root for
+ * the AWT components that will be embedded within the composite. In order
+ * for the embedding to succeed, the composite must have been created
+ * with the SWT.EMBEDDED style.
+ *
+ * IMPORTANT: As of JDK1.5, the embedded frame does not receive mouse events.
+ * When a lightweight component is added as a child of the embedded frame,
+ * the cursor does not change. In order to work around both these problems, it is
+ * strongly recommended that a heavyweight component such as java.awt.Panel
+ * be added to the frame as the root of all components.
+ *
+ *
+ * @param parent the parent Composite of the new java.awt.Frame
+ * @return a java.awt.Frame to be the parent of the embedded AWT components
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_ARGUMENT - if the parent Composite does not have the SWT.EMBEDDED style
+ *
+ *
+ * @since 3.0
+ */
+public static Frame new_Frame (final Composite parent) {
+ if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if ((parent.getStyle () & SWT.EMBEDDED) == 0) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ final Container container = ((CComposite)parent.handle).getClientArea();
+ final Frame frame = new Frame() {
+ public void setLayout(LayoutManager mgr) {
+ if(container != null) {
+ container.setLayout(mgr);
+ }
+ }
+ protected void addImpl(Component comp, Object constraints, int index) {
+ container.add(comp, constraints, index);
+ }
+ };
+ container.setLayout(new BorderLayout(0, 0));
+ parent.setData(EMBEDDED_FRAME_KEY, frame);
+// frame.addNotify();
+
+ /*
+ * Generate the appropriate events to activate and deactivate
+ * the embedded frame. This is needed in order to make keyboard
+ * focus work properly for lightweights.
+ */
+ Listener listener = new Listener () {
+ public void handleEvent (Event e) {
+ switch (e.type) {
+ case SWT.Dispose:
+ parent.setVisible(false);
+ EventQueue.invokeLater(new Runnable () {
+ public void run () {
+ frame.dispose ();
+ }
+ });
+ break;
+ case SWT.Activate:
+ EventQueue.invokeLater(new Runnable () {
+ public void run () {
+ if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 4, 0)) {
+ frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_ACTIVATED));
+ frame.dispatchEvent (new FocusEvent (frame, FocusEvent.FOCUS_GAINED));
+ } else {
+ frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_ACTIVATED));
+ frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_GAINED_FOCUS));
+ }
+ }
+ });
+ break;
+ case SWT.Deactivate:
+ EventQueue.invokeLater(new Runnable () {
+ public void run () {
+ if (Library.JAVA_VERSION < Library.JAVA_VERSION(1, 4, 0)) {
+ frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_DEACTIVATED));
+ frame.dispatchEvent (new FocusEvent (frame, FocusEvent.FOCUS_LOST));
+ } else {
+ frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_LOST_FOCUS));
+ frame.dispatchEvent (new WindowEvent (frame, WindowEvent.WINDOW_DEACTIVATED));
+ }
+ }
+ });
+ break;
+ }
+ }
+ };
+ parent.addListener (SWT.Activate, listener);
+ parent.addListener (SWT.Deactivate, listener);
+ parent.addListener (SWT.Dispose, listener);
+
+ parent.getDisplay().asyncExec(new Runnable() {
+ public void run () {
+ if (parent.isDisposed()) return;
+ final Rectangle clientArea = parent.getClientArea();
+ EventQueue.invokeLater(new Runnable () {
+ public void run () {
+ frame.setSize (clientArea.width, clientArea.height);
+ frame.validate ();
+ }
+ });
+ }
+ });
+ return frame;
+}
+
+/**
+ * Creates a new Shell. This Shell is the root for
+ * the SWT widgets that will be embedded within the AWT canvas.
+ *
+ * @param display the display for the new Shell
+ * @param parent the parent java.awt.Canvas of the new Shell
+ * @return a Shell to be the parent of the embedded SWT widgets
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the display is null
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_ARGUMENT - if the parent's peer is not created
+ *
+ *
+ * @since 3.0
+ */
+public static Shell new_Shell (final Display display, final Canvas parent) {
+ if (display == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ Utils.notImplemented(); return null;
+// int handle = 0;
+// try {
+// loadLibrary ();
+// handle = getAWTHandle (parent);
+// } catch (Throwable e) {
+// SWT.error (SWT.ERROR_NOT_IMPLEMENTED, e);
+// }
+// if (handle == 0) SWT.error (SWT.ERROR_INVALID_ARGUMENT, null, " [peer not created]");
+//
+// final Shell shell = Shell.win32_new (display, handle);
+// parent.addComponentListener(new ComponentAdapter () {
+// public void componentResized (ComponentEvent e) {
+// display.syncExec (new Runnable () {
+// public void run () {
+// Dimension dim = parent.getSize ();
+// shell.setSize (dim.width, dim.height);
+// }
+// });
+// }
+// });
+// shell.setVisible (true);
+// return shell;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Accessibility/swing/org/eclipse/swt/accessibility/Accessible.java b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/swing/org/eclipse/swt/accessibility/Accessible.java
new file mode 100644
index 00000000000..6608a5b0e45
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Accessibility/swing/org/eclipse/swt/accessibility/Accessible.java
@@ -0,0 +1,346 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.accessibility;
+
+
+import java.util.Vector;
+
+import javax.accessibility.AccessibleContext;
+import javax.swing.SwingUtilities;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Instances of this class provide a bridge between application
+ * code and assistive technology clients. Many platforms provide
+ * default accessible behavior for most widgets, and this class
+ * allows that default behavior to be overridden. Applications
+ * can get the default Accessible object for a control by sending
+ * it getAccessible, and then add an accessible listener
+ * to override simple items like the name and help string, or they
+ * can add an accessible control listener to override complex items.
+ * As a rule of thumb, an application would only want to use the
+ * accessible control listener to implement accessibility for a
+ * custom control.
+ *
+ * @see Control#getAccessible
+ * @see AccessibleListener
+ * @see AccessibleEvent
+ * @see AccessibleControlListener
+ * @see AccessibleControlEvent
+ *
+ * @since 2.0
+ */
+public class Accessible {
+ Control control;
+ AccessibleContext accessibleContext;
+ Vector accessibleListeners = new Vector();
+ Vector accessibleControlListeners = new Vector();
+ Vector textListeners = new Vector ();
+
+ Accessible(Control control) {
+ this.control = control;
+ accessibleContext = control.handle.getAccessibleContext();
+ }
+
+ /**
+ * Invokes platform specific functionality to allocate a new accessible object.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Accessible. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param control the control to get the accessible object for
+ * @return the platform specific accessible object
+ */
+ public static Accessible internal_new_Accessible(Control control) {
+ return new Accessible(control);
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an accessible client asks for certain strings,
+ * such as name, description, help, or keyboard shortcut. The
+ * listener is notified by sending it one of the messages defined
+ * in the AccessibleListener interface.
+ *
+ * @param listener the listener that should be notified when the receiver
+ * is asked for a name, description, help, or keyboard shortcut string
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
+ *
+ *
+ * @see AccessibleListener
+ * @see #removeAccessibleListener
+ */
+ public void addAccessibleListener(AccessibleListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ accessibleListeners.addElement(listener);
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will
+ * be notified when an accessible client asks for certain strings,
+ * such as name, description, help, or keyboard shortcut.
+ *
+ * @param listener the listener that should no longer be notified when the receiver
+ * is asked for a name, description, help, or keyboard shortcut string
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
+ *
+ *
+ * @see AccessibleListener
+ * @see #addAccessibleListener
+ */
+ public void removeAccessibleListener(AccessibleListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ accessibleListeners.removeElement(listener);
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an accessible client asks for custom control
+ * specific information. The listener is notified by sending it
+ * one of the messages defined in the AccessibleControlListener
+ * interface.
+ *
+ * @param listener the listener that should be notified when the receiver
+ * is asked for custom control specific information
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
+ *
+ *
+ * @see AccessibleControlListener
+ * @see #removeAccessibleControlListener
+ */
+ public void addAccessibleControlListener(AccessibleControlListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ accessibleControlListeners.addElement(listener);
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will
+ * be notified when an accessible client asks for custom control
+ * specific information.
+ *
+ * @param listener the listener that should no longer be notified when the receiver
+ * is asked for custom control specific information
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
+ *
+ *
+ * @see AccessibleControlListener
+ * @see #addAccessibleControlListener
+ */
+ public void removeAccessibleControlListener(AccessibleControlListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ accessibleControlListeners.removeElement(listener);
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an accessible client asks for custom text control
+ * specific information. The listener is notified by sending it
+ * one of the messages defined in the AccessibleTextListener
+ * interface.
+ *
+ * @param listener the listener that should be notified when the receiver
+ * is asked for custom text control specific information
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
+ *
+ *
+ * @see AccessibleTextListener
+ * @see #removeAccessibleTextListener
+ *
+ * @since 3.0
+ */
+ public void addAccessibleTextListener (AccessibleTextListener listener) {
+ checkWidget ();
+ if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ textListeners.addElement (listener);
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will
+ * be notified when an accessible client asks for custom text control
+ * specific information.
+ *
+ * @param listener the listener that should no longer be notified when the receiver
+ * is asked for custom text control specific information
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
+ *
+ *
+ * @see AccessibleTextListener
+ * @see #addAccessibleTextListener
+ *
+ * @since 3.0
+ */
+ public void removeAccessibleTextListener (AccessibleTextListener listener) {
+ checkWidget ();
+ if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ textListeners.removeElement (listener);
+ }
+
+ /**
+ * Returns the control for this Accessible object.
+ *
+ * @return the receiver's control
+ * @since 3.0
+ */
+ public Control getControl() {
+ return control;
+ }
+
+ /**
+ * Sends a message to accessible clients that the child selection
+ * within a custom container control has changed.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
+ *
+ *
+ * @since 3.0
+ */
+ public void selectionChanged () {
+ }
+
+ /**
+ * Sends a message to accessible clients that the text
+ * caret has moved within a custom control.
+ *
+ * @param index the new caret index within the control
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
+ *
+ *
+ * @since 3.0
+ */
+ public void textCaretMoved (int index) {
+ }
+
+ /**
+ * Sends a message to accessible clients that the text
+ * within a custom control has changed.
+ *
+ * @param type the type of change, one of ACC.NOTIFY_TEXT_INSERT
+ * or ACC.NOTIFY_TEXT_DELETE
+ * @param startIndex the text index within the control where the insertion or deletion begins
+ * @param length the non-negative length in characters of the insertion or deletion
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
+ *
+ *
+ * @see ACC#TEXT_INSERT
+ * @see ACC#TEXT_DELETE
+ *
+ * @since 3.0
+ */
+ public void textChanged (int type, int startIndex, int length) {
+ }
+
+ /**
+ * Sends a message to accessible clients that the text
+ * selection has changed within a custom control.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
+ *
+ *
+ * @since 3.0
+ */
+ public void textSelectionChanged () {
+ }
+
+ /**
+ * Sends a message to accessible clients indicating that the focus
+ * has changed within a custom control.
+ *
+ * @param childID an identifier specifying a child of the control
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control
+ *
+ */
+ public void setFocus(int childID) {
+ }
+
+ /**
+ * Invokes platform specific functionality to dispose an accessible object.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Accessible. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ */
+ public void internal_dispose_Accessible() {
+ }
+
+ /* checkWidget was copied from Widget, and rewritten to work in this package */
+ void checkWidget () {
+ if (!isValidThread ()) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ if (control.isDisposed ()) SWT.error (SWT.ERROR_WIDGET_DISPOSED);
+ }
+
+ /* isValidThread was copied from Widget, and rewritten to work in this package */
+ boolean isValidThread () {
+ return control.getDisplay ().getThread () == Thread.currentThread () || SwingUtilities.isEventDispatchThread();
+ }
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java b/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java
index 0bcc46d6cc6..b590e1db2f6 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Browser/common/org/eclipse/swt/browser/Browser.java
@@ -1,1204 +1,1204 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2022 IBM Corporation and others.
- *
- * This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License 2.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.swt.browser;
-
-import org.eclipse.swt.*;
-import org.eclipse.swt.widgets.*;
-
-/**
- * Instances of this class implement the browser user interface
- * metaphor. It allows the user to visualize and navigate through
- * HTML documents.
- *
- * Note that although this class is a subclass of Composite,
- * it does not make sense to set a layout on it.
- *
- * IMPORTANT: This class is not intended to be subclassed.
- *
- *
- * @see Browser snippets
- * @see SWT Examples: ControlExample, BrowserExample
- * @see Sample code and further information
- *
- * @since 3.0
- * @noextend This class is not intended to be subclassed by clients.
- */
-
-public class Browser extends Composite {
- WebBrowser webBrowser;
- int userStyle;
- boolean isClosing;
-
- static int DefaultType = SWT.DEFAULT;
-
- static final String NO_INPUT_METHOD = "org.eclipse.swt.internal.gtk.noInputMethod"; //$NON-NLS-1$
- static final String PACKAGE_PREFIX = "org.eclipse.swt.browser."; //$NON-NLS-1$
- static final String PROPERTY_DEFAULTTYPE = "org.eclipse.swt.browser.DefaultType"; //$NON-NLS-1$
-
-/**
- * Constructs a new instance of this class given its parent
- * and a style value describing its behavior and appearance.
- *
- * The style value is either one of the style constants defined in
- * class SWT which is applicable to instances of this
- * class, or must be built by bitwise OR'ing together
- * (that is, using the int "|" operator) two or more
- * of those SWT style constants. The class description
- * lists the style constants that are applicable to the class.
- * Style bits are also inherited from superclasses.
- *
- *
- * @param parent a widget which will be the parent of the new instance (cannot be null)
- * @param style the style of widget to construct
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the parent is null
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
- *
- * @exception SWTError
- *
ERROR_NO_HANDLES if a handle could not be obtained for browser creation
- *
- *
- * @see Widget#getStyle
- *
- * @since 3.0
- */
-public Browser (Composite parent, int style) {
- super (checkParent (parent), checkStyle (style));
- userStyle = style;
-
- String platform = SWT.getPlatform ();
- if ("gtk".equals (platform)) { //$NON-NLS-1$
- parent.getDisplay ().setData (NO_INPUT_METHOD, null);
- }
-
- style = getStyle ();
- webBrowser = new BrowserFactory ().createWebBrowser (style);
- if (webBrowser != null) {
- webBrowser.setBrowser (this);
- webBrowser.create (parent, style);
- return;
- }
- dispose ();
-
- String errMsg = " because there is no underlying browser available.\n";
- switch (SWT.getPlatform()) {
- case "gtk":
- errMsg = errMsg + "Please ensure that WebKit with its GTK 3.x/4.x bindings is installed.";
- break;
- case "cocoa":
- errMsg = errMsg + "SWT failed to load the WebKit library.\n";
- break;
- case "win32":
- errMsg = errMsg + "SWT uses either IE or WebKit. Either the SWT.WEBKIT flag is passed and the WebKit library was not "
- + "loaded properly by SWT, or SWT failed to load IE.\n";
- break;
- default:
- break;
- }
- SWT.error (SWT.ERROR_NO_HANDLES, null, errMsg);
-}
-
-static Composite checkParent (Composite parent) {
- String platform = SWT.getPlatform ();
- if (!"gtk".equals (platform)) return parent; //$NON-NLS-1$
-
- /*
- * Note. Mozilla provides all IM support needed for text input in web pages.
- * If SWT creates another input method context for the widget it will cause
- * indeterminate results to happen (hangs and crashes). The fix is to prevent
- * SWT from creating an input method context for the Browser widget.
- */
- if (parent != null && !parent.isDisposed ()) {
- Display display = parent.getDisplay ();
- if (display != null) {
- if (display.getThread () == Thread.currentThread ()) {
- display.setData (NO_INPUT_METHOD, "true"); //$NON-NLS-1$
- }
- }
- }
- return parent;
-}
-
-static int checkStyle(int style) {
- String platform = SWT.getPlatform ();
- if (DefaultType == SWT.DEFAULT) {
- /*
- * Some Browser clients that explicitly specify the native renderer to use (by
- * creating a Browser with SWT.WEBKIT) may also need to specify that all
- * "default" Browser instances (those created with style SWT.NONE) should use
- * this renderer as well. This may be needed in order to avoid incompatibilities
- * that can arise from having multiple native renderers loaded within the same
- * process. A client can do this by setting the
- * "org.eclipse.swt.browser.DefaultType" java system property to a value like
- * "ie" or "webkit".
- */
-
- /*
- * Plug-ins need an opportunity to set the org.eclipse.swt.browser.DefaultType
- * system property before the first Browser is created. To facilitate this,
- * reflection is used to reference non-existent class
- * org.eclipse.swt.browser.BrowserInitializer the first time a Browser is created.
- * A client wishing to use this hook can do so by creating a fragment of
- * org.eclipse.swt that implements this class and sets the system property in its
- * static initializer.
- */
- try {
- Class.forName ("org.eclipse.swt.browser.BrowserInitializer"); //$NON-NLS-1$
- } catch (ClassNotFoundException e) {
- /* no fragment is providing this class, which is the typical case */
- }
-
- String value = System.getProperty (PROPERTY_DEFAULTTYPE);
- if (value != null) {
- int index = 0;
- int length = value.length();
- do {
- int newIndex = value.indexOf(',', index);
- if (newIndex == -1) {
- newIndex = length;
- }
- String current = value.substring(index, newIndex).trim();
- if (current.equalsIgnoreCase ("webkit")) { //$NON-NLS-1$
- DefaultType = SWT.WEBKIT;
- break;
- } else if (current.equalsIgnoreCase ("edge") && "win32".equals (platform)) { //$NON-NLS-1$ //$NON-NLS-2$
- DefaultType = SWT.EDGE;
- } else if (current.equalsIgnoreCase ("ie") && "win32".equals (platform)) { //$NON-NLS-1$ //$NON-NLS-2$
- DefaultType = SWT.NONE;
- break;
- }
- index = newIndex + 1;
- } while (index < length);
- }
- if (DefaultType == SWT.DEFAULT) {
- DefaultType = SWT.NONE;
- }
- }
- /* If particular backend isn't specified, use the value from the system property. */
- if ((style & (SWT.WEBKIT | SWT.EDGE)) == 0) {
- style |= DefaultType;
- }
- if ("win32".equals (platform) && (style & SWT.EDGE) != 0) { //$NON-NLS-1$
- /* Hack to enable Browser to receive focus. */
- style |= SWT.EMBEDDED;
- }
- return style;
-}
-
-@Override
-protected void checkWidget () {
- super.checkWidget ();
-}
-
-/**
- * Clears all session cookies from all current Browser instances.
- *
- * @since 3.2
- */
-public static void clearSessions () {
- WebBrowser.clearSessions ();
-}
-
-/**
- * Returns the value of a cookie that is associated with a URL.
- * Note that cookies are shared amongst all Browser instances.
- *
- * @param name the cookie name
- * @param url the URL that the cookie is associated with
- * @return the cookie value, or null if no such cookie exists
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the name is null
- *
ERROR_NULL_ARGUMENT - if the url is null
- *
- *
- * @since 3.5
- */
-public static String getCookie (String name, String url) {
- if (name == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- return WebBrowser.GetCookie (name, url);
-}
-
-/**
- * Sets a cookie on a URL. Note that cookies are shared amongst all Browser instances.
- *
- * The value parameter must be a cookie header string that
- * complies with RFC 2109.
- * The value is passed through to the native browser unchanged.
- *
- * Example value strings:
- * foo=bar (basic session cookie)
- * foo=bar; path=/; domain=.eclipse.org (session cookie)
- * foo=bar; expires=Tue, 01-Jan-2030 00:00:01 GMT (persistent cookie)
- * foo=; expires=Thu, 01-Jan-1970 00:00:01 GMT (deletes cookie foo)
- *
- * @param value the cookie value
- * @param url the URL to associate the cookie with
- * @return true if the cookie was successfully set and false otherwise
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the value is null
- *
ERROR_NULL_ARGUMENT - if the url is null
- *
- *
- * @since 3.5
- */
-public static boolean setCookie (String value, String url) {
- if (value == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- return WebBrowser.SetCookie (value, url, true);
-}
-
-/**
- * Adds the listener to the collection of listeners who will be
- * notified when authentication is required.
- *
- * This notification occurs when a page requiring authentication is
- * encountered.
- *
- *
- * @param listener the listener which should be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.5
- */
-public void addAuthenticationListener (AuthenticationListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.addAuthenticationListener (listener);
-}
-
-/**
- * Adds the listener to the collection of listeners who will be
- * notified when the window hosting the receiver should be closed.
- *
- * This notification occurs when a javascript command such as
- * window.close gets executed by a Browser.
- *
- *
- * @param listener the listener which should be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void addCloseWindowListener (CloseWindowListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.addCloseWindowListener (listener);
-}
-
-/**
- * Adds the listener to the collection of listeners who will be
- * notified when the current location has changed or is about to change.
- *
- * This notification typically occurs when the application navigates
- * to a new location with {@link #setUrl(String)} or when the user
- * activates a hyperlink.
- *
- *
- * @param listener the listener which should be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void addLocationListener (LocationListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.addLocationListener (listener);
-}
-
-/**
- * Adds the listener to the collection of listeners who will be
- * notified when a new window needs to be created.
- *
- * This notification occurs when a javascript command such as
- * window.open gets executed by a Browser.
- *
- *
- * @param listener the listener which should be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void addOpenWindowListener (OpenWindowListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.addOpenWindowListener (listener);
-}
-
-/**
- * Adds the listener to the collection of listeners who will be
- * notified when a progress is made during the loading of the current
- * URL or when the loading of the current URL has been completed.
- *
- * @param listener the listener which should be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void addProgressListener (ProgressListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.addProgressListener (listener);
-}
-
-/**
- * Adds the listener to the collection of listeners who will be
- * notified when the status text is changed.
- *
- * The status text is typically displayed in the status bar of
- * a browser application.
- *
- *
- * @param listener the listener which should be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void addStatusTextListener (StatusTextListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.addStatusTextListener (listener);
-}
-
-/**
- * Adds the listener to the collection of listeners who will be
- * notified when the title of the current document is available
- * or has changed.
- *
- * @param listener the listener which should be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void addTitleListener (TitleListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.addTitleListener (listener);
-}
-
-/**
- * Adds the listener to the collection of listeners who will be
- * notified when a window hosting the receiver needs to be displayed
- * or hidden.
- *
- * @param listener the listener which should be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void addVisibilityWindowListener (VisibilityWindowListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.addVisibilityWindowListener (listener);
-}
-
-/**
- * Navigate to the previous session history item.
- *
- * @return true if the operation was successful and false otherwise
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- * Executes a script containing javascript commands in the context of the current document.
- * If document-defined functions or properties are accessed by the script then this method
- * should not be invoked until the document has finished loading (ProgressListener.completed()
- * gives notification of this).
- *
- * @param script the script with javascript commands
- *
- * @return true if the operation was successful and false otherwise
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the script is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @see ProgressListener#completed(ProgressEvent)
- *
- * @since 3.1
- */
-public boolean execute (String script) {
- checkWidget();
- if (script == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- return webBrowser.execute (script);
-}
-
-/**
- * Attempts to dispose the receiver, but allows the dispose to be vetoed
- * by the user in response to an onbeforeunload listener
- * in the Browser's current page.
- *
- * @return true if the receiver was disposed, and false otherwise
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- * Evaluates a script containing javascript commands in the context of
- * the current document. If document-defined functions or properties
- * are accessed by the script then this method should not be invoked
- * until the document has finished loading (ProgressListener.completed()
- * gives notification of this).
- *
- * If the script returns a value with a supported type then a java
- * representation of the value is returned. The supported
- * javascript -> java mappings are:
- *
- *
javascript null or undefined -> null
- *
javascript number -> java.lang.Double
- *
javascript string -> java.lang.String
- *
javascript boolean -> java.lang.Boolean
- *
javascript array whose elements are all of supported types -> java.lang.Object[]
- *
- *
- * An SWTException is thrown if the return value has an
- * unsupported type, or if evaluating the script causes a javascript
- * error to be thrown.
- *
- * @param script the script with javascript commands
- *
- * @return the return value, if any, of executing the script
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the script is null
- *
- *
- * @exception SWTException
- *
ERROR_FAILED_EVALUATE when the script evaluation causes a javascript error to be thrown
- *
ERROR_INVALID_RETURN_VALUE when the script returns a value of unsupported type
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- * Evaluates a script containing javascript commands.
- * When trusted is true script is executed in the context of Chrome
- * with Chrome security privileges.
- * When trusted is false script is executed in the context of the
- * current document with normal privileges.
- *
- * If document-defined functions or properties are accessed by the script then
- * this method should not be invoked until the document has finished loading
- * (ProgressListener.completed() gives notification of this).
- *
- * If the script returns a value with a supported type then a java
- * representation of the value is returned. The supported
- * javascript -> java mappings are:
- *
- *
javascript null or undefined -> null
- *
javascript number -> java.lang.Double
- *
javascript string -> java.lang.String
- *
javascript boolean -> java.lang.Boolean
- *
javascript array whose elements are all of supported types -> java.lang.Object[]
- *
- * An SWTException is thrown if the return value has an
- * unsupported type, or if evaluating the script causes a javascript
- * error to be thrown.
- *
- * @param script the script with javascript commands
- * @param trusted true or false depending on the security context to be used
- *
- * @return the return value, if any, of executing the script
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the script is null
- *
- *
- * @exception SWTException
- *
ERROR_FAILED_EVALUATE when the script evaluation causes a javascript error to be thrown
- *
ERROR_INVALID_RETURN_VALUE when the script returns a value of unsupported type
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @see ProgressListener#completed(ProgressEvent)
- */
-public Object evaluate (String script, boolean trusted) throws SWTException {
- checkWidget();
- if (script == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- return webBrowser.evaluate (script, trusted);
-}
-
-/**
- * Navigate to the next session history item.
- *
- * @return true if the operation was successful and false otherwise
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @see #back
- *
- * @since 3.0
- */
-public boolean forward () {
- checkWidget();
- return webBrowser.forward ();
-}
-
-/**
- * Returns the type of native browser being used by this instance.
- * Examples: "ie", "webkit"
- *
- * @return the type of the native browser
- *
- * @since 3.5
- */
-public String getBrowserType () {
- checkWidget();
- return webBrowser.getBrowserType ();
-}
-
-/**
- * Returns true if javascript will be allowed to run in pages
- * subsequently viewed in the receiver, and false otherwise.
- * Note that this may not reflect the javascript enablement on the currently-
- * viewed page if setJavascriptEnabled() has been invoked during
- * its lifetime.
- *
- * @return the receiver's javascript enabled state
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see #setJavascriptEnabled
- *
- * @since 3.5
- */
-public boolean getJavascriptEnabled () {
- checkWidget();
- return webBrowser.jsEnabledOnNextPage;
-}
-
-@Override
-public int getStyle () {
- /*
- * If SWT.BORDER was specified at creation time then getStyle() should answer
- * it even though it is removed for IE on win32 in checkStyle().
- */
- return super.getStyle () | (userStyle & SWT.BORDER);
-}
-
-/**
- * Returns a string with HTML that represents the content of the current page.
- *
- * @return HTML representing the current page or an empty String
- * if this is empty.
- *
Note, the exact return value is platform dependent.
- * For example on Windows, the returned string is the proccessed webpage
- * with javascript executed and missing html tags added.
- * On Linux and OS X, this returns the original HTML before the browser has
- * processed it.
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.4
- */
-public String getText () {
- checkWidget();
- return webBrowser.getText ();
-}
-
-/**
- * Returns the current URL.
- *
- * @return the current URL or an empty String if there is no current URL
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @see #setUrl
- *
- * @since 3.0
- */
-public String getUrl () {
- checkWidget();
- return webBrowser.getUrl ();
-}
-
-/**
- * Returns the JavaXPCOM nsIWebBrowser for the receiver, or null
- * if it is not available. In order for an nsIWebBrowser to be returned all
- * of the following must be true:
- *
the receiver's style must be SWT.MOZILLA
- *
the classes from JavaXPCOM >= 1.8.1.2 must be resolvable at runtime
- *
the version of the underlying XULRunner must be >= 1.8.1.2
- *
- *
- * @return the receiver's JavaXPCOM nsIWebBrowser or null
- *
- * @since 3.3
- * @deprecated SWT.MOZILLA is deprecated and XULRunner as a browser renderer is no longer supported.
- */
-@Deprecated
-public Object getWebBrowser () {
- checkWidget();
- return webBrowser.getWebBrowser ();
-}
-
-/**
- * Returns true if the receiver can navigate to the
- * previous session history item, and false otherwise.
- *
- * @return the receiver's back command enabled state
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see #back
- */
-public boolean isBackEnabled () {
- checkWidget();
- return webBrowser.isBackEnabled ();
-}
-
-@Override
-public boolean isFocusControl () {
- checkWidget();
- if (webBrowser.isFocusControl ()) return true;
- return super.isFocusControl ();
-}
-
-/**
- * Returns true if the receiver can navigate to the
- * next session history item, and false otherwise.
- *
- * @return the receiver's forward command enabled state
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void refresh () {
- checkWidget();
- webBrowser.refresh ();
-}
-
-/**
- * Removes the listener from the collection of listeners who will
- * be notified when authentication is required.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.5
- */
-public void removeAuthenticationListener (AuthenticationListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.removeAuthenticationListener (listener);
-}
-
-/**
- * Removes the listener from the collection of listeners who will
- * be notified when the window hosting the receiver should be closed.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void removeCloseWindowListener (CloseWindowListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.removeCloseWindowListener (listener);
-}
-
-/**
- * Removes the listener from the collection of listeners who will
- * be notified when the current location is changed or about to be changed.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void removeLocationListener (LocationListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.removeLocationListener (listener);
-}
-
-/**
- * Removes the listener from the collection of listeners who will
- * be notified when a new window needs to be created.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void removeOpenWindowListener (OpenWindowListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.removeOpenWindowListener (listener);
-}
-
-/**
- * Removes the listener from the collection of listeners who will
- * be notified when a progress is made during the loading of the current
- * URL or when the loading of the current URL has been completed.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void removeProgressListener (ProgressListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.removeProgressListener (listener);
-}
-
-/**
- * Removes the listener from the collection of listeners who will
- * be notified when the status text is changed.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void removeStatusTextListener (StatusTextListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.removeStatusTextListener (listener);
-}
-
-/**
- * Removes the listener from the collection of listeners who will
- * be notified when the title of the current document is available
- * or has changed.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void removeTitleListener (TitleListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.removeTitleListener (listener);
-}
-
-/**
- * Removes the listener from the collection of listeners who will
- * be notified when a window hosting the receiver needs to be displayed
- * or hidden.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void removeVisibilityWindowListener (VisibilityWindowListener listener) {
- checkWidget();
- if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- webBrowser.removeVisibilityWindowListener (listener);
-}
-
-/**
- * Sets whether javascript will be allowed to run in pages subsequently
- * viewed in the receiver. Note that setting this value does not affect
- * the running of javascript in the current page.
- *
- * @param enabled the receiver's new javascript enabled state
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public void setJavascriptEnabled (boolean enabled) {
- checkWidget();
- webBrowser.jsEnabledOnNextPage = enabled;
-}
-
-/**
- * Renders a string containing HTML. The rendering of the content occurs asynchronously.
- * The rendered page will be given trusted permissions; to render the page with untrusted
- * permissions use setText(String html, boolean trusted) instead.
- *
- * The html parameter is Unicode-encoded since it is a java String.
- * As a result, the HTML meta tag charset should not be set. The charset is implied
- * by the String itself.
- *
- * @param html the HTML content to be rendered
- *
- * @return true if the operation was successful and false otherwise.
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the html is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @see #setText(String,boolean)
- * @see #setUrl
- *
- * @since 3.0
- */
-public boolean setText (String html) {
- checkWidget();
- return setText (html, true);
-}
-
-/**
- * Renders a string containing HTML. The rendering of the content occurs asynchronously.
- * The rendered page can be given either trusted or untrusted permissions.
- *
- * The html parameter is Unicode-encoded since it is a java String.
- * As a result, the HTML meta tag charset should not be set. The charset is implied
- * by the String itself.
- *
- * The trusted parameter affects the permissions that will be granted to the rendered
- * page. Specifying true for trusted gives the page permissions equivalent
- * to a page on the local file system, while specifying false for trusted
- * gives the page permissions equivalent to a page from the internet. Page content should
- * be specified as trusted if the invoker created it or trusts its source, since this would
- * allow (for instance) style sheets on the local file system to be referenced. Page
- * content should be specified as untrusted if its source is not trusted or is not known.
- *
- * @param html the HTML content to be rendered
- * @param trusted false if the rendered page should be granted restricted
- * permissions and true otherwise
- *
- * @return true if the operation was successful and false otherwise.
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the html is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @see #setText(String)
- * @see #setUrl
- *
- * @since 3.6
- */
-public boolean setText (String html, boolean trusted) {
- checkWidget();
- if (html == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- return webBrowser.setText (html, trusted);
-}
-
-/**
- * Begins loading a URL. The loading of its content occurs asynchronously.
- *
- * @param url the URL to be loaded
- *
- * @return true if the operation was successful and false otherwise.
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the url is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- * If the URL causes an HTTP request to be initiated then the provided
- * postData and header arguments, if any, are
- * sent with the request. A value in the headers argument
- * must be a name-value pair with a colon separator in order to be sent
- * (for example: "user-agent: custom").
- *
- * @param url the URL to be loaded
- * @param postData post data to be sent with the request, or null
- * @param headers header lines to be sent with the request, or null
- *
- * @return true if the operation was successful and false otherwise.
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the url is null
- *
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
- *
ERROR_WIDGET_DISPOSED when the widget has been disposed
- *
- *
- * @since 3.0
- */
-public void stop () {
- checkWidget();
- webBrowser.stop ();
-}
-}
+///*******************************************************************************
+// * Copyright (c) 2003, 2022 IBM Corporation and others.
+// *
+// * This program and the accompanying materials
+// * are made available under the terms of the Eclipse Public License 2.0
+// * which accompanies this distribution, and is available at
+// * https://www.eclipse.org/legal/epl-2.0/
+// *
+// * SPDX-License-Identifier: EPL-2.0
+// *
+// * Contributors:
+// * IBM Corporation - initial API and implementation
+// *******************************************************************************/
+//package org.eclipse.swt.browser;
+//
+//import org.eclipse.swt.*;
+//import org.eclipse.swt.widgets.*;
+//
+///**
+// * Instances of this class implement the browser user interface
+// * metaphor. It allows the user to visualize and navigate through
+// * HTML documents.
+// *
+// * Note that although this class is a subclass of Composite,
+// * it does not make sense to set a layout on it.
+// *
+// * IMPORTANT: This class is not intended to be subclassed.
+// *
+// *
+// * @see Browser snippets
+// * @see SWT Examples: ControlExample, BrowserExample
+// * @see Sample code and further information
+// *
+// * @since 3.0
+// * @noextend This class is not intended to be subclassed by clients.
+// */
+//
+//public class Browser extends Composite {
+// WebBrowser webBrowser;
+// int userStyle;
+// boolean isClosing;
+//
+// static int DefaultType = SWT.DEFAULT;
+//
+// static final String NO_INPUT_METHOD = "org.eclipse.swt.internal.gtk.noInputMethod"; //$NON-NLS-1$
+// static final String PACKAGE_PREFIX = "org.eclipse.swt.browser."; //$NON-NLS-1$
+// static final String PROPERTY_DEFAULTTYPE = "org.eclipse.swt.browser.DefaultType"; //$NON-NLS-1$
+//
+///**
+// * Constructs a new instance of this class given its parent
+// * and a style value describing its behavior and appearance.
+// *
+// * The style value is either one of the style constants defined in
+// * class SWT which is applicable to instances of this
+// * class, or must be built by bitwise OR'ing together
+// * (that is, using the int "|" operator) two or more
+// * of those SWT style constants. The class description
+// * lists the style constants that are applicable to the class.
+// * Style bits are also inherited from superclasses.
+// *
+// *
+// * @param parent a widget which will be the parent of the new instance (cannot be null)
+// * @param style the style of widget to construct
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the parent is null
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+// *
+// * @exception SWTError
+// *
ERROR_NO_HANDLES if a handle could not be obtained for browser creation
+// *
+// *
+// * @see Widget#getStyle
+// *
+// * @since 3.0
+// */
+//public Browser (Composite parent, int style) {
+// super (checkParent (parent), checkStyle (style));
+// userStyle = style;
+//
+// String platform = SWT.getPlatform ();
+// if ("gtk".equals (platform)) { //$NON-NLS-1$
+// parent.getDisplay ().setData (NO_INPUT_METHOD, null);
+// }
+//
+// style = getStyle ();
+// webBrowser = new BrowserFactory ().createWebBrowser (style);
+// if (webBrowser != null) {
+// webBrowser.setBrowser (this);
+// webBrowser.create (parent, style);
+// return;
+// }
+// dispose ();
+//
+// String errMsg = " because there is no underlying browser available.\n";
+// switch (SWT.getPlatform()) {
+// case "gtk":
+// errMsg = errMsg + "Please ensure that WebKit with its GTK 3.x/4.x bindings is installed.";
+// break;
+// case "cocoa":
+// errMsg = errMsg + "SWT failed to load the WebKit library.\n";
+// break;
+// case "win32":
+// errMsg = errMsg + "SWT uses either IE or WebKit. Either the SWT.WEBKIT flag is passed and the WebKit library was not "
+// + "loaded properly by SWT, or SWT failed to load IE.\n";
+// break;
+// default:
+// break;
+// }
+// SWT.error (SWT.ERROR_NO_HANDLES, null, errMsg);
+//}
+//
+//static Composite checkParent (Composite parent) {
+// String platform = SWT.getPlatform ();
+// if (!"gtk".equals (platform)) return parent; //$NON-NLS-1$
+//
+// /*
+// * Note. Mozilla provides all IM support needed for text input in web pages.
+// * If SWT creates another input method context for the widget it will cause
+// * indeterminate results to happen (hangs and crashes). The fix is to prevent
+// * SWT from creating an input method context for the Browser widget.
+// */
+// if (parent != null && !parent.isDisposed ()) {
+// Display display = parent.getDisplay ();
+// if (display != null) {
+// if (display.getThread () == Thread.currentThread ()) {
+// display.setData (NO_INPUT_METHOD, "true"); //$NON-NLS-1$
+// }
+// }
+// }
+// return parent;
+//}
+//
+//static int checkStyle(int style) {
+// String platform = SWT.getPlatform ();
+// if (DefaultType == SWT.DEFAULT) {
+// /*
+// * Some Browser clients that explicitly specify the native renderer to use (by
+// * creating a Browser with SWT.WEBKIT) may also need to specify that all
+// * "default" Browser instances (those created with style SWT.NONE) should use
+// * this renderer as well. This may be needed in order to avoid incompatibilities
+// * that can arise from having multiple native renderers loaded within the same
+// * process. A client can do this by setting the
+// * "org.eclipse.swt.browser.DefaultType" java system property to a value like
+// * "ie" or "webkit".
+// */
+//
+// /*
+// * Plug-ins need an opportunity to set the org.eclipse.swt.browser.DefaultType
+// * system property before the first Browser is created. To facilitate this,
+// * reflection is used to reference non-existent class
+// * org.eclipse.swt.browser.BrowserInitializer the first time a Browser is created.
+// * A client wishing to use this hook can do so by creating a fragment of
+// * org.eclipse.swt that implements this class and sets the system property in its
+// * static initializer.
+// */
+// try {
+// Class.forName ("org.eclipse.swt.browser.BrowserInitializer"); //$NON-NLS-1$
+// } catch (ClassNotFoundException e) {
+// /* no fragment is providing this class, which is the typical case */
+// }
+//
+// String value = System.getProperty (PROPERTY_DEFAULTTYPE);
+// if (value != null) {
+// int index = 0;
+// int length = value.length();
+// do {
+// int newIndex = value.indexOf(',', index);
+// if (newIndex == -1) {
+// newIndex = length;
+// }
+// String current = value.substring(index, newIndex).trim();
+// if (current.equalsIgnoreCase ("webkit")) { //$NON-NLS-1$
+// DefaultType = SWT.WEBKIT;
+// break;
+// } else if (current.equalsIgnoreCase ("edge") && "win32".equals (platform)) { //$NON-NLS-1$ //$NON-NLS-2$
+// DefaultType = SWT.EDGE;
+// } else if (current.equalsIgnoreCase ("ie") && "win32".equals (platform)) { //$NON-NLS-1$ //$NON-NLS-2$
+// DefaultType = SWT.NONE;
+// break;
+// }
+// index = newIndex + 1;
+// } while (index < length);
+// }
+// if (DefaultType == SWT.DEFAULT) {
+// DefaultType = SWT.NONE;
+// }
+// }
+// /* If particular backend isn't specified, use the value from the system property. */
+// if ((style & (SWT.WEBKIT | SWT.EDGE)) == 0) {
+// style |= DefaultType;
+// }
+// if ("win32".equals (platform) && (style & SWT.EDGE) != 0) { //$NON-NLS-1$
+// /* Hack to enable Browser to receive focus. */
+// style |= SWT.EMBEDDED;
+// }
+// return style;
+//}
+//
+//@Override
+//protected void checkWidget () {
+// super.checkWidget ();
+//}
+//
+///**
+// * Clears all session cookies from all current Browser instances.
+// *
+// * @since 3.2
+// */
+//public static void clearSessions () {
+// WebBrowser.clearSessions ();
+//}
+//
+///**
+// * Returns the value of a cookie that is associated with a URL.
+// * Note that cookies are shared amongst all Browser instances.
+// *
+// * @param name the cookie name
+// * @param url the URL that the cookie is associated with
+// * @return the cookie value, or null if no such cookie exists
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the name is null
+// *
ERROR_NULL_ARGUMENT - if the url is null
+// *
+// *
+// * @since 3.5
+// */
+//public static String getCookie (String name, String url) {
+// if (name == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// return WebBrowser.GetCookie (name, url);
+//}
+//
+///**
+// * Sets a cookie on a URL. Note that cookies are shared amongst all Browser instances.
+// *
+// * The value parameter must be a cookie header string that
+// * complies with RFC 2109.
+// * The value is passed through to the native browser unchanged.
+// *
+// * Example value strings:
+// * foo=bar (basic session cookie)
+// * foo=bar; path=/; domain=.eclipse.org (session cookie)
+// * foo=bar; expires=Tue, 01-Jan-2030 00:00:01 GMT (persistent cookie)
+// * foo=; expires=Thu, 01-Jan-1970 00:00:01 GMT (deletes cookie foo)
+// *
+// * @param value the cookie value
+// * @param url the URL to associate the cookie with
+// * @return true if the cookie was successfully set and false otherwise
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the value is null
+// *
ERROR_NULL_ARGUMENT - if the url is null
+// *
+// *
+// * @since 3.5
+// */
+//public static boolean setCookie (String value, String url) {
+// if (value == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// if (url == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// return WebBrowser.SetCookie (value, url, true);
+//}
+//
+///**
+// * Adds the listener to the collection of listeners who will be
+// * notified when authentication is required.
+// *
+// * This notification occurs when a page requiring authentication is
+// * encountered.
+// *
+// *
+// * @param listener the listener which should be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.5
+// */
+//public void addAuthenticationListener (AuthenticationListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.addAuthenticationListener (listener);
+//}
+//
+///**
+// * Adds the listener to the collection of listeners who will be
+// * notified when the window hosting the receiver should be closed.
+// *
+// * This notification occurs when a javascript command such as
+// * window.close gets executed by a Browser.
+// *
+// *
+// * @param listener the listener which should be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void addCloseWindowListener (CloseWindowListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.addCloseWindowListener (listener);
+//}
+//
+///**
+// * Adds the listener to the collection of listeners who will be
+// * notified when the current location has changed or is about to change.
+// *
+// * This notification typically occurs when the application navigates
+// * to a new location with {@link #setUrl(String)} or when the user
+// * activates a hyperlink.
+// *
+// *
+// * @param listener the listener which should be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void addLocationListener (LocationListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.addLocationListener (listener);
+//}
+//
+///**
+// * Adds the listener to the collection of listeners who will be
+// * notified when a new window needs to be created.
+// *
+// * This notification occurs when a javascript command such as
+// * window.open gets executed by a Browser.
+// *
+// *
+// * @param listener the listener which should be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void addOpenWindowListener (OpenWindowListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.addOpenWindowListener (listener);
+//}
+//
+///**
+// * Adds the listener to the collection of listeners who will be
+// * notified when a progress is made during the loading of the current
+// * URL or when the loading of the current URL has been completed.
+// *
+// * @param listener the listener which should be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void addProgressListener (ProgressListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.addProgressListener (listener);
+//}
+//
+///**
+// * Adds the listener to the collection of listeners who will be
+// * notified when the status text is changed.
+// *
+// * The status text is typically displayed in the status bar of
+// * a browser application.
+// *
+// *
+// * @param listener the listener which should be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void addStatusTextListener (StatusTextListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.addStatusTextListener (listener);
+//}
+//
+///**
+// * Adds the listener to the collection of listeners who will be
+// * notified when the title of the current document is available
+// * or has changed.
+// *
+// * @param listener the listener which should be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void addTitleListener (TitleListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.addTitleListener (listener);
+//}
+//
+///**
+// * Adds the listener to the collection of listeners who will be
+// * notified when a window hosting the receiver needs to be displayed
+// * or hidden.
+// *
+// * @param listener the listener which should be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void addVisibilityWindowListener (VisibilityWindowListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.addVisibilityWindowListener (listener);
+//}
+//
+///**
+// * Navigate to the previous session history item.
+// *
+// * @return true if the operation was successful and false otherwise
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// * Executes a script containing javascript commands in the context of the current document.
+// * If document-defined functions or properties are accessed by the script then this method
+// * should not be invoked until the document has finished loading (ProgressListener.completed()
+// * gives notification of this).
+// *
+// * @param script the script with javascript commands
+// *
+// * @return true if the operation was successful and false otherwise
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the script is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @see ProgressListener#completed(ProgressEvent)
+// *
+// * @since 3.1
+// */
+//public boolean execute (String script) {
+// checkWidget();
+// if (script == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// return webBrowser.execute (script);
+//}
+//
+///**
+// * Attempts to dispose the receiver, but allows the dispose to be vetoed
+// * by the user in response to an onbeforeunload listener
+// * in the Browser's current page.
+// *
+// * @return true if the receiver was disposed, and false otherwise
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// * Evaluates a script containing javascript commands in the context of
+// * the current document. If document-defined functions or properties
+// * are accessed by the script then this method should not be invoked
+// * until the document has finished loading (ProgressListener.completed()
+// * gives notification of this).
+// *
+// * If the script returns a value with a supported type then a java
+// * representation of the value is returned. The supported
+// * javascript -> java mappings are:
+// *
+// *
javascript null or undefined -> null
+// *
javascript number -> java.lang.Double
+// *
javascript string -> java.lang.String
+// *
javascript boolean -> java.lang.Boolean
+// *
javascript array whose elements are all of supported types -> java.lang.Object[]
+// *
+// *
+// * An SWTException is thrown if the return value has an
+// * unsupported type, or if evaluating the script causes a javascript
+// * error to be thrown.
+// *
+// * @param script the script with javascript commands
+// *
+// * @return the return value, if any, of executing the script
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the script is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_FAILED_EVALUATE when the script evaluation causes a javascript error to be thrown
+// *
ERROR_INVALID_RETURN_VALUE when the script returns a value of unsupported type
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// * Evaluates a script containing javascript commands.
+// * When trusted is true script is executed in the context of Chrome
+// * with Chrome security privileges.
+// * When trusted is false script is executed in the context of the
+// * current document with normal privileges.
+// *
+// * If document-defined functions or properties are accessed by the script then
+// * this method should not be invoked until the document has finished loading
+// * (ProgressListener.completed() gives notification of this).
+// *
+// * If the script returns a value with a supported type then a java
+// * representation of the value is returned. The supported
+// * javascript -> java mappings are:
+// *
+// *
javascript null or undefined -> null
+// *
javascript number -> java.lang.Double
+// *
javascript string -> java.lang.String
+// *
javascript boolean -> java.lang.Boolean
+// *
javascript array whose elements are all of supported types -> java.lang.Object[]
+// *
+// * An SWTException is thrown if the return value has an
+// * unsupported type, or if evaluating the script causes a javascript
+// * error to be thrown.
+// *
+// * @param script the script with javascript commands
+// * @param trusted true or false depending on the security context to be used
+// *
+// * @return the return value, if any, of executing the script
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the script is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_FAILED_EVALUATE when the script evaluation causes a javascript error to be thrown
+// *
ERROR_INVALID_RETURN_VALUE when the script returns a value of unsupported type
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @see ProgressListener#completed(ProgressEvent)
+// */
+//public Object evaluate (String script, boolean trusted) throws SWTException {
+// checkWidget();
+// if (script == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// return webBrowser.evaluate (script, trusted);
+//}
+//
+///**
+// * Navigate to the next session history item.
+// *
+// * @return true if the operation was successful and false otherwise
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @see #back
+// *
+// * @since 3.0
+// */
+//public boolean forward () {
+// checkWidget();
+// return webBrowser.forward ();
+//}
+//
+///**
+// * Returns the type of native browser being used by this instance.
+// * Examples: "ie", "webkit"
+// *
+// * @return the type of the native browser
+// *
+// * @since 3.5
+// */
+//public String getBrowserType () {
+// checkWidget();
+// return webBrowser.getBrowserType ();
+//}
+//
+///**
+// * Returns true if javascript will be allowed to run in pages
+// * subsequently viewed in the receiver, and false otherwise.
+// * Note that this may not reflect the javascript enablement on the currently-
+// * viewed page if setJavascriptEnabled() has been invoked during
+// * its lifetime.
+// *
+// * @return the receiver's javascript enabled state
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see #setJavascriptEnabled
+// *
+// * @since 3.5
+// */
+//public boolean getJavascriptEnabled () {
+// checkWidget();
+// return webBrowser.jsEnabledOnNextPage;
+//}
+//
+//@Override
+//public int getStyle () {
+// /*
+// * If SWT.BORDER was specified at creation time then getStyle() should answer
+// * it even though it is removed for IE on win32 in checkStyle().
+// */
+// return super.getStyle () | (userStyle & SWT.BORDER);
+//}
+//
+///**
+// * Returns a string with HTML that represents the content of the current page.
+// *
+// * @return HTML representing the current page or an empty String
+// * if this is empty.
+// *
Note, the exact return value is platform dependent.
+// * For example on Windows, the returned string is the proccessed webpage
+// * with javascript executed and missing html tags added.
+// * On Linux and OS X, this returns the original HTML before the browser has
+// * processed it.
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.4
+// */
+//public String getText () {
+// checkWidget();
+// return webBrowser.getText ();
+//}
+//
+///**
+// * Returns the current URL.
+// *
+// * @return the current URL or an empty String if there is no current URL
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @see #setUrl
+// *
+// * @since 3.0
+// */
+//public String getUrl () {
+// checkWidget();
+// return webBrowser.getUrl ();
+//}
+//
+///**
+// * Returns the JavaXPCOM nsIWebBrowser for the receiver, or null
+// * if it is not available. In order for an nsIWebBrowser to be returned all
+// * of the following must be true:
+// *
the receiver's style must be SWT.MOZILLA
+// *
the classes from JavaXPCOM >= 1.8.1.2 must be resolvable at runtime
+// *
the version of the underlying XULRunner must be >= 1.8.1.2
+// *
+// *
+// * @return the receiver's JavaXPCOM nsIWebBrowser or null
+// *
+// * @since 3.3
+// * @deprecated SWT.MOZILLA is deprecated and XULRunner as a browser renderer is no longer supported.
+// */
+//@Deprecated
+//public Object getWebBrowser () {
+// checkWidget();
+// return webBrowser.getWebBrowser ();
+//}
+//
+///**
+// * Returns true if the receiver can navigate to the
+// * previous session history item, and false otherwise.
+// *
+// * @return the receiver's back command enabled state
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see #back
+// */
+//public boolean isBackEnabled () {
+// checkWidget();
+// return webBrowser.isBackEnabled ();
+//}
+//
+//@Override
+//public boolean isFocusControl () {
+// checkWidget();
+// if (webBrowser.isFocusControl ()) return true;
+// return super.isFocusControl ();
+//}
+//
+///**
+// * Returns true if the receiver can navigate to the
+// * next session history item, and false otherwise.
+// *
+// * @return the receiver's forward command enabled state
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void refresh () {
+// checkWidget();
+// webBrowser.refresh ();
+//}
+//
+///**
+// * Removes the listener from the collection of listeners who will
+// * be notified when authentication is required.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.5
+// */
+//public void removeAuthenticationListener (AuthenticationListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.removeAuthenticationListener (listener);
+//}
+//
+///**
+// * Removes the listener from the collection of listeners who will
+// * be notified when the window hosting the receiver should be closed.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void removeCloseWindowListener (CloseWindowListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.removeCloseWindowListener (listener);
+//}
+//
+///**
+// * Removes the listener from the collection of listeners who will
+// * be notified when the current location is changed or about to be changed.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void removeLocationListener (LocationListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.removeLocationListener (listener);
+//}
+//
+///**
+// * Removes the listener from the collection of listeners who will
+// * be notified when a new window needs to be created.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void removeOpenWindowListener (OpenWindowListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.removeOpenWindowListener (listener);
+//}
+//
+///**
+// * Removes the listener from the collection of listeners who will
+// * be notified when a progress is made during the loading of the current
+// * URL or when the loading of the current URL has been completed.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void removeProgressListener (ProgressListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.removeProgressListener (listener);
+//}
+//
+///**
+// * Removes the listener from the collection of listeners who will
+// * be notified when the status text is changed.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void removeStatusTextListener (StatusTextListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.removeStatusTextListener (listener);
+//}
+//
+///**
+// * Removes the listener from the collection of listeners who will
+// * be notified when the title of the current document is available
+// * or has changed.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void removeTitleListener (TitleListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.removeTitleListener (listener);
+//}
+//
+///**
+// * Removes the listener from the collection of listeners who will
+// * be notified when a window hosting the receiver needs to be displayed
+// * or hidden.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void removeVisibilityWindowListener (VisibilityWindowListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// webBrowser.removeVisibilityWindowListener (listener);
+//}
+//
+///**
+// * Sets whether javascript will be allowed to run in pages subsequently
+// * viewed in the receiver. Note that setting this value does not affect
+// * the running of javascript in the current page.
+// *
+// * @param enabled the receiver's new javascript enabled state
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public void setJavascriptEnabled (boolean enabled) {
+// checkWidget();
+// webBrowser.jsEnabledOnNextPage = enabled;
+//}
+//
+///**
+// * Renders a string containing HTML. The rendering of the content occurs asynchronously.
+// * The rendered page will be given trusted permissions; to render the page with untrusted
+// * permissions use setText(String html, boolean trusted) instead.
+// *
+// * The html parameter is Unicode-encoded since it is a java String.
+// * As a result, the HTML meta tag charset should not be set. The charset is implied
+// * by the String itself.
+// *
+// * @param html the HTML content to be rendered
+// *
+// * @return true if the operation was successful and false otherwise.
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the html is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @see #setText(String,boolean)
+// * @see #setUrl
+// *
+// * @since 3.0
+// */
+//public boolean setText (String html) {
+// checkWidget();
+// return setText (html, true);
+//}
+//
+///**
+// * Renders a string containing HTML. The rendering of the content occurs asynchronously.
+// * The rendered page can be given either trusted or untrusted permissions.
+// *
+// * The html parameter is Unicode-encoded since it is a java String.
+// * As a result, the HTML meta tag charset should not be set. The charset is implied
+// * by the String itself.
+// *
+// * The trusted parameter affects the permissions that will be granted to the rendered
+// * page. Specifying true for trusted gives the page permissions equivalent
+// * to a page on the local file system, while specifying false for trusted
+// * gives the page permissions equivalent to a page from the internet. Page content should
+// * be specified as trusted if the invoker created it or trusts its source, since this would
+// * allow (for instance) style sheets on the local file system to be referenced. Page
+// * content should be specified as untrusted if its source is not trusted or is not known.
+// *
+// * @param html the HTML content to be rendered
+// * @param trusted false if the rendered page should be granted restricted
+// * permissions and true otherwise
+// *
+// * @return true if the operation was successful and false otherwise.
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the html is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @see #setText(String)
+// * @see #setUrl
+// *
+// * @since 3.6
+// */
+//public boolean setText (String html, boolean trusted) {
+// checkWidget();
+// if (html == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// return webBrowser.setText (html, trusted);
+//}
+//
+///**
+// * Begins loading a URL. The loading of its content occurs asynchronously.
+// *
+// * @param url the URL to be loaded
+// *
+// * @return true if the operation was successful and false otherwise.
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the url is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// * If the URL causes an HTTP request to be initiated then the provided
+// * postData and header arguments, if any, are
+// * sent with the request. A value in the headers argument
+// * must be a name-value pair with a colon separator in order to be sent
+// * (for example: "user-agent: custom").
+// *
+// * @param url the URL to be loaded
+// * @param postData post data to be sent with the request, or null
+// * @param headers header lines to be sent with the request, or null
+// *
+// * @return true if the operation was successful and false otherwise.
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the url is null
+// *
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+// *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+// *
+// *
+// * @since 3.0
+// */
+//public void stop () {
+// checkWidget();
+// webBrowser.stop ();
+//}
+//}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Browser/swing/org/eclipse/swt/browser/Browser.java b/bundles/org.eclipse.swt/Eclipse SWT Browser/swing/org/eclipse/swt/browser/Browser.java
new file mode 100644
index 00000000000..f59bdc3c7cc
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Browser/swing/org/eclipse/swt/browser/Browser.java
@@ -0,0 +1,844 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.browser;
+
+import java.awt.*;
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.swing.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class implement the browser user interface
+ * metaphor. It allows the user to visualize and navigate through
+ * HTML documents.
+ *
+ * Note that although this class is a subclass of Composite,
+ * it does not make sense to set a layout on it.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @since 3.0
+ */
+public class Browser extends Composite {
+
+ /* External Listener management */
+ CloseWindowListener[] closeWindowListeners = new CloseWindowListener[0];
+ LocationListener[] locationListeners = new LocationListener[0];
+ OpenWindowListener[] openWindowListeners = new OpenWindowListener[0];
+ ProgressListener[] progressListeners = new ProgressListener[0];
+ StatusTextListener[] statusTextListeners = new StatusTextListener[0];
+ TitleListener[] titleListeners = new TitleListener[0];
+ VisibilityWindowListener[] visibilityWindowListeners = new VisibilityWindowListener[0];
+ WebBrowser webBrowser; // TODO (visjee) SWING
+
+ static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$
+
+ /* Package Name */
+ static final String PACKAGE_PREFIX = "org.eclipse.swt.browser."; //$NON-NLS-1$
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for browser creation
+ *
+ *
+ * @see Widget#getStyle
+ *
+ * @since 3.0
+ */
+public Browser(Composite parent, int style) {
+ super(parent, style &~ SWT.BORDER);
+}
+
+/**
+ * Clears all session cookies from all current Browser instances.
+ *
+ * @since 3.2
+ */
+public static void clearSessions () {
+ Utils.notImplemented();
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when the window hosting the receiver should be closed.
+ *
+ * This notification occurs when a javascript command such as
+ * window.close gets executed by a Browser.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void addCloseWindowListener(CloseWindowListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length + 1];
+ System.arraycopy(closeWindowListeners, 0, newCloseWindowListeners, 0, closeWindowListeners.length);
+ closeWindowListeners = newCloseWindowListeners;
+ closeWindowListeners[closeWindowListeners.length - 1] = listener;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when the current location has changed or is about to change.
+ *
+ * This notification typically occurs when the application navigates
+ * to a new location with {@link #setUrl(String)} or when the user
+ * activates a hyperlink.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void addLocationListener(LocationListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ LocationListener[] newLocationListeners = new LocationListener[locationListeners.length + 1];
+ System.arraycopy(locationListeners, 0, newLocationListeners, 0, locationListeners.length);
+ locationListeners = newLocationListeners;
+ locationListeners[locationListeners.length - 1] = listener;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when a new window needs to be created.
+ *
+ * This notification occurs when a javascript command such as
+ * window.open gets executed by a Browser.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void addOpenWindowListener(OpenWindowListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length + 1];
+ System.arraycopy(openWindowListeners, 0, newOpenWindowListeners, 0, openWindowListeners.length);
+ openWindowListeners = newOpenWindowListeners;
+ openWindowListeners[openWindowListeners.length - 1] = listener;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when a progress is made during the loading of the current
+ * URL or when the loading of the current URL has been completed.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void addProgressListener(ProgressListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length + 1];
+ System.arraycopy(progressListeners, 0, newProgressListeners, 0, progressListeners.length);
+ progressListeners = newProgressListeners;
+ progressListeners[progressListeners.length - 1] = listener;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when the status text is changed.
+ *
+ * The status text is typically displayed in the status bar of
+ * a browser application.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void addStatusTextListener(StatusTextListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length + 1];
+ System.arraycopy(statusTextListeners, 0, newStatusTextListeners, 0, statusTextListeners.length);
+ statusTextListeners = newStatusTextListeners;
+ statusTextListeners[statusTextListeners.length - 1] = listener;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when the title of the current document is available
+ * or has changed.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void addTitleListener(TitleListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ TitleListener[] newTitleListeners = new TitleListener[titleListeners.length + 1];
+ System.arraycopy(titleListeners, 0, newTitleListeners, 0, titleListeners.length);
+ titleListeners = newTitleListeners;
+ titleListeners[titleListeners.length - 1] = listener;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when a window hosting the receiver needs to be displayed
+ * or hidden.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void addVisibilityWindowListener(VisibilityWindowListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length + 1];
+ System.arraycopy(visibilityWindowListeners, 0, newVisibilityWindowListeners, 0, visibilityWindowListeners.length);
+ visibilityWindowListeners = newVisibilityWindowListeners;
+ visibilityWindowListeners[visibilityWindowListeners.length - 1] = listener;
+}
+
+/**
+ * Navigate to the previous session history item.
+ *
+ * @return true if the operation was successful and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ * Execute a script containing javascript commands in the context of the current document.
+ *
+ * @param script the script with javascript commands
+ *
+ * @return true if the operation was successful and false otherwise
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the script is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public boolean execute(String script) {
+ checkWidget();
+ if (script == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ // TODO: impossible to implement. Check in future versions of Java...
+ return false;
+}
+
+/**
+ * Navigate to the next session history item.
+ *
+ * @return true if the operation was successful and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @see #back
+ *
+ * @since 3.0
+ */
+public boolean forward() {
+ checkWidget();
+ return ((CBrowser)handle).forward();
+}
+
+/**
+ * Returns true if the receiver can navigate to the
+ * previous session history item, and false otherwise.
+ *
+ * @return the receiver's back command enabled state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #back
+ */
+public boolean isBackEnabled() {
+ checkWidget();
+ return ((CBrowser)handle).isBackEnabled();
+}
+
+/**
+ * Returns true if the receiver can navigate to the
+ * next session history item, and false otherwise.
+ *
+ * @return the receiver's forward command enabled state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #forward
+ */
+public boolean isForwardEnabled() {
+ checkWidget();
+ return ((CBrowser)handle).isForwardEnabled();
+}
+
+/**
+ * Returns the current URL.
+ *
+ * @return the current URL or an empty String if there is no current URL
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void refresh() {
+ checkWidget();
+ ((CBrowser)handle).refresh();
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the window hosting the receiver should be closed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void removeCloseWindowListener(CloseWindowListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (closeWindowListeners.length == 0) return;
+ int index = -1;
+ for (int i = 0; i < closeWindowListeners.length; i++) {
+ if (listener == closeWindowListeners[i]){
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) return;
+ if (closeWindowListeners.length == 1) {
+ closeWindowListeners = new CloseWindowListener[0];
+ return;
+ }
+ CloseWindowListener[] newCloseWindowListeners = new CloseWindowListener[closeWindowListeners.length - 1];
+ System.arraycopy(closeWindowListeners, 0, newCloseWindowListeners, 0, index);
+ System.arraycopy(closeWindowListeners, index + 1, newCloseWindowListeners, index, closeWindowListeners.length - index - 1);
+ closeWindowListeners = newCloseWindowListeners;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the current location is changed or about to be changed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void removeLocationListener(LocationListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (locationListeners.length == 0) return;
+ int index = -1;
+ for (int i = 0; i < locationListeners.length; i++) {
+ if (listener == locationListeners[i]){
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) return;
+ if (locationListeners.length == 1) {
+ locationListeners = new LocationListener[0];
+ return;
+ }
+ LocationListener[] newLocationListeners = new LocationListener[locationListeners.length - 1];
+ System.arraycopy(locationListeners, 0, newLocationListeners, 0, index);
+ System.arraycopy(locationListeners, index + 1, newLocationListeners, index, locationListeners.length - index - 1);
+ locationListeners = newLocationListeners;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a new window needs to be created.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void removeOpenWindowListener(OpenWindowListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (openWindowListeners.length == 0) return;
+ int index = -1;
+ for (int i = 0; i < openWindowListeners.length; i++) {
+ if (listener == openWindowListeners[i]){
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) return;
+ if (openWindowListeners.length == 1) {
+ openWindowListeners = new OpenWindowListener[0];
+ return;
+ }
+ OpenWindowListener[] newOpenWindowListeners = new OpenWindowListener[openWindowListeners.length - 1];
+ System.arraycopy(openWindowListeners, 0, newOpenWindowListeners, 0, index);
+ System.arraycopy(openWindowListeners, index + 1, newOpenWindowListeners, index, openWindowListeners.length - index - 1);
+ openWindowListeners = newOpenWindowListeners;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a progress is made during the loading of the current
+ * URL or when the loading of the current URL has been completed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void removeProgressListener(ProgressListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (progressListeners.length == 0) return;
+ int index = -1;
+ for (int i = 0; i < progressListeners.length; i++) {
+ if (listener == progressListeners[i]){
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) return;
+ if (progressListeners.length == 1) {
+ progressListeners = new ProgressListener[0];
+ return;
+ }
+ ProgressListener[] newProgressListeners = new ProgressListener[progressListeners.length - 1];
+ System.arraycopy(progressListeners, 0, newProgressListeners, 0, index);
+ System.arraycopy(progressListeners, index + 1, newProgressListeners, index, progressListeners.length - index - 1);
+ progressListeners = newProgressListeners;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the status text is changed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void removeStatusTextListener(StatusTextListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (statusTextListeners.length == 0) return;
+ int index = -1;
+ for (int i = 0; i < statusTextListeners.length; i++) {
+ if (listener == statusTextListeners[i]){
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) return;
+ if (statusTextListeners.length == 1) {
+ statusTextListeners = new StatusTextListener[0];
+ return;
+ }
+ StatusTextListener[] newStatusTextListeners = new StatusTextListener[statusTextListeners.length - 1];
+ System.arraycopy(statusTextListeners, 0, newStatusTextListeners, 0, index);
+ System.arraycopy(statusTextListeners, index + 1, newStatusTextListeners, index, statusTextListeners.length - index - 1);
+ statusTextListeners = newStatusTextListeners;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the title of the current document is available
+ * or has changed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void removeTitleListener(TitleListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (titleListeners.length == 0) return;
+ int index = -1;
+ for (int i = 0; i < titleListeners.length; i++) {
+ if (listener == titleListeners[i]){
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) return;
+ if (titleListeners.length == 1) {
+ titleListeners = new TitleListener[0];
+ return;
+ }
+ TitleListener[] newTitleListeners = new TitleListener[titleListeners.length - 1];
+ System.arraycopy(titleListeners, 0, newTitleListeners, 0, index);
+ System.arraycopy(titleListeners, index + 1, newTitleListeners, index, titleListeners.length - index - 1);
+ titleListeners = newTitleListeners;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a window hosting the receiver needs to be displayed
+ * or hidden.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void removeVisibilityWindowListener(VisibilityWindowListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (visibilityWindowListeners.length == 0) return;
+ int index = -1;
+ for (int i = 0; i < visibilityWindowListeners.length; i++) {
+ if (listener == visibilityWindowListeners[i]){
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) return;
+ if (visibilityWindowListeners.length == 1) {
+ visibilityWindowListeners = new VisibilityWindowListener[0];
+ return;
+ }
+ VisibilityWindowListener[] newVisibilityWindowListeners = new VisibilityWindowListener[visibilityWindowListeners.length - 1];
+ System.arraycopy(visibilityWindowListeners, 0, newVisibilityWindowListeners, 0, index);
+ System.arraycopy(visibilityWindowListeners, index + 1, newVisibilityWindowListeners, index, visibilityWindowListeners.length - index - 1);
+ visibilityWindowListeners = newVisibilityWindowListeners;
+}
+
+/**
+ * Renders HTML.
+ *
+ *
+ * The html parameter is Unicode encoded since it is a java String.
+ * As a result, the HTML meta tag charset should not be set. The charset is implied
+ * by the String itself.
+ *
+ * @param html the HTML content to be rendered
+ *
+ * @return true if the operation was successful and false otherwise.
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the html is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
+ *
+ *
+ * @see #setUrl
+ *
+ * @since 3.0
+ */
+public boolean setText(String html) {
+ checkWidget();
+ if (html == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return ((CBrowser)handle).setText(html);
+}
+
+/**
+ * Loads a URL.
+ *
+ * @param url the URL to be loaded
+ *
+ * @return true if the operation was successful and false otherwise.
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the url is null
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *
ERROR_WIDGET_DISPOSED when the widget has been disposed
*/
+// TODO (visjee) SWING
class RTFWriter extends StyledTextWriterBase {
- static final int DEFAULT_FOREGROUND = 0;
- static final int DEFAULT_BACKGROUND = 1;
- List colorTable;
- List fontTable;
-
- public RTFWriter(StyledText styledText, int start, int length) {
- super(styledText, start, length);
- colorTable = new ArrayList<>();
- fontTable = new ArrayList<>();
- colorTable.add(this.styledText.getForeground());
- colorTable.add(this.styledText.getBackground());
- fontTable.add(this.styledText.getFont());
- }
-
- @Override
- public void close() {
- if (!isClosed()) {
- writeHeader();
- write("\n}}\0");
- super.close();
- }
- }
-
- /**
- * Writes the RTF header including font table and color table.
- */
- @Override
- void writeHeader() {
- StringBuilder header = new StringBuilder();
- FontData fontData = styledText.getFont().getFontData()[0];
- header.append("{\\rtf1\\ansi");
- // specify code page, necessary for copy to work in bidi
- // systems that don't support Unicode RTF.
- String cpg = System.getProperty("file.encoding").toLowerCase();
- if (cpg.startsWith("cp") || cpg.startsWith("ms")) {
- cpg = cpg.substring(2, cpg.length());
- header.append("\\ansicpg");
- header.append(cpg);
- }
- header.append("\\uc1\\deff0{\\fonttbl{\\f0\\fnil ");
- header.append(fontData.getName());
- header.append(";");
- for (int i = 1; i < fontTable.size(); i++) {
- header.append("\\f");
- header.append(i);
- header.append(" ");
- FontData fd = fontTable.get(i).getFontData()[0];
- header.append(fd.getName());
- header.append(";");
- }
- header.append("}}\n{\\colortbl");
- for (Color color : colorTable) {
- header.append("\\red");
- header.append(color.getRed());
- header.append("\\green");
- header.append(color.getGreen());
- header.append("\\blue");
- header.append(color.getBlue());
- header.append(";");
- }
- // some RTF readers ignore the deff0 font tag. Explicitly
- // set the font for the whole document to work around this.
- header.append("}\n{\\f0\\fs");
- // font size is specified in half points
- header.append(fontData.getHeight() * 2);
- header.append(" ");
- write(header.toString(), 0);
- }
-
- @Override
- public void writeLineDelimiter(String lineDelimiter) {
- if (isClosed()) {
- SWT.error(SWT.ERROR_IO);
- }
- write(lineDelimiter);
- write("\\par ");
- }
-
- @Override
- String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) {
- write("\\fi");
- write(indent);
- switch (alignment) {
- case SWT.LEFT: write("\\ql"); break;
- case SWT.CENTER: write("\\qc"); break;
- case SWT.RIGHT: write("\\qr"); break;
- }
- if (justify) {
- write("\\qj");
- }
- write(" ");
-
- if (lineBackground != null) {
- // Background colors are written using the {@code \chshdng0\chcbpat} tag (vs. the {@code \cb} tag).
- write("{\\chshdng0\\chcbpat");
- write(getColorIndex(lineBackground, DEFAULT_BACKGROUND));
- write(" ");
- }
-
- // This is what will be used to close the line
- return lineBackground == null ? "" : "}";
- }
-
- @Override
- void writeEmptyLine() {
- // Do nothing. RTF does not need special treatment for empty paragraph.
- }
-
- @Override
- String writeSpanStart(StyleRange style) {
- write("{\\cf");
- write(getColorIndex(style.foreground, DEFAULT_FOREGROUND));
- int colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND);
- if (colorIndex != DEFAULT_BACKGROUND) {
- write("\\chshdng0\\chcbpat");
- write(colorIndex);
- }
- int fontStyle = style.fontStyle;
- Font font = style.font;
- if (font != null) {
- int fontIndex = getFontIndex(font);
- write("\\f");
- write(fontIndex);
- FontData fontData = font.getFontData()[0];
- write("\\fs");
- write(fontData.getHeight() * 2);
- fontStyle = fontData.getStyle();
- }
- if ((fontStyle & SWT.BOLD) != 0) {
- write("\\b");
- }
- if ((fontStyle & SWT.ITALIC) != 0) {
- write("\\i");
- }
- if (style.underline) {
- write("\\ul");
- }
- if (style.strikeout) {
- write("\\strike");
- }
- write(" ");
-
- // This is what will be used to close the span
- StringBuilder toCloseSpan = new StringBuilder();
- if ((fontStyle & SWT.BOLD) != 0) {
- toCloseSpan.append("\\b0");
- }
- if ((style.fontStyle & SWT.ITALIC) != 0) {
- toCloseSpan.append("\\i0");
- }
- if (style.underline) {
- toCloseSpan.append("\\ul0");
- }
- if (style.strikeout) {
- toCloseSpan.append("\\strike0");
- }
- toCloseSpan.append("}");
- return toCloseSpan.toString();
- }
-
- // ==== Helper methods ====
-
- @Override
- String escapeText(String string) {
- // The resulting string is at least as long as the original.
- StringBuilder result = new StringBuilder(string.length());
- string.chars().forEach(ch -> {
- if (ch > 0x7F) {
- result.append("\\u");
- result.append(Integer.toString((short) ch));
- result.append('?'); // ANSI representation (1 byte long, \\uc1)
- } else if (ch == '}' || ch == '{' || ch == '\\') {
- result.append('\\');
- result.append((char) ch);
- } else {
- // Fixes bug 21698.
- result.append((char) ch);
- }
- });
- return result.toString();
- }
-
- /**
- * Returns the index of the specified color in the RTF color table.
- *
- * @param color the color
- * @param defaultIndex return value if color is null
- * @return the index of the specified color in the RTF color table
- * or "defaultIndex" if "color" is null.
- */
- private int getColorIndex(Color color, int defaultIndex) {
- if (color == null) return defaultIndex;
- int index = colorTable.indexOf(color);
- if (index == -1) {
- index = colorTable.size();
- colorTable.add(color);
- }
- return index;
- }
- /**
- * Returns the index of the specified color in the RTF color table.
- *
- * @param color the color
- * @param defaultIndex return value if color is null
- * @return the index of the specified color in the RTF color table
- * or "defaultIndex" if "color" is null.
- */
- private int getFontIndex(Font font) {
- int index = fontTable.indexOf(font);
- if (index == -1) {
- index = fontTable.size();
- fontTable.add(font);
- }
- return index;
+ public RTFWriter(int start, int length) {
+ super(start, length);
+ // TODO Auto-generated constructor stub
}
+// static final int DEFAULT_FOREGROUND = 0;
+// static final int DEFAULT_BACKGROUND = 1;
+// List colorTable;
+// List fontTable;
+//
+// public RTFWriter(StyledText styledText, int start, int length) {
+// super(styledText, start, length);
+// colorTable = new ArrayList<>();
+// fontTable = new ArrayList<>();
+// colorTable.add(this.styledText.getForeground());
+// colorTable.add(this.styledText.getBackground());
+// fontTable.add(this.styledText.getFont());
+// }
+//
+// @Override
+// public void close() {
+// if (!isClosed()) {
+// writeHeader();
+// write("\n}}\0");
+// super.close();
+// }
+// }
+//
+// /**
+// * Writes the RTF header including font table and color table.
+// */
+// @Override
+// void writeHeader() {
+// StringBuilder header = new StringBuilder();
+// FontData fontData = styledText.getFont().getFontData()[0];
+// header.append("{\\rtf1\\ansi");
+// // specify code page, necessary for copy to work in bidi
+// // systems that don't support Unicode RTF.
+// String cpg = System.getProperty("file.encoding").toLowerCase();
+// if (cpg.startsWith("cp") || cpg.startsWith("ms")) {
+// cpg = cpg.substring(2, cpg.length());
+// header.append("\\ansicpg");
+// header.append(cpg);
+// }
+// header.append("\\uc1\\deff0{\\fonttbl{\\f0\\fnil ");
+// header.append(fontData.getName());
+// header.append(";");
+// for (int i = 1; i < fontTable.size(); i++) {
+// header.append("\\f");
+// header.append(i);
+// header.append(" ");
+// FontData fd = fontTable.get(i).getFontData()[0];
+// header.append(fd.getName());
+// header.append(";");
+// }
+// header.append("}}\n{\\colortbl");
+// for (Color color : colorTable) {
+// header.append("\\red");
+// header.append(color.getRed());
+// header.append("\\green");
+// header.append(color.getGreen());
+// header.append("\\blue");
+// header.append(color.getBlue());
+// header.append(";");
+// }
+// // some RTF readers ignore the deff0 font tag. Explicitly
+// // set the font for the whole document to work around this.
+// header.append("}\n{\\f0\\fs");
+// // font size is specified in half points
+// header.append(fontData.getHeight() * 2);
+// header.append(" ");
+// write(header.toString(), 0);
+// }
+//
+// @Override
+// public void writeLineDelimiter(String lineDelimiter) {
+// if (isClosed()) {
+// SWT.error(SWT.ERROR_IO);
+// }
+// write(lineDelimiter);
+// write("\\par ");
+// }
+//
+// @Override
+// String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) {
+// write("\\fi");
+// write(indent);
+// switch (alignment) {
+// case SWT.LEFT: write("\\ql"); break;
+// case SWT.CENTER: write("\\qc"); break;
+// case SWT.RIGHT: write("\\qr"); break;
+// }
+// if (justify) {
+// write("\\qj");
+// }
+// write(" ");
+//
+// if (lineBackground != null) {
+// // Background colors are written using the {@code \chshdng0\chcbpat} tag (vs. the {@code \cb} tag).
+// write("{\\chshdng0\\chcbpat");
+// write(getColorIndex(lineBackground, DEFAULT_BACKGROUND));
+// write(" ");
+// }
+//
+// // This is what will be used to close the line
+// return lineBackground == null ? "" : "}";
+// }
+//
+// @Override
+// void writeEmptyLine() {
+// // Do nothing. RTF does not need special treatment for empty paragraph.
+// }
+//
+// @Override
+// String writeSpanStart(StyleRange style) {
+// write("{\\cf");
+// write(getColorIndex(style.foreground, DEFAULT_FOREGROUND));
+// int colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND);
+// if (colorIndex != DEFAULT_BACKGROUND) {
+// write("\\chshdng0\\chcbpat");
+// write(colorIndex);
+// }
+// int fontStyle = style.fontStyle;
+// Font font = style.font;
+// if (font != null) {
+// int fontIndex = getFontIndex(font);
+// write("\\f");
+// write(fontIndex);
+// FontData fontData = font.getFontData()[0];
+// write("\\fs");
+// write(fontData.getHeight() * 2);
+// fontStyle = fontData.getStyle();
+// }
+// if ((fontStyle & SWT.BOLD) != 0) {
+// write("\\b");
+// }
+// if ((fontStyle & SWT.ITALIC) != 0) {
+// write("\\i");
+// }
+// if (style.underline) {
+// write("\\ul");
+// }
+// if (style.strikeout) {
+// write("\\strike");
+// }
+// write(" ");
+//
+// // This is what will be used to close the span
+// StringBuilder toCloseSpan = new StringBuilder();
+// if ((fontStyle & SWT.BOLD) != 0) {
+// toCloseSpan.append("\\b0");
+// }
+// if ((style.fontStyle & SWT.ITALIC) != 0) {
+// toCloseSpan.append("\\i0");
+// }
+// if (style.underline) {
+// toCloseSpan.append("\\ul0");
+// }
+// if (style.strikeout) {
+// toCloseSpan.append("\\strike0");
+// }
+// toCloseSpan.append("}");
+// return toCloseSpan.toString();
+// }
+//
+// // ==== Helper methods ====
+//
+// @Override
+// String escapeText(String string) {
+// // The resulting string is at least as long as the original.
+// StringBuilder result = new StringBuilder(string.length());
+// string.chars().forEach(ch -> {
+// if (ch > 0x7F) {
+// result.append("\\u");
+// result.append(Integer.toString((short) ch));
+// result.append('?'); // ANSI representation (1 byte long, \\uc1)
+// } else if (ch == '}' || ch == '{' || ch == '\\') {
+// result.append('\\');
+// result.append((char) ch);
+// } else {
+// // Fixes bug 21698.
+// result.append((char) ch);
+// }
+// });
+// return result.toString();
+// }
+//
+// /**
+// * Returns the index of the specified color in the RTF color table.
+// *
+// * @param color the color
+// * @param defaultIndex return value if color is null
+// * @return the index of the specified color in the RTF color table
+// * or "defaultIndex" if "color" is null.
+// */
+// private int getColorIndex(Color color, int defaultIndex) {
+// if (color == null) return defaultIndex;
+// int index = colorTable.indexOf(color);
+// if (index == -1) {
+// index = colorTable.size();
+// colorTable.add(color);
+// }
+// return index;
+// }
+//
+// /**
+// * Returns the index of the specified color in the RTF color table.
+// *
+// * @param color the color
+// * @param defaultIndex return value if color is null
+// * @return the index of the specified color in the RTF color table
+// * or "defaultIndex" if "color" is null.
+// */
+// private int getFontIndex(Font font) {
+// int index = fontTable.indexOf(font);
+// if (index == -1) {
+// index = fontTable.size();
+// fontTable.add(font);
+// }
+// return index;
+// }
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
index 335acfb8bfb..0fc1765ed9c 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
@@ -16,10869 +16,10919 @@
* Karsten Thoms - bug 528746 add getOffsetAtPoint(Point)
*******************************************************************************/
package org.eclipse.swt.custom;
-
-
-import java.util.*;
-import java.util.function.*;
-import java.util.stream.*;
-
-import org.eclipse.swt.*;
-import org.eclipse.swt.accessibility.*;
-import org.eclipse.swt.dnd.*;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.internal.*;
-import org.eclipse.swt.printing.*;
-import org.eclipse.swt.widgets.*;
-
-/**
- * A StyledText is an editable user interface object that displays lines
- * of text. The following style attributes can be defined for the text:
- *
- *
foreground color
- *
background color
- *
font style (bold, italic, bold-italic, regular)
- *
underline
- *
strikeout
- *
- *
- * In addition to text style attributes, the background color of a line may
- * be specified.
- *
- * There are two ways to use this widget when specifying text style information.
- * You may use the API that is defined for StyledText or you may define your own
- * LineStyleListener. If you define your own listener, you will be responsible
- * for maintaining the text style information for the widget. IMPORTANT: You may
- * not define your own listener and use the StyledText API. The following
- * StyledText API is not supported if you have defined a LineStyleListener:
- *
- *
getStyleRangeAtOffset(int)
- *
getStyleRanges()
- *
replaceStyleRanges(int,int,StyleRange[])
- *
setStyleRange(StyleRange)
- *
setStyleRanges(StyleRange[])
- *
- *
- * There are two ways to use this widget when specifying line background colors.
- * You may use the API that is defined for StyledText or you may define your own
- * LineBackgroundListener. If you define your own listener, you will be responsible
- * for maintaining the line background color information for the widget.
- * IMPORTANT: You may not define your own listener and use the StyledText API.
- * The following StyledText API is not supported if you have defined a
- * LineBackgroundListener:
- *
- *
getLineBackground(int)
- *
setLineBackground(int,int,Color)
- *
- *
- * The content implementation for this widget may also be user-defined. To do so,
- * you must implement the StyledTextContent interface and use the StyledText API
- * setContent(StyledTextContent) to initialize the widget.
- *
- *
- *
Styles:
FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP
- *
- * IMPORTANT: This class is not intended to be subclassed.
- *
- *
- * @see StyledText snippets
- * @see SWT Examples: CustomControlExample, TextEditor
- * @see Sample code and further information
- * @noextend This class is not intended to be subclassed by clients.
- */
-public class StyledText extends Canvas {
- static final char TAB = '\t';
- static final String PlatformLineDelimiter = System.lineSeparator();
- static final int BIDI_CARET_WIDTH = 3;
- static final int DEFAULT_WIDTH = 64;
- static final int DEFAULT_HEIGHT = 64;
- static final int V_SCROLL_RATE = 50;
- static final int H_SCROLL_RATE = 10;
- static final int PREVIOUS_OFFSET_TRAILING = 0;
- static final int OFFSET_LEADING = 1;
-
- static final String STYLEDTEXT_KEY = "org.eclipse.swt.internal.cocoa.styledtext"; //$NON-NLS-1$
- private static int getX(Point p) { return p.x; } // workaround p -> p.x lose typing and cannot be chained in comparing...
- static final Comparator SELECTION_COMPARATOR = Comparator.comparingInt(StyledText::getX).thenComparingInt(p -> p.y);
-
- Color selectionBackground; // selection background color
- Color selectionForeground; // selection foreground color
- StyledTextContent content; // native content (default or user specified)
- StyledTextRenderer renderer;
- Listener listener;
- TextChangeListener textChangeListener; // listener for TextChanging, TextChanged and TextSet events from StyledTextContent
- int verticalScrollOffset = 0; // pixel based
- int horizontalScrollOffset = 0; // pixel based
- boolean alwaysShowScroll = true;
- int ignoreResize = 0;
- int topIndex = 0; // top visible line
- int topIndexY;
- int clientAreaHeight = 0; // the client area height. Needed to calculate content width for new visible lines during Resize callback
- int clientAreaWidth = 0; // the client area width. Needed during Resize callback to determine if line wrap needs to be recalculated
- int tabLength = 4; // number of characters in a tab
- int [] tabs;
- int leftMargin;
- int topMargin;
- int rightMargin;
- int bottomMargin;
- Color marginColor;
- int columnX; // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935
- Caret[] carets;
- int[] caretOffsets = {0};
- int caretAlignment;
- Point[] selection = { new Point(0, 0) }; // x and y are start and end caret offsets of selection (x <= y)
- int[] selectionAnchors = {0}; // position of selection anchor for the selection ranges. 0 based offset from beginning of text
- Point clipboardSelection; // x and y are start and end caret offsets of previous selection
- Point doubleClickSelection; // selection after last mouse double click
- boolean editable = true;
- boolean wordWrap = false; // text is wrapped automatically
- boolean visualWrap = false; // process line breaks inside logical lines (inserted by BidiSegmentEvent)
- boolean hasStyleWithVariableHeight = false;
- boolean hasVerticalIndent = false;
- boolean doubleClickEnabled = true; // see getDoubleClickEnabled
- boolean overwrite = false; // insert/overwrite edit mode
- int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default.
- Map keyActionMap = new HashMap<>();
- Color background = null; // workaround for bug 4791
- Color foreground = null; //
- /** True if a non-default background color is set */
- boolean customBackground;
- /** True if a non-default foreground color is set */
- boolean customForeground;
- /** False iff the widget is disabled */
- boolean enabled = true;
- /** True iff the widget is in the midst of being enabled or disabled */
- boolean insideSetEnableCall;
- Clipboard clipboard;
- int clickCount;
- int autoScrollDirection = SWT.NULL; // the direction of autoscrolling (up, down, right, left)
- int autoScrollDistance = 0;
- int lastTextChangeStart; // cache data of the
- int lastTextChangeNewLineCount; // last text changing
- int lastTextChangeNewCharCount; // event for use in the
- int lastTextChangeReplaceLineCount; // text changed handler
- int lastTextChangeReplaceCharCount;
- int lastCharCount = 0;
- int lastLineBottom; // the bottom pixel of the last line been replaced
- boolean bidiColoring = false; // apply the BIDI algorithm on text segments of the same color
- Image leftCaretBitmap = null;
- Image rightCaretBitmap = null;
- int caretDirection = SWT.NULL;
- int caretWidth = 0;
- Caret defaultCaret = null;
- boolean updateCaretDirection = true;
- boolean dragDetect = true;
- IME ime;
- Cursor cursor;
- int alignment;
- boolean justify;
- int indent, wrapIndent;
- int lineSpacing;
- int alignmentMargin;
- int newOrientation = SWT.NONE;
- int accCaretOffset;
- Accessible acc;
- AccessibleControlAdapter accControlAdapter;
- AccessibleAttributeAdapter accAttributeAdapter;
- AccessibleEditableTextListener accEditableTextListener;
- AccessibleTextExtendedAdapter accTextExtendedAdapter;
- AccessibleAdapter accAdapter;
- MouseNavigator mouseNavigator;
- boolean middleClickPressed;
-
- //block selection
- boolean blockSelection;
- int blockXAnchor = -1, blockYAnchor = -1;
- int blockXLocation = -1, blockYLocation = -1;
-
- final static boolean IS_MAC, IS_GTK;
- static {
- String platform = SWT.getPlatform();
- IS_MAC = "cocoa".equals(platform);
- IS_GTK = "gtk".equals(platform);
- }
-
- /**
- * The Printing class implements printing of a range of text.
- * An instance of Printing is returned in the
- * StyledText#print(Printer) API. The run() method may be
- * invoked from any thread.
- */
- static class Printing implements Runnable {
- final static int LEFT = 0; // left aligned header/footer segment
- final static int CENTER = 1; // centered header/footer segment
- final static int RIGHT = 2; // right aligned header/footer segment
-
- Printer printer;
- StyledTextRenderer printerRenderer;
- StyledTextPrintOptions printOptions;
- Rectangle clientArea;
- FontData fontData;
- Font printerFont;
- Map resources;
- int tabLength;
- GC gc; // printer GC
- int pageWidth; // width of a printer page in pixels
- int startPage; // first page to print
- int endPage; // last page to print
- int scope; // scope of print job
- int startLine; // first (wrapped) line to print
- int endLine; // last (wrapped) line to print
- boolean singleLine; // widget single line mode
- Point[] selection = { new Point(0, 0) }; // x and y are start and end caret offsets of selection (x <= y)
- boolean mirrored; // indicates the printing gc should be mirrored
- int lineSpacing;
- int printMargin;
-
- /**
- * Creates an instance of Printing.
- * Copies the widget content and rendering data that needs
- * to be requested from listeners.
- *
- * @param parent StyledText widget to print.
- * @param printer printer device to print on.
- * @param printOptions print options
- */
- Printing(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) {
- this.printer = printer;
- this.printOptions = printOptions;
- this.mirrored = (styledText.getStyle() & SWT.MIRRORED) != 0;
- singleLine = styledText.isSingleLine();
- startPage = 1;
- endPage = Integer.MAX_VALUE;
- PrinterData data = printer.getPrinterData();
- scope = data.scope;
- if (scope == PrinterData.PAGE_RANGE) {
- startPage = data.startPage;
- endPage = data.endPage;
- if (endPage < startPage) {
- int temp = endPage;
- endPage = startPage;
- startPage = temp;
- }
- } else if (scope == PrinterData.SELECTION) {
- selection = Arrays.copyOf(styledText.selection, styledText.selection.length);
- }
- printerRenderer = new StyledTextRenderer(printer, null);
- printerRenderer.setContent(copyContent(styledText.getContent()));
- cacheLineData(styledText);
- }
- /**
- * Caches all line data that needs to be requested from a listener.
- *
- * @param printerContent StyledTextContent to request
- * line data for.
- */
- void cacheLineData(StyledText styledText) {
- StyledTextRenderer renderer = styledText.renderer;
- renderer.copyInto(printerRenderer);
- fontData = styledText.getFont().getFontData()[0];
- tabLength = styledText.tabLength;
- int lineCount = printerRenderer.lineCount;
- if (styledText.isListening(ST.LineGetBackground) || (styledText.isListening(ST.LineGetSegments)) || styledText.isListening(ST.LineGetStyle)) {
- StyledTextContent content = printerRenderer.content;
- for (int i = 0; i < lineCount; i++) {
- String line = content.getLine(i);
- int lineOffset = content.getOffsetAtLine(i);
- StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line);
- if (event != null && event.lineBackground != null) {
- printerRenderer.setLineBackground(i, 1, event.lineBackground);
- }
- event = styledText.getBidiSegments(lineOffset, line);
- if (event != null) {
- printerRenderer.setLineSegments(i, 1, event.segments);
- printerRenderer.setLineSegmentChars(i, 1, event.segmentsChars);
- }
- event = styledText.getLineStyleData(lineOffset, line);
- if (event != null) {
- printerRenderer.setLineIndent(i, 1, event.indent);
- printerRenderer.setLineAlignment(i, 1, event.alignment);
- printerRenderer.setLineJustify(i, 1, event.justify);
- printerRenderer.setLineBullet(i, 1, event.bullet);
- StyleRange[] styles = event.styles;
- if (styles != null && styles.length > 0) {
- printerRenderer.setStyleRanges(event.ranges, styles);
- }
- }
- }
- }
- Point screenDPI = styledText.getDisplay().getDPI();
- Point printerDPI = printer.getDPI();
- resources = new HashMap<> ();
- for (int i = 0; i < lineCount; i++) {
- Color color = printerRenderer.getLineBackground(i, null);
- if (color != null) {
- if (printOptions.printLineBackground) {
- Color printerColor = (Color)resources.get(color);
- if (printerColor == null) {
- printerColor = new Color (color.getRGB());
- resources.put(color, printerColor);
- }
- printerRenderer.setLineBackground(i, 1, printerColor);
- } else {
- printerRenderer.setLineBackground(i, 1, null);
- }
- }
- int indent = printerRenderer.getLineIndent(i, 0);
- if (indent != 0) {
- printerRenderer.setLineIndent(i, 1, indent * printerDPI.x / screenDPI.x);
- }
- }
- StyleRange[] styles = printerRenderer.styles;
- for (int i = 0; i < printerRenderer.styleCount; i++) {
- StyleRange style = styles[i];
- Font font = style.font;
- if (style.font != null) {
- Font printerFont = (Font)resources.get(font);
- if (printerFont == null) {
- printerFont = new Font (printer, font.getFontData());
- resources.put(font, printerFont);
- }
- style.font = printerFont;
- }
- Color color = style.foreground;
- if (color != null) {
- Color printerColor = (Color)resources.get(color);
- if (printOptions.printTextForeground) {
- if (printerColor == null) {
- printerColor = new Color (color.getRGB());
- resources.put(color, printerColor);
- }
- style.foreground = printerColor;
- } else {
- style.foreground = null;
- }
- }
- color = style.background;
- if (color != null) {
- Color printerColor = (Color)resources.get(color);
- if (printOptions.printTextBackground) {
- if (printerColor == null) {
- printerColor = new Color (color.getRGB());
- resources.put(color, printerColor);
- }
- style.background = printerColor;
- } else {
- style.background = null;
- }
- }
- if (!printOptions.printTextFontStyle) {
- style.fontStyle = SWT.NORMAL;
- }
- style.rise = style.rise * printerDPI.y / screenDPI.y;
- GlyphMetrics metrics = style.metrics;
- if (metrics != null) {
- metrics.ascent = metrics.ascent * printerDPI.y / screenDPI.y;
- metrics.descent = metrics.descent * printerDPI.y / screenDPI.y;
- metrics.width = metrics.width * printerDPI.x / screenDPI.x;
- }
- }
- lineSpacing = styledText.lineSpacing * printerDPI.y / screenDPI.y;
- if (printOptions.printLineNumbers) {
- printMargin = 3 * printerDPI.x / screenDPI.x;
- }
- }
- /**
- * Copies the text of the specified StyledTextContent.
- *
- * @param original the StyledTextContent to copy.
- */
- StyledTextContent copyContent(StyledTextContent original) {
- StyledTextContent printerContent = new DefaultContent();
- int insertOffset = 0;
- for (int i = 0; i < original.getLineCount(); i++) {
- int insertEndOffset;
- if (i < original.getLineCount() - 1) {
- insertEndOffset = original.getOffsetAtLine(i + 1);
- } else {
- insertEndOffset = original.getCharCount();
- }
- printerContent.replaceTextRange(insertOffset, 0, original.getTextRange(insertOffset, insertEndOffset - insertOffset));
- insertOffset = insertEndOffset;
- }
- return printerContent;
- }
- /**
- * Disposes of the resources and the PrintRenderer.
- */
- void dispose() {
- if (gc != null) {
- gc.dispose();
- gc = null;
- }
- if (resources != null) {
- for (Resource resource : resources.values()) {
- resource.dispose();
- }
- resources = null;
- }
- if (printerFont != null) {
- printerFont.dispose();
- printerFont = null;
- }
- if (printerRenderer != null) {
- printerRenderer.dispose();
- printerRenderer = null;
- }
- }
- void init() {
- Rectangle trim = printer.computeTrim(0, 0, 0, 0);
- Point dpi = printer.getDPI();
-
- printerFont = new Font(printer, fontData.getName(), fontData.getHeight(), SWT.NORMAL);
- clientArea = printer.getClientArea();
- pageWidth = clientArea.width;
- // one inch margin around text
- clientArea.x = dpi.x + trim.x;
- clientArea.y = dpi.y + trim.y;
- clientArea.width -= (clientArea.x + trim.width);
- clientArea.height -= (clientArea.y + trim.height);
-
- int style = mirrored ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
- gc = new GC(printer, style);
- gc.setFont(printerFont);
- printerRenderer.setFont(printerFont, tabLength);
- int lineHeight = printerRenderer.getLineHeight();
- if (printOptions.header != null) {
- clientArea.y += lineHeight * 2;
- clientArea.height -= lineHeight * 2;
- }
- if (printOptions.footer != null) {
- clientArea.height -= lineHeight * 2;
- }
-
- // TODO not wrapped
- StyledTextContent content = printerRenderer.content;
- startLine = 0;
- endLine = singleLine ? 0 : content.getLineCount() - 1;
- if (scope == PrinterData.PAGE_RANGE) {
- int pageSize = clientArea.height / lineHeight;//WRONG
- startLine = (startPage - 1) * pageSize;
- } else if (scope == PrinterData.SELECTION) {
- startLine = content.getLineAtOffset(selection[0].x);
- if (selection[0].y > 0) {
- endLine = content.getLineAtOffset(selection[0].y);
- } else {
- endLine = startLine - 1;
- }
- }
- }
- /**
- * Prints the lines in the specified page range.
- */
- void print() {
- Color background = gc.getBackground();
- Color foreground = gc.getForeground();
- int paintY = clientArea.y;
- int paintX = clientArea.x;
- int width = clientArea.width;
- int page = startPage;
- int pageBottom = clientArea.y + clientArea.height;
- int orientation = gc.getStyle() & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT);
- TextLayout printLayout = null;
- if (printOptions.printLineNumbers || printOptions.header != null || printOptions.footer != null) {
- printLayout = new TextLayout(printer);
- printLayout.setFont(printerFont);
- }
- if (printOptions.printLineNumbers) {
- int numberingWidth = 0;
- int count = endLine - startLine + 1;
- String[] lineLabels = printOptions.lineLabels;
- if (lineLabels != null) {
- for (int i = startLine; i < Math.min(count, lineLabels.length); i++) {
- if (lineLabels[i] != null) {
- printLayout.setText(lineLabels[i]);
- int lineWidth = printLayout.getBounds().width;
- numberingWidth = Math.max(numberingWidth, lineWidth);
- }
- }
- } else {
- StringBuilder buffer = new StringBuilder("0");
- while ((count /= 10) > 0) buffer.append("0");
- printLayout.setText(buffer.toString());
- numberingWidth = printLayout.getBounds().width;
- }
- numberingWidth += printMargin;
- if (numberingWidth > width) numberingWidth = width;
- paintX += numberingWidth;
- width -= numberingWidth;
- }
- for (int i = startLine; i <= endLine && page <= endPage; i++) {
- if (paintY == clientArea.y) {
- printer.startPage();
- printDecoration(page, true, printLayout);
- }
- TextLayout layout = printerRenderer.getTextLayout(i, orientation, width, lineSpacing);
- Color lineBackground = printerRenderer.getLineBackground(i, background);
- int paragraphBottom = paintY + layout.getBounds().height;
- if (paragraphBottom <= pageBottom) {
- //normal case, the whole paragraph fits in the current page
- printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
- paintY = paragraphBottom;
- } else {
- int lineCount = layout.getLineCount();
- while (paragraphBottom > pageBottom && lineCount > 0) {
- lineCount--;
- paragraphBottom -= layout.getLineBounds(lineCount).height + layout.getSpacing();
- }
- if (lineCount == 0) {
- //the whole paragraph goes to the next page
- printDecoration(page, false, printLayout);
- printer.endPage();
- page++;
- if (page <= endPage) {
- printer.startPage();
- printDecoration(page, true, printLayout);
- paintY = clientArea.y;
- printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
- paintY += layout.getBounds().height;
- }
- } else {
- //draw paragraph top in the current page and paragraph bottom in the next
- int height = paragraphBottom - paintY;
- gc.setClipping(clientArea.x, paintY, clientArea.width, height);
- printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
- gc.setClipping((Rectangle)null);
- printDecoration(page, false, printLayout);
- printer.endPage();
- page++;
- if (page <= endPage) {
- printer.startPage();
- printDecoration(page, true, printLayout);
- paintY = clientArea.y - height;
- int layoutHeight = layout.getBounds().height;
- gc.setClipping(clientArea.x, clientArea.y, clientArea.width, layoutHeight - height);
- printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
- gc.setClipping((Rectangle)null);
- paintY += layoutHeight;
- }
- }
- }
- printerRenderer.disposeTextLayout(layout);
- }
- if (page <= endPage && paintY > clientArea.y) {
- // close partial page
- printDecoration(page, false, printLayout);
- printer.endPage();
- }
- if (printLayout != null) printLayout.dispose();
- }
- /**
- * Print header or footer decorations.
- *
- * @param page page number to print, if specified in the StyledTextPrintOptions header or footer.
- * @param header true = print the header, false = print the footer
- */
- void printDecoration(int page, boolean header, TextLayout layout) {
- String text = header ? printOptions.header : printOptions.footer;
- if (text == null) return;
- int lastSegmentIndex = 0;
- for (int i = 0; i < 3; i++) {
- int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex);
- String segment;
- if (segmentIndex == -1) {
- segment = text.substring(lastSegmentIndex);
- printDecorationSegment(segment, i, page, header, layout);
- break;
- } else {
- segment = text.substring(lastSegmentIndex, segmentIndex);
- printDecorationSegment(segment, i, page, header, layout);
- lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length();
- }
- }
- }
- /**
- * Print one segment of a header or footer decoration.
- * Headers and footers have three different segments.
- * One each for left aligned, centered, and right aligned text.
- *
- * @param segment decoration segment to print
- * @param alignment alignment of the segment. 0=left, 1=center, 2=right
- * @param page page number to print, if specified in the decoration segment.
- * @param header true = print the header, false = print the footer
- */
- void printDecorationSegment(String segment, int alignment, int page, boolean header, TextLayout layout) {
- int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG);
- if (pageIndex != -1) {
- int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length();
- StringBuilder buffer = new StringBuilder(segment.substring (0, pageIndex));
- buffer.append (page);
- buffer.append (segment.substring(pageIndex + pageTagLength));
- segment = buffer.toString();
- }
- if (segment.length() > 0) {
- layout.setText(segment);
- int segmentWidth = layout.getBounds().width;
- int segmentHeight = printerRenderer.getLineHeight();
- int drawX = 0, drawY;
- if (alignment == LEFT) {
- drawX = clientArea.x;
- } else if (alignment == CENTER) {
- drawX = (pageWidth - segmentWidth) / 2;
- } else if (alignment == RIGHT) {
- drawX = clientArea.x + clientArea.width - segmentWidth;
- }
- if (header) {
- drawY = clientArea.y - segmentHeight * 2;
- } else {
- drawY = clientArea.y + clientArea.height + segmentHeight;
- }
- layout.draw(gc, drawX, drawY);
- }
- }
- void printLine(int x, int y, GC gc, Color foreground, Color background, TextLayout layout, TextLayout printLayout, int index) {
- if (background != null) {
- Rectangle rect = layout.getBounds();
- gc.setBackground(background);
- gc.fillRectangle(x, y, rect.width, rect.height);
-
-// int lineCount = layout.getLineCount();
+//
+//
+//import java.util.*;
+//import java.util.function.*;
+//import java.util.stream.*;
+//
+//import org.eclipse.swt.*;
+//import org.eclipse.swt.accessibility.*;
+//import org.eclipse.swt.dnd.*;
+//import org.eclipse.swt.events.*;
+//import org.eclipse.swt.graphics.*;
+//import org.eclipse.swt.internal.*;
+//import org.eclipse.swt.printing.*;
+//import org.eclipse.swt.widgets.*;
+//
+///**
+// * A StyledText is an editable user interface object that displays lines
+// * of text. The following style attributes can be defined for the text:
+// *
+// *
foreground color
+// *
background color
+// *
font style (bold, italic, bold-italic, regular)
+// *
underline
+// *
strikeout
+// *
+// *
+// * In addition to text style attributes, the background color of a line may
+// * be specified.
+// *
+// * There are two ways to use this widget when specifying text style information.
+// * You may use the API that is defined for StyledText or you may define your own
+// * LineStyleListener. If you define your own listener, you will be responsible
+// * for maintaining the text style information for the widget. IMPORTANT: You may
+// * not define your own listener and use the StyledText API. The following
+// * StyledText API is not supported if you have defined a LineStyleListener:
+// *
+// *
getStyleRangeAtOffset(int)
+// *
getStyleRanges()
+// *
replaceStyleRanges(int,int,StyleRange[])
+// *
setStyleRange(StyleRange)
+// *
setStyleRanges(StyleRange[])
+// *
+// *
+// * There are two ways to use this widget when specifying line background colors.
+// * You may use the API that is defined for StyledText or you may define your own
+// * LineBackgroundListener. If you define your own listener, you will be responsible
+// * for maintaining the line background color information for the widget.
+// * IMPORTANT: You may not define your own listener and use the StyledText API.
+// * The following StyledText API is not supported if you have defined a
+// * LineBackgroundListener:
+// *
+// *
getLineBackground(int)
+// *
setLineBackground(int,int,Color)
+// *
+// *
+// * The content implementation for this widget may also be user-defined. To do so,
+// * you must implement the StyledTextContent interface and use the StyledText API
+// * setContent(StyledTextContent) to initialize the widget.
+// *
+// *
+// *
Styles:
FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP
+// *
+// * IMPORTANT: This class is not intended to be subclassed.
+// *
+// *
+// * @see StyledText snippets
+// * @see SWT Examples: CustomControlExample, TextEditor
+// * @see Sample code and further information
+// * @noextend This class is not intended to be subclassed by clients.
+// */
+//public class StyledText extends Canvas {
+// static final char TAB = '\t';
+// static final String PlatformLineDelimiter = System.lineSeparator();
+// static final int BIDI_CARET_WIDTH = 3;
+// static final int DEFAULT_WIDTH = 64;
+// static final int DEFAULT_HEIGHT = 64;
+// static final int V_SCROLL_RATE = 50;
+// static final int H_SCROLL_RATE = 10;
+// static final int PREVIOUS_OFFSET_TRAILING = 0;
+// static final int OFFSET_LEADING = 1;
+//
+// static final String STYLEDTEXT_KEY = "org.eclipse.swt.internal.cocoa.styledtext"; //$NON-NLS-1$
+// private static int getX(Point p) { return p.x; } // workaround p -> p.x lose typing and cannot be chained in comparing...
+// static final Comparator SELECTION_COMPARATOR = Comparator.comparingInt(StyledText::getX).thenComparingInt(p -> p.y);
+//
+// Color selectionBackground; // selection background color
+// Color selectionForeground; // selection foreground color
+// StyledTextContent content; // native content (default or user specified)
+// StyledTextRenderer renderer;
+// Listener listener;
+// TextChangeListener textChangeListener; // listener for TextChanging, TextChanged and TextSet events from StyledTextContent
+// int verticalScrollOffset = 0; // pixel based
+// int horizontalScrollOffset = 0; // pixel based
+// boolean alwaysShowScroll = true;
+// int ignoreResize = 0;
+// int topIndex = 0; // top visible line
+// int topIndexY;
+// int clientAreaHeight = 0; // the client area height. Needed to calculate content width for new visible lines during Resize callback
+// int clientAreaWidth = 0; // the client area width. Needed during Resize callback to determine if line wrap needs to be recalculated
+// int tabLength = 4; // number of characters in a tab
+// int [] tabs;
+// int leftMargin;
+// int topMargin;
+// int rightMargin;
+// int bottomMargin;
+// Color marginColor;
+// int columnX; // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935
+// Caret[] carets;
+// int[] caretOffsets = {0};
+// int caretAlignment;
+// Point[] selection = { new Point(0, 0) }; // x and y are start and end caret offsets of selection (x <= y)
+// int[] selectionAnchors = {0}; // position of selection anchor for the selection ranges. 0 based offset from beginning of text
+// Point clipboardSelection; // x and y are start and end caret offsets of previous selection
+// Point doubleClickSelection; // selection after last mouse double click
+// boolean editable = true;
+// boolean wordWrap = false; // text is wrapped automatically
+// boolean visualWrap = false; // process line breaks inside logical lines (inserted by BidiSegmentEvent)
+// boolean hasStyleWithVariableHeight = false;
+// boolean hasVerticalIndent = false;
+// boolean doubleClickEnabled = true; // see getDoubleClickEnabled
+// boolean overwrite = false; // insert/overwrite edit mode
+// int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default.
+// Map keyActionMap = new HashMap<>();
+// Color background = null; // workaround for bug 4791
+// Color foreground = null; //
+// /** True if a non-default background color is set */
+// boolean customBackground;
+// /** True if a non-default foreground color is set */
+// boolean customForeground;
+// /** False iff the widget is disabled */
+// boolean enabled = true;
+// /** True iff the widget is in the midst of being enabled or disabled */
+// boolean insideSetEnableCall;
+// Clipboard clipboard;
+// int clickCount;
+// int autoScrollDirection = SWT.NULL; // the direction of autoscrolling (up, down, right, left)
+// int autoScrollDistance = 0;
+// int lastTextChangeStart; // cache data of the
+// int lastTextChangeNewLineCount; // last text changing
+// int lastTextChangeNewCharCount; // event for use in the
+// int lastTextChangeReplaceLineCount; // text changed handler
+// int lastTextChangeReplaceCharCount;
+// int lastCharCount = 0;
+// int lastLineBottom; // the bottom pixel of the last line been replaced
+// boolean bidiColoring = false; // apply the BIDI algorithm on text segments of the same color
+// Image leftCaretBitmap = null;
+// Image rightCaretBitmap = null;
+// int caretDirection = SWT.NULL;
+// int caretWidth = 0;
+// Caret defaultCaret = null;
+// boolean updateCaretDirection = true;
+// boolean dragDetect = true;
+// IME ime;
+// Cursor cursor;
+// int alignment;
+// boolean justify;
+// int indent, wrapIndent;
+// int lineSpacing;
+// int alignmentMargin;
+// int newOrientation = SWT.NONE;
+// int accCaretOffset;
+// Accessible acc;
+// AccessibleControlAdapter accControlAdapter;
+// AccessibleAttributeAdapter accAttributeAdapter;
+// AccessibleEditableTextListener accEditableTextListener;
+// AccessibleTextExtendedAdapter accTextExtendedAdapter;
+// AccessibleAdapter accAdapter;
+// MouseNavigator mouseNavigator;
+// boolean middleClickPressed;
+//
+// //block selection
+// boolean blockSelection;
+// int blockXAnchor = -1, blockYAnchor = -1;
+// int blockXLocation = -1, blockYLocation = -1;
+//
+// final static boolean IS_MAC, IS_GTK;
+// static {
+// String platform = SWT.getPlatform();
+// IS_MAC = "cocoa".equals(platform);
+// IS_GTK = "gtk".equals(platform);
+// }
+//
+// /**
+// * The Printing class implements printing of a range of text.
+// * An instance of Printing is returned in the
+// * StyledText#print(Printer) API. The run() method may be
+// * invoked from any thread.
+// */
+// static class Printing implements Runnable {
+// final static int LEFT = 0; // left aligned header/footer segment
+// final static int CENTER = 1; // centered header/footer segment
+// final static int RIGHT = 2; // right aligned header/footer segment
+//
+// Printer printer;
+// StyledTextRenderer printerRenderer;
+// StyledTextPrintOptions printOptions;
+// Rectangle clientArea;
+// FontData fontData;
+// Font printerFont;
+// Map resources;
+// int tabLength;
+// GC gc; // printer GC
+// int pageWidth; // width of a printer page in pixels
+// int startPage; // first page to print
+// int endPage; // last page to print
+// int scope; // scope of print job
+// int startLine; // first (wrapped) line to print
+// int endLine; // last (wrapped) line to print
+// boolean singleLine; // widget single line mode
+// Point[] selection = { new Point(0, 0) }; // x and y are start and end caret offsets of selection (x <= y)
+// boolean mirrored; // indicates the printing gc should be mirrored
+// int lineSpacing;
+// int printMargin;
+//
+// /**
+// * Creates an instance of Printing.
+// * Copies the widget content and rendering data that needs
+// * to be requested from listeners.
+// *
+// * @param parent StyledText widget to print.
+// * @param printer printer device to print on.
+// * @param printOptions print options
+// */
+// Printing(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) {
+// this.printer = printer;
+// this.printOptions = printOptions;
+// this.mirrored = (styledText.getStyle() & SWT.MIRRORED) != 0;
+// singleLine = styledText.isSingleLine();
+// startPage = 1;
+// endPage = Integer.MAX_VALUE;
+// PrinterData data = printer.getPrinterData();
+// scope = data.scope;
+// if (scope == PrinterData.PAGE_RANGE) {
+// startPage = data.startPage;
+// endPage = data.endPage;
+// if (endPage < startPage) {
+// int temp = endPage;
+// endPage = startPage;
+// startPage = temp;
+// }
+// } else if (scope == PrinterData.SELECTION) {
+// selection = Arrays.copyOf(styledText.selection, styledText.selection.length);
+// }
+// printerRenderer = new StyledTextRenderer(printer, null);
+// printerRenderer.setContent(copyContent(styledText.getContent()));
+// cacheLineData(styledText);
+// }
+// /**
+// * Caches all line data that needs to be requested from a listener.
+// *
+// * @param printerContent StyledTextContent to request
+// * line data for.
+// */
+// void cacheLineData(StyledText styledText) {
+// StyledTextRenderer renderer = styledText.renderer;
+// renderer.copyInto(printerRenderer);
+// fontData = styledText.getFont().getFontData()[0];
+// tabLength = styledText.tabLength;
+// int lineCount = printerRenderer.lineCount;
+// if (styledText.isListening(ST.LineGetBackground) || (styledText.isListening(ST.LineGetSegments)) || styledText.isListening(ST.LineGetStyle)) {
+// StyledTextContent content = printerRenderer.content;
// for (int i = 0; i < lineCount; i++) {
-// Rectangle rect = layout.getLineBounds(i);
-// rect.x += paintX;
-// rect.y += paintY + layout.getSpacing();
-// rect.width = width;//layout bounds
-// gc.fillRectangle(rect);
-// }
- }
- if (printOptions.printLineNumbers) {
- FontMetrics metrics = layout.getLineMetrics(0);
- printLayout.setAscent(metrics.getAscent() + metrics.getLeading());
- printLayout.setDescent(metrics.getDescent());
- String[] lineLabels = printOptions.lineLabels;
- if (lineLabels != null) {
- if (0 <= index && index < lineLabels.length && lineLabels[index] != null) {
- printLayout.setText(lineLabels[index]);
- } else {
- printLayout.setText("");
- }
- } else {
- printLayout.setText(String.valueOf(index));
- }
- int paintX = x - printMargin - printLayout.getBounds().width;
- printLayout.draw(gc, paintX, y);
- printLayout.setAscent(-1);
- printLayout.setDescent(-1);
- }
- gc.setForeground(foreground);
- layout.draw(gc, x, y);
- }
- /**
- * Starts a print job and prints the pages specified in the constructor.
- */
- @Override
- public void run() {
- String jobName = printOptions.jobName;
- if (jobName == null) {
- jobName = "Printing";
- }
- if (printer.startJob(jobName)) {
- init();
- print();
- dispose();
- printer.endJob();
- }
- }
- }
-
-/**
- * Constructs a new instance of this class given its parent
- * and a style value describing its behavior and appearance.
- *
- * The style value is either one of the style constants defined in
- * class SWT which is applicable to instances of this
- * class, or must be built by bitwise OR'ing together
- * (that is, using the int "|" operator) two or more
- * of those SWT style constants. The class description
- * lists the style constants that are applicable to the class.
- * Style bits are also inherited from superclasses.
- *
- *
- * @param parent a widget which will be the parent of the new instance (cannot be null)
- * @param style the style of widget to construct
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the parent is null
- *
- * @exception SWTException
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
- *
- *
- * @see SWT#FULL_SELECTION
- * @see SWT#MULTI
- * @see SWT#READ_ONLY
- * @see SWT#SINGLE
- * @see SWT#WRAP
- * @see #getStyle
- */
-public StyledText(Composite parent, int style) {
- super(parent, checkStyle(style));
- // set the fg in the OS to ensure that these are the same as StyledText, necessary
- // for ensuring that the bg/fg the IME box uses is the same as what StyledText uses
- super.setForeground(getForeground());
- super.setDragDetect(false);
- Display display = getDisplay();
- if ((style & SWT.READ_ONLY) != 0) {
- setEditable(false);
- }
- leftMargin = rightMargin = isBidiCaret() ? BIDI_CARET_WIDTH - 1: 0;
- if ((style & SWT.SINGLE) != 0 && (style & SWT.BORDER) != 0) {
- leftMargin = topMargin = rightMargin = bottomMargin = 2;
- }
- alignment = style & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
- if (alignment == 0) alignment = SWT.LEFT;
- clipboard = new Clipboard(display);
- installDefaultContent();
- renderer = new StyledTextRenderer(getDisplay(), this);
- renderer.setContent(content);
- renderer.setFont(getFont(), tabLength);
- ime = new IME(this, SWT.NONE);
- defaultCaret = new Caret(this, SWT.NONE);
- if ((style & SWT.WRAP) != 0) {
- setWordWrap(true);
- }
- if (isBidiCaret()) {
- createCaretBitmaps();
- Runnable runnable = () -> {
- int direction = BidiUtil.getKeyboardLanguage() == BidiUtil.KEYBOARD_BIDI ? SWT.RIGHT : SWT.LEFT;
- if (direction == caretDirection) return;
- if (getCaret() != defaultCaret) return;
- setCaretLocations(Arrays.stream(caretOffsets).mapToObj(this::getPointAtOffset).toArray(Point[]::new), direction);
- };
- BidiUtil.addLanguageListener(this, runnable);
- }
- setCaret(defaultCaret);
- calculateScrollBars();
- createKeyBindings();
- super.setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM));
- installListeners();
- initializeAccessible();
- setData("DEFAULT_DROP_TARGET_EFFECT", new StyledTextDropTargetEffect(this));
- if (IS_MAC) setData(STYLEDTEXT_KEY);
-}
-/**
- * Adds an extended modify listener. An ExtendedModify event is sent by the
- * widget when the widget text has changed.
- *
- * @param extendedModifyListener the listener
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- * A BidiSegmentEvent is sent
- * whenever a line of text is measured or rendered. You can
- * specify text ranges in the line that should be treated as if they
- * had a different direction than the surrounding text.
- * This may be used when adjacent segments of right-to-left text should
- * not be reordered relative to each other.
- * E.g., multiple Java string literals in a right-to-left language
- * should generally remain in logical order to each other, that is, the
- * way they are stored.
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- * @see BidiSegmentEvent
- * @since 2.0
- */
-public void addBidiSegmentListener(BidiSegmentListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- addListener(ST.LineGetSegments, new StyledTextListener(listener));
- resetCache(0, content.getLineCount());
- setCaretLocations();
- super.redraw();
-}
-/**
- * Adds a caret listener. CaretEvent is sent when the caret offset changes.
- *
- * @param listener the listener
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- *
- * @since 3.5
- */
-public void addCaretListener(CaretListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- addListener(ST.CaretMoved, new StyledTextListener(listener));
-}
-/**
- * Adds a line background listener. A LineGetBackground event is sent by the
- * widget to determine the background color for a line.
- *
- * @param listener the listener
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void addLineBackgroundListener(LineBackgroundListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- if (!isListening(ST.LineGetBackground)) {
- renderer.clearLineBackground(0, content.getLineCount());
- }
- addListener(ST.LineGetBackground, new StyledTextListener(listener));
-}
-/**
- * Adds a line style listener. A LineGetStyle event is sent by the widget to
- * determine the styles for a line.
- *
- * @param listener the listener
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void addLineStyleListener(LineStyleListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- if (!isListening(ST.LineGetStyle)) {
- setStyleRanges(0, 0, null, null, true);
- renderer.clearLineStyle(0, content.getLineCount());
- }
- addListener(ST.LineGetStyle, new StyledTextListener(listener));
- setCaretLocations();
-}
-/**
- * Adds a modify listener. A Modify event is sent by the widget when the widget text
- * has changed.
- *
- * @param modifyListener the listener
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void addModifyListener(ModifyListener modifyListener) {
- addTypedListener(modifyListener, SWT.Modify);
-}
-/**
- * Adds a paint object listener. A paint object event is sent by the widget when an object
- * needs to be drawn.
- *
- * @param listener the listener
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- *
- * @since 3.2
- *
- * @see PaintObjectListener
- * @see PaintObjectEvent
- */
-public void addPaintObjectListener(PaintObjectListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- addListener(ST.PaintObject, new StyledTextListener(listener));
-}
-/**
- * Adds a selection listener. A Selection event is sent by the widget when the
- * user changes the selection.
- *
- * When widgetSelected is called, the event x and y fields contain
- * the start and end caret indices of the selection[0]. The selection values returned are visual
- * (i.e., x will always always be <= y).
- * No event is sent when the caret is moved while the selection length is 0.
- *
- * widgetDefaultSelected is not called for StyledTexts.
- *
- *
- * @param listener the listener which should be notified when the user changes the receiver's selection
-
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see SelectionListener
- * @see #removeSelectionListener
- * @see SelectionEvent
- */
-public void addSelectionListener(SelectionListener listener) {
- addTypedListener(listener, SWT.Selection);
-}
-/**
- * Adds a verify key listener. A VerifyKey event is sent by the widget when a key
- * is pressed. The widget ignores the key press if the listener sets the doit field
- * of the event to false.
- *
- * @param listener the listener
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void addVerifyKeyListener(VerifyKeyListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- addListener(ST.VerifyKey, new StyledTextListener(listener));
-}
-/**
- * Adds a verify listener. A Verify event is sent by the widget when the widget text
- * is about to change. The listener can set the event text and the doit field to
- * change the text that is set in the widget or to force the widget to ignore the
- * text change.
- *
- * @param verifyListener the listener
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void addVerifyListener(VerifyListener verifyListener) {
- addTypedListener(verifyListener, SWT.Verify);
-}
-/**
- * Adds a word movement listener. A movement event is sent when the boundary
- * of a word is needed. For example, this occurs during word next and word
- * previous actions.
- *
- * @param movementListener the listener
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- *
- * @see MovementEvent
- * @see MovementListener
- * @see #removeWordMovementListener
- *
- * @since 3.3
- */
-public void addWordMovementListener(MovementListener movementListener) {
- checkWidget();
- if (movementListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- addListener(ST.WordNext, new StyledTextListener(movementListener));
- addListener(ST.WordPrevious, new StyledTextListener(movementListener));
-}
-/**
- * Appends a string to the text at the end of the widget.
- *
- * @param string the string to be appended
- * @see #replaceTextRange(int,int,String)
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void append(String string) {
- checkWidget();
- if (string == null) {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
- int lastChar = Math.max(getCharCount(), 0);
- replaceTextRange(lastChar, 0, string);
-}
-/**
- * Calculates the scroll bars
- */
-void calculateScrollBars() {
- ScrollBar horizontalBar = getHorizontalBar();
- ScrollBar verticalBar = getVerticalBar();
- setScrollBars(true);
- if (verticalBar != null) {
- verticalBar.setIncrement(getVerticalIncrement());
- }
- if (horizontalBar != null) {
- horizontalBar.setIncrement(getHorizontalIncrement());
- }
-}
-/**
- * Calculates the top index based on the current vertical scroll offset.
- * The top index is the index of the topmost fully visible line or the
- * topmost partially visible line if no line is fully visible.
- * The top index starts at 0.
- */
-void calculateTopIndex(int delta) {
- int oldDelta = delta;
- int oldTopIndex = topIndex;
- int oldTopIndexY = topIndexY;
- if (isFixedLineHeight()) {
- int verticalIncrement = getVerticalIncrement();
- if (verticalIncrement == 0) {
- return;
- }
- topIndex = Compatibility.ceil(getVerticalScrollOffset(), verticalIncrement);
- // Set top index to partially visible top line if no line is fully
- // visible but at least some of the widget client area is visible.
- // Fixes bug 15088.
- if (topIndex >= 0) {
- if (clientAreaHeight > 0) {
- int bottomPixel = getVerticalScrollOffset() + clientAreaHeight;
- topIndexY = getLinePixel(topIndex);
- int fullLineTopPixel = topIndex * verticalIncrement;
- int fullLineVisibleHeight = bottomPixel - fullLineTopPixel;
- // set top index to partially visible line if no line fully fits in
- // client area or if space is available but not used (the latter should
- // never happen because we use claimBottomFreeSpace)
- if (fullLineVisibleHeight < verticalIncrement) {
- topIndex = getVerticalScrollOffset() / verticalIncrement;
- }
- } else if (topIndex >= content.getLineCount()) {
- topIndex = content.getLineCount() - 1;
- }
- }
- } else {
- if (delta >= 0) {
- delta -= topIndexY;
- int lineIndex = topIndex;
- int lineCount = content.getLineCount();
- while (lineIndex < lineCount) {
- if (delta <= 0) break;
- delta -= renderer.getCachedLineHeight(lineIndex++);
- }
- if (lineIndex < lineCount && -delta + renderer.getCachedLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) {
- topIndex = lineIndex;
- topIndexY = -delta;
- } else {
- topIndex = lineIndex - 1;
- topIndexY = -renderer.getCachedLineHeight(topIndex) - delta;
- }
- } else {
- delta -= topIndexY;
- int lineIndex = topIndex;
- while (lineIndex > 0) {
- int lineHeight = renderer.getCachedLineHeight(lineIndex - 1);
- if (delta + lineHeight > 0) break;
- delta += lineHeight;
- lineIndex--;
- }
- if (lineIndex == 0 || -delta + renderer.getCachedLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) {
- topIndex = lineIndex;
- topIndexY = - delta;
- } else {
- topIndex = lineIndex - 1;
- topIndexY = - renderer.getCachedLineHeight(topIndex) - delta;
- }
- }
- }
- if (topIndex < 0) {
- // TODO: This logging is in place to determine why topIndex is getting set to negative values.
- // It should be deleted once we fix the root cause of this issue. See bug 487254 for details.
- System.err.println("StyledText: topIndex was " + topIndex
- + ", isFixedLineHeight() = " + isFixedLineHeight()
- + ", delta = " + delta
- + ", content.getLineCount() = " + content.getLineCount()
- + ", clientAreaHeight = " + clientAreaHeight
- + ", oldTopIndex = " + oldTopIndex
- + ", oldTopIndexY = " + oldTopIndexY
- + ", getVerticalScrollOffset = " + getVerticalScrollOffset()
- + ", oldDelta = " + oldDelta
- + ", getVerticalIncrement() = " + getVerticalIncrement());
- topIndex = 0;
- }
- if (topIndex != oldTopIndex || oldTopIndexY != topIndexY) {
- int width = renderer.getWidth();
- renderer.calculateClientArea();
- if (width != renderer.getWidth()) {
- setScrollBars(false);
- }
- }
-}
-/**
- * Hides the scroll bars if widget is created in single line mode.
- */
-static int checkStyle(int style) {
- if ((style & SWT.SINGLE) != 0) {
- style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP | SWT.MULTI);
- } else {
- style |= SWT.MULTI;
- if ((style & SWT.WRAP) != 0) {
- style &= ~SWT.H_SCROLL;
- }
- }
- style |= SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND;
- /* Clear SWT.CENTER to avoid the conflict with SWT.EMBEDDED */
- return style & ~SWT.CENTER;
-}
-/**
- * Scrolls down the text to use new space made available by a resize or by
- * deleted lines.
- */
-void claimBottomFreeSpace() {
- if (ime.getCompositionOffset() != -1) return;
- if (isFixedLineHeight()) {
- int newVerticalOffset = Math.max(0, renderer.getHeight() - clientAreaHeight);
- if (newVerticalOffset < getVerticalScrollOffset()) {
- scrollVertical(newVerticalOffset - getVerticalScrollOffset(), true);
- }
- } else {
- int bottomIndex = getPartialBottomIndex();
- int height = getLinePixel(bottomIndex + 1);
- if (clientAreaHeight > height) {
- scrollVertical(-getAvailableHeightAbove(clientAreaHeight - height), true);
- }
- }
-}
-/**
- * Scrolls text to the right to use new space made available by a resize.
- */
-void claimRightFreeSpace() {
- int newHorizontalOffset = Math.max(0, renderer.getWidth() - clientAreaWidth);
- if (newHorizontalOffset < horizontalScrollOffset) {
- // item is no longer drawn past the right border of the client area
- // align the right end of the item with the right border of the
- // client area (window is scrolled right).
- scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true);
- }
-}
-void clearBlockSelection(boolean reset, boolean sendEvent) {
- if (reset) resetSelection();
- blockXAnchor = blockYAnchor = -1;
- blockXLocation = blockYLocation = -1;
- caretDirection = SWT.NULL;
- updateCaretVisibility();
- super.redraw();
- if (sendEvent) sendSelectionEvent();
-}
-/**
- * Removes the widget selection.
- *
- * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset.
- */
-void clearSelection(boolean sendEvent) {
- int selectionStart = selection[0].x;
- int selectionEnd = selection[0].y;
- resetSelection();
- // redraw old selection, if any
- if (selectionEnd - selectionStart > 0) {
- int length = content.getCharCount();
- // called internally to remove selection after text is removed
- // therefore make sure redraw range is valid.
- int redrawStart = Math.min(selectionStart, length);
- int redrawEnd = Math.min(selectionEnd, length);
- if (redrawEnd - redrawStart > 0) {
- internalRedrawRange(redrawStart, redrawEnd - redrawStart);
- }
- if (sendEvent) {
- sendSelectionEvent();
- }
- }
-}
-@Override
-public Point computeSize (int wHint, int hHint, boolean changed) {
- checkWidget();
- int lineCount = (getStyle() & SWT.SINGLE) != 0 ? 1 : content.getLineCount();
- int width = 0;
- int height = 0;
- if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
- Display display = getDisplay();
- int maxHeight = display.getClientArea().height;
- for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
- TextLayout layout = renderer.getTextLayout(lineIndex);
- int wrapWidth = layout.getWidth();
- if (wordWrap) layout.setWidth(wHint == 0 ? 1 : wHint == SWT.DEFAULT ? SWT.DEFAULT : Math.max(1, wHint - leftMargin - rightMargin));
- Rectangle rect = layout.getBounds();
- height += rect.height;
- width = Math.max(width, rect.width);
- layout.setWidth(wrapWidth);
- renderer.disposeTextLayout(layout);
- if (isFixedLineHeight() && height > maxHeight) break;
- }
- if (isFixedLineHeight()) {
- height = lineCount * renderer.getLineHeight();
- }
- }
- // Use default values if no text is defined.
- if (width == 0) width = DEFAULT_WIDTH;
- if (height == 0) height = DEFAULT_HEIGHT;
- if (wHint != SWT.DEFAULT) width = wHint;
- if (hHint != SWT.DEFAULT) height = hHint;
- int wTrim = getLeftMargin() + rightMargin + getCaretWidth();
- int hTrim = topMargin + bottomMargin;
- Rectangle rect = computeTrim(0, 0, width + wTrim, height + hTrim);
- return new Point (rect.width, rect.height);
-}
-/**
- * Copies the selected text to the DND.CLIPBOARD clipboard.
- *
- * The text will be put on the clipboard in plain text, HTML, and RTF formats.
- * The DND.CLIPBOARD clipboard is used for data that is
- * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or
- * by menu action.
- *
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public void copy() {
- checkWidget();
- copySelection(DND.CLIPBOARD);
-}
-/**
- * Copies the selected text to the specified clipboard. The text will be put in the
- * clipboard in plain text, HTML, and RTF formats.
- *
- * The clipboardType is one of the clipboard constants defined in class
- * DND. The DND.CLIPBOARD clipboard is
- * used for data that is transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V)
- * or by menu action. The DND.SELECTION_CLIPBOARD
- * clipboard is used for data that is transferred by selecting text and pasting
- * with the middle mouse button.
- *
- *
- * @param clipboardType indicates the type of clipboard
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.1
- */
-public void copy(int clipboardType) {
- checkWidget();
- copySelection(clipboardType);
-}
-boolean copySelection(int type) {
- if (type != DND.CLIPBOARD && type != DND.SELECTION_CLIPBOARD) return false;
- try {
- if (blockSelection && blockXLocation != -1) {
- String text = getBlockSelectionText(PlatformLineDelimiter);
- if (text.length() > 0) {
- //TODO RTF support
- TextTransfer plainTextTransfer = TextTransfer.getInstance();
- Object[] data = new Object[]{text};
- Transfer[] types = new Transfer[]{plainTextTransfer};
- clipboard.setContents(data, types, type);
- return true;
- }
- } else if (getSelectionRanges().length > 2) {
- StringBuilder text = new StringBuilder();
- int[] ranges = getSelectionRanges();
- for (int i = 0; i < ranges.length; i += 2) {
- int offset = ranges[i];
- int length = ranges[i + 1];
- text.append(length == 0 ? "" : getText(offset, offset + length - 1));
- text.append(PlatformLineDelimiter);
- }
- text.delete(text.length() - PlatformLineDelimiter.length(), text.length());
- if (text.length() > 0) {
- //TODO RTF support
- clipboard.setContents(new Object[]{text.toString()}, new Transfer[]{TextTransfer.getInstance()}, type);
- return true;
- }
- } else {
- int length = selection[0].y - selection[0].x;
- if (length > 0) {
- setClipboardContent(selection[0].x, length, type);
- return true;
- }
- }
- } catch (SWTError error) {
- // Copy to clipboard failed. This happens when another application
- // is accessing the clipboard while we copy. Ignore the error.
- // Rethrow all other errors. Fixes bug 17578.
- if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) {
- throw error;
- }
- }
- return false;
-}
-/**
- * Returns the alignment of the widget.
- *
- * @return the alignment
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *R
- * @see #getLineAlignment(int)
- *
- * @since 3.2
- */
-public int getAlignment() {
- checkWidget();
- return alignment;
-}
-/**
- * Returns the Always Show Scrollbars flag. True if the scrollbars are
- * always shown even if they are not required. False if the scrollbars are only
- * visible when some part of the content needs to be scrolled to be seen.
- * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the
- * horizontal and vertical directions.
- *
- * @return the Always Show Scrollbars flag value
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.8
- */
-public boolean getAlwaysShowScrollBars() {
- checkWidget();
- return alwaysShowScroll;
-}
-int getAvailableHeightAbove(int height) {
- int maxHeight = verticalScrollOffset;
- if (maxHeight == -1) {
- int lineIndex = topIndex - 1;
- maxHeight = -topIndexY;
- if (topIndexY > 0) {
- maxHeight += renderer.getLineHeight(lineIndex--);
- }
- while (height > maxHeight && lineIndex >= 0) {
- maxHeight += renderer.getLineHeight(lineIndex--);
- }
- }
- return Math.min(height, maxHeight);
-}
-int getAvailableHeightBellow(int height) {
- int partialBottomIndex = getPartialBottomIndex();
- int topY = getLinePixel(partialBottomIndex);
- int lineHeight = renderer.getLineHeight(partialBottomIndex);
- int availableHeight = 0;
- int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin;
- if (topY + lineHeight > clientAreaHeight) {
- availableHeight = lineHeight - (clientAreaHeight - topY);
- }
- int lineIndex = partialBottomIndex + 1;
- int lineCount = content.getLineCount();
- while (height > availableHeight && lineIndex < lineCount) {
- availableHeight += renderer.getLineHeight(lineIndex++);
- }
- return Math.min(height, availableHeight);
-}
-/**
- * Returns the color of the margins.
- *
- * @return the color of the margins.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public Color getMarginColor() {
- checkWidget();
- return marginColor != null ? marginColor : getBackground();
-}
-/**
- * Returns a string that uses only the line delimiter specified by the
- * StyledTextContent implementation.
- *
- * Returns only the first line if the widget has the SWT.SINGLE style.
- *
- *
- * @param text the text that may have line delimiters that don't
- * match the model line delimiter. Possible line delimiters
- * are CR ('\r'), LF ('\n'), CR/LF ("\r\n")
- * @return the converted text that only uses the line delimiter
- * specified by the model. Returns only the first line if the widget
- * has the SWT.SINGLE style.
- */
-String getModelDelimitedText(String text) {
- int length = text.length();
- if (length == 0) {
- return text;
- }
- int crIndex = 0;
- int lfIndex = 0;
- int i = 0;
- StringBuilder convertedText = new StringBuilder(length);
- String delimiter = getLineDelimiter();
- while (i < length) {
- if (crIndex != -1) {
- crIndex = text.indexOf(SWT.CR, i);
- }
- if (lfIndex != -1) {
- lfIndex = text.indexOf(SWT.LF, i);
- }
- if (lfIndex == -1 && crIndex == -1) { // no more line breaks?
- break;
- } else if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) {
- convertedText.append(text.substring(i, crIndex));
- if (lfIndex == crIndex + 1) { // CR/LF combination?
- i = lfIndex + 1;
- } else {
- i = crIndex + 1;
- }
- } else { // LF occurs before CR!
- convertedText.append(text.substring(i, lfIndex));
- i = lfIndex + 1;
- }
- if (isSingleLine()) {
- break;
- }
- convertedText.append(delimiter);
- }
- // copy remaining text if any and if not in single line mode or no
- // text copied thus far (because there only is one line)
- if (i < length && (!isSingleLine() || convertedText.length() == 0)) {
- convertedText.append(text.substring(i));
- }
- return convertedText.toString();
-}
-boolean checkDragDetect(Event event) {
- if (!isListening(SWT.DragDetect)) return false;
- if (event.button != 1) return false;
- if (blockSelection && blockXLocation != -1) {
- Rectangle rect = getBlockSelectionRectangle();
- if (rect.contains(event.x, event.y)) {
- return dragDetect(event);
- }
- } else {
- if (selection[0].x == selection[0].y) return false;
- int offset = getOffsetAtPoint(event.x, event.y, null, true);
- if (selection[0].x <= offset && offset < selection[0].y) {
- return dragDetect(event);
- }
-
- }
- return false;
-}
-
-/**
- * Creates default key bindings.
- */
-void createKeyBindings() {
- int nextKey = isMirrored() ? SWT.ARROW_LEFT : SWT.ARROW_RIGHT;
- int previousKey = isMirrored() ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
-
- // Navigation
- setKeyBinding(SWT.ARROW_UP, ST.LINE_UP);
- setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN);
- if (IS_MAC) {
- setKeyBinding(previousKey | SWT.MOD1, ST.LINE_START);
- setKeyBinding(nextKey | SWT.MOD1, ST.LINE_END);
- setKeyBinding(SWT.HOME, ST.TEXT_START);
- setKeyBinding(SWT.END, ST.TEXT_END);
- setKeyBinding(SWT.ARROW_UP | SWT.MOD1, ST.TEXT_START);
- setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1, ST.TEXT_END);
- setKeyBinding(nextKey | SWT.MOD3, ST.WORD_NEXT);
- setKeyBinding(previousKey | SWT.MOD3, ST.WORD_PREVIOUS);
- } else {
- setKeyBinding(SWT.HOME, ST.LINE_START);
- setKeyBinding(SWT.END, ST.LINE_END);
- setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START);
- setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END);
- setKeyBinding(nextKey | SWT.MOD1, ST.WORD_NEXT);
- setKeyBinding(previousKey | SWT.MOD1, ST.WORD_PREVIOUS);
- }
- setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP);
- setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN);
- setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START);
- setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END);
- setKeyBinding(nextKey, ST.COLUMN_NEXT);
- setKeyBinding(previousKey, ST.COLUMN_PREVIOUS);
-
- // Selection
- setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP);
- setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN);
- if (IS_MAC) {
- setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_START);
- setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_END);
- setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_TEXT_START);
- setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_TEXT_END);
- setKeyBinding(SWT.ARROW_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START);
- setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END);
- setKeyBinding(nextKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_NEXT);
- setKeyBinding(previousKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_PREVIOUS);
- } else {
- setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START);
- setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END);
- setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START);
- setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END);
- setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT);
- setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS);
- }
- setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP);
- setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN);
- setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START);
- setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END);
- setKeyBinding(nextKey | SWT.MOD2, ST.SELECT_COLUMN_NEXT);
- setKeyBinding(previousKey | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS);
-
- // Modification
- // Cut, Copy, Paste
- setKeyBinding('X' | SWT.MOD1, ST.CUT);
- setKeyBinding('C' | SWT.MOD1, ST.COPY);
- setKeyBinding('V' | SWT.MOD1, ST.PASTE);
- if (IS_MAC) {
- setKeyBinding(SWT.DEL | SWT.MOD2, ST.DELETE_NEXT);
- setKeyBinding(SWT.BS | SWT.MOD3, ST.DELETE_WORD_PREVIOUS);
- setKeyBinding(SWT.DEL | SWT.MOD3, ST.DELETE_WORD_NEXT);
- } else {
- // Cut, Copy, Paste Wordstar style
- setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT);
- setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY);
- setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE);
- }
- setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS);
- setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS);
- setKeyBinding(SWT.DEL, ST.DELETE_NEXT);
- setKeyBinding(SWT.BS | SWT.MOD1, ST.DELETE_WORD_PREVIOUS);
- setKeyBinding(SWT.DEL | SWT.MOD1, ST.DELETE_WORD_NEXT);
-
- // Miscellaneous
- setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE);
-}
-/**
- * Create the bitmaps to use for the caret in bidi mode. This
- * method only needs to be called upon widget creation and when the
- * font changes (the caret bitmap height needs to match font height).
- */
-void createCaretBitmaps() {
- int caretWidth = BIDI_CARET_WIDTH;
- Display display = getDisplay();
- if (leftCaretBitmap != null) {
- if (defaultCaret != null && leftCaretBitmap.equals(defaultCaret.getImage())) {
- defaultCaret.setImage(null);
- }
- leftCaretBitmap.dispose();
- }
- int lineHeight = renderer.getLineHeight();
- leftCaretBitmap = new Image(display, caretWidth, lineHeight);
- GC gc = new GC (leftCaretBitmap);
- gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
- gc.fillRectangle(0, 0, caretWidth, lineHeight);
- gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
- gc.drawLine(0,0,0,lineHeight);
- gc.drawLine(0,0,caretWidth-1,0);
- gc.drawLine(0,1,1,1);
- gc.dispose();
-
- if (rightCaretBitmap != null) {
- if (defaultCaret != null && rightCaretBitmap.equals(defaultCaret.getImage())) {
- defaultCaret.setImage(null);
- }
- rightCaretBitmap.dispose();
- }
- rightCaretBitmap = new Image(display, caretWidth, lineHeight);
- gc = new GC (rightCaretBitmap);
- gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
- gc.fillRectangle(0, 0, caretWidth, lineHeight);
- gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
- gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight);
- gc.drawLine(0,0,caretWidth-1,0);
- gc.drawLine(caretWidth-1,1,1,1);
- gc.dispose();
-}
-/**
- * Moves the selected text to the clipboard. The text will be put in the
- * clipboard in plain text, HTML, and RTF formats.
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public void cut() {
- checkWidget();
- // Abort cut operation if copy to clipboard fails.
- // Fixes bug 21030.
- if (copySelection(DND.CLIPBOARD)) {
- if (blockSelection && blockXLocation != -1) {
- insertBlockSelectionText((char)0, SWT.NULL);
- } else {
- doDelete();
- }
- }
-}
-/**
- * A mouse move event has occurred. See if we should start autoscrolling. If
- * the move position is outside of the client area, initiate autoscrolling.
- * Otherwise, we've moved back into the widget so end autoscrolling.
- */
-void doAutoScroll(Event event) {
- int caretLine = getFirstCaretLine();
- if (event.y > clientAreaHeight - bottomMargin && caretLine != content.getLineCount() - 1) {
- doAutoScroll(SWT.DOWN, event.y - (clientAreaHeight - bottomMargin));
- } else if (event.y < topMargin && caretLine != 0) {
- doAutoScroll(SWT.UP, topMargin - event.y);
- } else if (event.x < leftMargin && !wordWrap) {
- doAutoScroll(ST.COLUMN_PREVIOUS, leftMargin - event.x);
- } else if (event.x > clientAreaWidth - rightMargin && !wordWrap) {
- doAutoScroll(ST.COLUMN_NEXT, event.x - (clientAreaWidth - rightMargin));
- } else {
- endAutoScroll();
- }
-}
-/**
- * Initiates autoscrolling.
- *
- * @param direction SWT.UP, SWT.DOWN, SWT.COLUMN_NEXT, SWT.COLUMN_PREVIOUS
- */
-void doAutoScroll(int direction, int distance) {
- autoScrollDistance = distance;
- // If we're already autoscrolling in the given direction do nothing
- if (autoScrollDirection == direction) {
- return;
- }
-
- Runnable timer = null;
- final Display display = getDisplay();
- // Set a timer that will simulate the user pressing and holding
- // down a cursor key (i.e., arrowUp, arrowDown).
- if (direction == SWT.UP) {
- timer = new Runnable() {
- @Override
- public void run() {
- /* Bug 437357 - NPE in StyledText.getCaretLine
- * StyledText.content is null at times, probably because the
- * widget itself has been disposed.
- */
- if (isDisposed()) return;
- if (autoScrollDirection == SWT.UP) {
- if (blockSelection) {
- int verticalScrollOffset = getVerticalScrollOffset();
- int y = blockYLocation - verticalScrollOffset;
- int pixels = Math.max(-autoScrollDistance, -verticalScrollOffset);
- if (pixels != 0) {
- setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true);
- scrollVertical(pixels, true);
- }
- } else {
- doSelectionPageUp(autoScrollDistance);
- }
- display.timerExec(V_SCROLL_RATE, this);
- }
- }
- };
- autoScrollDirection = direction;
- display.timerExec(V_SCROLL_RATE, timer);
- } else if (direction == SWT.DOWN) {
- timer = new Runnable() {
- @Override
- public void run() {
- /* Bug 437357 - NPE in StyledText.getCaretLine
- * StyledText.content is null at times, probably because the
- * widget itself has been disposed.
- */
- if (isDisposed()) return;
- if (autoScrollDirection == SWT.DOWN) {
- if (blockSelection) {
- int verticalScrollOffset = getVerticalScrollOffset();
- int y = blockYLocation - verticalScrollOffset;
- int max = renderer.getHeight() - verticalScrollOffset - clientAreaHeight;
- int pixels = Math.min(autoScrollDistance, Math.max(0,max));
- if (pixels != 0) {
- setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true);
- scrollVertical(pixels, true);
- }
- } else {
- doSelectionPageDown(autoScrollDistance);
- }
- display.timerExec(V_SCROLL_RATE, this);
- }
- }
- };
- autoScrollDirection = direction;
- display.timerExec(V_SCROLL_RATE, timer);
- } else if (direction == ST.COLUMN_NEXT) {
- timer = new Runnable() {
- @Override
- public void run() {
- /* Bug 437357 - NPE in StyledText.getCaretLine
- * StyledText.content is null at times, probably because the
- * widget itself has been disposed.
- */
- if (isDisposed()) return;
- if (autoScrollDirection == ST.COLUMN_NEXT) {
- if (blockSelection) {
- int x = blockXLocation - horizontalScrollOffset;
- int max = renderer.getWidth() - horizontalScrollOffset - clientAreaWidth;
- int pixels = Math.min(autoScrollDistance, Math.max(0,max));
- if (pixels != 0) {
- setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true);
- scrollHorizontal(pixels, true);
- }
- } else {
- doVisualNext();
- setMouseWordSelectionAnchor();
- doMouseSelection();
- }
- display.timerExec(H_SCROLL_RATE, this);
- }
- }
- };
- autoScrollDirection = direction;
- display.timerExec(H_SCROLL_RATE, timer);
- } else if (direction == ST.COLUMN_PREVIOUS) {
- timer = new Runnable() {
- @Override
- public void run() {
- /* Bug 437357 - NPE in StyledText.getCaretLine
- * StyledText.content is null at times, probably because the
- * widget itself has been disposed.
- */
- if (isDisposed()) return;
- if (autoScrollDirection == ST.COLUMN_PREVIOUS) {
- if (blockSelection) {
- int x = blockXLocation - horizontalScrollOffset;
- int pixels = Math.max(-autoScrollDistance, -horizontalScrollOffset);
- if (pixels != 0) {
- setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true);
- scrollHorizontal(pixels, true);
- }
- } else {
- doVisualPrevious();
- setMouseWordSelectionAnchor();
- doMouseSelection();
- }
- display.timerExec(H_SCROLL_RATE, this);
- }
- }
- };
- autoScrollDirection = direction;
- display.timerExec(H_SCROLL_RATE, timer);
- }
-}
-/**
- * Deletes the previous character. Delete the selected text if any.
- * Move the caret in front of the deleted text.
- */
-void doBackspace() {
- Event event = new Event();
- event.text = "";
- if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { // at least one range to delete
- for (int i = selection.length - 1; i >= 0; i--) { // from bottom to top to avoid moving ranges
- Point sel = selection[i];
- event.start = sel.x;
- event.end = sel.y;
- sendKeyEvent(event);
- }
- } else {
- for (int i = caretOffsets.length - 1; i >= 0; i--) { // reverse loop, process from bottom to top
- int caretOffset = caretOffsets[i];
- if (caretOffset > 0) {
- int lineIndex = content.getLineAtOffset(caretOffset);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- if (caretOffset == lineOffset) {
- lineOffset = content.getOffsetAtLine(lineIndex - 1);
- event.start = lineOffset + content.getLine(lineIndex - 1).length();
- event.end = caretOffset;
- } else {
- boolean isSurrogate = false;
- String lineText = content.getLine(lineIndex);
- char ch = lineText.charAt(caretOffset - lineOffset - 1);
- if (0xDC00 <= ch && ch <= 0xDFFF) {
- if (caretOffset - lineOffset - 2 >= 0) {
- ch = lineText.charAt(caretOffset - lineOffset - 2);
- isSurrogate = 0xD800 <= ch && ch <= 0xDBFF;
- }
- }
- TextLayout layout = renderer.getTextLayout(lineIndex);
- int start = layout.getPreviousOffset(caretOffset - lineOffset, isSurrogate ? SWT.MOVEMENT_CLUSTER : SWT.MOVEMENT_CHAR);
- renderer.disposeTextLayout(layout);
- event.start = start + lineOffset;
- event.end = caretOffset;
- }
- sendKeyEvent(event);
- }
- }
- }
-}
-void doBlockColumn(boolean next) {
- if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false);
- int x = blockXLocation - horizontalScrollOffset;
- int y = blockYLocation - getVerticalScrollOffset();
- int[] trailing = new int[1];
- int offset = getOffsetAtPoint(x, y, trailing, true);
- if (offset != -1) {
- offset += trailing[0];
- int lineIndex = content.getLineAtOffset(offset);
- int newOffset;
- if (next) {
- newOffset = getClusterNext(offset, lineIndex);
- } else {
- newOffset = getClusterPrevious(offset, lineIndex);
- }
- offset = newOffset != offset ? newOffset : -1;
- }
- if (offset != -1) {
- setBlockSelectionOffset(offset, true);
- showCaret();
- } else {
- int width = next ? renderer.averageCharWidth : -renderer.averageCharWidth;
- int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
- x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset;
- setBlockSelectionLocation(x, y, true);
- Rectangle rect = new Rectangle(x, y, 0, 0);
- showLocation(rect, true);
- }
-}
-void doBlockContentStartEnd(boolean end) {
- if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false);
- int offset = end ? content.getCharCount() : 0;
- setBlockSelectionOffset(offset, true);
- showCaret();
-}
-void doBlockWord(boolean next) {
- if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false);
- int x = blockXLocation - horizontalScrollOffset;
- int y = blockYLocation - getVerticalScrollOffset();
- int[] trailing = new int[1];
- int offset = getOffsetAtPoint(x, y, trailing, true);
- if (offset != -1) {
- offset += trailing[0];
- int lineIndex = content.getLineAtOffset(offset);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- String lineText = content.getLine(lineIndex);
- int lineLength = lineText.length();
- int newOffset = offset;
- if (next) {
- if (offset < lineOffset + lineLength) {
- newOffset = getWordNext(offset, SWT.MOVEMENT_WORD);
- }
- } else {
- if (offset > lineOffset) {
- newOffset = getWordPrevious(offset, SWT.MOVEMENT_WORD);
- }
- }
- offset = newOffset != offset ? newOffset : -1;
- }
- if (offset != -1) {
- setBlockSelectionOffset(offset, true);
- showCaret();
- } else {
- int width = (next ? renderer.averageCharWidth : -renderer.averageCharWidth) * 6;
- int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
- x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset;
- setBlockSelectionLocation(x, y, true);
- Rectangle rect = new Rectangle(x, y, 0, 0);
- showLocation(rect, true);
- }
-}
-void doBlockLineVertical(boolean up) {
- if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false);
- int y = blockYLocation - getVerticalScrollOffset();
- int lineIndex = getLineIndex(y);
- if (up) {
- if (lineIndex > 0) {
- y = getLinePixel(lineIndex - 1);
- setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true);
- if (y < topMargin) {
- scrollVertical(y - topMargin, true);
- }
- }
- } else {
- int lineCount = content.getLineCount();
- if (lineIndex + 1 < lineCount) {
- y = getLinePixel(lineIndex + 2) - 1;
- setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true);
- int bottom = clientAreaHeight - bottomMargin;
- if (y > bottom) {
- scrollVertical(y - bottom, true);
- }
- }
- }
-}
-void doBlockLineHorizontal(boolean end) {
- if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false);
- int x = blockXLocation - horizontalScrollOffset;
- int y = blockYLocation - getVerticalScrollOffset();
- int lineIndex = getLineIndex(y);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- String lineText = content.getLine(lineIndex);
- int lineLength = lineText.length();
- int[] trailing = new int[1];
- int offset = getOffsetAtPoint(x, y, trailing, true);
- if (offset != -1) {
- offset += trailing[0];
- int newOffset = offset;
- if (end) {
- if (offset < lineOffset + lineLength) {
- newOffset = lineOffset + lineLength;
- }
- } else {
- if (offset > lineOffset) {
- newOffset = lineOffset;
- }
- }
- offset = newOffset != offset ? newOffset : -1;
- } else {
- if (!end) offset = lineOffset + lineLength;
- }
- if (offset != -1) {
- setBlockSelectionOffset(offset, true);
- showCaret();
- } else {
- int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
- x = (end ? maxWidth : 0) - horizontalScrollOffset;
- setBlockSelectionLocation(x, y, true);
- Rectangle rect = new Rectangle(x, y, 0, 0);
- showLocation(rect, true);
- }
-}
-void doBlockSelection(boolean sendEvent) {
- if (caretOffsets[0] > selectionAnchors[0]) {
- selection[0].x = selectionAnchors[0];
- selection[0].y = caretOffsets[0];
- } else {
- selection[0].x = caretOffsets[0];
- selection[0].y = selectionAnchors[0];
- }
- updateCaretVisibility();
- setCaretLocations();
- super.redraw();
- if (sendEvent) {
- sendSelectionEvent();
- }
- sendAccessibleTextCaretMoved();
-}
-/**
- * Replaces the selection with the character or insert the character at the
- * current caret position if no selection exists.
- *
- * If a carriage return was typed replace it with the line break character
- * used by the widget on this platform.
- *
- *
- * @param key the character typed by the user
- */
-void doContent(final char key) {
- if (blockSelection && blockXLocation != -1) {
- insertBlockSelectionText(key, SWT.NULL);
- return;
- }
-
- for (int i = selection.length - 1; i >= 0; i--) {
- Point sel = selection[i];
- Event event = new Event();
- event.start = sel.x;
- event.end = sel.y;
- // replace a CR line break with the widget line break
- // CR does not make sense on Windows since most (all?) applications
- // don't recognize CR as a line break.
- if (key == SWT.CR || key == SWT.LF) {
- if (!isSingleLine()) {
- event.text = getLineDelimiter();
- }
- } else if (sel.x == sel.y && overwrite && key != TAB) {
- // no selection and overwrite mode is on and the typed key is not a
- // tab character (tabs are always inserted without overwriting)?
- int lineIndex = content.getLineAtOffset(event.end);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- String line = content.getLine(lineIndex);
- // replace character at caret offset if the caret is not at the
- // end of the line
- if (event.end < lineOffset + line.length()) {
- event.end++;
- }
- event.text = new String(new char[] {key});
- } else {
- event.text = new String(new char[] {key});
- }
- if (event.text != null) {
- if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) {
- return;
- }
- sendKeyEvent(event);
- }
- }
-}
-/**
- * Moves the caret after the last character of the widget content.
- */
-void doContentEnd() {
- // place caret at end of first line if receiver is in single
- // line mode. fixes 4820.
- if (isSingleLine()) {
- doLineEnd();
- } else {
- int length = content.getCharCount();
- setCaretOffsets(new int[] {length}, SWT.DEFAULT);
- showCaret();
- }
-}
-/**
- * Moves the caret in front of the first character of the widget content.
- */
-void doContentStart() {
- setCaretOffsets(new int[] {0}, SWT.DEFAULT);
- showCaret();
-}
-/**
- * Moves the caret to the start of the selection if a selection exists.
- * Otherwise, if no selection exists move the cursor according to the
- * cursor selection rules.
- *
- * @see #doSelectionCursorPrevious
- */
-void doCursorPrevious() {
- if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) {
- setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.x).toArray(), OFFSET_LEADING);
- showCaret();
- } else {
- doSelectionCursorPrevious();
- }
-}
-/**
- * Moves the caret to the end of the selection if a selection exists.
- * Otherwise, if no selection exists move the cursor according to the
- * cursor selection rules.
- *
- * @see #doSelectionCursorNext
- */
-void doCursorNext() {
- if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) {
- setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.y).toArray(), PREVIOUS_OFFSET_TRAILING);
- showCaret();
- } else {
- doSelectionCursorNext();
- }
-}
-/**
- * Deletes the next character. Delete the selected text if any.
- */
-void doDelete() {
- Event event = new Event();
- event.text = "";
- if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) {
- for (Point sel : selection) {
- event.start = sel.x;
- event.end = sel.y;
- sendKeyEvent(event);
- }
- } else {
- for (int i = caretOffsets.length - 1; i >= 0; i--) {
- int caretOffset = caretOffsets[i];
- if (caretOffset < content.getCharCount()) {
- int line = content.getLineAtOffset(caretOffset);
- int lineOffset = content.getOffsetAtLine(line);
- int lineLength = content.getLine(line).length();
- if (caretOffset == lineOffset + lineLength) {
- event.start = caretOffset;
- event.end = content.getOffsetAtLine(line + 1);
- } else {
- event.start = caretOffset;
- event.end = getClusterNext(caretOffset, line);
- }
- sendKeyEvent(event);
- }
- }
- }
-}
-/**
- * Deletes the next word.
- */
-void doDeleteWordNext() {
- if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) {
- // if a selection exists, treat the as if
- // only the delete key was pressed
- doDelete();
- } else {
- for (int i = caretOffsets.length - 1; i >= 0; i--) {
- int caretOffset = caretOffsets[i];
- Event event = new Event();
- event.text = "";
- event.start = caretOffset;
- event.end = getWordNext(caretOffset, SWT.MOVEMENT_WORD);
- sendKeyEvent(event);
- }
- }
-}
-/**
- * Deletes the previous word.
- */
-void doDeleteWordPrevious() {
- if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) {
- // if a selection exists, treat as if
- // only the backspace key was pressed
- doBackspace();
- } else {
- for (int i = caretOffsets.length - 1; i >= 0; i--) {
- int caretOffset = caretOffsets[i];
- Event event = new Event();
- event.text = "";
- event.start = getWordPrevious(caretOffset, SWT.MOVEMENT_WORD);
- event.end = caretOffset;
- sendKeyEvent(event);
- }
- }
-}
-/**
- * Moves the caret one line down and to the same character offset relative
- * to the beginning of the line. Move the caret to the end of the new line
- * if the new line is shorter than the character offset. Moves the caret to
- * the end of the text if the caret already is on the last line.
- */
-void doLineDown(boolean select) {
- int[] newCaretOffsets = new int[caretOffsets.length];
- int lineCount = content.getLineCount();
- int[] alignment = new int[1];
- for (int i = 0; i < caretOffsets.length; i++) {
- int caretOffset = caretOffsets[i];
- int caretLine = content.getLineAtOffset(caretOffset);
- int x = caretOffsets.length == 1 ? columnX : getPointAtOffset(caretOffset).x;
- int y = 0;
- boolean lastLine = false;
- if (isWordWrap()) {
- int lineOffset = content.getOffsetAtLine(caretLine);
- int offsetInLine = caretOffset - lineOffset;
- TextLayout layout = renderer.getTextLayout(caretLine);
- int lineIndex = getVisualLineIndex(layout, offsetInLine);
- int layoutLineCount = layout.getLineCount();
- if (lineIndex == layoutLineCount - 1) {
- lastLine = caretLine == lineCount - 1;
- caretLine++;
- } else {
- y = layout.getLineBounds(lineIndex + 1).y;
- y++; // bug 485722: workaround for fractional line heights
- }
- renderer.disposeTextLayout(layout);
- } else {
- lastLine = caretLine == lineCount - 1;
- caretLine++;
- }
- if (lastLine) {
- newCaretOffsets[i] = content.getCharCount();
- } else {
- newCaretOffsets[i] = getOffsetAtPoint(x, y, caretLine, alignment);
- }
- }
- boolean hitLastLine = content.getLineAtOffset(newCaretOffsets[newCaretOffsets.length - 1]) == lineCount - 1;
- setCaretOffsets(newCaretOffsets, hitLastLine ? SWT.DEFAULT : alignment[0]);
- int oldColumnX = columnX;
- int oldHScrollOffset = horizontalScrollOffset;
- if (select) {
- setMouseWordSelectionAnchor();
- // select first and then scroll to reduce flash when key
- // repeat scrolls lots of lines
- doSelection(ST.COLUMN_NEXT);
- }
- showCaret();
- int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
- columnX = oldColumnX + hScrollChange;
-}
-/**
- * Moves the caret to the end of the line.
- */
-void doLineEnd() {
- int[] newOffsets = new int[caretOffsets.length];
- for (int i = 0; i < caretOffsets.length; i++) {
- int caretOffset = caretOffsets[i];
- int caretLine = content.getLineAtOffset(caretOffset);
- int lineOffset = content.getOffsetAtLine(caretLine);
- int lineEndOffset;
- if (isWordWrap()) {
- TextLayout layout = renderer.getTextLayout(caretLine);
- int offsetInLine = caretOffset - lineOffset;
- int lineIndex = getVisualLineIndex(layout, offsetInLine);
- int[] offsets = layout.getLineOffsets();
- lineEndOffset = lineOffset + offsets[lineIndex + 1];
- renderer.disposeTextLayout(layout);
- } else {
- int lineLength = content.getLine(caretLine).length();
- lineEndOffset = lineOffset + lineLength;
- }
- newOffsets[i] = lineEndOffset;
- }
- setCaretOffsets(newOffsets, PREVIOUS_OFFSET_TRAILING);
- showCaret();
-}
-/**
- * Moves the caret to the beginning of the line.
- */
-void doLineStart() {
- int[] newCaretOffsets = new int[caretOffsets.length];
- for (int i = 0; i < caretOffsets.length; i++) {
- int caretOffset = caretOffsets[i];
- int caretLine = content.getLineAtOffset(caretOffset);
- int lineOffset = content.getOffsetAtLine(caretLine);
- if (isWordWrap()) {
- TextLayout layout = renderer.getTextLayout(caretLine);
- int offsetInLine = caretOffset - lineOffset;
- int lineIndex = getVisualLineIndex(layout, offsetInLine);
- int[] offsets = layout.getLineOffsets();
- lineOffset += offsets[lineIndex];
- renderer.disposeTextLayout(layout);
- }
- newCaretOffsets[i] = lineOffset;
- }
- setCaretOffsets(newCaretOffsets, OFFSET_LEADING);
- showCaret();
-}
-/**
- * Moves the caret one line up and to the same character offset relative
- * to the beginning of the line. Move the caret to the end of the new line
- * if the new line is shorter than the character offset. Moves the caret to
- * the beginning of the document if it is already on the first line.
- */
-void doLineUp(boolean select) {
- int[] newCaretOffsets = new int[caretOffsets.length];
- int[] alignment = new int[1];
- for (int i = 0; i < caretOffsets.length; i++) {
- int caretOffset = caretOffsets[i];
- int caretLine = content.getLineAtOffset(caretOffset);
- int x = caretOffsets.length == 1 ? columnX : getPointAtOffset(caretOffset).x;
- int y = 0;
- boolean firstLine = false;
- if (isWordWrap()) {
- int lineOffset = content.getOffsetAtLine(caretLine);
- int offsetInLine = caretOffset - lineOffset;
- TextLayout layout = renderer.getTextLayout(caretLine);
- int lineIndex = getVisualLineIndex(layout, offsetInLine);
- if (lineIndex == 0) {
- firstLine = caretLine == 0;
- if (!firstLine) {
- caretLine--;
- y = renderer.getLineHeight(caretLine) - 1;
- y--; // bug 485722: workaround for fractional line heights
- }
- } else {
- y = layout.getLineBounds(lineIndex - 1).y;
- y++; // bug 485722: workaround for fractional line heights
- }
- renderer.disposeTextLayout(layout);
- } else {
- firstLine = caretLine == 0;
- caretLine--;
- }
- if (firstLine) {
- newCaretOffsets[i] = 0;
- } else {
- newCaretOffsets[i] = getOffsetAtPoint(x, y, caretLine, alignment);
- }
- }
- setCaretOffsets(newCaretOffsets, newCaretOffsets[0] == 0 ? SWT.DEFAULT : alignment[0]);
- int oldColumnX = columnX;
- int oldHScrollOffset = horizontalScrollOffset;
- if (select) setMouseWordSelectionAnchor();
- showCaret();
- if (select) doSelection(ST.COLUMN_PREVIOUS);
- int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
- columnX = oldColumnX + hScrollChange;
-}
-void doMouseLinkCursor() {
- Display display = getDisplay();
- Point point = display.getCursorLocation();
- point = display.map(null, this, point);
- doMouseLinkCursor(point.x, point.y);
-}
-void doMouseLinkCursor(int x, int y) {
- int offset = getOffsetAtPoint(x, y, null, true);
- Display display = getDisplay();
- Cursor newCursor = cursor;
- if (renderer.hasLink(offset)) {
- newCursor = display.getSystemCursor(SWT.CURSOR_HAND);
- } else {
- if (cursor == null) {
- int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM;
- newCursor = display.getSystemCursor(type);
- }
- }
- if (newCursor != getCursor()) super.setCursor(newCursor);
-}
-/**
- * Moves the caret to the specified location.
- *
- * @param x x location of the new caret position
- * @param y y location of the new caret position
- * @param select the location change is a selection operation.
- * include the line delimiter in the selection
- */
-void doMouseLocationChange(int x, int y, boolean select) {
- int line = getLineIndex(y);
-
- updateCaretDirection = true;
-
- if (blockSelection) {
- x = Math.max(leftMargin, Math.min(x, clientAreaWidth - rightMargin));
- y = Math.max(topMargin, Math.min(y, clientAreaHeight - bottomMargin));
- if (doubleClickEnabled && clickCount > 1) {
- boolean wordSelect = (clickCount & 1) == 0;
- if (wordSelect) {
- Point left = getPointAtOffset(doubleClickSelection.x);
- int[] trailing = new int[1];
- int offset = getOffsetAtPoint(x, y, trailing, true);
- if (offset != -1) {
- if (x > left.x) {
- offset = getWordNext(offset + trailing[0], SWT.MOVEMENT_WORD_END);
- setBlockSelectionOffset(doubleClickSelection.x, offset, true);
- } else {
- offset = getWordPrevious(offset + trailing[0], SWT.MOVEMENT_WORD_START);
- setBlockSelectionOffset(doubleClickSelection.y, offset, true);
- }
- } else {
- if (x > left.x) {
- setBlockSelectionLocation(left.x, left.y, x, y, true);
- } else {
- Point right = getPointAtOffset(doubleClickSelection.y);
- setBlockSelectionLocation(right.x, right.y, x, y, true);
- }
- }
- } else {
- setBlockSelectionLocation(blockXLocation, y, true);
- }
- return;
- } else {
- if (select) {
- if (blockXLocation == -1) {
- setBlockSelectionOffset(caretOffsets[0], false);
- }
- } else {
- clearBlockSelection(true, false);
- }
- int[] trailing = new int[1];
- int offset = getOffsetAtPoint(x, y, trailing, true);
- if (offset != -1) {
- if (select) {
- setBlockSelectionOffset(offset + trailing[0], true);
- return;
- }
- } else {
- if (isFixedLineHeight() && renderer.fixedPitch) {
- int avg = renderer.averageCharWidth;
- x = ((x + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
- }
- setBlockSelectionLocation(x, y, true);
- return;
- }
- }
- }
-
- // allow caret to be placed below first line only if receiver is
- // not in single line mode. fixes 4820.
- if (line < 0 || (isSingleLine() && line > 0)) {
- return;
- }
- int[] alignment = new int[1];
- int newCaretOffset = getOffsetAtPoint(x, y, alignment);
- int newCaretAlignemnt = alignment[0];
-
- if (doubleClickEnabled && clickCount > 1) {
- newCaretOffset = doMouseWordSelect(x, newCaretOffset, line);
- }
-
- int newCaretLine = content.getLineAtOffset(newCaretOffset);
-
- // Is the mouse within the left client area border or on
- // a different line? If not the autoscroll selection
- // could be incorrectly reset. Fixes 1GKM3XS
- boolean vchange = 0 <= y && y < clientAreaHeight || newCaretLine == 0 || newCaretLine == content.getLineCount() - 1;
- boolean hchange = 0 <= x && x < clientAreaWidth || wordWrap || newCaretLine != content.getLineAtOffset(caretOffsets[0]);
- if (vchange && hchange && (newCaretOffset != caretOffsets[0] || newCaretAlignemnt != caretAlignment)) {
- setCaretOffsets(new int[] {newCaretOffset}, newCaretAlignemnt);
- if (select) doMouseSelection();
- showCaret();
- }
- if (!select) {
- setCaretOffsets(new int[] {newCaretOffset}, newCaretAlignemnt);
- clearSelection(true);
- }
-}
-/**
- * Updates the selection based on the caret position
- */
-void doMouseSelection() {
- if (caretOffsets[0] <= selection[0].x ||
- (caretOffsets[0] > selection[0].x &&
- caretOffsets[0] < selection[0].y && selectionAnchors[0] == selection[0].x)) {
- doSelection(ST.COLUMN_PREVIOUS);
- } else {
- doSelection(ST.COLUMN_NEXT);
- }
-}
-/**
- * Returns the offset of the word at the specified offset.
- * If the current selection extends from high index to low index
- * (i.e., right to left, or caret is at left border of selection on
- * non-bidi platforms) the start offset of the word preceding the
- * selection is returned. If the current selection extends from
- * low index to high index the end offset of the word following
- * the selection is returned.
- *
- * @param x mouse x location
- * @param newCaretOffset caret offset of the mouse cursor location
- * @param line line index of the mouse cursor location
- */
-int doMouseWordSelect(int x, int newCaretOffset, int line) {
- // flip selection anchor based on word selection direction from
- // base double click. Always do this here (and don't rely on doAutoScroll)
- // because auto scroll only does not cover all possible mouse selections
- // (e.g., mouse x < 0 && mouse y > caret line y)
- if (newCaretOffset < selectionAnchors[0] && selectionAnchors[0] == selection[0].x) {
- selectionAnchors[0] = doubleClickSelection.y;
- } else if (newCaretOffset > selectionAnchors[0] && selectionAnchors[0] == selection[0].y) {
- selectionAnchors[0] = doubleClickSelection.x;
- }
- if (0 <= x && x < clientAreaWidth) {
- boolean wordSelect = (clickCount & 1) == 0;
- if (caretOffsets[0] == selection[0].x) {
- if (wordSelect) {
- newCaretOffset = getWordPrevious(newCaretOffset, SWT.MOVEMENT_WORD_START);
- } else {
- newCaretOffset = content.getOffsetAtLine(line);
- }
- } else {
- if (wordSelect) {
- newCaretOffset = getWordNext(newCaretOffset, SWT.MOVEMENT_WORD_END);
- } else {
- int lineEnd = content.getCharCount();
- if (line + 1 < content.getLineCount()) {
- lineEnd = content.getOffsetAtLine(line + 1);
- }
- newCaretOffset = lineEnd;
- }
- }
- }
- return newCaretOffset;
-}
-/**
- * Scrolls one page down so that the last line (truncated or whole)
- * of the current page becomes the fully visible top line.
- *
- * The caret is scrolled the same number of lines so that its location
- * relative to the top line remains the same. The exception is the end
- * of the text where a full page scroll is not possible. In this case
- * the caret is moved after the last character.
- *
- *
- * @param select whether or not to select the page
- */
-void doPageDown(boolean select, int height) {
- if (isSingleLine()) return;
- int oldColumnX = columnX;
- int oldHScrollOffset = horizontalScrollOffset;
- if (isFixedLineHeight()) {
- int lineCount = content.getLineCount();
- int caretLine = getFirstCaretLine();
- if (caretLine < lineCount - 1) {
- int lineHeight = renderer.getLineHeight();
- int lines = (height == -1 ? clientAreaHeight : height) / lineHeight;
- int scrollLines = Math.min(lineCount - caretLine - 1, lines);
- // ensure that scrollLines never gets negative and at least one
- // line is scrolled. fixes bug 5602.
- scrollLines = Math.max(1, scrollLines);
- int[] alignment = new int[1];
- int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines), alignment);
- setCaretOffsets(new int[] {offset}, alignment[0]);
- if (select) {
- doSelection(ST.COLUMN_NEXT);
- }
- // scroll one page down or to the bottom
- int verticalMaximum = lineCount * getVerticalIncrement();
- int pageSize = clientAreaHeight;
- int verticalScrollOffset = getVerticalScrollOffset();
- int scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement();
- if (scrollOffset + pageSize > verticalMaximum) {
- scrollOffset = verticalMaximum - pageSize;
- }
- if (scrollOffset > verticalScrollOffset) {
- scrollVertical(scrollOffset - verticalScrollOffset, true);
- }
- }
- } else {
- int lineCount = content.getLineCount();
- int lineIndex, lineHeight;
- if (height == -1) {
- lineIndex = getPartialBottomIndex();
- int topY = getLinePixel(lineIndex);
- lineHeight = renderer.getLineHeight(lineIndex);
- height = topY;
- if (topY + lineHeight <= clientAreaHeight) {
- height += lineHeight;
- } else {
- if (isWordWrap()) {
- TextLayout layout = renderer.getTextLayout(lineIndex);
- int y = clientAreaHeight - topY;
- for (int i = 0; i < layout.getLineCount(); i++) {
- Rectangle bounds = layout.getLineBounds(i);
- if (bounds.contains(bounds.x, y)) {
- height += bounds.y;
- break;
- }
- }
- renderer.disposeTextLayout(layout);
- }
- }
- } else {
- lineIndex = getLineIndex(height);
- int topLineY = getLinePixel(lineIndex);
- if (isWordWrap()) {
- TextLayout layout = renderer.getTextLayout(lineIndex);
- int y = height - topLineY;
- for (int i = 0; i < layout.getLineCount(); i++) {
- Rectangle bounds = layout.getLineBounds(i);
- if (bounds.contains(bounds.x, y)) {
- height = topLineY + bounds.y + bounds.height;
- break;
- }
- }
- renderer.disposeTextLayout(layout);
- } else {
- height = topLineY + renderer.getLineHeight(lineIndex);
- }
- }
- int caretHeight = height;
- if (isWordWrap()) {
- for (int caretOffset : caretOffsets) {
- int caretLine = content.getLineAtOffset(caretOffset);
- TextLayout layout = renderer.getTextLayout(caretLine);
- int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine);
- lineIndex = getVisualLineIndex(layout, offsetInLine);
- caretHeight += layout.getLineBounds(lineIndex).y;
- renderer.disposeTextLayout(layout);
- }
- }
- lineIndex = getFirstCaretLine();
- lineHeight = renderer.getLineHeight(lineIndex);
- while (caretHeight - lineHeight >= 0 && lineIndex < lineCount - 1) {
- caretHeight -= lineHeight;
- lineHeight = renderer.getLineHeight(++lineIndex);
- }
- int[] alignment = new int[1];
- int offset = getOffsetAtPoint(columnX, caretHeight, lineIndex, alignment);
- setCaretOffsets(new int[] {offset}, alignment[0]);
- if (select) doSelection(ST.COLUMN_NEXT);
- height = getAvailableHeightBellow(height);
- scrollVertical(height, true);
- if (height == 0) setCaretLocations();
- }
- showCaret();
- int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
- columnX = oldColumnX + hScrollChange;
-}
-/**
- * Moves the cursor to the end of the last fully visible line.
- */
-void doPageEnd() {
- // go to end of line if in single line mode. fixes 5673
- if (isSingleLine()) {
- doLineEnd();
- } else if (caretOffsets.length == 1) { // pageEnd doesn't make sense with multi-carets
- int bottomOffset;
- if (isWordWrap()) {
- int lineIndex = getPartialBottomIndex();
- TextLayout layout = renderer.getTextLayout(lineIndex);
- int y = (clientAreaHeight - bottomMargin) - getLinePixel(lineIndex);
- int index = layout.getLineCount() - 1;
- while (index >= 0) {
- Rectangle bounds = layout.getLineBounds(index);
- if (y >= bounds.y + bounds.height) break;
- index--;
- }
- if (index == -1 && lineIndex > 0) {
- bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length();
- } else {
- bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1);
- }
- renderer.disposeTextLayout(layout);
- } else {
- int lineIndex = getBottomIndex();
- bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length();
- }
- if (caretOffsets[0] < bottomOffset) {
- setCaretOffsets(new int[] {bottomOffset}, OFFSET_LEADING);
- showCaret();
- }
- }
-}
-/**
- * Moves the cursor to the beginning of the first fully visible line.
- */
-void doPageStart() {
- int topOffset;
- if (isWordWrap()) {
- int y, lineIndex;
- if (topIndexY > 0) {
- lineIndex = topIndex - 1;
- y = renderer.getLineHeight(lineIndex) - topIndexY;
- } else {
- lineIndex = topIndex;
- y = -topIndexY;
- }
- TextLayout layout = renderer.getTextLayout(lineIndex);
- int index = 0;
- int lineCount = layout.getLineCount();
- while (index < lineCount) {
- Rectangle bounds = layout.getLineBounds(index);
- if (y <= bounds.y) break;
- index++;
- }
- if (index == lineCount) {
- topOffset = content.getOffsetAtLine(lineIndex + 1);
- } else {
- topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index];
- }
- renderer.disposeTextLayout(layout);
- } else {
- topOffset = content.getOffsetAtLine(topIndex);
- }
- if (caretOffsets[0] > topOffset) {
- setCaretOffsets(new int[] {topOffset}, OFFSET_LEADING);
- showCaret();
- }
-}
-/**
- * Scrolls one page up so that the first line (truncated or whole)
- * of the current page becomes the fully visible last line.
- * The caret is scrolled the same number of lines so that its location
- * relative to the top line remains the same. The exception is the beginning
- * of the text where a full page scroll is not possible. In this case the
- * caret is moved in front of the first character.
- */
-void doPageUp(boolean select, int height) {
- if (isSingleLine()) return;
- int oldHScrollOffset = horizontalScrollOffset;
- int oldColumnX = columnX;
- if (isFixedLineHeight()) {
- int caretLine = getFirstCaretLine();
- if (caretLine > 0) {
- int lineHeight = renderer.getLineHeight();
- int lines = (height == -1 ? clientAreaHeight : height) / lineHeight;
- int scrollLines = Math.max(1, Math.min(caretLine, lines));
- caretLine -= scrollLines;
- int[] alignment = new int[1];
- int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine), alignment);
- setCaretOffsets(new int[] {offset}, alignment[0]);
- if (select) {
- doSelection(ST.COLUMN_PREVIOUS);
- }
- int verticalScrollOffset = getVerticalScrollOffset();
- int scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement());
- if (scrollOffset < verticalScrollOffset) {
- scrollVertical(scrollOffset - verticalScrollOffset, true);
- }
- }
- } else {
- int lineHeight, lineIndex;
- if (height == -1) {
- if (topIndexY == 0) {
- height = clientAreaHeight;
- } else {
- int y;
- if (topIndex > 0) {
- lineIndex = topIndex - 1;
- lineHeight = renderer.getLineHeight(lineIndex);
- height = clientAreaHeight - topIndexY;
- y = lineHeight - topIndexY;
- } else {
- lineIndex = topIndex;
- lineHeight = renderer.getLineHeight(lineIndex);
- height = clientAreaHeight - (lineHeight + topIndexY);
- y = -topIndexY;
- }
- if (isWordWrap()) {
- TextLayout layout = renderer.getTextLayout(lineIndex);
- for (int i = 0; i < layout.getLineCount(); i++) {
- Rectangle bounds = layout.getLineBounds(i);
- if (bounds.contains(bounds.x, y)) {
- height += lineHeight - (bounds.y + bounds.height);
- break;
- }
- }
- renderer.disposeTextLayout(layout);
- }
- }
- } else {
- lineIndex = getLineIndex(clientAreaHeight - height);
- int topLineY = getLinePixel(lineIndex);
- if (isWordWrap()) {
- TextLayout layout = renderer.getTextLayout(lineIndex);
- int y = topLineY;
- for (int i = 0; i < layout.getLineCount(); i++) {
- Rectangle bounds = layout.getLineBounds(i);
- if (bounds.contains(bounds.x, y)) {
- height = clientAreaHeight - (topLineY + bounds.y);
- break;
- }
- }
- renderer.disposeTextLayout(layout);
- } else {
- height = clientAreaHeight - topLineY;
- }
- }
- int caretHeight = height;
- if (isWordWrap()) {
- for (int caretOffset : caretOffsets) {
- int caretLine = content.getLineAtOffset(caretOffset);
- TextLayout layout = renderer.getTextLayout(caretLine);
- int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine);
- lineIndex = getVisualLineIndex(layout, offsetInLine);
- caretHeight += layout.getBounds().height - layout.getLineBounds(lineIndex).y;
- renderer.disposeTextLayout(layout);
- }
- }
- lineIndex = getFirstCaretLine();
- lineHeight = renderer.getLineHeight(lineIndex);
- while (caretHeight - lineHeight >= 0 && lineIndex > 0) {
- caretHeight -= lineHeight;
- lineHeight = renderer.getLineHeight(--lineIndex);
- }
- lineHeight = renderer.getLineHeight(lineIndex);
- int[] alignment = new int[1];
- int offset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex, alignment);
- setCaretOffsets(new int[] {offset}, alignment[0]);
- if (select) doSelection(ST.COLUMN_PREVIOUS);
- height = getAvailableHeightAbove(height);
- scrollVertical(-height, true);
- if (height == 0) setCaretLocations();
- }
- showCaret();
- int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
- columnX = oldColumnX + hScrollChange;
-}
-/**
- * Updates the selection to extend to the current caret position.
- */
-void doSelection(int direction) {
- if (caretOffsets.length != selection.length) {
- return;
- }
- if (selectionAnchors.length != selection.length) {
- selectionAnchors = new int[selection.length];
- Arrays.fill(selectionAnchors, -1);
- }
- boolean selectionChanged = false;
- Point[] newSelection = Arrays.stream(selection).map(p -> new Point(p.x, p.y)).toArray(Point[]::new);
- boolean[] caretAtBeginning = new boolean[newSelection.length];
- for (int i = 0; i < caretOffsets.length; i++) {
- int caretOffset = caretOffsets[i];
- Point currentSelection = newSelection[i];
- int selectionAnchor = selectionAnchors[i];
- if (selectionAnchor == -1) {
- selectionAnchor = selectionAnchors[i] = currentSelection.x;
- }
- int redrawStart = -1;
- int redrawEnd = -1;
- if (direction == ST.COLUMN_PREVIOUS) {
- if (caretOffset < currentSelection.x) {
- caretAtBeginning[i] = true;
- // grow selection
- redrawEnd = currentSelection.x;
- redrawStart = currentSelection.x = caretOffset;
- // check if selection has reversed direction
- if (currentSelection.y != selectionAnchor) {
- redrawEnd = currentSelection.y;
- currentSelection.y = selectionAnchor;
- }
- // test whether selection actually changed. Fixes 1G71EO1
- } else if (selectionAnchor == currentSelection.x && caretOffset < currentSelection.y) {
- // caret moved towards selection anchor (left side of selection).
- // shrink selection
- redrawEnd = currentSelection.y;
- redrawStart = currentSelection.y = caretOffset;
- }
- } else {
- if (caretOffset > currentSelection.y) {
- // grow selection
- redrawStart = currentSelection.y;
- redrawEnd = currentSelection.y = caretOffset;
- // check if selection has reversed direction
- if (currentSelection.x != selectionAnchor) {
- redrawStart = currentSelection.x;
- currentSelection.x = selectionAnchor;
- }
- // test whether selection actually changed. Fixes 1G71EO1
- } else if (selectionAnchor == currentSelection.y && caretOffset > currentSelection.x) {
- // caret moved towards selection anchor (right side of selection).
- // shrink selection
- caretAtBeginning[i] = true;
- redrawStart = currentSelection.x;
- redrawEnd = currentSelection.x = caretOffset;
- }
- }
- if (redrawStart != -1 && redrawEnd != -1) {
- internalRedrawRange(redrawStart, redrawEnd - redrawStart);
- selectionChanged = true;
- }
- }
- if (selectionChanged) {
- int[] regions = new int[newSelection.length * 2];
- for (int i = 0; i < newSelection.length; i++) {
- Point p = newSelection[i];
- if (caretAtBeginning[i]) {
- regions[2 * i] = p.y;
- regions[2 * i + 1] = p.x - p.y;
- } else {
- regions[2 * i] = p.x;
- regions[2 * i + 1] = p.y - p.x;
- }
- }
- setSelection(regions, false, blockSelection);
- sendSelectionEvent();
- }
- sendAccessibleTextCaretMoved();
-}
-/**
- * Moves the caret to the next character or to the beginning of the
- * next line if the cursor is at the end of a line.
- */
-void doSelectionCursorNext() {
- int[] newCarets = Arrays.copyOf(caretOffsets, caretOffsets.length);
- int newAlignment = Integer.MIN_VALUE;
- for (int i = 0; i < caretOffsets.length; i++) {
- int caretOffset = caretOffsets[i];
- int caretLine = content.getLineAtOffset(caretOffset);
- int lineOffset = content.getOffsetAtLine(caretLine);
- int offsetInLine = caretOffset - lineOffset;
- int offset;
- if (offsetInLine < content.getLine(caretLine).length()) {
- TextLayout layout = renderer.getTextLayout(caretLine);
- offsetInLine = layout.getNextOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
- int lineStart = layout.getLineOffsets()[layout.getLineIndex(offsetInLine)];
- renderer.disposeTextLayout(layout);
- offset = offsetInLine + lineOffset;
- newAlignment = offsetInLine == lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING;
- newCarets[i] = offset;
- } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) {
- caretLine++;
- offset = content.getOffsetAtLine(caretLine);
- newAlignment = PREVIOUS_OFFSET_TRAILING;
- newCarets[i] = offset;
- }
- }
- if (newAlignment > Integer.MIN_VALUE) {
- setCaretOffsets(newCarets, newAlignment);
- showCaret();
- }
-}
-/**
- * Moves the caret to the previous character or to the end of the previous
- * line if the cursor is at the beginning of a line.
- */
-void doSelectionCursorPrevious() {
- int[] newCarets = Arrays.copyOf(caretOffsets, caretOffsets.length);
- for (int i = 0; i < caretOffsets.length; i++) {
- int caretOffset = caretOffsets[i];
- int caretLine = content.getLineAtOffset(caretOffset);
- int lineOffset = content.getOffsetAtLine(caretLine);
- int offsetInLine = caretOffset - lineOffset;
- if (offsetInLine > 0) {
- newCarets[i] = getClusterPrevious(caretOffset, caretLine);
- } else if (caretLine > 0) {
- caretLine--;
- lineOffset = content.getOffsetAtLine(caretLine);
- newCarets[i] = lineOffset + content.getLine(caretLine).length();
- }
- }
- if (!Arrays.equals(caretOffsets, newCarets)) {
- setCaretOffsets(newCarets, OFFSET_LEADING);
- showCaret();
- }
-}
-/**
- * Moves the caret one line down and to the same character offset relative
- * to the beginning of the line. Moves the caret to the end of the new line
- * if the new line is shorter than the character offset.
- * Moves the caret to the end of the text if the caret already is on the
- * last line.
- * Adjusts the selection according to the caret change. This can either add
- * to or subtract from the old selection, depending on the previous selection
- * direction.
- */
-void doSelectionLineDown() {
- int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x;
- doLineDown(true);
- columnX = oldColumnX;
-}
-/**
- * Moves the caret one line up and to the same character offset relative
- * to the beginning of the line. Moves the caret to the end of the new line
- * if the new line is shorter than the character offset.
- * Moves the caret to the beginning of the document if it is already on the
- * first line.
- * Adjusts the selection according to the caret change. This can either add
- * to or subtract from the old selection, depending on the previous selection
- * direction.
- */
-void doSelectionLineUp() {
- int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x;
- doLineUp(true);
- columnX = oldColumnX;
-}
-/**
- * Scrolls one page down so that the last line (truncated or whole)
- * of the current page becomes the fully visible top line.
- *
- * The caret is scrolled the same number of lines so that its location
- * relative to the top line remains the same. The exception is the end
- * of the text where a full page scroll is not possible. In this case
- * the caret is moved after the last character.
- *
- * Adjusts the selection according to the caret change. This can either add
- * to or subtract from the old selection, depending on the previous selection
- * direction.
- *
- */
-void doSelectionPageDown(int pixels) {
- int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x;
- doPageDown(true, pixels);
- columnX = oldColumnX;
-}
-/**
- * Scrolls one page up so that the first line (truncated or whole)
- * of the current page becomes the fully visible last line.
- *
- * The caret is scrolled the same number of lines so that its location
- * relative to the top line remains the same. The exception is the beginning
- * of the text where a full page scroll is not possible. In this case the
- * caret is moved in front of the first character.
- *
- * Adjusts the selection according to the caret change. This can either add
- * to or subtract from the old selection, depending on the previous selection
- * direction.
- *
- */
-void doSelectionPageUp(int pixels) {
- if (caretOffsets.length > 1) { // operation doesn't make sense for multi-carets
- return;
- }
- int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x;
- doPageUp(true, pixels);
- columnX = oldColumnX;
-}
-/**
- * Moves the caret to the end of the next word .
- */
-void doSelectionWordNext() {
- int[] offsets = Arrays.stream(caretOffsets).map(offset -> getWordNext(offset, SWT.MOVEMENT_WORD)).toArray();
- // don't change caret position if in single line mode and the cursor
- // would be on a different line. fixes 5673
- if (!isSingleLine()) {
- // Force symmetrical movement for word next and previous. Fixes 14536
- setCaretOffsets(offsets, OFFSET_LEADING);
- showCaret();
- } else {
- int[] linesForCurrentCarets = Arrays.stream(caretOffsets).map(offset -> content.getLineAtOffset(offset)).toArray();
- int[] linesForNewCarets = Arrays.stream(offsets).map(offset -> content.getLineAtOffset(offset)).toArray();
- if (Arrays.equals(linesForCurrentCarets, linesForNewCarets)) {
- // Force symmetrical movement for word next and previous. Fixes 14536
- setCaretOffsets(offsets, OFFSET_LEADING);
- showCaret();
- }
- }
-}
-/**
- * Moves the caret to the start of the previous word.
- */
-void doSelectionWordPrevious() {
- setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getWordPrevious(offset, SWT.MOVEMENT_WORD)).toArray(), OFFSET_LEADING);
- showCaret();
-}
-/**
- * Moves the caret one character to the left. Do not go to the previous line.
- * When in a bidi locale and at a R2L character the caret is moved to the
- * beginning of the R2L segment (visually right) and then one character to the
- * left (visually left because it's now in a L2R segment).
- */
-void doVisualPrevious() {
- setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getClusterPrevious(offset, content.getLineAtOffset(offset))).toArray(), SWT.DEFAULT);
- showCaret();
-}
-/**
- * Moves the caret one character to the right. Do not go to the next line.
- * When in a bidi locale and at a R2L character the caret is moved to the
- * end of the R2L segment (visually left) and then one character to the
- * right (visually right because it's now in a L2R segment).
- */
-void doVisualNext() {
- setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getClusterNext(offset, content.getLineAtOffset(offset))).toArray(), SWT.DEFAULT);
- showCaret();
-}
-/**
- * Moves the caret to the end of the next word.
- * If a selection exists, move the caret to the end of the selection
- * and remove the selection.
- */
-void doWordNext() {
- if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) {
- setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.y).toArray(), SWT.DEFAULT);
- showCaret();
- } else {
- doSelectionWordNext();
- }
-}
-/**
- * Moves the caret to the start of the previous word.
- * If a selection exists, move the caret to the start of the selection
- * and remove the selection.
- */
-void doWordPrevious() {
- if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) {
- setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.x).toArray(), SWT.DEFAULT);
- showCaret();
- } else {
- doSelectionWordPrevious();
- }
-}
-/**
- * Ends the autoscroll process.
- */
-void endAutoScroll() {
- autoScrollDirection = SWT.NULL;
-}
-@Override
-public Color getBackground() {
- checkWidget();
- if (background == null) {
- return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
- }
- return background;
-}
-/**
- * Returns the baseline, in points.
- *
- * Note: this API should not be used if a StyleRange attribute causes lines to
- * have different heights (i.e. different fonts, rise, etc).
- *
- * @return baseline the baseline
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @since 3.0
- *
- * @see #getBaseline(int)
- */
-public int getBaseline() {
- checkWidget();
- return renderer.getBaseline();
-}
-/**
- * Returns the baseline at the given offset, in points.
- *
- * @param offset the offset
- *
- * @return baseline the baseline
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
- *
- *
- * @since 3.2
- */
-public int getBaseline(int offset) {
- checkWidget();
- if (!(0 <= offset && offset <= content.getCharCount())) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- if (isFixedLineHeight()) {
- return renderer.getBaseline();
- }
- int lineIndex = content.getLineAtOffset(offset);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- TextLayout layout = renderer.getTextLayout(lineIndex);
- int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length()));
- FontMetrics metrics = layout.getLineMetrics(lineInParagraph);
- renderer.disposeTextLayout(layout);
- return metrics.getAscent() + metrics.getLeading();
-}
-/**
- * Gets the BIDI coloring mode. When true the BIDI text display
- * algorithm is applied to segments of text that are the same
- * color.
- *
- * @return the current coloring mode
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @deprecated use BidiSegmentListener instead.
- */
-@Deprecated
-public boolean getBidiColoring() {
- checkWidget();
- return bidiColoring;
-}
-/**
- * Returns whether the widget is in block selection mode.
- *
- * @return true if widget is in block selection mode, false otherwise
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public boolean getBlockSelection() {
- checkWidget();
- return blockSelection;
-}
-Rectangle getBlockSelectionPosition() {
- int firstLine = getLineIndex(blockYAnchor - getVerticalScrollOffset());
- int lastLine = getLineIndex(blockYLocation - getVerticalScrollOffset());
- if (firstLine > lastLine) {
- int temp = firstLine;
- firstLine = lastLine;
- lastLine = temp;
- }
- int left = blockXAnchor;
- int right = blockXLocation;
- if (left > right) {
- left = blockXLocation;
- right = blockXAnchor;
- }
- return new Rectangle (left - horizontalScrollOffset, firstLine, right - horizontalScrollOffset, lastLine);
-}
-/**
- * Returns the block selection bounds. The bounds is
- * relative to the upper left corner of the document.
- *
- * @return the block selection bounds
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public Rectangle getBlockSelectionBounds() {
- Rectangle rect;
- if (blockSelection && blockXLocation != -1) {
- rect = getBlockSelectionRectangle();
- } else {
- Point startPoint = getPointAtOffset(selection[0].x);
- Point endPoint = getPointAtOffset(selection[0].y);
- int height = getLineHeight(selection[0].y);
- rect = new Rectangle(startPoint.x, startPoint.y, endPoint.x - startPoint.x, endPoint.y + height - startPoint.y);
- if (selection[0].x == selection[0].y) {
- rect.width = getCaretWidth();
- }
- }
- rect.x += horizontalScrollOffset;
- rect.y += getVerticalScrollOffset();
- return rect;
-}
-Rectangle getBlockSelectionRectangle() {
- Rectangle rect = getBlockSelectionPosition();
- rect.y = getLinePixel(rect.y);
- rect.width = rect.width - rect.x;
- rect.height = getLinePixel(rect.height + 1) - rect.y;
- return rect;
-}
-String getBlockSelectionText(String delimiter) {
- Rectangle rect = getBlockSelectionPosition();
- int firstLine = rect.y;
- int lastLine = rect.height;
- int left = rect.x;
- int right = rect.width;
- StringBuilder buffer = new StringBuilder();
- for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
- int start = getOffsetAtPoint(left, 0, lineIndex, null);
- int end = getOffsetAtPoint(right, 0, lineIndex, null);
- if (start > end) {
- int temp = start;
- start = end;
- end = temp;
- }
- String text = content.getTextRange(start, end - start);
- buffer.append(text);
- if (lineIndex < lastLine) buffer.append(delimiter);
- }
- return buffer.toString();
-}
-/**
- * Returns the index of the last fully visible line.
- *
- * @return index of the last fully visible line.
- */
-int getBottomIndex() {
- int bottomIndex;
- if (isFixedLineHeight()) {
- int lineCount = 1;
- int lineHeight = renderer.getLineHeight();
- if (lineHeight != 0) {
- // calculate the number of lines that are fully visible
- int partialTopLineHeight = topIndex * lineHeight - getVerticalScrollOffset();
- lineCount = (clientAreaHeight - partialTopLineHeight) / lineHeight;
- }
- bottomIndex = Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1));
- } else {
- int clientAreaHeight = this.clientAreaHeight - bottomMargin;
- bottomIndex = getLineIndex(clientAreaHeight);
- if (bottomIndex > 0) {
- int linePixel = getLinePixel(bottomIndex);
- int lineHeight = renderer.getLineHeight(bottomIndex);
- if (linePixel + lineHeight > clientAreaHeight) {
- if (getLinePixel(bottomIndex - 1) >= topMargin) {
- bottomIndex--;
- }
- }
- }
- }
- return bottomIndex;
-}
-/**
- * Returns the bottom margin.
- *
- * @return the bottom margin.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public int getBottomMargin() {
- checkWidget();
- return bottomMargin;
-}
-Rectangle getBoundsAtOffset(int offset) {
- int lineIndex = content.getLineAtOffset(offset);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- String line = content.getLine(lineIndex);
- Rectangle bounds;
- if (line.length() != 0) {
- TextLayout layout = renderer.getTextLayout(lineIndex);
- int offsetInLine = Math.min (layout.getText().length(), Math.max (0, offset - lineOffset));
- bounds = layout.getBounds(offsetInLine, offsetInLine);
- if (getListeners(ST.LineGetSegments).length > 0 && caretAlignment == PREVIOUS_OFFSET_TRAILING && offsetInLine != 0) {
- offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
- Point point = layout.getLocation(offsetInLine, true);
- bounds = new Rectangle (point.x, point.y, 0, bounds.height);
- }
- renderer.disposeTextLayout(layout);
- } else {
- bounds = new Rectangle (0, 0, 0, renderer.getLineHeight());
- }
- if (Arrays.binarySearch(caretOffsets, offset) >= 0 && !isWordWrap()) {
- int lineEnd = lineOffset + line.length();
- if (offset == lineEnd) {
- bounds.width += getCaretWidth();
- }
- }
- bounds.x += leftMargin - horizontalScrollOffset;
- bounds.y += getLinePixel(lineIndex);
- return bounds;
-}
-/**
- * Returns the caret position relative to the start of the text.
- *
- * @return the caret position relative to the start of the text.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public int getCaretOffset() {
- checkWidget();
- return caretOffsets[0];
-}
-/**
- * Returns the caret width.
- *
- * @return the caret width, 0 if caret is null.
- */
-int getCaretWidth() {
- Caret caret = getCaret();
- if (caret == null) return 0;
- return caret.getSize().x;
-}
-Object getClipboardContent(int clipboardType) {
- TextTransfer plainTextTransfer = TextTransfer.getInstance();
- return clipboard.getContents(plainTextTransfer, clipboardType);
-}
-int getClusterNext(int offset, int lineIndex) {
- int lineOffset = content.getOffsetAtLine(lineIndex);
- TextLayout layout = renderer.getTextLayout(lineIndex);
- offset -= lineOffset;
- offset = layout.getNextOffset(offset, SWT.MOVEMENT_CLUSTER);
- offset += lineOffset;
- renderer.disposeTextLayout(layout);
- return offset;
-}
-int getClusterPrevious(int offset, int lineIndex) {
- int lineOffset = content.getOffsetAtLine(lineIndex);
- TextLayout layout = renderer.getTextLayout(lineIndex);
- offset -= lineOffset;
- offset = layout.getPreviousOffset(offset, SWT.MOVEMENT_CLUSTER);
- offset += lineOffset;
- renderer.disposeTextLayout(layout);
- return offset;
-}
-/**
- * Returns the content implementation that is used for text storage.
- *
- * @return content the user defined content implementation that is used for
- * text storage or the default content implementation if no user defined
- * content implementation has been set.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public StyledTextContent getContent() {
- checkWidget();
- return content;
-}
-@Override
-public boolean getDragDetect () {
- checkWidget ();
- return dragDetect;
-}
-/**
- * Returns whether the widget implements double click mouse behavior.
- *
- * @return true if double clicking a word selects the word, false if double clicks
- * have the same effect as regular mouse clicks
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public boolean getDoubleClickEnabled() {
- checkWidget();
- return doubleClickEnabled;
-}
-/**
- * Returns whether the widget content can be edited.
- *
- * @return true if content can be edited, false otherwise
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public boolean getEditable() {
- checkWidget();
- return editable;
-}
-@Override
-public Color getForeground() {
- checkWidget();
- if (foreground == null) {
- return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
- }
- return foreground;
-}
-/**
- * Returns the horizontal scroll increment.
- *
- * @return horizontal scroll increment.
- */
-int getHorizontalIncrement() {
- return renderer.averageCharWidth;
-}
-/**
- * Returns the horizontal scroll offset relative to the start of the line.
- *
- * @return horizontal scroll offset relative to the start of the line,
- * measured in character increments starting at 0, if > 0 the content is scrolled
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public int getHorizontalIndex() {
- checkWidget();
- return horizontalScrollOffset / getHorizontalIncrement();
-}
-/**
- * Returns the horizontal scroll offset relative to the start of the line.
- *
- * @return the horizontal scroll offset relative to the start of the line,
- * measured in SWT logical point starting at 0, if > 0 the content is scrolled.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public int getHorizontalPixel() {
- checkWidget();
- return horizontalScrollOffset;
-}
-/**
- * Returns the line indentation of the widget.
- *
- * @return the line indentation
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see #getLineJustify(int)
- *
- * @since 3.2
- */
-public boolean getJustify() {
- checkWidget();
- return justify;
-}
-/**
- * Returns the action assigned to the key.
- * Returns SWT.NULL if there is no action associated with the key.
- *
- * @param key a key code defined in SWT.java or a character.
- * Optionally ORd with a state mask. Preferred state masks are one or more of
- * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform
- * differences. However, there may be cases where using the specific state masks
- * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
- * @return one of the predefined actions defined in ST.java or SWT.NULL
- * if there is no action associated with the key.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public int getKeyBinding(int key) {
- checkWidget();
- Integer action = keyActionMap.get(key);
- return action == null ? SWT.NULL : action.intValue();
-}
-/**
- * Gets the number of characters.
- *
- * @return number of characters in the widget
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public int getCharCount() {
- checkWidget();
- return content.getCharCount();
-}
-/**
- * Returns the line at the given line index without delimiters.
- * Index 0 is the first line of the content. When there are not
- * any lines, getLine(0) is a valid call that answers an empty string.
- *
- * @param lineIndex index of the line to return.
- * @return the line text without delimiters
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
- *
- * @since 3.4
- */
-public String getLine(int lineIndex) {
- checkWidget();
- if (lineIndex < 0 ||
- (lineIndex > 0 && lineIndex >= content.getLineCount())) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- return content.getLine(lineIndex);
-}
-/**
- * Returns the alignment of the line at the given index.
- *
- * @param index the index of the line
- *
- * @return the line alignment
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the index is invalid
- *
- *
- * @see #getAlignment()
- *
- * @since 3.2
- */
-public int getLineAlignment(int index) {
- checkWidget();
- if (index < 0 || index > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- return renderer.getLineAlignment(index, alignment);
-}
-/**
- * Returns the line at the specified offset in the text
- * where 0 < offset < getCharCount() so that getLineAtOffset(getCharCount())
- * returns the line of the insert location.
- *
- * @param offset offset relative to the start of the content.
- * 0 <= offset <= getCharCount()
- * @return line at the specified offset in the text
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
- *
- */
-public int getLineAtOffset(int offset) {
- checkWidget();
- if (offset < 0 || offset > getCharCount()) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- return content.getLineAtOffset(offset);
-}
-/**
- * Returns the background color of the line at the given index.
- * Returns null if a LineBackgroundListener has been set or if no background
- * color has been specified for the line. Should not be called if a
- * LineBackgroundListener has been set since the listener maintains the
- * line background colors.
- *
- * @param index the index of the line
- * @return the background color of the line at the given index.
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the index is invalid
- *
- */
-public Color getLineBackground(int index) {
- checkWidget();
- if (index < 0 || index > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- return isListening(ST.LineGetBackground) ? null : renderer.getLineBackground(index, null);
-}
-/**
- * Returns the bullet of the line at the given index.
- *
- * @param index the index of the line
- *
- * @return the line bullet
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the index is invalid
- *
- *
- * @since 3.2
- */
-public Bullet getLineBullet(int index) {
- checkWidget();
- if (index < 0 || index > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- return isListening(ST.LineGetStyle) ? null : renderer.getLineBullet(index, null);
-}
-/**
- * Returns the line background data for the given line or null if
- * there is none.
- *
- * @param lineOffset offset of the line start relative to the start
- * of the content.
- * @param line line to get line background data for
- * @return line background data for the given line.
- */
-StyledTextEvent getLineBackgroundData(int lineOffset, String line) {
- return sendLineEvent(ST.LineGetBackground, lineOffset, line);
-}
-/**
- * Gets the number of text lines.
- *
- * @return the number of lines in the widget
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public int getLineCount() {
- checkWidget();
- return content.getLineCount();
-}
-/**
- * Returns the number of lines that can be completely displayed in the
- * widget client area.
- *
- * @return number of lines that can be completely displayed in the widget
- * client area.
- */
-int getLineCountWhole() {
- if (isFixedLineHeight()) {
- int lineHeight = renderer.getLineHeight();
- return lineHeight != 0 ? clientAreaHeight / lineHeight : 1;
- }
- return getBottomIndex() - topIndex + 1;
-}
-/**
- * Returns the line delimiter used for entering new lines by key down
- * or paste operation.
- *
- * @return line delimiter used for entering new lines by key down
- * or paste operation.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- * Note: this API should not be used if a StyleRange attribute causes lines to
- * have different heights (i.e. different fonts, rise, etc).
- *
- *
- * @return line height in points.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @see #getLineHeight(int)
- */
-public int getLineHeight() {
- checkWidget();
- return renderer.getLineHeight();
-}
-/**
- * Returns the line height at the given offset.
- *
- * @param offset the offset
- *
- * @return line height in points
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
- *
- *
- * @since 3.2
- */
-public int getLineHeight(int offset) {
- checkWidget();
- if (!(0 <= offset && offset <= content.getCharCount())) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- if (isFixedLineHeight()) {
- return renderer.getLineHeight();
- }
- int lineIndex = content.getLineAtOffset(offset);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- TextLayout layout = renderer.getTextLayout(lineIndex);
- int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length()));
- int height = layout.getLineBounds(lineInParagraph).height;
- renderer.disposeTextLayout(layout);
- return height;
-}
-/**
- * Returns the indentation of the line at the given index.
- *
- * @param index the index of the line
- *
- * @return the line indentation
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the index is invalid
- *
- *
- * @see #getIndent()
- *
- * @since 3.2
- */
-public int getLineIndent(int index) {
- checkWidget();
- if (index < 0 || index > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- return isListening(ST.LineGetStyle) ? 0 : renderer.getLineIndent(index, indent);
-}
-/**
- * Returns the vertical indentation of the line at the given index.
- *
- * @param index the index of the line
- *
- * @return the line vertical indentation
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the index is invalid
- *
- *
- * @since 3.109
- */
-public int getLineVerticalIndent(int index) {
- checkWidget();
- if (index < 0 || index >= content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- return isListening(ST.LineGetStyle) ? 0 : renderer.getLineVerticalIndent(index);
-}
-/**
- * Returns whether the line at the given index is justified.
- *
- * @param index the index of the line
- *
- * @return whether the line is justified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the index is invalid
- *
- *
- * @see #getJustify()
- *
- * @since 3.2
- */
-public boolean getLineJustify(int index) {
- checkWidget();
- if (index < 0 || index > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- return isListening(ST.LineGetStyle) ? false : renderer.getLineJustify(index, justify);
-}
-/**
- * Returns the line spacing of the widget.
- *
- * @return the line spacing
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.2
- */
-public int getLineSpacing() {
- checkWidget();
- return lineSpacing;
-}
-/**
- * Returns the line style data for the given line or null if there is
- * none.
- *
- * If there is a LineStyleListener but it does not set any styles,
- * the StyledTextEvent.styles field will be initialized to an empty
- * array.
- *
- *
- * @param lineOffset offset of the line start relative to the start of
- * the content.
- * @param line line to get line styles for
- * @return line style data for the given line. Styles may start before
- * line start and end after line end
- */
-StyledTextEvent getLineStyleData(int lineOffset, String line) {
- return sendLineEvent(ST.LineGetStyle, lineOffset, line);
-}
-/**
- * Returns the top SWT logical point, relative to the client area, of a given line.
- * Clamps out of ranges index.
- *
- * @param lineIndex the line index, the max value is lineCount. If
- * lineIndex == lineCount it returns the bottom SWT logical point of the last line.
- * It means this function can be used to retrieve the bottom SWT logical point of any line.
- *
- * @return the top SWT logical point of a given line index
- *
- * @since 3.2
- */
-public int getLinePixel(int lineIndex) {
- checkWidget();
- int lineCount = content.getLineCount();
- lineIndex = Math.max(0, Math.min(lineCount, lineIndex));
- if (isFixedLineHeight()) {
- int lineHeight = renderer.getLineHeight();
- return lineIndex * lineHeight - getVerticalScrollOffset() + topMargin;
- }
- if (lineIndex == topIndex)
- return topIndexY + topMargin;
- int height = topIndexY;
- if (lineIndex > topIndex) {
- for (int i = topIndex; i < lineIndex; i++) {
- height += renderer.getLineHeight(i);
- }
- } else {
- for (int i = topIndex - 1; i >= lineIndex; i--) {
- height -= renderer.getLineHeight(i);
- }
- }
- return height + topMargin;
-}
-/**
- * Returns the line index for a y, relative to the client area.
- * The line index returned is always in the range 0..lineCount - 1.
- *
- * @param y the y-coordinate point
- *
- * @return the line index for a given y-coordinate point
- *
- * @since 3.2
- */
-public int getLineIndex(int y) {
- checkWidget();
- y -= topMargin;
- if (isFixedLineHeight()) {
- int lineHeight = renderer.getLineHeight();
- int lineIndex = (y + getVerticalScrollOffset()) / lineHeight;
- int lineCount = content.getLineCount();
- lineIndex = Math.max(0, Math.min(lineCount - 1, lineIndex));
- return lineIndex;
- }
- if (y == topIndexY) return topIndex;
- int line = topIndex;
- if (y < topIndexY) {
- while (y < topIndexY && line > 0) {
- y += renderer.getLineHeight(--line);
- }
- } else {
- int lineCount = content.getLineCount();
- int lineHeight = renderer.getLineHeight(line);
- while (y - lineHeight >= topIndexY && line < lineCount - 1) {
- y -= lineHeight;
- lineHeight = renderer.getLineHeight(++line);
- }
- }
- return line;
-}
-/**
- * Returns the tab stops of the line at the given index.
- *
- * @param index the index of the line
- *
- * @return the tab stops for the line
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the index is invalid
- *
- *
- * @see #getTabStops()
- *
- * @since 3.6
- */
-public int[] getLineTabStops(int index) {
- checkWidget();
- if (index < 0 || index > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- if (isListening(ST.LineGetStyle)) return null;
- int[] tabs = renderer.getLineTabStops(index, null);
- if (tabs == null) tabs = this.tabs;
- if (tabs == null) return new int [] {renderer.tabWidth};
- int[] result = new int[tabs.length];
- System.arraycopy(tabs, 0, result, 0, tabs.length);
- return result;
-}
-/**
- * Returns the wrap indentation of the line at the given index.
- *
- * @param index the index of the line
- *
- * @return the wrap indentation
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the index is invalid
- *
- *
- * @see #getWrapIndent()
- *
- * @since 3.6
- */
-public int getLineWrapIndent(int index) {
- checkWidget();
- if (index < 0 || index > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- return isListening(ST.LineGetStyle) ? 0 : renderer.getLineWrapIndent(index, wrapIndent);
-}
-/**
- * Returns the left margin.
- *
- * @return the left margin.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public int getLeftMargin() {
- checkWidget();
- return leftMargin - alignmentMargin;
-}
-/**
- * Returns the x, y location of the upper left corner of the character
- * bounding box at the specified offset in the text. The point is
- * relative to the upper left corner of the widget client area.
- *
- * @param offset offset relative to the start of the content.
- * 0 <= offset <= getCharCount()
- * @return x, y location of the upper left corner of the character
- * bounding box at the specified offset in the text.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
- *
- */
-public Point getLocationAtOffset(int offset) {
- checkWidget();
- if (offset < 0 || offset > getCharCount()) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- return getPointAtOffset(offset);
-}
-/**
- * Returns true if the mouse navigator is enabled.
- * When mouse navigator is enabled, the user can navigate through the widget by pressing the middle button and moving the cursor
- *
- * @return the mouse navigator's enabled state
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see #getEnabled
- * @since 3.110
- */
-public boolean getMouseNavigatorEnabled () {
- checkWidget ();
- return mouseNavigator != null;
-}
-/**
- * Returns the character offset of the first character of the given line.
- *
- * @param lineIndex index of the line, 0 based relative to the first
- * line in the content. 0 <= lineIndex < getLineCount(), except
- * lineIndex may always be 0
- * @return offset offset of the first character of the line, relative to
- * the beginning of the document. The first character of the document is
- * at offset 0.
- * When there are not any lines, getOffsetAtLine(0) is a valid call that
- * answers 0.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
- *
- * @since 2.0
- */
-public int getOffsetAtLine(int lineIndex) {
- checkWidget();
- if (lineIndex < 0 ||
- (lineIndex > 0 && lineIndex >= content.getLineCount())) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- return content.getOffsetAtLine(lineIndex);
-}
-/**
- * Returns the offset of the character at the given location relative
- * to the first character in the document.
- *
- * The return value reflects the character offset that the caret will
- * be placed at if a mouse click occurred at the specified location.
- * If the x coordinate of the location is beyond the center of a character
- * the returned offset will be behind the character.
- *
- *
- * @param point the origin of character bounding box relative to
- * the origin of the widget client area.
- * @return offset of the character at the given location relative
- * to the first character in the document.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when point is null
- *
ERROR_INVALID_ARGUMENT when there is no character at the specified location
- *
- *
- * @deprecated Use {@link #getOffsetAtPoint(Point)} instead for better performance
- */
-@Deprecated
-public int getOffsetAtLocation(Point point) {
- checkWidget();
- if (point == null) {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
- int[] trailing = new int[1];
- int offset = getOffsetAtPoint(point.x, point.y, trailing, true);
- if (offset == -1) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- return offset + trailing[0];
-}
-
-/**
- * Returns the offset of the character at the given point relative
- * to the first character in the document.
- *
- * The return value reflects the character offset that the caret will
- * be placed at if a mouse click occurred at the specified point.
- * If the x coordinate of the point is beyond the center of a character
- * the returned offset will be behind the character.
- *
- * Note: This method is functionally similar to {@link #getOffsetAtLocation(Point)} except that
- * it does not throw an exception when no character is found and thus performs faster.
- *
- * @param point the origin of character bounding box relative to
- * the origin of the widget client area.
- * @return offset of the character at the given point relative
- * to the first character in the document.
- * -1 when there is no character at the specified location.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when point is null
- *
- *
- * @since 3.107
- */
-public int getOffsetAtPoint(Point point) {
- checkWidget();
- if (point == null) {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
- int[] trailing = new int[1];
- int offset = getOffsetAtPoint(point.x, point.y, trailing, true);
- return offset != -1 ? offset + trailing[0] : -1;
-}
-
-int getOffsetAtPoint(int x, int y, int[] alignment) {
- int lineIndex = getLineIndex(y);
- y -= getLinePixel(lineIndex);
- return getOffsetAtPoint(x, y, lineIndex, alignment);
-}
-int getOffsetAtPoint(int x, int y, int lineIndex, int[] alignment) {
- TextLayout layout = renderer.getTextLayout(lineIndex);
- x += horizontalScrollOffset - leftMargin;
- int[] trailing = new int[1];
- int offsetInLine = layout.getOffset(x, y, trailing);
- if (alignment != null) alignment[0] = OFFSET_LEADING;
- if (trailing[0] != 0) {
- int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]);
- int lineStart = layout.getLineOffsets()[lineInParagraph];
- if (offsetInLine + trailing[0] == lineStart) {
- offsetInLine += trailing[0];
- if (alignment != null) alignment[0] = PREVIOUS_OFFSET_TRAILING;
- } else {
- String line = content.getLine(lineIndex);
- int level = 0;
- if (alignment != null) {
- int offset = offsetInLine;
- while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--;
- if (offset == 0 && Character.isDigit(line.charAt(offset))) {
- level = isMirrored() ? 1 : 0;
- } else {
- level = layout.getLevel(offset) & 0x1;
- }
- }
- offsetInLine += trailing[0];
- if (alignment != null) {
- int trailingLevel = layout.getLevel(offsetInLine) & 0x1;
- if (level != trailingLevel) {
- alignment[0] = PREVIOUS_OFFSET_TRAILING;
- } else {
- alignment[0] = OFFSET_LEADING;
- }
- }
- }
- }
- renderer.disposeTextLayout(layout);
- return offsetInLine + content.getOffsetAtLine(lineIndex);
-}
-int getOffsetAtPoint(int x, int y, int[] trailing, boolean inTextOnly) {
- if (inTextOnly && y + getVerticalScrollOffset() < 0 || x + horizontalScrollOffset < 0) {
- return -1;
- }
- int bottomIndex = getPartialBottomIndex();
- int height = getLinePixel(bottomIndex + 1);
- if (inTextOnly && y > height) {
- return -1;
- }
- int lineIndex = getLineIndex(y);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- TextLayout layout = renderer.getTextLayout(lineIndex);
- x += horizontalScrollOffset - leftMargin;
- y -= getLinePixel(lineIndex);
- int offset = layout.getOffset(x, y, trailing);
- Rectangle rect = layout.getLineBounds(layout.getLineIndex(offset));
- renderer.disposeTextLayout(layout);
- if (inTextOnly && !(rect.x <= x && x <= rect.x + rect.width)) {
- return -1;
- }
- return offset + lineOffset;
-}
-/**
- * Returns the orientation of the receiver.
- *
- * @return the orientation style
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 2.1.2
- */
-@Override
-public int getOrientation () {
- return super.getOrientation ();
-}
-/**
- * Returns the index of the last partially visible line.
- *
- * @return index of the last partially visible line.
- */
-int getPartialBottomIndex() {
- if (isFixedLineHeight()) {
- int lineHeight = renderer.getLineHeight();
- int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight);
- return Math.max(0, Math.min(content.getLineCount(), topIndex + partialLineCount) - 1);
- }
- return getLineIndex(clientAreaHeight - bottomMargin);
-}
-/**
- * Returns the index of the first partially visible line.
- *
- * @return index of the first partially visible line.
- */
-int getPartialTopIndex() {
- if (isFixedLineHeight()) {
- int lineHeight = renderer.getLineHeight();
- return getVerticalScrollOffset() / lineHeight;
- }
- return topIndexY <= 0 ? topIndex : topIndex - 1;
-}
-/**
- * Returns the content in the specified range using the platform line
- * delimiter to separate lines.
- *
- * @param writer the TextWriter to write line text into
- * @return the content in the specified range using the platform line
- * delimiter to separate lines as written by the specified TextWriter.
- */
-String getPlatformDelimitedText(TextWriter writer) {
- int end = writer.getStart() + writer.getCharCount();
- int startLine = content.getLineAtOffset(writer.getStart());
- int endLine = content.getLineAtOffset(end);
- String endLineText = content.getLine(endLine);
- int endLineOffset = content.getOffsetAtLine(endLine);
-
- for (int i = startLine; i <= endLine; i++) {
- writer.writeLine(content.getLine(i), content.getOffsetAtLine(i));
- if (i < endLine) {
- writer.writeLineDelimiter(PlatformLineDelimiter);
- }
- }
- if (end > endLineOffset + endLineText.length()) {
- writer.writeLineDelimiter(PlatformLineDelimiter);
- }
- writer.close();
- return writer.toString();
-}
-/**
- * Returns all the ranges of text that have an associated StyleRange.
- * Returns an empty array if a LineStyleListener has been set.
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- * The ranges array contains start and length pairs. Each pair refers to
- * the corresponding style in the styles array. For example, the pair
- * that starts at ranges[n] with length ranges[n+1] uses the style
- * at styles[n/2] returned by getStyleRanges(int, int, boolean).
- *
- *
- * @return the ranges or an empty array if a LineStyleListener has been set.
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.2
- *
- * @see #getStyleRanges(boolean)
- */
-public int[] getRanges() {
- checkWidget();
- if (!isListening(ST.LineGetStyle)) {
- int[] ranges = renderer.getRanges(0, content.getCharCount());
- if (ranges != null) return ranges;
- }
- return new int[0];
-}
-/**
- * Returns the ranges of text that have an associated StyleRange.
- * Returns an empty array if a LineStyleListener has been set.
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- * The ranges array contains start and length pairs. Each pair refers to
- * the corresponding style in the styles array. For example, the pair
- * that starts at ranges[n] with length ranges[n+1] uses the style
- * at styles[n/2] returned by getStyleRanges(int, int, boolean).
- *
- *
- * @param start the start offset of the style ranges to return
- * @param length the number of style ranges to return
- *
- * @return the ranges or an empty array if a LineStyleListener has been set.
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE if start or length are outside the widget content
- *
- *
- * @since 3.2
- *
- * @see #getStyleRanges(int, int, boolean)
- */
-public int[] getRanges(int start, int length) {
- checkWidget();
- int contentLength = getCharCount();
- int end = start + length;
- if (start > end || start < 0 || end > contentLength) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- if (!isListening(ST.LineGetStyle)) {
- int[] ranges = renderer.getRanges(start, length);
- if (ranges != null) return ranges;
- }
- return new int[0];
-}
-/**
- * Returns the right margin.
- *
- * @return the right margin.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- * Text selections are specified in terms of caret positions. In a text
- * widget that contains N characters, there are N+1 caret positions,
- * ranging from 0..N
- *
- *
- * It is usually better to use {@link #getSelectionRanges()} which better
- * support multiple selection and carets and block selection.
- *
- *
- * @return start and end of the selection, x is the offset of the first
- * selected character, y is the offset after the last selected character.
- * The selection values returned are visual (i.e., x will always always be
- * <= y). To determine if a selection is right-to-left (RtoL) vs. left-to-right
- * (LtoR), compare the caretOffset to the start and end of the selection
- * (e.g., caretOffset == start of selection implies that the selection is RtoL).
- * @see #getSelectionRanges
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public Point getSelection() {
- checkWidget();
- return new Point(selection[0].x, selection[0].y);
-}
-/**
- * Returns the selection.
- *
- * It is usually better to use {@link #getSelectionRanges()} which better
- * support multiple selection and carets and block selection.
- *
- *
- * @return start and length of the selection, x is the offset of the
- * first selected character, relative to the first character of the
- * widget content. y is the length of the selection.
- * The selection values returned are visual (i.e., length will always always be
- * positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right
- * (LtoR), compare the caretOffset to the start and end of the selection
- * (e.g., caretOffset == start of selection implies that the selection is RtoL).
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @see #getSelectionRanges
- */
-public Point getSelectionRange() {
- checkWidget();
- return new Point(selection[0].x, selection[0].y - selection[0].x);
-}
-/**
- * Returns the selected ranges of text.
- * If block is enabled, return the ranges that are inside the block selection rectangle.
- *
- * The ranges array contains start and length pairs.
- *
- * When the receiver is not
- * in block selection mode the return arrays contains the start and length of
- * the regular selections.
- *
- * @return the ranges array
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- * @see #setSelectionRanges(int[])
- */
-public int[] getSelectionRanges() {
- checkWidget();
- if (blockSelection && blockXLocation != -1) {
- Rectangle rect = getBlockSelectionPosition();
- int firstLine = rect.y;
- int lastLine = rect.height;
- int left = rect.x;
- int right = rect.width;
- int[] ranges = new int[(lastLine - firstLine + 1) * 2];
- int index = 0;
- for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
- int start = getOffsetAtPoint(left, 0, lineIndex, null);
- int end = getOffsetAtPoint(right, 0, lineIndex, null);
- if (start > end) {
- int temp = start;
- start = end;
- end = temp;
- }
- ranges[index++] = start;
- ranges[index++] = end - start;
- }
- return ranges;
- }
- int[] res = new int[2 * selection.length];
- int index = 0;
- for (Point p : selection) {
- res[index++] = p.x;
- res[index++] = p.y - p.x;
- }
- return res;
-}
-/**
- * Returns the receiver's selection background color.
- *
- * @return the selection background color
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @since 2.1
- */
-public Color getSelectionBackground() {
- checkWidget();
- if (selectionBackground == null) {
- return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
- }
- return selectionBackground;
-}
-/**
- * Gets the number of selected characters.
- *
- * @return the number of selected characters.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- * Returns null if a LineStyleListener has been set or if a style is not set
- * for the offset.
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- *
- * @param offset the offset to return the style for.
- * 0 <= offset < getCharCount() must be true.
- * @return a StyleRange with start == offset and length == 1, indicating
- * the style at the given offset. null if a LineStyleListener has been set
- * or if a style is not set for the given offset.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- * Returns an empty array if a LineStyleListener has been set.
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- * Note: Because a StyleRange includes the start and length, the
- * same instance cannot occur multiple times in the array of styles.
- * If the same style attributes, such as font and color, occur in
- * multiple StyleRanges, getStyleRanges(boolean)
- * can be used to get the styles without the ranges.
- *
- *
- * @return the styles or an empty array if a LineStyleListener has been set.
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- * Returns an empty array if a LineStyleListener has been set.
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- * Note: When includeRanges is true, the start and length
- * fields of each StyleRange will be valid, however the StyleRange
- * objects may need to be cloned. When includeRanges is
- * false, getRanges(int, int) can be used to get the
- * associated ranges.
- *
- *
- * @param includeRanges whether the start and length field of the StyleRanges should be set.
- *
- * @return the styles or an empty array if a LineStyleListener has been set.
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.2
- *
- * @see #getRanges(int, int)
- * @see #setStyleRanges(int[], StyleRange[])
- */
-public StyleRange[] getStyleRanges(boolean includeRanges) {
- checkWidget();
- return getStyleRanges(0, content.getCharCount(), includeRanges);
-}
-/**
- * Returns the styles for the given text range.
- *
- * Returns an empty array if a LineStyleListener has been set.
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- * Note: Because the StyleRange includes the start and length, the
- * same instance cannot occur multiple times in the array of styles.
- * If the same style attributes, such as font and color, occur in
- * multiple StyleRanges, getStyleRanges(int, int, boolean)
- * can be used to get the styles without the ranges.
- *
- * @param start the start offset of the style ranges to return
- * @param length the number of style ranges to return
- *
- * @return the styles or an empty array if a LineStyleListener has
- * been set. The returned styles will reflect the given range. The first
- * returned StyleRange will have a starting offset >= start
- * and the last returned StyleRange will have an ending
- * offset <= start + length - 1
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
- *
- *
- * @see #getStyleRanges(int, int, boolean)
- *
- * @since 3.0
- */
-public StyleRange[] getStyleRanges(int start, int length) {
- checkWidget();
- return getStyleRanges(start, length, true);
-}
-/**
- * Returns the styles for the given text range.
- *
- * Returns an empty array if a LineStyleListener has been set.
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- * Note: When includeRanges is true, the start and length
- * fields of each StyleRange will be valid, however the StyleRange
- * objects may need to be cloned. When includeRanges is
- * false, getRanges(int, int) can be used to get the
- * associated ranges.
- *
- *
- * @param start the start offset of the style ranges to return
- * @param length the number of style ranges to return
- * @param includeRanges whether the start and length field of the StyleRanges should be set.
- *
- * @return the styles or an empty array if a LineStyleListener has
- * been set. The returned styles will reflect the given range. The first
- * returned StyleRange will have a starting offset >= start
- * and the last returned StyleRange will have an ending
- * offset >= start + length - 1
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
- *
- *
- * @since 3.2
- *
- * @see #getRanges(int, int)
- * @see #setStyleRanges(int[], StyleRange[])
- */
-public StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) {
- checkWidget();
- int contentLength = getCharCount();
- int end = start + length;
- if (start > end || start < 0 || end > contentLength) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- if (!isListening(ST.LineGetStyle)) {
- StyleRange[] ranges = renderer.getStyleRanges(start, length, includeRanges);
- if (ranges != null) return ranges;
- }
- return new StyleRange[0];
-}
-/**
- * Returns the tab width measured in characters.
- *
- * @return tab width measured in characters
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see #getTabStops()
- */
-public int getTabs() {
- checkWidget();
- return tabLength;
-}
-
-/**
- * Returns the tab list of the receiver.
- *
- * @return the tab list
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.6
- */
-public int[] getTabStops() {
- checkWidget();
- if (tabs == null) return new int [] {renderer.tabWidth};
- int[] result = new int[tabs.length];
- System.arraycopy(tabs, 0, result, 0, tabs.length);
- return result;
-}
-
-/**
- * Returns a copy of the widget content.
- *
- * @return copy of the widget content
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public String getText() {
- checkWidget();
- return content.getTextRange(0, getCharCount());
-}
-/**
- * Returns the widget content between the two offsets.
- *
- * @param start offset of the first character in the returned String
- * @param end offset of the last character in the returned String
- * @return widget content starting at start and ending at end
- * @see #getTextRange(int,int)
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
- *
- */
-public String getText(int start, int end) {
- checkWidget();
- int contentLength = getCharCount();
- if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- return content.getTextRange(start, end - start + 1);
-}
-/**
- * Returns the smallest bounding rectangle that includes the characters between two offsets.
- *
- * @param start offset of the first character included in the bounding box
- * @param end offset of the last character included in the bounding box
- * @return bounding box of the text between start and end
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
- *
- * @since 3.1
- */
-public Rectangle getTextBounds(int start, int end) {
- checkWidget();
- int contentLength = getCharCount();
- if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- int lineStart = content.getLineAtOffset(start);
- int lineEnd = content.getLineAtOffset(end);
- Rectangle rect;
- int y = getLinePixel(lineStart);
- int height = 0;
- int left = 0x7fffffff, right = 0;
- for (int i = lineStart; i <= lineEnd; i++) {
- int lineOffset = content.getOffsetAtLine(i);
- TextLayout layout = renderer.getTextLayout(i);
- int length = layout.getText().length();
- if (length > 0) {
- if (i == lineStart) {
- if (i == lineEnd) {
- rect = layout.getBounds(start - lineOffset, end - lineOffset);
- } else {
- rect = layout.getBounds(start - lineOffset, length);
- }
- y += rect.y;
- } else if (i == lineEnd) {
- rect = layout.getBounds(0, end - lineOffset);
- } else {
- rect = layout.getBounds();
- }
- left = Math.min(left, rect.x);
- right = Math.max(right, rect.x + rect.width);
- height += rect.height;
- } else {
- height += renderer.getLineHeight();
- }
- renderer.disposeTextLayout(layout);
- }
- rect = new Rectangle (left, y, right-left, height);
- rect.x += leftMargin - horizontalScrollOffset;
- return rect;
-}
-/**
- * Returns the widget content starting at start for length characters.
- *
- * @param start offset of the first character in the returned String
- * @param length number of characters to return
- * @return widget content starting at start and extending length characters.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when start and/or length are outside the widget content
- *
- */
-public String getTextRange(int start, int length) {
- checkWidget();
- int contentLength = getCharCount();
- int end = start + length;
- if (start > end || start < 0 || end > contentLength) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- return content.getTextRange(start, length);
-}
-/**
- * Returns the maximum number of characters that the receiver is capable of holding.
- *
- * @return the text limit
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public int getTextLimit() {
- checkWidget();
- return textLimit;
-}
-/**
- * Gets the top index.
- *
- * The top index is the index of the fully visible line that is currently
- * at the top of the widget or the topmost partially visible line if no line is fully visible.
- * The top index changes when the widget is scrolled. Indexing is zero based.
- *
- *
- * @return the index of the top line
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public int getTopIndex() {
- checkWidget();
- return topIndex;
-}
-/**
- * Returns the top margin.
- *
- * @return the top margin.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public int getTopMargin() {
- checkWidget();
- return topMargin;
-}
-/**
- * Gets the top SWT logical point.
- *
- * The top point is the SWT logical point position of the line that is
- * currently at the top of the widget. The text widget can be scrolled by points
- * by dragging the scroll thumb so that a partial line may be displayed at the top
- * the widget. The top point changes when the widget is scrolled. The top point
- * does not include the widget trimming.
- *
- *
- * @return SWT logical point position of the top line
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see #getLineWrapIndent(int)
- *
- * @since 3.6
- */
-public int getWrapIndent() {
- checkWidget();
- return wrapIndent;
-}
-/**
- * Returns the location of the given offset.
- *
- * NOTE: Does not return correct values for true italic fonts (vs. slanted fonts).
- *
- *
- * @return location of the character at the given offset in the line.
- */
-Point getPointAtOffset(int offset) {
- int lineIndex = content.getLineAtOffset(offset);
- String line = content.getLine(lineIndex);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- int offsetInLine = Math.max (0, offset - lineOffset);
- int lineLength = line.length();
- if (lineIndex < content.getLineCount() - 1) {
- int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1;
- if (lineLength < offsetInLine && offsetInLine <= endLineOffset) {
- offsetInLine = lineLength;
- }
- }
- Point point;
- TextLayout layout = renderer.getTextLayout(lineIndex);
- if (lineLength != 0 && offsetInLine <= lineLength) {
- if (offsetInLine == lineLength) {
- offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
- point = layout.getLocation(offsetInLine, true);
- } else {
- switch (caretAlignment) {
- case OFFSET_LEADING:
- point = layout.getLocation(offsetInLine, false);
- break;
- case PREVIOUS_OFFSET_TRAILING:
- default:
- boolean lineBegin = offsetInLine == 0;
- // If word wrap is enabled, we should also consider offsets
- // of wrapped line parts as line begin and do NOT go back.
- // This prevents clients to jump one line higher than
- // expected, see bug 488172.
- // Respect caretAlignment at the caretOffset, unless there's
- // a non-empty selection, see bug 488172 comment 6.
- if (wordWrap && !lineBegin && (Arrays.binarySearch(caretOffsets, offset) < 0 || Arrays.stream(selection).allMatch(p -> p.x == p.y))) {
- int[] offsets = layout.getLineOffsets();
- for (int i : offsets) {
- if (i == offsetInLine) {
- lineBegin = true;
- break;
- }
- }
- }
- if (lineBegin) {
- point = layout.getLocation(offsetInLine, false);
- } else {
- offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
- point = layout.getLocation(offsetInLine, true);
- }
- break;
- }
- }
- } else {
- point = new Point(layout.getIndent(), layout.getVerticalIndent());
- }
- renderer.disposeTextLayout(layout);
- point.x += leftMargin - horizontalScrollOffset;
- point.y += getLinePixel(lineIndex);
- return point;
-}
-/**
- * Inserts a string. The old selection is replaced with the new text.
- *
- * @param string the string
- * @see #replaceTextRange(int,int,String)
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when string is null
- *
- */
-public void insert(String string) {
- checkWidget();
- if (string == null) {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
- if (blockSelection) {
- insertBlockSelectionText(string, false);
- } else {
- Point sel = getSelectionRange();
- replaceTextRange(sel.x, sel.y, string);
- }
-}
-int insertBlockSelectionText(String text, boolean fillWithSpaces) {
- int lineCount = 1;
- for (int i = 0; i < text.length(); i++) {
- char ch = text.charAt(i);
- if (ch == '\n' || ch == '\r') {
- lineCount++;
- if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') {
- i++;
- }
- }
- }
- String[] lines = new String[lineCount];
- int start = 0;
- lineCount = 0;
- for (int i = 0; i < text.length(); i++) {
- char ch = text.charAt(i);
- if (ch == '\n' || ch == '\r') {
- lines[lineCount++] = text.substring(start, i);
- if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') {
- i++;
- }
- start = i + 1;
- }
- }
- lines[lineCount++] = text.substring(start);
- if (fillWithSpaces) {
- int maxLength = 0;
- for (String line : lines) {
- int length = line.length();
- maxLength = Math.max(maxLength, length);
- }
- for (int i = 0; i < lines.length; i++) {
- String line = lines[i];
- int length = line.length();
- if (length < maxLength) {
- int numSpaces = maxLength - length;
- StringBuilder buffer = new StringBuilder(length + numSpaces);
- buffer.append(line);
- for (int j = 0; j < numSpaces; j++) buffer.append(' ');
- lines[i] = buffer.toString();
- }
- }
- }
- int firstLine, lastLine, left, right;
- if (blockXLocation != -1) {
- Rectangle rect = getBlockSelectionPosition();
- firstLine = rect.y;
- lastLine = rect.height;
- left = rect.x;
- right = rect.width;
- } else {
- firstLine = lastLine = getFirstCaretLine();
- left = right = getPointAtOffset(caretOffsets[0]).x;
- }
- start = caretOffsets[0];
- int caretLine = getFirstCaretLine();
- int index = 0, lineIndex = firstLine;
- while (lineIndex <= lastLine) {
- String string = index < lineCount ? lines[index++] : "";
- int lineStart = sendTextEvent(left, right, lineIndex, string, fillWithSpaces);
- if (lineIndex == caretLine) start = lineStart;
- lineIndex++;
- }
- while (index < lineCount) {
- int lineStart = sendTextEvent(left, left, lineIndex, lines[index++], fillWithSpaces);
- if (lineIndex == caretLine) start = lineStart;
- lineIndex++;
- }
- return start;
-}
-void insertBlockSelectionText(char key, int action) {
- if (key == SWT.CR || key == SWT.LF) return;
- Rectangle rect = getBlockSelectionPosition();
- int firstLine = rect.y;
- int lastLine = rect.height;
- int left = rect.x;
- int right = rect.width;
- int[] trailing = new int[1];
- int offset = 0, delta = 0;
- String text = key != 0 ? new String(new char[] {key}) : "";
- int length = text.length();
- for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
- String line = content.getLine(lineIndex);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- int lineEndOffset = lineOffset + line.length();
- int linePixel = getLinePixel(lineIndex);
- int start = getOffsetAtPoint(left, linePixel, trailing, true);
- boolean outOfLine = start == -1;
- if (outOfLine) {
- start = left < leftMargin ? lineOffset : lineEndOffset;
- } else {
- start += trailing[0];
- }
- int end = getOffsetAtPoint(right, linePixel, trailing, true);
- if (end == -1) {
- end = right < leftMargin ? lineOffset : lineEndOffset;
- } else {
- end += trailing[0];
- }
- if (start > end) {
- int temp = start;
- start = end;
- end = temp;
- }
- if (start == end && !outOfLine) {
- switch (action) {
- case ST.DELETE_PREVIOUS:
- if (start > lineOffset) start = getClusterPrevious(start, lineIndex);
- break;
- case ST.DELETE_NEXT:
- if (end < lineEndOffset) end = getClusterNext(end, lineIndex);
- break;
- }
- }
- if (outOfLine) {
- if (line.length() >= delta) {
- delta = line.length();
- offset = lineEndOffset + length;
- }
- } else {
- offset = start + length;
- delta = content.getCharCount();
- }
- Event event = new Event();
- event.text = text;
- event.start = start;
- event.end = end;
- sendKeyEvent(event);
- }
- int x = getPointAtOffset(offset).x;
- int verticalScrollOffset = getVerticalScrollOffset();
- setBlockSelectionLocation(x, blockYAnchor - verticalScrollOffset, x, blockYLocation - verticalScrollOffset, false);
-}
-/**
- * Creates content change listeners and set the default content model.
- */
-void installDefaultContent() {
- textChangeListener = new TextChangeListener() {
- @Override
- public void textChanging(TextChangingEvent event) {
- handleTextChanging(event);
- }
- @Override
- public void textChanged(TextChangedEvent event) {
- handleTextChanged(event);
- }
- @Override
- public void textSet(TextChangedEvent event) {
- handleTextSet(event);
- }
- };
- content = new DefaultContent();
- content.addTextChangeListener(textChangeListener);
-}
-/**
- * Adds event listeners
- */
-void installListeners() {
- ScrollBar verticalBar = getVerticalBar();
- ScrollBar horizontalBar = getHorizontalBar();
-
- listener = event -> {
- switch (event.type) {
- case SWT.Dispose: handleDispose(event); break;
- case SWT.KeyDown: handleKeyDown(event); break;
- case SWT.KeyUp: handleKeyUp(event); break;
- case SWT.MenuDetect: handleMenuDetect(event); break;
- case SWT.MouseDown: handleMouseDown(event); break;
- case SWT.MouseUp: handleMouseUp(event); break;
- case SWT.MouseMove: handleMouseMove(event); break;
- case SWT.Paint: handlePaint(event); break;
- case SWT.Resize: handleResize(event); break;
- case SWT.Traverse: handleTraverse(event); break;
- }
- };
- addListener(SWT.Dispose, listener);
- addListener(SWT.KeyDown, listener);
- addListener(SWT.KeyUp, listener);
- addListener(SWT.MenuDetect, listener);
- addListener(SWT.MouseDown, listener);
- addListener(SWT.MouseUp, listener);
- addListener(SWT.MouseMove, listener);
- addListener(SWT.Paint, listener);
- addListener(SWT.Resize, listener);
- addListener(SWT.Traverse, listener);
- ime.addListener(SWT.ImeComposition, event -> {
- if (!editable) {
- event.doit = false;
- event.start = 0;
- event.end = 0;
- event.text = "";
- return;
- }
-
- switch (event.detail) {
- case SWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break;
- case SWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break;
- case SWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break;
- }
- });
- if (verticalBar != null) {
- verticalBar.addListener(SWT.Selection, this::handleVerticalScroll);
- }
- if (horizontalBar != null) {
- horizontalBar.addListener(SWT.Selection, this::handleHorizontalScroll);
- }
-}
-void internalRedrawRange(int start, int length) {
- if (length <= 0) return;
- int end = start + length;
- int startLine = content.getLineAtOffset(start);
- int endLine = content.getLineAtOffset(end);
- int partialBottomIndex = getPartialBottomIndex();
- int partialTopIndex = getPartialTopIndex();
- if (startLine > partialBottomIndex || endLine < partialTopIndex) {
- return;
- }
- if (partialTopIndex > startLine) {
- startLine = partialTopIndex;
- start = 0;
- } else {
- start -= content.getOffsetAtLine(startLine);
- }
- if (partialBottomIndex < endLine) {
- endLine = partialBottomIndex + 1;
- end = 0;
- } else {
- end -= content.getOffsetAtLine(endLine);
- }
-
- TextLayout layout = renderer.getTextLayout(startLine);
- int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine);
- int[] offsets = layout.getLineOffsets();
- int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length()));
-
- /* Redraw end of line before start line if wrapped and start offset is first char */
- if (isWordWrap() && startIndex > 0 && offsets[startIndex] == start) {
- Rectangle rect = layout.getLineBounds(startIndex - 1);
- rect.x = rect.width;
- rect.width = clientAreaWidth - rightMargin - rect.x;
- rect.x += lineX;
- rect.y += startLineY;
- super.redraw(rect.x, rect.y, rect.width, rect.height, false);
- }
-
- if (startLine == endLine) {
- int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length()));
- if (startIndex == endIndex) {
- /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */
- Rectangle rect = layout.getBounds(start, end - 1);
- rect.x += lineX;
- rect.y += startLineY;
- super.redraw(rect.x, rect.y, rect.width, rect.height, false);
- renderer.disposeTextLayout(layout);
- return;
- }
- }
-
- /* Redraw start line from the start offset to the end of client area */
- Rectangle startRect = layout.getBounds(start, offsets[startIndex + 1] - 1);
- if (startRect.height == 0) {
- Rectangle bounds = layout.getLineBounds(startIndex);
- startRect.x = bounds.width;
- startRect.y = bounds.y;
- startRect.height = bounds.height;
- }
- startRect.x += lineX;
- startRect.y += startLineY;
- startRect.width = clientAreaWidth - rightMargin - startRect.x;
- super.redraw(startRect.x, startRect.y, startRect.width, startRect.height, false);
-
- /* Redraw end line from the beginning of the line to the end offset */
- if (startLine != endLine) {
- renderer.disposeTextLayout(layout);
- layout = renderer.getTextLayout(endLine);
- offsets = layout.getLineOffsets();
- }
- int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length()));
- Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1);
- if (endRect.height == 0) {
- Rectangle bounds = layout.getLineBounds(endIndex);
- endRect.y = bounds.y;
- endRect.height = bounds.height;
- }
- endRect.x += lineX;
- endRect.y += getLinePixel(endLine);
- super.redraw(endRect.x, endRect.y, endRect.width, endRect.height, false);
- renderer.disposeTextLayout(layout);
-
- /* Redraw all lines in between start and end line */
- int y = startRect.y + startRect.height;
- if (endRect.y > y) {
- super.redraw(leftMargin, y, clientAreaWidth - rightMargin - leftMargin, endRect.y - y, false);
- }
-}
-void handleCompositionOffset (Event event) {
- int[] trailing = new int [1];
- event.index = getOffsetAtPoint(event.x, event.y, trailing, true);
- event.count = trailing[0];
-}
-void handleCompositionSelection (Event event) {
- if (event.start != event.end) {
- int charCount = getCharCount();
- event.start = Math.max(0, Math.min(event.start, charCount));
- event.end = Math.max(0, Math.min(event.end, charCount));
- if (event.text != null) {
- setSelection(event.start, event.end);
- } else {
- event.text = getTextRange(event.start, event.end - event.start);
- }
- } else {
- event.start = selection[0].x;
- event.end = selection[0].y;
- event.text = getSelectionText();
- }
-}
-void handleCompositionChanged(Event event) {
- String text = event.text;
- int start = event.start;
- int end = event.end;
- int charCount = content.getCharCount();
- start = Math.min(start, charCount);
- end = Math.min(end, charCount);
- int length = text.length();
- if (length == ime.getCommitCount()) {
- content.replaceTextRange(start, end - start, "");
- setCaretOffsets(new int[] {ime.getCompositionOffset()}, SWT.DEFAULT);
- caretWidth = 0;
- caretDirection = SWT.NULL;
- } else {
- content.replaceTextRange(start, end - start, text);
- int alignment = SWT.DEFAULT;
- if (ime.getWideCaret()) {
- start = ime.getCompositionOffset();
- for (int caretOffset : caretOffsets) {
- int lineIndex = content.getLineAtOffset(caretOffset);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- TextLayout layout = renderer.getTextLayout(lineIndex);
- caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width;
- renderer.disposeTextLayout(layout);
- }
- alignment = OFFSET_LEADING;
- }
- setCaretOffsets(new int[] {ime.getCaretOffset()}, alignment);
- }
- resetSelection();
- showCaret();
-}
-/**
- * Frees resources.
- */
-void handleDispose(Event event) {
- removeListener(SWT.Dispose, listener);
- notifyListeners(SWT.Dispose, event);
- event.type = SWT.None;
-
- clipboard.dispose();
- if (renderer != null) {
- renderer.dispose();
- renderer = null;
- }
- if (content != null) {
- content.removeTextChangeListener(textChangeListener);
- content = null;
- }
- if (defaultCaret != null) {
- defaultCaret.dispose();
- defaultCaret = null;
- }
- if (leftCaretBitmap != null) {
- leftCaretBitmap.dispose();
- leftCaretBitmap = null;
- }
- if (rightCaretBitmap != null) {
- rightCaretBitmap.dispose();
- rightCaretBitmap = null;
- }
- if (carets != null) {
- for (Caret caret : carets) {
- if (caret != null) {
- caret.dispose();
- }
- }
- carets = null;
- }
- if (isBidiCaret()) {
- BidiUtil.removeLanguageListener(this);
- }
- selectionBackground = null;
- selectionForeground = null;
- marginColor = null;
- textChangeListener = null;
- selection = null;
- doubleClickSelection = null;
- keyActionMap = null;
- background = null;
- foreground = null;
- clipboard = null;
- tabs = null;
-}
-/**
- * Scrolls the widget horizontally.
- */
-void handleHorizontalScroll(Event event) {
- int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset;
- scrollHorizontal(scrollPixel, false);
-}
-/**
- * If an action has been registered for the key stroke execute the action.
- * Otherwise, if a character has been entered treat it as new content.
- *
- * @param event keyboard event
- */
-void handleKey(Event event) {
- int action;
- caretAlignment = PREVIOUS_OFFSET_TRAILING;
- if (event.keyCode != 0) {
- // special key pressed (e.g., F1)
- action = getKeyBinding(event.keyCode | event.stateMask);
- } else {
- // character key pressed
- action = getKeyBinding(event.character | event.stateMask);
- if (action == SWT.NULL) {
- // see if we have a control character
- if ((event.stateMask & SWT.CTRL) != 0 && event.character <= 31) {
- // get the character from the CTRL+char sequence, the control
- // key subtracts 64 from the value of the key that it modifies
- int c = event.character + 64;
- action = getKeyBinding(c | event.stateMask);
- }
- }
- }
- if (action == SWT.NULL) {
- boolean ignore = false;
-
- if (IS_MAC) {
- // Ignore accelerator key combinations (we do not want to
- // insert a character in the text in this instance).
- ignore = (event.stateMask & (SWT.COMMAND | SWT.CTRL)) != 0;
- } else {
- // Ignore accelerator key combinations (we do not want to
- // insert a character in the text in this instance). Don't
- // ignore CTRL+ALT combinations since that is the Alt Gr
- // key on some keyboards. See bug 20953.
- ignore = event.stateMask == SWT.ALT ||
- event.stateMask == SWT.CTRL ||
- event.stateMask == (SWT.ALT | SWT.SHIFT) ||
- event.stateMask == (SWT.CTRL | SWT.SHIFT);
- }
- // -ignore anything below SPACE except for line delimiter keys and tab.
- // -ignore DEL
- if (!ignore && event.character > 31 && event.character != SWT.DEL ||
- event.character == SWT.CR || event.character == SWT.LF ||
- event.character == TAB) {
- doContent(event.character);
- update();
- }
- } else {
- invokeAction(action);
- }
-}
-/**
- * If a VerifyKey listener exists, verify that the key that was entered
- * should be processed.
- *
- * @param event keyboard event
- */
-void handleKeyDown(Event event) {
- if (clipboardSelection == null) {
- clipboardSelection = new Point(selection[0].x, selection[0].y);
- }
- newOrientation = SWT.NONE;
- event.stateMask &= SWT.MODIFIER_MASK;
-
- Event verifyEvent = new Event();
- verifyEvent.character = event.character;
- verifyEvent.keyCode = event.keyCode;
- verifyEvent.keyLocation = event.keyLocation;
- verifyEvent.stateMask = event.stateMask;
- verifyEvent.doit = event.doit;
- notifyListeners(ST.VerifyKey, verifyEvent);
- if (verifyEvent.doit) {
- if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL && event.keyCode == SWT.SHIFT && isBidiCaret()) {
- newOrientation = event.keyLocation == SWT.LEFT ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT;
- }
- handleKey(event);
- }
-}
-/**
- * Update the Selection Clipboard.
- *
- * @param event keyboard event
- */
-void handleKeyUp(Event event) {
- if (clipboardSelection != null) {
- if (clipboardSelection.x != selection[0].x || clipboardSelection.y != selection[0].y) {
- copySelection(DND.SELECTION_CLIPBOARD);
- }
- }
- clipboardSelection = null;
-
- if (newOrientation != SWT.NONE) {
- if (newOrientation != getOrientation()) {
- Event e = new Event();
- e.doit = true;
- notifyListeners(SWT.OrientationChange, e);
- if (e.doit) {
- setOrientation(newOrientation);
- }
- }
- newOrientation = SWT.NONE;
- }
-}
-/**
- * Update the event location for focus-based context menu triggers.
- *
- * @param event menu detect event
- */
-void handleMenuDetect(Event event) {
- if (event.detail == SWT.MENU_KEYBOARD) {
- Point point = getDisplay().map(this, null, getPointAtOffset(caretOffsets[0]));
- event.x = point.x;
- event.y = point.y + getLineHeight(caretOffsets[0]);
- }
-}
-/**
- * Updates the caret location and selection if mouse button 1 has been
- * pressed.
- */
-void handleMouseDown(Event event) {
- //force focus (object support)
- forceFocus();
-
- //drag detect
- if (dragDetect && checkDragDetect(event)) return;
-
- //paste clipboard selection
- if (event.button == 2) {
- // On GTK, if mouseNavigator is enabled we have to distinguish a short middle-click (to paste content) from
- // a long middle-click (mouse navigation started)
- if (IS_GTK && mouseNavigator != null) {
- middleClickPressed = true;
- getDisplay().timerExec(200, ()->{
- boolean click = middleClickPressed;
- middleClickPressed = false;
- if (click && mouseNavigator !=null) {
- mouseNavigator.onMouseDown(event);
- } else {
- pasteOnMiddleClick(event);
- }
- });
- return;
- } else {
- pasteOnMiddleClick(event);
- }
- }
-
- //set selection
- if ((event.button != 1) || (IS_MAC && (event.stateMask & SWT.MOD4) != 0)) {
- return;
- }
- clickCount = event.count;
- boolean addSelection = (event.stateMask & SWT.MOD3) != 0;
- if (clickCount == 1) {
- if (addSelection && !blockSelection) {
- int offset = getOffsetAtPoint(event.x, event.y, null);
- addSelection(offset, 0);
- sendSelectionEvent();
- } else {
- boolean expandSelection = (event.stateMask & SWT.MOD2) != 0;
- doMouseLocationChange(event.x, event.y, expandSelection);
- }
- } else {
- if (doubleClickEnabled) {
- boolean wordSelect = (clickCount & 1) == 0;
- int offset = getOffsetAtPoint(event.x, event.y, null);
- int lineIndex = content.getLineAtOffset(offset);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- if (wordSelect) {
- String line = content.getLine(lineIndex);
- int lineLength = line.length();
- int min = blockSelection ? lineOffset : 0;
- int max = blockSelection ? lineOffset + lineLength : content.getCharCount();
- final Point offsetPoint = getPointAtOffset(offset);
- if (event.x > offsetPoint.x
- && offset < Math.min(max, lineOffset + lineLength) // Not beyond EOL
- && !Character.isWhitespace(line.charAt(offset - lineOffset))) { // Not on whitespace
- offset++;
- }
- int start = Math.max(min, getWordPrevious(offset, SWT.MOVEMENT_WORD_START));
- int end = Math.min(max, getWordNext(start, SWT.MOVEMENT_WORD_END));
- int[] regions = new int[2];
- if (addSelection) {
- int[] current = getSelectionRanges();
- regions = Arrays.copyOf(current, current.length + 2);
- }
- regions[regions.length - 2] = start;
- regions[regions.length - 1] = end - start;
- setSelection(regions, false, true);
- sendSelectionEvent();
- } else {
- if (blockSelection) {
- setBlockSelectionLocation(leftMargin, event.y, clientAreaWidth - rightMargin, event.y, true);
- } else {
- int lineEnd = content.getCharCount();
- if (lineIndex + 1 < content.getLineCount()) {
- lineEnd = content.getOffsetAtLine(lineIndex + 1);
- }
- int[] regions = new int[2];
- if (addSelection) {
- int[] current = getSelectionRanges();
- regions = Arrays.copyOf(current, current.length + 2);
- }
- regions[regions.length - 2] = lineOffset;
- regions[regions.length - 1] = lineEnd - lineOffset;
- setSelection(regions, false, false);
- sendSelectionEvent();
- }
- }
- doubleClickSelection = new Point(selection[0].x, selection[0].y);
- showCaret();
- }
- }
-}
-
-void addSelection(int offset, int length) {
- int[] ranges = getSelectionRanges();
- ranges = Arrays.copyOf(ranges, ranges.length + 2);
- ranges[ranges.length - 2] = offset;
- ranges[ranges.length - 1] = length;
- setSelection(ranges, true, true);
-}
-
-/**
- * Updates the caret location and selection if mouse button 1 is pressed
- * during the mouse move.
- */
-void handleMouseMove(Event event) {
- if (clickCount > 0) {
- update();
- doAutoScroll(event);
- doMouseLocationChange(event.x, event.y, true);
- }
- if (renderer.hasLinks) {
- doMouseLinkCursor(event.x, event.y);
- }
-}
-/**
- * Autoscrolling ends when the mouse button is released.
- */
-void handleMouseUp(Event event) {
- middleClickPressed = false;
- clickCount = 0;
- endAutoScroll();
- if (event.button == 1) {
- copySelection(DND.SELECTION_CLIPBOARD);
- }
-}
-/**
- * Renders the invalidated area specified in the paint event.
- *
- * @param event paint event
- */
-void handlePaint(Event event) {
- if (event.width == 0 || event.height == 0) return;
- if (clientAreaWidth == 0 || clientAreaHeight == 0) return;
-
- final int endY = event.y + event.height;
- GC gc = event.gc;
- Color background = getBackground();
- Color foreground = getForeground();
- if (endY > 0) {
- final int startLine = getLineIndex(event.y);
- final int endLine = isSingleLine() ? 1 : content.getLineCount();
- final int x = leftMargin - horizontalScrollOffset;
- int y = getLinePixel(startLine);
- y += renderer.drawLines(startLine, endLine, x, y, endY, gc, background, foreground);
- if (y < endY) {
- gc.setBackground(background);
- drawBackground(gc, 0, y, clientAreaWidth, endY - y);
- }
- }
- if (blockSelection && blockXLocation != -1) {
- gc.setBackground(getSelectionBackground());
- Rectangle rect = getBlockSelectionRectangle();
- gc.drawRectangle(rect.x, rect.y, Math.max(1, rect.width - 1), Math.max(1, rect.height - 1));
- gc.setAdvanced(true);
- if (gc.getAdvanced()) {
- gc.setAlpha(100);
- gc.fillRectangle(rect);
- gc.setAdvanced(false);
- }
- }
- if(carets != null) {
- for (int i = 1; i < carets.length; i++) { //skip 1st caret that's already drawn
- Caret caret = carets[i];
- if (caret.isVisible()) {
- if (caret.getImage() != null) {
- gc.drawImage(caret.getImage(), caret.getBounds().x, caret.getBounds().y);
- } else {
- gc.drawRectangle(caret.getBounds().x, caret.getBounds().y, caret.getBounds().width, getLineHeight(caretOffsets[i]));
- }
- }
- }
- }
-
- // fill the margin background
- gc.setBackground(marginColor != null ? marginColor : background);
- if (topMargin > 0) {
- drawBackground(gc, 0, 0, clientAreaWidth, topMargin);
- }
- if (bottomMargin > 0) {
- drawBackground(gc, 0, clientAreaHeight - bottomMargin, clientAreaWidth, bottomMargin);
- }
- if (leftMargin - alignmentMargin > 0) {
- drawBackground(gc, 0, 0, leftMargin - alignmentMargin, clientAreaHeight);
- }
- if (rightMargin > 0) {
- drawBackground(gc, clientAreaWidth - rightMargin, 0, rightMargin, clientAreaHeight);
- }
-}
-/**
- * Recalculates the scroll bars. Rewraps all lines when in word
- * wrap mode.
- *
- * @param event resize event
- */
-void handleResize(Event event) {
- int oldHeight = clientAreaHeight;
- int oldWidth = clientAreaWidth;
- Rectangle clientArea = getClientArea();
- clientAreaHeight = clientArea.height;
- clientAreaWidth = clientArea.width;
- if (!alwaysShowScroll && ignoreResize != 0) return;
-
- redrawMargins(oldHeight, oldWidth);
- if (wordWrap) {
- if (oldWidth != clientAreaWidth) {
- renderer.reset(0, content.getLineCount());
- verticalScrollOffset = -1;
- renderer.calculateIdle();
- super.redraw();
- }
- if (oldHeight != clientAreaHeight) {
- if (oldHeight == 0) topIndexY = 0;
- setScrollBars(true);
- }
- setCaretLocations();
- } else {
- renderer.calculateClientArea();
- setScrollBars(true);
- claimRightFreeSpace();
- // StyledText allows any value for horizontalScrollOffset when clientArea is zero
- // in setHorizontalPixel() and setHorisontalOffset(). Fixes bug 168429.
- if (clientAreaWidth != 0) {
- ScrollBar horizontalBar = getHorizontalBar();
- if (horizontalBar != null && horizontalBar.getVisible()) {
- if (horizontalScrollOffset != horizontalBar.getSelection()) {
- horizontalBar.setSelection(horizontalScrollOffset);
- horizontalScrollOffset = horizontalBar.getSelection();
- }
- }
- }
- }
- updateCaretVisibility();
- claimBottomFreeSpace();
- setAlignment();
- //TODO FIX TOP INDEX DURING RESIZE
-// if (oldHeight != clientAreaHeight || wordWrap) {
-// calculateTopIndex(0);
-// }
-}
-/**
- * Updates the caret position and selection and the scroll bars to reflect
- * the content change.
- */
-void handleTextChanged(TextChangedEvent event) {
- int offset = ime.getCompositionOffset();
- if (offset != -1 && lastTextChangeStart < offset) {
- // updating the compositionOffset of the ongoing IME if last IMEs text is deleted meanwhile
- // for example 1.insert IME text 2.open IME menu 3. ctrl+backspace => 4. commit IME would result in IllegalArgumentException
- int compositionOffset = ime.getCaretOffset() + lastTextChangeNewCharCount - lastTextChangeReplaceCharCount;
- // workaround: while ongoing IME non-ime text is deleted it may result in too big compositionOffset
- // for example 1.insert IME text 2.insert space 3.open IME menu 4. ctrl+backspace twice => 5. commit IME would result in IllegalArgumentException
- compositionOffset= Math.min(compositionOffset, getCharCount());
- ime.setCompositionOffset(compositionOffset);
- }
- int firstLine = content.getLineAtOffset(lastTextChangeStart);
- resetCache(firstLine, 0);
- if (!isFixedLineHeight() && topIndex > firstLine) {
- topIndex = firstLine;
- if (topIndex < 0) {
- // TODO: This logging is in place to determine why topIndex is getting set to negative values.
- // It should be deleted once we fix the root cause of this issue. See bug 487254 for details.
- System.err.println("StyledText: topIndex was " + topIndex
- + ", lastTextChangeStart = " + lastTextChangeStart
- + ", content.getClass() = " + content.getClass()
- );
- topIndex = 0;
- }
- topIndexY = 0;
- super.redraw();
- } else {
- int lastLine = firstLine + lastTextChangeNewLineCount;
- int firstLineTop = getLinePixel(firstLine);
- int newLastLineBottom = getLinePixel(lastLine + 1);
- if (lastLineBottom != newLastLineBottom) {
- super.redraw();
- } else {
- super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false);
- redrawLinesBullet(renderer.redrawLines);
- }
- }
- renderer.redrawLines = null;
- // update selection/caret location after styles have been changed.
- // otherwise any text measuring could be incorrect
- //
- // also, this needs to be done after all scrolling. Otherwise,
- // selection redraw would be flushed during scroll which is wrong.
- // in some cases new text would be drawn in scroll source area even
- // though the intent is to scroll it.
- if (!(blockSelection && blockXLocation != -1)) {
- updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount);
- }
- if (lastTextChangeReplaceLineCount > 0 || wordWrap || visualWrap) {
- claimBottomFreeSpace();
- }
- if (lastTextChangeReplaceCharCount > 0) {
- claimRightFreeSpace();
- }
-
- sendAccessibleTextChanged(lastTextChangeStart, lastTextChangeNewCharCount, 0);
- lastCharCount += lastTextChangeNewCharCount;
- lastCharCount -= lastTextChangeReplaceCharCount;
- setAlignment();
-}
-/**
- * Updates the screen to reflect a pending content change.
- *
- * @param event .start the start offset of the change
- * @param event .newText text that is going to be inserted or empty String
- * if no text will be inserted
- * @param event .replaceCharCount length of text that is going to be replaced
- * @param event .newCharCount length of text that is going to be inserted
- * @param event .replaceLineCount number of lines that are going to be replaced
- * @param event .newLineCount number of new lines that are going to be inserted
- */
-void handleTextChanging(TextChangingEvent event) {
- if (event.replaceCharCount < 0) {
- event.start += event.replaceCharCount;
- event.replaceCharCount *= -1;
- }
- lastTextChangeStart = event.start;
- lastTextChangeNewLineCount = event.newLineCount;
- lastTextChangeNewCharCount = event.newCharCount;
- lastTextChangeReplaceLineCount = event.replaceLineCount;
- lastTextChangeReplaceCharCount = event.replaceCharCount;
- int lineIndex = content.getLineAtOffset(event.start);
- int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1);
- int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight();
- lastLineBottom = destY;
- if (srcY < 0 && destY < 0) {
- lastLineBottom += srcY - destY;
- verticalScrollOffset += destY - srcY;
- calculateTopIndex(destY - srcY);
- setScrollBars(true);
- } else {
- scrollText(srcY, destY);
- }
- sendAccessibleTextChanged(lastTextChangeStart, 0, lastTextChangeReplaceCharCount);
- renderer.textChanging(event);
-
- // Update the caret offset if it is greater than the length of the content.
- // This is necessary since style range API may be called between the
- // handleTextChanging and handleTextChanged events and this API sets the
- // caretOffset.
- int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount;
- int tooBigOffsets = 0;
- while (tooBigOffsets < caretOffsets.length && caretOffsets[caretOffsets.length - 1 - tooBigOffsets] > newEndOfText) {
- tooBigOffsets++;
- }
- if (tooBigOffsets != 0) {
- int[] newCaretOffsets = Arrays.copyOf(caretOffsets, caretOffsets.length - tooBigOffsets + 1);
- newCaretOffsets[newCaretOffsets.length - 1] = newEndOfText;
- setCaretOffsets(newCaretOffsets, SWT.DEFAULT);
- }
-}
-/**
- * Called when the widget content is set programmatically, overwriting
- * the old content. Resets the caret position, selection and scroll offsets.
- * Recalculates the content width and scroll bars. Redraws the widget.
- *
- * @param event text change event.
- */
-void handleTextSet(TextChangedEvent event) {
- reset();
- int newCharCount = getCharCount();
- sendAccessibleTextChanged(0, newCharCount, lastCharCount);
- lastCharCount = newCharCount;
- setAlignment();
-}
-/**
- * Called when a traversal key is pressed.
- * Allow tab next traversal to occur when the widget is in single
- * line mode or in multi line and non-editable mode .
- * When in editable multi line mode we want to prevent the tab
- * traversal and receive the tab key event instead.
- *
- * @param event the event
- */
-void handleTraverse(Event event) {
- switch (event.detail) {
- case SWT.TRAVERSE_ESCAPE:
- case SWT.TRAVERSE_PAGE_NEXT:
- case SWT.TRAVERSE_PAGE_PREVIOUS:
- event.doit = true;
- break;
- case SWT.TRAVERSE_RETURN:
- case SWT.TRAVERSE_TAB_NEXT:
- case SWT.TRAVERSE_TAB_PREVIOUS:
- if ((getStyle() & SWT.SINGLE) != 0) {
- event.doit = true;
- } else {
- if (!editable || (event.stateMask & SWT.MODIFIER_MASK) != 0) {
- event.doit = true;
- }
- }
- break;
- }
-}
-/**
- * Scrolls the widget vertically.
- */
-void handleVerticalScroll(Event event) {
- int scrollPixel = getVerticalBar().getSelection() - getVerticalScrollOffset();
- scrollVertical(scrollPixel, false);
-}
-/**
- * Add accessibility support for the widget.
- */
-void initializeAccessible() {
- acc = getAccessible();
-
- accAdapter = new AccessibleAdapter() {
- @Override
- public void getName (AccessibleEvent e) {
- String name = null;
- String text = getAssociatedLabel ();
- if (text != null) {
- name = stripMnemonic (text);
- }
- e.result = name;
- }
- @Override
- public void getHelp(AccessibleEvent e) {
- e.result = getToolTipText();
- }
- @Override
- public void getKeyboardShortcut(AccessibleEvent e) {
- String shortcut = null;
- String text = getAssociatedLabel ();
- if (text != null) {
- char mnemonic = _findMnemonic (text);
- if (mnemonic != '\0') {
- shortcut = "Alt+"+mnemonic; //$NON-NLS-1$
- }
- }
- e.result = shortcut;
- }
- };
- acc.addAccessibleListener(accAdapter);
-
- accTextExtendedAdapter = new AccessibleTextExtendedAdapter() {
- @Override
- public void getCaretOffset(AccessibleTextEvent e) {
- e.offset = StyledText.this.getCaretOffset();
- }
- @Override
- public void setCaretOffset(AccessibleTextEvent e) {
- StyledText.this.setCaretOffset(e.offset);
- e.result = ACC.OK;
- }
- @Override
- public void getSelectionRange(AccessibleTextEvent e) {
- Point selection = StyledText.this.getSelectionRange();
- e.offset = selection.x;
- e.length = selection.y;
- }
- @Override
- public void addSelection(AccessibleTextEvent e) {
- StyledText st = StyledText.this;
- Point point = st.getSelection();
- if (point.x == point.y) {
- int end = e.end;
- if (end == -1) end = st.getCharCount();
- st.setSelection(e.start, end);
- e.result = ACC.OK;
- }
- }
- @Override
- public void getSelection(AccessibleTextEvent e) {
- StyledText st = StyledText.this;
- if (st.blockSelection && st.blockXLocation != -1) {
- Rectangle rect = st.getBlockSelectionPosition();
- int lineIndex = rect.y + e.index;
- int linePixel = st.getLinePixel(lineIndex);
- e.ranges = getRanges(rect.x, linePixel, rect.width, linePixel);
- if (e.ranges.length > 0) {
- e.start = e.ranges[0];
- e.end = e.ranges[e.ranges.length - 1];
- }
- } else {
- if (e.index == 0) {
- Point point = st.getSelection();
- e.start = point.x;
- e.end = point.y;
- if (e.start > e.end) {
- int temp = e.start;
- e.start = e.end;
- e.end = temp;
- }
- }
- }
- }
- @Override
- public void getSelectionCount(AccessibleTextEvent e) {
- StyledText st = StyledText.this;
- if (st.blockSelection && st.blockXLocation != -1) {
- Rectangle rect = st.getBlockSelectionPosition();
- e.count = rect.height - rect.y + 1;
- } else {
- Point point = st.getSelection();
- e.count = point.x == point.y ? 0 : 1;
- }
- }
- @Override
- public void removeSelection(AccessibleTextEvent e) {
- StyledText st = StyledText.this;
- if (e.index == 0) {
- if (st.blockSelection) {
- st.clearBlockSelection(true, false);
- } else {
- st.clearSelection(false);
- }
- e.result = ACC.OK;
- }
- }
- @Override
- public void setSelection(AccessibleTextEvent e) {
- if (e.index != 0) return;
- StyledText st = StyledText.this;
- Point point = st.getSelection();
- if (point.x == point.y) return;
- int end = e.end;
- if (end == -1) end = st.getCharCount();
- st.setSelection(e.start, end);
- e.result = ACC.OK;
- }
- @Override
- public void getCharacterCount(AccessibleTextEvent e) {
- e.count = StyledText.this.getCharCount();
- }
- @Override
- public void getOffsetAtPoint(AccessibleTextEvent e) {
- StyledText st = StyledText.this;
- Point point = new Point (e.x, e.y);
- Display display = st.getDisplay();
- point = display.map(null, st, point);
- e.offset = st.getOffsetAtPoint(point.x, point.y, null, true);
- }
- @Override
- public void getTextBounds(AccessibleTextEvent e) {
- StyledText st = StyledText.this;
- int start = e.start;
- int end = e.end;
- int contentLength = st.getCharCount();
- start = Math.max(0, Math.min(start, contentLength));
- end = Math.max(0, Math.min(end, contentLength));
- if (start > end) {
- int temp = start;
- start = end;
- end = temp;
- }
- int startLine = st.getLineAtOffset(start);
- int endLine = st.getLineAtOffset(end);
- Rectangle[] rects = new Rectangle[endLine - startLine + 1];
- Rectangle bounds = null;
- int index = 0;
- Display display = st.getDisplay();
- for (int lineIndex = startLine; lineIndex <= endLine; lineIndex++) {
- Rectangle rect = new Rectangle(0, 0, 0, 0);
- rect.y = st.getLinePixel(lineIndex);
- rect.height = st.renderer.getLineHeight(lineIndex);
- if (lineIndex == startLine) {
- rect.x = st.getPointAtOffset(start).x;
- } else {
- rect.x = st.leftMargin - st.horizontalScrollOffset;
- }
- if (lineIndex == endLine) {
- rect.width = st.getPointAtOffset(end).x - rect.x;
- } else {
- TextLayout layout = st.renderer.getTextLayout(lineIndex);
- rect.width = layout.getBounds().width - rect.x;
- st.renderer.disposeTextLayout(layout);
- }
- rects [index++] = rect = display.map(st, null, rect);
- if (bounds == null) {
- bounds = new Rectangle(rect.x, rect.y, rect.width, rect.height);
- } else {
- bounds.add(rect);
- }
- }
- e.rectangles = rects;
- if (bounds != null) {
- e.x = bounds.x;
- e.y = bounds.y;
- e.width = bounds.width;
- e.height = bounds.height;
- }
- }
- int[] getRanges(int left, int top, int right, int bottom) {
- StyledText st = StyledText.this;
- int lineStart = st.getLineIndex(top);
- int lineEnd = st.getLineIndex(bottom);
- int count = lineEnd - lineStart + 1;
- int[] ranges = new int [count * 2];
- int index = 0;
- for (int lineIndex = lineStart; lineIndex <= lineEnd; lineIndex++) {
- String line = st.content.getLine(lineIndex);
- int lineOffset = st.content.getOffsetAtLine(lineIndex);
- int lineEndOffset = lineOffset + line.length();
- int linePixel = st.getLinePixel(lineIndex);
- int start = st.getOffsetAtPoint(left, linePixel, null, true);
- if (start == -1) {
- start = left < st.leftMargin ? lineOffset : lineEndOffset;
- }
- int[] trailing = new int[1];
- int end = st.getOffsetAtPoint(right, linePixel, trailing, true);
- if (end == -1) {
- end = right < st.leftMargin ? lineOffset : lineEndOffset;
- } else {
- end += trailing[0];
- }
- if (start > end) {
- int temp = start;
- start = end;
- end = temp;
- }
- ranges[index++] = start;
- ranges[index++] = end;
- }
- return ranges;
- }
- @Override
- public void getRanges(AccessibleTextEvent e) {
- StyledText st = StyledText.this;
- Point point = new Point (e.x, e.y);
- Display display = st.getDisplay();
- point = display.map(null, st, point);
- e.ranges = getRanges(point.x, point.y, point.x + e.width, point.y + e.height);
- if (e.ranges.length > 0) {
- e.start = e.ranges[0];
- e.end = e.ranges[e.ranges.length - 1];
- }
- }
- @Override
- public void getText(AccessibleTextEvent e) {
- StyledText st = StyledText.this;
- int start = e.start;
- int end = e.end;
- int contentLength = st.getCharCount();
- if (end == -1) end = contentLength;
- start = Math.max(0, Math.min(start, contentLength));
- end = Math.max(0, Math.min(end, contentLength));
- if (start > end) {
- int temp = start;
- start = end;
- end = temp;
- }
- int count = e.count;
- switch (e.type) {
- case ACC.TEXT_BOUNDARY_ALL:
- //nothing to do
- break;
- case ACC.TEXT_BOUNDARY_CHAR: {
- int newCount = 0;
- if (count > 0) {
- while (count-- > 0) {
- int newEnd = st.getWordNext(end, SWT.MOVEMENT_CLUSTER);
- if (newEnd == contentLength) break;
- if (newEnd == end) break;
- end = newEnd;
- newCount++;
- }
- start = end;
- end = st.getWordNext(end, SWT.MOVEMENT_CLUSTER);
- } else {
- while (count++ < 0) {
- int newStart = st.getWordPrevious(start, SWT.MOVEMENT_CLUSTER);
- if (newStart == start) break;
- start = newStart;
- newCount--;
- }
- end = st.getWordNext(start, SWT.MOVEMENT_CLUSTER);
- }
- count = newCount;
- break;
- }
- case ACC.TEXT_BOUNDARY_WORD: {
- int newCount = 0;
- if (count > 0) {
- while (count-- > 0) {
- int newEnd = st.getWordNext(end, SWT.MOVEMENT_WORD_START, true);
- if (newEnd == end) break;
- newCount++;
- end = newEnd;
- }
- start = end;
- end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true);
- } else {
- if (st.getWordPrevious(Math.min(start + 1, contentLength), SWT.MOVEMENT_WORD_START, true) == start) {
- //start is a word start already
- count++;
- }
- while (count <= 0) {
- int newStart = st.getWordPrevious(start, SWT.MOVEMENT_WORD_START, true);
- if (newStart == start) break;
- count++;
- start = newStart;
- if (count != 0) newCount--;
- }
- if (count <= 0 && start == 0) {
- end = start;
- } else {
- end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true);
- }
- }
- count = newCount;
- break;
- }
- case ACC.TEXT_BOUNDARY_LINE:
- //TODO implement line
- case ACC.TEXT_BOUNDARY_PARAGRAPH:
- case ACC.TEXT_BOUNDARY_SENTENCE: {
- int offset = count > 0 ? end : start;
- int lineIndex = st.getLineAtOffset(offset) + count;
- lineIndex = Math.max(0, Math.min(lineIndex, st.getLineCount() - 1));
- start = st.getOffsetAtLine(lineIndex);
- String line = st.getLine(lineIndex);
- end = start + line.length();
- count = lineIndex - st.getLineAtOffset(offset);
- break;
- }
- }
- e.start = start;
- e.end = end;
- e.count = count;
- e.result = st.content.getTextRange(start, end - start);
- }
- @Override
- public void getVisibleRanges(AccessibleTextEvent e) {
- e.ranges = getRanges(leftMargin, topMargin, clientAreaWidth - rightMargin, clientAreaHeight - bottomMargin);
- if (e.ranges.length > 0) {
- e.start = e.ranges[0];
- e.end = e.ranges[e.ranges.length - 1];
- }
- }
- @Override
- public void scrollText(AccessibleTextEvent e) {
- StyledText st = StyledText.this;
- int topPixel = getTopPixel(), horizontalPixel = st.getHorizontalPixel();
- switch (e.type) {
- case ACC.SCROLL_TYPE_ANYWHERE:
- case ACC.SCROLL_TYPE_TOP_LEFT:
- case ACC.SCROLL_TYPE_LEFT_EDGE:
- case ACC.SCROLL_TYPE_TOP_EDGE: {
- Rectangle rect = st.getBoundsAtOffset(e.start);
- if (e.type != ACC.SCROLL_TYPE_TOP_EDGE) {
- horizontalPixel = horizontalPixel + rect.x - st.leftMargin;
- }
- if (e.type != ACC.SCROLL_TYPE_LEFT_EDGE) {
- topPixel = topPixel + rect.y - st.topMargin;
- }
- break;
- }
- case ACC.SCROLL_TYPE_BOTTOM_RIGHT:
- case ACC.SCROLL_TYPE_BOTTOM_EDGE:
- case ACC.SCROLL_TYPE_RIGHT_EDGE: {
- Rectangle rect = st.getBoundsAtOffset(e.end - 1);
- if (e.type != ACC.SCROLL_TYPE_BOTTOM_EDGE) {
- horizontalPixel = horizontalPixel - st.clientAreaWidth + rect.x + rect.width + st.rightMargin;
- }
- if (e.type != ACC.SCROLL_TYPE_RIGHT_EDGE) {
- topPixel = topPixel - st.clientAreaHeight + rect.y +rect.height + st.bottomMargin;
- }
- break;
- }
- case ACC.SCROLL_TYPE_POINT: {
- Point point = new Point(e.x, e.y);
- Display display = st.getDisplay();
- point = display.map(null, st, point);
- Rectangle rect = st.getBoundsAtOffset(e.start);
- topPixel = topPixel - point.y + rect.y;
- horizontalPixel = horizontalPixel - point.x + rect.x;
- break;
- }
- }
- st.setTopPixel(topPixel);
- st.setHorizontalPixel(horizontalPixel);
- e.result = ACC.OK;
- }
- };
- acc.addAccessibleTextListener(accTextExtendedAdapter);
-
- accEditableTextListener = new AccessibleEditableTextListener() {
- @Override
- public void setTextAttributes(AccessibleTextAttributeEvent e) {
- // This method must be implemented by the application
- e.result = ACC.OK;
- }
- @Override
- public void replaceText(AccessibleEditableTextEvent e) {
- StyledText st = StyledText.this;
- st.replaceTextRange(e.start, e.end - e.start, e.string);
- e.result = ACC.OK;
- }
- @Override
- public void pasteText(AccessibleEditableTextEvent e) {
- StyledText st = StyledText.this;
- st.setSelection(e.start);
- st.paste();
- e.result = ACC.OK;
- }
- @Override
- public void cutText(AccessibleEditableTextEvent e) {
- StyledText st = StyledText.this;
- st.setSelection(e.start, e.end);
- st.cut();
- e.result = ACC.OK;
- }
- @Override
- public void copyText(AccessibleEditableTextEvent e) {
- StyledText st = StyledText.this;
- st.setSelection(e.start, e.end);
- st.copy();
- e.result = ACC.OK;
- }
- };
- acc.addAccessibleEditableTextListener(accEditableTextListener);
-
- accAttributeAdapter = new AccessibleAttributeAdapter() {
- @Override
- public void getAttributes(AccessibleAttributeEvent e) {
- StyledText st = StyledText.this;
- e.leftMargin = st.getLeftMargin();
- e.topMargin = st.getTopMargin();
- e.rightMargin = st.getRightMargin();
- e.bottomMargin = st.getBottomMargin();
- e.tabStops = st.getTabStops();
- e.justify = st.getJustify();
- e.alignment = st.getAlignment();
- e.indent = st.getIndent();
- }
- @Override
- public void getTextAttributes(AccessibleTextAttributeEvent e) {
- StyledText st = StyledText.this;
- int contentLength = st.getCharCount();
- if (!isListening(ST.LineGetStyle) && st.renderer.styleCount == 0) {
- e.start = 0;
- e.end = contentLength;
- e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background);
- return;
- }
- int offset = Math.max(0, Math.min(e.offset, contentLength - 1));
- int lineIndex = st.getLineAtOffset(offset);
- int lineOffset = st.getOffsetAtLine(lineIndex);
- int lineCount = st.getLineCount();
- offset = offset - lineOffset;
-
- TextLayout layout = st.renderer.getTextLayout(lineIndex);
- int lineLength = layout.getText().length();
- if (lineLength > 0) {
- e.textStyle = layout.getStyle(Math.max(0, Math.min(offset, lineLength - 1)));
- }
-
- // If no override info available, use defaults. Don't supply default colors, though.
- if (e.textStyle == null) {
- e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background);
- } else {
- if (e.textStyle.foreground == null || e.textStyle.background == null || e.textStyle.font == null) {
- TextStyle textStyle = new TextStyle(e.textStyle);
- if (textStyle.foreground == null) textStyle.foreground = st.foreground;
- if (textStyle.background == null) textStyle.background = st.background;
- if (textStyle.font == null) textStyle.font = st.getFont();
- e.textStyle = textStyle;
- }
- }
-
- //offset at line delimiter case
- if (offset >= lineLength) {
- e.start = lineOffset + lineLength;
- if (lineIndex + 1 < lineCount) {
- e.end = st.getOffsetAtLine(lineIndex + 1);
- } else {
- e.end = contentLength;
- }
- return;
- }
-
- int[] ranges = layout.getRanges();
- st.renderer.disposeTextLayout(layout);
- int index = 0;
- int end = 0;
- while (index < ranges.length) {
- int styleStart = ranges[index++];
- int styleEnd = ranges[index++];
- if (styleStart <= offset && offset <= styleEnd) {
- e.start = lineOffset + styleStart;
- e.end = lineOffset + styleEnd + 1;
- return;
- }
- if (styleStart > offset) {
- e.start = lineOffset + end;
- e.end = lineOffset + styleStart;
- return;
- }
- end = styleEnd + 1;
- }
- if (index == ranges.length) {
- e.start = lineOffset + end;
- if (lineIndex + 1 < lineCount) {
- e.end = st.getOffsetAtLine(lineIndex + 1);
- } else {
- e.end = contentLength;
- }
- }
- }
- };
- acc.addAccessibleAttributeListener(accAttributeAdapter);
-
- accControlAdapter = new AccessibleControlAdapter() {
- @Override
- public void getRole(AccessibleControlEvent e) {
- e.detail = ACC.ROLE_TEXT;
- }
- @Override
- public void getState(AccessibleControlEvent e) {
- int state = 0;
- if (isEnabled()) state |= ACC.STATE_FOCUSABLE;
- if (isFocusControl()) state |= ACC.STATE_FOCUSED;
- if (!isVisible()) state |= ACC.STATE_INVISIBLE;
- if (!getEditable()) state |= ACC.STATE_READONLY;
- if (isSingleLine()) state |= ACC.STATE_SINGLELINE;
- else state |= ACC.STATE_MULTILINE;
- e.detail = state;
- }
- @Override
- public void getValue(AccessibleControlEvent e) {
- e.result = StyledText.this.getText();
- }
- };
- acc.addAccessibleControlListener(accControlAdapter);
-
- addListener(SWT.FocusIn, event -> acc.setFocus(ACC.CHILDID_SELF));
-
- addListener(SWT.Dispose, event -> {
- // Issue 448: A 3rd party program that uses Accessible may
- // cache obtained connection and query it even after StyledText
- // is disposed. Disconnect all listeners to avoid querying a
- // disposed control.
- acc.removeAccessibleControlListener(accControlAdapter);
- acc.removeAccessibleAttributeListener(accAttributeAdapter);
- acc.removeAccessibleEditableTextListener(accEditableTextListener);
- acc.removeAccessibleTextListener(accTextExtendedAdapter);
- acc.removeAccessibleListener(accAdapter);
- });
-}
-
-/*
- * Return the Label immediately preceding the receiver in the z-order,
- * or null if none.
- */
-String getAssociatedLabel () {
- Control[] siblings = getParent ().getChildren ();
- for (int i = 0; i < siblings.length; i++) {
- if (siblings [i] == StyledText.this) {
- if (i > 0) {
- Control sibling = siblings [i-1];
- if (sibling instanceof Label) return ((Label) sibling).getText();
- if (sibling instanceof CLabel) return ((CLabel) sibling).getText();
- }
- break;
- }
- }
- return null;
-}
-String stripMnemonic (String string) {
- int index = 0;
- int length = string.length ();
- do {
- while ((index < length) && (string.charAt (index) != '&')) index++;
- if (++index >= length) return string;
- if (string.charAt (index) != '&') {
- return string.substring(0, index-1) + string.substring(index, length);
- }
- index++;
- } while (index < length);
- return string;
-}
-/*
- * Return the lowercase of the first non-'&' character following
- * an '&' character in the given string. If there are no '&'
- * characters in the given string, return '\0'.
- */
-char _findMnemonic (String string) {
- if (string == null) return '\0';
- int index = 0;
- int length = string.length ();
- do {
- while (index < length && string.charAt (index) != '&') index++;
- if (++index >= length) return '\0';
- if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (index));
- index++;
- } while (index < length);
- return '\0';
-}
-/**
- * Executes the action.
- *
- * @param action one of the actions defined in ST.java
- */
-public void invokeAction(int action) {
- checkWidget();
- if (blockSelection && invokeBlockAction(action)) return;
- updateCaretDirection = true;
- switch (action) {
- // Navigation
- case ST.LINE_UP:
- doLineUp(false);
- clearSelection(true);
- break;
- case ST.LINE_DOWN:
- doLineDown(false);
- clearSelection(true);
- break;
- case ST.LINE_START:
- doLineStart();
- clearSelection(true);
- break;
- case ST.LINE_END:
- doLineEnd();
- clearSelection(true);
- break;
- case ST.COLUMN_PREVIOUS:
- doCursorPrevious();
- clearSelection(true);
- break;
- case ST.COLUMN_NEXT:
- doCursorNext();
- clearSelection(true);
- break;
- case ST.PAGE_UP:
- doPageUp(false, -1);
- clearSelection(true);
- break;
- case ST.PAGE_DOWN:
- doPageDown(false, -1);
- clearSelection(true);
- break;
- case ST.WORD_PREVIOUS:
- doWordPrevious();
- clearSelection(true);
- break;
- case ST.WORD_NEXT:
- doWordNext();
- clearSelection(true);
- break;
- case ST.TEXT_START:
- doContentStart();
- clearSelection(true);
- break;
- case ST.TEXT_END:
- doContentEnd();
- clearSelection(true);
- break;
- case ST.WINDOW_START:
- doPageStart();
- clearSelection(true);
- break;
- case ST.WINDOW_END:
- doPageEnd();
- clearSelection(true);
- break;
- // Selection
- case ST.SELECT_LINE_UP:
- doSelectionLineUp();
- break;
- case ST.SELECT_ALL:
- selectAll();
- break;
- case ST.SELECT_LINE_DOWN:
- doSelectionLineDown();
- break;
- case ST.SELECT_LINE_START:
- doLineStart();
- doSelection(ST.COLUMN_PREVIOUS);
- break;
- case ST.SELECT_LINE_END:
- doLineEnd();
- doSelection(ST.COLUMN_NEXT);
- break;
- case ST.SELECT_COLUMN_PREVIOUS:
- doSelectionCursorPrevious();
- doSelection(ST.COLUMN_PREVIOUS);
- break;
- case ST.SELECT_COLUMN_NEXT:
- doSelectionCursorNext();
- doSelection(ST.COLUMN_NEXT);
- break;
- case ST.SELECT_PAGE_UP:
- doSelectionPageUp(-1);
- break;
- case ST.SELECT_PAGE_DOWN:
- doSelectionPageDown(-1);
- break;
- case ST.SELECT_WORD_PREVIOUS:
- doSelectionWordPrevious();
- doSelection(ST.COLUMN_PREVIOUS);
- break;
- case ST.SELECT_WORD_NEXT:
- doSelectionWordNext();
- doSelection(ST.COLUMN_NEXT);
- break;
- case ST.SELECT_TEXT_START:
- doContentStart();
- doSelection(ST.COLUMN_PREVIOUS);
- break;
- case ST.SELECT_TEXT_END:
- doContentEnd();
- doSelection(ST.COLUMN_NEXT);
- break;
- case ST.SELECT_WINDOW_START:
- doPageStart();
- doSelection(ST.COLUMN_PREVIOUS);
- break;
- case ST.SELECT_WINDOW_END:
- doPageEnd();
- doSelection(ST.COLUMN_NEXT);
- break;
- // Modification
- case ST.CUT:
- cut();
- break;
- case ST.COPY:
- copy();
- break;
- case ST.PASTE:
- paste();
- break;
- case ST.DELETE_PREVIOUS:
- doBackspace();
- break;
- case ST.DELETE_NEXT:
- doDelete();
- break;
- case ST.DELETE_WORD_PREVIOUS:
- doDeleteWordPrevious();
- break;
- case ST.DELETE_WORD_NEXT:
- doDeleteWordNext();
- break;
- // Miscellaneous
- case ST.TOGGLE_OVERWRITE:
- overwrite = !overwrite; // toggle insert/overwrite mode
- break;
- case ST.TOGGLE_BLOCKSELECTION:
- setBlockSelection(!blockSelection);
- break;
- }
-}
-/**
-* Returns true if an action should not be performed when block
-* selection in active
-*/
-boolean invokeBlockAction(int action) {
- switch (action) {
- // Navigation
- case ST.LINE_UP:
- case ST.LINE_DOWN:
- case ST.LINE_START:
- case ST.LINE_END:
- case ST.COLUMN_PREVIOUS:
- case ST.COLUMN_NEXT:
- case ST.PAGE_UP:
- case ST.PAGE_DOWN:
- case ST.WORD_PREVIOUS:
- case ST.WORD_NEXT:
- case ST.TEXT_START:
- case ST.TEXT_END:
- case ST.WINDOW_START:
- case ST.WINDOW_END:
- clearBlockSelection(false, false);
- return false;
- // Selection
- case ST.SELECT_LINE_UP:
- doBlockLineVertical(true);
- return true;
- case ST.SELECT_LINE_DOWN:
- doBlockLineVertical(false);
- return true;
- case ST.SELECT_LINE_START:
- doBlockLineHorizontal(false);
- return true;
- case ST.SELECT_LINE_END:
- doBlockLineHorizontal(true);
- return false;
- case ST.SELECT_COLUMN_PREVIOUS:
- doBlockColumn(false);
- return true;
- case ST.SELECT_COLUMN_NEXT:
- doBlockColumn(true);
- return true;
- case ST.SELECT_WORD_PREVIOUS:
- doBlockWord(false);
- return true;
- case ST.SELECT_WORD_NEXT:
- doBlockWord(true);
- return true;
- case ST.SELECT_ALL:
- return false;
- case ST.SELECT_TEXT_START:
- doBlockContentStartEnd(false);
- break;
- case ST.SELECT_TEXT_END:
- doBlockContentStartEnd(true);
- break;
- case ST.SELECT_PAGE_UP:
- case ST.SELECT_PAGE_DOWN:
- case ST.SELECT_WINDOW_START:
- case ST.SELECT_WINDOW_END:
- //blocked actions
- return true;
- // Modification
- case ST.CUT:
- case ST.COPY:
- case ST.PASTE:
- return false;
- case ST.DELETE_PREVIOUS:
- case ST.DELETE_NEXT:
- if (blockXLocation != -1) {
- insertBlockSelectionText((char)0, action);
- return true;
- }
- return false;
- case ST.DELETE_WORD_PREVIOUS:
- case ST.DELETE_WORD_NEXT:
- //blocked actions
- return blockXLocation != -1;
- }
- return false;
-}
-boolean isBidiCaret() {
- return BidiUtil.isBidiPlatform();
-}
-boolean isFixedLineHeight() {
- return !isWordWrap() && lineSpacing == 0 && renderer.lineSpacingProvider == null && !hasStyleWithVariableHeight && !hasVerticalIndent;
-}
-/**
- * Returns whether the given offset is inside a multi byte line delimiter.
- * Example:
- * "Line1\r\n" isLineDelimiter(5) == false but isLineDelimiter(6) == true
- *
- * @return true if the given offset is inside a multi byte line delimiter.
- * false if the given offset is before or after a line delimiter.
- */
-boolean isLineDelimiter(int offset) {
- int line = content.getLineAtOffset(offset);
- int lineOffset = content.getOffsetAtLine(line);
- int offsetInLine = offset - lineOffset;
- // offsetInLine will be greater than line length if the line
- // delimiter is longer than one character and the offset is set
- // in between parts of the line delimiter.
- return offsetInLine > content.getLine(line).length();
-}
-/**
- * Returns whether the widget is mirrored (right oriented/right to left
- * writing order).
- *
- * @return isMirrored true=the widget is right oriented, false=the widget
- * is left oriented
- */
-boolean isMirrored() {
- return (getStyle() & SWT.MIRRORED) != 0;
-}
-/**
- * Returns true if any text in the widget is selected,
- * and false otherwise.
- *
- * @return the text selection state
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.103
- */
-public boolean isTextSelected() {
- checkWidget();
- if (blockSelection && blockXLocation != -1) {
- Rectangle rect = getBlockSelectionPosition();
- return !rect.isEmpty();
- }
- return Arrays.stream(selection).anyMatch(range -> range.x != range.y);
-}
-/**
- * Returns whether the widget can have only one line.
- *
- * @return true if widget can have only one line, false if widget can have
- * multiple lines
- */
-boolean isSingleLine() {
- return (getStyle() & SWT.SINGLE) != 0;
-}
-
-/**
- * Sends the specified verify event, replace/insert text as defined by
- * the event and send a modify event.
- *
- * @param event the text change event.
- *
- *
event.start - the replace start offset
- *
event.end - the replace end offset
- *
event.text - the new text
- *
- * @param updateCaret whether or not he caret should be set behind
- * the new text
- */
-void modifyContent(Event event, boolean updateCaret) {
- event.doit = true;
- notifyListeners(SWT.Verify, event);
- if (event.doit) {
- StyledTextEvent styledTextEvent = null;
- int replacedLength = event.end - event.start;
- if (isListening(ST.ExtendedModify)) {
- styledTextEvent = new StyledTextEvent(content);
- styledTextEvent.start = event.start;
- styledTextEvent.end = event.start + event.text.length();
- styledTextEvent.text = content.getTextRange(event.start, replacedLength);
- }
- if (updateCaret) {
- //Fix advancing flag for delete/backspace key on direction boundary
- if (event.text.length() == 0) {
- int lineIndex = content.getLineAtOffset(event.start);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- TextLayout layout = renderer.getTextLayout(lineIndex);
- int levelStart = layout.getLevel(event.start - lineOffset);
- int lineIndexEnd = content.getLineAtOffset(event.end);
- if (lineIndex != lineIndexEnd) {
- renderer.disposeTextLayout(layout);
- lineOffset = content.getOffsetAtLine(lineIndexEnd);
- layout = renderer.getTextLayout(lineIndexEnd);
- }
- int levelEnd = layout.getLevel(event.end - lineOffset);
- renderer.disposeTextLayout(layout);
- if (levelStart != levelEnd) {
- caretAlignment = PREVIOUS_OFFSET_TRAILING;
- } else {
- caretAlignment = OFFSET_LEADING;
- }
- }
- }
- content.replaceTextRange(event.start, replacedLength, event.text);
- // set the caret position prior to sending the modify event.
- // fixes 1GBB8NJ
- if (updateCaret && !(blockSelection && blockXLocation != -1)) {
- // always update the caret location. fixes 1G8FODP
- setSelection(Arrays.stream(selection).map(sel -> {
- if (sel.y < event.start || sel.x > event.end) {
- return sel;
- } else { // current range edited
- return new Point(event.start + event.text.length(), event.start + event.text.length());
- }
- }).flatMapToInt(p -> IntStream.of(p.x, p.y - p.x)).toArray(), true, false);
- showCaret();
- }
- notifyListeners(SWT.Modify, event);
- if (isListening(ST.ExtendedModify)) {
- notifyListeners(ST.ExtendedModify, styledTextEvent);
- }
- }
-}
-void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style, Bullet bullet, int bulletIndex) {
- if (isListening(ST.PaintObject)) {
- StyledTextEvent event = new StyledTextEvent (content) ;
- event.gc = gc;
- event.x = x;
- event.y = y;
- event.ascent = ascent;
- event.descent = descent;
- event.style = style;
- event.bullet = bullet;
- event.bulletIndex = bulletIndex;
- notifyListeners(ST.PaintObject, event);
- }
-}
-/**
- * Replaces the selection with the text on the DND.CLIPBOARD
- * clipboard or, if there is no selection, inserts the text at the current
- * caret offset. If the widget has the SWT.SINGLE style and the
- * clipboard text contains more than one line, only the first line without
- * line delimiters is inserted in the widget.
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public void paste(){
- checkWidget();
- String text = (String) getClipboardContent(DND.CLIPBOARD);
- if (text != null && text.length() > 0) {
- if (blockSelection) {
- boolean fillWithSpaces = isFixedLineHeight() && renderer.fixedPitch;
- int offset = insertBlockSelectionText(text, fillWithSpaces);
- setCaretOffsets(new int[] {offset}, SWT.DEFAULT);
- clearBlockSelection(true, true);
- setCaretLocations();
- return;
- } else if (getSelectionRanges().length / 2 > 1) { // multi selection
- insertMultiSelectionText(text);
- setCaretLocations();
- return;
- }
- Event event = new Event();
- event.start = selection[0].x;
- event.end = selection[0].y;
- String delimitedText = getModelDelimitedText(text);
- if (textLimit > 0) {
- int uneditedTextLength = getCharCount() - (selection[0].y - selection[0].x);
- if ((uneditedTextLength + delimitedText.length()) > textLimit) {
- int endIndex = textLimit - uneditedTextLength;
- delimitedText = delimitedText.substring(0, Math.max(endIndex, 0));
- }
- }
- event.text = delimitedText;
- sendKeyEvent(event);
- }
-}
-
-private void insertMultiSelectionText(String text) {
- String[] blocks = text.split(PlatformLineDelimiter);
- int[] ranges = getSelectionRanges();
- for (int i = ranges.length / 2 - 1; i >= 0; i --) {
- int offset = ranges[2 * i];
- int length = ranges[2 * i + 1];
- String toPaste = blocks.length > i ? blocks[i] : blocks[blocks.length - 1];
- Event event = new Event();
- event.start = offset;
- event.end = offset + length;
- event.text = toPaste;
- sendKeyEvent(event);
- }
-}
-
-private void pasteOnMiddleClick(Event event) {
- String text = (String)getClipboardContent(DND.SELECTION_CLIPBOARD);
- if (text != null && text.length() > 0) {
- // position cursor
- doMouseLocationChange(event.x, event.y, false);
- // insert text
- Event e = new Event();
- e.start = selection[0].x;
- e.end = selection[0].y;
- e.text = getModelDelimitedText(text);
- sendKeyEvent(e);
- }
-}
-/**
- * Prints the widget's text to the default printer.
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public void print() {
- checkWidget();
- Printer printer = new Printer();
- StyledTextPrintOptions options = new StyledTextPrintOptions();
- options.printTextForeground = true;
- options.printTextBackground = true;
- options.printTextFontStyle = true;
- options.printLineBackground = true;
- new Printing(this, printer, options).run();
- printer.dispose();
-}
-/**
- * Returns a runnable that will print the widget's text
- * to the specified printer.
- *
- * The runnable may be run in a non-UI thread.
- *
- *
- * @param printer the printer to print to
- *
- * @return a Runnable for printing the receiver's text
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when printer is null
- *
- */
-public Runnable print(Printer printer) {
- checkWidget();
- if (printer == null) {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
- StyledTextPrintOptions options = new StyledTextPrintOptions();
- options.printTextForeground = true;
- options.printTextBackground = true;
- options.printTextFontStyle = true;
- options.printLineBackground = true;
- return print(printer, options);
-}
-/**
- * Returns a runnable that will print the widget's text
- * to the specified printer.
- *
- * The runnable may be run in a non-UI thread.
- *
- *
- * @param printer the printer to print to
- * @param options print options to use during printing
- *
- * @return a Runnable for printing the receiver's text
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when printer or options is null
- *
- * @since 2.1
- */
-public Runnable print(Printer printer, StyledTextPrintOptions options) {
- checkWidget();
- if (printer == null || options == null) {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
- return new Printing(this, printer, options);
-}
-/**
- * Causes the entire bounds of the receiver to be marked
- * as needing to be redrawn. The next time a paint request
- * is processed, the control will be completely painted.
- *
- * Recalculates the content width for all lines in the bounds.
- * When a LineStyleListener is used a redraw call
- * is the only notification to the widget that styles have changed
- * and that the content width may have changed.
- *
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see Control#update()
- */
-@Override
-public void redraw() {
- super.redraw();
- int itemCount = getPartialBottomIndex() - topIndex + 1;
- renderer.reset(topIndex, itemCount);
- renderer.calculate(topIndex, itemCount);
- setScrollBars(false);
- doMouseLinkCursor();
-}
-/**
- * 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. If the all flag
- * is true, any children of the receiver which
- * intersect with the specified area will also paint their
- * intersecting areas. If the all flag is
- * false, the children will not be painted.
- *
- * Marks the content width of all lines in the specified rectangle
- * as unknown. Recalculates the content width of all visible lines.
- * When a LineStyleListener is used a redraw call
- * is the only notification to the widget that styles have changed
- * and that the content width may have changed.
- *
- *
- * @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 true if children should redraw, and false otherwise
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see Control#update()
- */
-@Override
-public void redraw(int x, int y, int width, int height, boolean all) {
- super.redraw(x, y, width, height, all);
- if (height > 0) {
- int firstLine = getLineIndex(y);
- int lastLine = getLineIndex(y + height);
- resetCache(firstLine, lastLine - firstLine + 1);
- doMouseLinkCursor();
- }
-}
-void redrawLines(int startLine, int lineCount, boolean bottomChanged) {
- // do nothing if redraw range is completely invisible
- int endLine = startLine + lineCount - 1;
- int partialBottomIndex = getPartialBottomIndex();
- int partialTopIndex = getPartialTopIndex();
- if (startLine > partialBottomIndex || endLine < partialTopIndex) {
- return;
- }
- // only redraw visible lines
- if (startLine < partialTopIndex) {
- startLine = partialTopIndex;
- }
- if (endLine > partialBottomIndex) {
- endLine = partialBottomIndex;
- }
- int redrawTop = getLinePixel(startLine);
- int redrawBottom = getLinePixel(endLine + 1);
- if (bottomChanged) redrawBottom = clientAreaHeight - bottomMargin;
- int redrawWidth = clientAreaWidth - leftMargin - rightMargin;
- super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true);
-}
-void redrawLinesBullet (int[] redrawLines) {
- if (redrawLines == null) return;
- int topIndex = getPartialTopIndex();
- int bottomIndex = getPartialBottomIndex();
- for (int redrawLine : redrawLines) {
- int lineIndex = redrawLine;
- if (!(topIndex <= lineIndex && lineIndex <= bottomIndex)) continue;
- int width = -1;
- Bullet bullet = renderer.getLineBullet(lineIndex, null);
- if (bullet != null) {
- StyleRange style = bullet.style;
- GlyphMetrics metrics = style.metrics;
- width = metrics.width;
- }
- if (width == -1) width = getClientArea().width;
- int height = renderer.getLineHeight(lineIndex);
- int y = getLinePixel(lineIndex);
- super.redraw(0, y, width, height, false);
- }
-}
-void redrawMargins(int oldHeight, int oldWidth) {
- /* Redraw the old or new right/bottom margin if needed */
- if (oldWidth != clientAreaWidth) {
- if (rightMargin > 0) {
- int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin;
- super.redraw(x, 0, rightMargin, oldHeight, false);
- }
- }
- if (oldHeight != clientAreaHeight) {
- if (bottomMargin > 0) {
- int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin;
- super.redraw(0, y, oldWidth, bottomMargin, false);
- }
- }
-}
-/**
- * Redraws the specified text range.
- *
- * @param start offset of the first character to redraw
- * @param length number of characters to redraw
- * @param clearBackground true if the background should be cleared as
- * part of the redraw operation. If true, the entire redraw range will
- * be cleared before anything is redrawn. If the redraw range includes
- * the last character of a line (i.e., the entire line is redrawn) the
- * line is cleared all the way to the right border of the widget.
- * The redraw operation will be faster and smoother if clearBackground
- * is set to false. Whether or not the flag can be set to false depends
- * on the type of change that has taken place. If font styles or
- * background colors for the redraw range have changed, clearBackground
- * should be set to true. If only foreground colors have changed for
- * the redraw range, clearBackground can be set to false.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
- *
- */
-public void redrawRange(int start, int length, boolean clearBackground) {
- checkWidget();
- int end = start + length;
- int contentLength = content.getCharCount();
- if (start > end || start < 0 || end > contentLength) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- int firstLine = content.getLineAtOffset(start);
- int lastLine = content.getLineAtOffset(end);
- resetCache(firstLine, lastLine - firstLine + 1);
- internalRedrawRange(start, length);
- doMouseLinkCursor();
-}
-/**
- * Removes the specified bidirectional segment listener.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- *
- * @since 2.0
- */
-public void removeBidiSegmentListener(BidiSegmentListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- removeTypedListener(ST.LineGetSegments, listener);
- resetCache(0, content.getLineCount());
- setCaretLocations();
- super.redraw();
-}
-/**
- * Removes the specified caret listener.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- *
- * @since 3.5
- */
-public void removeCaretListener(CaretListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- removeTypedListener(ST.CaretMoved, listener);
-}
-/**
- * Removes the specified extended modify listener.
- *
- * @param extendedModifyListener the listener which should no longer be notified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) {
- checkWidget();
- if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- removeTypedListener(ST.ExtendedModify, extendedModifyListener);
-}
-/**
- * Removes the specified line background listener.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void removeLineBackgroundListener(LineBackgroundListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- removeTypedListener(ST.LineGetBackground, listener);
-}
-/**
- * Removes the specified line style listener.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void removeLineStyleListener(LineStyleListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- removeTypedListener(ST.LineGetStyle, listener);
- setCaretLocations();
-}
-/**
- * Removes the specified modify listener.
- *
- * @param modifyListener the listener which should no longer be notified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void removeModifyListener(ModifyListener modifyListener) {
- checkWidget();
- if (modifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- removeTypedListener(SWT.Modify, modifyListener);
-}
-/**
- * Removes the specified listener.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- * @since 3.2
- */
-public void removePaintObjectListener(PaintObjectListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- removeTypedListener(ST.PaintObject, listener);
-}
-/**
- * Removes the listener from the collection of listeners who will
- * be notified when the user changes the receiver's selection.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT - if the listener is null
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see SelectionListener
- * @see #addSelectionListener
- */
-public void removeSelectionListener(SelectionListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- removeTypedListener(SWT.Selection, listener);
-}
-/**
- * Removes the specified verify listener.
- *
- * @param verifyListener the listener which should no longer be notified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void removeVerifyListener(VerifyListener verifyListener) {
- checkWidget();
- if (verifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- removeTypedListener(SWT.Verify, verifyListener);
-}
-/**
- * Removes the specified key verify listener.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void removeVerifyKeyListener(VerifyKeyListener listener) {
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- removeTypedListener(ST.VerifyKey, listener);
-}
-/**
- * Removes the specified word movement listener.
- *
- * @param listener the listener which should no longer be notified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- *
- * @see MovementEvent
- * @see MovementListener
- * @see #addWordMovementListener
- *
- * @since 3.3
- */
-
-public void removeWordMovementListener(MovementListener listener) {
- checkWidget();
- if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- removeTypedListener(ST.WordNext, listener);
- removeTypedListener(ST.WordPrevious, listener);
-}
-/**
- * Replaces the styles in the given range with new styles. This method
- * effectively deletes the styles in the given range and then adds the
- * the new styles.
- *
- * Note: Because a StyleRange includes the start and length, the
- * same instance cannot occur multiple times in the array of styles.
- * If the same style attributes, such as font and color, occur in
- * multiple StyleRanges, setStyleRanges(int, int, int[], StyleRange[])
- * can be used to share styles and reduce memory usage.
- *
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- *
- * @param start offset of first character where styles will be deleted
- * @param length length of the range to delete styles in
- * @param ranges StyleRange objects containing the new style information.
- * The ranges should not overlap and should be within the specified start
- * and length. The style rendering is undefined if the ranges do overlap
- * or are ill-defined. Must not be null.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
- *
ERROR_NULL_ARGUMENT when ranges is null
- *
- *
- * @since 2.0
- *
- * @see #setStyleRanges(int, int, int[], StyleRange[])
- */
-public void replaceStyleRanges(int start, int length, StyleRange[] ranges) {
- checkWidget();
- if (isListening(ST.LineGetStyle)) return;
- if (ranges == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- setStyleRanges(start, length, null, ranges, false);
-}
-/**
- * Replaces the given text range with new text.
- * If the widget has the SWT.SINGLE style and "text" contains more than
- * one line, only the first line is rendered but the text is stored
- * unchanged. A subsequent call to getText will return the same text
- * that was set. Note that only a single line of text should be set when
- * the SWT.SINGLE style is used.
- *
- * NOTE: During the replace operation the current selection is
- * changed as follows:
- *
- *
- *
selection before replaced text: selection unchanged
- *
selection after replaced text: adjust the selection so that same text
- * remains selected
- *
selection intersects replaced text: selection is cleared and caret
- * is placed after inserted text
- *
- *
- * @param start offset of first character to replace
- * @param length number of characters to replace. Use 0 to insert text
- * @param text new text. May be empty to delete text.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
- *
ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter.
- * Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported
- *
ERROR_NULL_ARGUMENT when string is null
- *
- */
-public void replaceTextRange(int start, int length, String text) {
- checkWidget();
- if (text == null) {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
- int contentLength = getCharCount();
- int end = start + length;
- if (start > end || start < 0 || end > contentLength) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- Event event = new Event();
- event.start = start;
- event.end = end;
- event.text = text;
- modifyContent(event, false);
-}
-/**
- * Resets the caret position, selection and scroll offsets. Recalculate
- * the content width and scroll bars. Redraw the widget.
- */
-void reset() {
- ScrollBar verticalBar = getVerticalBar();
- ScrollBar horizontalBar = getHorizontalBar();
- setCaretOffsets(new int[] {0}, SWT.DEFAULT);
- topIndex = 0;
- topIndexY = 0;
- verticalScrollOffset = 0;
- horizontalScrollOffset = 0;
- resetSelection();
- renderer.setContent(content);
- if (verticalBar != null) {
- verticalBar.setSelection(0);
- }
- if (horizontalBar != null) {
- horizontalBar.setSelection(0);
- }
- resetCache(0, 0);
- setCaretLocations();
- super.redraw();
-}
-void resetBidiData() {
- caretDirection = SWT.NULL;
- resetCache(0, content.getLineCount());
- setCaretLocations();
- keyActionMap.clear();
- createKeyBindings();
- super.redraw();
-}
-void resetCache(SortedSet lines) {
- if (lines == null || lines.isEmpty()) return;
- int maxLineIndex = renderer.maxWidthLineIndex;
- renderer.reset(lines);
- renderer.calculateClientArea();
- if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) {
- renderer.calculate(maxLineIndex, 1);
- }
- setScrollBars(true);
- if (!isFixedLineHeight()) {
- if (topIndex > lines.iterator().next()) {
- verticalScrollOffset = -1;
- }
- renderer.calculateIdle();
- }
-}
-void resetCache(int firstLine, int count) {
- int maxLineIndex = renderer.maxWidthLineIndex;
- renderer.reset(firstLine, count);
- renderer.calculateClientArea();
- if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) {
- renderer.calculate(maxLineIndex, 1);
- }
- setScrollBars(true);
- if (!isFixedLineHeight()) {
- if (topIndex > firstLine) {
- verticalScrollOffset = -1;
- }
- renderer.calculateIdle();
- }
-}
-/**
- * Resets the selection.
- */
-void resetSelection() {
- selection = Arrays.stream(caretOffsets).mapToObj(offset -> new Point(offset, offset)).toArray(Point[]::new);
- selectionAnchors = Arrays.copyOf(caretOffsets, caretOffsets.length);
- sendAccessibleTextCaretMoved();
-}
-
-@Override
-public void scroll(int destX, int destY, int x, int y, int width, int height, boolean all) {
- super.scroll(destX, destY, x, y, width, height, false);
- if (all) {
- int deltaX = destX - x, deltaY = destY - y;
- for (Control child : getChildren()) {
- Rectangle rect = child.getBounds();
- child.setLocation(rect.x + deltaX, rect.y + deltaY);
- }
- }
-}
-
-/**
- * Scrolls the widget horizontally.
- *
- * @param pixels number of SWT logical points to scroll, > 0 = scroll left,
- * < 0 scroll right
- * @param adjustScrollBar
- * true= the scroll thumb will be moved to reflect the new scroll offset.
- * false = the scroll thumb will not be moved
- * @return
- * true=the widget was scrolled
- * false=the widget was not scrolled, the given offset is not valid.
- */
-boolean scrollHorizontal(int pixels, boolean adjustScrollBar) {
- if (pixels == 0) return false;
- if (wordWrap) return false;
- ScrollBar horizontalBar = getHorizontalBar();
- if (horizontalBar != null && adjustScrollBar) {
- horizontalBar.setSelection(horizontalScrollOffset + pixels);
- }
- int scrollHeight = clientAreaHeight - topMargin - bottomMargin;
- if (pixels > 0) {
- int sourceX = leftMargin + pixels;
- int scrollWidth = clientAreaWidth - sourceX - rightMargin;
- if (scrollWidth > 0) {
- scroll(leftMargin, topMargin, sourceX, topMargin, scrollWidth, scrollHeight, true);
- }
- if (sourceX > scrollWidth) {
- super.redraw(leftMargin + scrollWidth, topMargin, pixels - scrollWidth, scrollHeight, true);
- }
- } else {
- int destinationX = leftMargin - pixels;
- int scrollWidth = clientAreaWidth - destinationX - rightMargin;
- if (scrollWidth > 0) {
- scroll(destinationX, topMargin, leftMargin, topMargin, scrollWidth, scrollHeight, true);
- }
- if (destinationX > scrollWidth) {
- super.redraw(leftMargin + scrollWidth, topMargin, -pixels - scrollWidth, scrollHeight, true);
- }
- }
- horizontalScrollOffset += pixels;
- setCaretLocations();
- return true;
-}
-/**
- * Scrolls the widget vertically.
- *
- * @param pixel the new vertical scroll offset
- * @param adjustScrollBar
- * true= the scroll thumb will be moved to reflect the new scroll offset.
- * false = the scroll thumb will not be moved
- * @return
- * true=the widget was scrolled
- * false=the widget was not scrolled
- */
-boolean scrollVertical(int pixels, boolean adjustScrollBar) {
- if (pixels == 0) {
- return false;
- }
- if (verticalScrollOffset != -1) {
- ScrollBar verticalBar = getVerticalBar();
- if (verticalBar != null && adjustScrollBar) {
- verticalBar.setSelection(verticalScrollOffset + pixels);
- }
- int deltaY = 0;
- if (pixels > 0) {
- int sourceY = topMargin + pixels;
- int scrollHeight = clientAreaHeight - sourceY - bottomMargin;
- if (scrollHeight > 0) {
- deltaY = -pixels;
- }
- } else {
- int destinationY = topMargin - pixels;
- int scrollHeight = clientAreaHeight - destinationY - bottomMargin;
- if (scrollHeight > 0) {
- deltaY = -pixels;
- }
- }
- Control[] children = getChildren();
- for (Control child : children) {
- Rectangle rect = child.getBounds();
- child.setLocation(rect.x, rect.y + deltaY);
- }
- verticalScrollOffset += pixels;
- calculateTopIndex(pixels);
- super.redraw();
- } else {
- calculateTopIndex(pixels);
- super.redraw();
- }
- setCaretLocations();
- return true;
-}
-void scrollText(int srcY, int destY) {
- if (srcY == destY) return;
- int deltaY = destY - srcY;
- int scrollWidth = clientAreaWidth - leftMargin - rightMargin, scrollHeight;
- if (deltaY > 0) {
- scrollHeight = clientAreaHeight - srcY - bottomMargin;
- } else {
- scrollHeight = clientAreaHeight - destY - bottomMargin;
- }
- scroll(leftMargin, destY, leftMargin, srcY, scrollWidth, scrollHeight, true);
- if ((0 < srcY + scrollHeight) && (topMargin > srcY)) {
- super.redraw(leftMargin, deltaY, scrollWidth, topMargin, false);
- }
- if ((0 < destY + scrollHeight) && (topMargin > destY)) {
- super.redraw(leftMargin, 0, scrollWidth, topMargin, false);
- }
- if ((clientAreaHeight - bottomMargin < srcY + scrollHeight) && (clientAreaHeight > srcY)) {
- super.redraw(leftMargin, clientAreaHeight - bottomMargin + deltaY, scrollWidth, bottomMargin, false);
- }
- if ((clientAreaHeight - bottomMargin < destY + scrollHeight) && (clientAreaHeight > destY)) {
- super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false);
- }
-}
-void sendAccessibleTextCaretMoved() {
- if (Arrays.stream(caretOffsets).noneMatch(caretOffset -> caretOffset == accCaretOffset)) {
- accCaretOffset = caretOffsets[0];
- getAccessible().textCaretMoved(caretOffsets[0]);
- }
-}
-void sendAccessibleTextChanged(int start, int newCharCount, int replaceCharCount) {
- Accessible accessible = getAccessible();
- if (replaceCharCount != 0) {
- accessible.textChanged(ACC.TEXT_DELETE, start, replaceCharCount);
- }
- if (newCharCount != 0) {
- accessible.textChanged(ACC.TEXT_INSERT, start, newCharCount);
- }
-}
-/**
- * Selects all the text.
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public void selectAll() {
- checkWidget();
- if (blockSelection) {
- renderer.calculate(0, content.getLineCount());
- setScrollBars(false);
- int verticalScrollOffset = getVerticalScrollOffset();
- int left = leftMargin - horizontalScrollOffset;
- int top = topMargin - verticalScrollOffset;
- int right = renderer.getWidth() - rightMargin - horizontalScrollOffset;
- int bottom = renderer.getHeight() - bottomMargin - verticalScrollOffset;
- setBlockSelectionLocation(left, top, right, bottom, false);
- return;
- }
- setSelection(0, Math.max(getCharCount(),0));
-}
-/**
- * Replaces/inserts text as defined by the event.
- *
- * @param event the text change event.
- *
- *
event.start - the replace start offset
- *
event.end - the replace end offset
- *
event.text - the new text
- *
- */
-void sendKeyEvent(Event event) {
- if (editable) {
- modifyContent(event, true);
- }
-}
-/**
- * Returns a StyledTextEvent that can be used to request data such
- * as styles and background color for a line.
- *
- * The specified line may be a visual (wrapped) line if in word
- * wrap mode. The returned object will always be for a logical
- * (unwrapped) line.
- *
- *
- * @param lineOffset offset of the line. This may be the offset of
- * a visual line if the widget is in word wrap mode.
- * @param line line text. This may be the text of a visual line if
- * the widget is in word wrap mode.
- * @return StyledTextEvent that can be used to request line data
- * for the given line.
- */
-StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) {
- StyledTextEvent event = null;
- if (isListening(eventType)) {
- event = new StyledTextEvent(content);
- event.detail = lineOffset;
- event.text = line;
- event.alignment = alignment;
- event.indent = indent;
- event.wrapIndent = wrapIndent;
- event.justify = justify;
- notifyListeners(eventType, event);
- }
- return event;
-}
-/**
- * Sends the specified selection event.
- */
-void sendSelectionEvent() {
- getAccessible().textSelectionChanged();
- Event event = new Event();
- event.x = selection[0].x;
- event.y = selection[selection.length - 1].y;
- notifyListeners(SWT.Selection, event);
-}
-int sendTextEvent(int left, int right, int lineIndex, String text, boolean fillWithSpaces) {
- int lineWidth = 0, start, end;
- StringBuilder buffer = new StringBuilder();
- if (lineIndex < content.getLineCount()) {
- int[] trailing = new int[1];
- start = getOffsetAtPoint(left, getLinePixel(lineIndex), trailing, true);
- if (start == -1) {
- int lineOffset = content.getOffsetAtLine(lineIndex);
- int lineLegth = content.getLine(lineIndex).length();
- start = end = lineOffset + lineLegth;
- if (fillWithSpaces) {
- TextLayout layout = renderer.getTextLayout(lineIndex);
- lineWidth = layout.getBounds().width;
- renderer.disposeTextLayout(layout);
- }
- } else {
- start += trailing[0];
- end = left == right ? start : getOffsetAtPoint(right, 0, lineIndex, null);
- fillWithSpaces = false;
- }
- } else {
- start = end = content.getCharCount();
- buffer.append(content.getLineDelimiter());
- }
- if (start > end) {
- int temp = start;
- start = end;
- end = temp;
- }
- if (fillWithSpaces) {
- int spacesWidth = left - lineWidth + horizontalScrollOffset - leftMargin;
- int spacesCount = spacesWidth / renderer.averageCharWidth;
- for (int i = 0; i < spacesCount; i++) {
- buffer.append(' ');
- }
- }
- buffer.append(text);
- Event event = new Event();
- event.start = start;
- event.end = end;
- event.text = buffer.toString();
- sendKeyEvent(event);
- return event.start + event.text.length();
-}
-int sendWordBoundaryEvent(int eventType, int movement, int offset, int newOffset, String lineText, int lineOffset) {
- if (isListening(eventType)) {
- StyledTextEvent event = new StyledTextEvent(content);
- event.detail = lineOffset;
- event.text = lineText;
- event.count = movement;
- event.start = offset;
- event.end = newOffset;
- notifyListeners(eventType, event);
- offset = event.end;
- if (offset != newOffset) {
- int length = getCharCount();
- if (offset < 0) {
- offset = 0;
- } else if (offset > length) {
- offset = length;
- } else {
- if (isLineDelimiter(offset)) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- }
- }
- return offset;
- }
- return newOffset;
-}
-void setAlignment() {
- if ((getStyle() & SWT.SINGLE) == 0) return;
- int alignment = renderer.getLineAlignment(0, this.alignment);
- int newAlignmentMargin = 0;
- if (alignment != SWT.LEFT) {
- renderer.calculate(0, 1);
- int width = renderer.getWidth() - alignmentMargin;
- newAlignmentMargin = clientAreaWidth - width;
- if (newAlignmentMargin < 0) newAlignmentMargin = 0;
- if (alignment == SWT.CENTER) newAlignmentMargin /= 2;
- }
- if (alignmentMargin != newAlignmentMargin) {
- leftMargin -= alignmentMargin;
- leftMargin += newAlignmentMargin;
- alignmentMargin = newAlignmentMargin;
- resetCache(0, 1);
- setCaretLocations();
- super.redraw();
- }
-}
-/**
- * Sets the alignment of the widget. The argument should be one of SWT.LEFT,
- * SWT.CENTER or SWT.RIGHT. The alignment applies for all lines.
- *
- * Note that if SWT.MULTI is set, then SWT.WRAP must also be set
- * in order to stabilize the right edge before setting alignment.
- *
- *
- * @param alignment the new alignment
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see #setLineAlignment(int, int, int)
- *
- * @since 3.2
- */
-public void setAlignment(int alignment) {
- checkWidget();
- alignment &= (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
- if (alignment == 0 || this.alignment == alignment) return;
- this.alignment = alignment;
- resetCache(0, content.getLineCount());
- setCaretLocations();
- setAlignment();
- super.redraw();
-}
-/**
- * Set the Always Show Scrollbars flag. True if the scrollbars are
- * always shown even if they are not required (default value). False if the scrollbars are only
- * visible when some part of the content needs to be scrolled to be seen.
- * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the
- * horizontal and vertical directions.
- *
- * @param show true to show the scrollbars even when not required, false to show scrollbars only when required
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.8
- */
-public void setAlwaysShowScrollBars(boolean show) {
- checkWidget();
- if (show == alwaysShowScroll) return;
- alwaysShowScroll = show;
- setScrollBars(true);
-}
-/**
- * @see Control#setBackground(Color)
- */
-@Override
-public void setBackground(Color color) {
- checkWidget();
- boolean backgroundDisabled = false;
- if (!this.enabled && color == null) {
- if (background != null) {
- Color disabledBg = getDisplay().getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND);
- if (background.equals(disabledBg)) {
- return;
- } else {
- color = new Color (disabledBg.getRGBA());
- backgroundDisabled = true;
- }
- }
- }
- customBackground = color != null && !this.insideSetEnableCall && !backgroundDisabled;
- background = color;
- super.setBackground(color);
- resetCache(0, content.getLineCount());
- setCaretLocations();
- super.redraw();
-}
-/**
- * Sets the block selection mode.
- *
- * @param blockSelection true=enable block selection, false=disable block selection
- *
- * @since 3.5
- */
-public void setBlockSelection(boolean blockSelection) {
- checkWidget();
- if ((getStyle() & SWT.SINGLE) != 0) return;
- if (blockSelection == this.blockSelection) return;
- if (wordWrap) return;
- this.blockSelection = blockSelection;
- if (cursor == null) {
- Display display = getDisplay();
- int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM;
- super.setCursor(display.getSystemCursor(type));
- }
- if (blockSelection) {
- int start = selection[0].x;
- int end = selection[0].y;
- if (start != end) {
- setBlockSelectionOffset(start, end, false);
- }
- } else {
- clearBlockSelection(false, false);
- }
-}
-/**
- * Sets the block selection bounds. The bounds is
- * relative to the upper left corner of the document.
- *
- * @param rect the new bounds for the block selection
- *
- * @see #setBlockSelectionBounds(int, int, int, int)
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when point is null
- *
- *
- * @since 3.5
- */
-public void setBlockSelectionBounds(Rectangle rect) {
- checkWidget();
- if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
- setBlockSelectionBounds(rect.x, rect.y, rect.width, rect.height);
-}
-/**
- * Sets the block selection bounds. The bounds is
- * relative to the upper left corner of the document.
- *
- * @param x the new x coordinate for the block selection
- * @param y the new y coordinate for the block selection
- * @param width the new width for the block selection
- * @param height the new height for the block selection
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public void setBlockSelectionBounds(int x, int y, int width, int height) {
- checkWidget();
- int verticalScrollOffset = getVerticalScrollOffset();
- if (!blockSelection) {
- x -= horizontalScrollOffset;
- y -= verticalScrollOffset;
- int start = getOffsetAtPoint(x, y, null);
- int end = getOffsetAtPoint(x+width-1, y+height-1, null);
- setSelection(new int[] {start, end - start}, false, false);
- setCaretLocations();
- return;
- }
- int minY = topMargin;
- int minX = leftMargin;
- int maxY = renderer.getHeight() - bottomMargin;
- int maxX = Math.max(clientAreaWidth, renderer.getWidth()) - rightMargin;
- int anchorX = Math.max(minX, Math.min(maxX, x)) - horizontalScrollOffset;
- int anchorY = Math.max(minY, Math.min(maxY, y)) - verticalScrollOffset;
- int locationX = Math.max(minX, Math.min(maxX, x + width)) - horizontalScrollOffset;
- int locationY = Math.max(minY, Math.min(maxY, y + height - 1)) - verticalScrollOffset;
- if (isFixedLineHeight() && renderer.fixedPitch) {
- int avg = renderer.averageCharWidth;
- anchorX = ((anchorX - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
- locationX = ((locationX + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
- }
- setBlockSelectionLocation(anchorX, anchorY, locationX, locationY, false);
-}
-void setBlockSelectionLocation (int x, int y, boolean sendEvent) {
- int verticalScrollOffset = getVerticalScrollOffset();
- blockXLocation = x + horizontalScrollOffset;
- blockYLocation = y + verticalScrollOffset;
- int[] alignment = new int[1];
- int offset = getOffsetAtPoint(x, y, alignment);
- setCaretOffsets(new int[] {offset}, alignment[0]);
- if (blockXAnchor == -1) {
- blockXAnchor = blockXLocation;
- blockYAnchor = blockYLocation;
- selectionAnchors[0] = caretOffsets[0];
- }
- doBlockSelection(sendEvent);
-}
-void setBlockSelectionLocation (int anchorX, int anchorY, int x, int y, boolean sendEvent) {
- int verticalScrollOffset = getVerticalScrollOffset();
- blockXAnchor = anchorX + horizontalScrollOffset;
- blockYAnchor = anchorY + verticalScrollOffset;
- selectionAnchors[0] = getOffsetAtPoint(anchorX, anchorY, null);
- setBlockSelectionLocation(x, y, sendEvent);
-}
-void setBlockSelectionOffset (int offset, boolean sendEvent) {
- Point point = getPointAtOffset(offset);
- int verticalScrollOffset = getVerticalScrollOffset();
- blockXLocation = point.x + horizontalScrollOffset;
- blockYLocation = point.y + verticalScrollOffset;
- setCaretOffsets(new int[] {offset}, SWT.DEFAULT);
- if (blockXAnchor == -1) {
- blockXAnchor = blockXLocation;
- blockYAnchor = blockYLocation;
- selectionAnchors[0] = caretOffsets[0];
- }
- doBlockSelection(sendEvent);
-}
-void setBlockSelectionOffset (int anchorOffset, int offset, boolean sendEvent) {
- int verticalScrollOffset = getVerticalScrollOffset();
- Point anchorPoint = getPointAtOffset(anchorOffset);
- blockXAnchor = anchorPoint.x + horizontalScrollOffset;
- blockYAnchor = anchorPoint.y + verticalScrollOffset;
- selectionAnchors[0] = anchorOffset;
- setBlockSelectionOffset(offset, sendEvent);
-}
-
-/**
- * Sets the receiver's caret. Set the caret's height and location.
- *
- * @param caret the new caret for the receiver
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-@Override
-public void setCaret(Caret caret) {
- checkWidget ();
- super.setCaret(caret);
- caretDirection = SWT.NULL;
- if (caret != null) {
- setCaretLocations();
- if(carets != null) {
- for (int i = 1; i < carets.length; i++) {
- carets[i].dispose();
- }
- }
- carets = new Caret[] {caret};
- } else {
- carets = null;
- }
-}
-/**
- * Sets the BIDI coloring mode. When true the BIDI text display
- * algorithm is applied to segments of text that are the same
- * color.
- *
- * @param mode the new coloring mode
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public void setBottomMargin (int bottomMargin) {
- checkWidget();
- setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin);
-}
-/**
- * Moves the Caret to the current caret offset.
- */
-void setCaretLocations() {
- Point[] newCaretPos = Arrays.stream(caretOffsets).mapToObj(this::getPointAtOffset).toArray(Point[]::new);
- setCaretLocations(newCaretPos, getCaretDirection());
-}
-void setCaretLocations(final Point[] locations, int direction) {
- Caret firstCaret = getCaret();
- if (firstCaret != null) {
- if (carets == null || carets.length == 0) {
- carets = new Caret[] { firstCaret };
- }
- final boolean isDefaultCaret = firstCaret == defaultCaret;
- if (locations.length > carets.length) {
- int formerCaretCount = carets.length;
- carets = Arrays.copyOf(carets, locations.length);
- for (int i = formerCaretCount; i < carets.length; i++) {
- carets[i] = new Caret(this, firstCaret.getStyle());
- carets[i].setImage(firstCaret.getImage());
- carets[i].setFont(firstCaret.getFont());
- carets[i].setSize(firstCaret.getSize());
- }
- } else if (locations.length < carets.length) {
- for (int i = locations.length; i < carets.length; i++) {
- carets[i].dispose();
- }
- carets = Arrays.copyOf(carets, locations.length);
- }
- for (int i = Math.min(caretOffsets.length, locations.length)-1; i>=0; i--) { // reverse order, seee bug 579028#c7
- final Caret caret = carets[i];
- final int caretOffset = caretOffsets[i];
- final Point location = locations[i];
- final StyleRange styleAtOffset = content.getCharCount() > 0 ?
- (caretOffset < content.getCharCount() ?
- getStyleRangeAtOffset(caretOffset) :
- getStyleRangeAtOffset(content.getCharCount() - 1)) : // caret after last char: use last char style
- null;
- final int caretLine = content.getLineAtOffset(caretOffset);
-
- int graphicalLineHeight = getLineHeight();
- final int lineStartOffset = getOffsetAtLine(caretLine);
- int graphicalLineFirstOffset = lineStartOffset;
- final int lineEndOffset = lineStartOffset + getLine(caretLine).length();
- int graphicalLineLastOffset = lineEndOffset;
- if (caretLine < getLineCount() && renderer.getLineHeight(caretLine) != getLineHeight()) { // word wrap, metrics, styles...
- graphicalLineHeight = getLineHeight(caretOffset);
- final Rectangle characterBounds = getBoundsAtOffset(caretOffset);
- graphicalLineFirstOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y));
- graphicalLineLastOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y + graphicalLineHeight)) - 1;
- if (graphicalLineLastOffset < graphicalLineFirstOffset) {
- graphicalLineLastOffset = getCharCount();
- }
- }
-
- int caretHeight = getLineHeight();
- boolean isTextAlignedAtBottom = true;
- if (graphicalLineFirstOffset >= 0) {
- for (StyleRange style : getStyleRanges(graphicalLineFirstOffset, graphicalLineLastOffset - graphicalLineFirstOffset)) {
- isTextAlignedAtBottom &= (
- (style.font == null || Objects.equals(style.font, getFont())) &&
- style.rise >= 0 &&
- (style.metrics == null || style.metrics.descent <= 0)
- );
- }
- }
- if (!isTextAlignedAtBottom || (styleAtOffset != null && styleAtOffset.isVariableHeight())) {
- if (isDefaultCaret) {
- direction = SWT.DEFAULT;
- caretHeight = graphicalLineHeight;
- } else {
- caretHeight = caret.getSize().y;
- }
- }
- if (isTextAlignedAtBottom && caretHeight < graphicalLineHeight) {
- location.y += (graphicalLineHeight - caretHeight);
- }
-
- int imageDirection = direction;
- if (isMirrored()) {
- if (imageDirection == SWT.LEFT) {
- imageDirection = SWT.RIGHT;
- } else if (imageDirection == SWT.RIGHT) {
- imageDirection = SWT.LEFT;
- }
- }
- if (isDefaultCaret && imageDirection == SWT.RIGHT) {
- location.x -= (caret.getSize().x - 1);
- }
- if (isDefaultCaret) {
- caret.setBounds(location.x, location.y, caretWidth, caretHeight);
- } else {
- caret.setLocation(location);
- }
- if (direction != caretDirection) {
- caretDirection = direction;
- if (isDefaultCaret) {
- if (imageDirection == SWT.DEFAULT) {
- defaultCaret.setImage(null);
- } else if (imageDirection == SWT.LEFT) {
- defaultCaret.setImage(leftCaretBitmap);
- } else if (imageDirection == SWT.RIGHT) {
- defaultCaret.setImage(rightCaretBitmap);
- }
- }
- if (caretDirection == SWT.LEFT) {
- BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_NON_BIDI);
- } else if (caretDirection == SWT.RIGHT) {
- BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI);
- }
- }
- }
- updateCaretVisibility();
- super.redraw();
- }
- columnX = locations[0].x;
-}
-/**
- * Sets the caret offset.
- *
- * @param offset caret offset, relative to the first character in the text.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the offset is inside a multi byte line
- * delimiter (and thus neither clearly in front of or after the line delimiter)
- *
- */
-public void setCaretOffset(int offset) {
- checkWidget();
- int length = getCharCount();
- if (length > 0 && !Arrays.equals(caretOffsets, new int[] {offset})) {
- if (offset < 0) {
- offset = 0;
- } else if (offset > length) {
- offset = length;
- } else {
- if (isLineDelimiter(offset)) {
- // offset is inside a multi byte line delimiter. This is an
- // illegal operation and an exception is thrown. Fixes 1GDKK3R
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- }
- setCaretOffsets(new int[] {offset}, PREVIOUS_OFFSET_TRAILING);
- // clear the selection if the caret is moved.
- // don't notify listeners about the selection change.
- if (blockSelection) {
- clearBlockSelection(true, false);
- } else {
- clearSelection(false);
- }
- }
- setCaretLocations();
-}
-void setCaretOffsets(int[] newOffsets, int alignment) {
- if (newOffsets.length > 1) {
- newOffsets = Arrays.stream(newOffsets).distinct().sorted().toArray();
- }
- if (!Arrays.equals(caretOffsets, newOffsets)) {
- caretOffsets = newOffsets;
- if (isListening(ST.CaretMoved)) {
- StyledTextEvent event = new StyledTextEvent(content);
- event.end = caretOffsets[caretOffsets.length - 1];
- notifyListeners(ST.CaretMoved, event);
- }
- }
- if (alignment != SWT.DEFAULT) {
- caretAlignment = alignment;
- }
-}
-/**
- * Copies the specified text range to the clipboard. The text will be placed
- * in the clipboard in plain text, HTML, and RTF formats.
- *
- * @param start start index of the text
- * @param length length of text to place in clipboard
- *
- * @exception SWTError
- * @see org.eclipse.swt.dnd.Clipboard#setContents
- */
-void setClipboardContent(int start, int length, int clipboardType) throws SWTError {
- if (clipboardType == DND.SELECTION_CLIPBOARD && !IS_GTK) return;
- TextTransfer plainTextTransfer = TextTransfer.getInstance();
- TextWriter plainTextWriter = new TextWriter(start, length);
- String plainText = getPlatformDelimitedText(plainTextWriter);
- Object[] data;
- Transfer[] types;
- if (clipboardType == DND.SELECTION_CLIPBOARD) {
- data = new Object[]{plainText};
- types = new Transfer[]{plainTextTransfer};
- } else {
- try {
- RTFTransfer rtfTransfer = RTFTransfer.getInstance();
- RTFWriter rtfWriter = new RTFWriter(this, start, length);
- String rtfText = getPlatformDelimitedText(rtfWriter);
-
- HTMLTransfer htmlTransfer = HTMLTransfer.getInstance();
- HTMLWriter htmlWriter = new HTMLWriter(this, start, length, content);
- String htmlText = getPlatformDelimitedText(htmlWriter);
- htmlText = "" +htmlText; //cause extra memory pressure to fail fast instead of failing in HTMLTransfer.javaToNative()
- data = new Object[]{rtfText, htmlText, plainText};
- types = new Transfer[]{rtfTransfer, htmlTransfer, plainTextTransfer};
- } catch (OutOfMemoryError oome) {
- // Adding RTF and HTML text may increase size by factor > 15
- // fall back: copy plain text
- data = new Object[] { plainText };
- types = new Transfer[] { plainTextTransfer };
- clipboard.setContents(data, types, clipboardType);
- OutOfMemoryError customOome = new OutOfMemoryError(
- "Out of Memory: Copied only plain text (" + plainText.lines().count() + " lines).");
- customOome.initCause(oome);
- // Still throw as it is likely that other threads silently failed too, but at least copied text is not lost
- throw customOome;
- }
- }
- clipboard.setContents(data, types, clipboardType);
-}
-/**
- * Sets the content implementation to use for text storage.
- *
- * @param newContent StyledTextContent implementation to use for text storage.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when listener is null
- *
- */
-public void setContent(StyledTextContent newContent) {
- checkWidget();
- if (newContent == null) {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
- if (content != null) {
- content.removeTextChangeListener(textChangeListener);
- }
- content = newContent;
- content.addTextChangeListener(textChangeListener);
- reset();
-}
-/**
- * Sets the receiver's cursor to the cursor specified by the
- * argument. Overridden to handle the null case since the
- * StyledText widget uses an ibeam as its default cursor.
- *
- * @see Control#setCursor(Cursor)
- */
-@Override
-public void setCursor (Cursor cursor) {
- checkWidget();
- if (cursor != null && cursor.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- this.cursor = cursor;
- if (cursor == null) {
- Display display = getDisplay();
- int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM;
- super.setCursor(display.getSystemCursor(type));
- } else {
- super.setCursor(cursor);
- }
-}
-/**
- * Sets whether the widget implements double click mouse behavior.
- *
- * @param enable if true double clicking a word selects the word, if false
- * double clicks have the same effect as regular mouse clicks.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public void setDoubleClickEnabled(boolean enable) {
- checkWidget();
- doubleClickEnabled = enable;
-}
-@Override
-public void setDragDetect (boolean dragDetect) {
- checkWidget ();
- this.dragDetect = dragDetect;
-}
-/**
- * Sets whether the widget content can be edited.
- *
- * @param editable if true content can be edited, if false content can not be
- * edited
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- * NOTE: Italic fonts are not supported unless they have no overhang
- * and the same baseline as regular fonts.
- *
- *
- * @param font new font
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-@Override
-public void setFont(Font font) {
- checkWidget();
- int oldLineHeight = renderer.getLineHeight();
- super.setFont(font);
- renderer.setFont(getFont(), tabLength);
- // keep the same top line visible. fixes 5815
- if (isFixedLineHeight()) {
- int lineHeight = renderer.getLineHeight();
- if (lineHeight != oldLineHeight) {
- int vscroll = (getVerticalScrollOffset() * lineHeight / oldLineHeight) - getVerticalScrollOffset();
- scrollVertical(vscroll, true);
- }
- }
- resetCache(0, content.getLineCount());
- claimBottomFreeSpace();
- calculateScrollBars();
- if (isBidiCaret()) createCaretBitmaps();
- caretDirection = SWT.NULL;
- setCaretLocations();
- super.redraw();
-}
-@Override
-public void setForeground(Color color) {
- checkWidget();
- boolean foregroundDisabled = false;
- if (!this.enabled && color == null) {
- if (foreground != null) {
- Color disabledFg = getDisplay().getSystemColor(SWT.COLOR_WIDGET_DISABLED_FOREGROUND);
- if (foreground.equals(disabledFg)) {
- return;
- } else {
- color = new Color (disabledFg.getRGBA());
- foregroundDisabled = true;
- }
- }
- }
- customForeground = color != null && !this.insideSetEnableCall && !foregroundDisabled;
- foreground = color;
- super.setForeground(color);
- resetCache(0, content.getLineCount());
- setCaretLocations();
- super.redraw();
-}
-/**
- * Sets the horizontal scroll offset relative to the start of the line.
- * Do nothing if there is no text set.
- *
- * NOTE: The horizontal index is reset to 0 when new text is set in the
- * widget.
- *
- *
- * @param offset horizontal scroll offset relative to the start
- * of the line, measured in character increments starting at 0, if
- * equal to 0 the content is not scrolled, if > 0 = the content is scrolled.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public void setHorizontalIndex(int offset) {
- checkWidget();
- if (getCharCount() == 0) {
- return;
- }
- if (offset < 0) {
- offset = 0;
- }
- offset *= getHorizontalIncrement();
- // allow any value if client area width is unknown or 0.
- // offset will be checked in resize handler.
- // don't use isVisible since width is known even if widget
- // is temporarily invisible
- if (clientAreaWidth > 0) {
- int width = renderer.getWidth();
- // prevent scrolling if the content fits in the client area.
- // align end of longest line with right border of client area
- // if offset is out of range.
- if (offset > width - clientAreaWidth) {
- offset = Math.max(0, width - clientAreaWidth);
- }
- }
- scrollHorizontal(offset - horizontalScrollOffset, true);
-}
-/**
- * Sets the horizontal SWT logical point offset relative to the start of the line.
- * Do nothing if there is no text set.
- *
- * NOTE: The horizontal SWT logical point offset is reset to 0 when new text
- * is set in the widget.
- *
- *
- * @param pixel horizontal SWT logical point offset relative to the start
- * of the line.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @since 2.0
- */
-public void setHorizontalPixel(int pixel) {
- checkWidget();
- if (getCharCount() == 0) {
- return;
- }
- if (pixel < 0) {
- pixel = 0;
- }
- // allow any value if client area width is unknown or 0.
- // offset will be checked in resize handler.
- // don't use isVisible since width is known even if widget
- // is temporarily invisible
- if (clientAreaWidth > 0) {
- int width = renderer.getWidth();
- // prevent scrolling if the content fits in the client area.
- // align end of longest line with right border of client area
- // if offset is out of range.
- if (pixel > width - clientAreaWidth) {
- pixel = Math.max(0, width - clientAreaWidth);
- }
- }
- scrollHorizontal(pixel - horizontalScrollOffset, true);
-}
-/**
- * Sets the line indentation of the widget.
- *
- * It is the amount of blank space, in points, at the beginning of each line.
- * When a line wraps in several lines only the first one is indented.
- *
- *
- * @param indent the new indent
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- * One action can be associated with N keys. However, each key can only
- * have one action (key:action is N:1 relation).
- *
- *
- * @param key a key code defined in SWT.java or a character.
- * Optionally ORd with a state mask. Preferred state masks are one or more of
- * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform
- * differences. However, there may be cases where using the specific state masks
- * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
- * @param action one of the predefined actions defined in ST.java.
- * Use SWT.NULL to remove a key binding.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public void setKeyBinding(int key, int action) {
- checkWidget();
- int modifierValue = key & SWT.MODIFIER_MASK;
- int keyInt = key & SWT.KEY_MASK;
- char keyChar = (char)keyInt;
- /**
- * Bug 440535: Make sure the key getting mapped to letter is in defiened
- * character range and filter out incorrect int to char typecasting. For
- * Example: SWT.KEYPAD_CR int gets wrongly type-cast to char letter 'p'
- */
- if (Character.isDefined(keyInt) && Character.isLetter(keyChar)) {
- // make the keybinding case insensitive by adding it
- // in its upper and lower case form
- char ch = Character.toUpperCase(keyChar);
- int newKey = ch | modifierValue;
- if (action == SWT.NULL) {
- keyActionMap.remove(newKey);
- } else {
- keyActionMap.put(newKey, action);
- }
- ch = Character.toLowerCase(keyChar);
- newKey = ch | modifierValue;
- if (action == SWT.NULL) {
- keyActionMap.remove(newKey);
- } else {
- keyActionMap.put(newKey, action);
- }
- } else {
- if (action == SWT.NULL) {
- keyActionMap.remove(key);
- } else {
- keyActionMap.put(key, action);
- }
- }
-}
-/**
- * Sets the left margin.
- *
- * @param leftMargin the left margin.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public void setLeftMargin (int leftMargin) {
- checkWidget();
- setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
-}
-/**
- * Sets the alignment of the specified lines. The argument should be one of SWT.LEFT,
- * SWT.CENTER or SWT.RIGHT.
- *
- * Note that if SWT.MULTI is set, then SWT.WRAP must also be set
- * in order to stabilize the right edge before setting alignment.
- *
- * Should not be called if a LineStyleListener has been set since the listener
- * maintains the line attributes.
- *
- * All line attributes are maintained relative to the line text, not the
- * line index that is specified in this method call.
- * During text changes, when entire lines are inserted or removed, the line
- * attributes that are associated with the lines after the change
- * will "move" with their respective text. An entire line is defined as
- * extending from the first character on a line to the last and including the
- * line delimiter.
- *
- * When two lines are joined by deleting a line delimiter, the top line
- * attributes take precedence and the attributes of the bottom line are deleted.
- * For all other text changes line attributes will remain unchanged.
- *
- * @param startLine first line the alignment is applied to, 0 based
- * @param lineCount number of lines the alignment applies to.
- * @param alignment line alignment
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
- *
- * @see #setAlignment(int)
- * @since 3.2
- */
-public void setLineAlignment(int startLine, int lineCount, int alignment) {
- checkWidget();
- if (isListening(ST.LineGetStyle)) return;
- if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
-
- renderer.setLineAlignment(startLine, lineCount, alignment);
- resetCache(startLine, lineCount);
- redrawLines(startLine, lineCount, false);
- if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) {
- setCaretLocations();
- }
- setAlignment();
-}
-/**
- * Sets the background color of the specified lines.
- *
- * The background color is drawn for the width of the widget. All
- * line background colors are discarded when setText is called.
- * The text background color if defined in a StyleRange overlays the
- * line background color.
- *
- * Should not be called if a LineBackgroundListener has been set since the
- * listener maintains the line backgrounds.
- *
- * All line attributes are maintained relative to the line text, not the
- * line index that is specified in this method call.
- * During text changes, when entire lines are inserted or removed, the line
- * attributes that are associated with the lines after the change
- * will "move" with their respective text. An entire line is defined as
- * extending from the first character on a line to the last and including the
- * line delimiter.
- *
- * When two lines are joined by deleting a line delimiter, the top line
- * attributes take precedence and the attributes of the bottom line are deleted.
- * For all other text changes line attributes will remain unchanged.
- *
- *
- * @param startLine first line the color is applied to, 0 based
- * @param lineCount number of lines the color applies to.
- * @param background line background color
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
- *
- */
-public void setLineBackground(int startLine, int lineCount, Color background) {
- checkWidget();
- if (isListening(ST.LineGetBackground)) return;
- if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- if (background != null) {
- renderer.setLineBackground(startLine, lineCount, background);
- } else {
- renderer.clearLineBackground(startLine, lineCount);
- }
- redrawLines(startLine, lineCount, false);
-}
-/**
- * Sets the bullet of the specified lines.
- *
- * Should not be called if a LineStyleListener has been set since the listener
- * maintains the line attributes.
- *
- * All line attributes are maintained relative to the line text, not the
- * line index that is specified in this method call.
- * During text changes, when entire lines are inserted or removed, the line
- * attributes that are associated with the lines after the change
- * will "move" with their respective text. An entire line is defined as
- * extending from the first character on a line to the last and including the
- * line delimiter.
- *
- * When two lines are joined by deleting a line delimiter, the top line
- * attributes take precedence and the attributes of the bottom line are deleted.
- * For all other text changes line attributes will remain unchanged.
- *
- *
- * @param startLine first line the bullet is applied to, 0 based
- * @param lineCount number of lines the bullet applies to.
- * @param bullet line bullet
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
- *
- * @since 3.2
- */
-public void setLineBullet(int startLine, int lineCount, Bullet bullet) {
- checkWidget();
- if (isListening(ST.LineGetStyle)) return;
- if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- int oldBottom = getLinePixel(startLine + lineCount);
- renderer.setLineBullet(startLine, lineCount, bullet);
- resetCache(startLine, lineCount);
- int newBottom = getLinePixel(startLine + lineCount);
- redrawLines(startLine, lineCount, oldBottom != newBottom);
- if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) {
- setCaretLocations();
- }
-}
-/**
- * Returns true if StyledText is in word wrap mode and false otherwise.
- *
- * @return true if StyledText is in word wrap mode and false otherwise.
- */
-boolean isWordWrap() {
- return wordWrap || visualWrap;
-}
-/**
- * Sets the indent of the specified lines.
- *
- * Should not be called if a LineStyleListener has been set since the listener
- * maintains the line attributes.
- *
- * All line attributes are maintained relative to the line text, not the
- * line index that is specified in this method call.
- * During text changes, when entire lines are inserted or removed, the line
- * attributes that are associated with the lines after the change
- * will "move" with their respective text. An entire line is defined as
- * extending from the first character on a line to the last and including the
- * line delimiter.
- *
- * When two lines are joined by deleting a line delimiter, the top line
- * attributes take precedence and the attributes of the bottom line are deleted.
- * For all other text changes line attributes will remain unchanged.
- *
- *
- * @param startLine first line the indent is applied to, 0 based
- * @param lineCount number of lines the indent applies to.
- * @param indent line indent
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
- * Should not be called if a LineStyleListener has been set since the listener
- * maintains the line attributes.
- *
- * All line attributes are maintained relative to the line text, not the
- * line index that is specified in this method call.
- * During text changes, when entire lines are inserted or removed, the line
- * attributes that are associated with the lines after the change
- * will "move" with their respective text. An entire line is defined as
- * extending from the first character on a line to the last and including the
- * line delimiter.
- *
- * When two lines are joined by deleting a line delimiter, the top line
- * attributes take precedence and the attributes of the bottom line are deleted.
- * For all other text changes line attributes will remain unchanged.
- *
- * Setting both line spacing and vertical indent on a line would result in the
- * spacing and indent add up for the line.
- *
- *
- * @param lineIndex line index the vertical indent is applied to, 0 based
- * @param verticalLineIndent vertical line indent
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the specified line index is invalid
- * Should not be called if a LineStyleListener has been set since the listener
- * maintains the line attributes.
- *
- * All line attributes are maintained relative to the line text, not the
- * line index that is specified in this method call.
- * During text changes, when entire lines are inserted or removed, the line
- * attributes that are associated with the lines after the change
- * will "move" with their respective text. An entire line is defined as
- * extending from the first character on a line to the last and including the
- * line delimiter.
- *
- * When two lines are joined by deleting a line delimiter, the top line
- * attributes take precedence and the attributes of the bottom line are deleted.
- * For all other text changes line attributes will remain unchanged.
- *
- *
- * @param startLine first line the justify is applied to, 0 based
- * @param lineCount number of lines the justify applies to.
- * @param justify true if lines should be justified
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
- *
- * @see #setJustify(boolean)
- * @since 3.2
- */
-public void setLineJustify(int startLine, int lineCount, boolean justify) {
- checkWidget();
- if (isListening(ST.LineGetStyle)) return;
- if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
-
- renderer.setLineJustify(startLine, lineCount, justify);
- resetCache(startLine, lineCount);
- redrawLines(startLine, lineCount, false);
- if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) {
- setCaretLocations();
- }
-}
-/**
- * Sets the line spacing of the widget. The line spacing applies for all lines.
- * In the case of #setLineSpacingProvider(StyledTextLineSpacingProvider) is customized,
- * the line spacing are applied only for the lines which are not managed by {@link StyledTextLineSpacingProvider}.
- *
- * @param lineSpacing the line spacing
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @see #setLineSpacingProvider(StyledTextLineSpacingProvider)
- * @since 3.2
- */
-public void setLineSpacing(int lineSpacing) {
- checkWidget();
- if (this.lineSpacing == lineSpacing || lineSpacing < 0) return;
- this.lineSpacing = lineSpacing;
- resetCache(0, content.getLineCount());
- setCaretLocations();
- super.redraw();
-}
-/**
- * Sets the line spacing provider of the widget. The line spacing applies for some lines with customized spacing
- * or reset the customized spacing if the argument is null.
- *
- * @param lineSpacingProvider the line spacing provider (or null)
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @see #setLineSpacingProvider(StyledTextLineSpacingProvider)
- * @since 3.107
- */
-public void setLineSpacingProvider(StyledTextLineSpacingProvider lineSpacingProvider) {
- checkWidget();
- boolean wasFixedLineHeight = isFixedLineHeight();
- if (renderer.getLineSpacingProvider() == null && lineSpacingProvider == null
- || (renderer.getLineSpacingProvider() != null
- && renderer.getLineSpacingProvider().equals(lineSpacingProvider)))
- return;
- renderer.setLineSpacingProvider(lineSpacingProvider);
- // reset lines cache if needed
- if (lineSpacingProvider == null) {
- if (!wasFixedLineHeight) {
- resetCache(0, content.getLineCount());
- }
- } else {
- if (wasFixedLineHeight) {
- int firstLine = -1;
- for (int i = 0; i < content.getLineCount(); i++) {
- Integer lineSpacing = lineSpacingProvider.getLineSpacing(i);
- if (lineSpacing != null && lineSpacing > 0) {
- // there is a custom line spacing, set StyledText as variable line height mode
- // reset only the line size
- renderer.reset(i, 1);
- if (firstLine == -1) {
- firstLine = i;
- }
- }
- }
- if (firstLine != -1) {
- // call reset cache for the first line which have changed to recompute scrollbars
- resetCache(firstLine, 0);
- }
- }
- }
- setCaretLocations();
- super.redraw();
-}
-/**
- * Sets the tab stops of the specified lines.
- *
- * Should not be called if a LineStyleListener has been set since the listener
- * maintains the line attributes.
- *
- * All line attributes are maintained relative to the line text, not the
- * line index that is specified in this method call.
- * During text changes, when entire lines are inserted or removed, the line
- * attributes that are associated with the lines after the change
- * will "move" with their respective text. An entire line is defined as
- * extending from the first character on a line to the last and including the
- * line delimiter.
- *
- * When two lines are joined by deleting a line delimiter, the top line
- * attributes take precedence and the attributes of the bottom line are deleted.
- * For all other text changes line attributes will remain unchanged.
- *
- *
- * @param startLine first line the justify is applied to, 0 based
- * @param lineCount number of lines the justify applies to.
- * @param tabStops tab stops
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
- *
- * @see #setTabStops(int[])
- * @since 3.6
- */
-public void setLineTabStops(int startLine, int lineCount, int[] tabStops) {
- checkWidget();
- if (isListening(ST.LineGetStyle)) return;
- if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- if (tabStops != null) {
- int pos = 0;
- int[] newTabs = new int[tabStops.length];
- for (int i = 0; i < tabStops.length; i++) {
- if (tabStops[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- newTabs[i] = pos = tabStops[i];
- }
- renderer.setLineTabStops(startLine, lineCount, newTabs);
- } else {
- renderer.setLineTabStops(startLine, lineCount, null);
- }
- resetCache(startLine, lineCount);
- redrawLines(startLine, lineCount, false);
- if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) {
- setCaretLocations();
- }
-}
-/**
- * Sets the wrap indent of the specified lines.
- *
- * Should not be called if a LineStyleListener has been set since the listener
- * maintains the line attributes.
- *
- * All line attributes are maintained relative to the line text, not the
- * line index that is specified in this method call.
- * During text changes, when entire lines are inserted or removed, the line
- * attributes that are associated with the lines after the change
- * will "move" with their respective text. An entire line is defined as
- * extending from the first character on a line to the last and including the
- * line delimiter.
- *
- * When two lines are joined by deleting a line delimiter, the top line
- * attributes take precedence and the attributes of the bottom line are deleted.
- * For all other text changes line attributes will remain unchanged.
- *
- *
- * @param startLine first line the wrap indent is applied to, 0 based
- * @param lineCount number of lines the wrap indent applies to.
- * @param wrapIndent line wrap indent
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
- *
- * @see #setWrapIndent(int)
- * @since 3.6
- */
-public void setLineWrapIndent(int startLine, int lineCount, int wrapIndent) {
- checkWidget();
- if (isListening(ST.LineGetStyle)) return;
- if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- int oldBottom = getLinePixel(startLine + lineCount);
- renderer.setLineWrapIndent(startLine, lineCount, wrapIndent);
- resetCache(startLine, lineCount);
- int newBottom = getLinePixel(startLine + lineCount);
- redrawLines(startLine, lineCount, oldBottom != newBottom);
- if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) {
- setCaretLocations();
- }
-}
-
-/**
- * Sets the color of the margins.
- *
- * @param color the new color (or null)
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public void setMarginColor(Color color) {
- checkWidget();
- if (color != null && color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- marginColor = color;
- super.redraw();
-}
-/**
- * Sets the margins.
- *
- * @param leftMargin the left margin.
- * @param topMargin the top margin.
- * @param rightMargin the right margin.
- * @param bottomMargin the bottom margin.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public void setMargins (int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
- checkWidget();
- this.leftMargin = Math.max(0, leftMargin) + alignmentMargin;
- this.topMargin = Math.max(0, topMargin);
- this.rightMargin = Math.max(0, rightMargin);
- this.bottomMargin = Math.max(0, bottomMargin);
- resetCache(0, content.getLineCount());
- setScrollBars(true);
- setCaretLocations();
- setAlignment();
- super.redraw();
-}
-/**
- * Sets the enabled state of the mouse navigator. When the mouse navigator is enabled, the user can navigate through the widget
- * by pressing the middle button and moving the cursor.
- *
- * @param enabled if true, the mouse navigator is enabled, if false the mouse navigator is deactivated
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @since 3.110
- */
-public void setMouseNavigatorEnabled(boolean enabled) {
- checkWidget();
- if ((enabled && mouseNavigator != null) || (!enabled && mouseNavigator == null)) {
- return;
- }
- if (enabled) {
- mouseNavigator = new MouseNavigator(this);
- } else {
- mouseNavigator.dispose();
- mouseNavigator = null;
- }
-}
-/**
- * Flips selection anchor based on word selection direction.
- */
-void setMouseWordSelectionAnchor() {
- if (doubleClickEnabled && clickCount > 1) {
- if (caretOffsets[0] < doubleClickSelection.x) {
- selectionAnchors[0] = doubleClickSelection.y;
- } else if (caretOffsets[0] > doubleClickSelection.y) {
- selectionAnchors[0] = doubleClickSelection.x;
- }
- }
-}
-/**
- * Sets the orientation of the receiver, which must be one
- * of the constants SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT.
- *
- * @param orientation new orientation style
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 2.1.2
- */
-@Override
-public void setOrientation(int orientation) {
- int oldOrientation = getOrientation();
- super.setOrientation(orientation);
- int newOrientation = getOrientation();
- if (oldOrientation != newOrientation) {
- resetBidiData();
- }
-}
-/**
- * Sets the right margin.
- *
- * @param rightMargin the right margin.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public void setRightMargin (int rightMargin) {
- checkWidget();
- setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin);
-}
-void setScrollBar(ScrollBar bar, int clientArea, int maximum, int margin) {
- int inactive = 1;
- if (clientArea < maximum) {
- bar.setMaximum(maximum - margin);
- bar.setThumb(clientArea - margin);
- bar.setPageIncrement(clientArea - margin);
- if (!alwaysShowScroll) bar.setVisible(true);
- } else if (bar.getThumb() != inactive || bar.getMaximum() != inactive) {
- bar.setValues(bar.getSelection(), bar.getMinimum(), inactive, inactive, bar.getIncrement(), inactive);
- }
-}
-/**
- * Adjusts the maximum and the page size of the scroll bars to
- * reflect content width/length changes.
- *
- * @param vertical indicates if the vertical scrollbar also needs to be set
- */
-void setScrollBars(boolean vertical) {
- ignoreResize++;
- if (!isFixedLineHeight() || !alwaysShowScroll) vertical = true;
- ScrollBar verticalBar = vertical ? getVerticalBar() : null;
- ScrollBar horizontalBar = getHorizontalBar();
- int oldHeight = clientAreaHeight;
- int oldWidth = clientAreaWidth;
- if (!alwaysShowScroll) {
- if (verticalBar != null) verticalBar.setVisible(false);
- if (horizontalBar != null) horizontalBar.setVisible(false);
- }
- if (verticalBar != null) {
- setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin);
- }
- if (horizontalBar != null && !wordWrap) {
- setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin);
- if (!alwaysShowScroll && horizontalBar.getVisible() && verticalBar != null) {
- setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin);
- if (verticalBar.getVisible()) {
- setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin);
- }
- }
- }
- if (!alwaysShowScroll) {
- redrawMargins(oldHeight, oldWidth);
- }
- ignoreResize--;
-}
-/**
- * Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start).
- *
- * @param start new caret position
- * @see #setSelection(int,int)
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
- * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
- *
- */
-public void setSelection(int start) {
- // checkWidget test done in setSelectionRange
- setSelection(start, start);
-}
-/**
- * Sets the selection and scrolls it into view.
- *
- * Indexing is zero based. Text selections are specified in terms of
- * caret positions. In a text widget that contains N characters, there are
- * N+1 caret positions, ranging from 0..N
- *
- *
- * @param point x=selection start offset, y=selection end offset
- * The caret will be placed at the selection start when x > y.
- * @see #setSelection(int,int)
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when point is null
- *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
- * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
- *
- */
-public void setSelection(Point point) {
- checkWidget();
- if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
- setSelection(point.x, point.y);
-}
-/**
- * Sets the receiver's selection 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
- *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @since 2.1
- */
-public void setSelectionBackground (Color color) {
- checkWidget ();
- if (color != null) {
- if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- selectionBackground = color;
- resetCache(0, content.getLineCount());
- setCaretLocations();
- super.redraw();
-}
-/**
- * Sets the receiver's selection foreground color to the color specified
- * by the argument, or to the default system color for the control
- * if the argument is null.
- *
- * Note that this is a HINT. Some platforms do not allow the application
- * to change the selection foreground color.
- *
- * @param color the new color (or null)
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @since 2.1
- */
-public void setSelectionForeground (Color color) {
- checkWidget ();
- if (color != null) {
- if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- selectionForeground = color;
- resetCache(0, content.getLineCount());
- setCaretLocations();
- super.redraw();
-}
-/**
- * Sets the selection and scrolls it into view.
- *
- * Indexing is zero based. Text selections are specified in terms of
- * caret positions. In a text widget that contains N characters, there are
- * N+1 caret positions, ranging from 0..N
- *
- *
- * @param start selection start offset. The caret will be placed at the
- * selection start when start > end.
- * @param end selection end offset
- * @see #setSelectionRange(int,int)
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
- * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
- *
- */
-public void setSelection(int start, int end) {
- setSelectionRange(start, end - start);
- showSelection();
-}
-/**
- * Sets the selection.
- *
- * The new selection may not be visible. Call showSelection to scroll
- * the selection into view.
- *
- *
- * @param start offset of the first selected character, start >= 0 must be true.
- * @param length number of characters to select, 0 <= start + length
- * <= getCharCount() must be true.
- * A negative length places the caret at the selection start.
- * @param sendEvent a Selection event is sent when set to true and when
- * the selection is reset.
- */
-void setSelection(int[] regions, boolean sendEvent, boolean doBlock) {
- if (regions.length == 2 && selection.length == 1) { // single range before/after
- int start = regions[0];
- int length = regions[1];
- int end = start + length;
- if (start > end) {
- int temp = end;
- end = start;
- start = temp;
- }
- int selectionAnchor = selectionAnchors[0];
- // is the selection range different or is the selection direction
- // different?
- if (selection[0].x != start || selection[0].y != end ||
- (length > 0 && selectionAnchor != selection[0].x) ||
- (length < 0 && selectionAnchor != selection[0].y)) {
- if (blockSelection && doBlock) {
- if (length < 0) {
- setBlockSelectionOffset(end, start, sendEvent);
- } else {
- setBlockSelectionOffset(start, end, sendEvent);
- }
- } else {
- int oldStart = selection[0].x;
- int oldLength = selection[0].y - selection[0].x;
- int charCount = content.getCharCount();
- // called internally to remove selection after text is removed
- // therefore make sure redraw range is valid.
- int redrawX = Math.min(selection[0].x, charCount);
- int redrawY = Math.min(selection[0].y, charCount);
- if (length < 0) {
- selectionAnchors[0] = selectionAnchor = selection[0].y = end;
- selection[0].x = start;
- setCaretOffsets(new int[] {start}, PREVIOUS_OFFSET_TRAILING);
- } else {
- selectionAnchors[0] = selectionAnchor = selection[0].x = start;
- selection[0].y = end;
- setCaretOffsets(new int[] {end}, PREVIOUS_OFFSET_TRAILING);
- }
- redrawX = Math.min(redrawX, selection[0].x);
- redrawY = Math.max(redrawY, selection[0].y);
- if (redrawY - redrawX > 0) {
- internalRedrawRange(redrawX, redrawY - redrawX);
- }
- if (sendEvent && (oldLength != end - start || (oldLength != 0 && oldStart != start))) {
- sendSelectionEvent();
- }
- sendAccessibleTextCaretMoved();
- }
- }
- } else if (!blockSelection || !doBlock) {
- boolean caretAtEndOfSelection = regions[1] > 0;
- int charCount = content.getCharCount();
- Point[] newRanges = new Point[regions.length / 2];
- for (int i = 0; i < regions.length; i += 2) {
- int start = regions[i];
- int length = regions[i + 1];
- int end = start + length;
- if (start > end) {
- int temp = end;
- end = start;
- start = temp;
- }
- newRanges[i / 2] = new Point(start, end);
- }
- Arrays.sort(newRanges, SELECTION_COMPARATOR);
- // merge contiguous ranges
- int newRangeIndex = 0;
- for (Point range : newRanges) {
- if (newRangeIndex > 0) {
- Point previousRange = newRanges[newRangeIndex - 1];
- if (previousRange.y >= range.x) {
- previousRange.y = Math.max(previousRange.y, range.y);
- } else {
- newRanges[newRangeIndex] = range;
- newRangeIndex++;
- }
- } else {
- newRanges[newRangeIndex] = range;
- newRangeIndex++;
- }
- }
- Point[] toRedraw = new Point[newRangeIndex + selection.length];
- System.arraycopy(newRanges, 0, toRedraw, 0, newRangeIndex);
- System.arraycopy(selection, 0, toRedraw, newRangeIndex, selection.length);
- Arrays.sort(toRedraw, SELECTION_COMPARATOR);
- Point[] formerSelection = selection;
- selection = Arrays.copyOf(newRanges, newRangeIndex);
- Point currentToRedraw = null;
- for (Point p : toRedraw) {
- if (currentToRedraw == null) {
- currentToRedraw = new Point(p.x, p.y);
- } else if (currentToRedraw.y >= p.x - 1) {
- // expand if necessary
- currentToRedraw = new Point(currentToRedraw.x, Math.max(p.y, currentToRedraw.y));
- } else {
- currentToRedraw = new Point(Math.max(0, currentToRedraw.x), Math.min(charCount, currentToRedraw.y));
- internalRedrawRange(currentToRedraw.x, currentToRedraw.y - currentToRedraw.x);
- currentToRedraw = null;
- }
- }
- if (currentToRedraw != null) {
- currentToRedraw = new Point(Math.max(0, currentToRedraw.x), Math.min(charCount, currentToRedraw.y));
- internalRedrawRange(currentToRedraw.x, currentToRedraw.y - currentToRedraw.x);
- }
- if (!caretAtEndOfSelection) {
- selectionAnchors = Arrays.stream(selection).mapToInt(p -> p.y).toArray();
- setCaretOffsets(Arrays.stream(selection).mapToInt(p -> p.x).toArray(), PREVIOUS_OFFSET_TRAILING);
- } else {
- selectionAnchors = Arrays.stream(selection).mapToInt(p -> p.x).toArray();
- setCaretOffsets(Arrays.stream(selection).mapToInt(p -> p.y).toArray(), PREVIOUS_OFFSET_TRAILING);
- }
- setCaretLocations();
- if (sendEvent && !Arrays.equals(formerSelection, selection)) {
- sendSelectionEvent();
- }
- sendAccessibleTextCaretMoved();
- }
-}
-/**
- * Sets the selection.
- *
- * The new selection may not be visible. Call showSelection to scroll the selection
- * into view. A negative length places the caret at the visual start of the selection.
- *
- *
- * @param start offset of the first selected character
- * @param length number of characters to select
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
- * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
- *
- * The new selection may not be visible. Call showSelection to scroll the selection
- * into view. A negative length places the caret at the visual start of the selection.
- *
- *
- * @param ranges an array of offset/length pairs.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT when either the start or the end of one selection range is inside a
- * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
- *
ERROR_INVALID_ARGUMENT when ranges are null or size isn't valid (not pair)
- *
- * @see #getSelectionRanges()
- * @since 3.117
- */
-public void setSelectionRanges(int[] ranges) {
- checkWidget();
- int contentLength = getCharCount();
- if (ranges.length % 2 != 0) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- int[] fixedRanges = Arrays.copyOf(ranges, ranges.length);
- for (int i = 0; i < ranges.length; i+=2) {
- int start = ranges[i];
- start = Math.max(0, Math.min(start, contentLength));
- int length = ranges[i + 1];
- int end = start + length;
- if (end < 0) {
- length = -start;
- } else if (end > contentLength) {
- length = contentLength - start;
- }
- if (isLineDelimiter(start) || isLineDelimiter(start + length)) {
- // the start offset or end offset of the selection range is inside a
- // multi byte line delimiter. This is an illegal operation and an exception
- // is thrown. Fixes 1GDKK3R
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- fixedRanges[i] = start;
- fixedRanges[i + 1] = length;
- }
- setSelection(fixedRanges, false, true);
- setCaretLocations();
-}
-
-/**
- * Adds the specified style.
- *
- * The new style overwrites existing styles for the specified range.
- * Existing style ranges are adjusted if they partially overlap with
- * the new style. To clear an individual style, call setStyleRange
- * with a StyleRange that has null attributes.
- *
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- *
- * @param range StyleRange object containing the style information.
- * Overwrites the old style in the given range. May be null to delete
- * all styles.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())
- *
- */
-public void setStyleRange(StyleRange range) {
- checkWidget();
- if (isListening(ST.LineGetStyle)) return;
- if (range != null) {
- if (range.isUnstyled()) {
- setStyleRanges(range.start, range.length, null, null, false);
- } else {
- setStyleRanges(range.start, 0, null, new StyleRange[]{range}, false);
- }
- } else {
- setStyleRanges(0, 0, null, null, true);
- }
-}
-/**
- * Clears the styles in the range specified by start and
- * length and adds the new styles.
- *
- * The ranges array contains start and length pairs. Each pair refers to
- * the corresponding style in the styles array. For example, the pair
- * that starts at ranges[n] with length ranges[n+1] uses the style
- * at styles[n/2]. The range fields within each StyleRange are ignored.
- * If ranges or styles is null, the specified range is cleared.
- *
- * Note: It is expected that the same instance of a StyleRange will occur
- * multiple times within the styles array, reducing memory usage.
- *
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- *
- * @param start offset of first character where styles will be deleted
- * @param length length of the range to delete styles in
- * @param ranges the array of ranges. The ranges must not overlap and must be in order.
- * @param styles the array of StyleRanges. The range fields within the StyleRange are unused.
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when an element in the styles array is null
- *
ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
- *
ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
- *
ERROR_INVALID_RANGE when a range overlaps
- *
- *
- * @since 3.2
- */
-public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) {
- checkWidget();
- if (isListening(ST.LineGetStyle)) return;
- if (ranges == null || styles == null) {
- setStyleRanges(start, length, null, null, false);
- } else {
- setStyleRanges(start, length, ranges, styles, false);
- }
-}
-/**
- * Sets styles to be used for rendering the widget content.
- *
- * All styles in the widget will be replaced with the given set of ranges and styles.
- * The ranges array contains start and length pairs. Each pair refers to
- * the corresponding style in the styles array. For example, the pair
- * that starts at ranges[n] with length ranges[n+1] uses the style
- * at styles[n/2]. The range fields within each StyleRange are ignored.
- * If either argument is null, the styles are cleared.
- *
- * Note: It is expected that the same instance of a StyleRange will occur
- * multiple times within the styles array, reducing memory usage.
- *
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- *
- * @param ranges the array of ranges. The ranges must not overlap and must be in order.
- * @param styles the array of StyleRanges. The range fields within the StyleRange are unused.
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when an element in the styles array is null
- *
ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
- *
ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
- *
ERROR_INVALID_RANGE when a range overlaps
- *
- *
- * @since 3.2
- */
-public void setStyleRanges(int[] ranges, StyleRange[] styles) {
- checkWidget();
- if (isListening(ST.LineGetStyle)) return;
- if (ranges == null || styles == null) {
- setStyleRanges(0, 0, null, null, true);
- } else {
- setStyleRanges(0, 0, ranges, styles, true);
- }
-}
-void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles, boolean reset) {
- int charCount = content.getCharCount();
- if (reset) {
- start = 0;
- length = charCount;
- }
- int[] formerRanges = getRanges(start, length);
- StyleRange[] formerStyles = getStyleRanges(start, length);
- int end = start + length;
- final boolean wasFixedLineHeight = isFixedLineHeight();
- if (start > end || start < 0) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- if (styles != null) {
- if (end > charCount) {
- SWT.error(SWT.ERROR_INVALID_RANGE);
- }
- if (ranges != null) {
- if (ranges.length != styles.length << 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- int lastOffset = 0;
- for (int i = 0; i < styles.length; i ++) {
- if (styles[i] == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- int rangeStart, rangeLength;
- if (ranges != null) {
- rangeStart = ranges[i << 1];
- rangeLength = ranges[(i << 1) + 1];
- } else {
- rangeStart = styles[i].start;
- rangeLength = styles[i].length;
- }
- if (rangeLength < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- if (lastOffset > rangeStart) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- hasStyleWithVariableHeight |= styles[i].isVariableHeight();
- lastOffset = rangeStart + rangeLength;
- }
- }
- int rangeStart = start, rangeEnd = end;
- if (styles != null && styles.length > 0) {
- if (ranges != null) {
- rangeStart = ranges[0];
- rangeEnd = ranges[ranges.length - 2] + ranges[ranges.length - 1];
- } else {
- rangeStart = styles[0].start;
- rangeEnd = styles[styles.length - 1].start + styles[styles.length - 1].length;
- }
- }
+// String line = content.getLine(i);
+// int lineOffset = content.getOffsetAtLine(i);
+// StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line);
+// if (event != null && event.lineBackground != null) {
+// printerRenderer.setLineBackground(i, 1, event.lineBackground);
+// }
+// event = styledText.getBidiSegments(lineOffset, line);
+// if (event != null) {
+// printerRenderer.setLineSegments(i, 1, event.segments);
+// printerRenderer.setLineSegmentChars(i, 1, event.segmentsChars);
+// }
+// event = styledText.getLineStyleData(lineOffset, line);
+// if (event != null) {
+// printerRenderer.setLineIndent(i, 1, event.indent);
+// printerRenderer.setLineAlignment(i, 1, event.alignment);
+// printerRenderer.setLineJustify(i, 1, event.justify);
+// printerRenderer.setLineBullet(i, 1, event.bullet);
+// StyleRange[] styles = event.styles;
+// if (styles != null && styles.length > 0) {
+// printerRenderer.setStyleRanges(event.ranges, styles);
+// }
+// }
+// }
+// }
+// Point screenDPI = styledText.getDisplay().getDPI();
+// Point printerDPI = printer.getDPI();
+// resources = new HashMap<> ();
+// for (int i = 0; i < lineCount; i++) {
+// Color color = printerRenderer.getLineBackground(i, null);
+// if (color != null) {
+// if (printOptions.printLineBackground) {
+// Color printerColor = (Color)resources.get(color);
+// if (printerColor == null) {
+// printerColor = new Color (color.getRGB());
+// resources.put(color, printerColor);
+// }
+// printerRenderer.setLineBackground(i, 1, printerColor);
+// } else {
+// printerRenderer.setLineBackground(i, 1, null);
+// }
+// }
+// int indent = printerRenderer.getLineIndent(i, 0);
+// if (indent != 0) {
+// printerRenderer.setLineIndent(i, 1, indent * printerDPI.x / screenDPI.x);
+// }
+// }
+// StyleRange[] styles = printerRenderer.styles;
+// for (int i = 0; i < printerRenderer.styleCount; i++) {
+// StyleRange style = styles[i];
+// Font font = style.font;
+// if (style.font != null) {
+// Font printerFont = (Font)resources.get(font);
+// if (printerFont == null) {
+// printerFont = new Font (printer, font.getFontData());
+// resources.put(font, printerFont);
+// }
+// style.font = printerFont;
+// }
+// Color color = style.foreground;
+// if (color != null) {
+// Color printerColor = (Color)resources.get(color);
+// if (printOptions.printTextForeground) {
+// if (printerColor == null) {
+// printerColor = new Color (color.getRGB());
+// resources.put(color, printerColor);
+// }
+// style.foreground = printerColor;
+// } else {
+// style.foreground = null;
+// }
+// }
+// color = style.background;
+// if (color != null) {
+// Color printerColor = (Color)resources.get(color);
+// if (printOptions.printTextBackground) {
+// if (printerColor == null) {
+// printerColor = new Color (color.getRGB());
+// resources.put(color, printerColor);
+// }
+// style.background = printerColor;
+// } else {
+// style.background = null;
+// }
+// }
+// if (!printOptions.printTextFontStyle) {
+// style.fontStyle = SWT.NORMAL;
+// }
+// style.rise = style.rise * printerDPI.y / screenDPI.y;
+// GlyphMetrics metrics = style.metrics;
+// if (metrics != null) {
+// metrics.ascent = metrics.ascent * printerDPI.y / screenDPI.y;
+// metrics.descent = metrics.descent * printerDPI.y / screenDPI.y;
+// metrics.width = metrics.width * printerDPI.x / screenDPI.x;
+// }
+// }
+// lineSpacing = styledText.lineSpacing * printerDPI.y / screenDPI.y;
+// if (printOptions.printLineNumbers) {
+// printMargin = 3 * printerDPI.x / screenDPI.x;
+// }
+// }
+// /**
+// * Copies the text of the specified StyledTextContent.
+// *
+// * @param original the StyledTextContent to copy.
+// */
+// StyledTextContent copyContent(StyledTextContent original) {
+// StyledTextContent printerContent = new DefaultContent();
+// int insertOffset = 0;
+// for (int i = 0; i < original.getLineCount(); i++) {
+// int insertEndOffset;
+// if (i < original.getLineCount() - 1) {
+// insertEndOffset = original.getOffsetAtLine(i + 1);
+// } else {
+// insertEndOffset = original.getCharCount();
+// }
+// printerContent.replaceTextRange(insertOffset, 0, original.getTextRange(insertOffset, insertEndOffset - insertOffset));
+// insertOffset = insertEndOffset;
+// }
+// return printerContent;
+// }
+// /**
+// * Disposes of the resources and the PrintRenderer.
+// */
+// void dispose() {
+// if (gc != null) {
+// gc.dispose();
+// gc = null;
+// }
+// if (resources != null) {
+// for (Resource resource : resources.values()) {
+// resource.dispose();
+// }
+// resources = null;
+// }
+// if (printerFont != null) {
+// printerFont.dispose();
+// printerFont = null;
+// }
+// if (printerRenderer != null) {
+// printerRenderer.dispose();
+// printerRenderer = null;
+// }
+// }
+// void init() {
+// Rectangle trim = printer.computeTrim(0, 0, 0, 0);
+// Point dpi = printer.getDPI();
+//
+// printerFont = new Font(printer, fontData.getName(), fontData.getHeight(), SWT.NORMAL);
+// clientArea = printer.getClientArea();
+// pageWidth = clientArea.width;
+// // one inch margin around text
+// clientArea.x = dpi.x + trim.x;
+// clientArea.y = dpi.y + trim.y;
+// clientArea.width -= (clientArea.x + trim.width);
+// clientArea.height -= (clientArea.y + trim.height);
+//
+// int style = mirrored ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
+// gc = new GC(printer, style);
+// gc.setFont(printerFont);
+// printerRenderer.setFont(printerFont, tabLength);
+// int lineHeight = printerRenderer.getLineHeight();
+// if (printOptions.header != null) {
+// clientArea.y += lineHeight * 2;
+// clientArea.height -= lineHeight * 2;
+// }
+// if (printOptions.footer != null) {
+// clientArea.height -= lineHeight * 2;
+// }
+//
+// // TODO not wrapped
+// StyledTextContent content = printerRenderer.content;
+// startLine = 0;
+// endLine = singleLine ? 0 : content.getLineCount() - 1;
+// if (scope == PrinterData.PAGE_RANGE) {
+// int pageSize = clientArea.height / lineHeight;//WRONG
+// startLine = (startPage - 1) * pageSize;
+// } else if (scope == PrinterData.SELECTION) {
+// startLine = content.getLineAtOffset(selection[0].x);
+// if (selection[0].y > 0) {
+// endLine = content.getLineAtOffset(selection[0].y);
+// } else {
+// endLine = startLine - 1;
+// }
+// }
+// }
+// /**
+// * Prints the lines in the specified page range.
+// */
+// void print() {
+// Color background = gc.getBackground();
+// Color foreground = gc.getForeground();
+// int paintY = clientArea.y;
+// int paintX = clientArea.x;
+// int width = clientArea.width;
+// int page = startPage;
+// int pageBottom = clientArea.y + clientArea.height;
+// int orientation = gc.getStyle() & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT);
+// TextLayout printLayout = null;
+// if (printOptions.printLineNumbers || printOptions.header != null || printOptions.footer != null) {
+// printLayout = new TextLayout(printer);
+// printLayout.setFont(printerFont);
+// }
+// if (printOptions.printLineNumbers) {
+// int numberingWidth = 0;
+// int count = endLine - startLine + 1;
+// String[] lineLabels = printOptions.lineLabels;
+// if (lineLabels != null) {
+// for (int i = startLine; i < Math.min(count, lineLabels.length); i++) {
+// if (lineLabels[i] != null) {
+// printLayout.setText(lineLabels[i]);
+// int lineWidth = printLayout.getBounds().width;
+// numberingWidth = Math.max(numberingWidth, lineWidth);
+// }
+// }
+// } else {
+// StringBuilder buffer = new StringBuilder("0");
+// while ((count /= 10) > 0) buffer.append("0");
+// printLayout.setText(buffer.toString());
+// numberingWidth = printLayout.getBounds().width;
+// }
+// numberingWidth += printMargin;
+// if (numberingWidth > width) numberingWidth = width;
+// paintX += numberingWidth;
+// width -= numberingWidth;
+// }
+// for (int i = startLine; i <= endLine && page <= endPage; i++) {
+// if (paintY == clientArea.y) {
+// printer.startPage();
+// printDecoration(page, true, printLayout);
+// }
+// TextLayout layout = printerRenderer.getTextLayout(i, orientation, width, lineSpacing);
+// Color lineBackground = printerRenderer.getLineBackground(i, background);
+// int paragraphBottom = paintY + layout.getBounds().height;
+// if (paragraphBottom <= pageBottom) {
+// //normal case, the whole paragraph fits in the current page
+// printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
+// paintY = paragraphBottom;
+// } else {
+// int lineCount = layout.getLineCount();
+// while (paragraphBottom > pageBottom && lineCount > 0) {
+// lineCount--;
+// paragraphBottom -= layout.getLineBounds(lineCount).height + layout.getSpacing();
+// }
+// if (lineCount == 0) {
+// //the whole paragraph goes to the next page
+// printDecoration(page, false, printLayout);
+// printer.endPage();
+// page++;
+// if (page <= endPage) {
+// printer.startPage();
+// printDecoration(page, true, printLayout);
+// paintY = clientArea.y;
+// printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
+// paintY += layout.getBounds().height;
+// }
+// } else {
+// //draw paragraph top in the current page and paragraph bottom in the next
+// int height = paragraphBottom - paintY;
+// gc.setClipping(clientArea.x, paintY, clientArea.width, height);
+// printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
+// gc.setClipping((Rectangle)null);
+// printDecoration(page, false, printLayout);
+// printer.endPage();
+// page++;
+// if (page <= endPage) {
+// printer.startPage();
+// printDecoration(page, true, printLayout);
+// paintY = clientArea.y - height;
+// int layoutHeight = layout.getBounds().height;
+// gc.setClipping(clientArea.x, clientArea.y, clientArea.width, layoutHeight - height);
+// printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
+// gc.setClipping((Rectangle)null);
+// paintY += layoutHeight;
+// }
+// }
+// }
+// printerRenderer.disposeTextLayout(layout);
+// }
+// if (page <= endPage && paintY > clientArea.y) {
+// // close partial page
+// printDecoration(page, false, printLayout);
+// printer.endPage();
+// }
+// if (printLayout != null) printLayout.dispose();
+// }
+// /**
+// * Print header or footer decorations.
+// *
+// * @param page page number to print, if specified in the StyledTextPrintOptions header or footer.
+// * @param header true = print the header, false = print the footer
+// */
+// void printDecoration(int page, boolean header, TextLayout layout) {
+// String text = header ? printOptions.header : printOptions.footer;
+// if (text == null) return;
+// int lastSegmentIndex = 0;
+// for (int i = 0; i < 3; i++) {
+// int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex);
+// String segment;
+// if (segmentIndex == -1) {
+// segment = text.substring(lastSegmentIndex);
+// printDecorationSegment(segment, i, page, header, layout);
+// break;
+// } else {
+// segment = text.substring(lastSegmentIndex, segmentIndex);
+// printDecorationSegment(segment, i, page, header, layout);
+// lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length();
+// }
+// }
+// }
+// /**
+// * Print one segment of a header or footer decoration.
+// * Headers and footers have three different segments.
+// * One each for left aligned, centered, and right aligned text.
+// *
+// * @param segment decoration segment to print
+// * @param alignment alignment of the segment. 0=left, 1=center, 2=right
+// * @param page page number to print, if specified in the decoration segment.
+// * @param header true = print the header, false = print the footer
+// */
+// void printDecorationSegment(String segment, int alignment, int page, boolean header, TextLayout layout) {
+// int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG);
+// if (pageIndex != -1) {
+// int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length();
+// StringBuilder buffer = new StringBuilder(segment.substring (0, pageIndex));
+// buffer.append (page);
+// buffer.append (segment.substring(pageIndex + pageTagLength));
+// segment = buffer.toString();
+// }
+// if (segment.length() > 0) {
+// layout.setText(segment);
+// int segmentWidth = layout.getBounds().width;
+// int segmentHeight = printerRenderer.getLineHeight();
+// int drawX = 0, drawY;
+// if (alignment == LEFT) {
+// drawX = clientArea.x;
+// } else if (alignment == CENTER) {
+// drawX = (pageWidth - segmentWidth) / 2;
+// } else if (alignment == RIGHT) {
+// drawX = clientArea.x + clientArea.width - segmentWidth;
+// }
+// if (header) {
+// drawY = clientArea.y - segmentHeight * 2;
+// } else {
+// drawY = clientArea.y + clientArea.height + segmentHeight;
+// }
+// layout.draw(gc, drawX, drawY);
+// }
+// }
+// void printLine(int x, int y, GC gc, Color foreground, Color background, TextLayout layout, TextLayout printLayout, int index) {
+// if (background != null) {
+// Rectangle rect = layout.getBounds();
+// gc.setBackground(background);
+// gc.fillRectangle(x, y, rect.width, rect.height);
+//
+//// int lineCount = layout.getLineCount();
+//// for (int i = 0; i < lineCount; i++) {
+//// Rectangle rect = layout.getLineBounds(i);
+//// rect.x += paintX;
+//// rect.y += paintY + layout.getSpacing();
+//// rect.width = width;//layout bounds
+//// gc.fillRectangle(rect);
+//// }
+// }
+// if (printOptions.printLineNumbers) {
+// FontMetrics metrics = layout.getLineMetrics(0);
+// printLayout.setAscent(metrics.getAscent() + metrics.getLeading());
+// printLayout.setDescent(metrics.getDescent());
+// String[] lineLabels = printOptions.lineLabels;
+// if (lineLabels != null) {
+// if (0 <= index && index < lineLabels.length && lineLabels[index] != null) {
+// printLayout.setText(lineLabels[index]);
+// } else {
+// printLayout.setText("");
+// }
+// } else {
+// printLayout.setText(String.valueOf(index));
+// }
+// int paintX = x - printMargin - printLayout.getBounds().width;
+// printLayout.draw(gc, paintX, y);
+// printLayout.setAscent(-1);
+// printLayout.setDescent(-1);
+// }
+// gc.setForeground(foreground);
+// layout.draw(gc, x, y);
+// }
+// /**
+// * Starts a print job and prints the pages specified in the constructor.
+// */
+// @Override
+// public void run() {
+// String jobName = printOptions.jobName;
+// if (jobName == null) {
+// jobName = "Printing";
+// }
+// if (printer.startJob(jobName)) {
+// init();
+// print();
+// dispose();
+// printer.endJob();
+// }
+// }
+// }
+//
+///**
+// * Constructs a new instance of this class given its parent
+// * and a style value describing its behavior and appearance.
+// *
+// * The style value is either one of the style constants defined in
+// * class SWT which is applicable to instances of this
+// * class, or must be built by bitwise OR'ing together
+// * (that is, using the int "|" operator) two or more
+// * of those SWT style constants. The class description
+// * lists the style constants that are applicable to the class.
+// * Style bits are also inherited from superclasses.
+// *
+// *
+// * @param parent a widget which will be the parent of the new instance (cannot be null)
+// * @param style the style of widget to construct
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the parent is null
+// *
+// * @exception SWTException
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+// *
+// *
+// * @see SWT#FULL_SELECTION
+// * @see SWT#MULTI
+// * @see SWT#READ_ONLY
+// * @see SWT#SINGLE
+// * @see SWT#WRAP
+// * @see #getStyle
+// */
+//public StyledText(Composite parent, int style) {
+// super(parent, checkStyle(style));
+// // set the fg in the OS to ensure that these are the same as StyledText, necessary
+// // for ensuring that the bg/fg the IME box uses is the same as what StyledText uses
+// super.setForeground(getForeground());
+// super.setDragDetect(false);
+// Display display = getDisplay();
+// if ((style & SWT.READ_ONLY) != 0) {
+// setEditable(false);
+// }
+// leftMargin = rightMargin = isBidiCaret() ? BIDI_CARET_WIDTH - 1: 0;
+// if ((style & SWT.SINGLE) != 0 && (style & SWT.BORDER) != 0) {
+// leftMargin = topMargin = rightMargin = bottomMargin = 2;
+// }
+// alignment = style & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+// if (alignment == 0) alignment = SWT.LEFT;
+// clipboard = new Clipboard(display);
+// installDefaultContent();
+// renderer = new StyledTextRenderer(getDisplay(), this);
+// renderer.setContent(content);
+// renderer.setFont(getFont(), tabLength);
+// ime = new IME(this, SWT.NONE);
+// defaultCaret = new Caret(this, SWT.NONE);
+// if ((style & SWT.WRAP) != 0) {
+// setWordWrap(true);
+// }
+// if (isBidiCaret()) {
+// createCaretBitmaps();
+// Runnable runnable = () -> {
+// int direction = BidiUtil.getKeyboardLanguage() == BidiUtil.KEYBOARD_BIDI ? SWT.RIGHT : SWT.LEFT;
+// if (direction == caretDirection) return;
+// if (getCaret() != defaultCaret) return;
+// setCaretLocations(Arrays.stream(caretOffsets).mapToObj(this::getPointAtOffset).toArray(Point[]::new), direction);
+// };
+// BidiUtil.addLanguageListener(this, runnable);
+// }
+// setCaret(defaultCaret);
+// calculateScrollBars();
+// createKeyBindings();
+// super.setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM));
+// installListeners();
+// initializeAccessible();
+// setData("DEFAULT_DROP_TARGET_EFFECT", new StyledTextDropTargetEffect(this));
+// if (IS_MAC) setData(STYLEDTEXT_KEY);
+//}
+///**
+// * Adds an extended modify listener. An ExtendedModify event is sent by the
+// * widget when the widget text has changed.
+// *
+// * @param extendedModifyListener the listener
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// * A BidiSegmentEvent is sent
+// * whenever a line of text is measured or rendered. You can
+// * specify text ranges in the line that should be treated as if they
+// * had a different direction than the surrounding text.
+// * This may be used when adjacent segments of right-to-left text should
+// * not be reordered relative to each other.
+// * E.g., multiple Java string literals in a right-to-left language
+// * should generally remain in logical order to each other, that is, the
+// * way they are stored.
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// * @see BidiSegmentEvent
+// * @since 2.0
+// */
+//public void addBidiSegmentListener(BidiSegmentListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// addListener(ST.LineGetSegments, new StyledTextListener(listener));
+// resetCache(0, content.getLineCount());
+// setCaretLocations();
+// super.redraw();
+//}
+///**
+// * Adds a caret listener. CaretEvent is sent when the caret offset changes.
+// *
+// * @param listener the listener
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// *
+// * @since 3.5
+// */
+//public void addCaretListener(CaretListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// addListener(ST.CaretMoved, new StyledTextListener(listener));
+//}
+///**
+// * Adds a line background listener. A LineGetBackground event is sent by the
+// * widget to determine the background color for a line.
+// *
+// * @param listener the listener
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void addLineBackgroundListener(LineBackgroundListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// if (!isListening(ST.LineGetBackground)) {
+// renderer.clearLineBackground(0, content.getLineCount());
+// }
+// addListener(ST.LineGetBackground, new StyledTextListener(listener));
+//}
+///**
+// * Adds a line style listener. A LineGetStyle event is sent by the widget to
+// * determine the styles for a line.
+// *
+// * @param listener the listener
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void addLineStyleListener(LineStyleListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// if (!isListening(ST.LineGetStyle)) {
+// setStyleRanges(0, 0, null, null, true);
+// renderer.clearLineStyle(0, content.getLineCount());
+// }
+// addListener(ST.LineGetStyle, new StyledTextListener(listener));
+// setCaretLocations();
+//}
+///**
+// * Adds a modify listener. A Modify event is sent by the widget when the widget text
+// * has changed.
+// *
+// * @param modifyListener the listener
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void addModifyListener(ModifyListener modifyListener) {
+// addTypedListener(modifyListener, SWT.Modify);
+//}
+///**
+// * Adds a paint object listener. A paint object event is sent by the widget when an object
+// * needs to be drawn.
+// *
+// * @param listener the listener
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// *
+// * @since 3.2
+// *
+// * @see PaintObjectListener
+// * @see PaintObjectEvent
+// */
+//public void addPaintObjectListener(PaintObjectListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// addListener(ST.PaintObject, new StyledTextListener(listener));
+//}
+///**
+// * Adds a selection listener. A Selection event is sent by the widget when the
+// * user changes the selection.
+// *
+// * When widgetSelected is called, the event x and y fields contain
+// * the start and end caret indices of the selection[0]. The selection values returned are visual
+// * (i.e., x will always always be <= y).
+// * No event is sent when the caret is moved while the selection length is 0.
+// *
+// * widgetDefaultSelected is not called for StyledTexts.
+// *
+// *
+// * @param listener the listener which should be notified when the user changes the receiver's selection
+//
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see SelectionListener
+// * @see #removeSelectionListener
+// * @see SelectionEvent
+// */
+//public void addSelectionListener(SelectionListener listener) {
+// addTypedListener(listener, SWT.Selection);
+//}
+///**
+// * Adds a verify key listener. A VerifyKey event is sent by the widget when a key
+// * is pressed. The widget ignores the key press if the listener sets the doit field
+// * of the event to false.
+// *
+// * @param listener the listener
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void addVerifyKeyListener(VerifyKeyListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// addListener(ST.VerifyKey, new StyledTextListener(listener));
+//}
+///**
+// * Adds a verify listener. A Verify event is sent by the widget when the widget text
+// * is about to change. The listener can set the event text and the doit field to
+// * change the text that is set in the widget or to force the widget to ignore the
+// * text change.
+// *
+// * @param verifyListener the listener
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void addVerifyListener(VerifyListener verifyListener) {
+// addTypedListener(verifyListener, SWT.Verify);
+//}
+///**
+// * Adds a word movement listener. A movement event is sent when the boundary
+// * of a word is needed. For example, this occurs during word next and word
+// * previous actions.
+// *
+// * @param movementListener the listener
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// *
+// * @see MovementEvent
+// * @see MovementListener
+// * @see #removeWordMovementListener
+// *
+// * @since 3.3
+// */
+//public void addWordMovementListener(MovementListener movementListener) {
+// checkWidget();
+// if (movementListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// addListener(ST.WordNext, new StyledTextListener(movementListener));
+// addListener(ST.WordPrevious, new StyledTextListener(movementListener));
+//}
+///**
+// * Appends a string to the text at the end of the widget.
+// *
+// * @param string the string to be appended
+// * @see #replaceTextRange(int,int,String)
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void append(String string) {
+// checkWidget();
+// if (string == null) {
+// SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// }
+// int lastChar = Math.max(getCharCount(), 0);
+// replaceTextRange(lastChar, 0, string);
+//}
+///**
+// * Calculates the scroll bars
+// */
+//void calculateScrollBars() {
+// ScrollBar horizontalBar = getHorizontalBar();
+// ScrollBar verticalBar = getVerticalBar();
+// setScrollBars(true);
+// if (verticalBar != null) {
+// verticalBar.setIncrement(getVerticalIncrement());
+// }
+// if (horizontalBar != null) {
+// horizontalBar.setIncrement(getHorizontalIncrement());
+// }
+//}
+///**
+// * Calculates the top index based on the current vertical scroll offset.
+// * The top index is the index of the topmost fully visible line or the
+// * topmost partially visible line if no line is fully visible.
+// * The top index starts at 0.
+// */
+//void calculateTopIndex(int delta) {
+// int oldDelta = delta;
+// int oldTopIndex = topIndex;
+// int oldTopIndexY = topIndexY;
+// if (isFixedLineHeight()) {
+// int verticalIncrement = getVerticalIncrement();
+// if (verticalIncrement == 0) {
+// return;
+// }
+// topIndex = Compatibility.ceil(getVerticalScrollOffset(), verticalIncrement);
+// // Set top index to partially visible top line if no line is fully
+// // visible but at least some of the widget client area is visible.
+// // Fixes bug 15088.
+// if (topIndex >= 0) {
+// if (clientAreaHeight > 0) {
+// int bottomPixel = getVerticalScrollOffset() + clientAreaHeight;
+// topIndexY = getLinePixel(topIndex);
+// int fullLineTopPixel = topIndex * verticalIncrement;
+// int fullLineVisibleHeight = bottomPixel - fullLineTopPixel;
+// // set top index to partially visible line if no line fully fits in
+// // client area or if space is available but not used (the latter should
+// // never happen because we use claimBottomFreeSpace)
+// if (fullLineVisibleHeight < verticalIncrement) {
+// topIndex = getVerticalScrollOffset() / verticalIncrement;
+// }
+// } else if (topIndex >= content.getLineCount()) {
+// topIndex = content.getLineCount() - 1;
+// }
+// }
+// } else {
+// if (delta >= 0) {
+// delta -= topIndexY;
+// int lineIndex = topIndex;
+// int lineCount = content.getLineCount();
+// while (lineIndex < lineCount) {
+// if (delta <= 0) break;
+// delta -= renderer.getCachedLineHeight(lineIndex++);
+// }
+// if (lineIndex < lineCount && -delta + renderer.getCachedLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) {
+// topIndex = lineIndex;
+// topIndexY = -delta;
+// } else {
+// topIndex = lineIndex - 1;
+// topIndexY = -renderer.getCachedLineHeight(topIndex) - delta;
+// }
+// } else {
+// delta -= topIndexY;
+// int lineIndex = topIndex;
+// while (lineIndex > 0) {
+// int lineHeight = renderer.getCachedLineHeight(lineIndex - 1);
+// if (delta + lineHeight > 0) break;
+// delta += lineHeight;
+// lineIndex--;
+// }
+// if (lineIndex == 0 || -delta + renderer.getCachedLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) {
+// topIndex = lineIndex;
+// topIndexY = - delta;
+// } else {
+// topIndex = lineIndex - 1;
+// topIndexY = - renderer.getCachedLineHeight(topIndex) - delta;
+// }
+// }
+// }
+// if (topIndex < 0) {
+// // TODO: This logging is in place to determine why topIndex is getting set to negative values.
+// // It should be deleted once we fix the root cause of this issue. See bug 487254 for details.
+// System.err.println("StyledText: topIndex was " + topIndex
+// + ", isFixedLineHeight() = " + isFixedLineHeight()
+// + ", delta = " + delta
+// + ", content.getLineCount() = " + content.getLineCount()
+// + ", clientAreaHeight = " + clientAreaHeight
+// + ", oldTopIndex = " + oldTopIndex
+// + ", oldTopIndexY = " + oldTopIndexY
+// + ", getVerticalScrollOffset = " + getVerticalScrollOffset()
+// + ", oldDelta = " + oldDelta
+// + ", getVerticalIncrement() = " + getVerticalIncrement());
+// topIndex = 0;
+// }
+// if (topIndex != oldTopIndex || oldTopIndexY != topIndexY) {
+// int width = renderer.getWidth();
+// renderer.calculateClientArea();
+// if (width != renderer.getWidth()) {
+// setScrollBars(false);
+// }
+// }
+//}
+///**
+// * Hides the scroll bars if widget is created in single line mode.
+// */
+//static int checkStyle(int style) {
+// if ((style & SWT.SINGLE) != 0) {
+// style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP | SWT.MULTI);
+// } else {
+// style |= SWT.MULTI;
+// if ((style & SWT.WRAP) != 0) {
+// style &= ~SWT.H_SCROLL;
+// }
+// }
+// style |= SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND;
+// /* Clear SWT.CENTER to avoid the conflict with SWT.EMBEDDED */
+// return style & ~SWT.CENTER;
+//}
+///**
+// * Scrolls down the text to use new space made available by a resize or by
+// * deleted lines.
+// */
+//void claimBottomFreeSpace() {
+// if (ime.getCompositionOffset() != -1) return;
+// if (isFixedLineHeight()) {
+// int newVerticalOffset = Math.max(0, renderer.getHeight() - clientAreaHeight);
+// if (newVerticalOffset < getVerticalScrollOffset()) {
+// scrollVertical(newVerticalOffset - getVerticalScrollOffset(), true);
+// }
+// } else {
+// int bottomIndex = getPartialBottomIndex();
+// int height = getLinePixel(bottomIndex + 1);
+// if (clientAreaHeight > height) {
+// scrollVertical(-getAvailableHeightAbove(clientAreaHeight - height), true);
+// }
+// }
+//}
+///**
+// * Scrolls text to the right to use new space made available by a resize.
+// */
+//void claimRightFreeSpace() {
+// int newHorizontalOffset = Math.max(0, renderer.getWidth() - clientAreaWidth);
+// if (newHorizontalOffset < horizontalScrollOffset) {
+// // item is no longer drawn past the right border of the client area
+// // align the right end of the item with the right border of the
+// // client area (window is scrolled right).
+// scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true);
+// }
+//}
+//void clearBlockSelection(boolean reset, boolean sendEvent) {
+// if (reset) resetSelection();
+// blockXAnchor = blockYAnchor = -1;
+// blockXLocation = blockYLocation = -1;
+// caretDirection = SWT.NULL;
+// updateCaretVisibility();
+// super.redraw();
+// if (sendEvent) sendSelectionEvent();
+//}
+///**
+// * Removes the widget selection.
+// *
+// * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset.
+// */
+//void clearSelection(boolean sendEvent) {
+// int selectionStart = selection[0].x;
+// int selectionEnd = selection[0].y;
+// resetSelection();
+// // redraw old selection, if any
+// if (selectionEnd - selectionStart > 0) {
+// int length = content.getCharCount();
+// // called internally to remove selection after text is removed
+// // therefore make sure redraw range is valid.
+// int redrawStart = Math.min(selectionStart, length);
+// int redrawEnd = Math.min(selectionEnd, length);
+// if (redrawEnd - redrawStart > 0) {
+// internalRedrawRange(redrawStart, redrawEnd - redrawStart);
+// }
+// if (sendEvent) {
+// sendSelectionEvent();
+// }
+// }
+//}
+//@Override
+//public Point computeSize (int wHint, int hHint, boolean changed) {
+// checkWidget();
+// int lineCount = (getStyle() & SWT.SINGLE) != 0 ? 1 : content.getLineCount();
+// int width = 0;
+// int height = 0;
+// if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
+// Display display = getDisplay();
+// int maxHeight = display.getClientArea().height;
+// for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// int wrapWidth = layout.getWidth();
+// if (wordWrap) layout.setWidth(wHint == 0 ? 1 : wHint == SWT.DEFAULT ? SWT.DEFAULT : Math.max(1, wHint - leftMargin - rightMargin));
+// Rectangle rect = layout.getBounds();
+// height += rect.height;
+// width = Math.max(width, rect.width);
+// layout.setWidth(wrapWidth);
+// renderer.disposeTextLayout(layout);
+// if (isFixedLineHeight() && height > maxHeight) break;
+// }
+// if (isFixedLineHeight()) {
+// height = lineCount * renderer.getLineHeight();
+// }
+// }
+// // Use default values if no text is defined.
+// if (width == 0) width = DEFAULT_WIDTH;
+// if (height == 0) height = DEFAULT_HEIGHT;
+// if (wHint != SWT.DEFAULT) width = wHint;
+// if (hHint != SWT.DEFAULT) height = hHint;
+// int wTrim = getLeftMargin() + rightMargin + getCaretWidth();
+// int hTrim = topMargin + bottomMargin;
+// Rectangle rect = computeTrim(0, 0, width + wTrim, height + hTrim);
+// return new Point (rect.width, rect.height);
+//}
+///**
+// * Copies the selected text to the DND.CLIPBOARD clipboard.
+// *
+// * The text will be put on the clipboard in plain text, HTML, and RTF formats.
+// * The DND.CLIPBOARD clipboard is used for data that is
+// * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or
+// * by menu action.
+// *
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public void copy() {
+// checkWidget();
+// copySelection(DND.CLIPBOARD);
+//}
+///**
+// * Copies the selected text to the specified clipboard. The text will be put in the
+// * clipboard in plain text, HTML, and RTF formats.
+// *
+// * The clipboardType is one of the clipboard constants defined in class
+// * DND. The DND.CLIPBOARD clipboard is
+// * used for data that is transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V)
+// * or by menu action. The DND.SELECTION_CLIPBOARD
+// * clipboard is used for data that is transferred by selecting text and pasting
+// * with the middle mouse button.
+// *
+// *
+// * @param clipboardType indicates the type of clipboard
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.1
+// */
+//public void copy(int clipboardType) {
+// checkWidget();
+// copySelection(clipboardType);
+//}
+//boolean copySelection(int type) {
+// if (type != DND.CLIPBOARD && type != DND.SELECTION_CLIPBOARD) return false;
+// try {
+// if (blockSelection && blockXLocation != -1) {
+// String text = getBlockSelectionText(PlatformLineDelimiter);
+// if (text.length() > 0) {
+// //TODO RTF support
+// TextTransfer plainTextTransfer = TextTransfer.getInstance();
+// Object[] data = new Object[]{text};
+// Transfer[] types = new Transfer[]{plainTextTransfer};
+// clipboard.setContents(data, types, type);
+// return true;
+// }
+// } else if (getSelectionRanges().length > 2) {
+// StringBuilder text = new StringBuilder();
+// int[] ranges = getSelectionRanges();
+// for (int i = 0; i < ranges.length; i += 2) {
+// int offset = ranges[i];
+// int length = ranges[i + 1];
+// text.append(length == 0 ? "" : getText(offset, offset + length - 1));
+// text.append(PlatformLineDelimiter);
+// }
+// text.delete(text.length() - PlatformLineDelimiter.length(), text.length());
+// if (text.length() > 0) {
+// //TODO RTF support
+// clipboard.setContents(new Object[]{text.toString()}, new Transfer[]{TextTransfer.getInstance()}, type);
+// return true;
+// }
+// } else {
+// int length = selection[0].y - selection[0].x;
+// if (length > 0) {
+// setClipboardContent(selection[0].x, length, type);
+// return true;
+// }
+// }
+// } catch (SWTError error) {
+// // Copy to clipboard failed. This happens when another application
+// // is accessing the clipboard while we copy. Ignore the error.
+// // Rethrow all other errors. Fixes bug 17578.
+// if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) {
+// throw error;
+// }
+// }
+// return false;
+//}
+///**
+// * Returns the alignment of the widget.
+// *
+// * @return the alignment
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *R
+// * @see #getLineAlignment(int)
+// *
+// * @since 3.2
+// */
+//public int getAlignment() {
+// checkWidget();
+// return alignment;
+//}
+///**
+// * Returns the Always Show Scrollbars flag. True if the scrollbars are
+// * always shown even if they are not required. False if the scrollbars are only
+// * visible when some part of the content needs to be scrolled to be seen.
+// * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the
+// * horizontal and vertical directions.
+// *
+// * @return the Always Show Scrollbars flag value
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.8
+// */
+//public boolean getAlwaysShowScrollBars() {
+// checkWidget();
+// return alwaysShowScroll;
+//}
+//int getAvailableHeightAbove(int height) {
+// int maxHeight = verticalScrollOffset;
+// if (maxHeight == -1) {
+// int lineIndex = topIndex - 1;
+// maxHeight = -topIndexY;
+// if (topIndexY > 0) {
+// maxHeight += renderer.getLineHeight(lineIndex--);
+// }
+// while (height > maxHeight && lineIndex >= 0) {
+// maxHeight += renderer.getLineHeight(lineIndex--);
+// }
+// }
+// return Math.min(height, maxHeight);
+//}
+//int getAvailableHeightBellow(int height) {
+// int partialBottomIndex = getPartialBottomIndex();
+// int topY = getLinePixel(partialBottomIndex);
+// int lineHeight = renderer.getLineHeight(partialBottomIndex);
+// int availableHeight = 0;
+// int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin;
+// if (topY + lineHeight > clientAreaHeight) {
+// availableHeight = lineHeight - (clientAreaHeight - topY);
+// }
+// int lineIndex = partialBottomIndex + 1;
+// int lineCount = content.getLineCount();
+// while (height > availableHeight && lineIndex < lineCount) {
+// availableHeight += renderer.getLineHeight(lineIndex++);
+// }
+// return Math.min(height, availableHeight);
+//}
+///**
+// * Returns the color of the margins.
+// *
+// * @return the color of the margins.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public Color getMarginColor() {
+// checkWidget();
+// return marginColor != null ? marginColor : getBackground();
+//}
+///**
+// * Returns a string that uses only the line delimiter specified by the
+// * StyledTextContent implementation.
+// *
+// * Returns only the first line if the widget has the SWT.SINGLE style.
+// *
+// *
+// * @param text the text that may have line delimiters that don't
+// * match the model line delimiter. Possible line delimiters
+// * are CR ('\r'), LF ('\n'), CR/LF ("\r\n")
+// * @return the converted text that only uses the line delimiter
+// * specified by the model. Returns only the first line if the widget
+// * has the SWT.SINGLE style.
+// */
+//String getModelDelimitedText(String text) {
+// int length = text.length();
+// if (length == 0) {
+// return text;
+// }
+// int crIndex = 0;
+// int lfIndex = 0;
+// int i = 0;
+// StringBuilder convertedText = new StringBuilder(length);
+// String delimiter = getLineDelimiter();
+// while (i < length) {
+// if (crIndex != -1) {
+// crIndex = text.indexOf(SWT.CR, i);
+// }
+// if (lfIndex != -1) {
+// lfIndex = text.indexOf(SWT.LF, i);
+// }
+// if (lfIndex == -1 && crIndex == -1) { // no more line breaks?
+// break;
+// } else if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) {
+// convertedText.append(text.substring(i, crIndex));
+// if (lfIndex == crIndex + 1) { // CR/LF combination?
+// i = lfIndex + 1;
+// } else {
+// i = crIndex + 1;
+// }
+// } else { // LF occurs before CR!
+// convertedText.append(text.substring(i, lfIndex));
+// i = lfIndex + 1;
+// }
+// if (isSingleLine()) {
+// break;
+// }
+// convertedText.append(delimiter);
+// }
+// // copy remaining text if any and if not in single line mode or no
+// // text copied thus far (because there only is one line)
+// if (i < length && (!isSingleLine() || convertedText.length() == 0)) {
+// convertedText.append(text.substring(i));
+// }
+// return convertedText.toString();
+//}
+//boolean checkDragDetect(Event event) {
+// if (!isListening(SWT.DragDetect)) return false;
+// if (event.button != 1) return false;
+// if (blockSelection && blockXLocation != -1) {
+// Rectangle rect = getBlockSelectionRectangle();
+// if (rect.contains(event.x, event.y)) {
+// return dragDetect(event);
+// }
+// } else {
+// if (selection[0].x == selection[0].y) return false;
+// int offset = getOffsetAtPoint(event.x, event.y, null, true);
+// if (selection[0].x <= offset && offset < selection[0].y) {
+// return dragDetect(event);
+// }
+//
+// }
+// return false;
+//}
+//
+///**
+// * Creates default key bindings.
+// */
+//void createKeyBindings() {
+// int nextKey = isMirrored() ? SWT.ARROW_LEFT : SWT.ARROW_RIGHT;
+// int previousKey = isMirrored() ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
+//
+// // Navigation
+// setKeyBinding(SWT.ARROW_UP, ST.LINE_UP);
+// setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN);
+// if (IS_MAC) {
+// setKeyBinding(previousKey | SWT.MOD1, ST.LINE_START);
+// setKeyBinding(nextKey | SWT.MOD1, ST.LINE_END);
+// setKeyBinding(SWT.HOME, ST.TEXT_START);
+// setKeyBinding(SWT.END, ST.TEXT_END);
+// setKeyBinding(SWT.ARROW_UP | SWT.MOD1, ST.TEXT_START);
+// setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1, ST.TEXT_END);
+// setKeyBinding(nextKey | SWT.MOD3, ST.WORD_NEXT);
+// setKeyBinding(previousKey | SWT.MOD3, ST.WORD_PREVIOUS);
+// } else {
+// setKeyBinding(SWT.HOME, ST.LINE_START);
+// setKeyBinding(SWT.END, ST.LINE_END);
+// setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START);
+// setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END);
+// setKeyBinding(nextKey | SWT.MOD1, ST.WORD_NEXT);
+// setKeyBinding(previousKey | SWT.MOD1, ST.WORD_PREVIOUS);
+// }
+// setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP);
+// setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN);
+// setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START);
+// setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END);
+// setKeyBinding(nextKey, ST.COLUMN_NEXT);
+// setKeyBinding(previousKey, ST.COLUMN_PREVIOUS);
+//
+// // Selection
+// setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP);
+// setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN);
+// if (IS_MAC) {
+// setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_START);
+// setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_END);
+// setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_TEXT_START);
+// setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_TEXT_END);
+// setKeyBinding(SWT.ARROW_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START);
+// setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END);
+// setKeyBinding(nextKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_NEXT);
+// setKeyBinding(previousKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_PREVIOUS);
+// } else {
+// setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START);
+// setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END);
+// setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START);
+// setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END);
+// setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT);
+// setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS);
+// }
+// setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP);
+// setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN);
+// setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START);
+// setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END);
+// setKeyBinding(nextKey | SWT.MOD2, ST.SELECT_COLUMN_NEXT);
+// setKeyBinding(previousKey | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS);
+//
+// // Modification
+// // Cut, Copy, Paste
+// setKeyBinding('X' | SWT.MOD1, ST.CUT);
+// setKeyBinding('C' | SWT.MOD1, ST.COPY);
+// setKeyBinding('V' | SWT.MOD1, ST.PASTE);
+// if (IS_MAC) {
+// setKeyBinding(SWT.DEL | SWT.MOD2, ST.DELETE_NEXT);
+// setKeyBinding(SWT.BS | SWT.MOD3, ST.DELETE_WORD_PREVIOUS);
+// setKeyBinding(SWT.DEL | SWT.MOD3, ST.DELETE_WORD_NEXT);
+// } else {
+// // Cut, Copy, Paste Wordstar style
+// setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT);
+// setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY);
+// setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE);
+// }
+// setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS);
+// setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS);
+// setKeyBinding(SWT.DEL, ST.DELETE_NEXT);
+// setKeyBinding(SWT.BS | SWT.MOD1, ST.DELETE_WORD_PREVIOUS);
+// setKeyBinding(SWT.DEL | SWT.MOD1, ST.DELETE_WORD_NEXT);
+//
+// // Miscellaneous
+// setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE);
+//}
+///**
+// * Create the bitmaps to use for the caret in bidi mode. This
+// * method only needs to be called upon widget creation and when the
+// * font changes (the caret bitmap height needs to match font height).
+// */
+//void createCaretBitmaps() {
+// int caretWidth = BIDI_CARET_WIDTH;
+// Display display = getDisplay();
+// if (leftCaretBitmap != null) {
+// if (defaultCaret != null && leftCaretBitmap.equals(defaultCaret.getImage())) {
+// defaultCaret.setImage(null);
+// }
+// leftCaretBitmap.dispose();
+// }
+// int lineHeight = renderer.getLineHeight();
+// leftCaretBitmap = new Image(display, caretWidth, lineHeight);
+// GC gc = new GC (leftCaretBitmap);
+// gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+// gc.fillRectangle(0, 0, caretWidth, lineHeight);
+// gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+// gc.drawLine(0,0,0,lineHeight);
+// gc.drawLine(0,0,caretWidth-1,0);
+// gc.drawLine(0,1,1,1);
+// gc.dispose();
+//
+// if (rightCaretBitmap != null) {
+// if (defaultCaret != null && rightCaretBitmap.equals(defaultCaret.getImage())) {
+// defaultCaret.setImage(null);
+// }
+// rightCaretBitmap.dispose();
+// }
+// rightCaretBitmap = new Image(display, caretWidth, lineHeight);
+// gc = new GC (rightCaretBitmap);
+// gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+// gc.fillRectangle(0, 0, caretWidth, lineHeight);
+// gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+// gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight);
+// gc.drawLine(0,0,caretWidth-1,0);
+// gc.drawLine(caretWidth-1,1,1,1);
+// gc.dispose();
+//}
+///**
+// * Moves the selected text to the clipboard. The text will be put in the
+// * clipboard in plain text, HTML, and RTF formats.
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public void cut() {
+// checkWidget();
+// // Abort cut operation if copy to clipboard fails.
+// // Fixes bug 21030.
+// if (copySelection(DND.CLIPBOARD)) {
+// if (blockSelection && blockXLocation != -1) {
+// insertBlockSelectionText((char)0, SWT.NULL);
+// } else {
+// doDelete();
+// }
+// }
+//}
+///**
+// * A mouse move event has occurred. See if we should start autoscrolling. If
+// * the move position is outside of the client area, initiate autoscrolling.
+// * Otherwise, we've moved back into the widget so end autoscrolling.
+// */
+//void doAutoScroll(Event event) {
+// int caretLine = getFirstCaretLine();
+// if (event.y > clientAreaHeight - bottomMargin && caretLine != content.getLineCount() - 1) {
+// doAutoScroll(SWT.DOWN, event.y - (clientAreaHeight - bottomMargin));
+// } else if (event.y < topMargin && caretLine != 0) {
+// doAutoScroll(SWT.UP, topMargin - event.y);
+// } else if (event.x < leftMargin && !wordWrap) {
+// doAutoScroll(ST.COLUMN_PREVIOUS, leftMargin - event.x);
+// } else if (event.x > clientAreaWidth - rightMargin && !wordWrap) {
+// doAutoScroll(ST.COLUMN_NEXT, event.x - (clientAreaWidth - rightMargin));
+// } else {
+// endAutoScroll();
+// }
+//}
+///**
+// * Initiates autoscrolling.
+// *
+// * @param direction SWT.UP, SWT.DOWN, SWT.COLUMN_NEXT, SWT.COLUMN_PREVIOUS
+// */
+//void doAutoScroll(int direction, int distance) {
+// autoScrollDistance = distance;
+// // If we're already autoscrolling in the given direction do nothing
+// if (autoScrollDirection == direction) {
+// return;
+// }
+//
+// Runnable timer = null;
+// final Display display = getDisplay();
+// // Set a timer that will simulate the user pressing and holding
+// // down a cursor key (i.e., arrowUp, arrowDown).
+// if (direction == SWT.UP) {
+// timer = new Runnable() {
+// @Override
+// public void run() {
+// /* Bug 437357 - NPE in StyledText.getCaretLine
+// * StyledText.content is null at times, probably because the
+// * widget itself has been disposed.
+// */
+// if (isDisposed()) return;
+// if (autoScrollDirection == SWT.UP) {
+// if (blockSelection) {
+// int verticalScrollOffset = getVerticalScrollOffset();
+// int y = blockYLocation - verticalScrollOffset;
+// int pixels = Math.max(-autoScrollDistance, -verticalScrollOffset);
+// if (pixels != 0) {
+// setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true);
+// scrollVertical(pixels, true);
+// }
+// } else {
+// doSelectionPageUp(autoScrollDistance);
+// }
+// display.timerExec(V_SCROLL_RATE, this);
+// }
+// }
+// };
+// autoScrollDirection = direction;
+// display.timerExec(V_SCROLL_RATE, timer);
+// } else if (direction == SWT.DOWN) {
+// timer = new Runnable() {
+// @Override
+// public void run() {
+// /* Bug 437357 - NPE in StyledText.getCaretLine
+// * StyledText.content is null at times, probably because the
+// * widget itself has been disposed.
+// */
+// if (isDisposed()) return;
+// if (autoScrollDirection == SWT.DOWN) {
+// if (blockSelection) {
+// int verticalScrollOffset = getVerticalScrollOffset();
+// int y = blockYLocation - verticalScrollOffset;
+// int max = renderer.getHeight() - verticalScrollOffset - clientAreaHeight;
+// int pixels = Math.min(autoScrollDistance, Math.max(0,max));
+// if (pixels != 0) {
+// setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true);
+// scrollVertical(pixels, true);
+// }
+// } else {
+// doSelectionPageDown(autoScrollDistance);
+// }
+// display.timerExec(V_SCROLL_RATE, this);
+// }
+// }
+// };
+// autoScrollDirection = direction;
+// display.timerExec(V_SCROLL_RATE, timer);
+// } else if (direction == ST.COLUMN_NEXT) {
+// timer = new Runnable() {
+// @Override
+// public void run() {
+// /* Bug 437357 - NPE in StyledText.getCaretLine
+// * StyledText.content is null at times, probably because the
+// * widget itself has been disposed.
+// */
+// if (isDisposed()) return;
+// if (autoScrollDirection == ST.COLUMN_NEXT) {
+// if (blockSelection) {
+// int x = blockXLocation - horizontalScrollOffset;
+// int max = renderer.getWidth() - horizontalScrollOffset - clientAreaWidth;
+// int pixels = Math.min(autoScrollDistance, Math.max(0,max));
+// if (pixels != 0) {
+// setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true);
+// scrollHorizontal(pixels, true);
+// }
+// } else {
+// doVisualNext();
+// setMouseWordSelectionAnchor();
+// doMouseSelection();
+// }
+// display.timerExec(H_SCROLL_RATE, this);
+// }
+// }
+// };
+// autoScrollDirection = direction;
+// display.timerExec(H_SCROLL_RATE, timer);
+// } else if (direction == ST.COLUMN_PREVIOUS) {
+// timer = new Runnable() {
+// @Override
+// public void run() {
+// /* Bug 437357 - NPE in StyledText.getCaretLine
+// * StyledText.content is null at times, probably because the
+// * widget itself has been disposed.
+// */
+// if (isDisposed()) return;
+// if (autoScrollDirection == ST.COLUMN_PREVIOUS) {
+// if (blockSelection) {
+// int x = blockXLocation - horizontalScrollOffset;
+// int pixels = Math.max(-autoScrollDistance, -horizontalScrollOffset);
+// if (pixels != 0) {
+// setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true);
+// scrollHorizontal(pixels, true);
+// }
+// } else {
+// doVisualPrevious();
+// setMouseWordSelectionAnchor();
+// doMouseSelection();
+// }
+// display.timerExec(H_SCROLL_RATE, this);
+// }
+// }
+// };
+// autoScrollDirection = direction;
+// display.timerExec(H_SCROLL_RATE, timer);
+// }
+//}
+///**
+// * Deletes the previous character. Delete the selected text if any.
+// * Move the caret in front of the deleted text.
+// */
+//void doBackspace() {
+// Event event = new Event();
+// event.text = "";
+// if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) { // at least one range to delete
+// for (int i = selection.length - 1; i >= 0; i--) { // from bottom to top to avoid moving ranges
+// Point sel = selection[i];
+// event.start = sel.x;
+// event.end = sel.y;
+// sendKeyEvent(event);
+// }
+// } else {
+// for (int i = caretOffsets.length - 1; i >= 0; i--) { // reverse loop, process from bottom to top
+// int caretOffset = caretOffsets[i];
+// if (caretOffset > 0) {
+// int lineIndex = content.getLineAtOffset(caretOffset);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// if (caretOffset == lineOffset) {
+// lineOffset = content.getOffsetAtLine(lineIndex - 1);
+// event.start = lineOffset + content.getLine(lineIndex - 1).length();
+// event.end = caretOffset;
+// } else {
+// boolean isSurrogate = false;
+// String lineText = content.getLine(lineIndex);
+// char ch = lineText.charAt(caretOffset - lineOffset - 1);
+// if (0xDC00 <= ch && ch <= 0xDFFF) {
+// if (caretOffset - lineOffset - 2 >= 0) {
+// ch = lineText.charAt(caretOffset - lineOffset - 2);
+// isSurrogate = 0xD800 <= ch && ch <= 0xDBFF;
+// }
+// }
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// int start = layout.getPreviousOffset(caretOffset - lineOffset, isSurrogate ? SWT.MOVEMENT_CLUSTER : SWT.MOVEMENT_CHAR);
+// renderer.disposeTextLayout(layout);
+// event.start = start + lineOffset;
+// event.end = caretOffset;
+// }
+// sendKeyEvent(event);
+// }
+// }
+// }
+//}
+//void doBlockColumn(boolean next) {
+// if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false);
+// int x = blockXLocation - horizontalScrollOffset;
+// int y = blockYLocation - getVerticalScrollOffset();
+// int[] trailing = new int[1];
+// int offset = getOffsetAtPoint(x, y, trailing, true);
+// if (offset != -1) {
+// offset += trailing[0];
+// int lineIndex = content.getLineAtOffset(offset);
+// int newOffset;
+// if (next) {
+// newOffset = getClusterNext(offset, lineIndex);
+// } else {
+// newOffset = getClusterPrevious(offset, lineIndex);
+// }
+// offset = newOffset != offset ? newOffset : -1;
+// }
+// if (offset != -1) {
+// setBlockSelectionOffset(offset, true);
+// showCaret();
+// } else {
+// int width = next ? renderer.averageCharWidth : -renderer.averageCharWidth;
+// int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
+// x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset;
+// setBlockSelectionLocation(x, y, true);
+// Rectangle rect = new Rectangle(x, y, 0, 0);
+// showLocation(rect, true);
+// }
+//}
+//void doBlockContentStartEnd(boolean end) {
+// if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false);
+// int offset = end ? content.getCharCount() : 0;
+// setBlockSelectionOffset(offset, true);
+// showCaret();
+//}
+//void doBlockWord(boolean next) {
+// if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false);
+// int x = blockXLocation - horizontalScrollOffset;
+// int y = blockYLocation - getVerticalScrollOffset();
+// int[] trailing = new int[1];
+// int offset = getOffsetAtPoint(x, y, trailing, true);
+// if (offset != -1) {
+// offset += trailing[0];
+// int lineIndex = content.getLineAtOffset(offset);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// String lineText = content.getLine(lineIndex);
+// int lineLength = lineText.length();
+// int newOffset = offset;
+// if (next) {
+// if (offset < lineOffset + lineLength) {
+// newOffset = getWordNext(offset, SWT.MOVEMENT_WORD);
+// }
+// } else {
+// if (offset > lineOffset) {
+// newOffset = getWordPrevious(offset, SWT.MOVEMENT_WORD);
+// }
+// }
+// offset = newOffset != offset ? newOffset : -1;
+// }
+// if (offset != -1) {
+// setBlockSelectionOffset(offset, true);
+// showCaret();
+// } else {
+// int width = (next ? renderer.averageCharWidth : -renderer.averageCharWidth) * 6;
+// int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
+// x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset;
+// setBlockSelectionLocation(x, y, true);
+// Rectangle rect = new Rectangle(x, y, 0, 0);
+// showLocation(rect, true);
+// }
+//}
+//void doBlockLineVertical(boolean up) {
+// if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false);
+// int y = blockYLocation - getVerticalScrollOffset();
+// int lineIndex = getLineIndex(y);
+// if (up) {
+// if (lineIndex > 0) {
+// y = getLinePixel(lineIndex - 1);
+// setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true);
+// if (y < topMargin) {
+// scrollVertical(y - topMargin, true);
+// }
+// }
+// } else {
+// int lineCount = content.getLineCount();
+// if (lineIndex + 1 < lineCount) {
+// y = getLinePixel(lineIndex + 2) - 1;
+// setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true);
+// int bottom = clientAreaHeight - bottomMargin;
+// if (y > bottom) {
+// scrollVertical(y - bottom, true);
+// }
+// }
+// }
+//}
+//void doBlockLineHorizontal(boolean end) {
+// if (blockXLocation == -1) setBlockSelectionOffset(caretOffsets[0], false);
+// int x = blockXLocation - horizontalScrollOffset;
+// int y = blockYLocation - getVerticalScrollOffset();
+// int lineIndex = getLineIndex(y);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// String lineText = content.getLine(lineIndex);
+// int lineLength = lineText.length();
+// int[] trailing = new int[1];
+// int offset = getOffsetAtPoint(x, y, trailing, true);
+// if (offset != -1) {
+// offset += trailing[0];
+// int newOffset = offset;
+// if (end) {
+// if (offset < lineOffset + lineLength) {
+// newOffset = lineOffset + lineLength;
+// }
+// } else {
+// if (offset > lineOffset) {
+// newOffset = lineOffset;
+// }
+// }
+// offset = newOffset != offset ? newOffset : -1;
+// } else {
+// if (!end) offset = lineOffset + lineLength;
+// }
+// if (offset != -1) {
+// setBlockSelectionOffset(offset, true);
+// showCaret();
+// } else {
+// int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
+// x = (end ? maxWidth : 0) - horizontalScrollOffset;
+// setBlockSelectionLocation(x, y, true);
+// Rectangle rect = new Rectangle(x, y, 0, 0);
+// showLocation(rect, true);
+// }
+//}
+//void doBlockSelection(boolean sendEvent) {
+// if (caretOffsets[0] > selectionAnchors[0]) {
+// selection[0].x = selectionAnchors[0];
+// selection[0].y = caretOffsets[0];
+// } else {
+// selection[0].x = caretOffsets[0];
+// selection[0].y = selectionAnchors[0];
+// }
+// updateCaretVisibility();
+// setCaretLocations();
+// super.redraw();
+// if (sendEvent) {
+// sendSelectionEvent();
+// }
+// sendAccessibleTextCaretMoved();
+//}
+///**
+// * Replaces the selection with the character or insert the character at the
+// * current caret position if no selection exists.
+// *
+// * If a carriage return was typed replace it with the line break character
+// * used by the widget on this platform.
+// *
+// *
+// * @param key the character typed by the user
+// */
+//void doContent(final char key) {
+// if (blockSelection && blockXLocation != -1) {
+// insertBlockSelectionText(key, SWT.NULL);
+// return;
+// }
+//
+// for (int i = selection.length - 1; i >= 0; i--) {
+// Point sel = selection[i];
+// Event event = new Event();
+// event.start = sel.x;
+// event.end = sel.y;
+// // replace a CR line break with the widget line break
+// // CR does not make sense on Windows since most (all?) applications
+// // don't recognize CR as a line break.
+// if (key == SWT.CR || key == SWT.LF) {
+// if (!isSingleLine()) {
+// event.text = getLineDelimiter();
+// }
+// } else if (sel.x == sel.y && overwrite && key != TAB) {
+// // no selection and overwrite mode is on and the typed key is not a
+// // tab character (tabs are always inserted without overwriting)?
+// int lineIndex = content.getLineAtOffset(event.end);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// String line = content.getLine(lineIndex);
+// // replace character at caret offset if the caret is not at the
+// // end of the line
+// if (event.end < lineOffset + line.length()) {
+// event.end++;
+// }
+// event.text = new String(new char[] {key});
+// } else {
+// event.text = new String(new char[] {key});
+// }
+// if (event.text != null) {
+// if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) {
+// return;
+// }
+// sendKeyEvent(event);
+// }
+// }
+//}
+///**
+// * Moves the caret after the last character of the widget content.
+// */
+//void doContentEnd() {
+// // place caret at end of first line if receiver is in single
+// // line mode. fixes 4820.
+// if (isSingleLine()) {
+// doLineEnd();
+// } else {
+// int length = content.getCharCount();
+// setCaretOffsets(new int[] {length}, SWT.DEFAULT);
+// showCaret();
+// }
+//}
+///**
+// * Moves the caret in front of the first character of the widget content.
+// */
+//void doContentStart() {
+// setCaretOffsets(new int[] {0}, SWT.DEFAULT);
+// showCaret();
+//}
+///**
+// * Moves the caret to the start of the selection if a selection exists.
+// * Otherwise, if no selection exists move the cursor according to the
+// * cursor selection rules.
+// *
+// * @see #doSelectionCursorPrevious
+// */
+//void doCursorPrevious() {
+// if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) {
+// setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.x).toArray(), OFFSET_LEADING);
+// showCaret();
+// } else {
+// doSelectionCursorPrevious();
+// }
+//}
+///**
+// * Moves the caret to the end of the selection if a selection exists.
+// * Otherwise, if no selection exists move the cursor according to the
+// * cursor selection rules.
+// *
+// * @see #doSelectionCursorNext
+// */
+//void doCursorNext() {
+// if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) {
+// setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.y).toArray(), PREVIOUS_OFFSET_TRAILING);
+// showCaret();
+// } else {
+// doSelectionCursorNext();
+// }
+//}
+///**
+// * Deletes the next character. Delete the selected text if any.
+// */
+//void doDelete() {
+// Event event = new Event();
+// event.text = "";
+// if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) {
+// for (Point sel : selection) {
+// event.start = sel.x;
+// event.end = sel.y;
+// sendKeyEvent(event);
+// }
+// } else {
+// for (int i = caretOffsets.length - 1; i >= 0; i--) {
+// int caretOffset = caretOffsets[i];
+// if (caretOffset < content.getCharCount()) {
+// int line = content.getLineAtOffset(caretOffset);
+// int lineOffset = content.getOffsetAtLine(line);
+// int lineLength = content.getLine(line).length();
+// if (caretOffset == lineOffset + lineLength) {
+// event.start = caretOffset;
+// event.end = content.getOffsetAtLine(line + 1);
+// } else {
+// event.start = caretOffset;
+// event.end = getClusterNext(caretOffset, line);
+// }
+// sendKeyEvent(event);
+// }
+// }
+// }
+//}
+///**
+// * Deletes the next word.
+// */
+//void doDeleteWordNext() {
+// if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) {
+// // if a selection exists, treat the as if
+// // only the delete key was pressed
+// doDelete();
+// } else {
+// for (int i = caretOffsets.length - 1; i >= 0; i--) {
+// int caretOffset = caretOffsets[i];
+// Event event = new Event();
+// event.text = "";
+// event.start = caretOffset;
+// event.end = getWordNext(caretOffset, SWT.MOVEMENT_WORD);
+// sendKeyEvent(event);
+// }
+// }
+//}
+///**
+// * Deletes the previous word.
+// */
+//void doDeleteWordPrevious() {
+// if (Arrays.stream(selection).anyMatch(sel -> sel.x != sel.y)) {
+// // if a selection exists, treat as if
+// // only the backspace key was pressed
+// doBackspace();
+// } else {
+// for (int i = caretOffsets.length - 1; i >= 0; i--) {
+// int caretOffset = caretOffsets[i];
+// Event event = new Event();
+// event.text = "";
+// event.start = getWordPrevious(caretOffset, SWT.MOVEMENT_WORD);
+// event.end = caretOffset;
+// sendKeyEvent(event);
+// }
+// }
+//}
+///**
+// * Moves the caret one line down and to the same character offset relative
+// * to the beginning of the line. Move the caret to the end of the new line
+// * if the new line is shorter than the character offset. Moves the caret to
+// * the end of the text if the caret already is on the last line.
+// */
+//void doLineDown(boolean select) {
+// int[] newCaretOffsets = new int[caretOffsets.length];
+// int lineCount = content.getLineCount();
+// int[] alignment = new int[1];
+// for (int i = 0; i < caretOffsets.length; i++) {
+// int caretOffset = caretOffsets[i];
+// int caretLine = content.getLineAtOffset(caretOffset);
+// int x = caretOffsets.length == 1 ? columnX : getPointAtOffset(caretOffset).x;
+// int y = 0;
+// boolean lastLine = false;
+// if (isWordWrap()) {
+// int lineOffset = content.getOffsetAtLine(caretLine);
+// int offsetInLine = caretOffset - lineOffset;
+// TextLayout layout = renderer.getTextLayout(caretLine);
+// int lineIndex = getVisualLineIndex(layout, offsetInLine);
+// int layoutLineCount = layout.getLineCount();
+// if (lineIndex == layoutLineCount - 1) {
+// lastLine = caretLine == lineCount - 1;
+// caretLine++;
+// } else {
+// y = layout.getLineBounds(lineIndex + 1).y;
+// y++; // bug 485722: workaround for fractional line heights
+// }
+// renderer.disposeTextLayout(layout);
+// } else {
+// lastLine = caretLine == lineCount - 1;
+// caretLine++;
+// }
+// if (lastLine) {
+// newCaretOffsets[i] = content.getCharCount();
+// } else {
+// newCaretOffsets[i] = getOffsetAtPoint(x, y, caretLine, alignment);
+// }
+// }
+// boolean hitLastLine = content.getLineAtOffset(newCaretOffsets[newCaretOffsets.length - 1]) == lineCount - 1;
+// setCaretOffsets(newCaretOffsets, hitLastLine ? SWT.DEFAULT : alignment[0]);
+// int oldColumnX = columnX;
+// int oldHScrollOffset = horizontalScrollOffset;
+// if (select) {
+// setMouseWordSelectionAnchor();
+// // select first and then scroll to reduce flash when key
+// // repeat scrolls lots of lines
+// doSelection(ST.COLUMN_NEXT);
+// }
+// showCaret();
+// int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+// columnX = oldColumnX + hScrollChange;
+//}
+///**
+// * Moves the caret to the end of the line.
+// */
+//void doLineEnd() {
+// int[] newOffsets = new int[caretOffsets.length];
+// for (int i = 0; i < caretOffsets.length; i++) {
+// int caretOffset = caretOffsets[i];
+// int caretLine = content.getLineAtOffset(caretOffset);
+// int lineOffset = content.getOffsetAtLine(caretLine);
+// int lineEndOffset;
+// if (isWordWrap()) {
+// TextLayout layout = renderer.getTextLayout(caretLine);
+// int offsetInLine = caretOffset - lineOffset;
+// int lineIndex = getVisualLineIndex(layout, offsetInLine);
+// int[] offsets = layout.getLineOffsets();
+// lineEndOffset = lineOffset + offsets[lineIndex + 1];
+// renderer.disposeTextLayout(layout);
+// } else {
+// int lineLength = content.getLine(caretLine).length();
+// lineEndOffset = lineOffset + lineLength;
+// }
+// newOffsets[i] = lineEndOffset;
+// }
+// setCaretOffsets(newOffsets, PREVIOUS_OFFSET_TRAILING);
+// showCaret();
+//}
+///**
+// * Moves the caret to the beginning of the line.
+// */
+//void doLineStart() {
+// int[] newCaretOffsets = new int[caretOffsets.length];
+// for (int i = 0; i < caretOffsets.length; i++) {
+// int caretOffset = caretOffsets[i];
+// int caretLine = content.getLineAtOffset(caretOffset);
+// int lineOffset = content.getOffsetAtLine(caretLine);
+// if (isWordWrap()) {
+// TextLayout layout = renderer.getTextLayout(caretLine);
+// int offsetInLine = caretOffset - lineOffset;
+// int lineIndex = getVisualLineIndex(layout, offsetInLine);
+// int[] offsets = layout.getLineOffsets();
+// lineOffset += offsets[lineIndex];
+// renderer.disposeTextLayout(layout);
+// }
+// newCaretOffsets[i] = lineOffset;
+// }
+// setCaretOffsets(newCaretOffsets, OFFSET_LEADING);
+// showCaret();
+//}
+///**
+// * Moves the caret one line up and to the same character offset relative
+// * to the beginning of the line. Move the caret to the end of the new line
+// * if the new line is shorter than the character offset. Moves the caret to
+// * the beginning of the document if it is already on the first line.
+// */
+//void doLineUp(boolean select) {
+// int[] newCaretOffsets = new int[caretOffsets.length];
+// int[] alignment = new int[1];
+// for (int i = 0; i < caretOffsets.length; i++) {
+// int caretOffset = caretOffsets[i];
+// int caretLine = content.getLineAtOffset(caretOffset);
+// int x = caretOffsets.length == 1 ? columnX : getPointAtOffset(caretOffset).x;
+// int y = 0;
+// boolean firstLine = false;
+// if (isWordWrap()) {
+// int lineOffset = content.getOffsetAtLine(caretLine);
+// int offsetInLine = caretOffset - lineOffset;
+// TextLayout layout = renderer.getTextLayout(caretLine);
+// int lineIndex = getVisualLineIndex(layout, offsetInLine);
+// if (lineIndex == 0) {
+// firstLine = caretLine == 0;
+// if (!firstLine) {
+// caretLine--;
+// y = renderer.getLineHeight(caretLine) - 1;
+// y--; // bug 485722: workaround for fractional line heights
+// }
+// } else {
+// y = layout.getLineBounds(lineIndex - 1).y;
+// y++; // bug 485722: workaround for fractional line heights
+// }
+// renderer.disposeTextLayout(layout);
+// } else {
+// firstLine = caretLine == 0;
+// caretLine--;
+// }
+// if (firstLine) {
+// newCaretOffsets[i] = 0;
+// } else {
+// newCaretOffsets[i] = getOffsetAtPoint(x, y, caretLine, alignment);
+// }
+// }
+// setCaretOffsets(newCaretOffsets, newCaretOffsets[0] == 0 ? SWT.DEFAULT : alignment[0]);
+// int oldColumnX = columnX;
+// int oldHScrollOffset = horizontalScrollOffset;
+// if (select) setMouseWordSelectionAnchor();
+// showCaret();
+// if (select) doSelection(ST.COLUMN_PREVIOUS);
+// int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+// columnX = oldColumnX + hScrollChange;
+//}
+//void doMouseLinkCursor() {
+// Display display = getDisplay();
+// Point point = display.getCursorLocation();
+// point = display.map(null, this, point);
+// doMouseLinkCursor(point.x, point.y);
+//}
+//void doMouseLinkCursor(int x, int y) {
+// int offset = getOffsetAtPoint(x, y, null, true);
+// Display display = getDisplay();
+// Cursor newCursor = cursor;
+// if (renderer.hasLink(offset)) {
+// newCursor = display.getSystemCursor(SWT.CURSOR_HAND);
+// } else {
+// if (cursor == null) {
+// int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM;
+// newCursor = display.getSystemCursor(type);
+// }
+// }
+// if (newCursor != getCursor()) super.setCursor(newCursor);
+//}
+///**
+// * Moves the caret to the specified location.
+// *
+// * @param x x location of the new caret position
+// * @param y y location of the new caret position
+// * @param select the location change is a selection operation.
+// * include the line delimiter in the selection
+// */
+//void doMouseLocationChange(int x, int y, boolean select) {
+// int line = getLineIndex(y);
+//
+// updateCaretDirection = true;
+//
+// if (blockSelection) {
+// x = Math.max(leftMargin, Math.min(x, clientAreaWidth - rightMargin));
+// y = Math.max(topMargin, Math.min(y, clientAreaHeight - bottomMargin));
+// if (doubleClickEnabled && clickCount > 1) {
+// boolean wordSelect = (clickCount & 1) == 0;
+// if (wordSelect) {
+// Point left = getPointAtOffset(doubleClickSelection.x);
+// int[] trailing = new int[1];
+// int offset = getOffsetAtPoint(x, y, trailing, true);
+// if (offset != -1) {
+// if (x > left.x) {
+// offset = getWordNext(offset + trailing[0], SWT.MOVEMENT_WORD_END);
+// setBlockSelectionOffset(doubleClickSelection.x, offset, true);
+// } else {
+// offset = getWordPrevious(offset + trailing[0], SWT.MOVEMENT_WORD_START);
+// setBlockSelectionOffset(doubleClickSelection.y, offset, true);
+// }
+// } else {
+// if (x > left.x) {
+// setBlockSelectionLocation(left.x, left.y, x, y, true);
+// } else {
+// Point right = getPointAtOffset(doubleClickSelection.y);
+// setBlockSelectionLocation(right.x, right.y, x, y, true);
+// }
+// }
+// } else {
+// setBlockSelectionLocation(blockXLocation, y, true);
+// }
+// return;
+// } else {
+// if (select) {
+// if (blockXLocation == -1) {
+// setBlockSelectionOffset(caretOffsets[0], false);
+// }
+// } else {
+// clearBlockSelection(true, false);
+// }
+// int[] trailing = new int[1];
+// int offset = getOffsetAtPoint(x, y, trailing, true);
+// if (offset != -1) {
+// if (select) {
+// setBlockSelectionOffset(offset + trailing[0], true);
+// return;
+// }
+// } else {
+// if (isFixedLineHeight() && renderer.fixedPitch) {
+// int avg = renderer.averageCharWidth;
+// x = ((x + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
+// }
+// setBlockSelectionLocation(x, y, true);
+// return;
+// }
+// }
+// }
+//
+// // allow caret to be placed below first line only if receiver is
+// // not in single line mode. fixes 4820.
+// if (line < 0 || (isSingleLine() && line > 0)) {
+// return;
+// }
+// int[] alignment = new int[1];
+// int newCaretOffset = getOffsetAtPoint(x, y, alignment);
+// int newCaretAlignemnt = alignment[0];
+//
+// if (doubleClickEnabled && clickCount > 1) {
+// newCaretOffset = doMouseWordSelect(x, newCaretOffset, line);
+// }
+//
+// int newCaretLine = content.getLineAtOffset(newCaretOffset);
+//
+// // Is the mouse within the left client area border or on
+// // a different line? If not the autoscroll selection
+// // could be incorrectly reset. Fixes 1GKM3XS
+// boolean vchange = 0 <= y && y < clientAreaHeight || newCaretLine == 0 || newCaretLine == content.getLineCount() - 1;
+// boolean hchange = 0 <= x && x < clientAreaWidth || wordWrap || newCaretLine != content.getLineAtOffset(caretOffsets[0]);
+// if (vchange && hchange && (newCaretOffset != caretOffsets[0] || newCaretAlignemnt != caretAlignment)) {
+// setCaretOffsets(new int[] {newCaretOffset}, newCaretAlignemnt);
+// if (select) doMouseSelection();
+// showCaret();
+// }
+// if (!select) {
+// setCaretOffsets(new int[] {newCaretOffset}, newCaretAlignemnt);
+// clearSelection(true);
+// }
+//}
+///**
+// * Updates the selection based on the caret position
+// */
+//void doMouseSelection() {
+// if (caretOffsets[0] <= selection[0].x ||
+// (caretOffsets[0] > selection[0].x &&
+// caretOffsets[0] < selection[0].y && selectionAnchors[0] == selection[0].x)) {
+// doSelection(ST.COLUMN_PREVIOUS);
+// } else {
+// doSelection(ST.COLUMN_NEXT);
+// }
+//}
+///**
+// * Returns the offset of the word at the specified offset.
+// * If the current selection extends from high index to low index
+// * (i.e., right to left, or caret is at left border of selection on
+// * non-bidi platforms) the start offset of the word preceding the
+// * selection is returned. If the current selection extends from
+// * low index to high index the end offset of the word following
+// * the selection is returned.
+// *
+// * @param x mouse x location
+// * @param newCaretOffset caret offset of the mouse cursor location
+// * @param line line index of the mouse cursor location
+// */
+//int doMouseWordSelect(int x, int newCaretOffset, int line) {
+// // flip selection anchor based on word selection direction from
+// // base double click. Always do this here (and don't rely on doAutoScroll)
+// // because auto scroll only does not cover all possible mouse selections
+// // (e.g., mouse x < 0 && mouse y > caret line y)
+// if (newCaretOffset < selectionAnchors[0] && selectionAnchors[0] == selection[0].x) {
+// selectionAnchors[0] = doubleClickSelection.y;
+// } else if (newCaretOffset > selectionAnchors[0] && selectionAnchors[0] == selection[0].y) {
+// selectionAnchors[0] = doubleClickSelection.x;
+// }
+// if (0 <= x && x < clientAreaWidth) {
+// boolean wordSelect = (clickCount & 1) == 0;
+// if (caretOffsets[0] == selection[0].x) {
+// if (wordSelect) {
+// newCaretOffset = getWordPrevious(newCaretOffset, SWT.MOVEMENT_WORD_START);
+// } else {
+// newCaretOffset = content.getOffsetAtLine(line);
+// }
+// } else {
+// if (wordSelect) {
+// newCaretOffset = getWordNext(newCaretOffset, SWT.MOVEMENT_WORD_END);
+// } else {
+// int lineEnd = content.getCharCount();
+// if (line + 1 < content.getLineCount()) {
+// lineEnd = content.getOffsetAtLine(line + 1);
+// }
+// newCaretOffset = lineEnd;
+// }
+// }
+// }
+// return newCaretOffset;
+//}
+///**
+// * Scrolls one page down so that the last line (truncated or whole)
+// * of the current page becomes the fully visible top line.
+// *
+// * The caret is scrolled the same number of lines so that its location
+// * relative to the top line remains the same. The exception is the end
+// * of the text where a full page scroll is not possible. In this case
+// * the caret is moved after the last character.
+// *
+// *
+// * @param select whether or not to select the page
+// */
+//void doPageDown(boolean select, int height) {
+// if (isSingleLine()) return;
+// int oldColumnX = columnX;
+// int oldHScrollOffset = horizontalScrollOffset;
+// if (isFixedLineHeight()) {
+// int lineCount = content.getLineCount();
+// int caretLine = getFirstCaretLine();
+// if (caretLine < lineCount - 1) {
+// int lineHeight = renderer.getLineHeight();
+// int lines = (height == -1 ? clientAreaHeight : height) / lineHeight;
+// int scrollLines = Math.min(lineCount - caretLine - 1, lines);
+// // ensure that scrollLines never gets negative and at least one
+// // line is scrolled. fixes bug 5602.
+// scrollLines = Math.max(1, scrollLines);
+// int[] alignment = new int[1];
+// int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines), alignment);
+// setCaretOffsets(new int[] {offset}, alignment[0]);
+// if (select) {
+// doSelection(ST.COLUMN_NEXT);
+// }
+// // scroll one page down or to the bottom
+// int verticalMaximum = lineCount * getVerticalIncrement();
+// int pageSize = clientAreaHeight;
+// int verticalScrollOffset = getVerticalScrollOffset();
+// int scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement();
+// if (scrollOffset + pageSize > verticalMaximum) {
+// scrollOffset = verticalMaximum - pageSize;
+// }
+// if (scrollOffset > verticalScrollOffset) {
+// scrollVertical(scrollOffset - verticalScrollOffset, true);
+// }
+// }
+// } else {
+// int lineCount = content.getLineCount();
+// int lineIndex, lineHeight;
+// if (height == -1) {
+// lineIndex = getPartialBottomIndex();
+// int topY = getLinePixel(lineIndex);
+// lineHeight = renderer.getLineHeight(lineIndex);
+// height = topY;
+// if (topY + lineHeight <= clientAreaHeight) {
+// height += lineHeight;
+// } else {
+// if (isWordWrap()) {
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// int y = clientAreaHeight - topY;
+// for (int i = 0; i < layout.getLineCount(); i++) {
+// Rectangle bounds = layout.getLineBounds(i);
+// if (bounds.contains(bounds.x, y)) {
+// height += bounds.y;
+// break;
+// }
+// }
+// renderer.disposeTextLayout(layout);
+// }
+// }
+// } else {
+// lineIndex = getLineIndex(height);
+// int topLineY = getLinePixel(lineIndex);
+// if (isWordWrap()) {
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// int y = height - topLineY;
+// for (int i = 0; i < layout.getLineCount(); i++) {
+// Rectangle bounds = layout.getLineBounds(i);
+// if (bounds.contains(bounds.x, y)) {
+// height = topLineY + bounds.y + bounds.height;
+// break;
+// }
+// }
+// renderer.disposeTextLayout(layout);
+// } else {
+// height = topLineY + renderer.getLineHeight(lineIndex);
+// }
+// }
+// int caretHeight = height;
+// if (isWordWrap()) {
+// for (int caretOffset : caretOffsets) {
+// int caretLine = content.getLineAtOffset(caretOffset);
+// TextLayout layout = renderer.getTextLayout(caretLine);
+// int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine);
+// lineIndex = getVisualLineIndex(layout, offsetInLine);
+// caretHeight += layout.getLineBounds(lineIndex).y;
+// renderer.disposeTextLayout(layout);
+// }
+// }
+// lineIndex = getFirstCaretLine();
+// lineHeight = renderer.getLineHeight(lineIndex);
+// while (caretHeight - lineHeight >= 0 && lineIndex < lineCount - 1) {
+// caretHeight -= lineHeight;
+// lineHeight = renderer.getLineHeight(++lineIndex);
+// }
+// int[] alignment = new int[1];
+// int offset = getOffsetAtPoint(columnX, caretHeight, lineIndex, alignment);
+// setCaretOffsets(new int[] {offset}, alignment[0]);
+// if (select) doSelection(ST.COLUMN_NEXT);
+// height = getAvailableHeightBellow(height);
+// scrollVertical(height, true);
+// if (height == 0) setCaretLocations();
+// }
+// showCaret();
+// int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+// columnX = oldColumnX + hScrollChange;
+//}
+///**
+// * Moves the cursor to the end of the last fully visible line.
+// */
+//void doPageEnd() {
+// // go to end of line if in single line mode. fixes 5673
+// if (isSingleLine()) {
+// doLineEnd();
+// } else if (caretOffsets.length == 1) { // pageEnd doesn't make sense with multi-carets
+// int bottomOffset;
+// if (isWordWrap()) {
+// int lineIndex = getPartialBottomIndex();
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// int y = (clientAreaHeight - bottomMargin) - getLinePixel(lineIndex);
+// int index = layout.getLineCount() - 1;
+// while (index >= 0) {
+// Rectangle bounds = layout.getLineBounds(index);
+// if (y >= bounds.y + bounds.height) break;
+// index--;
+// }
+// if (index == -1 && lineIndex > 0) {
+// bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length();
+// } else {
+// bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1);
+// }
+// renderer.disposeTextLayout(layout);
+// } else {
+// int lineIndex = getBottomIndex();
+// bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length();
+// }
+// if (caretOffsets[0] < bottomOffset) {
+// setCaretOffsets(new int[] {bottomOffset}, OFFSET_LEADING);
+// showCaret();
+// }
+// }
+//}
+///**
+// * Moves the cursor to the beginning of the first fully visible line.
+// */
+//void doPageStart() {
+// int topOffset;
+// if (isWordWrap()) {
+// int y, lineIndex;
+// if (topIndexY > 0) {
+// lineIndex = topIndex - 1;
+// y = renderer.getLineHeight(lineIndex) - topIndexY;
+// } else {
+// lineIndex = topIndex;
+// y = -topIndexY;
+// }
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// int index = 0;
+// int lineCount = layout.getLineCount();
+// while (index < lineCount) {
+// Rectangle bounds = layout.getLineBounds(index);
+// if (y <= bounds.y) break;
+// index++;
+// }
+// if (index == lineCount) {
+// topOffset = content.getOffsetAtLine(lineIndex + 1);
+// } else {
+// topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index];
+// }
+// renderer.disposeTextLayout(layout);
+// } else {
+// topOffset = content.getOffsetAtLine(topIndex);
+// }
+// if (caretOffsets[0] > topOffset) {
+// setCaretOffsets(new int[] {topOffset}, OFFSET_LEADING);
+// showCaret();
+// }
+//}
+///**
+// * Scrolls one page up so that the first line (truncated or whole)
+// * of the current page becomes the fully visible last line.
+// * The caret is scrolled the same number of lines so that its location
+// * relative to the top line remains the same. The exception is the beginning
+// * of the text where a full page scroll is not possible. In this case the
+// * caret is moved in front of the first character.
+// */
+//void doPageUp(boolean select, int height) {
+// if (isSingleLine()) return;
+// int oldHScrollOffset = horizontalScrollOffset;
+// int oldColumnX = columnX;
+// if (isFixedLineHeight()) {
+// int caretLine = getFirstCaretLine();
+// if (caretLine > 0) {
+// int lineHeight = renderer.getLineHeight();
+// int lines = (height == -1 ? clientAreaHeight : height) / lineHeight;
+// int scrollLines = Math.max(1, Math.min(caretLine, lines));
+// caretLine -= scrollLines;
+// int[] alignment = new int[1];
+// int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine), alignment);
+// setCaretOffsets(new int[] {offset}, alignment[0]);
+// if (select) {
+// doSelection(ST.COLUMN_PREVIOUS);
+// }
+// int verticalScrollOffset = getVerticalScrollOffset();
+// int scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement());
+// if (scrollOffset < verticalScrollOffset) {
+// scrollVertical(scrollOffset - verticalScrollOffset, true);
+// }
+// }
+// } else {
+// int lineHeight, lineIndex;
+// if (height == -1) {
+// if (topIndexY == 0) {
+// height = clientAreaHeight;
+// } else {
+// int y;
+// if (topIndex > 0) {
+// lineIndex = topIndex - 1;
+// lineHeight = renderer.getLineHeight(lineIndex);
+// height = clientAreaHeight - topIndexY;
+// y = lineHeight - topIndexY;
+// } else {
+// lineIndex = topIndex;
+// lineHeight = renderer.getLineHeight(lineIndex);
+// height = clientAreaHeight - (lineHeight + topIndexY);
+// y = -topIndexY;
+// }
+// if (isWordWrap()) {
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// for (int i = 0; i < layout.getLineCount(); i++) {
+// Rectangle bounds = layout.getLineBounds(i);
+// if (bounds.contains(bounds.x, y)) {
+// height += lineHeight - (bounds.y + bounds.height);
+// break;
+// }
+// }
+// renderer.disposeTextLayout(layout);
+// }
+// }
+// } else {
+// lineIndex = getLineIndex(clientAreaHeight - height);
+// int topLineY = getLinePixel(lineIndex);
+// if (isWordWrap()) {
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// int y = topLineY;
+// for (int i = 0; i < layout.getLineCount(); i++) {
+// Rectangle bounds = layout.getLineBounds(i);
+// if (bounds.contains(bounds.x, y)) {
+// height = clientAreaHeight - (topLineY + bounds.y);
+// break;
+// }
+// }
+// renderer.disposeTextLayout(layout);
+// } else {
+// height = clientAreaHeight - topLineY;
+// }
+// }
+// int caretHeight = height;
+// if (isWordWrap()) {
+// for (int caretOffset : caretOffsets) {
+// int caretLine = content.getLineAtOffset(caretOffset);
+// TextLayout layout = renderer.getTextLayout(caretLine);
+// int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine);
+// lineIndex = getVisualLineIndex(layout, offsetInLine);
+// caretHeight += layout.getBounds().height - layout.getLineBounds(lineIndex).y;
+// renderer.disposeTextLayout(layout);
+// }
+// }
+// lineIndex = getFirstCaretLine();
+// lineHeight = renderer.getLineHeight(lineIndex);
+// while (caretHeight - lineHeight >= 0 && lineIndex > 0) {
+// caretHeight -= lineHeight;
+// lineHeight = renderer.getLineHeight(--lineIndex);
+// }
+// lineHeight = renderer.getLineHeight(lineIndex);
+// int[] alignment = new int[1];
+// int offset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex, alignment);
+// setCaretOffsets(new int[] {offset}, alignment[0]);
+// if (select) doSelection(ST.COLUMN_PREVIOUS);
+// height = getAvailableHeightAbove(height);
+// scrollVertical(-height, true);
+// if (height == 0) setCaretLocations();
+// }
+// showCaret();
+// int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+// columnX = oldColumnX + hScrollChange;
+//}
+///**
+// * Updates the selection to extend to the current caret position.
+// */
+//void doSelection(int direction) {
+// if (caretOffsets.length != selection.length) {
+// return;
+// }
+// if (selectionAnchors.length != selection.length) {
+// selectionAnchors = new int[selection.length];
+// Arrays.fill(selectionAnchors, -1);
+// }
+// boolean selectionChanged = false;
+// Point[] newSelection = Arrays.stream(selection).map(p -> new Point(p.x, p.y)).toArray(Point[]::new);
+// boolean[] caretAtBeginning = new boolean[newSelection.length];
+// for (int i = 0; i < caretOffsets.length; i++) {
+// int caretOffset = caretOffsets[i];
+// Point currentSelection = newSelection[i];
+// int selectionAnchor = selectionAnchors[i];
+// if (selectionAnchor == -1) {
+// selectionAnchor = selectionAnchors[i] = currentSelection.x;
+// }
+// int redrawStart = -1;
+// int redrawEnd = -1;
+// if (direction == ST.COLUMN_PREVIOUS) {
+// if (caretOffset < currentSelection.x) {
+// caretAtBeginning[i] = true;
+// // grow selection
+// redrawEnd = currentSelection.x;
+// redrawStart = currentSelection.x = caretOffset;
+// // check if selection has reversed direction
+// if (currentSelection.y != selectionAnchor) {
+// redrawEnd = currentSelection.y;
+// currentSelection.y = selectionAnchor;
+// }
+// // test whether selection actually changed. Fixes 1G71EO1
+// } else if (selectionAnchor == currentSelection.x && caretOffset < currentSelection.y) {
+// // caret moved towards selection anchor (left side of selection).
+// // shrink selection
+// redrawEnd = currentSelection.y;
+// redrawStart = currentSelection.y = caretOffset;
+// }
+// } else {
+// if (caretOffset > currentSelection.y) {
+// // grow selection
+// redrawStart = currentSelection.y;
+// redrawEnd = currentSelection.y = caretOffset;
+// // check if selection has reversed direction
+// if (currentSelection.x != selectionAnchor) {
+// redrawStart = currentSelection.x;
+// currentSelection.x = selectionAnchor;
+// }
+// // test whether selection actually changed. Fixes 1G71EO1
+// } else if (selectionAnchor == currentSelection.y && caretOffset > currentSelection.x) {
+// // caret moved towards selection anchor (right side of selection).
+// // shrink selection
+// caretAtBeginning[i] = true;
+// redrawStart = currentSelection.x;
+// redrawEnd = currentSelection.x = caretOffset;
+// }
+// }
+// if (redrawStart != -1 && redrawEnd != -1) {
+// internalRedrawRange(redrawStart, redrawEnd - redrawStart);
+// selectionChanged = true;
+// }
+// }
+// if (selectionChanged) {
+// int[] regions = new int[newSelection.length * 2];
+// for (int i = 0; i < newSelection.length; i++) {
+// Point p = newSelection[i];
+// if (caretAtBeginning[i]) {
+// regions[2 * i] = p.y;
+// regions[2 * i + 1] = p.x - p.y;
+// } else {
+// regions[2 * i] = p.x;
+// regions[2 * i + 1] = p.y - p.x;
+// }
+// }
+// setSelection(regions, false, blockSelection);
+// sendSelectionEvent();
+// }
+// sendAccessibleTextCaretMoved();
+//}
+///**
+// * Moves the caret to the next character or to the beginning of the
+// * next line if the cursor is at the end of a line.
+// */
+//void doSelectionCursorNext() {
+// int[] newCarets = Arrays.copyOf(caretOffsets, caretOffsets.length);
+// int newAlignment = Integer.MIN_VALUE;
+// for (int i = 0; i < caretOffsets.length; i++) {
+// int caretOffset = caretOffsets[i];
+// int caretLine = content.getLineAtOffset(caretOffset);
+// int lineOffset = content.getOffsetAtLine(caretLine);
+// int offsetInLine = caretOffset - lineOffset;
+// int offset;
+// if (offsetInLine < content.getLine(caretLine).length()) {
+// TextLayout layout = renderer.getTextLayout(caretLine);
+// offsetInLine = layout.getNextOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
+// int lineStart = layout.getLineOffsets()[layout.getLineIndex(offsetInLine)];
+// renderer.disposeTextLayout(layout);
+// offset = offsetInLine + lineOffset;
+// newAlignment = offsetInLine == lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING;
+// newCarets[i] = offset;
+// } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) {
+// caretLine++;
+// offset = content.getOffsetAtLine(caretLine);
+// newAlignment = PREVIOUS_OFFSET_TRAILING;
+// newCarets[i] = offset;
+// }
+// }
+// if (newAlignment > Integer.MIN_VALUE) {
+// setCaretOffsets(newCarets, newAlignment);
+// showCaret();
+// }
+//}
+///**
+// * Moves the caret to the previous character or to the end of the previous
+// * line if the cursor is at the beginning of a line.
+// */
+//void doSelectionCursorPrevious() {
+// int[] newCarets = Arrays.copyOf(caretOffsets, caretOffsets.length);
+// for (int i = 0; i < caretOffsets.length; i++) {
+// int caretOffset = caretOffsets[i];
+// int caretLine = content.getLineAtOffset(caretOffset);
+// int lineOffset = content.getOffsetAtLine(caretLine);
+// int offsetInLine = caretOffset - lineOffset;
+// if (offsetInLine > 0) {
+// newCarets[i] = getClusterPrevious(caretOffset, caretLine);
+// } else if (caretLine > 0) {
+// caretLine--;
+// lineOffset = content.getOffsetAtLine(caretLine);
+// newCarets[i] = lineOffset + content.getLine(caretLine).length();
+// }
+// }
+// if (!Arrays.equals(caretOffsets, newCarets)) {
+// setCaretOffsets(newCarets, OFFSET_LEADING);
+// showCaret();
+// }
+//}
+///**
+// * Moves the caret one line down and to the same character offset relative
+// * to the beginning of the line. Moves the caret to the end of the new line
+// * if the new line is shorter than the character offset.
+// * Moves the caret to the end of the text if the caret already is on the
+// * last line.
+// * Adjusts the selection according to the caret change. This can either add
+// * to or subtract from the old selection, depending on the previous selection
+// * direction.
+// */
+//void doSelectionLineDown() {
+// int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x;
+// doLineDown(true);
+// columnX = oldColumnX;
+//}
+///**
+// * Moves the caret one line up and to the same character offset relative
+// * to the beginning of the line. Moves the caret to the end of the new line
+// * if the new line is shorter than the character offset.
+// * Moves the caret to the beginning of the document if it is already on the
+// * first line.
+// * Adjusts the selection according to the caret change. This can either add
+// * to or subtract from the old selection, depending on the previous selection
+// * direction.
+// */
+//void doSelectionLineUp() {
+// int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x;
+// doLineUp(true);
+// columnX = oldColumnX;
+//}
+///**
+// * Scrolls one page down so that the last line (truncated or whole)
+// * of the current page becomes the fully visible top line.
+// *
+// * The caret is scrolled the same number of lines so that its location
+// * relative to the top line remains the same. The exception is the end
+// * of the text where a full page scroll is not possible. In this case
+// * the caret is moved after the last character.
+// *
+// * Adjusts the selection according to the caret change. This can either add
+// * to or subtract from the old selection, depending on the previous selection
+// * direction.
+// *
+// */
+//void doSelectionPageDown(int pixels) {
+// int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x;
+// doPageDown(true, pixels);
+// columnX = oldColumnX;
+//}
+///**
+// * Scrolls one page up so that the first line (truncated or whole)
+// * of the current page becomes the fully visible last line.
+// *
+// * The caret is scrolled the same number of lines so that its location
+// * relative to the top line remains the same. The exception is the beginning
+// * of the text where a full page scroll is not possible. In this case the
+// * caret is moved in front of the first character.
+// *
+// * Adjusts the selection according to the caret change. This can either add
+// * to or subtract from the old selection, depending on the previous selection
+// * direction.
+// *
+// */
+//void doSelectionPageUp(int pixels) {
+// if (caretOffsets.length > 1) { // operation doesn't make sense for multi-carets
+// return;
+// }
+// int oldColumnX = columnX = getPointAtOffset(caretOffsets[0]).x;
+// doPageUp(true, pixels);
+// columnX = oldColumnX;
+//}
+///**
+// * Moves the caret to the end of the next word .
+// */
+//void doSelectionWordNext() {
+// int[] offsets = Arrays.stream(caretOffsets).map(offset -> getWordNext(offset, SWT.MOVEMENT_WORD)).toArray();
+// // don't change caret position if in single line mode and the cursor
+// // would be on a different line. fixes 5673
+// if (!isSingleLine()) {
+// // Force symmetrical movement for word next and previous. Fixes 14536
+// setCaretOffsets(offsets, OFFSET_LEADING);
+// showCaret();
+// } else {
+// int[] linesForCurrentCarets = Arrays.stream(caretOffsets).map(offset -> content.getLineAtOffset(offset)).toArray();
+// int[] linesForNewCarets = Arrays.stream(offsets).map(offset -> content.getLineAtOffset(offset)).toArray();
+// if (Arrays.equals(linesForCurrentCarets, linesForNewCarets)) {
+// // Force symmetrical movement for word next and previous. Fixes 14536
+// setCaretOffsets(offsets, OFFSET_LEADING);
+// showCaret();
+// }
+// }
+//}
+///**
+// * Moves the caret to the start of the previous word.
+// */
+//void doSelectionWordPrevious() {
+// setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getWordPrevious(offset, SWT.MOVEMENT_WORD)).toArray(), OFFSET_LEADING);
+// showCaret();
+//}
+///**
+// * Moves the caret one character to the left. Do not go to the previous line.
+// * When in a bidi locale and at a R2L character the caret is moved to the
+// * beginning of the R2L segment (visually right) and then one character to the
+// * left (visually left because it's now in a L2R segment).
+// */
+//void doVisualPrevious() {
+// setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getClusterPrevious(offset, content.getLineAtOffset(offset))).toArray(), SWT.DEFAULT);
+// showCaret();
+//}
+///**
+// * Moves the caret one character to the right. Do not go to the next line.
+// * When in a bidi locale and at a R2L character the caret is moved to the
+// * end of the R2L segment (visually left) and then one character to the
+// * right (visually right because it's now in a L2R segment).
+// */
+//void doVisualNext() {
+// setCaretOffsets(Arrays.stream(caretOffsets).map(offset -> getClusterNext(offset, content.getLineAtOffset(offset))).toArray(), SWT.DEFAULT);
+// showCaret();
+//}
+///**
+// * Moves the caret to the end of the next word.
+// * If a selection exists, move the caret to the end of the selection
+// * and remove the selection.
+// */
+//void doWordNext() {
+// if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) {
+// setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.y).toArray(), SWT.DEFAULT);
+// showCaret();
+// } else {
+// doSelectionWordNext();
+// }
+//}
+///**
+// * Moves the caret to the start of the previous word.
+// * If a selection exists, move the caret to the start of the selection
+// * and remove the selection.
+// */
+//void doWordPrevious() {
+// if (Arrays.stream(selection).anyMatch(p -> p.x != p.y)) {
+// setCaretOffsets(Arrays.stream(selection).mapToInt(sel -> sel.x).toArray(), SWT.DEFAULT);
+// showCaret();
+// } else {
+// doSelectionWordPrevious();
+// }
+//}
+///**
+// * Ends the autoscroll process.
+// */
+//void endAutoScroll() {
+// autoScrollDirection = SWT.NULL;
+//}
+//@Override
+//public Color getBackground() {
+// checkWidget();
+// if (background == null) {
+// return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+// }
+// return background;
+//}
+///**
+// * Returns the baseline, in points.
+// *
+// * Note: this API should not be used if a StyleRange attribute causes lines to
+// * have different heights (i.e. different fonts, rise, etc).
+// *
+// * @return baseline the baseline
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @since 3.0
+// *
+// * @see #getBaseline(int)
+// */
+//public int getBaseline() {
+// checkWidget();
+// return renderer.getBaseline();
+//}
+///**
+// * Returns the baseline at the given offset, in points.
+// *
+// * @param offset the offset
+// *
+// * @return baseline the baseline
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
+// *
+// *
+// * @since 3.2
+// */
+//public int getBaseline(int offset) {
+// checkWidget();
+// if (!(0 <= offset && offset <= content.getCharCount())) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// if (isFixedLineHeight()) {
+// return renderer.getBaseline();
+// }
+// int lineIndex = content.getLineAtOffset(offset);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length()));
+// FontMetrics metrics = layout.getLineMetrics(lineInParagraph);
+// renderer.disposeTextLayout(layout);
+// return metrics.getAscent() + metrics.getLeading();
+//}
+///**
+// * Gets the BIDI coloring mode. When true the BIDI text display
+// * algorithm is applied to segments of text that are the same
+// * color.
+// *
+// * @return the current coloring mode
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @deprecated use BidiSegmentListener instead.
+// */
+//@Deprecated
+//public boolean getBidiColoring() {
+// checkWidget();
+// return bidiColoring;
+//}
+///**
+// * Returns whether the widget is in block selection mode.
+// *
+// * @return true if widget is in block selection mode, false otherwise
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public boolean getBlockSelection() {
+// checkWidget();
+// return blockSelection;
+//}
+//Rectangle getBlockSelectionPosition() {
+// int firstLine = getLineIndex(blockYAnchor - getVerticalScrollOffset());
+// int lastLine = getLineIndex(blockYLocation - getVerticalScrollOffset());
+// if (firstLine > lastLine) {
+// int temp = firstLine;
+// firstLine = lastLine;
+// lastLine = temp;
+// }
+// int left = blockXAnchor;
+// int right = blockXLocation;
+// if (left > right) {
+// left = blockXLocation;
+// right = blockXAnchor;
+// }
+// return new Rectangle (left - horizontalScrollOffset, firstLine, right - horizontalScrollOffset, lastLine);
+//}
+///**
+// * Returns the block selection bounds. The bounds is
+// * relative to the upper left corner of the document.
+// *
+// * @return the block selection bounds
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public Rectangle getBlockSelectionBounds() {
+// Rectangle rect;
+// if (blockSelection && blockXLocation != -1) {
+// rect = getBlockSelectionRectangle();
+// } else {
+// Point startPoint = getPointAtOffset(selection[0].x);
+// Point endPoint = getPointAtOffset(selection[0].y);
+// int height = getLineHeight(selection[0].y);
+// rect = new Rectangle(startPoint.x, startPoint.y, endPoint.x - startPoint.x, endPoint.y + height - startPoint.y);
+// if (selection[0].x == selection[0].y) {
+// rect.width = getCaretWidth();
+// }
+// }
+// rect.x += horizontalScrollOffset;
+// rect.y += getVerticalScrollOffset();
+// return rect;
+//}
+//Rectangle getBlockSelectionRectangle() {
+// Rectangle rect = getBlockSelectionPosition();
+// rect.y = getLinePixel(rect.y);
+// rect.width = rect.width - rect.x;
+// rect.height = getLinePixel(rect.height + 1) - rect.y;
+// return rect;
+//}
+//String getBlockSelectionText(String delimiter) {
+// Rectangle rect = getBlockSelectionPosition();
+// int firstLine = rect.y;
+// int lastLine = rect.height;
+// int left = rect.x;
+// int right = rect.width;
+// StringBuilder buffer = new StringBuilder();
+// for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
+// int start = getOffsetAtPoint(left, 0, lineIndex, null);
+// int end = getOffsetAtPoint(right, 0, lineIndex, null);
+// if (start > end) {
+// int temp = start;
+// start = end;
+// end = temp;
+// }
+// String text = content.getTextRange(start, end - start);
+// buffer.append(text);
+// if (lineIndex < lastLine) buffer.append(delimiter);
+// }
+// return buffer.toString();
+//}
+///**
+// * Returns the index of the last fully visible line.
+// *
+// * @return index of the last fully visible line.
+// */
+//int getBottomIndex() {
+// int bottomIndex;
+// if (isFixedLineHeight()) {
+// int lineCount = 1;
+// int lineHeight = renderer.getLineHeight();
+// if (lineHeight != 0) {
+// // calculate the number of lines that are fully visible
+// int partialTopLineHeight = topIndex * lineHeight - getVerticalScrollOffset();
+// lineCount = (clientAreaHeight - partialTopLineHeight) / lineHeight;
+// }
+// bottomIndex = Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1));
+// } else {
+// int clientAreaHeight = this.clientAreaHeight - bottomMargin;
+// bottomIndex = getLineIndex(clientAreaHeight);
+// if (bottomIndex > 0) {
+// int linePixel = getLinePixel(bottomIndex);
+// int lineHeight = renderer.getLineHeight(bottomIndex);
+// if (linePixel + lineHeight > clientAreaHeight) {
+// if (getLinePixel(bottomIndex - 1) >= topMargin) {
+// bottomIndex--;
+// }
+// }
+// }
+// }
+// return bottomIndex;
+//}
+///**
+// * Returns the bottom margin.
+// *
+// * @return the bottom margin.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public int getBottomMargin() {
+// checkWidget();
+// return bottomMargin;
+//}
+//Rectangle getBoundsAtOffset(int offset) {
+// int lineIndex = content.getLineAtOffset(offset);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// String line = content.getLine(lineIndex);
+// Rectangle bounds;
+// if (line.length() != 0) {
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// int offsetInLine = Math.min (layout.getText().length(), Math.max (0, offset - lineOffset));
+// bounds = layout.getBounds(offsetInLine, offsetInLine);
+// if (getListeners(ST.LineGetSegments).length > 0 && caretAlignment == PREVIOUS_OFFSET_TRAILING && offsetInLine != 0) {
+// offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
+// Point point = layout.getLocation(offsetInLine, true);
+// bounds = new Rectangle (point.x, point.y, 0, bounds.height);
+// }
+// renderer.disposeTextLayout(layout);
+// } else {
+// bounds = new Rectangle (0, 0, 0, renderer.getLineHeight());
+// }
+// if (Arrays.binarySearch(caretOffsets, offset) >= 0 && !isWordWrap()) {
+// int lineEnd = lineOffset + line.length();
+// if (offset == lineEnd) {
+// bounds.width += getCaretWidth();
+// }
+// }
+// bounds.x += leftMargin - horizontalScrollOffset;
+// bounds.y += getLinePixel(lineIndex);
+// return bounds;
+//}
+///**
+// * Returns the caret position relative to the start of the text.
+// *
+// * @return the caret position relative to the start of the text.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public int getCaretOffset() {
+// checkWidget();
+// return caretOffsets[0];
+//}
+///**
+// * Returns the caret width.
+// *
+// * @return the caret width, 0 if caret is null.
+// */
+//int getCaretWidth() {
+// Caret caret = getCaret();
+// if (caret == null) return 0;
+// return caret.getSize().x;
+//}
+//Object getClipboardContent(int clipboardType) {
+// TextTransfer plainTextTransfer = TextTransfer.getInstance();
+// return clipboard.getContents(plainTextTransfer, clipboardType);
+//}
+//int getClusterNext(int offset, int lineIndex) {
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// offset -= lineOffset;
+// offset = layout.getNextOffset(offset, SWT.MOVEMENT_CLUSTER);
+// offset += lineOffset;
+// renderer.disposeTextLayout(layout);
+// return offset;
+//}
+//int getClusterPrevious(int offset, int lineIndex) {
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// offset -= lineOffset;
+// offset = layout.getPreviousOffset(offset, SWT.MOVEMENT_CLUSTER);
+// offset += lineOffset;
+// renderer.disposeTextLayout(layout);
+// return offset;
+//}
+///**
+// * Returns the content implementation that is used for text storage.
+// *
+// * @return content the user defined content implementation that is used for
+// * text storage or the default content implementation if no user defined
+// * content implementation has been set.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public StyledTextContent getContent() {
+// checkWidget();
+// return content;
+//}
+//@Override
+//public boolean getDragDetect () {
+// checkWidget ();
+// return dragDetect;
+//}
+///**
+// * Returns whether the widget implements double click mouse behavior.
+// *
+// * @return true if double clicking a word selects the word, false if double clicks
+// * have the same effect as regular mouse clicks
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public boolean getDoubleClickEnabled() {
+// checkWidget();
+// return doubleClickEnabled;
+//}
+///**
+// * Returns whether the widget content can be edited.
+// *
+// * @return true if content can be edited, false otherwise
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public boolean getEditable() {
+// checkWidget();
+// return editable;
+//}
+//@Override
+//public Color getForeground() {
+// checkWidget();
+// if (foreground == null) {
+// return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+// }
+// return foreground;
+//}
+///**
+// * Returns the horizontal scroll increment.
+// *
+// * @return horizontal scroll increment.
+// */
+//int getHorizontalIncrement() {
+// return renderer.averageCharWidth;
+//}
+///**
+// * Returns the horizontal scroll offset relative to the start of the line.
+// *
+// * @return horizontal scroll offset relative to the start of the line,
+// * measured in character increments starting at 0, if > 0 the content is scrolled
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public int getHorizontalIndex() {
+// checkWidget();
+// return horizontalScrollOffset / getHorizontalIncrement();
+//}
+///**
+// * Returns the horizontal scroll offset relative to the start of the line.
+// *
+// * @return the horizontal scroll offset relative to the start of the line,
+// * measured in SWT logical point starting at 0, if > 0 the content is scrolled.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public int getHorizontalPixel() {
+// checkWidget();
+// return horizontalScrollOffset;
+//}
+///**
+// * Returns the line indentation of the widget.
+// *
+// * @return the line indentation
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see #getLineJustify(int)
+// *
+// * @since 3.2
+// */
+//public boolean getJustify() {
+// checkWidget();
+// return justify;
+//}
+///**
+// * Returns the action assigned to the key.
+// * Returns SWT.NULL if there is no action associated with the key.
+// *
+// * @param key a key code defined in SWT.java or a character.
+// * Optionally ORd with a state mask. Preferred state masks are one or more of
+// * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform
+// * differences. However, there may be cases where using the specific state masks
+// * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
+// * @return one of the predefined actions defined in ST.java or SWT.NULL
+// * if there is no action associated with the key.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public int getKeyBinding(int key) {
+// checkWidget();
+// Integer action = keyActionMap.get(key);
+// return action == null ? SWT.NULL : action.intValue();
+//}
+///**
+// * Gets the number of characters.
+// *
+// * @return number of characters in the widget
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public int getCharCount() {
+// checkWidget();
+// return content.getCharCount();
+//}
+///**
+// * Returns the line at the given line index without delimiters.
+// * Index 0 is the first line of the content. When there are not
+// * any lines, getLine(0) is a valid call that answers an empty string.
+// *
+// * @param lineIndex index of the line to return.
+// * @return the line text without delimiters
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
+// *
+// * @since 3.4
+// */
+//public String getLine(int lineIndex) {
+// checkWidget();
+// if (lineIndex < 0 ||
+// (lineIndex > 0 && lineIndex >= content.getLineCount())) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// return content.getLine(lineIndex);
+//}
+///**
+// * Returns the alignment of the line at the given index.
+// *
+// * @param index the index of the line
+// *
+// * @return the line alignment
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the index is invalid
+// *
+// *
+// * @see #getAlignment()
+// *
+// * @since 3.2
+// */
+//public int getLineAlignment(int index) {
+// checkWidget();
+// if (index < 0 || index > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// return renderer.getLineAlignment(index, alignment);
+//}
+///**
+// * Returns the line at the specified offset in the text
+// * where 0 < offset < getCharCount() so that getLineAtOffset(getCharCount())
+// * returns the line of the insert location.
+// *
+// * @param offset offset relative to the start of the content.
+// * 0 <= offset <= getCharCount()
+// * @return line at the specified offset in the text
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
+// *
+// */
+//public int getLineAtOffset(int offset) {
+// checkWidget();
+// if (offset < 0 || offset > getCharCount()) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// return content.getLineAtOffset(offset);
+//}
+///**
+// * Returns the background color of the line at the given index.
+// * Returns null if a LineBackgroundListener has been set or if no background
+// * color has been specified for the line. Should not be called if a
+// * LineBackgroundListener has been set since the listener maintains the
+// * line background colors.
+// *
+// * @param index the index of the line
+// * @return the background color of the line at the given index.
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the index is invalid
+// *
+// */
+//public Color getLineBackground(int index) {
+// checkWidget();
+// if (index < 0 || index > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// return isListening(ST.LineGetBackground) ? null : renderer.getLineBackground(index, null);
+//}
+///**
+// * Returns the bullet of the line at the given index.
+// *
+// * @param index the index of the line
+// *
+// * @return the line bullet
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the index is invalid
+// *
+// *
+// * @since 3.2
+// */
+//public Bullet getLineBullet(int index) {
+// checkWidget();
+// if (index < 0 || index > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// return isListening(ST.LineGetStyle) ? null : renderer.getLineBullet(index, null);
+//}
+///**
+// * Returns the line background data for the given line or null if
+// * there is none.
+// *
+// * @param lineOffset offset of the line start relative to the start
+// * of the content.
+// * @param line line to get line background data for
+// * @return line background data for the given line.
+// */
+//StyledTextEvent getLineBackgroundData(int lineOffset, String line) {
+// return sendLineEvent(ST.LineGetBackground, lineOffset, line);
+//}
+///**
+// * Gets the number of text lines.
+// *
+// * @return the number of lines in the widget
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public int getLineCount() {
+// checkWidget();
+// return content.getLineCount();
+//}
+///**
+// * Returns the number of lines that can be completely displayed in the
+// * widget client area.
+// *
+// * @return number of lines that can be completely displayed in the widget
+// * client area.
+// */
+//int getLineCountWhole() {
+// if (isFixedLineHeight()) {
+// int lineHeight = renderer.getLineHeight();
+// return lineHeight != 0 ? clientAreaHeight / lineHeight : 1;
+// }
+// return getBottomIndex() - topIndex + 1;
+//}
+///**
+// * Returns the line delimiter used for entering new lines by key down
+// * or paste operation.
+// *
+// * @return line delimiter used for entering new lines by key down
+// * or paste operation.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// * Note: this API should not be used if a StyleRange attribute causes lines to
+// * have different heights (i.e. different fonts, rise, etc).
+// *
+// *
+// * @return line height in points.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @see #getLineHeight(int)
+// */
+//public int getLineHeight() {
+// checkWidget();
+// return renderer.getLineHeight();
+//}
+///**
+// * Returns the line height at the given offset.
+// *
+// * @param offset the offset
+// *
+// * @return line height in points
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
+// *
+// *
+// * @since 3.2
+// */
+//public int getLineHeight(int offset) {
+// checkWidget();
+// if (!(0 <= offset && offset <= content.getCharCount())) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// if (isFixedLineHeight()) {
+// return renderer.getLineHeight();
+// }
+// int lineIndex = content.getLineAtOffset(offset);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length()));
+// int height = layout.getLineBounds(lineInParagraph).height;
+// renderer.disposeTextLayout(layout);
+// return height;
+//}
+///**
+// * Returns the indentation of the line at the given index.
+// *
+// * @param index the index of the line
+// *
+// * @return the line indentation
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the index is invalid
+// *
+// *
+// * @see #getIndent()
+// *
+// * @since 3.2
+// */
+//public int getLineIndent(int index) {
+// checkWidget();
+// if (index < 0 || index > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// return isListening(ST.LineGetStyle) ? 0 : renderer.getLineIndent(index, indent);
+//}
+///**
+// * Returns the vertical indentation of the line at the given index.
+// *
+// * @param index the index of the line
+// *
+// * @return the line vertical indentation
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the index is invalid
+// *
+// *
+// * @since 3.109
+// */
+//public int getLineVerticalIndent(int index) {
+// checkWidget();
+// if (index < 0 || index >= content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// return isListening(ST.LineGetStyle) ? 0 : renderer.getLineVerticalIndent(index);
+//}
+///**
+// * Returns whether the line at the given index is justified.
+// *
+// * @param index the index of the line
+// *
+// * @return whether the line is justified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the index is invalid
+// *
+// *
+// * @see #getJustify()
+// *
+// * @since 3.2
+// */
+//public boolean getLineJustify(int index) {
+// checkWidget();
+// if (index < 0 || index > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// return isListening(ST.LineGetStyle) ? false : renderer.getLineJustify(index, justify);
+//}
+///**
+// * Returns the line spacing of the widget.
+// *
+// * @return the line spacing
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.2
+// */
+//public int getLineSpacing() {
+// checkWidget();
+// return lineSpacing;
+//}
+///**
+// * Returns the line style data for the given line or null if there is
+// * none.
+// *
+// * If there is a LineStyleListener but it does not set any styles,
+// * the StyledTextEvent.styles field will be initialized to an empty
+// * array.
+// *
+// *
+// * @param lineOffset offset of the line start relative to the start of
+// * the content.
+// * @param line line to get line styles for
+// * @return line style data for the given line. Styles may start before
+// * line start and end after line end
+// */
+//StyledTextEvent getLineStyleData(int lineOffset, String line) {
+// return sendLineEvent(ST.LineGetStyle, lineOffset, line);
+//}
+///**
+// * Returns the top SWT logical point, relative to the client area, of a given line.
+// * Clamps out of ranges index.
+// *
+// * @param lineIndex the line index, the max value is lineCount. If
+// * lineIndex == lineCount it returns the bottom SWT logical point of the last line.
+// * It means this function can be used to retrieve the bottom SWT logical point of any line.
+// *
+// * @return the top SWT logical point of a given line index
+// *
+// * @since 3.2
+// */
+//public int getLinePixel(int lineIndex) {
+// checkWidget();
+// int lineCount = content.getLineCount();
+// lineIndex = Math.max(0, Math.min(lineCount, lineIndex));
+// if (isFixedLineHeight()) {
+// int lineHeight = renderer.getLineHeight();
+// return lineIndex * lineHeight - getVerticalScrollOffset() + topMargin;
+// }
+// if (lineIndex == topIndex)
+// return topIndexY + topMargin;
+// int height = topIndexY;
+// if (lineIndex > topIndex) {
+// for (int i = topIndex; i < lineIndex; i++) {
+// height += renderer.getLineHeight(i);
+// }
+// } else {
+// for (int i = topIndex - 1; i >= lineIndex; i--) {
+// height -= renderer.getLineHeight(i);
+// }
+// }
+// return height + topMargin;
+//}
+///**
+// * Returns the line index for a y, relative to the client area.
+// * The line index returned is always in the range 0..lineCount - 1.
+// *
+// * @param y the y-coordinate point
+// *
+// * @return the line index for a given y-coordinate point
+// *
+// * @since 3.2
+// */
+//public int getLineIndex(int y) {
+// checkWidget();
+// y -= topMargin;
+// if (isFixedLineHeight()) {
+// int lineHeight = renderer.getLineHeight();
+// int lineIndex = (y + getVerticalScrollOffset()) / lineHeight;
+// int lineCount = content.getLineCount();
+// lineIndex = Math.max(0, Math.min(lineCount - 1, lineIndex));
+// return lineIndex;
+// }
+// if (y == topIndexY) return topIndex;
+// int line = topIndex;
+// if (y < topIndexY) {
+// while (y < topIndexY && line > 0) {
+// y += renderer.getLineHeight(--line);
+// }
+// } else {
+// int lineCount = content.getLineCount();
+// int lineHeight = renderer.getLineHeight(line);
+// while (y - lineHeight >= topIndexY && line < lineCount - 1) {
+// y -= lineHeight;
+// lineHeight = renderer.getLineHeight(++line);
+// }
+// }
+// return line;
+//}
+///**
+// * Returns the tab stops of the line at the given index.
+// *
+// * @param index the index of the line
+// *
+// * @return the tab stops for the line
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the index is invalid
+// *
+// *
+// * @see #getTabStops()
+// *
+// * @since 3.6
+// */
+//public int[] getLineTabStops(int index) {
+// checkWidget();
+// if (index < 0 || index > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// if (isListening(ST.LineGetStyle)) return null;
+// int[] tabs = renderer.getLineTabStops(index, null);
+// if (tabs == null) tabs = this.tabs;
+// if (tabs == null) return new int [] {renderer.tabWidth};
+// int[] result = new int[tabs.length];
+// System.arraycopy(tabs, 0, result, 0, tabs.length);
+// return result;
+//}
+///**
+// * Returns the wrap indentation of the line at the given index.
+// *
+// * @param index the index of the line
+// *
+// * @return the wrap indentation
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the index is invalid
+// *
+// *
+// * @see #getWrapIndent()
+// *
+// * @since 3.6
+// */
+//public int getLineWrapIndent(int index) {
+// checkWidget();
+// if (index < 0 || index > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// return isListening(ST.LineGetStyle) ? 0 : renderer.getLineWrapIndent(index, wrapIndent);
+//}
+///**
+// * Returns the left margin.
+// *
+// * @return the left margin.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public int getLeftMargin() {
+// checkWidget();
+// return leftMargin - alignmentMargin;
+//}
+///**
+// * Returns the x, y location of the upper left corner of the character
+// * bounding box at the specified offset in the text. The point is
+// * relative to the upper left corner of the widget client area.
+// *
+// * @param offset offset relative to the start of the content.
+// * 0 <= offset <= getCharCount()
+// * @return x, y location of the upper left corner of the character
+// * bounding box at the specified offset in the text.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
+// *
+// */
+//public Point getLocationAtOffset(int offset) {
+// checkWidget();
+// if (offset < 0 || offset > getCharCount()) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// return getPointAtOffset(offset);
+//}
+///**
+// * Returns true if the mouse navigator is enabled.
+// * When mouse navigator is enabled, the user can navigate through the widget by pressing the middle button and moving the cursor
+// *
+// * @return the mouse navigator's enabled state
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see #getEnabled
+// * @since 3.110
+// */
+//public boolean getMouseNavigatorEnabled () {
+// checkWidget ();
+// return mouseNavigator != null;
+//}
+///**
+// * Returns the character offset of the first character of the given line.
+// *
+// * @param lineIndex index of the line, 0 based relative to the first
+// * line in the content. 0 <= lineIndex < getLineCount(), except
+// * lineIndex may always be 0
+// * @return offset offset of the first character of the line, relative to
+// * the beginning of the document. The first character of the document is
+// * at offset 0.
+// * When there are not any lines, getOffsetAtLine(0) is a valid call that
+// * answers 0.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())
+// *
+// * @since 2.0
+// */
+//public int getOffsetAtLine(int lineIndex) {
+// checkWidget();
+// if (lineIndex < 0 ||
+// (lineIndex > 0 && lineIndex >= content.getLineCount())) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// return content.getOffsetAtLine(lineIndex);
+//}
+///**
+// * Returns the offset of the character at the given location relative
+// * to the first character in the document.
+// *
+// * The return value reflects the character offset that the caret will
+// * be placed at if a mouse click occurred at the specified location.
+// * If the x coordinate of the location is beyond the center of a character
+// * the returned offset will be behind the character.
+// *
+// *
+// * @param point the origin of character bounding box relative to
+// * the origin of the widget client area.
+// * @return offset of the character at the given location relative
+// * to the first character in the document.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when point is null
+// *
ERROR_INVALID_ARGUMENT when there is no character at the specified location
+// *
+// *
+// * @deprecated Use {@link #getOffsetAtPoint(Point)} instead for better performance
+// */
+//@Deprecated
+//public int getOffsetAtLocation(Point point) {
+// checkWidget();
+// if (point == null) {
+// SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// }
+// int[] trailing = new int[1];
+// int offset = getOffsetAtPoint(point.x, point.y, trailing, true);
+// if (offset == -1) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// return offset + trailing[0];
+//}
+//
+///**
+// * Returns the offset of the character at the given point relative
+// * to the first character in the document.
+// *
+// * The return value reflects the character offset that the caret will
+// * be placed at if a mouse click occurred at the specified point.
+// * If the x coordinate of the point is beyond the center of a character
+// * the returned offset will be behind the character.
+// *
+// * Note: This method is functionally similar to {@link #getOffsetAtLocation(Point)} except that
+// * it does not throw an exception when no character is found and thus performs faster.
+// *
+// * @param point the origin of character bounding box relative to
+// * the origin of the widget client area.
+// * @return offset of the character at the given point relative
+// * to the first character in the document.
+// * -1 when there is no character at the specified location.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when point is null
+// *
+// *
+// * @since 3.107
+// */
+//public int getOffsetAtPoint(Point point) {
+// checkWidget();
+// if (point == null) {
+// SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// }
+// int[] trailing = new int[1];
+// int offset = getOffsetAtPoint(point.x, point.y, trailing, true);
+// return offset != -1 ? offset + trailing[0] : -1;
+//}
+//
+//int getOffsetAtPoint(int x, int y, int[] alignment) {
+// int lineIndex = getLineIndex(y);
+// y -= getLinePixel(lineIndex);
+// return getOffsetAtPoint(x, y, lineIndex, alignment);
+//}
+//int getOffsetAtPoint(int x, int y, int lineIndex, int[] alignment) {
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// x += horizontalScrollOffset - leftMargin;
+// int[] trailing = new int[1];
+// int offsetInLine = layout.getOffset(x, y, trailing);
+// if (alignment != null) alignment[0] = OFFSET_LEADING;
+// if (trailing[0] != 0) {
+// int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]);
+// int lineStart = layout.getLineOffsets()[lineInParagraph];
+// if (offsetInLine + trailing[0] == lineStart) {
+// offsetInLine += trailing[0];
+// if (alignment != null) alignment[0] = PREVIOUS_OFFSET_TRAILING;
+// } else {
+// String line = content.getLine(lineIndex);
+// int level = 0;
+// if (alignment != null) {
+// int offset = offsetInLine;
+// while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--;
+// if (offset == 0 && Character.isDigit(line.charAt(offset))) {
+// level = isMirrored() ? 1 : 0;
+// } else {
+// level = layout.getLevel(offset) & 0x1;
+// }
+// }
+// offsetInLine += trailing[0];
+// if (alignment != null) {
+// int trailingLevel = layout.getLevel(offsetInLine) & 0x1;
+// if (level != trailingLevel) {
+// alignment[0] = PREVIOUS_OFFSET_TRAILING;
+// } else {
+// alignment[0] = OFFSET_LEADING;
+// }
+// }
+// }
+// }
+// renderer.disposeTextLayout(layout);
+// return offsetInLine + content.getOffsetAtLine(lineIndex);
+//}
+//int getOffsetAtPoint(int x, int y, int[] trailing, boolean inTextOnly) {
+// if (inTextOnly && y + getVerticalScrollOffset() < 0 || x + horizontalScrollOffset < 0) {
+// return -1;
+// }
+// int bottomIndex = getPartialBottomIndex();
+// int height = getLinePixel(bottomIndex + 1);
+// if (inTextOnly && y > height) {
+// return -1;
+// }
+// int lineIndex = getLineIndex(y);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// x += horizontalScrollOffset - leftMargin;
+// y -= getLinePixel(lineIndex);
+// int offset = layout.getOffset(x, y, trailing);
+// Rectangle rect = layout.getLineBounds(layout.getLineIndex(offset));
+// renderer.disposeTextLayout(layout);
+// if (inTextOnly && !(rect.x <= x && x <= rect.x + rect.width)) {
+// return -1;
+// }
+// return offset + lineOffset;
+//}
+///**
+// * Returns the orientation of the receiver.
+// *
+// * @return the orientation style
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 2.1.2
+// */
+//@Override
+//public int getOrientation () {
+// return super.getOrientation ();
+//}
+///**
+// * Returns the index of the last partially visible line.
+// *
+// * @return index of the last partially visible line.
+// */
+//int getPartialBottomIndex() {
+// if (isFixedLineHeight()) {
+// int lineHeight = renderer.getLineHeight();
+// int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight);
+// return Math.max(0, Math.min(content.getLineCount(), topIndex + partialLineCount) - 1);
+// }
+// return getLineIndex(clientAreaHeight - bottomMargin);
+//}
+///**
+// * Returns the index of the first partially visible line.
+// *
+// * @return index of the first partially visible line.
+// */
+//int getPartialTopIndex() {
+// if (isFixedLineHeight()) {
+// int lineHeight = renderer.getLineHeight();
+// return getVerticalScrollOffset() / lineHeight;
+// }
+// return topIndexY <= 0 ? topIndex : topIndex - 1;
+//}
+///**
+// * Returns the content in the specified range using the platform line
+// * delimiter to separate lines.
+// *
+// * @param writer the TextWriter to write line text into
+// * @return the content in the specified range using the platform line
+// * delimiter to separate lines as written by the specified TextWriter.
+// */
+//String getPlatformDelimitedText(TextWriter writer) {
+// int end = writer.getStart() + writer.getCharCount();
+// int startLine = content.getLineAtOffset(writer.getStart());
+// int endLine = content.getLineAtOffset(end);
+// String endLineText = content.getLine(endLine);
+// int endLineOffset = content.getOffsetAtLine(endLine);
+//
+// for (int i = startLine; i <= endLine; i++) {
+// writer.writeLine(content.getLine(i), content.getOffsetAtLine(i));
+// if (i < endLine) {
+// writer.writeLineDelimiter(PlatformLineDelimiter);
+// }
+// }
+// if (end > endLineOffset + endLineText.length()) {
+// writer.writeLineDelimiter(PlatformLineDelimiter);
+// }
+// writer.close();
+// return writer.toString();
+//}
+///**
+// * Returns all the ranges of text that have an associated StyleRange.
+// * Returns an empty array if a LineStyleListener has been set.
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// * The ranges array contains start and length pairs. Each pair refers to
+// * the corresponding style in the styles array. For example, the pair
+// * that starts at ranges[n] with length ranges[n+1] uses the style
+// * at styles[n/2] returned by getStyleRanges(int, int, boolean).
+// *
+// *
+// * @return the ranges or an empty array if a LineStyleListener has been set.
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.2
+// *
+// * @see #getStyleRanges(boolean)
+// */
+//public int[] getRanges() {
+// checkWidget();
+// if (!isListening(ST.LineGetStyle)) {
+// int[] ranges = renderer.getRanges(0, content.getCharCount());
+// if (ranges != null) return ranges;
+// }
+// return new int[0];
+//}
+///**
+// * Returns the ranges of text that have an associated StyleRange.
+// * Returns an empty array if a LineStyleListener has been set.
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// * The ranges array contains start and length pairs. Each pair refers to
+// * the corresponding style in the styles array. For example, the pair
+// * that starts at ranges[n] with length ranges[n+1] uses the style
+// * at styles[n/2] returned by getStyleRanges(int, int, boolean).
+// *
+// *
+// * @param start the start offset of the style ranges to return
+// * @param length the number of style ranges to return
+// *
+// * @return the ranges or an empty array if a LineStyleListener has been set.
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE if start or length are outside the widget content
+// *
+// *
+// * @since 3.2
+// *
+// * @see #getStyleRanges(int, int, boolean)
+// */
+//public int[] getRanges(int start, int length) {
+// checkWidget();
+// int contentLength = getCharCount();
+// int end = start + length;
+// if (start > end || start < 0 || end > contentLength) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// if (!isListening(ST.LineGetStyle)) {
+// int[] ranges = renderer.getRanges(start, length);
+// if (ranges != null) return ranges;
+// }
+// return new int[0];
+//}
+///**
+// * Returns the right margin.
+// *
+// * @return the right margin.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// * Text selections are specified in terms of caret positions. In a text
+// * widget that contains N characters, there are N+1 caret positions,
+// * ranging from 0..N
+// *
+// *
+// * It is usually better to use {@link #getSelectionRanges()} which better
+// * support multiple selection and carets and block selection.
+// *
+// *
+// * @return start and end of the selection, x is the offset of the first
+// * selected character, y is the offset after the last selected character.
+// * The selection values returned are visual (i.e., x will always always be
+// * <= y). To determine if a selection is right-to-left (RtoL) vs. left-to-right
+// * (LtoR), compare the caretOffset to the start and end of the selection
+// * (e.g., caretOffset == start of selection implies that the selection is RtoL).
+// * @see #getSelectionRanges
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public Point getSelection() {
+// checkWidget();
+// return new Point(selection[0].x, selection[0].y);
+//}
+///**
+// * Returns the selection.
+// *
+// * It is usually better to use {@link #getSelectionRanges()} which better
+// * support multiple selection and carets and block selection.
+// *
+// *
+// * @return start and length of the selection, x is the offset of the
+// * first selected character, relative to the first character of the
+// * widget content. y is the length of the selection.
+// * The selection values returned are visual (i.e., length will always always be
+// * positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right
+// * (LtoR), compare the caretOffset to the start and end of the selection
+// * (e.g., caretOffset == start of selection implies that the selection is RtoL).
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @see #getSelectionRanges
+// */
+//public Point getSelectionRange() {
+// checkWidget();
+// return new Point(selection[0].x, selection[0].y - selection[0].x);
+//}
+///**
+// * Returns the selected ranges of text.
+// * If block is enabled, return the ranges that are inside the block selection rectangle.
+// *
+// * The ranges array contains start and length pairs.
+// *
+// * When the receiver is not
+// * in block selection mode the return arrays contains the start and length of
+// * the regular selections.
+// *
+// * @return the ranges array
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// * @see #setSelectionRanges(int[])
+// */
+//public int[] getSelectionRanges() {
+// checkWidget();
+// if (blockSelection && blockXLocation != -1) {
+// Rectangle rect = getBlockSelectionPosition();
+// int firstLine = rect.y;
+// int lastLine = rect.height;
+// int left = rect.x;
+// int right = rect.width;
+// int[] ranges = new int[(lastLine - firstLine + 1) * 2];
+// int index = 0;
+// for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
+// int start = getOffsetAtPoint(left, 0, lineIndex, null);
+// int end = getOffsetAtPoint(right, 0, lineIndex, null);
+// if (start > end) {
+// int temp = start;
+// start = end;
+// end = temp;
+// }
+// ranges[index++] = start;
+// ranges[index++] = end - start;
+// }
+// return ranges;
+// }
+// int[] res = new int[2 * selection.length];
+// int index = 0;
+// for (Point p : selection) {
+// res[index++] = p.x;
+// res[index++] = p.y - p.x;
+// }
+// return res;
+//}
+///**
+// * Returns the receiver's selection background color.
+// *
+// * @return the selection background color
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @since 2.1
+// */
+//public Color getSelectionBackground() {
+// checkWidget();
+// if (selectionBackground == null) {
+// return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
+// }
+// return selectionBackground;
+//}
+///**
+// * Gets the number of selected characters.
+// *
+// * @return the number of selected characters.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// * Returns null if a LineStyleListener has been set or if a style is not set
+// * for the offset.
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// *
+// * @param offset the offset to return the style for.
+// * 0 <= offset < getCharCount() must be true.
+// * @return a StyleRange with start == offset and length == 1, indicating
+// * the style at the given offset. null if a LineStyleListener has been set
+// * or if a style is not set for the given offset.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// * Returns an empty array if a LineStyleListener has been set.
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// * Note: Because a StyleRange includes the start and length, the
+// * same instance cannot occur multiple times in the array of styles.
+// * If the same style attributes, such as font and color, occur in
+// * multiple StyleRanges, getStyleRanges(boolean)
+// * can be used to get the styles without the ranges.
+// *
+// *
+// * @return the styles or an empty array if a LineStyleListener has been set.
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// * Returns an empty array if a LineStyleListener has been set.
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// * Note: When includeRanges is true, the start and length
+// * fields of each StyleRange will be valid, however the StyleRange
+// * objects may need to be cloned. When includeRanges is
+// * false, getRanges(int, int) can be used to get the
+// * associated ranges.
+// *
+// *
+// * @param includeRanges whether the start and length field of the StyleRanges should be set.
+// *
+// * @return the styles or an empty array if a LineStyleListener has been set.
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.2
+// *
+// * @see #getRanges(int, int)
+// * @see #setStyleRanges(int[], StyleRange[])
+// */
+//public StyleRange[] getStyleRanges(boolean includeRanges) {
+// checkWidget();
+// return getStyleRanges(0, content.getCharCount(), includeRanges);
+//}
+///**
+// * Returns the styles for the given text range.
+// *
+// * Returns an empty array if a LineStyleListener has been set.
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// * Note: Because the StyleRange includes the start and length, the
+// * same instance cannot occur multiple times in the array of styles.
+// * If the same style attributes, such as font and color, occur in
+// * multiple StyleRanges, getStyleRanges(int, int, boolean)
+// * can be used to get the styles without the ranges.
+// *
+// * @param start the start offset of the style ranges to return
+// * @param length the number of style ranges to return
+// *
+// * @return the styles or an empty array if a LineStyleListener has
+// * been set. The returned styles will reflect the given range. The first
+// * returned StyleRange will have a starting offset >= start
+// * and the last returned StyleRange will have an ending
+// * offset <= start + length - 1
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
+// *
+// *
+// * @see #getStyleRanges(int, int, boolean)
+// *
+// * @since 3.0
+// */
+//public StyleRange[] getStyleRanges(int start, int length) {
+// checkWidget();
+// return getStyleRanges(start, length, true);
+//}
+///**
+// * Returns the styles for the given text range.
+// *
+// * Returns an empty array if a LineStyleListener has been set.
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// * Note: When includeRanges is true, the start and length
+// * fields of each StyleRange will be valid, however the StyleRange
+// * objects may need to be cloned. When includeRanges is
+// * false, getRanges(int, int) can be used to get the
+// * associated ranges.
+// *
+// *
+// * @param start the start offset of the style ranges to return
+// * @param length the number of style ranges to return
+// * @param includeRanges whether the start and length field of the StyleRanges should be set.
+// *
+// * @return the styles or an empty array if a LineStyleListener has
+// * been set. The returned styles will reflect the given range. The first
+// * returned StyleRange will have a starting offset >= start
+// * and the last returned StyleRange will have an ending
+// * offset >= start + length - 1
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
+// *
+// *
+// * @since 3.2
+// *
+// * @see #getRanges(int, int)
+// * @see #setStyleRanges(int[], StyleRange[])
+// */
+//public StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) {
+// checkWidget();
+// int contentLength = getCharCount();
+// int end = start + length;
+// if (start > end || start < 0 || end > contentLength) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// if (!isListening(ST.LineGetStyle)) {
+// StyleRange[] ranges = renderer.getStyleRanges(start, length, includeRanges);
+// if (ranges != null) return ranges;
+// }
+// return new StyleRange[0];
+//}
+///**
+// * Returns the tab width measured in characters.
+// *
+// * @return tab width measured in characters
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see #getTabStops()
+// */
+//public int getTabs() {
+// checkWidget();
+// return tabLength;
+//}
+//
+///**
+// * Returns the tab list of the receiver.
+// *
+// * @return the tab list
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.6
+// */
+//public int[] getTabStops() {
+// checkWidget();
+// if (tabs == null) return new int [] {renderer.tabWidth};
+// int[] result = new int[tabs.length];
+// System.arraycopy(tabs, 0, result, 0, tabs.length);
+// return result;
+//}
+//
+///**
+// * Returns a copy of the widget content.
+// *
+// * @return copy of the widget content
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public String getText() {
+// checkWidget();
+// return content.getTextRange(0, getCharCount());
+//}
+///**
+// * Returns the widget content between the two offsets.
+// *
+// * @param start offset of the first character in the returned String
+// * @param end offset of the last character in the returned String
+// * @return widget content starting at start and ending at end
+// * @see #getTextRange(int,int)
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
+// *
+// */
+//public String getText(int start, int end) {
+// checkWidget();
+// int contentLength = getCharCount();
+// if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// return content.getTextRange(start, end - start + 1);
+//}
+///**
+// * Returns the smallest bounding rectangle that includes the characters between two offsets.
+// *
+// * @param start offset of the first character included in the bounding box
+// * @param end offset of the last character included in the bounding box
+// * @return bounding box of the text between start and end
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
+// *
+// * @since 3.1
+// */
+//public Rectangle getTextBounds(int start, int end) {
+// checkWidget();
+// int contentLength = getCharCount();
+// if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// int lineStart = content.getLineAtOffset(start);
+// int lineEnd = content.getLineAtOffset(end);
+// Rectangle rect;
+// int y = getLinePixel(lineStart);
+// int height = 0;
+// int left = 0x7fffffff, right = 0;
+// for (int i = lineStart; i <= lineEnd; i++) {
+// int lineOffset = content.getOffsetAtLine(i);
+// TextLayout layout = renderer.getTextLayout(i);
+// int length = layout.getText().length();
+// if (length > 0) {
+// if (i == lineStart) {
+// if (i == lineEnd) {
+// rect = layout.getBounds(start - lineOffset, end - lineOffset);
+// } else {
+// rect = layout.getBounds(start - lineOffset, length);
+// }
+// y += rect.y;
+// } else if (i == lineEnd) {
+// rect = layout.getBounds(0, end - lineOffset);
+// } else {
+// rect = layout.getBounds();
+// }
+// left = Math.min(left, rect.x);
+// right = Math.max(right, rect.x + rect.width);
+// height += rect.height;
+// } else {
+// height += renderer.getLineHeight();
+// }
+// renderer.disposeTextLayout(layout);
+// }
+// rect = new Rectangle (left, y, right-left, height);
+// rect.x += leftMargin - horizontalScrollOffset;
+// return rect;
+//}
+///**
+// * Returns the widget content starting at start for length characters.
+// *
+// * @param start offset of the first character in the returned String
+// * @param length number of characters to return
+// * @return widget content starting at start and extending length characters.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when start and/or length are outside the widget content
+// *
+// */
+//public String getTextRange(int start, int length) {
+// checkWidget();
+// int contentLength = getCharCount();
+// int end = start + length;
+// if (start > end || start < 0 || end > contentLength) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// return content.getTextRange(start, length);
+//}
+///**
+// * Returns the maximum number of characters that the receiver is capable of holding.
+// *
+// * @return the text limit
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public int getTextLimit() {
+// checkWidget();
+// return textLimit;
+//}
+///**
+// * Gets the top index.
+// *
+// * The top index is the index of the fully visible line that is currently
+// * at the top of the widget or the topmost partially visible line if no line is fully visible.
+// * The top index changes when the widget is scrolled. Indexing is zero based.
+// *
+// *
+// * @return the index of the top line
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public int getTopIndex() {
+// checkWidget();
+// return topIndex;
+//}
+///**
+// * Returns the top margin.
+// *
+// * @return the top margin.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public int getTopMargin() {
+// checkWidget();
+// return topMargin;
+//}
+///**
+// * Gets the top SWT logical point.
+// *
+// * The top point is the SWT logical point position of the line that is
+// * currently at the top of the widget. The text widget can be scrolled by points
+// * by dragging the scroll thumb so that a partial line may be displayed at the top
+// * the widget. The top point changes when the widget is scrolled. The top point
+// * does not include the widget trimming.
+// *
+// *
+// * @return SWT logical point position of the top line
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see #getLineWrapIndent(int)
+// *
+// * @since 3.6
+// */
+//public int getWrapIndent() {
+// checkWidget();
+// return wrapIndent;
+//}
+///**
+// * Returns the location of the given offset.
+// *
+// * NOTE: Does not return correct values for true italic fonts (vs. slanted fonts).
+// *
+// *
+// * @return location of the character at the given offset in the line.
+// */
+//Point getPointAtOffset(int offset) {
+// int lineIndex = content.getLineAtOffset(offset);
+// String line = content.getLine(lineIndex);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// int offsetInLine = Math.max (0, offset - lineOffset);
+// int lineLength = line.length();
+// if (lineIndex < content.getLineCount() - 1) {
+// int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1;
+// if (lineLength < offsetInLine && offsetInLine <= endLineOffset) {
+// offsetInLine = lineLength;
+// }
+// }
+// Point point;
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// if (lineLength != 0 && offsetInLine <= lineLength) {
+// if (offsetInLine == lineLength) {
+// offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
+// point = layout.getLocation(offsetInLine, true);
+// } else {
+// switch (caretAlignment) {
+// case OFFSET_LEADING:
+// point = layout.getLocation(offsetInLine, false);
+// break;
+// case PREVIOUS_OFFSET_TRAILING:
+// default:
+// boolean lineBegin = offsetInLine == 0;
+// // If word wrap is enabled, we should also consider offsets
+// // of wrapped line parts as line begin and do NOT go back.
+// // This prevents clients to jump one line higher than
+// // expected, see bug 488172.
+// // Respect caretAlignment at the caretOffset, unless there's
+// // a non-empty selection, see bug 488172 comment 6.
+// if (wordWrap && !lineBegin && (Arrays.binarySearch(caretOffsets, offset) < 0 || Arrays.stream(selection).allMatch(p -> p.x == p.y))) {
+// int[] offsets = layout.getLineOffsets();
+// for (int i : offsets) {
+// if (i == offsetInLine) {
+// lineBegin = true;
+// break;
+// }
+// }
+// }
+// if (lineBegin) {
+// point = layout.getLocation(offsetInLine, false);
+// } else {
+// offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
+// point = layout.getLocation(offsetInLine, true);
+// }
+// break;
+// }
+// }
+// } else {
+// point = new Point(layout.getIndent(), layout.getVerticalIndent());
+// }
+// renderer.disposeTextLayout(layout);
+// point.x += leftMargin - horizontalScrollOffset;
+// point.y += getLinePixel(lineIndex);
+// return point;
+//}
+///**
+// * Inserts a string. The old selection is replaced with the new text.
+// *
+// * @param string the string
+// * @see #replaceTextRange(int,int,String)
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when string is null
+// *
+// */
+//public void insert(String string) {
+// checkWidget();
+// if (string == null) {
+// SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// }
+// if (blockSelection) {
+// insertBlockSelectionText(string, false);
+// } else {
+// Point sel = getSelectionRange();
+// replaceTextRange(sel.x, sel.y, string);
+// }
+//}
+//int insertBlockSelectionText(String text, boolean fillWithSpaces) {
+// int lineCount = 1;
+// for (int i = 0; i < text.length(); i++) {
+// char ch = text.charAt(i);
+// if (ch == '\n' || ch == '\r') {
+// lineCount++;
+// if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') {
+// i++;
+// }
+// }
+// }
+// String[] lines = new String[lineCount];
+// int start = 0;
+// lineCount = 0;
+// for (int i = 0; i < text.length(); i++) {
+// char ch = text.charAt(i);
+// if (ch == '\n' || ch == '\r') {
+// lines[lineCount++] = text.substring(start, i);
+// if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') {
+// i++;
+// }
+// start = i + 1;
+// }
+// }
+// lines[lineCount++] = text.substring(start);
+// if (fillWithSpaces) {
+// int maxLength = 0;
+// for (String line : lines) {
+// int length = line.length();
+// maxLength = Math.max(maxLength, length);
+// }
+// for (int i = 0; i < lines.length; i++) {
+// String line = lines[i];
+// int length = line.length();
+// if (length < maxLength) {
+// int numSpaces = maxLength - length;
+// StringBuilder buffer = new StringBuilder(length + numSpaces);
+// buffer.append(line);
+// for (int j = 0; j < numSpaces; j++) buffer.append(' ');
+// lines[i] = buffer.toString();
+// }
+// }
+// }
+// int firstLine, lastLine, left, right;
+// if (blockXLocation != -1) {
+// Rectangle rect = getBlockSelectionPosition();
+// firstLine = rect.y;
+// lastLine = rect.height;
+// left = rect.x;
+// right = rect.width;
+// } else {
+// firstLine = lastLine = getFirstCaretLine();
+// left = right = getPointAtOffset(caretOffsets[0]).x;
+// }
+// start = caretOffsets[0];
+// int caretLine = getFirstCaretLine();
+// int index = 0, lineIndex = firstLine;
+// while (lineIndex <= lastLine) {
+// String string = index < lineCount ? lines[index++] : "";
+// int lineStart = sendTextEvent(left, right, lineIndex, string, fillWithSpaces);
+// if (lineIndex == caretLine) start = lineStart;
+// lineIndex++;
+// }
+// while (index < lineCount) {
+// int lineStart = sendTextEvent(left, left, lineIndex, lines[index++], fillWithSpaces);
+// if (lineIndex == caretLine) start = lineStart;
+// lineIndex++;
+// }
+// return start;
+//}
+//void insertBlockSelectionText(char key, int action) {
+// if (key == SWT.CR || key == SWT.LF) return;
+// Rectangle rect = getBlockSelectionPosition();
+// int firstLine = rect.y;
+// int lastLine = rect.height;
+// int left = rect.x;
+// int right = rect.width;
+// int[] trailing = new int[1];
+// int offset = 0, delta = 0;
+// String text = key != 0 ? new String(new char[] {key}) : "";
+// int length = text.length();
+// for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
+// String line = content.getLine(lineIndex);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// int lineEndOffset = lineOffset + line.length();
+// int linePixel = getLinePixel(lineIndex);
+// int start = getOffsetAtPoint(left, linePixel, trailing, true);
+// boolean outOfLine = start == -1;
+// if (outOfLine) {
+// start = left < leftMargin ? lineOffset : lineEndOffset;
+// } else {
+// start += trailing[0];
+// }
+// int end = getOffsetAtPoint(right, linePixel, trailing, true);
+// if (end == -1) {
+// end = right < leftMargin ? lineOffset : lineEndOffset;
+// } else {
+// end += trailing[0];
+// }
+// if (start > end) {
+// int temp = start;
+// start = end;
+// end = temp;
+// }
+// if (start == end && !outOfLine) {
+// switch (action) {
+// case ST.DELETE_PREVIOUS:
+// if (start > lineOffset) start = getClusterPrevious(start, lineIndex);
+// break;
+// case ST.DELETE_NEXT:
+// if (end < lineEndOffset) end = getClusterNext(end, lineIndex);
+// break;
+// }
+// }
+// if (outOfLine) {
+// if (line.length() >= delta) {
+// delta = line.length();
+// offset = lineEndOffset + length;
+// }
+// } else {
+// offset = start + length;
+// delta = content.getCharCount();
+// }
+// Event event = new Event();
+// event.text = text;
+// event.start = start;
+// event.end = end;
+// sendKeyEvent(event);
+// }
+// int x = getPointAtOffset(offset).x;
+// int verticalScrollOffset = getVerticalScrollOffset();
+// setBlockSelectionLocation(x, blockYAnchor - verticalScrollOffset, x, blockYLocation - verticalScrollOffset, false);
+//}
+///**
+// * Creates content change listeners and set the default content model.
+// */
+//void installDefaultContent() {
+// textChangeListener = new TextChangeListener() {
+// @Override
+// public void textChanging(TextChangingEvent event) {
+// handleTextChanging(event);
+// }
+// @Override
+// public void textChanged(TextChangedEvent event) {
+// handleTextChanged(event);
+// }
+// @Override
+// public void textSet(TextChangedEvent event) {
+// handleTextSet(event);
+// }
+// };
+// content = new DefaultContent();
+// content.addTextChangeListener(textChangeListener);
+//}
+///**
+// * Adds event listeners
+// */
+//void installListeners() {
+// ScrollBar verticalBar = getVerticalBar();
+// ScrollBar horizontalBar = getHorizontalBar();
+//
+// listener = event -> {
+// switch (event.type) {
+// case SWT.Dispose: handleDispose(event); break;
+// case SWT.KeyDown: handleKeyDown(event); break;
+// case SWT.KeyUp: handleKeyUp(event); break;
+// case SWT.MenuDetect: handleMenuDetect(event); break;
+// case SWT.MouseDown: handleMouseDown(event); break;
+// case SWT.MouseUp: handleMouseUp(event); break;
+// case SWT.MouseMove: handleMouseMove(event); break;
+// case SWT.Paint: handlePaint(event); break;
+// case SWT.Resize: handleResize(event); break;
+// case SWT.Traverse: handleTraverse(event); break;
+// }
+// };
+// addListener(SWT.Dispose, listener);
+// addListener(SWT.KeyDown, listener);
+// addListener(SWT.KeyUp, listener);
+// addListener(SWT.MenuDetect, listener);
+// addListener(SWT.MouseDown, listener);
+// addListener(SWT.MouseUp, listener);
+// addListener(SWT.MouseMove, listener);
+// addListener(SWT.Paint, listener);
+// addListener(SWT.Resize, listener);
+// addListener(SWT.Traverse, listener);
+// ime.addListener(SWT.ImeComposition, event -> {
+// if (!editable) {
+// event.doit = false;
+// event.start = 0;
+// event.end = 0;
+// event.text = "";
+// return;
+// }
+//
+// switch (event.detail) {
+// case SWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break;
+// case SWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break;
+// case SWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break;
+// }
+// });
+// if (verticalBar != null) {
+// verticalBar.addListener(SWT.Selection, this::handleVerticalScroll);
+// }
+// if (horizontalBar != null) {
+// horizontalBar.addListener(SWT.Selection, this::handleHorizontalScroll);
+// }
+//}
+//void internalRedrawRange(int start, int length) {
+// if (length <= 0) return;
+// int end = start + length;
+// int startLine = content.getLineAtOffset(start);
+// int endLine = content.getLineAtOffset(end);
+// int partialBottomIndex = getPartialBottomIndex();
+// int partialTopIndex = getPartialTopIndex();
+// if (startLine > partialBottomIndex || endLine < partialTopIndex) {
+// return;
+// }
+// if (partialTopIndex > startLine) {
+// startLine = partialTopIndex;
+// start = 0;
+// } else {
+// start -= content.getOffsetAtLine(startLine);
+// }
+// if (partialBottomIndex < endLine) {
+// endLine = partialBottomIndex + 1;
+// end = 0;
+// } else {
+// end -= content.getOffsetAtLine(endLine);
+// }
+//
+// TextLayout layout = renderer.getTextLayout(startLine);
+// int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine);
+// int[] offsets = layout.getLineOffsets();
+// int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length()));
+//
+// /* Redraw end of line before start line if wrapped and start offset is first char */
+// if (isWordWrap() && startIndex > 0 && offsets[startIndex] == start) {
+// Rectangle rect = layout.getLineBounds(startIndex - 1);
+// rect.x = rect.width;
+// rect.width = clientAreaWidth - rightMargin - rect.x;
+// rect.x += lineX;
+// rect.y += startLineY;
+// super.redraw(rect.x, rect.y, rect.width, rect.height, false);
+// }
+//
+// if (startLine == endLine) {
+// int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length()));
+// if (startIndex == endIndex) {
+// /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */
+// Rectangle rect = layout.getBounds(start, end - 1);
+// rect.x += lineX;
+// rect.y += startLineY;
+// super.redraw(rect.x, rect.y, rect.width, rect.height, false);
+// renderer.disposeTextLayout(layout);
+// return;
+// }
+// }
+//
+// /* Redraw start line from the start offset to the end of client area */
+// Rectangle startRect = layout.getBounds(start, offsets[startIndex + 1] - 1);
+// if (startRect.height == 0) {
+// Rectangle bounds = layout.getLineBounds(startIndex);
+// startRect.x = bounds.width;
+// startRect.y = bounds.y;
+// startRect.height = bounds.height;
+// }
+// startRect.x += lineX;
+// startRect.y += startLineY;
+// startRect.width = clientAreaWidth - rightMargin - startRect.x;
+// super.redraw(startRect.x, startRect.y, startRect.width, startRect.height, false);
+//
+// /* Redraw end line from the beginning of the line to the end offset */
+// if (startLine != endLine) {
+// renderer.disposeTextLayout(layout);
+// layout = renderer.getTextLayout(endLine);
+// offsets = layout.getLineOffsets();
+// }
+// int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length()));
+// Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1);
+// if (endRect.height == 0) {
+// Rectangle bounds = layout.getLineBounds(endIndex);
+// endRect.y = bounds.y;
+// endRect.height = bounds.height;
+// }
+// endRect.x += lineX;
+// endRect.y += getLinePixel(endLine);
+// super.redraw(endRect.x, endRect.y, endRect.width, endRect.height, false);
+// renderer.disposeTextLayout(layout);
+//
+// /* Redraw all lines in between start and end line */
+// int y = startRect.y + startRect.height;
+// if (endRect.y > y) {
+// super.redraw(leftMargin, y, clientAreaWidth - rightMargin - leftMargin, endRect.y - y, false);
+// }
+//}
+//void handleCompositionOffset (Event event) {
+// int[] trailing = new int [1];
+// event.index = getOffsetAtPoint(event.x, event.y, trailing, true);
+// event.count = trailing[0];
+//}
+//void handleCompositionSelection (Event event) {
+// if (event.start != event.end) {
+// int charCount = getCharCount();
+// event.start = Math.max(0, Math.min(event.start, charCount));
+// event.end = Math.max(0, Math.min(event.end, charCount));
+// if (event.text != null) {
+// setSelection(event.start, event.end);
+// } else {
+// event.text = getTextRange(event.start, event.end - event.start);
+// }
+// } else {
+// event.start = selection[0].x;
+// event.end = selection[0].y;
+// event.text = getSelectionText();
+// }
+//}
+//void handleCompositionChanged(Event event) {
+// String text = event.text;
+// int start = event.start;
+// int end = event.end;
+// int charCount = content.getCharCount();
+// start = Math.min(start, charCount);
+// end = Math.min(end, charCount);
+// int length = text.length();
+// if (length == ime.getCommitCount()) {
+// content.replaceTextRange(start, end - start, "");
+// setCaretOffsets(new int[] {ime.getCompositionOffset()}, SWT.DEFAULT);
+// caretWidth = 0;
+// caretDirection = SWT.NULL;
+// } else {
+// content.replaceTextRange(start, end - start, text);
+// int alignment = SWT.DEFAULT;
+// if (ime.getWideCaret()) {
+// start = ime.getCompositionOffset();
+// for (int caretOffset : caretOffsets) {
+// int lineIndex = content.getLineAtOffset(caretOffset);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width;
+// renderer.disposeTextLayout(layout);
+// }
+// alignment = OFFSET_LEADING;
+// }
+// setCaretOffsets(new int[] {ime.getCaretOffset()}, alignment);
+// }
+// resetSelection();
+// showCaret();
+//}
+///**
+// * Frees resources.
+// */
+//void handleDispose(Event event) {
+// removeListener(SWT.Dispose, listener);
+// notifyListeners(SWT.Dispose, event);
+// event.type = SWT.None;
+//
+// clipboard.dispose();
+// if (renderer != null) {
+// renderer.dispose();
+// renderer = null;
+// }
+// if (content != null) {
+// content.removeTextChangeListener(textChangeListener);
+// content = null;
+// }
+// if (defaultCaret != null) {
+// defaultCaret.dispose();
+// defaultCaret = null;
+// }
+// if (leftCaretBitmap != null) {
+// leftCaretBitmap.dispose();
+// leftCaretBitmap = null;
+// }
+// if (rightCaretBitmap != null) {
+// rightCaretBitmap.dispose();
+// rightCaretBitmap = null;
+// }
+// if (carets != null) {
+// for (Caret caret : carets) {
+// if (caret != null) {
+// caret.dispose();
+// }
+// }
+// carets = null;
+// }
+// if (isBidiCaret()) {
+// BidiUtil.removeLanguageListener(this);
+// }
+// selectionBackground = null;
+// selectionForeground = null;
+// marginColor = null;
+// textChangeListener = null;
+// selection = null;
+// doubleClickSelection = null;
+// keyActionMap = null;
+// background = null;
+// foreground = null;
+// clipboard = null;
+// tabs = null;
+//}
+///**
+// * Scrolls the widget horizontally.
+// */
+//void handleHorizontalScroll(Event event) {
+// int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset;
+// scrollHorizontal(scrollPixel, false);
+//}
+///**
+// * If an action has been registered for the key stroke execute the action.
+// * Otherwise, if a character has been entered treat it as new content.
+// *
+// * @param event keyboard event
+// */
+//void handleKey(Event event) {
+// int action;
+// caretAlignment = PREVIOUS_OFFSET_TRAILING;
+// if (event.keyCode != 0) {
+// // special key pressed (e.g., F1)
+// action = getKeyBinding(event.keyCode | event.stateMask);
+// } else {
+// // character key pressed
+// action = getKeyBinding(event.character | event.stateMask);
+// if (action == SWT.NULL) {
+// // see if we have a control character
+// if ((event.stateMask & SWT.CTRL) != 0 && event.character <= 31) {
+// // get the character from the CTRL+char sequence, the control
+// // key subtracts 64 from the value of the key that it modifies
+// int c = event.character + 64;
+// action = getKeyBinding(c | event.stateMask);
+// }
+// }
+// }
+// if (action == SWT.NULL) {
+// boolean ignore = false;
+//
+// if (IS_MAC) {
+// // Ignore accelerator key combinations (we do not want to
+// // insert a character in the text in this instance).
+// ignore = (event.stateMask & (SWT.COMMAND | SWT.CTRL)) != 0;
+// } else {
+// // Ignore accelerator key combinations (we do not want to
+// // insert a character in the text in this instance). Don't
+// // ignore CTRL+ALT combinations since that is the Alt Gr
+// // key on some keyboards. See bug 20953.
+// ignore = event.stateMask == SWT.ALT ||
+// event.stateMask == SWT.CTRL ||
+// event.stateMask == (SWT.ALT | SWT.SHIFT) ||
+// event.stateMask == (SWT.CTRL | SWT.SHIFT);
+// }
+// // -ignore anything below SPACE except for line delimiter keys and tab.
+// // -ignore DEL
+// if (!ignore && event.character > 31 && event.character != SWT.DEL ||
+// event.character == SWT.CR || event.character == SWT.LF ||
+// event.character == TAB) {
+// doContent(event.character);
+// update();
+// }
+// } else {
+// invokeAction(action);
+// }
+//}
+///**
+// * If a VerifyKey listener exists, verify that the key that was entered
+// * should be processed.
+// *
+// * @param event keyboard event
+// */
+//void handleKeyDown(Event event) {
+// if (clipboardSelection == null) {
+// clipboardSelection = new Point(selection[0].x, selection[0].y);
+// }
+// newOrientation = SWT.NONE;
+// event.stateMask &= SWT.MODIFIER_MASK;
+//
+// Event verifyEvent = new Event();
+// verifyEvent.character = event.character;
+// verifyEvent.keyCode = event.keyCode;
+// verifyEvent.keyLocation = event.keyLocation;
+// verifyEvent.stateMask = event.stateMask;
+// verifyEvent.doit = event.doit;
+// notifyListeners(ST.VerifyKey, verifyEvent);
+// if (verifyEvent.doit) {
+// if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL && event.keyCode == SWT.SHIFT && isBidiCaret()) {
+// newOrientation = event.keyLocation == SWT.LEFT ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT;
+// }
+// handleKey(event);
+// }
+//}
+///**
+// * Update the Selection Clipboard.
+// *
+// * @param event keyboard event
+// */
+//void handleKeyUp(Event event) {
+// if (clipboardSelection != null) {
+// if (clipboardSelection.x != selection[0].x || clipboardSelection.y != selection[0].y) {
+// copySelection(DND.SELECTION_CLIPBOARD);
+// }
+// }
+// clipboardSelection = null;
+//
+// if (newOrientation != SWT.NONE) {
+// if (newOrientation != getOrientation()) {
+// Event e = new Event();
+// e.doit = true;
+// notifyListeners(SWT.OrientationChange, e);
+// if (e.doit) {
+// setOrientation(newOrientation);
+// }
+// }
+// newOrientation = SWT.NONE;
+// }
+//}
+///**
+// * Update the event location for focus-based context menu triggers.
+// *
+// * @param event menu detect event
+// */
+//void handleMenuDetect(Event event) {
+// if (event.detail == SWT.MENU_KEYBOARD) {
+// Point point = getDisplay().map(this, null, getPointAtOffset(caretOffsets[0]));
+// event.x = point.x;
+// event.y = point.y + getLineHeight(caretOffsets[0]);
+// }
+//}
+///**
+// * Updates the caret location and selection if mouse button 1 has been
+// * pressed.
+// */
+//void handleMouseDown(Event event) {
+// //force focus (object support)
+// forceFocus();
+//
+// //drag detect
+// if (dragDetect && checkDragDetect(event)) return;
+//
+// //paste clipboard selection
+// if (event.button == 2) {
+// // On GTK, if mouseNavigator is enabled we have to distinguish a short middle-click (to paste content) from
+// // a long middle-click (mouse navigation started)
+// if (IS_GTK && mouseNavigator != null) {
+// middleClickPressed = true;
+// getDisplay().timerExec(200, ()->{
+// boolean click = middleClickPressed;
+// middleClickPressed = false;
+// if (click && mouseNavigator !=null) {
+// mouseNavigator.onMouseDown(event);
+// } else {
+// pasteOnMiddleClick(event);
+// }
+// });
+// return;
+// } else {
+// pasteOnMiddleClick(event);
+// }
+// }
+//
+// //set selection
+// if ((event.button != 1) || (IS_MAC && (event.stateMask & SWT.MOD4) != 0)) {
+// return;
+// }
+// clickCount = event.count;
+// boolean addSelection = (event.stateMask & SWT.MOD3) != 0;
+// if (clickCount == 1) {
+// if (addSelection && !blockSelection) {
+// int offset = getOffsetAtPoint(event.x, event.y, null);
+// addSelection(offset, 0);
+// sendSelectionEvent();
+// } else {
+// boolean expandSelection = (event.stateMask & SWT.MOD2) != 0;
+// doMouseLocationChange(event.x, event.y, expandSelection);
+// }
+// } else {
+// if (doubleClickEnabled) {
+// boolean wordSelect = (clickCount & 1) == 0;
+// int offset = getOffsetAtPoint(event.x, event.y, null);
+// int lineIndex = content.getLineAtOffset(offset);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// if (wordSelect) {
+// String line = content.getLine(lineIndex);
+// int lineLength = line.length();
+// int min = blockSelection ? lineOffset : 0;
+// int max = blockSelection ? lineOffset + lineLength : content.getCharCount();
+// final Point offsetPoint = getPointAtOffset(offset);
+// if (event.x > offsetPoint.x
+// && offset < Math.min(max, lineOffset + lineLength) // Not beyond EOL
+// && !Character.isWhitespace(line.charAt(offset - lineOffset))) { // Not on whitespace
+// offset++;
+// }
+// int start = Math.max(min, getWordPrevious(offset, SWT.MOVEMENT_WORD_START));
+// int end = Math.min(max, getWordNext(start, SWT.MOVEMENT_WORD_END));
+// int[] regions = new int[2];
+// if (addSelection) {
+// int[] current = getSelectionRanges();
+// regions = Arrays.copyOf(current, current.length + 2);
+// }
+// regions[regions.length - 2] = start;
+// regions[regions.length - 1] = end - start;
+// setSelection(regions, false, true);
+// sendSelectionEvent();
+// } else {
+// if (blockSelection) {
+// setBlockSelectionLocation(leftMargin, event.y, clientAreaWidth - rightMargin, event.y, true);
+// } else {
+// int lineEnd = content.getCharCount();
+// if (lineIndex + 1 < content.getLineCount()) {
+// lineEnd = content.getOffsetAtLine(lineIndex + 1);
+// }
+// int[] regions = new int[2];
+// if (addSelection) {
+// int[] current = getSelectionRanges();
+// regions = Arrays.copyOf(current, current.length + 2);
+// }
+// regions[regions.length - 2] = lineOffset;
+// regions[regions.length - 1] = lineEnd - lineOffset;
+// setSelection(regions, false, false);
+// sendSelectionEvent();
+// }
+// }
+// doubleClickSelection = new Point(selection[0].x, selection[0].y);
+// showCaret();
+// }
+// }
+//}
+//
+//void addSelection(int offset, int length) {
+// int[] ranges = getSelectionRanges();
+// ranges = Arrays.copyOf(ranges, ranges.length + 2);
+// ranges[ranges.length - 2] = offset;
+// ranges[ranges.length - 1] = length;
+// setSelection(ranges, true, true);
+//}
+//
+///**
+// * Updates the caret location and selection if mouse button 1 is pressed
+// * during the mouse move.
+// */
+//void handleMouseMove(Event event) {
+// if (clickCount > 0) {
+// update();
+// doAutoScroll(event);
+// doMouseLocationChange(event.x, event.y, true);
+// }
+// if (renderer.hasLinks) {
+// doMouseLinkCursor(event.x, event.y);
+// }
+//}
+///**
+// * Autoscrolling ends when the mouse button is released.
+// */
+//void handleMouseUp(Event event) {
+// middleClickPressed = false;
+// clickCount = 0;
+// endAutoScroll();
+// if (event.button == 1) {
+// copySelection(DND.SELECTION_CLIPBOARD);
+// }
+//}
+///**
+// * Renders the invalidated area specified in the paint event.
+// *
+// * @param event paint event
+// */
+//void handlePaint(Event event) {
+// if (event.width == 0 || event.height == 0) return;
+// if (clientAreaWidth == 0 || clientAreaHeight == 0) return;
+//
+// final int endY = event.y + event.height;
+// GC gc = event.gc;
+// Color background = getBackground();
+// Color foreground = getForeground();
+// if (endY > 0) {
+// final int startLine = getLineIndex(event.y);
+// final int endLine = isSingleLine() ? 1 : content.getLineCount();
+// final int x = leftMargin - horizontalScrollOffset;
+// int y = getLinePixel(startLine);
+// y += renderer.drawLines(startLine, endLine, x, y, endY, gc, background, foreground);
+// if (y < endY) {
+// gc.setBackground(background);
+// drawBackground(gc, 0, y, clientAreaWidth, endY - y);
+// }
+// }
+// if (blockSelection && blockXLocation != -1) {
+// gc.setBackground(getSelectionBackground());
+// Rectangle rect = getBlockSelectionRectangle();
+// gc.drawRectangle(rect.x, rect.y, Math.max(1, rect.width - 1), Math.max(1, rect.height - 1));
+// gc.setAdvanced(true);
+// if (gc.getAdvanced()) {
+// gc.setAlpha(100);
+// gc.fillRectangle(rect);
+// gc.setAdvanced(false);
+// }
+// }
+// if(carets != null) {
+// for (int i = 1; i < carets.length; i++) { //skip 1st caret that's already drawn
+// Caret caret = carets[i];
+// if (caret.isVisible()) {
+// if (caret.getImage() != null) {
+// gc.drawImage(caret.getImage(), caret.getBounds().x, caret.getBounds().y);
+// } else {
+// gc.drawRectangle(caret.getBounds().x, caret.getBounds().y, caret.getBounds().width, getLineHeight(caretOffsets[i]));
+// }
+// }
+// }
+// }
+//
+// // fill the margin background
+// gc.setBackground(marginColor != null ? marginColor : background);
+// if (topMargin > 0) {
+// drawBackground(gc, 0, 0, clientAreaWidth, topMargin);
+// }
+// if (bottomMargin > 0) {
+// drawBackground(gc, 0, clientAreaHeight - bottomMargin, clientAreaWidth, bottomMargin);
+// }
+// if (leftMargin - alignmentMargin > 0) {
+// drawBackground(gc, 0, 0, leftMargin - alignmentMargin, clientAreaHeight);
+// }
+// if (rightMargin > 0) {
+// drawBackground(gc, clientAreaWidth - rightMargin, 0, rightMargin, clientAreaHeight);
+// }
+//}
+///**
+// * Recalculates the scroll bars. Rewraps all lines when in word
+// * wrap mode.
+// *
+// * @param event resize event
+// */
+//void handleResize(Event event) {
+// int oldHeight = clientAreaHeight;
+// int oldWidth = clientAreaWidth;
+// Rectangle clientArea = getClientArea();
+// clientAreaHeight = clientArea.height;
+// clientAreaWidth = clientArea.width;
+// if (!alwaysShowScroll && ignoreResize != 0) return;
+//
+// redrawMargins(oldHeight, oldWidth);
+// if (wordWrap) {
+// if (oldWidth != clientAreaWidth) {
+// renderer.reset(0, content.getLineCount());
+// verticalScrollOffset = -1;
+// renderer.calculateIdle();
+// super.redraw();
+// }
+// if (oldHeight != clientAreaHeight) {
+// if (oldHeight == 0) topIndexY = 0;
+// setScrollBars(true);
+// }
+// setCaretLocations();
+// } else {
+// renderer.calculateClientArea();
+// setScrollBars(true);
+// claimRightFreeSpace();
+// // StyledText allows any value for horizontalScrollOffset when clientArea is zero
+// // in setHorizontalPixel() and setHorisontalOffset(). Fixes bug 168429.
+// if (clientAreaWidth != 0) {
+// ScrollBar horizontalBar = getHorizontalBar();
+// if (horizontalBar != null && horizontalBar.getVisible()) {
+// if (horizontalScrollOffset != horizontalBar.getSelection()) {
+// horizontalBar.setSelection(horizontalScrollOffset);
+// horizontalScrollOffset = horizontalBar.getSelection();
+// }
+// }
+// }
+// }
+// updateCaretVisibility();
+// claimBottomFreeSpace();
+// setAlignment();
+// //TODO FIX TOP INDEX DURING RESIZE
+//// if (oldHeight != clientAreaHeight || wordWrap) {
+//// calculateTopIndex(0);
+//// }
+//}
+///**
+// * Updates the caret position and selection and the scroll bars to reflect
+// * the content change.
+// */
+//void handleTextChanged(TextChangedEvent event) {
+// int offset = ime.getCompositionOffset();
+// if (offset != -1 && lastTextChangeStart < offset) {
+// // updating the compositionOffset of the ongoing IME if last IMEs text is deleted meanwhile
+// // for example 1.insert IME text 2.open IME menu 3. ctrl+backspace => 4. commit IME would result in IllegalArgumentException
+// int compositionOffset = ime.getCaretOffset() + lastTextChangeNewCharCount - lastTextChangeReplaceCharCount;
+// // workaround: while ongoing IME non-ime text is deleted it may result in too big compositionOffset
+// // for example 1.insert IME text 2.insert space 3.open IME menu 4. ctrl+backspace twice => 5. commit IME would result in IllegalArgumentException
+// compositionOffset= Math.min(compositionOffset, getCharCount());
+// ime.setCompositionOffset(compositionOffset);
+// }
+// int firstLine = content.getLineAtOffset(lastTextChangeStart);
+// resetCache(firstLine, 0);
+// if (!isFixedLineHeight() && topIndex > firstLine) {
+// topIndex = firstLine;
+// if (topIndex < 0) {
+// // TODO: This logging is in place to determine why topIndex is getting set to negative values.
+// // It should be deleted once we fix the root cause of this issue. See bug 487254 for details.
+// System.err.println("StyledText: topIndex was " + topIndex
+// + ", lastTextChangeStart = " + lastTextChangeStart
+// + ", content.getClass() = " + content.getClass()
+// );
+// topIndex = 0;
+// }
+// topIndexY = 0;
+// super.redraw();
+// } else {
+// int lastLine = firstLine + lastTextChangeNewLineCount;
+// int firstLineTop = getLinePixel(firstLine);
+// int newLastLineBottom = getLinePixel(lastLine + 1);
+// if (lastLineBottom != newLastLineBottom) {
+// super.redraw();
+// } else {
+// super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false);
+// redrawLinesBullet(renderer.redrawLines);
+// }
+// }
+// renderer.redrawLines = null;
+// // update selection/caret location after styles have been changed.
+// // otherwise any text measuring could be incorrect
+// //
+// // also, this needs to be done after all scrolling. Otherwise,
+// // selection redraw would be flushed during scroll which is wrong.
+// // in some cases new text would be drawn in scroll source area even
+// // though the intent is to scroll it.
+// if (!(blockSelection && blockXLocation != -1)) {
+// updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount);
+// }
+// if (lastTextChangeReplaceLineCount > 0 || wordWrap || visualWrap) {
+// claimBottomFreeSpace();
+// }
+// if (lastTextChangeReplaceCharCount > 0) {
+// claimRightFreeSpace();
+// }
+//
+// sendAccessibleTextChanged(lastTextChangeStart, lastTextChangeNewCharCount, 0);
+// lastCharCount += lastTextChangeNewCharCount;
+// lastCharCount -= lastTextChangeReplaceCharCount;
+// setAlignment();
+//}
+///**
+// * Updates the screen to reflect a pending content change.
+// *
+// * @param event .start the start offset of the change
+// * @param event .newText text that is going to be inserted or empty String
+// * if no text will be inserted
+// * @param event .replaceCharCount length of text that is going to be replaced
+// * @param event .newCharCount length of text that is going to be inserted
+// * @param event .replaceLineCount number of lines that are going to be replaced
+// * @param event .newLineCount number of new lines that are going to be inserted
+// */
+//void handleTextChanging(TextChangingEvent event) {
+// if (event.replaceCharCount < 0) {
+// event.start += event.replaceCharCount;
+// event.replaceCharCount *= -1;
+// }
+// lastTextChangeStart = event.start;
+// lastTextChangeNewLineCount = event.newLineCount;
+// lastTextChangeNewCharCount = event.newCharCount;
+// lastTextChangeReplaceLineCount = event.replaceLineCount;
+// lastTextChangeReplaceCharCount = event.replaceCharCount;
+// int lineIndex = content.getLineAtOffset(event.start);
+// int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1);
+// int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight();
+// lastLineBottom = destY;
+// if (srcY < 0 && destY < 0) {
+// lastLineBottom += srcY - destY;
+// verticalScrollOffset += destY - srcY;
+// calculateTopIndex(destY - srcY);
+// setScrollBars(true);
+// } else {
+// scrollText(srcY, destY);
+// }
+// sendAccessibleTextChanged(lastTextChangeStart, 0, lastTextChangeReplaceCharCount);
+// renderer.textChanging(event);
+//
+// // Update the caret offset if it is greater than the length of the content.
+// // This is necessary since style range API may be called between the
+// // handleTextChanging and handleTextChanged events and this API sets the
+// // caretOffset.
+// int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount;
+// int tooBigOffsets = 0;
+// while (tooBigOffsets < caretOffsets.length && caretOffsets[caretOffsets.length - 1 - tooBigOffsets] > newEndOfText) {
+// tooBigOffsets++;
+// }
+// if (tooBigOffsets != 0) {
+// int[] newCaretOffsets = Arrays.copyOf(caretOffsets, caretOffsets.length - tooBigOffsets + 1);
+// newCaretOffsets[newCaretOffsets.length - 1] = newEndOfText;
+// setCaretOffsets(newCaretOffsets, SWT.DEFAULT);
+// }
+//}
+///**
+// * Called when the widget content is set programmatically, overwriting
+// * the old content. Resets the caret position, selection and scroll offsets.
+// * Recalculates the content width and scroll bars. Redraws the widget.
+// *
+// * @param event text change event.
+// */
+//void handleTextSet(TextChangedEvent event) {
+// reset();
+// int newCharCount = getCharCount();
+// sendAccessibleTextChanged(0, newCharCount, lastCharCount);
+// lastCharCount = newCharCount;
+// setAlignment();
+//}
+///**
+// * Called when a traversal key is pressed.
+// * Allow tab next traversal to occur when the widget is in single
+// * line mode or in multi line and non-editable mode .
+// * When in editable multi line mode we want to prevent the tab
+// * traversal and receive the tab key event instead.
+// *
+// * @param event the event
+// */
+//void handleTraverse(Event event) {
+// switch (event.detail) {
+// case SWT.TRAVERSE_ESCAPE:
+// case SWT.TRAVERSE_PAGE_NEXT:
+// case SWT.TRAVERSE_PAGE_PREVIOUS:
+// event.doit = true;
+// break;
+// case SWT.TRAVERSE_RETURN:
+// case SWT.TRAVERSE_TAB_NEXT:
+// case SWT.TRAVERSE_TAB_PREVIOUS:
+// if ((getStyle() & SWT.SINGLE) != 0) {
+// event.doit = true;
+// } else {
+// if (!editable || (event.stateMask & SWT.MODIFIER_MASK) != 0) {
+// event.doit = true;
+// }
+// }
+// break;
+// }
+//}
+///**
+// * Scrolls the widget vertically.
+// */
+//void handleVerticalScroll(Event event) {
+// int scrollPixel = getVerticalBar().getSelection() - getVerticalScrollOffset();
+// scrollVertical(scrollPixel, false);
+//}
+///**
+// * Add accessibility support for the widget.
+// */
+//void initializeAccessible() {
+// acc = getAccessible();
+//
+// accAdapter = new AccessibleAdapter() {
+// @Override
+// public void getName (AccessibleEvent e) {
+// String name = null;
+// String text = getAssociatedLabel ();
+// if (text != null) {
+// name = stripMnemonic (text);
+// }
+// e.result = name;
+// }
+// @Override
+// public void getHelp(AccessibleEvent e) {
+// e.result = getToolTipText();
+// }
+// @Override
+// public void getKeyboardShortcut(AccessibleEvent e) {
+// String shortcut = null;
+// String text = getAssociatedLabel ();
+// if (text != null) {
+// char mnemonic = _findMnemonic (text);
+// if (mnemonic != '\0') {
+// shortcut = "Alt+"+mnemonic; //$NON-NLS-1$
+// }
+// }
+// e.result = shortcut;
+// }
+// };
+// acc.addAccessibleListener(accAdapter);
+//
+// accTextExtendedAdapter = new AccessibleTextExtendedAdapter() {
+// @Override
+// public void getCaretOffset(AccessibleTextEvent e) {
+// e.offset = StyledText.this.getCaretOffset();
+// }
+// @Override
+// public void setCaretOffset(AccessibleTextEvent e) {
+// StyledText.this.setCaretOffset(e.offset);
+// e.result = ACC.OK;
+// }
+// @Override
+// public void getSelectionRange(AccessibleTextEvent e) {
+// Point selection = StyledText.this.getSelectionRange();
+// e.offset = selection.x;
+// e.length = selection.y;
+// }
+// @Override
+// public void addSelection(AccessibleTextEvent e) {
+// StyledText st = StyledText.this;
+// Point point = st.getSelection();
+// if (point.x == point.y) {
+// int end = e.end;
+// if (end == -1) end = st.getCharCount();
+// st.setSelection(e.start, end);
+// e.result = ACC.OK;
+// }
+// }
+// @Override
+// public void getSelection(AccessibleTextEvent e) {
+// StyledText st = StyledText.this;
+// if (st.blockSelection && st.blockXLocation != -1) {
+// Rectangle rect = st.getBlockSelectionPosition();
+// int lineIndex = rect.y + e.index;
+// int linePixel = st.getLinePixel(lineIndex);
+// e.ranges = getRanges(rect.x, linePixel, rect.width, linePixel);
+// if (e.ranges.length > 0) {
+// e.start = e.ranges[0];
+// e.end = e.ranges[e.ranges.length - 1];
+// }
+// } else {
+// if (e.index == 0) {
+// Point point = st.getSelection();
+// e.start = point.x;
+// e.end = point.y;
+// if (e.start > e.end) {
+// int temp = e.start;
+// e.start = e.end;
+// e.end = temp;
+// }
+// }
+// }
+// }
+// @Override
+// public void getSelectionCount(AccessibleTextEvent e) {
+// StyledText st = StyledText.this;
+// if (st.blockSelection && st.blockXLocation != -1) {
+// Rectangle rect = st.getBlockSelectionPosition();
+// e.count = rect.height - rect.y + 1;
+// } else {
+// Point point = st.getSelection();
+// e.count = point.x == point.y ? 0 : 1;
+// }
+// }
+// @Override
+// public void removeSelection(AccessibleTextEvent e) {
+// StyledText st = StyledText.this;
+// if (e.index == 0) {
+// if (st.blockSelection) {
+// st.clearBlockSelection(true, false);
+// } else {
+// st.clearSelection(false);
+// }
+// e.result = ACC.OK;
+// }
+// }
+// @Override
+// public void setSelection(AccessibleTextEvent e) {
+// if (e.index != 0) return;
+// StyledText st = StyledText.this;
+// Point point = st.getSelection();
+// if (point.x == point.y) return;
+// int end = e.end;
+// if (end == -1) end = st.getCharCount();
+// st.setSelection(e.start, end);
+// e.result = ACC.OK;
+// }
+// @Override
+// public void getCharacterCount(AccessibleTextEvent e) {
+// e.count = StyledText.this.getCharCount();
+// }
+// @Override
+// public void getOffsetAtPoint(AccessibleTextEvent e) {
+// StyledText st = StyledText.this;
+// Point point = new Point (e.x, e.y);
+// Display display = st.getDisplay();
+// point = display.map(null, st, point);
+// e.offset = st.getOffsetAtPoint(point.x, point.y, null, true);
+// }
+// @Override
+// public void getTextBounds(AccessibleTextEvent e) {
+// StyledText st = StyledText.this;
+// int start = e.start;
+// int end = e.end;
+// int contentLength = st.getCharCount();
+// start = Math.max(0, Math.min(start, contentLength));
+// end = Math.max(0, Math.min(end, contentLength));
+// if (start > end) {
+// int temp = start;
+// start = end;
+// end = temp;
+// }
+// int startLine = st.getLineAtOffset(start);
+// int endLine = st.getLineAtOffset(end);
+// Rectangle[] rects = new Rectangle[endLine - startLine + 1];
+// Rectangle bounds = null;
+// int index = 0;
+// Display display = st.getDisplay();
+// for (int lineIndex = startLine; lineIndex <= endLine; lineIndex++) {
+// Rectangle rect = new Rectangle(0, 0, 0, 0);
+// rect.y = st.getLinePixel(lineIndex);
+// rect.height = st.renderer.getLineHeight(lineIndex);
+// if (lineIndex == startLine) {
+// rect.x = st.getPointAtOffset(start).x;
+// } else {
+// rect.x = st.leftMargin - st.horizontalScrollOffset;
+// }
+// if (lineIndex == endLine) {
+// rect.width = st.getPointAtOffset(end).x - rect.x;
+// } else {
+// TextLayout layout = st.renderer.getTextLayout(lineIndex);
+// rect.width = layout.getBounds().width - rect.x;
+// st.renderer.disposeTextLayout(layout);
+// }
+// rects [index++] = rect = display.map(st, null, rect);
+// if (bounds == null) {
+// bounds = new Rectangle(rect.x, rect.y, rect.width, rect.height);
+// } else {
+// bounds.add(rect);
+// }
+// }
+// e.rectangles = rects;
+// if (bounds != null) {
+// e.x = bounds.x;
+// e.y = bounds.y;
+// e.width = bounds.width;
+// e.height = bounds.height;
+// }
+// }
+// int[] getRanges(int left, int top, int right, int bottom) {
+// StyledText st = StyledText.this;
+// int lineStart = st.getLineIndex(top);
+// int lineEnd = st.getLineIndex(bottom);
+// int count = lineEnd - lineStart + 1;
+// int[] ranges = new int [count * 2];
+// int index = 0;
+// for (int lineIndex = lineStart; lineIndex <= lineEnd; lineIndex++) {
+// String line = st.content.getLine(lineIndex);
+// int lineOffset = st.content.getOffsetAtLine(lineIndex);
+// int lineEndOffset = lineOffset + line.length();
+// int linePixel = st.getLinePixel(lineIndex);
+// int start = st.getOffsetAtPoint(left, linePixel, null, true);
+// if (start == -1) {
+// start = left < st.leftMargin ? lineOffset : lineEndOffset;
+// }
+// int[] trailing = new int[1];
+// int end = st.getOffsetAtPoint(right, linePixel, trailing, true);
+// if (end == -1) {
+// end = right < st.leftMargin ? lineOffset : lineEndOffset;
+// } else {
+// end += trailing[0];
+// }
+// if (start > end) {
+// int temp = start;
+// start = end;
+// end = temp;
+// }
+// ranges[index++] = start;
+// ranges[index++] = end;
+// }
+// return ranges;
+// }
+// @Override
+// public void getRanges(AccessibleTextEvent e) {
+// StyledText st = StyledText.this;
+// Point point = new Point (e.x, e.y);
+// Display display = st.getDisplay();
+// point = display.map(null, st, point);
+// e.ranges = getRanges(point.x, point.y, point.x + e.width, point.y + e.height);
+// if (e.ranges.length > 0) {
+// e.start = e.ranges[0];
+// e.end = e.ranges[e.ranges.length - 1];
+// }
+// }
+// @Override
+// public void getText(AccessibleTextEvent e) {
+// StyledText st = StyledText.this;
+// int start = e.start;
+// int end = e.end;
+// int contentLength = st.getCharCount();
+// if (end == -1) end = contentLength;
+// start = Math.max(0, Math.min(start, contentLength));
+// end = Math.max(0, Math.min(end, contentLength));
+// if (start > end) {
+// int temp = start;
+// start = end;
+// end = temp;
+// }
+// int count = e.count;
+// switch (e.type) {
+// case ACC.TEXT_BOUNDARY_ALL:
+// //nothing to do
+// break;
+// case ACC.TEXT_BOUNDARY_CHAR: {
+// int newCount = 0;
+// if (count > 0) {
+// while (count-- > 0) {
+// int newEnd = st.getWordNext(end, SWT.MOVEMENT_CLUSTER);
+// if (newEnd == contentLength) break;
+// if (newEnd == end) break;
+// end = newEnd;
+// newCount++;
+// }
+// start = end;
+// end = st.getWordNext(end, SWT.MOVEMENT_CLUSTER);
+// } else {
+// while (count++ < 0) {
+// int newStart = st.getWordPrevious(start, SWT.MOVEMENT_CLUSTER);
+// if (newStart == start) break;
+// start = newStart;
+// newCount--;
+// }
+// end = st.getWordNext(start, SWT.MOVEMENT_CLUSTER);
+// }
+// count = newCount;
+// break;
+// }
+// case ACC.TEXT_BOUNDARY_WORD: {
+// int newCount = 0;
+// if (count > 0) {
+// while (count-- > 0) {
+// int newEnd = st.getWordNext(end, SWT.MOVEMENT_WORD_START, true);
+// if (newEnd == end) break;
+// newCount++;
+// end = newEnd;
+// }
+// start = end;
+// end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true);
+// } else {
+// if (st.getWordPrevious(Math.min(start + 1, contentLength), SWT.MOVEMENT_WORD_START, true) == start) {
+// //start is a word start already
+// count++;
+// }
+// while (count <= 0) {
+// int newStart = st.getWordPrevious(start, SWT.MOVEMENT_WORD_START, true);
+// if (newStart == start) break;
+// count++;
+// start = newStart;
+// if (count != 0) newCount--;
+// }
+// if (count <= 0 && start == 0) {
+// end = start;
+// } else {
+// end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true);
+// }
+// }
+// count = newCount;
+// break;
+// }
+// case ACC.TEXT_BOUNDARY_LINE:
+// //TODO implement line
+// case ACC.TEXT_BOUNDARY_PARAGRAPH:
+// case ACC.TEXT_BOUNDARY_SENTENCE: {
+// int offset = count > 0 ? end : start;
+// int lineIndex = st.getLineAtOffset(offset) + count;
+// lineIndex = Math.max(0, Math.min(lineIndex, st.getLineCount() - 1));
+// start = st.getOffsetAtLine(lineIndex);
+// String line = st.getLine(lineIndex);
+// end = start + line.length();
+// count = lineIndex - st.getLineAtOffset(offset);
+// break;
+// }
+// }
+// e.start = start;
+// e.end = end;
+// e.count = count;
+// e.result = st.content.getTextRange(start, end - start);
+// }
+// @Override
+// public void getVisibleRanges(AccessibleTextEvent e) {
+// e.ranges = getRanges(leftMargin, topMargin, clientAreaWidth - rightMargin, clientAreaHeight - bottomMargin);
+// if (e.ranges.length > 0) {
+// e.start = e.ranges[0];
+// e.end = e.ranges[e.ranges.length - 1];
+// }
+// }
+// @Override
+// public void scrollText(AccessibleTextEvent e) {
+// StyledText st = StyledText.this;
+// int topPixel = getTopPixel(), horizontalPixel = st.getHorizontalPixel();
+// switch (e.type) {
+// case ACC.SCROLL_TYPE_ANYWHERE:
+// case ACC.SCROLL_TYPE_TOP_LEFT:
+// case ACC.SCROLL_TYPE_LEFT_EDGE:
+// case ACC.SCROLL_TYPE_TOP_EDGE: {
+// Rectangle rect = st.getBoundsAtOffset(e.start);
+// if (e.type != ACC.SCROLL_TYPE_TOP_EDGE) {
+// horizontalPixel = horizontalPixel + rect.x - st.leftMargin;
+// }
+// if (e.type != ACC.SCROLL_TYPE_LEFT_EDGE) {
+// topPixel = topPixel + rect.y - st.topMargin;
+// }
+// break;
+// }
+// case ACC.SCROLL_TYPE_BOTTOM_RIGHT:
+// case ACC.SCROLL_TYPE_BOTTOM_EDGE:
+// case ACC.SCROLL_TYPE_RIGHT_EDGE: {
+// Rectangle rect = st.getBoundsAtOffset(e.end - 1);
+// if (e.type != ACC.SCROLL_TYPE_BOTTOM_EDGE) {
+// horizontalPixel = horizontalPixel - st.clientAreaWidth + rect.x + rect.width + st.rightMargin;
+// }
+// if (e.type != ACC.SCROLL_TYPE_RIGHT_EDGE) {
+// topPixel = topPixel - st.clientAreaHeight + rect.y +rect.height + st.bottomMargin;
+// }
+// break;
+// }
+// case ACC.SCROLL_TYPE_POINT: {
+// Point point = new Point(e.x, e.y);
+// Display display = st.getDisplay();
+// point = display.map(null, st, point);
+// Rectangle rect = st.getBoundsAtOffset(e.start);
+// topPixel = topPixel - point.y + rect.y;
+// horizontalPixel = horizontalPixel - point.x + rect.x;
+// break;
+// }
+// }
+// st.setTopPixel(topPixel);
+// st.setHorizontalPixel(horizontalPixel);
+// e.result = ACC.OK;
+// }
+// };
+// acc.addAccessibleTextListener(accTextExtendedAdapter);
+//
+// accEditableTextListener = new AccessibleEditableTextListener() {
+// @Override
+// public void setTextAttributes(AccessibleTextAttributeEvent e) {
+// // This method must be implemented by the application
+// e.result = ACC.OK;
+// }
+// @Override
+// public void replaceText(AccessibleEditableTextEvent e) {
+// StyledText st = StyledText.this;
+// st.replaceTextRange(e.start, e.end - e.start, e.string);
+// e.result = ACC.OK;
+// }
+// @Override
+// public void pasteText(AccessibleEditableTextEvent e) {
+// StyledText st = StyledText.this;
+// st.setSelection(e.start);
+// st.paste();
+// e.result = ACC.OK;
+// }
+// @Override
+// public void cutText(AccessibleEditableTextEvent e) {
+// StyledText st = StyledText.this;
+// st.setSelection(e.start, e.end);
+// st.cut();
+// e.result = ACC.OK;
+// }
+// @Override
+// public void copyText(AccessibleEditableTextEvent e) {
+// StyledText st = StyledText.this;
+// st.setSelection(e.start, e.end);
+// st.copy();
+// e.result = ACC.OK;
+// }
+// };
+// acc.addAccessibleEditableTextListener(accEditableTextListener);
+//
+// accAttributeAdapter = new AccessibleAttributeAdapter() {
+// @Override
+// public void getAttributes(AccessibleAttributeEvent e) {
+// StyledText st = StyledText.this;
+// e.leftMargin = st.getLeftMargin();
+// e.topMargin = st.getTopMargin();
+// e.rightMargin = st.getRightMargin();
+// e.bottomMargin = st.getBottomMargin();
+// e.tabStops = st.getTabStops();
+// e.justify = st.getJustify();
+// e.alignment = st.getAlignment();
+// e.indent = st.getIndent();
+// }
+// @Override
+// public void getTextAttributes(AccessibleTextAttributeEvent e) {
+// StyledText st = StyledText.this;
+// int contentLength = st.getCharCount();
+// if (!isListening(ST.LineGetStyle) && st.renderer.styleCount == 0) {
+// e.start = 0;
+// e.end = contentLength;
+// e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background);
+// return;
+// }
+// int offset = Math.max(0, Math.min(e.offset, contentLength - 1));
+// int lineIndex = st.getLineAtOffset(offset);
+// int lineOffset = st.getOffsetAtLine(lineIndex);
+// int lineCount = st.getLineCount();
+// offset = offset - lineOffset;
+//
+// TextLayout layout = st.renderer.getTextLayout(lineIndex);
+// int lineLength = layout.getText().length();
+// if (lineLength > 0) {
+// e.textStyle = layout.getStyle(Math.max(0, Math.min(offset, lineLength - 1)));
+// }
+//
+// // If no override info available, use defaults. Don't supply default colors, though.
+// if (e.textStyle == null) {
+// e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background);
+// } else {
+// if (e.textStyle.foreground == null || e.textStyle.background == null || e.textStyle.font == null) {
+// TextStyle textStyle = new TextStyle(e.textStyle);
+// if (textStyle.foreground == null) textStyle.foreground = st.foreground;
+// if (textStyle.background == null) textStyle.background = st.background;
+// if (textStyle.font == null) textStyle.font = st.getFont();
+// e.textStyle = textStyle;
+// }
+// }
+//
+// //offset at line delimiter case
+// if (offset >= lineLength) {
+// e.start = lineOffset + lineLength;
+// if (lineIndex + 1 < lineCount) {
+// e.end = st.getOffsetAtLine(lineIndex + 1);
+// } else {
+// e.end = contentLength;
+// }
+// return;
+// }
+//
+// int[] ranges = layout.getRanges();
+// st.renderer.disposeTextLayout(layout);
+// int index = 0;
+// int end = 0;
+// while (index < ranges.length) {
+// int styleStart = ranges[index++];
+// int styleEnd = ranges[index++];
+// if (styleStart <= offset && offset <= styleEnd) {
+// e.start = lineOffset + styleStart;
+// e.end = lineOffset + styleEnd + 1;
+// return;
+// }
+// if (styleStart > offset) {
+// e.start = lineOffset + end;
+// e.end = lineOffset + styleStart;
+// return;
+// }
+// end = styleEnd + 1;
+// }
+// if (index == ranges.length) {
+// e.start = lineOffset + end;
+// if (lineIndex + 1 < lineCount) {
+// e.end = st.getOffsetAtLine(lineIndex + 1);
+// } else {
+// e.end = contentLength;
+// }
+// }
+// }
+// };
+// acc.addAccessibleAttributeListener(accAttributeAdapter);
+//
+// accControlAdapter = new AccessibleControlAdapter() {
+// @Override
+// public void getRole(AccessibleControlEvent e) {
+// e.detail = ACC.ROLE_TEXT;
+// }
+// @Override
+// public void getState(AccessibleControlEvent e) {
+// int state = 0;
+// if (isEnabled()) state |= ACC.STATE_FOCUSABLE;
+// if (isFocusControl()) state |= ACC.STATE_FOCUSED;
+// if (!isVisible()) state |= ACC.STATE_INVISIBLE;
+// if (!getEditable()) state |= ACC.STATE_READONLY;
+// if (isSingleLine()) state |= ACC.STATE_SINGLELINE;
+// else state |= ACC.STATE_MULTILINE;
+// e.detail = state;
+// }
+// @Override
+// public void getValue(AccessibleControlEvent e) {
+// e.result = StyledText.this.getText();
+// }
+// };
+// acc.addAccessibleControlListener(accControlAdapter);
+//
+// addListener(SWT.FocusIn, event -> acc.setFocus(ACC.CHILDID_SELF));
+//
+// addListener(SWT.Dispose, event -> {
+// // Issue 448: A 3rd party program that uses Accessible may
+// // cache obtained connection and query it even after StyledText
+// // is disposed. Disconnect all listeners to avoid querying a
+// // disposed control.
+// acc.removeAccessibleControlListener(accControlAdapter);
+// acc.removeAccessibleAttributeListener(accAttributeAdapter);
+// acc.removeAccessibleEditableTextListener(accEditableTextListener);
+// acc.removeAccessibleTextListener(accTextExtendedAdapter);
+// acc.removeAccessibleListener(accAdapter);
+// });
+//}
+//
+///*
+// * Return the Label immediately preceding the receiver in the z-order,
+// * or null if none.
+// */
+//String getAssociatedLabel () {
+// Control[] siblings = getParent ().getChildren ();
+// for (int i = 0; i < siblings.length; i++) {
+// if (siblings [i] == StyledText.this) {
+// if (i > 0) {
+// Control sibling = siblings [i-1];
+// if (sibling instanceof Label) return ((Label) sibling).getText();
+// if (sibling instanceof CLabel) return ((CLabel) sibling).getText();
+// }
+// break;
+// }
+// }
+// return null;
+//}
+//String stripMnemonic (String string) {
+// int index = 0;
+// int length = string.length ();
+// do {
+// while ((index < length) && (string.charAt (index) != '&')) index++;
+// if (++index >= length) return string;
+// if (string.charAt (index) != '&') {
+// return string.substring(0, index-1) + string.substring(index, length);
+// }
+// index++;
+// } while (index < length);
+// return string;
+//}
+///*
+// * Return the lowercase of the first non-'&' character following
+// * an '&' character in the given string. If there are no '&'
+// * characters in the given string, return '\0'.
+// */
+//char _findMnemonic (String string) {
+// if (string == null) return '\0';
+// int index = 0;
+// int length = string.length ();
+// do {
+// while (index < length && string.charAt (index) != '&') index++;
+// if (++index >= length) return '\0';
+// if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (index));
+// index++;
+// } while (index < length);
+// return '\0';
+//}
+///**
+// * Executes the action.
+// *
+// * @param action one of the actions defined in ST.java
+// */
+//public void invokeAction(int action) {
+// checkWidget();
+// if (blockSelection && invokeBlockAction(action)) return;
+// updateCaretDirection = true;
+// switch (action) {
+// // Navigation
+// case ST.LINE_UP:
+// doLineUp(false);
+// clearSelection(true);
+// break;
+// case ST.LINE_DOWN:
+// doLineDown(false);
+// clearSelection(true);
+// break;
+// case ST.LINE_START:
+// doLineStart();
+// clearSelection(true);
+// break;
+// case ST.LINE_END:
+// doLineEnd();
+// clearSelection(true);
+// break;
+// case ST.COLUMN_PREVIOUS:
+// doCursorPrevious();
+// clearSelection(true);
+// break;
+// case ST.COLUMN_NEXT:
+// doCursorNext();
+// clearSelection(true);
+// break;
+// case ST.PAGE_UP:
+// doPageUp(false, -1);
+// clearSelection(true);
+// break;
+// case ST.PAGE_DOWN:
+// doPageDown(false, -1);
+// clearSelection(true);
+// break;
+// case ST.WORD_PREVIOUS:
+// doWordPrevious();
+// clearSelection(true);
+// break;
+// case ST.WORD_NEXT:
+// doWordNext();
+// clearSelection(true);
+// break;
+// case ST.TEXT_START:
+// doContentStart();
+// clearSelection(true);
+// break;
+// case ST.TEXT_END:
+// doContentEnd();
+// clearSelection(true);
+// break;
+// case ST.WINDOW_START:
+// doPageStart();
+// clearSelection(true);
+// break;
+// case ST.WINDOW_END:
+// doPageEnd();
+// clearSelection(true);
+// break;
+// // Selection
+// case ST.SELECT_LINE_UP:
+// doSelectionLineUp();
+// break;
+// case ST.SELECT_ALL:
+// selectAll();
+// break;
+// case ST.SELECT_LINE_DOWN:
+// doSelectionLineDown();
+// break;
+// case ST.SELECT_LINE_START:
+// doLineStart();
+// doSelection(ST.COLUMN_PREVIOUS);
+// break;
+// case ST.SELECT_LINE_END:
+// doLineEnd();
+// doSelection(ST.COLUMN_NEXT);
+// break;
+// case ST.SELECT_COLUMN_PREVIOUS:
+// doSelectionCursorPrevious();
+// doSelection(ST.COLUMN_PREVIOUS);
+// break;
+// case ST.SELECT_COLUMN_NEXT:
+// doSelectionCursorNext();
+// doSelection(ST.COLUMN_NEXT);
+// break;
+// case ST.SELECT_PAGE_UP:
+// doSelectionPageUp(-1);
+// break;
+// case ST.SELECT_PAGE_DOWN:
+// doSelectionPageDown(-1);
+// break;
+// case ST.SELECT_WORD_PREVIOUS:
+// doSelectionWordPrevious();
+// doSelection(ST.COLUMN_PREVIOUS);
+// break;
+// case ST.SELECT_WORD_NEXT:
+// doSelectionWordNext();
+// doSelection(ST.COLUMN_NEXT);
+// break;
+// case ST.SELECT_TEXT_START:
+// doContentStart();
+// doSelection(ST.COLUMN_PREVIOUS);
+// break;
+// case ST.SELECT_TEXT_END:
+// doContentEnd();
+// doSelection(ST.COLUMN_NEXT);
+// break;
+// case ST.SELECT_WINDOW_START:
+// doPageStart();
+// doSelection(ST.COLUMN_PREVIOUS);
+// break;
+// case ST.SELECT_WINDOW_END:
+// doPageEnd();
+// doSelection(ST.COLUMN_NEXT);
+// break;
+// // Modification
+// case ST.CUT:
+// cut();
+// break;
+// case ST.COPY:
+// copy();
+// break;
+// case ST.PASTE:
+// paste();
+// break;
+// case ST.DELETE_PREVIOUS:
+// doBackspace();
+// break;
+// case ST.DELETE_NEXT:
+// doDelete();
+// break;
+// case ST.DELETE_WORD_PREVIOUS:
+// doDeleteWordPrevious();
+// break;
+// case ST.DELETE_WORD_NEXT:
+// doDeleteWordNext();
+// break;
+// // Miscellaneous
+// case ST.TOGGLE_OVERWRITE:
+// overwrite = !overwrite; // toggle insert/overwrite mode
+// break;
+// case ST.TOGGLE_BLOCKSELECTION:
+// setBlockSelection(!blockSelection);
+// break;
+// }
+//}
+///**
+//* Returns true if an action should not be performed when block
+//* selection in active
+//*/
+//boolean invokeBlockAction(int action) {
+// switch (action) {
+// // Navigation
+// case ST.LINE_UP:
+// case ST.LINE_DOWN:
+// case ST.LINE_START:
+// case ST.LINE_END:
+// case ST.COLUMN_PREVIOUS:
+// case ST.COLUMN_NEXT:
+// case ST.PAGE_UP:
+// case ST.PAGE_DOWN:
+// case ST.WORD_PREVIOUS:
+// case ST.WORD_NEXT:
+// case ST.TEXT_START:
+// case ST.TEXT_END:
+// case ST.WINDOW_START:
+// case ST.WINDOW_END:
+// clearBlockSelection(false, false);
+// return false;
+// // Selection
+// case ST.SELECT_LINE_UP:
+// doBlockLineVertical(true);
+// return true;
+// case ST.SELECT_LINE_DOWN:
+// doBlockLineVertical(false);
+// return true;
+// case ST.SELECT_LINE_START:
+// doBlockLineHorizontal(false);
+// return true;
+// case ST.SELECT_LINE_END:
+// doBlockLineHorizontal(true);
+// return false;
+// case ST.SELECT_COLUMN_PREVIOUS:
+// doBlockColumn(false);
+// return true;
+// case ST.SELECT_COLUMN_NEXT:
+// doBlockColumn(true);
+// return true;
+// case ST.SELECT_WORD_PREVIOUS:
+// doBlockWord(false);
+// return true;
+// case ST.SELECT_WORD_NEXT:
+// doBlockWord(true);
+// return true;
+// case ST.SELECT_ALL:
+// return false;
+// case ST.SELECT_TEXT_START:
+// doBlockContentStartEnd(false);
+// break;
+// case ST.SELECT_TEXT_END:
+// doBlockContentStartEnd(true);
+// break;
+// case ST.SELECT_PAGE_UP:
+// case ST.SELECT_PAGE_DOWN:
+// case ST.SELECT_WINDOW_START:
+// case ST.SELECT_WINDOW_END:
+// //blocked actions
+// return true;
+// // Modification
+// case ST.CUT:
+// case ST.COPY:
+// case ST.PASTE:
+// return false;
+// case ST.DELETE_PREVIOUS:
+// case ST.DELETE_NEXT:
+// if (blockXLocation != -1) {
+// insertBlockSelectionText((char)0, action);
+// return true;
+// }
+// return false;
+// case ST.DELETE_WORD_PREVIOUS:
+// case ST.DELETE_WORD_NEXT:
+// //blocked actions
+// return blockXLocation != -1;
+// }
+// return false;
+//}
+//boolean isBidiCaret() {
+// return BidiUtil.isBidiPlatform();
+//}
+//boolean isFixedLineHeight() {
+// return !isWordWrap() && lineSpacing == 0 && renderer.lineSpacingProvider == null && !hasStyleWithVariableHeight && !hasVerticalIndent;
+//}
+///**
+// * Returns whether the given offset is inside a multi byte line delimiter.
+// * Example:
+// * "Line1\r\n" isLineDelimiter(5) == false but isLineDelimiter(6) == true
+// *
+// * @return true if the given offset is inside a multi byte line delimiter.
+// * false if the given offset is before or after a line delimiter.
+// */
+//boolean isLineDelimiter(int offset) {
+// int line = content.getLineAtOffset(offset);
+// int lineOffset = content.getOffsetAtLine(line);
+// int offsetInLine = offset - lineOffset;
+// // offsetInLine will be greater than line length if the line
+// // delimiter is longer than one character and the offset is set
+// // in between parts of the line delimiter.
+// return offsetInLine > content.getLine(line).length();
+//}
+///**
+// * Returns whether the widget is mirrored (right oriented/right to left
+// * writing order).
+// *
+// * @return isMirrored true=the widget is right oriented, false=the widget
+// * is left oriented
+// */
+//boolean isMirrored() {
+// return (getStyle() & SWT.MIRRORED) != 0;
+//}
+///**
+// * Returns true if any text in the widget is selected,
+// * and false otherwise.
+// *
+// * @return the text selection state
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.103
+// */
+//public boolean isTextSelected() {
+// checkWidget();
+// if (blockSelection && blockXLocation != -1) {
+// Rectangle rect = getBlockSelectionPosition();
+// return !rect.isEmpty();
+// }
+// return Arrays.stream(selection).anyMatch(range -> range.x != range.y);
+//}
+///**
+// * Returns whether the widget can have only one line.
+// *
+// * @return true if widget can have only one line, false if widget can have
+// * multiple lines
+// */
+//boolean isSingleLine() {
+// return (getStyle() & SWT.SINGLE) != 0;
+//}
+//
+///**
+// * Sends the specified verify event, replace/insert text as defined by
+// * the event and send a modify event.
+// *
+// * @param event the text change event.
+// *
+// *
event.start - the replace start offset
+// *
event.end - the replace end offset
+// *
event.text - the new text
+// *
+// * @param updateCaret whether or not he caret should be set behind
+// * the new text
+// */
+//void modifyContent(Event event, boolean updateCaret) {
+// event.doit = true;
+// notifyListeners(SWT.Verify, event);
+// if (event.doit) {
+// StyledTextEvent styledTextEvent = null;
+// int replacedLength = event.end - event.start;
+// if (isListening(ST.ExtendedModify)) {
+// styledTextEvent = new StyledTextEvent(content);
+// styledTextEvent.start = event.start;
+// styledTextEvent.end = event.start + event.text.length();
+// styledTextEvent.text = content.getTextRange(event.start, replacedLength);
+// }
+// if (updateCaret) {
+// //Fix advancing flag for delete/backspace key on direction boundary
+// if (event.text.length() == 0) {
+// int lineIndex = content.getLineAtOffset(event.start);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// int levelStart = layout.getLevel(event.start - lineOffset);
+// int lineIndexEnd = content.getLineAtOffset(event.end);
+// if (lineIndex != lineIndexEnd) {
+// renderer.disposeTextLayout(layout);
+// lineOffset = content.getOffsetAtLine(lineIndexEnd);
+// layout = renderer.getTextLayout(lineIndexEnd);
+// }
+// int levelEnd = layout.getLevel(event.end - lineOffset);
+// renderer.disposeTextLayout(layout);
+// if (levelStart != levelEnd) {
+// caretAlignment = PREVIOUS_OFFSET_TRAILING;
+// } else {
+// caretAlignment = OFFSET_LEADING;
+// }
+// }
+// }
+// content.replaceTextRange(event.start, replacedLength, event.text);
+// // set the caret position prior to sending the modify event.
+// // fixes 1GBB8NJ
+// if (updateCaret && !(blockSelection && blockXLocation != -1)) {
+// // always update the caret location. fixes 1G8FODP
+// setSelection(Arrays.stream(selection).map(sel -> {
+// if (sel.y < event.start || sel.x > event.end) {
+// return sel;
+// } else { // current range edited
+// return new Point(event.start + event.text.length(), event.start + event.text.length());
+// }
+// }).flatMapToInt(p -> IntStream.of(p.x, p.y - p.x)).toArray(), true, false);
+// showCaret();
+// }
+// notifyListeners(SWT.Modify, event);
+// if (isListening(ST.ExtendedModify)) {
+// notifyListeners(ST.ExtendedModify, styledTextEvent);
+// }
+// }
+//}
+//void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style, Bullet bullet, int bulletIndex) {
+// if (isListening(ST.PaintObject)) {
+// StyledTextEvent event = new StyledTextEvent (content) ;
+// event.gc = gc;
+// event.x = x;
+// event.y = y;
+// event.ascent = ascent;
+// event.descent = descent;
+// event.style = style;
+// event.bullet = bullet;
+// event.bulletIndex = bulletIndex;
+// notifyListeners(ST.PaintObject, event);
+// }
+//}
+///**
+// * Replaces the selection with the text on the DND.CLIPBOARD
+// * clipboard or, if there is no selection, inserts the text at the current
+// * caret offset. If the widget has the SWT.SINGLE style and the
+// * clipboard text contains more than one line, only the first line without
+// * line delimiters is inserted in the widget.
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public void paste(){
+// checkWidget();
+// String text = (String) getClipboardContent(DND.CLIPBOARD);
+// if (text != null && text.length() > 0) {
+// if (blockSelection) {
+// boolean fillWithSpaces = isFixedLineHeight() && renderer.fixedPitch;
+// int offset = insertBlockSelectionText(text, fillWithSpaces);
+// setCaretOffsets(new int[] {offset}, SWT.DEFAULT);
+// clearBlockSelection(true, true);
+// setCaretLocations();
+// return;
+// } else if (getSelectionRanges().length / 2 > 1) { // multi selection
+// insertMultiSelectionText(text);
+// setCaretLocations();
+// return;
+// }
+// Event event = new Event();
+// event.start = selection[0].x;
+// event.end = selection[0].y;
+// String delimitedText = getModelDelimitedText(text);
+// if (textLimit > 0) {
+// int uneditedTextLength = getCharCount() - (selection[0].y - selection[0].x);
+// if ((uneditedTextLength + delimitedText.length()) > textLimit) {
+// int endIndex = textLimit - uneditedTextLength;
+// delimitedText = delimitedText.substring(0, Math.max(endIndex, 0));
+// }
+// }
+// event.text = delimitedText;
+// sendKeyEvent(event);
+// }
+//}
+//
+//private void insertMultiSelectionText(String text) {
+// String[] blocks = text.split(PlatformLineDelimiter);
+// int[] ranges = getSelectionRanges();
+// for (int i = ranges.length / 2 - 1; i >= 0; i --) {
+// int offset = ranges[2 * i];
+// int length = ranges[2 * i + 1];
+// String toPaste = blocks.length > i ? blocks[i] : blocks[blocks.length - 1];
+// Event event = new Event();
+// event.start = offset;
+// event.end = offset + length;
+// event.text = toPaste;
+// sendKeyEvent(event);
+// }
+//}
+//
+//private void pasteOnMiddleClick(Event event) {
+// String text = (String)getClipboardContent(DND.SELECTION_CLIPBOARD);
+// if (text != null && text.length() > 0) {
+// // position cursor
+// doMouseLocationChange(event.x, event.y, false);
+// // insert text
+// Event e = new Event();
+// e.start = selection[0].x;
+// e.end = selection[0].y;
+// e.text = getModelDelimitedText(text);
+// sendKeyEvent(e);
+// }
+//}
+///**
+// * Prints the widget's text to the default printer.
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public void print() {
+// checkWidget();
+// Printer printer = new Printer();
+// StyledTextPrintOptions options = new StyledTextPrintOptions();
+// options.printTextForeground = true;
+// options.printTextBackground = true;
+// options.printTextFontStyle = true;
+// options.printLineBackground = true;
+// new Printing(this, printer, options).run();
+// printer.dispose();
+//}
+///**
+// * Returns a runnable that will print the widget's text
+// * to the specified printer.
+// *
+// * The runnable may be run in a non-UI thread.
+// *
+// *
+// * @param printer the printer to print to
+// *
+// * @return a Runnable for printing the receiver's text
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when printer is null
+// *
+// */
+//public Runnable print(Printer printer) {
+// checkWidget();
+// if (printer == null) {
+// SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// }
+// StyledTextPrintOptions options = new StyledTextPrintOptions();
+// options.printTextForeground = true;
+// options.printTextBackground = true;
+// options.printTextFontStyle = true;
+// options.printLineBackground = true;
+// return print(printer, options);
+//}
+///**
+// * Returns a runnable that will print the widget's text
+// * to the specified printer.
+// *
+// * The runnable may be run in a non-UI thread.
+// *
+// *
+// * @param printer the printer to print to
+// * @param options print options to use during printing
+// *
+// * @return a Runnable for printing the receiver's text
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when printer or options is null
+// *
+// * @since 2.1
+// */
+//public Runnable print(Printer printer, StyledTextPrintOptions options) {
+// checkWidget();
+// if (printer == null || options == null) {
+// SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// }
+// return new Printing(this, printer, options);
+//}
+///**
+// * Causes the entire bounds of the receiver to be marked
+// * as needing to be redrawn. The next time a paint request
+// * is processed, the control will be completely painted.
+// *
+// * Recalculates the content width for all lines in the bounds.
+// * When a LineStyleListener is used a redraw call
+// * is the only notification to the widget that styles have changed
+// * and that the content width may have changed.
+// *
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see Control#update()
+// */
+//@Override
+//public void redraw() {
+// super.redraw();
+// int itemCount = getPartialBottomIndex() - topIndex + 1;
+// renderer.reset(topIndex, itemCount);
+// renderer.calculate(topIndex, itemCount);
+// setScrollBars(false);
+// doMouseLinkCursor();
+//}
+///**
+// * 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. If the all flag
+// * is true, any children of the receiver which
+// * intersect with the specified area will also paint their
+// * intersecting areas. If the all flag is
+// * false, the children will not be painted.
+// *
+// * Marks the content width of all lines in the specified rectangle
+// * as unknown. Recalculates the content width of all visible lines.
+// * When a LineStyleListener is used a redraw call
+// * is the only notification to the widget that styles have changed
+// * and that the content width may have changed.
+// *
+// *
+// * @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 true if children should redraw, and false otherwise
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see Control#update()
+// */
+//@Override
+//public void redraw(int x, int y, int width, int height, boolean all) {
+// super.redraw(x, y, width, height, all);
+// if (height > 0) {
+// int firstLine = getLineIndex(y);
+// int lastLine = getLineIndex(y + height);
+// resetCache(firstLine, lastLine - firstLine + 1);
+// doMouseLinkCursor();
+// }
+//}
+//void redrawLines(int startLine, int lineCount, boolean bottomChanged) {
+// // do nothing if redraw range is completely invisible
+// int endLine = startLine + lineCount - 1;
+// int partialBottomIndex = getPartialBottomIndex();
+// int partialTopIndex = getPartialTopIndex();
+// if (startLine > partialBottomIndex || endLine < partialTopIndex) {
+// return;
+// }
+// // only redraw visible lines
+// if (startLine < partialTopIndex) {
+// startLine = partialTopIndex;
+// }
+// if (endLine > partialBottomIndex) {
+// endLine = partialBottomIndex;
+// }
+// int redrawTop = getLinePixel(startLine);
+// int redrawBottom = getLinePixel(endLine + 1);
+// if (bottomChanged) redrawBottom = clientAreaHeight - bottomMargin;
+// int redrawWidth = clientAreaWidth - leftMargin - rightMargin;
+// super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true);
+//}
+//void redrawLinesBullet (int[] redrawLines) {
+// if (redrawLines == null) return;
+// int topIndex = getPartialTopIndex();
+// int bottomIndex = getPartialBottomIndex();
+// for (int redrawLine : redrawLines) {
+// int lineIndex = redrawLine;
+// if (!(topIndex <= lineIndex && lineIndex <= bottomIndex)) continue;
+// int width = -1;
+// Bullet bullet = renderer.getLineBullet(lineIndex, null);
+// if (bullet != null) {
+// StyleRange style = bullet.style;
+// GlyphMetrics metrics = style.metrics;
+// width = metrics.width;
+// }
+// if (width == -1) width = getClientArea().width;
+// int height = renderer.getLineHeight(lineIndex);
+// int y = getLinePixel(lineIndex);
+// super.redraw(0, y, width, height, false);
+// }
+//}
+//void redrawMargins(int oldHeight, int oldWidth) {
+// /* Redraw the old or new right/bottom margin if needed */
+// if (oldWidth != clientAreaWidth) {
+// if (rightMargin > 0) {
+// int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin;
+// super.redraw(x, 0, rightMargin, oldHeight, false);
+// }
+// }
+// if (oldHeight != clientAreaHeight) {
+// if (bottomMargin > 0) {
+// int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin;
+// super.redraw(0, y, oldWidth, bottomMargin, false);
+// }
+// }
+//}
+///**
+// * Redraws the specified text range.
+// *
+// * @param start offset of the first character to redraw
+// * @param length number of characters to redraw
+// * @param clearBackground true if the background should be cleared as
+// * part of the redraw operation. If true, the entire redraw range will
+// * be cleared before anything is redrawn. If the redraw range includes
+// * the last character of a line (i.e., the entire line is redrawn) the
+// * line is cleared all the way to the right border of the widget.
+// * The redraw operation will be faster and smoother if clearBackground
+// * is set to false. Whether or not the flag can be set to false depends
+// * on the type of change that has taken place. If font styles or
+// * background colors for the redraw range have changed, clearBackground
+// * should be set to true. If only foreground colors have changed for
+// * the redraw range, clearBackground can be set to false.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
+// *
+// */
+//public void redrawRange(int start, int length, boolean clearBackground) {
+// checkWidget();
+// int end = start + length;
+// int contentLength = content.getCharCount();
+// if (start > end || start < 0 || end > contentLength) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// int firstLine = content.getLineAtOffset(start);
+// int lastLine = content.getLineAtOffset(end);
+// resetCache(firstLine, lastLine - firstLine + 1);
+// internalRedrawRange(start, length);
+// doMouseLinkCursor();
+//}
+///**
+// * Removes the specified bidirectional segment listener.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// *
+// * @since 2.0
+// */
+//public void removeBidiSegmentListener(BidiSegmentListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// removeTypedListener(ST.LineGetSegments, listener);
+// resetCache(0, content.getLineCount());
+// setCaretLocations();
+// super.redraw();
+//}
+///**
+// * Removes the specified caret listener.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// *
+// * @since 3.5
+// */
+//public void removeCaretListener(CaretListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// removeTypedListener(ST.CaretMoved, listener);
+//}
+///**
+// * Removes the specified extended modify listener.
+// *
+// * @param extendedModifyListener the listener which should no longer be notified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) {
+// checkWidget();
+// if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// removeTypedListener(ST.ExtendedModify, extendedModifyListener);
+//}
+///**
+// * Removes the specified line background listener.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void removeLineBackgroundListener(LineBackgroundListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// removeTypedListener(ST.LineGetBackground, listener);
+//}
+///**
+// * Removes the specified line style listener.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void removeLineStyleListener(LineStyleListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// removeTypedListener(ST.LineGetStyle, listener);
+// setCaretLocations();
+//}
+///**
+// * Removes the specified modify listener.
+// *
+// * @param modifyListener the listener which should no longer be notified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void removeModifyListener(ModifyListener modifyListener) {
+// checkWidget();
+// if (modifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// removeTypedListener(SWT.Modify, modifyListener);
+//}
+///**
+// * Removes the specified listener.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// * @since 3.2
+// */
+//public void removePaintObjectListener(PaintObjectListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// removeTypedListener(ST.PaintObject, listener);
+//}
+///**
+// * Removes the listener from the collection of listeners who will
+// * be notified when the user changes the receiver's selection.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the listener is null
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see SelectionListener
+// * @see #addSelectionListener
+// */
+//public void removeSelectionListener(SelectionListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// removeTypedListener(SWT.Selection, listener);
+//}
+///**
+// * Removes the specified verify listener.
+// *
+// * @param verifyListener the listener which should no longer be notified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void removeVerifyListener(VerifyListener verifyListener) {
+// checkWidget();
+// if (verifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// removeTypedListener(SWT.Verify, verifyListener);
+//}
+///**
+// * Removes the specified key verify listener.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void removeVerifyKeyListener(VerifyKeyListener listener) {
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// removeTypedListener(ST.VerifyKey, listener);
+//}
+///**
+// * Removes the specified word movement listener.
+// *
+// * @param listener the listener which should no longer be notified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// *
+// * @see MovementEvent
+// * @see MovementListener
+// * @see #addWordMovementListener
+// *
+// * @since 3.3
+// */
+//
+//public void removeWordMovementListener(MovementListener listener) {
+// checkWidget();
+// if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// removeTypedListener(ST.WordNext, listener);
+// removeTypedListener(ST.WordPrevious, listener);
+//}
+///**
+// * Replaces the styles in the given range with new styles. This method
+// * effectively deletes the styles in the given range and then adds the
+// * the new styles.
+// *
+// * Note: Because a StyleRange includes the start and length, the
+// * same instance cannot occur multiple times in the array of styles.
+// * If the same style attributes, such as font and color, occur in
+// * multiple StyleRanges, setStyleRanges(int, int, int[], StyleRange[])
+// * can be used to share styles and reduce memory usage.
+// *
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// *
+// * @param start offset of first character where styles will be deleted
+// * @param length length of the range to delete styles in
+// * @param ranges StyleRange objects containing the new style information.
+// * The ranges should not overlap and should be within the specified start
+// * and length. The style rendering is undefined if the ranges do overlap
+// * or are ill-defined. Must not be null.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
+// *
ERROR_NULL_ARGUMENT when ranges is null
+// *
+// *
+// * @since 2.0
+// *
+// * @see #setStyleRanges(int, int, int[], StyleRange[])
+// */
+//public void replaceStyleRanges(int start, int length, StyleRange[] ranges) {
+// checkWidget();
+// if (isListening(ST.LineGetStyle)) return;
+// if (ranges == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// setStyleRanges(start, length, null, ranges, false);
+//}
+///**
+// * Replaces the given text range with new text.
+// * If the widget has the SWT.SINGLE style and "text" contains more than
+// * one line, only the first line is rendered but the text is stored
+// * unchanged. A subsequent call to getText will return the same text
+// * that was set. Note that only a single line of text should be set when
+// * the SWT.SINGLE style is used.
+// *
+// * NOTE: During the replace operation the current selection is
+// * changed as follows:
+// *
+// *
+// *
selection before replaced text: selection unchanged
+// *
selection after replaced text: adjust the selection so that same text
+// * remains selected
+// *
selection intersects replaced text: selection is cleared and caret
+// * is placed after inserted text
+// *
+// *
+// * @param start offset of first character to replace
+// * @param length number of characters to replace. Use 0 to insert text
+// * @param text new text. May be empty to delete text.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
+// *
ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter.
+// * Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported
+// *
ERROR_NULL_ARGUMENT when string is null
+// *
+// */
+//public void replaceTextRange(int start, int length, String text) {
+// checkWidget();
+// if (text == null) {
+// SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// }
+// int contentLength = getCharCount();
+// int end = start + length;
+// if (start > end || start < 0 || end > contentLength) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// Event event = new Event();
+// event.start = start;
+// event.end = end;
+// event.text = text;
+// modifyContent(event, false);
+//}
+///**
+// * Resets the caret position, selection and scroll offsets. Recalculate
+// * the content width and scroll bars. Redraw the widget.
+// */
+//void reset() {
+// ScrollBar verticalBar = getVerticalBar();
+// ScrollBar horizontalBar = getHorizontalBar();
+// setCaretOffsets(new int[] {0}, SWT.DEFAULT);
+// topIndex = 0;
+// topIndexY = 0;
+// verticalScrollOffset = 0;
+// horizontalScrollOffset = 0;
+// resetSelection();
+// renderer.setContent(content);
+// if (verticalBar != null) {
+// verticalBar.setSelection(0);
+// }
+// if (horizontalBar != null) {
+// horizontalBar.setSelection(0);
+// }
+// resetCache(0, 0);
+// setCaretLocations();
+// super.redraw();
+//}
+//void resetBidiData() {
+// caretDirection = SWT.NULL;
+// resetCache(0, content.getLineCount());
+// setCaretLocations();
+// keyActionMap.clear();
+// createKeyBindings();
+// super.redraw();
+//}
+//void resetCache(SortedSet lines) {
+// if (lines == null || lines.isEmpty()) return;
+// int maxLineIndex = renderer.maxWidthLineIndex;
+// renderer.reset(lines);
+// renderer.calculateClientArea();
+// if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) {
+// renderer.calculate(maxLineIndex, 1);
+// }
+// setScrollBars(true);
+// if (!isFixedLineHeight()) {
+// if (topIndex > lines.iterator().next()) {
+// verticalScrollOffset = -1;
+// }
+// renderer.calculateIdle();
+// }
+//}
+//void resetCache(int firstLine, int count) {
+// int maxLineIndex = renderer.maxWidthLineIndex;
+// renderer.reset(firstLine, count);
+// renderer.calculateClientArea();
+// if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) {
+// renderer.calculate(maxLineIndex, 1);
+// }
+// setScrollBars(true);
+// if (!isFixedLineHeight()) {
+// if (topIndex > firstLine) {
+// verticalScrollOffset = -1;
+// }
+// renderer.calculateIdle();
+// }
+//}
+///**
+// * Resets the selection.
+// */
+//void resetSelection() {
+// selection = Arrays.stream(caretOffsets).mapToObj(offset -> new Point(offset, offset)).toArray(Point[]::new);
+// selectionAnchors = Arrays.copyOf(caretOffsets, caretOffsets.length);
+// sendAccessibleTextCaretMoved();
+//}
+//
+//@Override
+//public void scroll(int destX, int destY, int x, int y, int width, int height, boolean all) {
+// super.scroll(destX, destY, x, y, width, height, false);
+// if (all) {
+// int deltaX = destX - x, deltaY = destY - y;
+// for (Control child : getChildren()) {
+// Rectangle rect = child.getBounds();
+// child.setLocation(rect.x + deltaX, rect.y + deltaY);
+// }
+// }
+//}
+//
+///**
+// * Scrolls the widget horizontally.
+// *
+// * @param pixels number of SWT logical points to scroll, > 0 = scroll left,
+// * < 0 scroll right
+// * @param adjustScrollBar
+// * true= the scroll thumb will be moved to reflect the new scroll offset.
+// * false = the scroll thumb will not be moved
+// * @return
+// * true=the widget was scrolled
+// * false=the widget was not scrolled, the given offset is not valid.
+// */
+//boolean scrollHorizontal(int pixels, boolean adjustScrollBar) {
+// if (pixels == 0) return false;
+// if (wordWrap) return false;
+// ScrollBar horizontalBar = getHorizontalBar();
+// if (horizontalBar != null && adjustScrollBar) {
+// horizontalBar.setSelection(horizontalScrollOffset + pixels);
+// }
+// int scrollHeight = clientAreaHeight - topMargin - bottomMargin;
+// if (pixels > 0) {
+// int sourceX = leftMargin + pixels;
+// int scrollWidth = clientAreaWidth - sourceX - rightMargin;
+// if (scrollWidth > 0) {
+// scroll(leftMargin, topMargin, sourceX, topMargin, scrollWidth, scrollHeight, true);
+// }
+// if (sourceX > scrollWidth) {
+// super.redraw(leftMargin + scrollWidth, topMargin, pixels - scrollWidth, scrollHeight, true);
+// }
+// } else {
+// int destinationX = leftMargin - pixels;
+// int scrollWidth = clientAreaWidth - destinationX - rightMargin;
+// if (scrollWidth > 0) {
+// scroll(destinationX, topMargin, leftMargin, topMargin, scrollWidth, scrollHeight, true);
+// }
+// if (destinationX > scrollWidth) {
+// super.redraw(leftMargin + scrollWidth, topMargin, -pixels - scrollWidth, scrollHeight, true);
+// }
+// }
+// horizontalScrollOffset += pixels;
+// setCaretLocations();
+// return true;
+//}
+///**
+// * Scrolls the widget vertically.
+// *
+// * @param pixel the new vertical scroll offset
+// * @param adjustScrollBar
+// * true= the scroll thumb will be moved to reflect the new scroll offset.
+// * false = the scroll thumb will not be moved
+// * @return
+// * true=the widget was scrolled
+// * false=the widget was not scrolled
+// */
+//boolean scrollVertical(int pixels, boolean adjustScrollBar) {
+// if (pixels == 0) {
+// return false;
+// }
+// if (verticalScrollOffset != -1) {
+// ScrollBar verticalBar = getVerticalBar();
+// if (verticalBar != null && adjustScrollBar) {
+// verticalBar.setSelection(verticalScrollOffset + pixels);
+// }
+// int deltaY = 0;
+// if (pixels > 0) {
+// int sourceY = topMargin + pixels;
+// int scrollHeight = clientAreaHeight - sourceY - bottomMargin;
+// if (scrollHeight > 0) {
+// deltaY = -pixels;
+// }
+// } else {
+// int destinationY = topMargin - pixels;
+// int scrollHeight = clientAreaHeight - destinationY - bottomMargin;
+// if (scrollHeight > 0) {
+// deltaY = -pixels;
+// }
+// }
+// Control[] children = getChildren();
+// for (Control child : children) {
+// Rectangle rect = child.getBounds();
+// child.setLocation(rect.x, rect.y + deltaY);
+// }
+// verticalScrollOffset += pixels;
+// calculateTopIndex(pixels);
+// super.redraw();
+// } else {
+// calculateTopIndex(pixels);
+// super.redraw();
+// }
+// setCaretLocations();
+// return true;
+//}
+//void scrollText(int srcY, int destY) {
+// if (srcY == destY) return;
+// int deltaY = destY - srcY;
+// int scrollWidth = clientAreaWidth - leftMargin - rightMargin, scrollHeight;
+// if (deltaY > 0) {
+// scrollHeight = clientAreaHeight - srcY - bottomMargin;
+// } else {
+// scrollHeight = clientAreaHeight - destY - bottomMargin;
+// }
+// scroll(leftMargin, destY, leftMargin, srcY, scrollWidth, scrollHeight, true);
+// if ((0 < srcY + scrollHeight) && (topMargin > srcY)) {
+// super.redraw(leftMargin, deltaY, scrollWidth, topMargin, false);
+// }
+// if ((0 < destY + scrollHeight) && (topMargin > destY)) {
+// super.redraw(leftMargin, 0, scrollWidth, topMargin, false);
+// }
+// if ((clientAreaHeight - bottomMargin < srcY + scrollHeight) && (clientAreaHeight > srcY)) {
+// super.redraw(leftMargin, clientAreaHeight - bottomMargin + deltaY, scrollWidth, bottomMargin, false);
+// }
+// if ((clientAreaHeight - bottomMargin < destY + scrollHeight) && (clientAreaHeight > destY)) {
+// super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false);
+// }
+//}
+//void sendAccessibleTextCaretMoved() {
+// if (Arrays.stream(caretOffsets).noneMatch(caretOffset -> caretOffset == accCaretOffset)) {
+// accCaretOffset = caretOffsets[0];
+// getAccessible().textCaretMoved(caretOffsets[0]);
+// }
+//}
+//void sendAccessibleTextChanged(int start, int newCharCount, int replaceCharCount) {
+// Accessible accessible = getAccessible();
+// if (replaceCharCount != 0) {
+// accessible.textChanged(ACC.TEXT_DELETE, start, replaceCharCount);
+// }
+// if (newCharCount != 0) {
+// accessible.textChanged(ACC.TEXT_INSERT, start, newCharCount);
+// }
+//}
+///**
+// * Selects all the text.
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public void selectAll() {
+// checkWidget();
+// if (blockSelection) {
+// renderer.calculate(0, content.getLineCount());
+// setScrollBars(false);
+// int verticalScrollOffset = getVerticalScrollOffset();
+// int left = leftMargin - horizontalScrollOffset;
+// int top = topMargin - verticalScrollOffset;
+// int right = renderer.getWidth() - rightMargin - horizontalScrollOffset;
+// int bottom = renderer.getHeight() - bottomMargin - verticalScrollOffset;
+// setBlockSelectionLocation(left, top, right, bottom, false);
+// return;
+// }
+// setSelection(0, Math.max(getCharCount(),0));
+//}
+///**
+// * Replaces/inserts text as defined by the event.
+// *
+// * @param event the text change event.
+// *
+// *
event.start - the replace start offset
+// *
event.end - the replace end offset
+// *
event.text - the new text
+// *
+// */
+//void sendKeyEvent(Event event) {
+// if (editable) {
+// modifyContent(event, true);
+// }
+//}
+///**
+// * Returns a StyledTextEvent that can be used to request data such
+// * as styles and background color for a line.
+// *
+// * The specified line may be a visual (wrapped) line if in word
+// * wrap mode. The returned object will always be for a logical
+// * (unwrapped) line.
+// *
+// *
+// * @param lineOffset offset of the line. This may be the offset of
+// * a visual line if the widget is in word wrap mode.
+// * @param line line text. This may be the text of a visual line if
+// * the widget is in word wrap mode.
+// * @return StyledTextEvent that can be used to request line data
+// * for the given line.
+// */
+//StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) {
+// StyledTextEvent event = null;
+// if (isListening(eventType)) {
+// event = new StyledTextEvent(content);
+// event.detail = lineOffset;
+// event.text = line;
+// event.alignment = alignment;
+// event.indent = indent;
+// event.wrapIndent = wrapIndent;
+// event.justify = justify;
+// notifyListeners(eventType, event);
+// }
+// return event;
+//}
+///**
+// * Sends the specified selection event.
+// */
+//void sendSelectionEvent() {
+// getAccessible().textSelectionChanged();
+// Event event = new Event();
+// event.x = selection[0].x;
+// event.y = selection[selection.length - 1].y;
+// notifyListeners(SWT.Selection, event);
+//}
+//int sendTextEvent(int left, int right, int lineIndex, String text, boolean fillWithSpaces) {
+// int lineWidth = 0, start, end;
+// StringBuilder buffer = new StringBuilder();
+// if (lineIndex < content.getLineCount()) {
+// int[] trailing = new int[1];
+// start = getOffsetAtPoint(left, getLinePixel(lineIndex), trailing, true);
+// if (start == -1) {
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// int lineLegth = content.getLine(lineIndex).length();
+// start = end = lineOffset + lineLegth;
+// if (fillWithSpaces) {
+// TextLayout layout = renderer.getTextLayout(lineIndex);
+// lineWidth = layout.getBounds().width;
+// renderer.disposeTextLayout(layout);
+// }
+// } else {
+// start += trailing[0];
+// end = left == right ? start : getOffsetAtPoint(right, 0, lineIndex, null);
+// fillWithSpaces = false;
+// }
+// } else {
+// start = end = content.getCharCount();
+// buffer.append(content.getLineDelimiter());
+// }
+// if (start > end) {
+// int temp = start;
+// start = end;
+// end = temp;
+// }
+// if (fillWithSpaces) {
+// int spacesWidth = left - lineWidth + horizontalScrollOffset - leftMargin;
+// int spacesCount = spacesWidth / renderer.averageCharWidth;
+// for (int i = 0; i < spacesCount; i++) {
+// buffer.append(' ');
+// }
+// }
+// buffer.append(text);
+// Event event = new Event();
+// event.start = start;
+// event.end = end;
+// event.text = buffer.toString();
+// sendKeyEvent(event);
+// return event.start + event.text.length();
+//}
+//int sendWordBoundaryEvent(int eventType, int movement, int offset, int newOffset, String lineText, int lineOffset) {
+// if (isListening(eventType)) {
+// StyledTextEvent event = new StyledTextEvent(content);
+// event.detail = lineOffset;
+// event.text = lineText;
+// event.count = movement;
+// event.start = offset;
+// event.end = newOffset;
+// notifyListeners(eventType, event);
+// offset = event.end;
+// if (offset != newOffset) {
+// int length = getCharCount();
+// if (offset < 0) {
+// offset = 0;
+// } else if (offset > length) {
+// offset = length;
+// } else {
+// if (isLineDelimiter(offset)) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// }
+// }
+// return offset;
+// }
+// return newOffset;
+//}
+//void setAlignment() {
+// if ((getStyle() & SWT.SINGLE) == 0) return;
+// int alignment = renderer.getLineAlignment(0, this.alignment);
+// int newAlignmentMargin = 0;
+// if (alignment != SWT.LEFT) {
+// renderer.calculate(0, 1);
+// int width = renderer.getWidth() - alignmentMargin;
+// newAlignmentMargin = clientAreaWidth - width;
+// if (newAlignmentMargin < 0) newAlignmentMargin = 0;
+// if (alignment == SWT.CENTER) newAlignmentMargin /= 2;
+// }
+// if (alignmentMargin != newAlignmentMargin) {
+// leftMargin -= alignmentMargin;
+// leftMargin += newAlignmentMargin;
+// alignmentMargin = newAlignmentMargin;
+// resetCache(0, 1);
+// setCaretLocations();
+// super.redraw();
+// }
+//}
+///**
+// * Sets the alignment of the widget. The argument should be one of SWT.LEFT,
+// * SWT.CENTER or SWT.RIGHT. The alignment applies for all lines.
+// *
+// * Note that if SWT.MULTI is set, then SWT.WRAP must also be set
+// * in order to stabilize the right edge before setting alignment.
+// *
+// *
+// * @param alignment the new alignment
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see #setLineAlignment(int, int, int)
+// *
+// * @since 3.2
+// */
+//public void setAlignment(int alignment) {
+// checkWidget();
+// alignment &= (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+// if (alignment == 0 || this.alignment == alignment) return;
+// this.alignment = alignment;
+// resetCache(0, content.getLineCount());
+// setCaretLocations();
+// setAlignment();
+// super.redraw();
+//}
+///**
+// * Set the Always Show Scrollbars flag. True if the scrollbars are
+// * always shown even if they are not required (default value). False if the scrollbars are only
+// * visible when some part of the content needs to be scrolled to be seen.
+// * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the
+// * horizontal and vertical directions.
+// *
+// * @param show true to show the scrollbars even when not required, false to show scrollbars only when required
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.8
+// */
+//public void setAlwaysShowScrollBars(boolean show) {
+// checkWidget();
+// if (show == alwaysShowScroll) return;
+// alwaysShowScroll = show;
+// setScrollBars(true);
+//}
+///**
+// * @see Control#setBackground(Color)
+// */
+//@Override
+//public void setBackground(Color color) {
+// checkWidget();
+// boolean backgroundDisabled = false;
+// if (!this.enabled && color == null) {
+// if (background != null) {
+// Color disabledBg = getDisplay().getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND);
+// if (background.equals(disabledBg)) {
+// return;
+// } else {
+// color = new Color (disabledBg.getRGBA());
+// backgroundDisabled = true;
+// }
+// }
+// }
+// customBackground = color != null && !this.insideSetEnableCall && !backgroundDisabled;
+// background = color;
+// super.setBackground(color);
+// resetCache(0, content.getLineCount());
+// setCaretLocations();
+// super.redraw();
+//}
+///**
+// * Sets the block selection mode.
+// *
+// * @param blockSelection true=enable block selection, false=disable block selection
+// *
+// * @since 3.5
+// */
+//public void setBlockSelection(boolean blockSelection) {
+// checkWidget();
+// if ((getStyle() & SWT.SINGLE) != 0) return;
+// if (blockSelection == this.blockSelection) return;
+// if (wordWrap) return;
+// this.blockSelection = blockSelection;
+// if (cursor == null) {
+// Display display = getDisplay();
+// int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM;
+// super.setCursor(display.getSystemCursor(type));
+// }
+// if (blockSelection) {
+// int start = selection[0].x;
+// int end = selection[0].y;
+// if (start != end) {
+// setBlockSelectionOffset(start, end, false);
+// }
+// } else {
+// clearBlockSelection(false, false);
+// }
+//}
+///**
+// * Sets the block selection bounds. The bounds is
+// * relative to the upper left corner of the document.
+// *
+// * @param rect the new bounds for the block selection
+// *
+// * @see #setBlockSelectionBounds(int, int, int, int)
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when point is null
+// *
+// *
+// * @since 3.5
+// */
+//public void setBlockSelectionBounds(Rectangle rect) {
+// checkWidget();
+// if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// setBlockSelectionBounds(rect.x, rect.y, rect.width, rect.height);
+//}
+///**
+// * Sets the block selection bounds. The bounds is
+// * relative to the upper left corner of the document.
+// *
+// * @param x the new x coordinate for the block selection
+// * @param y the new y coordinate for the block selection
+// * @param width the new width for the block selection
+// * @param height the new height for the block selection
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public void setBlockSelectionBounds(int x, int y, int width, int height) {
+// checkWidget();
+// int verticalScrollOffset = getVerticalScrollOffset();
+// if (!blockSelection) {
+// x -= horizontalScrollOffset;
+// y -= verticalScrollOffset;
+// int start = getOffsetAtPoint(x, y, null);
+// int end = getOffsetAtPoint(x+width-1, y+height-1, null);
+// setSelection(new int[] {start, end - start}, false, false);
+// setCaretLocations();
+// return;
+// }
+// int minY = topMargin;
+// int minX = leftMargin;
+// int maxY = renderer.getHeight() - bottomMargin;
+// int maxX = Math.max(clientAreaWidth, renderer.getWidth()) - rightMargin;
+// int anchorX = Math.max(minX, Math.min(maxX, x)) - horizontalScrollOffset;
+// int anchorY = Math.max(minY, Math.min(maxY, y)) - verticalScrollOffset;
+// int locationX = Math.max(minX, Math.min(maxX, x + width)) - horizontalScrollOffset;
+// int locationY = Math.max(minY, Math.min(maxY, y + height - 1)) - verticalScrollOffset;
+// if (isFixedLineHeight() && renderer.fixedPitch) {
+// int avg = renderer.averageCharWidth;
+// anchorX = ((anchorX - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
+// locationX = ((locationX + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
+// }
+// setBlockSelectionLocation(anchorX, anchorY, locationX, locationY, false);
+//}
+//void setBlockSelectionLocation (int x, int y, boolean sendEvent) {
+// int verticalScrollOffset = getVerticalScrollOffset();
+// blockXLocation = x + horizontalScrollOffset;
+// blockYLocation = y + verticalScrollOffset;
+// int[] alignment = new int[1];
+// int offset = getOffsetAtPoint(x, y, alignment);
+// setCaretOffsets(new int[] {offset}, alignment[0]);
+// if (blockXAnchor == -1) {
+// blockXAnchor = blockXLocation;
+// blockYAnchor = blockYLocation;
+// selectionAnchors[0] = caretOffsets[0];
+// }
+// doBlockSelection(sendEvent);
+//}
+//void setBlockSelectionLocation (int anchorX, int anchorY, int x, int y, boolean sendEvent) {
+// int verticalScrollOffset = getVerticalScrollOffset();
+// blockXAnchor = anchorX + horizontalScrollOffset;
+// blockYAnchor = anchorY + verticalScrollOffset;
+// selectionAnchors[0] = getOffsetAtPoint(anchorX, anchorY, null);
+// setBlockSelectionLocation(x, y, sendEvent);
+//}
+//void setBlockSelectionOffset (int offset, boolean sendEvent) {
+// Point point = getPointAtOffset(offset);
+// int verticalScrollOffset = getVerticalScrollOffset();
+// blockXLocation = point.x + horizontalScrollOffset;
+// blockYLocation = point.y + verticalScrollOffset;
+// setCaretOffsets(new int[] {offset}, SWT.DEFAULT);
+// if (blockXAnchor == -1) {
+// blockXAnchor = blockXLocation;
+// blockYAnchor = blockYLocation;
+// selectionAnchors[0] = caretOffsets[0];
+// }
+// doBlockSelection(sendEvent);
+//}
+//void setBlockSelectionOffset (int anchorOffset, int offset, boolean sendEvent) {
+// int verticalScrollOffset = getVerticalScrollOffset();
+// Point anchorPoint = getPointAtOffset(anchorOffset);
+// blockXAnchor = anchorPoint.x + horizontalScrollOffset;
+// blockYAnchor = anchorPoint.y + verticalScrollOffset;
+// selectionAnchors[0] = anchorOffset;
+// setBlockSelectionOffset(offset, sendEvent);
+//}
+//
+///**
+// * Sets the receiver's caret. Set the caret's height and location.
+// *
+// * @param caret the new caret for the receiver
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//@Override
+//public void setCaret(Caret caret) {
+// checkWidget ();
+// super.setCaret(caret);
+// caretDirection = SWT.NULL;
+// if (caret != null) {
+// setCaretLocations();
+// if(carets != null) {
+// for (int i = 1; i < carets.length; i++) {
+// carets[i].dispose();
+// }
+// }
+// carets = new Caret[] {caret};
+// } else {
+// carets = null;
+// }
+//}
+///**
+// * Sets the BIDI coloring mode. When true the BIDI text display
+// * algorithm is applied to segments of text that are the same
+// * color.
+// *
+// * @param mode the new coloring mode
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public void setBottomMargin (int bottomMargin) {
+// checkWidget();
+// setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin);
+//}
+///**
+// * Moves the Caret to the current caret offset.
+// */
+//void setCaretLocations() {
+// Point[] newCaretPos = Arrays.stream(caretOffsets).mapToObj(this::getPointAtOffset).toArray(Point[]::new);
+// setCaretLocations(newCaretPos, getCaretDirection());
+//}
+//void setCaretLocations(final Point[] locations, int direction) {
+// Caret firstCaret = getCaret();
+// if (firstCaret != null) {
+// if (carets == null || carets.length == 0) {
+// carets = new Caret[] { firstCaret };
+// }
+// final boolean isDefaultCaret = firstCaret == defaultCaret;
+// if (locations.length > carets.length) {
+// int formerCaretCount = carets.length;
+// carets = Arrays.copyOf(carets, locations.length);
+// for (int i = formerCaretCount; i < carets.length; i++) {
+// carets[i] = new Caret(this, firstCaret.getStyle());
+// carets[i].setImage(firstCaret.getImage());
+// carets[i].setFont(firstCaret.getFont());
+// carets[i].setSize(firstCaret.getSize());
+// }
+// } else if (locations.length < carets.length) {
+// for (int i = locations.length; i < carets.length; i++) {
+// carets[i].dispose();
+// }
+// carets = Arrays.copyOf(carets, locations.length);
+// }
+// for (int i = Math.min(caretOffsets.length, locations.length)-1; i>=0; i--) { // reverse order, seee bug 579028#c7
+// final Caret caret = carets[i];
+// final int caretOffset = caretOffsets[i];
+// final Point location = locations[i];
+// final StyleRange styleAtOffset = content.getCharCount() > 0 ?
+// (caretOffset < content.getCharCount() ?
+// getStyleRangeAtOffset(caretOffset) :
+// getStyleRangeAtOffset(content.getCharCount() - 1)) : // caret after last char: use last char style
+// null;
+// final int caretLine = content.getLineAtOffset(caretOffset);
+//
+// int graphicalLineHeight = getLineHeight();
+// final int lineStartOffset = getOffsetAtLine(caretLine);
+// int graphicalLineFirstOffset = lineStartOffset;
+// final int lineEndOffset = lineStartOffset + getLine(caretLine).length();
+// int graphicalLineLastOffset = lineEndOffset;
+// if (caretLine < getLineCount() && renderer.getLineHeight(caretLine) != getLineHeight()) { // word wrap, metrics, styles...
+// graphicalLineHeight = getLineHeight(caretOffset);
+// final Rectangle characterBounds = getBoundsAtOffset(caretOffset);
+// graphicalLineFirstOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y));
+// graphicalLineLastOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y + graphicalLineHeight)) - 1;
+// if (graphicalLineLastOffset < graphicalLineFirstOffset) {
+// graphicalLineLastOffset = getCharCount();
+// }
+// }
+//
+// int caretHeight = getLineHeight();
+// boolean isTextAlignedAtBottom = true;
+// if (graphicalLineFirstOffset >= 0) {
+// for (StyleRange style : getStyleRanges(graphicalLineFirstOffset, graphicalLineLastOffset - graphicalLineFirstOffset)) {
+// isTextAlignedAtBottom &= (
+// (style.font == null || Objects.equals(style.font, getFont())) &&
+// style.rise >= 0 &&
+// (style.metrics == null || style.metrics.descent <= 0)
+// );
+// }
+// }
+// if (!isTextAlignedAtBottom || (styleAtOffset != null && styleAtOffset.isVariableHeight())) {
+// if (isDefaultCaret) {
+// direction = SWT.DEFAULT;
+// caretHeight = graphicalLineHeight;
+// } else {
+// caretHeight = caret.getSize().y;
+// }
+// }
+// if (isTextAlignedAtBottom && caretHeight < graphicalLineHeight) {
+// location.y += (graphicalLineHeight - caretHeight);
+// }
+//
+// int imageDirection = direction;
+// if (isMirrored()) {
+// if (imageDirection == SWT.LEFT) {
+// imageDirection = SWT.RIGHT;
+// } else if (imageDirection == SWT.RIGHT) {
+// imageDirection = SWT.LEFT;
+// }
+// }
+// if (isDefaultCaret && imageDirection == SWT.RIGHT) {
+// location.x -= (caret.getSize().x - 1);
+// }
+// if (isDefaultCaret) {
+// caret.setBounds(location.x, location.y, caretWidth, caretHeight);
+// } else {
+// caret.setLocation(location);
+// }
+// if (direction != caretDirection) {
+// caretDirection = direction;
+// if (isDefaultCaret) {
+// if (imageDirection == SWT.DEFAULT) {
+// defaultCaret.setImage(null);
+// } else if (imageDirection == SWT.LEFT) {
+// defaultCaret.setImage(leftCaretBitmap);
+// } else if (imageDirection == SWT.RIGHT) {
+// defaultCaret.setImage(rightCaretBitmap);
+// }
+// }
+// if (caretDirection == SWT.LEFT) {
+// BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_NON_BIDI);
+// } else if (caretDirection == SWT.RIGHT) {
+// BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI);
+// }
+// }
+// }
+// updateCaretVisibility();
+// super.redraw();
+// }
+// columnX = locations[0].x;
+//}
+///**
+// * Sets the caret offset.
+// *
+// * @param offset caret offset, relative to the first character in the text.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the offset is inside a multi byte line
+// * delimiter (and thus neither clearly in front of or after the line delimiter)
+// *
+// */
+//public void setCaretOffset(int offset) {
+// checkWidget();
+// int length = getCharCount();
+// if (length > 0 && !Arrays.equals(caretOffsets, new int[] {offset})) {
+// if (offset < 0) {
+// offset = 0;
+// } else if (offset > length) {
+// offset = length;
+// } else {
+// if (isLineDelimiter(offset)) {
+// // offset is inside a multi byte line delimiter. This is an
+// // illegal operation and an exception is thrown. Fixes 1GDKK3R
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// }
+// setCaretOffsets(new int[] {offset}, PREVIOUS_OFFSET_TRAILING);
+// // clear the selection if the caret is moved.
+// // don't notify listeners about the selection change.
+// if (blockSelection) {
+// clearBlockSelection(true, false);
+// } else {
+// clearSelection(false);
+// }
+// }
+// setCaretLocations();
+//}
+//void setCaretOffsets(int[] newOffsets, int alignment) {
+// if (newOffsets.length > 1) {
+// newOffsets = Arrays.stream(newOffsets).distinct().sorted().toArray();
+// }
+// if (!Arrays.equals(caretOffsets, newOffsets)) {
+// caretOffsets = newOffsets;
+// if (isListening(ST.CaretMoved)) {
+// StyledTextEvent event = new StyledTextEvent(content);
+// event.end = caretOffsets[caretOffsets.length - 1];
+// notifyListeners(ST.CaretMoved, event);
+// }
+// }
+// if (alignment != SWT.DEFAULT) {
+// caretAlignment = alignment;
+// }
+//}
+///**
+// * Copies the specified text range to the clipboard. The text will be placed
+// * in the clipboard in plain text, HTML, and RTF formats.
+// *
+// * @param start start index of the text
+// * @param length length of text to place in clipboard
+// *
+// * @exception SWTError
+// * @see org.eclipse.swt.dnd.Clipboard#setContents
+// */
+//void setClipboardContent(int start, int length, int clipboardType) throws SWTError {
+// if (clipboardType == DND.SELECTION_CLIPBOARD && !IS_GTK) return;
+// TextTransfer plainTextTransfer = TextTransfer.getInstance();
+// TextWriter plainTextWriter = new TextWriter(start, length);
+// String plainText = getPlatformDelimitedText(plainTextWriter);
+// Object[] data;
+// Transfer[] types;
+// if (clipboardType == DND.SELECTION_CLIPBOARD) {
+// data = new Object[]{plainText};
+// types = new Transfer[]{plainTextTransfer};
+// } else {
+// try {
+// RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+// RTFWriter rtfWriter = new RTFWriter(this, start, length);
+// String rtfText = getPlatformDelimitedText(rtfWriter);
+//
+// HTMLTransfer htmlTransfer = HTMLTransfer.getInstance();
+// HTMLWriter htmlWriter = new HTMLWriter(this, start, length, content);
+// String htmlText = getPlatformDelimitedText(htmlWriter);
+// htmlText = "" +htmlText; //cause extra memory pressure to fail fast instead of failing in HTMLTransfer.javaToNative()
+// data = new Object[]{rtfText, htmlText, plainText};
+// types = new Transfer[]{rtfTransfer, htmlTransfer, plainTextTransfer};
+// } catch (OutOfMemoryError oome) {
+// // Adding RTF and HTML text may increase size by factor > 15
+// // fall back: copy plain text
+// data = new Object[] { plainText };
+// types = new Transfer[] { plainTextTransfer };
+// clipboard.setContents(data, types, clipboardType);
+// OutOfMemoryError customOome = new OutOfMemoryError(
+// "Out of Memory: Copied only plain text (" + plainText.lines().count() + " lines).");
+// customOome.initCause(oome);
+// // Still throw as it is likely that other threads silently failed too, but at least copied text is not lost
+// throw customOome;
+// }
+// }
+// clipboard.setContents(data, types, clipboardType);
+//}
+///**
+// * Sets the content implementation to use for text storage.
+// *
+// * @param newContent StyledTextContent implementation to use for text storage.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when listener is null
+// *
+// */
+//public void setContent(StyledTextContent newContent) {
+// checkWidget();
+// if (newContent == null) {
+// SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// }
+// if (content != null) {
+// content.removeTextChangeListener(textChangeListener);
+// }
+// content = newContent;
+// content.addTextChangeListener(textChangeListener);
+// reset();
+//}
+///**
+// * Sets the receiver's cursor to the cursor specified by the
+// * argument. Overridden to handle the null case since the
+// * StyledText widget uses an ibeam as its default cursor.
+// *
+// * @see Control#setCursor(Cursor)
+// */
+//@Override
+//public void setCursor (Cursor cursor) {
+// checkWidget();
+// if (cursor != null && cursor.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// this.cursor = cursor;
+// if (cursor == null) {
+// Display display = getDisplay();
+// int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM;
+// super.setCursor(display.getSystemCursor(type));
+// } else {
+// super.setCursor(cursor);
+// }
+//}
+///**
+// * Sets whether the widget implements double click mouse behavior.
+// *
+// * @param enable if true double clicking a word selects the word, if false
+// * double clicks have the same effect as regular mouse clicks.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public void setDoubleClickEnabled(boolean enable) {
+// checkWidget();
+// doubleClickEnabled = enable;
+//}
+//@Override
+//public void setDragDetect (boolean dragDetect) {
+// checkWidget ();
+// this.dragDetect = dragDetect;
+//}
+///**
+// * Sets whether the widget content can be edited.
+// *
+// * @param editable if true content can be edited, if false content can not be
+// * edited
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// * NOTE: Italic fonts are not supported unless they have no overhang
+// * and the same baseline as regular fonts.
+// *
+// *
+// * @param font new font
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//@Override
+//public void setFont(Font font) {
+// checkWidget();
+// int oldLineHeight = renderer.getLineHeight();
+// super.setFont(font);
+// renderer.setFont(getFont(), tabLength);
+// // keep the same top line visible. fixes 5815
+// if (isFixedLineHeight()) {
+// int lineHeight = renderer.getLineHeight();
+// if (lineHeight != oldLineHeight) {
+// int vscroll = (getVerticalScrollOffset() * lineHeight / oldLineHeight) - getVerticalScrollOffset();
+// scrollVertical(vscroll, true);
+// }
+// }
+// resetCache(0, content.getLineCount());
+// claimBottomFreeSpace();
+// calculateScrollBars();
+// if (isBidiCaret()) createCaretBitmaps();
+// caretDirection = SWT.NULL;
+// setCaretLocations();
+// super.redraw();
+//}
+//@Override
+//public void setForeground(Color color) {
+// checkWidget();
+// boolean foregroundDisabled = false;
+// if (!this.enabled && color == null) {
+// if (foreground != null) {
+// Color disabledFg = getDisplay().getSystemColor(SWT.COLOR_WIDGET_DISABLED_FOREGROUND);
+// if (foreground.equals(disabledFg)) {
+// return;
+// } else {
+// color = new Color (disabledFg.getRGBA());
+// foregroundDisabled = true;
+// }
+// }
+// }
+// customForeground = color != null && !this.insideSetEnableCall && !foregroundDisabled;
+// foreground = color;
+// super.setForeground(color);
+// resetCache(0, content.getLineCount());
+// setCaretLocations();
+// super.redraw();
+//}
+///**
+// * Sets the horizontal scroll offset relative to the start of the line.
+// * Do nothing if there is no text set.
+// *
+// * NOTE: The horizontal index is reset to 0 when new text is set in the
+// * widget.
+// *
+// *
+// * @param offset horizontal scroll offset relative to the start
+// * of the line, measured in character increments starting at 0, if
+// * equal to 0 the content is not scrolled, if > 0 = the content is scrolled.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public void setHorizontalIndex(int offset) {
+// checkWidget();
+// if (getCharCount() == 0) {
+// return;
+// }
+// if (offset < 0) {
+// offset = 0;
+// }
+// offset *= getHorizontalIncrement();
+// // allow any value if client area width is unknown or 0.
+// // offset will be checked in resize handler.
+// // don't use isVisible since width is known even if widget
+// // is temporarily invisible
+// if (clientAreaWidth > 0) {
+// int width = renderer.getWidth();
+// // prevent scrolling if the content fits in the client area.
+// // align end of longest line with right border of client area
+// // if offset is out of range.
+// if (offset > width - clientAreaWidth) {
+// offset = Math.max(0, width - clientAreaWidth);
+// }
+// }
+// scrollHorizontal(offset - horizontalScrollOffset, true);
+//}
+///**
+// * Sets the horizontal SWT logical point offset relative to the start of the line.
+// * Do nothing if there is no text set.
+// *
+// * NOTE: The horizontal SWT logical point offset is reset to 0 when new text
+// * is set in the widget.
+// *
+// *
+// * @param pixel horizontal SWT logical point offset relative to the start
+// * of the line.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @since 2.0
+// */
+//public void setHorizontalPixel(int pixel) {
+// checkWidget();
+// if (getCharCount() == 0) {
+// return;
+// }
+// if (pixel < 0) {
+// pixel = 0;
+// }
+// // allow any value if client area width is unknown or 0.
+// // offset will be checked in resize handler.
+// // don't use isVisible since width is known even if widget
+// // is temporarily invisible
+// if (clientAreaWidth > 0) {
+// int width = renderer.getWidth();
+// // prevent scrolling if the content fits in the client area.
+// // align end of longest line with right border of client area
+// // if offset is out of range.
+// if (pixel > width - clientAreaWidth) {
+// pixel = Math.max(0, width - clientAreaWidth);
+// }
+// }
+// scrollHorizontal(pixel - horizontalScrollOffset, true);
+//}
+///**
+// * Sets the line indentation of the widget.
+// *
+// * It is the amount of blank space, in points, at the beginning of each line.
+// * When a line wraps in several lines only the first one is indented.
+// *
+// *
+// * @param indent the new indent
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// * One action can be associated with N keys. However, each key can only
+// * have one action (key:action is N:1 relation).
+// *
+// *
+// * @param key a key code defined in SWT.java or a character.
+// * Optionally ORd with a state mask. Preferred state masks are one or more of
+// * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform
+// * differences. However, there may be cases where using the specific state masks
+// * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
+// * @param action one of the predefined actions defined in ST.java.
+// * Use SWT.NULL to remove a key binding.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public void setKeyBinding(int key, int action) {
+// checkWidget();
+// int modifierValue = key & SWT.MODIFIER_MASK;
+// int keyInt = key & SWT.KEY_MASK;
+// char keyChar = (char)keyInt;
+// /**
+// * Bug 440535: Make sure the key getting mapped to letter is in defiened
+// * character range and filter out incorrect int to char typecasting. For
+// * Example: SWT.KEYPAD_CR int gets wrongly type-cast to char letter 'p'
+// */
+// if (Character.isDefined(keyInt) && Character.isLetter(keyChar)) {
+// // make the keybinding case insensitive by adding it
+// // in its upper and lower case form
+// char ch = Character.toUpperCase(keyChar);
+// int newKey = ch | modifierValue;
+// if (action == SWT.NULL) {
+// keyActionMap.remove(newKey);
+// } else {
+// keyActionMap.put(newKey, action);
+// }
+// ch = Character.toLowerCase(keyChar);
+// newKey = ch | modifierValue;
+// if (action == SWT.NULL) {
+// keyActionMap.remove(newKey);
+// } else {
+// keyActionMap.put(newKey, action);
+// }
+// } else {
+// if (action == SWT.NULL) {
+// keyActionMap.remove(key);
+// } else {
+// keyActionMap.put(key, action);
+// }
+// }
+//}
+///**
+// * Sets the left margin.
+// *
+// * @param leftMargin the left margin.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public void setLeftMargin (int leftMargin) {
+// checkWidget();
+// setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
+//}
+///**
+// * Sets the alignment of the specified lines. The argument should be one of SWT.LEFT,
+// * SWT.CENTER or SWT.RIGHT.
+// *
+// * Note that if SWT.MULTI is set, then SWT.WRAP must also be set
+// * in order to stabilize the right edge before setting alignment.
+// *
+// * Should not be called if a LineStyleListener has been set since the listener
+// * maintains the line attributes.
+// *
+// * All line attributes are maintained relative to the line text, not the
+// * line index that is specified in this method call.
+// * During text changes, when entire lines are inserted or removed, the line
+// * attributes that are associated with the lines after the change
+// * will "move" with their respective text. An entire line is defined as
+// * extending from the first character on a line to the last and including the
+// * line delimiter.
+// *
+// * When two lines are joined by deleting a line delimiter, the top line
+// * attributes take precedence and the attributes of the bottom line are deleted.
+// * For all other text changes line attributes will remain unchanged.
+// *
+// * @param startLine first line the alignment is applied to, 0 based
+// * @param lineCount number of lines the alignment applies to.
+// * @param alignment line alignment
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+// *
+// * @see #setAlignment(int)
+// * @since 3.2
+// */
+//public void setLineAlignment(int startLine, int lineCount, int alignment) {
+// checkWidget();
+// if (isListening(ST.LineGetStyle)) return;
+// if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+//
+// renderer.setLineAlignment(startLine, lineCount, alignment);
+// resetCache(startLine, lineCount);
+// redrawLines(startLine, lineCount, false);
+// if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) {
+// setCaretLocations();
+// }
+// setAlignment();
+//}
+///**
+// * Sets the background color of the specified lines.
+// *
+// * The background color is drawn for the width of the widget. All
+// * line background colors are discarded when setText is called.
+// * The text background color if defined in a StyleRange overlays the
+// * line background color.
+// *
+// * Should not be called if a LineBackgroundListener has been set since the
+// * listener maintains the line backgrounds.
+// *
+// * All line attributes are maintained relative to the line text, not the
+// * line index that is specified in this method call.
+// * During text changes, when entire lines are inserted or removed, the line
+// * attributes that are associated with the lines after the change
+// * will "move" with their respective text. An entire line is defined as
+// * extending from the first character on a line to the last and including the
+// * line delimiter.
+// *
+// * When two lines are joined by deleting a line delimiter, the top line
+// * attributes take precedence and the attributes of the bottom line are deleted.
+// * For all other text changes line attributes will remain unchanged.
+// *
+// *
+// * @param startLine first line the color is applied to, 0 based
+// * @param lineCount number of lines the color applies to.
+// * @param background line background color
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+// *
+// */
+//public void setLineBackground(int startLine, int lineCount, Color background) {
+// checkWidget();
+// if (isListening(ST.LineGetBackground)) return;
+// if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// if (background != null) {
+// renderer.setLineBackground(startLine, lineCount, background);
+// } else {
+// renderer.clearLineBackground(startLine, lineCount);
+// }
+// redrawLines(startLine, lineCount, false);
+//}
+///**
+// * Sets the bullet of the specified lines.
+// *
+// * Should not be called if a LineStyleListener has been set since the listener
+// * maintains the line attributes.
+// *
+// * All line attributes are maintained relative to the line text, not the
+// * line index that is specified in this method call.
+// * During text changes, when entire lines are inserted or removed, the line
+// * attributes that are associated with the lines after the change
+// * will "move" with their respective text. An entire line is defined as
+// * extending from the first character on a line to the last and including the
+// * line delimiter.
+// *
+// * When two lines are joined by deleting a line delimiter, the top line
+// * attributes take precedence and the attributes of the bottom line are deleted.
+// * For all other text changes line attributes will remain unchanged.
+// *
+// *
+// * @param startLine first line the bullet is applied to, 0 based
+// * @param lineCount number of lines the bullet applies to.
+// * @param bullet line bullet
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+// *
+// * @since 3.2
+// */
+//public void setLineBullet(int startLine, int lineCount, Bullet bullet) {
+// checkWidget();
+// if (isListening(ST.LineGetStyle)) return;
+// if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// int oldBottom = getLinePixel(startLine + lineCount);
+// renderer.setLineBullet(startLine, lineCount, bullet);
+// resetCache(startLine, lineCount);
+// int newBottom = getLinePixel(startLine + lineCount);
+// redrawLines(startLine, lineCount, oldBottom != newBottom);
+// if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) {
+// setCaretLocations();
+// }
+//}
+///**
+// * Returns true if StyledText is in word wrap mode and false otherwise.
+// *
+// * @return true if StyledText is in word wrap mode and false otherwise.
+// */
+//boolean isWordWrap() {
+// return wordWrap || visualWrap;
+//}
+///**
+// * Sets the indent of the specified lines.
+// *
+// * Should not be called if a LineStyleListener has been set since the listener
+// * maintains the line attributes.
+// *
+// * All line attributes are maintained relative to the line text, not the
+// * line index that is specified in this method call.
+// * During text changes, when entire lines are inserted or removed, the line
+// * attributes that are associated with the lines after the change
+// * will "move" with their respective text. An entire line is defined as
+// * extending from the first character on a line to the last and including the
+// * line delimiter.
+// *
+// * When two lines are joined by deleting a line delimiter, the top line
+// * attributes take precedence and the attributes of the bottom line are deleted.
+// * For all other text changes line attributes will remain unchanged.
+// *
+// *
+// * @param startLine first line the indent is applied to, 0 based
+// * @param lineCount number of lines the indent applies to.
+// * @param indent line indent
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+// * Should not be called if a LineStyleListener has been set since the listener
+// * maintains the line attributes.
+// *
+// * All line attributes are maintained relative to the line text, not the
+// * line index that is specified in this method call.
+// * During text changes, when entire lines are inserted or removed, the line
+// * attributes that are associated with the lines after the change
+// * will "move" with their respective text. An entire line is defined as
+// * extending from the first character on a line to the last and including the
+// * line delimiter.
+// *
+// * When two lines are joined by deleting a line delimiter, the top line
+// * attributes take precedence and the attributes of the bottom line are deleted.
+// * For all other text changes line attributes will remain unchanged.
+// *
+// * Setting both line spacing and vertical indent on a line would result in the
+// * spacing and indent add up for the line.
+// *
+// *
+// * @param lineIndex line index the vertical indent is applied to, 0 based
+// * @param verticalLineIndent vertical line indent
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the specified line index is invalid
+// * Should not be called if a LineStyleListener has been set since the listener
+// * maintains the line attributes.
+// *
+// * All line attributes are maintained relative to the line text, not the
+// * line index that is specified in this method call.
+// * During text changes, when entire lines are inserted or removed, the line
+// * attributes that are associated with the lines after the change
+// * will "move" with their respective text. An entire line is defined as
+// * extending from the first character on a line to the last and including the
+// * line delimiter.
+// *
+// * When two lines are joined by deleting a line delimiter, the top line
+// * attributes take precedence and the attributes of the bottom line are deleted.
+// * For all other text changes line attributes will remain unchanged.
+// *
+// *
+// * @param startLine first line the justify is applied to, 0 based
+// * @param lineCount number of lines the justify applies to.
+// * @param justify true if lines should be justified
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+// *
+// * @see #setJustify(boolean)
+// * @since 3.2
+// */
+//public void setLineJustify(int startLine, int lineCount, boolean justify) {
+// checkWidget();
+// if (isListening(ST.LineGetStyle)) return;
+// if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+//
+// renderer.setLineJustify(startLine, lineCount, justify);
+// resetCache(startLine, lineCount);
+// redrawLines(startLine, lineCount, false);
+// if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) {
+// setCaretLocations();
+// }
+//}
+///**
+// * Sets the line spacing of the widget. The line spacing applies for all lines.
+// * In the case of #setLineSpacingProvider(StyledTextLineSpacingProvider) is customized,
+// * the line spacing are applied only for the lines which are not managed by {@link StyledTextLineSpacingProvider}.
+// *
+// * @param lineSpacing the line spacing
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @see #setLineSpacingProvider(StyledTextLineSpacingProvider)
+// * @since 3.2
+// */
+//public void setLineSpacing(int lineSpacing) {
+// checkWidget();
+// if (this.lineSpacing == lineSpacing || lineSpacing < 0) return;
+// this.lineSpacing = lineSpacing;
+// resetCache(0, content.getLineCount());
+// setCaretLocations();
+// super.redraw();
+//}
+///**
+// * Sets the line spacing provider of the widget. The line spacing applies for some lines with customized spacing
+// * or reset the customized spacing if the argument is null.
+// *
+// * @param lineSpacingProvider the line spacing provider (or null)
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @see #setLineSpacingProvider(StyledTextLineSpacingProvider)
+// * @since 3.107
+// */
+//public void setLineSpacingProvider(StyledTextLineSpacingProvider lineSpacingProvider) {
+// checkWidget();
+// boolean wasFixedLineHeight = isFixedLineHeight();
+// if (renderer.getLineSpacingProvider() == null && lineSpacingProvider == null
+// || (renderer.getLineSpacingProvider() != null
+// && renderer.getLineSpacingProvider().equals(lineSpacingProvider)))
+// return;
+// renderer.setLineSpacingProvider(lineSpacingProvider);
+// // reset lines cache if needed
+// if (lineSpacingProvider == null) {
+// if (!wasFixedLineHeight) {
+// resetCache(0, content.getLineCount());
+// }
+// } else {
+// if (wasFixedLineHeight) {
+// int firstLine = -1;
+// for (int i = 0; i < content.getLineCount(); i++) {
+// Integer lineSpacing = lineSpacingProvider.getLineSpacing(i);
+// if (lineSpacing != null && lineSpacing > 0) {
+// // there is a custom line spacing, set StyledText as variable line height mode
+// // reset only the line size
+// renderer.reset(i, 1);
+// if (firstLine == -1) {
+// firstLine = i;
+// }
+// }
+// }
+// if (firstLine != -1) {
+// // call reset cache for the first line which have changed to recompute scrollbars
+// resetCache(firstLine, 0);
+// }
+// }
+// }
+// setCaretLocations();
+// super.redraw();
+//}
+///**
+// * Sets the tab stops of the specified lines.
+// *
+// * Should not be called if a LineStyleListener has been set since the listener
+// * maintains the line attributes.
+// *
+// * All line attributes are maintained relative to the line text, not the
+// * line index that is specified in this method call.
+// * During text changes, when entire lines are inserted or removed, the line
+// * attributes that are associated with the lines after the change
+// * will "move" with their respective text. An entire line is defined as
+// * extending from the first character on a line to the last and including the
+// * line delimiter.
+// *
+// * When two lines are joined by deleting a line delimiter, the top line
+// * attributes take precedence and the attributes of the bottom line are deleted.
+// * For all other text changes line attributes will remain unchanged.
+// *
+// *
+// * @param startLine first line the justify is applied to, 0 based
+// * @param lineCount number of lines the justify applies to.
+// * @param tabStops tab stops
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+// *
+// * @see #setTabStops(int[])
+// * @since 3.6
+// */
+//public void setLineTabStops(int startLine, int lineCount, int[] tabStops) {
+// checkWidget();
+// if (isListening(ST.LineGetStyle)) return;
+// if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// if (tabStops != null) {
+// int pos = 0;
+// int[] newTabs = new int[tabStops.length];
+// for (int i = 0; i < tabStops.length; i++) {
+// if (tabStops[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// newTabs[i] = pos = tabStops[i];
+// }
+// renderer.setLineTabStops(startLine, lineCount, newTabs);
+// } else {
+// renderer.setLineTabStops(startLine, lineCount, null);
+// }
+// resetCache(startLine, lineCount);
+// redrawLines(startLine, lineCount, false);
+// if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) {
+// setCaretLocations();
+// }
+//}
+///**
+// * Sets the wrap indent of the specified lines.
+// *
+// * Should not be called if a LineStyleListener has been set since the listener
+// * maintains the line attributes.
+// *
+// * All line attributes are maintained relative to the line text, not the
+// * line index that is specified in this method call.
+// * During text changes, when entire lines are inserted or removed, the line
+// * attributes that are associated with the lines after the change
+// * will "move" with their respective text. An entire line is defined as
+// * extending from the first character on a line to the last and including the
+// * line delimiter.
+// *
+// * When two lines are joined by deleting a line delimiter, the top line
+// * attributes take precedence and the attributes of the bottom line are deleted.
+// * For all other text changes line attributes will remain unchanged.
+// *
+// *
+// * @param startLine first line the wrap indent is applied to, 0 based
+// * @param lineCount number of lines the wrap indent applies to.
+// * @param wrapIndent line wrap indent
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+// *
+// * @see #setWrapIndent(int)
+// * @since 3.6
+// */
+//public void setLineWrapIndent(int startLine, int lineCount, int wrapIndent) {
+// checkWidget();
+// if (isListening(ST.LineGetStyle)) return;
+// if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// int oldBottom = getLinePixel(startLine + lineCount);
+// renderer.setLineWrapIndent(startLine, lineCount, wrapIndent);
+// resetCache(startLine, lineCount);
+// int newBottom = getLinePixel(startLine + lineCount);
+// redrawLines(startLine, lineCount, oldBottom != newBottom);
+// if (Arrays.stream(caretOffsets).map(content::getLineAtOffset).anyMatch(caretLine -> startLine <= caretLine && caretLine < startLine + lineCount)) {
+// setCaretLocations();
+// }
+//}
+//
+///**
+// * Sets the color of the margins.
+// *
+// * @param color the new color (or null)
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public void setMarginColor(Color color) {
+// checkWidget();
+// if (color != null && color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// marginColor = color;
+// super.redraw();
+//}
+///**
+// * Sets the margins.
+// *
+// * @param leftMargin the left margin.
+// * @param topMargin the top margin.
+// * @param rightMargin the right margin.
+// * @param bottomMargin the bottom margin.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public void setMargins (int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
+// checkWidget();
+// this.leftMargin = Math.max(0, leftMargin) + alignmentMargin;
+// this.topMargin = Math.max(0, topMargin);
+// this.rightMargin = Math.max(0, rightMargin);
+// this.bottomMargin = Math.max(0, bottomMargin);
+// resetCache(0, content.getLineCount());
+// setScrollBars(true);
+// setCaretLocations();
+// setAlignment();
+// super.redraw();
+//}
+///**
+// * Sets the enabled state of the mouse navigator. When the mouse navigator is enabled, the user can navigate through the widget
+// * by pressing the middle button and moving the cursor.
+// *
+// * @param enabled if true, the mouse navigator is enabled, if false the mouse navigator is deactivated
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @since 3.110
+// */
+//public void setMouseNavigatorEnabled(boolean enabled) {
+// checkWidget();
+// if ((enabled && mouseNavigator != null) || (!enabled && mouseNavigator == null)) {
+// return;
+// }
+// if (enabled) {
+// mouseNavigator = new MouseNavigator(this);
+// } else {
+// mouseNavigator.dispose();
+// mouseNavigator = null;
+// }
+//}
+///**
+// * Flips selection anchor based on word selection direction.
+// */
+//void setMouseWordSelectionAnchor() {
+// if (doubleClickEnabled && clickCount > 1) {
+// if (caretOffsets[0] < doubleClickSelection.x) {
+// selectionAnchors[0] = doubleClickSelection.y;
+// } else if (caretOffsets[0] > doubleClickSelection.y) {
+// selectionAnchors[0] = doubleClickSelection.x;
+// }
+// }
+//}
+///**
+// * Sets the orientation of the receiver, which must be one
+// * of the constants SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT.
+// *
+// * @param orientation new orientation style
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 2.1.2
+// */
+//@Override
+//public void setOrientation(int orientation) {
+// int oldOrientation = getOrientation();
+// super.setOrientation(orientation);
+// int newOrientation = getOrientation();
+// if (oldOrientation != newOrientation) {
+// resetBidiData();
+// }
+//}
+///**
+// * Sets the right margin.
+// *
+// * @param rightMargin the right margin.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public void setRightMargin (int rightMargin) {
+// checkWidget();
+// setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin);
+//}
+//void setScrollBar(ScrollBar bar, int clientArea, int maximum, int margin) {
+// int inactive = 1;
+// if (clientArea < maximum) {
+// bar.setMaximum(maximum - margin);
+// bar.setThumb(clientArea - margin);
+// bar.setPageIncrement(clientArea - margin);
+// if (!alwaysShowScroll) bar.setVisible(true);
+// } else if (bar.getThumb() != inactive || bar.getMaximum() != inactive) {
+// bar.setValues(bar.getSelection(), bar.getMinimum(), inactive, inactive, bar.getIncrement(), inactive);
+// }
+//}
+///**
+// * Adjusts the maximum and the page size of the scroll bars to
+// * reflect content width/length changes.
+// *
+// * @param vertical indicates if the vertical scrollbar also needs to be set
+// */
+//void setScrollBars(boolean vertical) {
+// ignoreResize++;
+// if (!isFixedLineHeight() || !alwaysShowScroll) vertical = true;
+// ScrollBar verticalBar = vertical ? getVerticalBar() : null;
+// ScrollBar horizontalBar = getHorizontalBar();
+// int oldHeight = clientAreaHeight;
+// int oldWidth = clientAreaWidth;
+// if (!alwaysShowScroll) {
+// if (verticalBar != null) verticalBar.setVisible(false);
+// if (horizontalBar != null) horizontalBar.setVisible(false);
+// }
+// if (verticalBar != null) {
+// setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin);
+// }
+// if (horizontalBar != null && !wordWrap) {
+// setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin);
+// if (!alwaysShowScroll && horizontalBar.getVisible() && verticalBar != null) {
+// setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin);
+// if (verticalBar.getVisible()) {
+// setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin);
+// }
+// }
+// }
+// if (!alwaysShowScroll) {
+// redrawMargins(oldHeight, oldWidth);
+// }
+// ignoreResize--;
+//}
+///**
+// * Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start).
+// *
+// * @param start new caret position
+// * @see #setSelection(int,int)
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
+// * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+// *
+// */
+//public void setSelection(int start) {
+// // checkWidget test done in setSelectionRange
+// setSelection(start, start);
+//}
+///**
+// * Sets the selection and scrolls it into view.
+// *
+// * Indexing is zero based. Text selections are specified in terms of
+// * caret positions. In a text widget that contains N characters, there are
+// * N+1 caret positions, ranging from 0..N
+// *
+// *
+// * @param point x=selection start offset, y=selection end offset
+// * The caret will be placed at the selection start when x > y.
+// * @see #setSelection(int,int)
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when point is null
+// *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
+// * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+// *
+// */
+//public void setSelection(Point point) {
+// checkWidget();
+// if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+// setSelection(point.x, point.y);
+//}
+///**
+// * Sets the receiver's selection 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
+// *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @since 2.1
+// */
+//public void setSelectionBackground (Color color) {
+// checkWidget ();
+// if (color != null) {
+// if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// selectionBackground = color;
+// resetCache(0, content.getLineCount());
+// setCaretLocations();
+// super.redraw();
+//}
+///**
+// * Sets the receiver's selection foreground color to the color specified
+// * by the argument, or to the default system color for the control
+// * if the argument is null.
+// *
+// * Note that this is a HINT. Some platforms do not allow the application
+// * to change the selection foreground color.
+// *
+// * @param color the new color (or null)
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @since 2.1
+// */
+//public void setSelectionForeground (Color color) {
+// checkWidget ();
+// if (color != null) {
+// if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// selectionForeground = color;
+// resetCache(0, content.getLineCount());
+// setCaretLocations();
+// super.redraw();
+//}
+///**
+// * Sets the selection and scrolls it into view.
+// *
+// * Indexing is zero based. Text selections are specified in terms of
+// * caret positions. In a text widget that contains N characters, there are
+// * N+1 caret positions, ranging from 0..N
+// *
+// *
+// * @param start selection start offset. The caret will be placed at the
+// * selection start when start > end.
+// * @param end selection end offset
+// * @see #setSelectionRange(int,int)
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
+// * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+// *
+// */
+//public void setSelection(int start, int end) {
+// setSelectionRange(start, end - start);
+// showSelection();
+//}
+///**
+// * Sets the selection.
+// *
+// * The new selection may not be visible. Call showSelection to scroll
+// * the selection into view.
+// *
+// *
+// * @param start offset of the first selected character, start >= 0 must be true.
+// * @param length number of characters to select, 0 <= start + length
+// * <= getCharCount() must be true.
+// * A negative length places the caret at the selection start.
+// * @param sendEvent a Selection event is sent when set to true and when
+// * the selection is reset.
+// */
+//void setSelection(int[] regions, boolean sendEvent, boolean doBlock) {
+// if (regions.length == 2 && selection.length == 1) { // single range before/after
+// int start = regions[0];
+// int length = regions[1];
+// int end = start + length;
+// if (start > end) {
+// int temp = end;
+// end = start;
+// start = temp;
+// }
+// int selectionAnchor = selectionAnchors[0];
+// // is the selection range different or is the selection direction
+// // different?
+// if (selection[0].x != start || selection[0].y != end ||
+// (length > 0 && selectionAnchor != selection[0].x) ||
+// (length < 0 && selectionAnchor != selection[0].y)) {
+// if (blockSelection && doBlock) {
+// if (length < 0) {
+// setBlockSelectionOffset(end, start, sendEvent);
+// } else {
+// setBlockSelectionOffset(start, end, sendEvent);
+// }
+// } else {
+// int oldStart = selection[0].x;
+// int oldLength = selection[0].y - selection[0].x;
+// int charCount = content.getCharCount();
+// // called internally to remove selection after text is removed
+// // therefore make sure redraw range is valid.
+// int redrawX = Math.min(selection[0].x, charCount);
+// int redrawY = Math.min(selection[0].y, charCount);
+// if (length < 0) {
+// selectionAnchors[0] = selectionAnchor = selection[0].y = end;
+// selection[0].x = start;
+// setCaretOffsets(new int[] {start}, PREVIOUS_OFFSET_TRAILING);
+// } else {
+// selectionAnchors[0] = selectionAnchor = selection[0].x = start;
+// selection[0].y = end;
+// setCaretOffsets(new int[] {end}, PREVIOUS_OFFSET_TRAILING);
+// }
+// redrawX = Math.min(redrawX, selection[0].x);
+// redrawY = Math.max(redrawY, selection[0].y);
+// if (redrawY - redrawX > 0) {
+// internalRedrawRange(redrawX, redrawY - redrawX);
+// }
+// if (sendEvent && (oldLength != end - start || (oldLength != 0 && oldStart != start))) {
+// sendSelectionEvent();
+// }
+// sendAccessibleTextCaretMoved();
+// }
+// }
+// } else if (!blockSelection || !doBlock) {
+// boolean caretAtEndOfSelection = regions[1] > 0;
+// int charCount = content.getCharCount();
+// Point[] newRanges = new Point[regions.length / 2];
+// for (int i = 0; i < regions.length; i += 2) {
+// int start = regions[i];
+// int length = regions[i + 1];
+// int end = start + length;
+// if (start > end) {
+// int temp = end;
+// end = start;
+// start = temp;
+// }
+// newRanges[i / 2] = new Point(start, end);
+// }
+// Arrays.sort(newRanges, SELECTION_COMPARATOR);
+// // merge contiguous ranges
+// int newRangeIndex = 0;
+// for (Point range : newRanges) {
+// if (newRangeIndex > 0) {
+// Point previousRange = newRanges[newRangeIndex - 1];
+// if (previousRange.y >= range.x) {
+// previousRange.y = Math.max(previousRange.y, range.y);
+// } else {
+// newRanges[newRangeIndex] = range;
+// newRangeIndex++;
+// }
+// } else {
+// newRanges[newRangeIndex] = range;
+// newRangeIndex++;
+// }
+// }
+// Point[] toRedraw = new Point[newRangeIndex + selection.length];
+// System.arraycopy(newRanges, 0, toRedraw, 0, newRangeIndex);
+// System.arraycopy(selection, 0, toRedraw, newRangeIndex, selection.length);
+// Arrays.sort(toRedraw, SELECTION_COMPARATOR);
+// Point[] formerSelection = selection;
+// selection = Arrays.copyOf(newRanges, newRangeIndex);
+// Point currentToRedraw = null;
+// for (Point p : toRedraw) {
+// if (currentToRedraw == null) {
+// currentToRedraw = new Point(p.x, p.y);
+// } else if (currentToRedraw.y >= p.x - 1) {
+// // expand if necessary
+// currentToRedraw = new Point(currentToRedraw.x, Math.max(p.y, currentToRedraw.y));
+// } else {
+// currentToRedraw = new Point(Math.max(0, currentToRedraw.x), Math.min(charCount, currentToRedraw.y));
+// internalRedrawRange(currentToRedraw.x, currentToRedraw.y - currentToRedraw.x);
+// currentToRedraw = null;
+// }
+// }
+// if (currentToRedraw != null) {
+// currentToRedraw = new Point(Math.max(0, currentToRedraw.x), Math.min(charCount, currentToRedraw.y));
+// internalRedrawRange(currentToRedraw.x, currentToRedraw.y - currentToRedraw.x);
+// }
+// if (!caretAtEndOfSelection) {
+// selectionAnchors = Arrays.stream(selection).mapToInt(p -> p.y).toArray();
+// setCaretOffsets(Arrays.stream(selection).mapToInt(p -> p.x).toArray(), PREVIOUS_OFFSET_TRAILING);
+// } else {
+// selectionAnchors = Arrays.stream(selection).mapToInt(p -> p.x).toArray();
+// setCaretOffsets(Arrays.stream(selection).mapToInt(p -> p.y).toArray(), PREVIOUS_OFFSET_TRAILING);
+// }
+// setCaretLocations();
+// if (sendEvent && !Arrays.equals(formerSelection, selection)) {
+// sendSelectionEvent();
+// }
+// sendAccessibleTextCaretMoved();
+// }
+//}
+///**
+// * Sets the selection.
+// *
+// * The new selection may not be visible. Call showSelection to scroll the selection
+// * into view. A negative length places the caret at the visual start of the selection.
+// *
+// *
+// * @param start offset of the first selected character
+// * @param length number of characters to select
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
+// * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+// *
+// * The new selection may not be visible. Call showSelection to scroll the selection
+// * into view. A negative length places the caret at the visual start of the selection.
+// *
+// *
+// * @param ranges an array of offset/length pairs.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT when either the start or the end of one selection range is inside a
+// * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+// *
ERROR_INVALID_ARGUMENT when ranges are null or size isn't valid (not pair)
+// *
+// * @see #getSelectionRanges()
+// * @since 3.117
+// */
+//public void setSelectionRanges(int[] ranges) {
+// checkWidget();
+// int contentLength = getCharCount();
+// if (ranges.length % 2 != 0) {
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// int[] fixedRanges = Arrays.copyOf(ranges, ranges.length);
+// for (int i = 0; i < ranges.length; i+=2) {
+// int start = ranges[i];
+// start = Math.max(0, Math.min(start, contentLength));
+// int length = ranges[i + 1];
+// int end = start + length;
+// if (end < 0) {
+// length = -start;
+// } else if (end > contentLength) {
+// length = contentLength - start;
+// }
+// if (isLineDelimiter(start) || isLineDelimiter(start + length)) {
+// // the start offset or end offset of the selection range is inside a
+// // multi byte line delimiter. This is an illegal operation and an exception
+// // is thrown. Fixes 1GDKK3R
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// fixedRanges[i] = start;
+// fixedRanges[i + 1] = length;
+// }
+// setSelection(fixedRanges, false, true);
+// setCaretLocations();
+//}
+//
+///**
+// * Adds the specified style.
+// *
+// * The new style overwrites existing styles for the specified range.
+// * Existing style ranges are adjusted if they partially overlap with
+// * the new style. To clear an individual style, call setStyleRange
+// * with a StyleRange that has null attributes.
+// *
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// *
+// * @param range StyleRange object containing the style information.
+// * Overwrites the old style in the given range. May be null to delete
+// * all styles.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())
+// *
+// */
+//public void setStyleRange(StyleRange range) {
+// checkWidget();
+// if (isListening(ST.LineGetStyle)) return;
+// if (range != null) {
+// if (range.isUnstyled()) {
+// setStyleRanges(range.start, range.length, null, null, false);
+// } else {
+// setStyleRanges(range.start, 0, null, new StyleRange[]{range}, false);
+// }
+// } else {
+// setStyleRanges(0, 0, null, null, true);
+// }
+//}
+///**
+// * Clears the styles in the range specified by start and
+// * length and adds the new styles.
+// *
+// * The ranges array contains start and length pairs. Each pair refers to
+// * the corresponding style in the styles array. For example, the pair
+// * that starts at ranges[n] with length ranges[n+1] uses the style
+// * at styles[n/2]. The range fields within each StyleRange are ignored.
+// * If ranges or styles is null, the specified range is cleared.
+// *
+// * Note: It is expected that the same instance of a StyleRange will occur
+// * multiple times within the styles array, reducing memory usage.
+// *
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// *
+// * @param start offset of first character where styles will be deleted
+// * @param length length of the range to delete styles in
+// * @param ranges the array of ranges. The ranges must not overlap and must be in order.
+// * @param styles the array of StyleRanges. The range fields within the StyleRange are unused.
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when an element in the styles array is null
+// *
ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
+// *
ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
+// *
ERROR_INVALID_RANGE when a range overlaps
+// *
+// *
+// * @since 3.2
+// */
+//public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) {
+// checkWidget();
+// if (isListening(ST.LineGetStyle)) return;
+// if (ranges == null || styles == null) {
+// setStyleRanges(start, length, null, null, false);
+// } else {
+// setStyleRanges(start, length, ranges, styles, false);
+// }
+//}
+///**
+// * Sets styles to be used for rendering the widget content.
+// *
+// * All styles in the widget will be replaced with the given set of ranges and styles.
+// * The ranges array contains start and length pairs. Each pair refers to
+// * the corresponding style in the styles array. For example, the pair
+// * that starts at ranges[n] with length ranges[n+1] uses the style
+// * at styles[n/2]. The range fields within each StyleRange are ignored.
+// * If either argument is null, the styles are cleared.
+// *
+// * Note: It is expected that the same instance of a StyleRange will occur
+// * multiple times within the styles array, reducing memory usage.
+// *
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// *
+// * @param ranges the array of ranges. The ranges must not overlap and must be in order.
+// * @param styles the array of StyleRanges. The range fields within the StyleRange are unused.
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when an element in the styles array is null
+// *
ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
+// *
ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
+// *
ERROR_INVALID_RANGE when a range overlaps
+// *
+// *
+// * @since 3.2
+// */
+//public void setStyleRanges(int[] ranges, StyleRange[] styles) {
+// checkWidget();
+// if (isListening(ST.LineGetStyle)) return;
+// if (ranges == null || styles == null) {
+// setStyleRanges(0, 0, null, null, true);
+// } else {
+// setStyleRanges(0, 0, ranges, styles, true);
+// }
+//}
+//void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles, boolean reset) {
+// int charCount = content.getCharCount();
+// if (reset) {
+// start = 0;
+// length = charCount;
+// }
+// int[] formerRanges = getRanges(start, length);
+// StyleRange[] formerStyles = getStyleRanges(start, length);
+// int end = start + length;
+// final boolean wasFixedLineHeight = isFixedLineHeight();
+// if (start > end || start < 0) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// if (styles != null) {
+// if (end > charCount) {
+// SWT.error(SWT.ERROR_INVALID_RANGE);
+// }
+// if (ranges != null) {
+// if (ranges.length != styles.length << 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// int lastOffset = 0;
+// for (int i = 0; i < styles.length; i ++) {
+// if (styles[i] == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// int rangeStart, rangeLength;
+// if (ranges != null) {
+// rangeStart = ranges[i << 1];
+// rangeLength = ranges[(i << 1) + 1];
+// } else {
+// rangeStart = styles[i].start;
+// rangeLength = styles[i].length;
+// }
+// if (rangeLength < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// if (lastOffset > rangeStart) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// hasStyleWithVariableHeight |= styles[i].isVariableHeight();
+// lastOffset = rangeStart + rangeLength;
+// }
+// }
+// int rangeStart = start, rangeEnd = end;
+// if (styles != null && styles.length > 0) {
+// if (ranges != null) {
+// rangeStart = ranges[0];
+// rangeEnd = ranges[ranges.length - 2] + ranges[ranges.length - 1];
+// } else {
+// rangeStart = styles[0].start;
+// rangeEnd = styles[styles.length - 1].start + styles[styles.length - 1].length;
+// }
+// }
+//
+// // This needs to happen before new styles are applied
+// int expectedBottom = 0;
+// if (!isFixedLineHeight() && !reset) {
+// int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
+// int partialTopIndex = getPartialTopIndex();
+// int partialBottomIndex = getPartialBottomIndex();
+// if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
+// expectedBottom = getLinePixel(lineEnd + 1);
+// }
+// }
+// if (reset) {
+// renderer.setStyleRanges(null, null);
+// } else {
+// renderer.updateRanges(start, length, length);
+// }
+// if (styles != null && styles.length > 0) {
+// renderer.setStyleRanges(ranges, styles);
+// }
+//
+// // re-evaluate variable height with all styles (including new ones)
+// hasStyleWithVariableHeight = false;
+// for (StyleRange style : getStyleRanges(false)) {
+// hasStyleWithVariableHeight = style.isVariableHeight();
+// if (hasStyleWithVariableHeight) break;
+// }
+//
+// SortedSet modifiedLines = computeModifiedLines(formerRanges, formerStyles, ranges, styles);
+// resetCache(modifiedLines);
+// if (reset) {
+// super.redraw();
+// } else {
+// int lineStart = content.getLineAtOffset(Math.min(start, rangeStart));
+// int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
+// int partialTopIndex = getPartialTopIndex();
+// int partialBottomIndex = getPartialBottomIndex();
+// if (!(lineStart > partialBottomIndex || lineEnd < partialTopIndex)) {
+// int top = 0;
+// int bottom = clientAreaHeight;
+// if (partialTopIndex <= lineStart && lineStart <= partialBottomIndex) {
+// top = Math.max(0, getLinePixel(lineStart));
+// }
+// if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
+// bottom = getLinePixel(lineEnd + 1);
+// }
+// if (!(wasFixedLineHeight && isFixedLineHeight()) && bottom != expectedBottom) {
+// bottom = clientAreaHeight;
+// }
+// super.redraw(0, top, clientAreaWidth, bottom - top, false);
+// }
+// }
+// int oldColumnX = columnX;
+// setCaretLocations();
+// columnX = oldColumnX;
+// doMouseLinkCursor();
+//}
+//
+///**
+// *
+// * @param referenceRanges former ranges, sorted by order and without overlapping, typically returned {@link #getRanges(int, int)}
+// * @param newRanges former ranges, sorted by order and without overlapping
+// */
+//private SortedSet computeModifiedLines(int[] referenceRanges, StyleRange[] referenceStyles, int[] newRanges, StyleRange[] newStyles) {
+// if (referenceStyles == null) {
+// referenceStyles = new StyleRange[0];
+// }
+// if (referenceRanges == null) {
+// referenceRanges = createRanges(referenceStyles);
+// }
+// if (newStyles == null) {
+// newStyles = new StyleRange[0];
+// }
+// if (newRanges == null) {
+// newRanges = createRanges(newStyles);
+// }
+// if (referenceRanges.length != 2 * referenceStyles.length) {
+// throw new IllegalArgumentException();
+// }
+// if (newRanges.length != 2 * newStyles.length) {
+// throw new IllegalArgumentException();
+// }
+// SortedSet res = new TreeSet<>();
+// int referenceRangeIndex = 0;
+// int newRangeIndex = 0;
+// StyleRange defaultStyle = new StyleRange();
+// defaultStyle.foreground = this.foreground;
+// defaultStyle.background = this.background;
+// defaultStyle.font = getFont();
+// int currentOffset = referenceRanges.length > 0 ? referenceRanges[0] : Integer.MAX_VALUE;
+// if (newRanges.length > 0) {
+// currentOffset = Math.min(currentOffset, newRanges[0]);
+// }
+// while (currentOffset < content.getCharCount() && (referenceRangeIndex < referenceStyles.length || newRangeIndex < newRanges.length)) {
+// int nextMilestoneOffset = Integer.MAX_VALUE; // next new range start/end after current offset
+//
+// while (referenceRangeIndex < referenceStyles.length && endRangeOffset(referenceRanges, referenceRangeIndex) <= currentOffset) {
+// referenceRangeIndex++;
+// }
+// StyleRange referenceStyleAtCurrentOffset = defaultStyle;
+// if (isInRange(referenceRanges, referenceRangeIndex, currentOffset)) { // has styling
+// referenceStyleAtCurrentOffset = referenceStyles[referenceRangeIndex];
+// nextMilestoneOffset = endRangeOffset(referenceRanges, referenceRangeIndex);
+// } else if (referenceRangeIndex < referenceStyles.length) { // no range, default styling
+// nextMilestoneOffset = referenceRanges[2 * referenceRangeIndex]; // beginning of next range
+// }
+//
+// while (newRangeIndex < newStyles.length && endRangeOffset(newRanges, newRangeIndex) <= currentOffset) {
+// newRangeIndex++;
+// }
+// StyleRange newStyleAtCurrentOffset = defaultStyle;
+// if (isInRange(newRanges, newRangeIndex, currentOffset)) {
+// newStyleAtCurrentOffset = newStyles[newRangeIndex];
+// nextMilestoneOffset = Math.min(nextMilestoneOffset, endRangeOffset(newRanges, newRangeIndex));
+// } else if (newRangeIndex < newStyles.length) {
+// nextMilestoneOffset = Math.min(nextMilestoneOffset, newRanges[2 * newRangeIndex]);
+// }
+//
+// if (!referenceStyleAtCurrentOffset.similarTo(newStyleAtCurrentOffset)) {
+// int fromLine = getLineAtOffset(currentOffset);
+// int toLine = getLineAtOffset(nextMilestoneOffset - 1);
+// for (int line = fromLine; line <= toLine; line++) {
+// res.add(line);
+// }
+// currentOffset = toLine + 1 < getLineCount() ? getOffsetAtLine(toLine + 1) : content.getCharCount();
+// } else {
+// currentOffset = nextMilestoneOffset;
+// }
+// }
+// return res;
+//}
+//private int[] createRanges(StyleRange[] referenceStyles) {
+// int[] referenceRanges;
+// referenceRanges = new int[2 * referenceStyles.length];
+// for (int i = 0; i < referenceStyles.length; i++) {
+// referenceRanges[2 * i] = referenceStyles[i].start;
+// referenceRanges[2 * i + 1] = referenceStyles[i].length;
+// }
+// return referenceRanges;
+//}
+//
+//private boolean isInRange(int[] ranges, int styleIndex, int offset) {
+// if (ranges == null || ranges.length == 0 || styleIndex < 0 || 2 * styleIndex + 1 > ranges.length) {
+// return false;
+// }
+// int start = ranges[2 * styleIndex];
+// int length = ranges[2 * styleIndex + 1];
+// return offset >= start && offset < start + length;
+//}
+//
+///**
+// * The offset on which the range ends (excluded)
+// */
+//private int endRangeOffset(int[] ranges, int styleIndex) {
+// if (styleIndex < 0 || 2 * styleIndex > ranges.length) {
+// throw new IllegalArgumentException();
+// }
+// int start = ranges[2 * styleIndex];
+// int length = ranges[2 * styleIndex + 1];
+// return start + length;
+//}
+//
+///**
+// * Sets styles to be used for rendering the widget content. All styles
+// * in the widget will be replaced with the given set of styles.
+// *
+// * Note: Because a StyleRange includes the start and length, the
+// * same instance cannot occur multiple times in the array of styles.
+// * If the same style attributes, such as font and color, occur in
+// * multiple StyleRanges, setStyleRanges(int[], StyleRange[])
+// * can be used to share styles and reduce memory usage.
+// *
+// * Should not be called if a LineStyleListener has been set since the
+// * listener maintains the styles.
+// *
+// *
+// * @param ranges StyleRange objects containing the style information.
+// * The ranges should not overlap. The style rendering is undefined if
+// * the ranges do overlap. Must not be null. The styles need to be in order.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when the list of ranges is null
+// *
ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see #setTabStops(int[])
+// */
+//public void setTabs(int tabs) {
+// checkWidget();
+// tabLength = tabs;
+// renderer.setFont(null, tabs);
+// resetCache(0, content.getLineCount());
+// setCaretLocations();
+// super.redraw();
+//}
+//
+///**
+// * Sets the receiver's tab list. Each value in the tab list specifies
+// * the space in points from the origin of the document to the respective
+// * tab stop. The last tab stop width is repeated continuously.
+// *
+// * @param tabs the new tab list (or null)
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_INVALID_ARGUMENT - if a tab stop is negative or less than the previous stop in the list
+// *
+// *
+// * @see StyledText#getTabStops()
+// *
+// * @since 3.6
+// */
+//public void setTabStops(int [] tabs) {
+// checkWidget();
+// if (tabs != null) {
+// int pos = 0;
+// int[] newTabs = new int[tabs.length];
+// for (int i = 0; i < tabs.length; i++) {
+// if (tabs[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// newTabs[i] = pos = tabs[i];
+// }
+// this.tabs = newTabs;
+// } else {
+// this.tabs = null;
+// }
+// resetCache(0, content.getLineCount());
+// setCaretLocations();
+// super.redraw();
+//}
+//
+///**
+// * Sets the widget content.
+// * If the widget has the SWT.SINGLE style and "text" contains more than
+// * one line, only the first line is rendered but the text is stored
+// * unchanged. A subsequent call to getText will return the same text
+// * that was set.
+// *
+// * Note: Only a single line of text should be set when the SWT.SINGLE
+// * style is used.
+// *
+// *
+// * @param text new widget content. Replaces existing content. Line styles
+// * that were set using StyledText API are discarded. The
+// * current selection is also discarded.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT when string is null
+// *
+// */
+//public void setText(String text) {
+// checkWidget();
+// if (text == null) {
+// SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// }
+// Event event = new Event();
+// event.start = 0;
+// event.end = getCharCount();
+// event.text = text;
+// event.doit = true;
+// notifyListeners(SWT.Verify, event);
+// if (event.doit) {
+// StyledTextEvent styledTextEvent = null;
+// if (isListening(ST.ExtendedModify)) {
+// styledTextEvent = new StyledTextEvent(content);
+// styledTextEvent.start = event.start;
+// styledTextEvent.end = event.start + event.text.length();
+// styledTextEvent.text = content.getTextRange(event.start, event.end - event.start);
+// }
+// content.setText(event.text);
+// notifyListeners(SWT.Modify, event);
+// if (styledTextEvent != null) {
+// notifyListeners(ST.ExtendedModify, styledTextEvent);
+// }
+// }
+//}
+//
+///**
+// * Sets the base text direction (a.k.a. "paragraph direction") of the receiver,
+// * which must be one of the constants SWT.LEFT_TO_RIGHT or
+// * SWT.RIGHT_TO_LEFT.
+// *
+// * setOrientation would override this value with the text direction
+// * that is consistent with the new orientation.
+// *
+// *
+// * Warning: This API is currently only implemented on Windows.
+// * It doesn't set the base text direction on GTK and Cocoa.
+// *
+// *
+// * @param textDirection the base text direction style
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @see SWT#FLIP_TEXT_DIRECTION
+// */
+//@Override
+//public void setTextDirection(int textDirection) {
+// checkWidget();
+// int oldStyle = getStyle();
+// super.setTextDirection(textDirection);
+// if (isAutoDirection () || oldStyle != getStyle()) {
+// resetBidiData();
+// }
+//}
+//
+///**
+// * Sets the text limit to the specified number of characters.
+// *
+// * The text limit specifies the amount of text that
+// * the user can type into the widget.
+// *
+// *
+// * @param limit the new text limit.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_CANNOT_BE_ZERO when limit is 0
+// *
+// */
+//public void setTextLimit(int limit) {
+// checkWidget();
+// if (limit == 0) {
+// SWT.error(SWT.ERROR_CANNOT_BE_ZERO);
+// }
+// textLimit = limit;
+//}
+///**
+// * Sets the top index. Do nothing if there is no text set.
+// *
+// * The top index is the index of the line that is currently at the top
+// * of the widget. The top index changes when the widget is scrolled.
+// * Indexing starts from zero.
+// * Note: The top index is reset to 0 when new text is set in the widget.
+// *
+// *
+// * @param topIndex new top index. Must be between 0 and
+// * getLineCount() - fully visible lines per page. If no lines are fully
+// * visible the maximum value is getLineCount() - 1. An out of range
+// * index will be adjusted accordingly.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// *
+// * @since 3.5
+// */
+//public void setTopMargin (int topMargin) {
+// checkWidget();
+// setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin);
+//}
+///**
+// * Sets the top SWT logical point offset. Do nothing if there is no text set.
+// *
+// * The top point offset is the vertical SWT logical point offset of the widget. The
+// * widget is scrolled so that the given SWT logical point position is at the top.
+// * The top index is adjusted to the corresponding top line.
+// * Note: The top point is reset to 0 when new text is set in the widget.
+// *
+// *
+// * @param pixel new top point offset. Must be between 0 and
+// * (getLineCount() - visible lines per page) / getLineHeight()). An out
+// * of range offset will be adjusted accordingly.
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// * This overrides the creation style bit SWT.WRAP.
+// *
+// *
+// * @param wrap true=widget wraps lines, false=widget does not wrap lines
+// * @since 2.0
+// */
+//public void setWordWrap(boolean wrap) {
+// checkWidget();
+// if ((getStyle() & SWT.SINGLE) != 0) return;
+// if (wordWrap == wrap) return;
+// if (wordWrap && blockSelection) setBlockSelection(false);
+// wordWrap = wrap;
+// resetCache(0, content.getLineCount());
+// horizontalScrollOffset = 0;
+// ScrollBar horizontalBar = getHorizontalBar();
+// if (horizontalBar != null) {
+// horizontalBar.setVisible(!wordWrap);
+// }
+// setScrollBars(true);
+// setCaretLocations();
+// super.redraw();
+//}
+///**
+// * Sets the wrap line indentation of the widget.
+// *
+// * It is the amount of blank space, in points, at the beginning of each wrapped line.
+// * When a line wraps in several lines all the lines but the first one is indented
+// * by this amount.
+// *
+// *
+// * @param wrapIndent the new wrap indent
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// * The end of the selection will be scrolled into view.
+// * Note that if a right-to-left selection exists, the end of the selection is
+// * the visual beginning of the selection (i.e., where the caret is located).
+// *
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//public void showSelection() {
+// checkWidget();
+// // is selection from right-to-left?
+// boolean rightToLeft = caretOffsets[0] == selection[0].x;
+// int startOffset, endOffset;
+// if (rightToLeft) {
+// startOffset = selection[0].y;
+// endOffset = selection[0].x;
+// } else {
+// startOffset = selection[0].x;
+// endOffset = selection[0].y;
+// }
+//
+// Rectangle startBounds = getBoundsAtOffset(startOffset);
+// Rectangle endBounds = getBoundsAtOffset(endOffset);
+//
+// // can the selection be fully displayed within the widget's visible width?
+// int w = clientAreaWidth - leftMargin - rightMargin;
+// boolean selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w;
+// if (selectionFits) {
+// // show as much of the selection as possible by first showing
+// // the start of the selection
+// if (showLocation(startBounds, false)) {
+// // endX value could change if showing startX caused a scroll to occur
+// endBounds = getBoundsAtOffset(endOffset);
+// }
+// // the character at endOffset is not part of the selection
+// endBounds.width = endOffset == caretOffsets[0] ? getCaretWidth() : 0;
+// showLocation(endBounds, false);
+// } else {
+// // just show the end of the selection since the selection start
+// // will not be visible
+// showLocation(endBounds, true);
+// }
+//}
+//void updateCaretVisibility() {
+// Caret caret = getCaret();
+// if (caret != null) {
+// if (carets == null || carets.length == 0) {
+// carets = new Caret[] { caret };
+// }
+// if (blockSelection && blockXLocation != -1) {
+// Arrays.stream(carets).forEach(c -> c.setVisible(false));
+// } else {
+// Arrays.stream(carets).forEach(c -> {
+// Point location = c.getLocation();
+// Point size = c.getSize();
+// boolean visible =
+// topMargin <= location.y + size.y && location.y <= clientAreaHeight - bottomMargin &&
+// leftMargin <= location.x + size.x && location.x <= clientAreaWidth - rightMargin;
+// c.setVisible(visible);
+// });
+// }
+// }
+//}
+///**
+// * Updates the selection and caret position depending on the text change.
+// *
+// * If the selection intersects with the replaced text, the selection is
+// * reset and the caret moved to the end of the new text.
+// * If the selection is behind the replaced text it is moved so that the
+// * same text remains selected. If the selection is before the replaced text
+// * it is left unchanged.
+// *
+// *
+// * @param startOffset offset of the text change
+// * @param replacedLength length of text being replaced
+// * @param newLength length of new text
+// */
+//void updateSelection(int startOffset, int replacedLength, int newLength) {
+// if (selection[selection.length - 1].y <= startOffset) {
+// // selection ends before text change
+// if (isWordWrap()) setCaretLocations();
+// return;
+// }
+// // clear selection fragment before text change
+// Arrays.stream(selection)
+// .filter(sel -> sel.y > startOffset)
+// .filter(sel -> sel.x < startOffset)
+// .forEach(sel -> internalRedrawRange(sel.x, startOffset - sel.x));
+// Arrays.stream(selection)
+// .filter(sel -> sel.y > startOffset)
+// .filter(sel -> sel.y > startOffset + replacedLength && sel.x < startOffset + replacedLength)
+// .forEach(sel -> {
+// // clear selection fragment after text change.
+// // do this only when the selection is actually affected by the
+// // change. Selection is only affected if it intersects the change (1GDY217).
+// int netNewLength = newLength - replacedLength;
+// int redrawStart = startOffset + newLength;
+// internalRedrawRange(redrawStart, sel.y + netNewLength - redrawStart);
+// });
+// setSelection(Arrays.stream(selection).map(sel -> {
+// if (sel.y <= startOffset) {
+// return sel;
+// } else if (sel.x == startOffset && sel.y == startOffset + replacedLength) {
+// return new Point(startOffset + newLength, startOffset + newLength);
+// } else if (sel.y > startOffset && sel.x < startOffset + replacedLength) {
+// // selection intersects replaced text. set caret behind text change
+// return new Point(startOffset + newLength, startOffset + newLength);
+// } else {
+// // move selection to keep same text selected
+// int x = sel.x + newLength - replacedLength;
+// int y = sel.x + newLength - replacedLength + (sel.y - sel.x);
+//
+// return new Point(x < 0 ? 0 : x, y < 0 ? 0 : y);
+// }
+// }).flatMapToInt(p -> IntStream.of(p.x, p.y - p.x))
+// .toArray(), true, false);
+// setCaretLocations();
+//}
+//
+///**
+// * The method accepts a StyledText and a callback which takes
+// * all the carets of the StyledText as the argument and executes it.
+// * The caret is refreshed after the execution of the callback.
+// *
+// * @param styledText the StyledText to get the carets from
+// * @param caretUpdater the callback which works with the carets
+// *
+// * @noreference This method is not intended to be referenced by clients.
+// */
+//public static void updateAndRefreshCarets(StyledText styledText, Consumer caretUpdater) {
+// caretUpdater.accept(styledText.getCaret());
+// caretUpdater.accept(styledText.defaultCaret);
+// for (Caret caret : styledText.carets) {
+// caretUpdater.accept(caret);
+// }
+// styledText.updateCaretVisibility();
+// styledText.setCaretLocations();
+//
+//}
+//
+//}
- // This needs to happen before new styles are applied
- int expectedBottom = 0;
- if (!isFixedLineHeight() && !reset) {
- int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
- int partialTopIndex = getPartialTopIndex();
- int partialBottomIndex = getPartialBottomIndex();
- if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
- expectedBottom = getLinePixel(lineEnd + 1);
- }
- }
- if (reset) {
- renderer.setStyleRanges(null, null);
- } else {
- renderer.updateRanges(start, length, length);
- }
- if (styles != null && styles.length > 0) {
- renderer.setStyleRanges(ranges, styles);
- }
+import org.eclipse.swt.widgets.*;
- // re-evaluate variable height with all styles (including new ones)
- hasStyleWithVariableHeight = false;
- for (StyleRange style : getStyleRanges(false)) {
- hasStyleWithVariableHeight = style.isVariableHeight();
- if (hasStyleWithVariableHeight) break;
- }
+// TODO (visjee) SWING
+public class StyledText extends Canvas {
- SortedSet modifiedLines = computeModifiedLines(formerRanges, formerStyles, ranges, styles);
- resetCache(modifiedLines);
- if (reset) {
- super.redraw();
- } else {
- int lineStart = content.getLineAtOffset(Math.min(start, rangeStart));
- int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
- int partialTopIndex = getPartialTopIndex();
- int partialBottomIndex = getPartialBottomIndex();
- if (!(lineStart > partialBottomIndex || lineEnd < partialTopIndex)) {
- int top = 0;
- int bottom = clientAreaHeight;
- if (partialTopIndex <= lineStart && lineStart <= partialBottomIndex) {
- top = Math.max(0, getLinePixel(lineStart));
- }
- if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
- bottom = getLinePixel(lineEnd + 1);
- }
- if (!(wasFixedLineHeight && isFixedLineHeight()) && bottom != expectedBottom) {
- bottom = clientAreaHeight;
- }
- super.redraw(0, top, clientAreaWidth, bottom - top, false);
- }
+ public StyledText(Composite parent, int style) {
+ super(parent, style);
}
- int oldColumnX = columnX;
- setCaretLocations();
- columnX = oldColumnX;
- doMouseLinkCursor();
-}
-/**
- *
- * @param referenceRanges former ranges, sorted by order and without overlapping, typically returned {@link #getRanges(int, int)}
- * @param newRanges former ranges, sorted by order and without overlapping
- */
-private SortedSet computeModifiedLines(int[] referenceRanges, StyleRange[] referenceStyles, int[] newRanges, StyleRange[] newStyles) {
- if (referenceStyles == null) {
- referenceStyles = new StyleRange[0];
- }
- if (referenceRanges == null) {
- referenceRanges = createRanges(referenceStyles);
- }
- if (newStyles == null) {
- newStyles = new StyleRange[0];
- }
- if (newRanges == null) {
- newRanges = createRanges(newStyles);
- }
- if (referenceRanges.length != 2 * referenceStyles.length) {
- throw new IllegalArgumentException();
+ public String getMarginColor() {
+ throw new UnsupportedOperationException("Not implemented yet");
}
- if (newRanges.length != 2 * newStyles.length) {
- throw new IllegalArgumentException();
- }
- SortedSet res = new TreeSet<>();
- int referenceRangeIndex = 0;
- int newRangeIndex = 0;
- StyleRange defaultStyle = new StyleRange();
- defaultStyle.foreground = this.foreground;
- defaultStyle.background = this.background;
- defaultStyle.font = getFont();
- int currentOffset = referenceRanges.length > 0 ? referenceRanges[0] : Integer.MAX_VALUE;
- if (newRanges.length > 0) {
- currentOffset = Math.min(currentOffset, newRanges[0]);
- }
- while (currentOffset < content.getCharCount() && (referenceRangeIndex < referenceStyles.length || newRangeIndex < newRanges.length)) {
- int nextMilestoneOffset = Integer.MAX_VALUE; // next new range start/end after current offset
-
- while (referenceRangeIndex < referenceStyles.length && endRangeOffset(referenceRanges, referenceRangeIndex) <= currentOffset) {
- referenceRangeIndex++;
- }
- StyleRange referenceStyleAtCurrentOffset = defaultStyle;
- if (isInRange(referenceRanges, referenceRangeIndex, currentOffset)) { // has styling
- referenceStyleAtCurrentOffset = referenceStyles[referenceRangeIndex];
- nextMilestoneOffset = endRangeOffset(referenceRanges, referenceRangeIndex);
- } else if (referenceRangeIndex < referenceStyles.length) { // no range, default styling
- nextMilestoneOffset = referenceRanges[2 * referenceRangeIndex]; // beginning of next range
- }
-
- while (newRangeIndex < newStyles.length && endRangeOffset(newRanges, newRangeIndex) <= currentOffset) {
- newRangeIndex++;
- }
- StyleRange newStyleAtCurrentOffset = defaultStyle;
- if (isInRange(newRanges, newRangeIndex, currentOffset)) {
- newStyleAtCurrentOffset = newStyles[newRangeIndex];
- nextMilestoneOffset = Math.min(nextMilestoneOffset, endRangeOffset(newRanges, newRangeIndex));
- } else if (newRangeIndex < newStyles.length) {
- nextMilestoneOffset = Math.min(nextMilestoneOffset, newRanges[2 * newRangeIndex]);
- }
- if (!referenceStyleAtCurrentOffset.similarTo(newStyleAtCurrentOffset)) {
- int fromLine = getLineAtOffset(currentOffset);
- int toLine = getLineAtOffset(nextMilestoneOffset - 1);
- for (int line = fromLine; line <= toLine; line++) {
- res.add(line);
- }
- currentOffset = toLine + 1 < getLineCount() ? getOffsetAtLine(toLine + 1) : content.getCharCount();
- } else {
- currentOffset = nextMilestoneOffset;
- }
+ public String getTopMargin() {
+ throw new UnsupportedOperationException("Not implemented yet");
}
- return res;
-}
-private int[] createRanges(StyleRange[] referenceStyles) {
- int[] referenceRanges;
- referenceRanges = new int[2 * referenceStyles.length];
- for (int i = 0; i < referenceStyles.length; i++) {
- referenceRanges[2 * i] = referenceStyles[i].start;
- referenceRanges[2 * i + 1] = referenceStyles[i].length;
- }
- return referenceRanges;
-}
-private boolean isInRange(int[] ranges, int styleIndex, int offset) {
- if (ranges == null || ranges.length == 0 || styleIndex < 0 || 2 * styleIndex + 1 > ranges.length) {
- return false;
+ public String getRightMargin() {
+ throw new UnsupportedOperationException("Not implemented yet");
}
- int start = ranges[2 * styleIndex];
- int length = ranges[2 * styleIndex + 1];
- return offset >= start && offset < start + length;
-}
-/**
- * The offset on which the range ends (excluded)
- */
-private int endRangeOffset(int[] ranges, int styleIndex) {
- if (styleIndex < 0 || 2 * styleIndex > ranges.length) {
- throw new IllegalArgumentException();
+ public String getBottomMargin() {
+ throw new UnsupportedOperationException("Not implemented yet");
}
- int start = ranges[2 * styleIndex];
- int length = ranges[2 * styleIndex + 1];
- return start + length;
-}
-
-/**
- * Sets styles to be used for rendering the widget content. All styles
- * in the widget will be replaced with the given set of styles.
- *
- * Note: Because a StyleRange includes the start and length, the
- * same instance cannot occur multiple times in the array of styles.
- * If the same style attributes, such as font and color, occur in
- * multiple StyleRanges, setStyleRanges(int[], StyleRange[])
- * can be used to share styles and reduce memory usage.
- *
- * Should not be called if a LineStyleListener has been set since the
- * listener maintains the styles.
- *
- *
- * @param ranges StyleRange objects containing the style information.
- * The ranges should not overlap. The style rendering is undefined if
- * the ranges do overlap. Must not be null. The styles need to be in order.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when the list of ranges is null
- *
ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see #setTabStops(int[])
- */
-public void setTabs(int tabs) {
- checkWidget();
- tabLength = tabs;
- renderer.setFont(null, tabs);
- resetCache(0, content.getLineCount());
- setCaretLocations();
- super.redraw();
-}
-/**
- * Sets the receiver's tab list. Each value in the tab list specifies
- * the space in points from the origin of the document to the respective
- * tab stop. The last tab stop width is repeated continuously.
- *
- * @param tabs the new tab list (or null)
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_INVALID_ARGUMENT - if a tab stop is negative or less than the previous stop in the list
- *
- *
- * @see StyledText#getTabStops()
- *
- * @since 3.6
- */
-public void setTabStops(int [] tabs) {
- checkWidget();
- if (tabs != null) {
- int pos = 0;
- int[] newTabs = new int[tabs.length];
- for (int i = 0; i < tabs.length; i++) {
- if (tabs[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- newTabs[i] = pos = tabs[i];
- }
- this.tabs = newTabs;
- } else {
- this.tabs = null;
+ public String getLeftMargin() {
+ throw new UnsupportedOperationException("Not implemented yet");
}
- resetCache(0, content.getLineCount());
- setCaretLocations();
- super.redraw();
-}
-/**
- * Sets the widget content.
- * If the widget has the SWT.SINGLE style and "text" contains more than
- * one line, only the first line is rendered but the text is stored
- * unchanged. A subsequent call to getText will return the same text
- * that was set.
- *
- * Note: Only a single line of text should be set when the SWT.SINGLE
- * style is used.
- *
- *
- * @param text new widget content. Replaces existing content. Line styles
- * that were set using StyledText API are discarded. The
- * current selection is also discarded.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_NULL_ARGUMENT when string is null
- *
- */
-public void setText(String text) {
- checkWidget();
- if (text == null) {
- SWT.error(SWT.ERROR_NULL_ARGUMENT);
- }
- Event event = new Event();
- event.start = 0;
- event.end = getCharCount();
- event.text = text;
- event.doit = true;
- notifyListeners(SWT.Verify, event);
- if (event.doit) {
- StyledTextEvent styledTextEvent = null;
- if (isListening(ST.ExtendedModify)) {
- styledTextEvent = new StyledTextEvent(content);
- styledTextEvent.start = event.start;
- styledTextEvent.end = event.start + event.text.length();
- styledTextEvent.text = content.getTextRange(event.start, event.end - event.start);
- }
- content.setText(event.text);
- notifyListeners(SWT.Modify, event);
- if (styledTextEvent != null) {
- notifyListeners(ST.ExtendedModify, styledTextEvent);
- }
+ public int getIndent() {
+ throw new UnsupportedOperationException("Not implemented yet");
}
-}
-/**
- * Sets the base text direction (a.k.a. "paragraph direction") of the receiver,
- * which must be one of the constants SWT.LEFT_TO_RIGHT or
- * SWT.RIGHT_TO_LEFT.
- *
- * setOrientation would override this value with the text direction
- * that is consistent with the new orientation.
- *
- *
- * Warning: This API is currently only implemented on Windows.
- * It doesn't set the base text direction on GTK and Cocoa.
- *
- *
- * @param textDirection the base text direction style
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @see SWT#FLIP_TEXT_DIRECTION
- */
-@Override
-public void setTextDirection(int textDirection) {
- checkWidget();
- int oldStyle = getStyle();
- super.setTextDirection(textDirection);
- if (isAutoDirection () || oldStyle != getStyle()) {
- resetBidiData();
+ public boolean getWordWrap() {
+ throw new UnsupportedOperationException("Not implemented yet");
}
-}
-/**
- * Sets the text limit to the specified number of characters.
- *
- * The text limit specifies the amount of text that
- * the user can type into the widget.
- *
- *
- * @param limit the new text limit.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- * @exception IllegalArgumentException
- *
ERROR_CANNOT_BE_ZERO when limit is 0
- *
- */
-public void setTextLimit(int limit) {
- checkWidget();
- if (limit == 0) {
- SWT.error(SWT.ERROR_CANNOT_BE_ZERO);
- }
- textLimit = limit;
-}
-/**
- * Sets the top index. Do nothing if there is no text set.
- *
- * The top index is the index of the line that is currently at the top
- * of the widget. The top index changes when the widget is scrolled.
- * Indexing starts from zero.
- * Note: The top index is reset to 0 when new text is set in the widget.
- *
- *
- * @param topIndex new top index. Must be between 0 and
- * getLineCount() - fully visible lines per page. If no lines are fully
- * visible the maximum value is getLineCount() - 1. An out of range
- * index will be adjusted accordingly.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- *
- * @since 3.5
- */
-public void setTopMargin (int topMargin) {
- checkWidget();
- setMargins(getLeftMargin(), topMargin, rightMargin, bottomMargin);
-}
-/**
- * Sets the top SWT logical point offset. Do nothing if there is no text set.
- *
- * The top point offset is the vertical SWT logical point offset of the widget. The
- * widget is scrolled so that the given SWT logical point position is at the top.
- * The top index is adjusted to the corresponding top line.
- * Note: The top point is reset to 0 when new text is set in the widget.
- *
- *
- * @param pixel new top point offset. Must be between 0 and
- * (getLineCount() - visible lines per page) / getLineHeight()). An out
- * of range offset will be adjusted accordingly.
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- * This overrides the creation style bit SWT.WRAP.
- *
- *
- * @param wrap true=widget wraps lines, false=widget does not wrap lines
- * @since 2.0
- */
-public void setWordWrap(boolean wrap) {
- checkWidget();
- if ((getStyle() & SWT.SINGLE) != 0) return;
- if (wordWrap == wrap) return;
- if (wordWrap && blockSelection) setBlockSelection(false);
- wordWrap = wrap;
- resetCache(0, content.getLineCount());
- horizontalScrollOffset = 0;
- ScrollBar horizontalBar = getHorizontalBar();
- if (horizontalBar != null) {
- horizontalBar.setVisible(!wordWrap);
- }
- setScrollBars(true);
- setCaretLocations();
- super.redraw();
-}
-/**
- * Sets the wrap line indentation of the widget.
- *
- * It is the amount of blank space, in points, at the beginning of each wrapped line.
- * When a line wraps in several lines all the lines but the first one is indented
- * by this amount.
- *
- *
- * @param wrapIndent the new wrap indent
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- * The end of the selection will be scrolled into view.
- * Note that if a right-to-left selection exists, the end of the selection is
- * the visual beginning of the selection (i.e., where the caret is located).
- *
- *
- * @exception SWTException
- *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
- *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
- *
- */
-public void showSelection() {
- checkWidget();
- // is selection from right-to-left?
- boolean rightToLeft = caretOffsets[0] == selection[0].x;
- int startOffset, endOffset;
- if (rightToLeft) {
- startOffset = selection[0].y;
- endOffset = selection[0].x;
- } else {
- startOffset = selection[0].x;
- endOffset = selection[0].y;
- }
-
- Rectangle startBounds = getBoundsAtOffset(startOffset);
- Rectangle endBounds = getBoundsAtOffset(endOffset);
- // can the selection be fully displayed within the widget's visible width?
- int w = clientAreaWidth - leftMargin - rightMargin;
- boolean selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w;
- if (selectionFits) {
- // show as much of the selection as possible by first showing
- // the start of the selection
- if (showLocation(startBounds, false)) {
- // endX value could change if showing startX caused a scroll to occur
- endBounds = getBoundsAtOffset(endOffset);
- }
- // the character at endOffset is not part of the selection
- endBounds.width = endOffset == caretOffsets[0] ? getCaretWidth() : 0;
- showLocation(endBounds, false);
- } else {
- // just show the end of the selection since the selection start
- // will not be visible
- showLocation(endBounds, true);
+ public boolean getJustify() {
+ throw new UnsupportedOperationException("Not implemented yet");
}
-}
-void updateCaretVisibility() {
- Caret caret = getCaret();
- if (caret != null) {
- if (carets == null || carets.length == 0) {
- carets = new Caret[] { caret };
- }
- if (blockSelection && blockXLocation != -1) {
- Arrays.stream(carets).forEach(c -> c.setVisible(false));
- } else {
- Arrays.stream(carets).forEach(c -> {
- Point location = c.getLocation();
- Point size = c.getSize();
- boolean visible =
- topMargin <= location.y + size.y && location.y <= clientAreaHeight - bottomMargin &&
- leftMargin <= location.x + size.x && location.x <= clientAreaWidth - rightMargin;
- c.setVisible(visible);
- });
- }
- }
-}
-/**
- * Updates the selection and caret position depending on the text change.
- *
- * If the selection intersects with the replaced text, the selection is
- * reset and the caret moved to the end of the new text.
- * If the selection is behind the replaced text it is moved so that the
- * same text remains selected. If the selection is before the replaced text
- * it is left unchanged.
- *
- *
- * @param startOffset offset of the text change
- * @param replacedLength length of text being replaced
- * @param newLength length of new text
- */
-void updateSelection(int startOffset, int replacedLength, int newLength) {
- if (selection[selection.length - 1].y <= startOffset) {
- // selection ends before text change
- if (isWordWrap()) setCaretLocations();
- return;
- }
- // clear selection fragment before text change
- Arrays.stream(selection)
- .filter(sel -> sel.y > startOffset)
- .filter(sel -> sel.x < startOffset)
- .forEach(sel -> internalRedrawRange(sel.x, startOffset - sel.x));
- Arrays.stream(selection)
- .filter(sel -> sel.y > startOffset)
- .filter(sel -> sel.y > startOffset + replacedLength && sel.x < startOffset + replacedLength)
- .forEach(sel -> {
- // clear selection fragment after text change.
- // do this only when the selection is actually affected by the
- // change. Selection is only affected if it intersects the change (1GDY217).
- int netNewLength = newLength - replacedLength;
- int redrawStart = startOffset + newLength;
- internalRedrawRange(redrawStart, sel.y + netNewLength - redrawStart);
- });
- setSelection(Arrays.stream(selection).map(sel -> {
- if (sel.y <= startOffset) {
- return sel;
- } else if (sel.x == startOffset && sel.y == startOffset + replacedLength) {
- return new Point(startOffset + newLength, startOffset + newLength);
- } else if (sel.y > startOffset && sel.x < startOffset + replacedLength) {
- // selection intersects replaced text. set caret behind text change
- return new Point(startOffset + newLength, startOffset + newLength);
- } else {
- // move selection to keep same text selected
- int x = sel.x + newLength - replacedLength;
- int y = sel.x + newLength - replacedLength + (sel.y - sel.x);
-
- return new Point(x < 0 ? 0 : x, y < 0 ? 0 : y);
- }
- }).flatMapToInt(p -> IntStream.of(p.x, p.y - p.x))
- .toArray(), true, false);
- setCaretLocations();
-}
-/**
- * The method accepts a StyledText and a callback which takes
- * all the carets of the StyledText as the argument and executes it.
- * The caret is refreshed after the execution of the callback.
- *
- * @param styledText the StyledText to get the carets from
- * @param caretUpdater the callback which works with the carets
- *
- * @noreference This method is not intended to be referenced by clients.
- */
-public static void updateAndRefreshCarets(StyledText styledText, Consumer caretUpdater) {
- caretUpdater.accept(styledText.getCaret());
- caretUpdater.accept(styledText.defaultCaret);
- for (Caret caret : styledText.carets) {
- caretUpdater.accept(caret);
+ public int getTextDirection() {
+ throw new UnsupportedOperationException("Not implemented yet");
}
- styledText.updateCaretVisibility();
- styledText.setCaretLocations();
-
-}
-
-}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java
index 675cad903a8..bff9e09edb0 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java
@@ -13,9 +13,7 @@
*******************************************************************************/
package org.eclipse.swt.custom;
-import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
-import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
@@ -48,198 +46,203 @@
* @since 3.3
*/
public class StyledTextDropTargetEffect extends DropTargetEffect {
- static final int CARET_WIDTH = 2;
- static final int SCROLL_HYSTERESIS = 100; // milli seconds
- static final int SCROLL_TOLERANCE = 20; // pixels
- int currentOffset = -1;
- long scrollBeginTime;
- int scrollX = -1, scrollY = -1;
- Listener paintListener;
-
- /**
- * Creates a new StyledTextDropTargetEffect to handle the drag under effect on the specified
- * StyledText.
- *
- * @param styledText the StyledText over which the user positions the cursor to drop the data
- */
- public StyledTextDropTargetEffect(StyledText styledText) {
- super(styledText);
- paintListener = event -> {
- if (currentOffset != -1) {
- StyledText text = (StyledText) getControl();
- Point position = text.getLocationAtOffset(currentOffset);
- int height = text.getLineHeight(currentOffset);
- event.gc.setBackground(event.display.getSystemColor (SWT.COLOR_BLACK));
- event.gc.fillRectangle(position.x, position.y, CARET_WIDTH, height);
- }
- };
- }
-
- /**
- * This implementation of dragEnter provides a default drag under effect
- * for the feedback specified in event.feedback.
- *
- * For additional information see DropTargetAdapter.dragEnter.
- *
- * Subclasses that override this method should call super.dragEnter(event)
- * to get the default drag under effect implementation.
- *
- * @param event the information associated with the drag start event
- *
- * @see DropTargetAdapter
- * @see DropTargetEvent
- */
- @Override
- public void dragEnter(DropTargetEvent event) {
- currentOffset = -1;
- scrollBeginTime = 0;
- scrollX = -1;
- scrollY = -1;
- getControl().removeListener(SWT.Paint, paintListener);
- getControl().addListener (SWT.Paint, paintListener);
- }
-
- /**
- * This implementation of dragLeave provides a default drag under effect
- * for the feedback specified in event.feedback.
- *
- * For additional information see DropTargetAdapter.dragLeave.
- *
- * Subclasses that override this method should call super.dragLeave(event)
- * to get the default drag under effect implementation.
- *
- * @param event the information associated with the drag leave event
- *
- * @see DropTargetAdapter
- * @see DropTargetEvent
- */
- @Override
- public void dragLeave(DropTargetEvent event) {
- StyledText text = (StyledText) getControl();
- if (currentOffset != -1) {
- refreshCaret(text, currentOffset, -1);
- }
- text.removeListener(SWT.Paint, paintListener);
- scrollBeginTime = 0;
- scrollX = -1;
- scrollY = -1;
- }
-
- /**
- * This implementation of dragOver provides a default drag under effect
- * for the feedback specified in event.feedback.
- *
- * For additional information see DropTargetAdapter.dragOver.
- *
- * Subclasses that override this method should call super.dragOver(event)
- * to get the default drag under effect implementation.
- *
- * @param event the information associated with the drag over event
- *
- * @see DropTargetAdapter
- * @see DropTargetEvent
- * @see DND#FEEDBACK_SELECT
- * @see DND#FEEDBACK_SCROLL
- */
- @Override
- public void dragOver(DropTargetEvent event) {
- int effect = event.feedback;
- StyledText text = (StyledText) getControl();
-
- Point pt = text.getDisplay().map(null, text, event.x, event.y);
- if ((effect & DND.FEEDBACK_SCROLL) == 0) {
- scrollBeginTime = 0;
- scrollX = scrollY = -1;
- } else {
- if (text.getCharCount() == 0) {
- scrollBeginTime = 0;
- scrollX = scrollY = -1;
- } else {
- if (scrollX != -1 && scrollY != -1 && scrollBeginTime != 0 &&
- (pt.x >= scrollX && pt.x <= (scrollX + SCROLL_TOLERANCE) ||
- pt.y >= scrollY && pt.y <= (scrollY + SCROLL_TOLERANCE))) {
- if (System.currentTimeMillis() >= scrollBeginTime) {
- Rectangle area = text.getClientArea();
- GC gc = new GC(text);
- FontMetrics fm = gc.getFontMetrics();
- gc.dispose();
- double charWidth = fm.getAverageCharacterWidth();
- int scrollAmount = (int) (10*charWidth);
- if (pt.x < area.x + 3*charWidth) {
- int leftPixel = text.getHorizontalPixel();
- text.setHorizontalPixel(leftPixel - scrollAmount);
- }
- if (pt.x > area.width - 3*charWidth) {
- int leftPixel = text.getHorizontalPixel();
- text.setHorizontalPixel(leftPixel + scrollAmount);
- }
- int lineHeight = text.getLineHeight();
- if (pt.y < area.y + lineHeight) {
- int topPixel = text.getTopPixel();
- text.setTopPixel(topPixel - lineHeight);
- }
- if (pt.y > area.height - lineHeight) {
- int topPixel = text.getTopPixel();
- text.setTopPixel(topPixel + lineHeight);
- }
- scrollBeginTime = 0;
- scrollX = scrollY = -1;
- }
- } else {
- scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
- scrollX = pt.x;
- scrollY = pt.y;
- }
- }
- }
-
- if ((effect & DND.FEEDBACK_SELECT) != 0) {
- int[] trailing = new int [1];
- int newOffset = text.getOffsetAtPoint(pt.x, pt.y, trailing, false);
- newOffset += trailing [0];
- if (newOffset != currentOffset) {
- refreshCaret(text, currentOffset, newOffset);
- currentOffset = newOffset;
- }
- }
- }
-
- void refreshCaret(StyledText text, int oldOffset, int newOffset) {
- if (oldOffset != newOffset) {
- if (oldOffset != -1) {
- Point oldPos = text.getLocationAtOffset(oldOffset);
- int oldHeight = text.getLineHeight(oldOffset);
- text.redraw (oldPos.x, oldPos.y, CARET_WIDTH, oldHeight, false);
- }
- if (newOffset != -1) {
- Point newPos = text.getLocationAtOffset(newOffset);
- int newHeight = text.getLineHeight(newOffset);
- text.redraw (newPos.x, newPos.y, CARET_WIDTH, newHeight, false);
- }
- }
- }
-
- /**
- * This implementation of dropAccept provides a default drag under effect
- * for the feedback specified in event.feedback.
- *
- * For additional information see DropTargetAdapter.dropAccept.
- *
- * Subclasses that override this method should call super.dropAccept(event)
- * to get the default drag under effect implementation.
- *
- * @param event the information associated with the drop accept event
- *
- * @see DropTargetAdapter
- * @see DropTargetEvent
- */
- @Override
- public void dropAccept(DropTargetEvent event) {
- if (currentOffset != -1) {
- StyledText text = (StyledText) getControl();
- text.setSelection(currentOffset);
- currentOffset = -1;
- }
+ public StyledTextDropTargetEffect(Control control) {
+ super(control);
+ // TODO Auto-generated constructor stub
}
+// static final int CARET_WIDTH = 2;
+// static final int SCROLL_HYSTERESIS = 100; // milli seconds
+// static final int SCROLL_TOLERANCE = 20; // pixels
+//
+// int currentOffset = -1;
+// long scrollBeginTime;
+// int scrollX = -1, scrollY = -1;
+// Listener paintListener;
+//
+// /**
+// * Creates a new StyledTextDropTargetEffect to handle the drag under effect on the specified
+// * StyledText.
+// *
+// * @param styledText the StyledText over which the user positions the cursor to drop the data
+// */
+// public StyledTextDropTargetEffect(StyledText styledText) {
+// super(styledText);
+// paintListener = event -> {
+// if (currentOffset != -1) {
+// StyledText text = (StyledText) getControl();
+// Point position = text.getLocationAtOffset(currentOffset);
+// int height = text.getLineHeight(currentOffset);
+// event.gc.setBackground(event.display.getSystemColor (SWT.COLOR_BLACK));
+// event.gc.fillRectangle(position.x, position.y, CARET_WIDTH, height);
+// }
+// };
+// }
+//
+// /**
+// * This implementation of dragEnter provides a default drag under effect
+// * for the feedback specified in event.feedback.
+// *
+// * For additional information see DropTargetAdapter.dragEnter.
+// *
+// * Subclasses that override this method should call super.dragEnter(event)
+// * to get the default drag under effect implementation.
+// *
+// * @param event the information associated with the drag start event
+// *
+// * @see DropTargetAdapter
+// * @see DropTargetEvent
+// */
+// @Override
+// public void dragEnter(DropTargetEvent event) {
+// currentOffset = -1;
+// scrollBeginTime = 0;
+// scrollX = -1;
+// scrollY = -1;
+// getControl().removeListener(SWT.Paint, paintListener);
+// getControl().addListener (SWT.Paint, paintListener);
+// }
+//
+// /**
+// * This implementation of dragLeave provides a default drag under effect
+// * for the feedback specified in event.feedback.
+// *
+// * For additional information see DropTargetAdapter.dragLeave.
+// *
+// * Subclasses that override this method should call super.dragLeave(event)
+// * to get the default drag under effect implementation.
+// *
+// * @param event the information associated with the drag leave event
+// *
+// * @see DropTargetAdapter
+// * @see DropTargetEvent
+// */
+// @Override
+// public void dragLeave(DropTargetEvent event) {
+// StyledText text = (StyledText) getControl();
+// if (currentOffset != -1) {
+// refreshCaret(text, currentOffset, -1);
+// }
+// text.removeListener(SWT.Paint, paintListener);
+// scrollBeginTime = 0;
+// scrollX = -1;
+// scrollY = -1;
+// }
+//
+// /**
+// * This implementation of dragOver provides a default drag under effect
+// * for the feedback specified in event.feedback.
+// *
+// * For additional information see DropTargetAdapter.dragOver.
+// *
+// * Subclasses that override this method should call super.dragOver(event)
+// * to get the default drag under effect implementation.
+// *
+// * @param event the information associated with the drag over event
+// *
+// * @see DropTargetAdapter
+// * @see DropTargetEvent
+// * @see DND#FEEDBACK_SELECT
+// * @see DND#FEEDBACK_SCROLL
+// */
+// @Override
+// public void dragOver(DropTargetEvent event) {
+// int effect = event.feedback;
+// StyledText text = (StyledText) getControl();
+//
+// Point pt = text.getDisplay().map(null, text, event.x, event.y);
+// if ((effect & DND.FEEDBACK_SCROLL) == 0) {
+// scrollBeginTime = 0;
+// scrollX = scrollY = -1;
+// } else {
+// if (text.getCharCount() == 0) {
+// scrollBeginTime = 0;
+// scrollX = scrollY = -1;
+// } else {
+// if (scrollX != -1 && scrollY != -1 && scrollBeginTime != 0 &&
+// (pt.x >= scrollX && pt.x <= (scrollX + SCROLL_TOLERANCE) ||
+// pt.y >= scrollY && pt.y <= (scrollY + SCROLL_TOLERANCE))) {
+// if (System.currentTimeMillis() >= scrollBeginTime) {
+// Rectangle area = text.getClientArea();
+// GC gc = new GC(text);
+// FontMetrics fm = gc.getFontMetrics();
+// gc.dispose();
+// double charWidth = fm.getAverageCharacterWidth();
+// int scrollAmount = (int) (10*charWidth);
+// if (pt.x < area.x + 3*charWidth) {
+// int leftPixel = text.getHorizontalPixel();
+// text.setHorizontalPixel(leftPixel - scrollAmount);
+// }
+// if (pt.x > area.width - 3*charWidth) {
+// int leftPixel = text.getHorizontalPixel();
+// text.setHorizontalPixel(leftPixel + scrollAmount);
+// }
+// int lineHeight = text.getLineHeight();
+// if (pt.y < area.y + lineHeight) {
+// int topPixel = text.getTopPixel();
+// text.setTopPixel(topPixel - lineHeight);
+// }
+// if (pt.y > area.height - lineHeight) {
+// int topPixel = text.getTopPixel();
+// text.setTopPixel(topPixel + lineHeight);
+// }
+// scrollBeginTime = 0;
+// scrollX = scrollY = -1;
+// }
+// } else {
+// scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
+// scrollX = pt.x;
+// scrollY = pt.y;
+// }
+// }
+// }
+//
+// if ((effect & DND.FEEDBACK_SELECT) != 0) {
+// int[] trailing = new int [1];
+// int newOffset = text.getOffsetAtPoint(pt.x, pt.y, trailing, false);
+// newOffset += trailing [0];
+// if (newOffset != currentOffset) {
+// refreshCaret(text, currentOffset, newOffset);
+// currentOffset = newOffset;
+// }
+// }
+// }
+//
+// void refreshCaret(StyledText text, int oldOffset, int newOffset) {
+// if (oldOffset != newOffset) {
+// if (oldOffset != -1) {
+// Point oldPos = text.getLocationAtOffset(oldOffset);
+// int oldHeight = text.getLineHeight(oldOffset);
+// text.redraw (oldPos.x, oldPos.y, CARET_WIDTH, oldHeight, false);
+// }
+// if (newOffset != -1) {
+// Point newPos = text.getLocationAtOffset(newOffset);
+// int newHeight = text.getLineHeight(newOffset);
+// text.redraw (newPos.x, newPos.y, CARET_WIDTH, newHeight, false);
+// }
+// }
+// }
+//
+// /**
+// * This implementation of dropAccept provides a default drag under effect
+// * for the feedback specified in event.feedback.
+// *
+// * For additional information see DropTargetAdapter.dropAccept.
+// *
+// * Subclasses that override this method should call super.dropAccept(event)
+// * to get the default drag under effect implementation.
+// *
+// * @param event the information associated with the drop accept event
+// *
+// * @see DropTargetAdapter
+// * @see DropTargetEvent
+// */
+// @Override
+// public void dropAccept(DropTargetEvent event) {
+// if (currentOffset != -1) {
+// StyledText text = (StyledText) getControl();
+// text.setSelection(currentOffset);
+// currentOffset = -1;
+// }
+// }
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java
index fa0281c2b31..53d5ac9d5c0 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java
@@ -15,2040 +15,2032 @@
*******************************************************************************/
package org.eclipse.swt.custom;
-
-import java.util.*;
-import java.util.List;
-
-import org.eclipse.swt.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
/**
* A StyledTextRenderer renders the content of a StyledText widget.
* This class can be used to render to the display or to a printer.
*/
class StyledTextRenderer {
- Device device;
- StyledText styledText;
- StyledTextContent content;
-
- /* Custom line spacing */
- StyledTextLineSpacingProvider lineSpacingProvider;
- boolean lineSpacingComputing;
-
- /* Custom line metrics */
- private FontMetrics fixedLineMetrics;
-
- /* Font info */
- Font regularFont, boldFont, italicFont, boldItalicFont;
- int tabWidth;
- int ascent, descent;
- int averageCharWidth;
- int tabLength; //tab length in spaces
-
- /* Line data */
- int topIndex = -1;
- TextLayout[] layouts;
- int lineCount;
- LineSizeInfo[] lineSizes;
- LineInfo[] lines;
- int maxWidth;
- int maxWidthLineIndex;
- float averageLineHeight;
- int linesInAverageLineHeight;
- boolean idleRunning;
-
- /* Bullet */
- Bullet[] bullets;
- int[] bulletsIndices;
- int[] redrawLines;
-
- /* Style data */
- int[] ranges;
- int styleCount;
- StyleRange[] styles;
- StyleRange[] stylesSet;
- int stylesSetCount = 0;
- boolean hasLinks, fixedPitch;
- final static int BULLET_MARGIN = 8;
-
- final static boolean COMPACT_STYLES = true;
- final static boolean MERGE_STYLES = true;
-
- final static int GROW = 32;
- final static int IDLE_TIME = 50;
- final static int CACHE_SIZE = 300;
-
- final static int BACKGROUND = 1 << 0;
- final static int ALIGNMENT = 1 << 1;
- final static int INDENT = 1 << 2;
- final static int JUSTIFY = 1 << 3;
- final static int SEGMENTS = 1 << 5;
- final static int TABSTOPS = 1 << 6;
- final static int WRAP_INDENT = 1 << 7;
- final static int SEGMENT_CHARS = 1 << 8;
- final static int VERTICAL_INDENT = 1 << 9;
-
- static class LineSizeInfo {
-
- private static final int RESETED_SIZE = -1;
-
- /* Line size */
- int height;
- int width;
-
- public LineSizeInfo() {
- resetSize();
- }
-
- /**
- * Reset the line size.
- */
- void resetSize() {
- height = RESETED_SIZE;
- width = RESETED_SIZE;
- }
-
- /**
- * Returns true if the TextLayout get from the layout pool can be directly used
- * or must be refreshed with styles.
- *
- * @return true if the TextLayout get from the layout pool can be directly used
- * or must be refreshed with styles.
- */
- boolean canLayout() {
- return !needsRecalculateWidth();
- }
-
- /**
- * Returns true if it needs to recalculate the line size and false
- * otherwise.
- *
- * @return true if it needs to recalculate the line size and false
- * otherwise.
- */
- boolean needsRecalculateSize() {
- return needsRecalculateWidth() || needsRecalculateHeight();
- }
-
- /**
- * Returns true if it needs to recalculate the line width and false
- * otherwise.
- *
- * @return true if it needs to recalculate the line width and false
- * otherwise.
- */
- boolean needsRecalculateWidth() {
- return width == RESETED_SIZE;
- }
-
- /**
- * Returns true if it needs to recalculate the line height and false
- * otherwise.
- *
- * @return true if it needs to recalculate the line height and false
- * otherwise.
- */
- boolean needsRecalculateHeight() {
- return height == RESETED_SIZE;
- }
- }
-
- static class LineInfo {
- int flags;
- Color background;
- int alignment;
- int indent;
- int wrapIndent;
- boolean justify;
- int[] segments;
- char[] segmentsChars;
- int[] tabStops;
- int verticalIndent;
-
- public LineInfo() {
- }
- public LineInfo(LineInfo info) {
- if (info != null) {
- flags = info.flags;
- background = info.background;
- alignment = info.alignment;
- indent = info.indent;
- wrapIndent = info.wrapIndent;
- justify = info.justify;
- segments = info.segments;
- segmentsChars = info.segmentsChars;
- tabStops = info.tabStops;
- verticalIndent = info.verticalIndent;
- }
- }
- }
-
- private record LineDrawInfo(int index, TextLayout layout, String text, int offset, int height) {
-
- }
-
- static int cap (TextLayout layout, int offset) {
- if (layout == null) return offset;
- return Math.min (layout.getText().length() -1, Math.max (0, offset));
- }
-
-StyledTextRenderer(Device device, StyledText styledText) {
- this.device = device;
- this.styledText = styledText;
-}
-int addMerge(int[] mergeRanges, StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) {
- int rangeCount = styleCount << 1;
- StyleRange endStyle = null;
- int endStart = 0, endLength = 0;
- if (modifyEnd < rangeCount) {
- endStyle = styles[modifyEnd >> 1];
- endStart = ranges[modifyEnd];
- endLength = ranges[modifyEnd + 1];
- }
- int grow = mergeCount - (modifyEnd - modifyStart);
- if (rangeCount + grow >= ranges.length) {
- int[] tmpRanges = new int[ranges.length + grow + (GROW << 1)];
- System.arraycopy(ranges, 0, tmpRanges, 0, modifyStart);
- StyleRange[] tmpStyles = new StyleRange[styles.length + (grow >> 1) + GROW];
- System.arraycopy(styles, 0, tmpStyles, 0, modifyStart >> 1);
- if (rangeCount > modifyEnd) {
- System.arraycopy(ranges, modifyEnd, tmpRanges, modifyStart + mergeCount, rangeCount - modifyEnd);
- System.arraycopy(styles, modifyEnd >> 1, tmpStyles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1));
- }
- ranges = tmpRanges;
- styles = tmpStyles;
- } else {
- if (rangeCount > modifyEnd) {
- System.arraycopy(ranges, modifyEnd, ranges, modifyStart + mergeCount, rangeCount - modifyEnd);
- System.arraycopy(styles, modifyEnd >> 1, styles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1));
- }
- }
- if (MERGE_STYLES) {
- int j = modifyStart;
- for (int i = 0; i < mergeCount; i += 2) {
- if (j > 0 && ranges[j - 2] + ranges[j - 1] == mergeRanges[i] && mergeStyles[i >> 1].similarTo(styles[(j - 2) >> 1])) {
- ranges[j - 1] += mergeRanges[i + 1];
- } else {
- styles[j >> 1] = mergeStyles[i >> 1];
- ranges[j++] = mergeRanges[i];
- ranges[j++] = mergeRanges[i + 1];
- }
- }
- if (endStyle != null && ranges[j - 2] + ranges[j - 1] == endStart && endStyle.similarTo(styles[(j - 2) >> 1])) {
- ranges[j - 1] += endLength;
- modifyEnd += 2;
- mergeCount += 2;
- }
- if (rangeCount > modifyEnd) {
- System.arraycopy(ranges, modifyStart + mergeCount, ranges, j, rangeCount - modifyEnd);
- System.arraycopy(styles, (modifyStart + mergeCount) >> 1, styles, j >> 1, styleCount - (modifyEnd >> 1));
- }
- grow = (j - modifyStart) - (modifyEnd - modifyStart);
- } else {
- System.arraycopy(mergeRanges, 0, ranges, modifyStart, mergeCount);
- System.arraycopy(mergeStyles, 0, styles, modifyStart >> 1, mergeCount >> 1);
- }
- styleCount += grow >> 1;
- return grow;
-}
-int addMerge(StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) {
- int grow = mergeCount - (modifyEnd - modifyStart);
- StyleRange endStyle = null;
- if (modifyEnd < styleCount) endStyle = styles[modifyEnd];
- if (styleCount + grow >= styles.length) {
- StyleRange[] tmpStyles = new StyleRange[styles.length + grow + GROW];
- System.arraycopy(styles, 0, tmpStyles, 0, modifyStart);
- if (styleCount > modifyEnd) {
- System.arraycopy(styles, modifyEnd, tmpStyles, modifyStart + mergeCount, styleCount - modifyEnd);
- }
- styles = tmpStyles;
- } else {
- if (styleCount > modifyEnd) {
- System.arraycopy(styles, modifyEnd, styles, modifyStart + mergeCount, styleCount - modifyEnd);
- }
- }
- if (MERGE_STYLES) {
- int j = modifyStart;
- for (int i = 0; i < mergeCount; i++) {
- StyleRange newStyle = mergeStyles[i], style;
- if (j > 0 && (style = styles[j - 1]).start + style.length == newStyle.start && newStyle.similarTo(style)) {
- style.length += newStyle.length;
- } else {
- styles[j++] = newStyle;
- }
- }
- StyleRange style = styles[j - 1];
- if (endStyle != null && style.start + style.length == endStyle.start && endStyle.similarTo(style)) {
- style.length += endStyle.length;
- modifyEnd++;
- mergeCount++;
- }
- if (styleCount > modifyEnd) {
- System.arraycopy(styles, modifyStart + mergeCount, styles, j, styleCount - modifyEnd);
- }
- grow = (j - modifyStart) - (modifyEnd - modifyStart);
- } else {
- System.arraycopy(mergeStyles, 0, styles, modifyStart, mergeCount);
- }
- styleCount += grow;
- return grow;
-}
-void calculate(int startLine, int lineCount) {
- int endLine = startLine + lineCount;
- if (startLine < 0 || endLine > lineSizes.length) {
- return;
- }
- int hTrim = styledText.leftMargin + styledText.rightMargin + styledText.getCaretWidth();
- for (int i = startLine; i < endLine; i++) {
- LineSizeInfo line = getLineSize(i);
- if (line.needsRecalculateSize()) {
- TextLayout layout = getTextLayout(i);
- Rectangle rect = layout.getBounds();
- line.width = rect.width + hTrim;
- line.height = rect.height;
- averageLineHeight += (line.height - Math.round(averageLineHeight)) / ++linesInAverageLineHeight;
- disposeTextLayout(layout);
- }
- if (line.width > maxWidth) {
- maxWidth = line.width;
- maxWidthLineIndex = i;
- }
- }
-}
-LineSizeInfo getLineSize(int i) {
- if (lineSizes[i] == null) {
- lineSizes[i] = new LineSizeInfo();
- }
- return lineSizes[i];
-}
-void calculateClientArea () {
- int index = Math.max (0, styledText.getTopIndex());
- int lineCount = content.getLineCount();
- int height = styledText.getClientArea().height;
- int y = 0;
- /*
- * There exists a possibility of ArrayIndexOutOfBounds Exception in
- * below code, exact scenario not known. To avoid this exception added
- * check for 'index' value, refer Bug 471192.
- */
- while (height > y && lineCount > index && lineSizes.length > index) {
- calculate(index, 1);
- y += lineSizes[index++].height;
- }
-}
-void calculateIdle () {
- if (idleRunning) return;
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- if (styledText == null) return;
- int i;
- long start = System.currentTimeMillis();
- for (i = 0; i < lineCount; i++) {
- LineSizeInfo line = getLineSize(i);
- if (line.needsRecalculateSize()) {
- calculate(i, 1);
- if (System.currentTimeMillis() - start > IDLE_TIME) break;
- }
- }
- if (i < lineCount) {
- Display display = styledText.getDisplay();
- display.asyncExec(this);
- } else {
- idleRunning = false;
- styledText.setScrollBars(true);
- ScrollBar bar = styledText.getVerticalBar();
- if (bar != null) {
- bar.setSelection(styledText.getVerticalScrollOffset());
- }
- }
- }
- };
- Display display = styledText.getDisplay();
- display.asyncExec(runnable);
- idleRunning = true;
-}
-void clearLineBackground(int startLine, int count) {
- if (lines == null) return;
- for (int i = startLine; i < startLine + count; i++) {
- LineInfo info = lines[i];
- if (info != null) {
- info.flags &= ~BACKGROUND;
- info.background = null;
- if (info.flags == 0) lines[i] = null;
- }
- }
-}
-void clearLineStyle(int startLine, int count) {
- if (lines == null) return;
- for (int i = startLine; i < startLine + count; i++) {
- LineInfo info = lines[i];
- if (info != null) {
- info.flags &= ~(ALIGNMENT | INDENT | VERTICAL_INDENT | WRAP_INDENT | JUSTIFY | TABSTOPS);
- if (info.flags == 0) lines[i] = null;
- }
- }
-}
-void copyInto(StyledTextRenderer renderer) {
- if (ranges != null) {
- int[] newRanges = renderer.ranges = new int[styleCount << 1];
- System.arraycopy(ranges, 0, newRanges, 0, newRanges.length);
- }
- if (styles != null) {
- StyleRange[] newStyles = renderer.styles = new StyleRange[styleCount];
- for (int i = 0; i < newStyles.length; i++) {
- newStyles[i] = (StyleRange)styles[i].clone();
- }
- renderer.styleCount = styleCount;
- }
- if (lines != null) {
- LineInfo[] newLines = renderer.lines = new LineInfo[lineCount];
- for (int i = 0; i < newLines.length; i++) {
- newLines[i] = new LineInfo(lines[i]);
- }
- renderer.lineCount = lineCount;
- }
-}
-void dispose() {
- if (boldFont != null) boldFont.dispose();
- if (italicFont != null) italicFont.dispose();
- if (boldItalicFont != null) boldItalicFont.dispose();
- boldFont = italicFont = boldItalicFont = null;
- reset();
- content = null;
- device = null;
- styledText = null;
-}
-void disposeTextLayout (TextLayout layout) {
- if (layouts != null) {
- for (TextLayout l : layouts) {
- if (l == layout) return;
- }
- }
- layout.dispose();
-}
-void drawBullet(Bullet bullet, GC gc, int paintX, int paintY, int index, int lineAscent, int lineDescent) {
- StyleRange style = bullet.style;
- GlyphMetrics metrics = style.metrics;
- Color color = style.foreground;
- if (color != null) gc.setForeground(color);
- Font font = style.font;
- if (font != null) gc.setFont(font);
- String string = "";
- int type = bullet.type & (ST.BULLET_DOT|ST.BULLET_NUMBER|ST.BULLET_LETTER_LOWER|ST.BULLET_LETTER_UPPER);
- switch (type) {
- case ST.BULLET_DOT: string = "\u2022"; break;
- case ST.BULLET_NUMBER: string = String.valueOf(index + 1); break;
- case ST.BULLET_LETTER_LOWER: string = String.valueOf((char) (index % 26 + 97)); break;
- case ST.BULLET_LETTER_UPPER: string = String.valueOf((char) (index % 26 + 65)); break;
- }
- if ((bullet.type & ST.BULLET_TEXT) != 0) string += bullet.text;
- Display display = styledText.getDisplay();
- TextLayout layout = new TextLayout(display);
- layout.setText(string);
- layout.setAscent(lineAscent);
- layout.setDescent(lineDescent);
- style = (StyleRange)style.clone();
- style.metrics = null;
- if (style.font == null) style.font = getFont(style.fontStyle);
- layout.setStyle(style, 0, string.length());
- int x = paintX + Math.max(0, metrics.width - layout.getBounds().width - BULLET_MARGIN);
- layout.draw(gc, x, paintY);
- layout.dispose();
-}
-
-/**
- * Caches draw-related info that may be expensive to calculate twice when
- * drawing first background and then foreground.
- */
-private LineDrawInfo makeLineDrawInfo(int lineIndex) {
- TextLayout layout = getTextLayout(lineIndex);
- String text = content.getLine(lineIndex);
- int offset = content.getOffsetAtLine(lineIndex);
- int height = layout.getBounds().height;
- return new LineDrawInfo(lineIndex, layout, text, offset, height);
-}
-
-int drawLines(int startLine, int endLine, int begX, int begY, int endY, GC gc, Color widgetBackground, Color widgetForeground) {
- // When fixed line metrics is in effect, tall unicode characters
- // will not always fit line's height. In this case, they will
- // draw out of line's bounds. To prevent them from being clipped
- // by next line's background, paint entire background before any
- // foreground.
- // I considered to make this mode default, but was worried about
- // potential regressions in various legacy code. For example, it
- // could change something about line heights/colors during
- // painting. While this doesn't sound like a good thing to do, yet
- // still, I'd rather stay safe.
- final boolean drawBackBeforeFore = (fixedLineMetrics != null);
-
- if (drawBackBeforeFore) {
- // Cache drawing information
- final List drawInfos = new ArrayList<>();
- int y = begY;
- for (int iLine = startLine; y < endY && iLine < endLine; iLine++) {
- LineDrawInfo lineInfo = makeLineDrawInfo(iLine);
- drawInfos.add(lineInfo);
- y += lineInfo.height;
- }
-
- // Draw background
- y = begY;
- for (LineDrawInfo lineInfo : drawInfos) {
- drawLineBackground(lineInfo, y, gc, widgetBackground);
- y += lineInfo.height;
- }
-
- // Draw foreground
- y = begY;
- for (LineDrawInfo lineInfo : drawInfos) {
- drawLineForeground(lineInfo, begX, y, gc, widgetForeground);
- y += lineInfo.height;
- }
-
- // cleanup
- for (LineDrawInfo lineInfo : drawInfos) {
- disposeTextLayout(lineInfo.layout);
- }
-
- return y - begY;
- }
-
- int y = begY;
- for (int iLine = startLine; y < endY && iLine < endLine; iLine++) {
- LineDrawInfo lineInfo = makeLineDrawInfo(iLine);
- drawLineBackground(lineInfo, y, gc, widgetBackground);
- drawLineForeground(lineInfo, begX, y, gc, widgetForeground);
- disposeTextLayout(lineInfo.layout);
- y += lineInfo.height;
- }
- return y - begY;
-}
-
-private void drawLineBackground(LineDrawInfo lineInfo, int paintY, GC gc, Color widgetBackground) {
- Rectangle client = styledText.getClientArea();
- Color lineBackground = getLineBackground(lineInfo.index, null);
- StyledTextEvent event = styledText.getLineBackgroundData(lineInfo.offset, lineInfo.text);
- if (event != null && event.lineBackground != null) lineBackground = event.lineBackground;
- int verticalIndent = lineInfo.layout.getVerticalIndent();
-
- if (lineBackground != null) {
- if (verticalIndent > 0) {
- gc.setBackground(widgetBackground);
- gc.fillRectangle(client.x, paintY, client.width, verticalIndent);
- }
- gc.setBackground(lineBackground);
- gc.fillRectangle(client.x, paintY + verticalIndent, client.width, lineInfo.height - verticalIndent);
- } else {
- gc.setBackground(widgetBackground);
- styledText.drawBackground(gc, client.x, paintY, client.width, lineInfo.height);
- }
-}
-
-private void drawLineForeground(LineDrawInfo lineInfo, int paintX, int paintY, GC gc, Color widgetForeground) {
- int lineLength = lineInfo.text.length();
- gc.setForeground(widgetForeground);
- Point[] selection = intersectingRelativeNonEmptySelections(lineInfo.offset, lineInfo.offset + lineLength);
- if (styledText.getBlockSelection() || selection.length == 0) {
- lineInfo.layout.draw(gc, paintX, paintY);
- } else {
- Color selectionFg = styledText.getSelectionForeground();
- Color selectionBg = styledText.getSelectionBackground();
- final int baseFlags = (styledText.getStyle() & SWT.FULL_SELECTION) != 0 ? SWT.FULL_SELECTION : SWT.DELIMITER_SELECTION;
- for (Point relativeSelection : selection) {
- int start = Math.max(0, relativeSelection.x);
- int end = Math.min(lineLength, relativeSelection.y);
- int flags = baseFlags;
- if (relativeSelection.x <= lineLength && lineLength < relativeSelection.y ) {
- flags |= SWT.LAST_LINE_SELECTION;
- }
- // TODO calling draw multiple times here prints line multiple times, overriding some colors
- lineInfo.layout.draw(gc, paintX, paintY, start, end - 1, selectionFg, selectionBg, flags);
- }
- }
-
- // draw objects
- Bullet bullet = null;
- int bulletIndex = -1;
- if (bullets != null) {
- if (bulletsIndices != null) {
- int index = lineInfo.index - topIndex;
- if (0 <= index && index < CACHE_SIZE) {
- bullet = bullets[index];
- bulletIndex = bulletsIndices[index];
- }
- } else {
- for (Bullet b : bullets) {
- bullet = b;
- bulletIndex = bullet.indexOf(lineInfo.index);
- if (bulletIndex != -1) break;
- }
- }
- }
- if (bulletIndex != -1 && bullet != null) {
- FontMetrics metrics = lineInfo.layout.getLineMetrics(0);
- int lineAscent = metrics.getAscent() + metrics.getLeading();
- if (bullet.type == ST.BULLET_CUSTOM) {
- bullet.style.start = lineInfo.offset;
- styledText.paintObject(gc, paintX, paintY, lineAscent, metrics.getDescent(), bullet.style, bullet, bulletIndex);
- } else {
- drawBullet(bullet, gc, paintX, paintY, bulletIndex, lineAscent, metrics.getDescent());
- }
- }
- TextStyle[] styles = lineInfo.layout.getStyles();
- int[] ranges = null;
- for (int i = 0; i < styles.length; i++) {
- if (styles[i].metrics != null) {
- if (ranges == null) ranges = lineInfo.layout.getRanges();
- int start = ranges[i << 1];
- int length = ranges[(i << 1) + 1] - start + 1;
- Point point = lineInfo.layout.getLocation(start, false);
- FontMetrics metrics = lineInfo.layout.getLineMetrics(lineInfo.layout.getLineIndex(start));
- StyleRange style = (StyleRange)((StyleRange)styles[i]).clone();
- style.start = start + lineInfo.offset;
- style.length = length;
- int lineAscent = metrics.getAscent() + metrics.getLeading();
- styledText.paintObject(gc, point.x + paintX, point.y + paintY, lineAscent, metrics.getDescent(), style, null, 0);
- }
- }
-}
-
-private Point[] intersectingRelativeNonEmptySelections(int fromOffset, int toOffset) {
- int[] selectionRanges = styledText.getSelectionRanges();
- int lineLength = toOffset - fromOffset;
- List res = new ArrayList<>();
- for (int i = 0; i < selectionRanges.length; i += 2) {
- // ranges are assumed to be sorted by start offset, then (positive)length or higher end offset
- Point relativeSelection = new Point(selectionRanges[i] - fromOffset, selectionRanges[i] + selectionRanges[i + 1] - fromOffset);
- if (relativeSelection.x != relativeSelection.y &&
- relativeSelection.x <= lineLength && relativeSelection.y >= 0) {
- res.add(relativeSelection);
- }
- }
- return res.toArray(new Point[res.size()]);
-}
-
-int getBaseline() {
- return ascent;
-}
-int getCachedLineHeight(int lineIndex) {
- return getLineHeight(lineIndex, false);
-}
-Font getFont(int style) {
- switch (style) {
- case SWT.BOLD:
- if (boldFont != null) return boldFont;
- return boldFont = new Font(device, getFontData(style));
- case SWT.ITALIC:
- if (italicFont != null) return italicFont;
- return italicFont = new Font(device, getFontData(style));
- case SWT.BOLD | SWT.ITALIC:
- if (boldItalicFont != null) return boldItalicFont;
- return boldItalicFont = new Font(device, getFontData(style));
- default:
- return regularFont;
- }
-}
-FontData[] getFontData(int style) {
- FontData[] fontDatas = regularFont.getFontData();
- for (FontData fontData : fontDatas) {
- fontData.setStyle(style);
- }
- return fontDatas;
-}
-int getHeight () {
- int defaultLineHeight = getLineHeight();
- if (styledText.isFixedLineHeight()) {
- return lineCount * defaultLineHeight + styledText.topMargin + styledText.bottomMargin;
- }
- int totalHeight = 0;
- int width = styledText.getWrapWidth();
- for (int i = 0; i < lineCount; i++) {
- LineSizeInfo line = getLineSize(i);
- int height = line.height;
- if (line.needsRecalculateHeight()) {
- if (width > 0) {
- int length = content.getLine(i).length();
- height = ((length * averageCharWidth / width) + 1) * defaultLineHeight;
- } else {
- height = defaultLineHeight;
- }
- }
- totalHeight += height;
- }
- return totalHeight + styledText.topMargin + styledText.bottomMargin;
-}
-boolean hasLink(int offset) {
- if (offset == -1) return false;
- int lineIndex = content.getLineAtOffset(offset);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- String line = content.getLine(lineIndex);
- StyledTextEvent event = styledText.getLineStyleData(lineOffset, line);
- if (event != null) {
- StyleRange[] styles = event.styles;
- if (styles != null) {
- int[] ranges = event.ranges;
- if (ranges != null) {
- for (int i = 0; i < ranges.length; i+=2) {
- if (ranges[i] <= offset && offset < ranges[i] + ranges[i+1] && styles[i >> 1].underline && styles[i >> 1].underlineStyle == SWT.UNDERLINE_LINK) {
- return true;
- }
- }
- } else {
- for (StyleRange style : styles) {
- if (style.start <= offset && offset < style.start + style.length && style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) {
- return true;
- }
- }
- }
- }
- } else {
- if (ranges != null) {
- int rangeCount = styleCount << 1;
- int index = getRangeIndex(offset, -1, rangeCount);
- if (index >= rangeCount) return false;
- int rangeStart = ranges[index];
- int rangeLength = ranges[index + 1];
- StyleRange rangeStyle = styles[index >> 1];
- if (rangeStart <= offset && offset < rangeStart + rangeLength && rangeStyle.underline && rangeStyle.underlineStyle == SWT.UNDERLINE_LINK) {
- return true;
- }
- }
- }
- return false;
-}
-int getLineAlignment(int index, int defaultAlignment) {
- if (lines == null) return defaultAlignment;
- LineInfo info = lines[index];
- if (info != null && (info.flags & ALIGNMENT) != 0) {
- return info.alignment;
- }
- return defaultAlignment;
-}
-Color getLineBackground(int index, Color defaultBackground) {
- if (lines == null) return defaultBackground;
- LineInfo info = lines[index];
- if (info != null && (info.flags & BACKGROUND) != 0) {
- return info.background;
- }
- return defaultBackground;
-}
-Bullet getLineBullet (int index, Bullet defaultBullet) {
- if (bullets == null) return defaultBullet;
- if (bulletsIndices != null) return defaultBullet;
- for (Bullet bullet : bullets) {
- if (bullet.indexOf(index) != -1) return bullet;
- }
- return defaultBullet;
-}
-int getLineHeight() {
- return ascent + descent;
-}
-int getLineHeight(int lineIndex) {
- return getLineHeight(lineIndex, true);
-}
-int getLineHeight(int lineIndex, boolean exact) {
- LineSizeInfo line = getLineSize(lineIndex);
- if (line.needsRecalculateHeight()) {
- // here we are in "variable line height", the call of calculate which uses TextLayout is very slow
- // so use the average line height of all calculated lines when many heights are needed e.g. for scrolling.
- if (isVariableHeight(lineIndex)) {
- if (exact) {
- calculate(lineIndex, 1);
- } else {
- return Math.round(averageLineHeight);
- }
- } else {
- line.height = getLineHeight() + getLineSpacing(lineIndex) + getLineVerticalIndent(lineIndex);
- }
- }
- return line.height;
-}
-/**
- * Returns true if the given line can use the default line height and false
- * otherwise.
- *
- * @param lineIndex
- * line index
- * @return true if the given line can use the default line height and false
- * otherwise.
- */
-private boolean isVariableHeight(int lineIndex) {
- if (styledText.isWordWrap()) {
- // In word wrap mode, the line height must be recomputed with TextLayout
- return true;
- }
- StyleRange[] styles = getStylesForLine(lineIndex);
- if (styles != null) {
- for (StyleRange style : styles) {
- if (style.isVariableHeight()) {
- // style is variable height
- return true;
- }
- }
- }
- return false;
-}
-/**
- * returns true if the given line index defines custom line spacing and false
- * otherwise.
- *
- * @param lineIndex
- * the line index.
- * @return true if the given line index defines custom line spacing and false
- * otherwise.
- */
-private int getLineSpacing(int lineIndex) {
- if (styledText.lineSpacing > 0) {
- return styledText.lineSpacing;
- } else if (lineSpacingProvider != null) {
- Integer lineSpacing = lineSpacingProvider.getLineSpacing(lineIndex);
- if (lineSpacing != null) {
- return lineSpacing;
- }
- }
- return 0;
-}
-/**
- * Returns styles range for the given line index and null otherwise.
- *
- * @param lineIndex
- * the line index.
- * @return styles range for the given line index and null otherwise.
- */
-private StyleRange[] getStylesForLine(int lineIndex) {
- int start = styledText.getOffsetAtLine(lineIndex);
- int length = styledText.getLine(lineIndex).length();
- return getStyleRanges(start, length, false);
-}
-int getLineIndent(int index, int defaultIndent) {
- if (lines == null) return defaultIndent;
- LineInfo info = lines[index];
- if (info != null && (info.flags & INDENT) != 0) {
- return info.indent;
- }
- return defaultIndent;
-}
-int getLineVerticalIndent(int index) {
- if (lines == null) return 0;
- LineInfo info = lines[index];
- if (info != null && (info.flags & VERTICAL_INDENT) != 0) {
- return info.verticalIndent;
- }
- return 0;
-}
-int getLineWrapIndent(int index, int defaultWrapIndent) {
- if (lines == null) return defaultWrapIndent;
- LineInfo info = lines[index];
- if (info != null && (info.flags & WRAP_INDENT) != 0) {
- return info.wrapIndent;
- }
- return defaultWrapIndent;
-}
-boolean getLineJustify(int index, boolean defaultJustify) {
- if (lines == null) return defaultJustify;
- LineInfo info = lines[index];
- if (info != null && (info.flags & JUSTIFY) != 0) {
- return info.justify;
- }
- return defaultJustify;
-}
-int[] getLineTabStops(int index, int[] defaultTabStops) {
- if (lines == null) return defaultTabStops;
- LineInfo info = lines[index];
- if (info != null && (info.flags & TABSTOPS) != 0) {
- return info.tabStops;
- }
- return defaultTabStops;
-}
-StyledTextLineSpacingProvider getLineSpacingProvider() {
- return lineSpacingProvider;
-}
-int getRangeIndex(int offset, int low, int high) {
- if (styleCount == 0) return 0;
- if (ranges != null) {
- while (high - low > 2) {
- int index = ((high + low) / 2) / 2 * 2;
- int end = ranges[index] + ranges[index + 1];
- if (end > offset) {
- high = index;
- } else {
- low = index;
- }
- }
- } else {
- while (high - low > 1) {
- int index = ((high + low) / 2);
- int end = styles[index].start + styles[index].length;
- if (end > offset) {
- high = index;
- } else {
- low = index;
- }
- }
- }
- return high;
-}
-int[] getRanges(int start, int length) {
- if (length == 0) return null;
- int[] newRanges;
- int end = start + length - 1;
- if (ranges != null) {
- int rangeCount = styleCount << 1;
- int rangeStart = getRangeIndex(start, -1, rangeCount);
- if (rangeStart >= rangeCount) return null;
- if (ranges[rangeStart] > end) return null;
- int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount));
- if (ranges[rangeEnd] > end) rangeEnd = Math.max(rangeStart, rangeEnd - 2);
- newRanges = new int[rangeEnd - rangeStart + 2];
- System.arraycopy(ranges, rangeStart, newRanges, 0, newRanges.length);
- } else {
- int rangeStart = getRangeIndex(start, -1, styleCount);
- if (rangeStart >= styleCount) return null;
- if (styles[rangeStart].start > end) return null;
- int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount));
- if (styles[rangeEnd].start > end) rangeEnd = Math.max(rangeStart, rangeEnd - 1);
- newRanges = new int[(rangeEnd - rangeStart + 1) << 1];
- for (int i = rangeStart, j = 0; i <= rangeEnd; i++, j += 2) {
- StyleRange style = styles[i];
- newRanges[j] = style.start;
- newRanges[j + 1] = style.length;
- }
- }
- if (start > newRanges[0]) {
- newRanges[1] = newRanges[0] + newRanges[1] - start;
- newRanges[0] = start;
- }
- if (end < newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1] - 1) {
- newRanges[newRanges.length - 1] = end - newRanges[newRanges.length - 2] + 1;
- }
- return newRanges;
-}
-StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) {
- if (length == 0) return null;
- StyleRange[] newStyles;
- int end = start + length - 1;
- if (ranges != null) {
- int rangeCount = styleCount << 1;
- int rangeStart = getRangeIndex(start, -1, rangeCount);
- if (rangeStart >= rangeCount) return null;
- if (ranges[rangeStart] > end) return null;
- int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount));
- if (ranges[rangeEnd] > end) rangeEnd = Math.max(rangeStart, rangeEnd - 2);
- newStyles = new StyleRange[((rangeEnd - rangeStart) >> 1) + 1];
- if (includeRanges) {
- for (int i = rangeStart, j = 0; i <= rangeEnd; i += 2, j++) {
- newStyles[j] = (StyleRange)styles[i >> 1].clone();
- newStyles[j].start = ranges[i];
- newStyles[j].length = ranges[i + 1];
- }
- } else {
- System.arraycopy(styles, rangeStart >> 1, newStyles, 0, newStyles.length);
- }
- } else {
- int rangeStart = getRangeIndex(start, -1, styleCount);
- if (rangeStart >= styleCount) return null;
- if (styles[rangeStart].start > end) return null;
- int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount));
- if (styles[rangeEnd].start > end) rangeEnd = Math.max(rangeStart, rangeEnd - 1);
- newStyles = new StyleRange[rangeEnd - rangeStart + 1];
- System.arraycopy(styles, rangeStart, newStyles, 0, newStyles.length);
- }
- if (includeRanges || ranges == null) {
- StyleRange style = newStyles[0];
- if (start > style.start) {
- newStyles[0] = style = (StyleRange)style.clone();
- style.length = style.start + style.length - start;
- style.start = start;
- }
- style = newStyles[newStyles.length - 1];
- if (end < style.start + style.length - 1) {
- newStyles[newStyles.length - 1] = style = (StyleRange)style.clone();
- style.length = end - style.start + 1;
- }
- }
- return newStyles;
-}
-StyleRange getStyleRange(StyleRange style) {
- if (style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) hasLinks = true;
- if (style.start == 0 && style.length == 0 && style.fontStyle == SWT.NORMAL) return style;
- StyleRange clone = (StyleRange)style.clone();
- clone.start = clone.length = 0;
- clone.fontStyle = SWT.NORMAL;
- if (clone.font == null) clone.font = getFont(style.fontStyle);
- return clone;
-}
-TextLayout getTextLayout(int lineIndex) {
- if (lineSpacingProvider == null) {
- return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), styledText.lineSpacing);
- }
- // Compute line spacing for the given line index.
- int newLineSpacing = styledText.lineSpacing;
- Integer spacing = lineSpacingProvider.getLineSpacing(lineIndex);
- if (spacing != null && spacing.intValue() >= 0) {
- newLineSpacing = spacing;
- }
- // Check if line spacing has not changed
- if (isSameLineSpacing(lineIndex, newLineSpacing)) {
- return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), newLineSpacing);
- }
- // Get text layout with original StyledText line spacing.
- TextLayout layout = getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(),
- styledText.lineSpacing);
- if (layout.getSpacing() != newLineSpacing) {
- layout.setSpacing(newLineSpacing);
- if (lineSpacingComputing) {
- return layout;
- }
- try {
- /* Call of resetCache, setCaretLocation, redraw call getTextLayout method
- * To avoid having stack overflow, lineSpacingComputing flag is used to call
- * resetCache, setCaretLocation, redraw methods only at the end of the compute of all lines spacing.
- */
- lineSpacingComputing = true;
- styledText.resetCache(lineIndex, 1);
- styledText.setCaretLocations();
- styledText.redraw();
- } finally {
- lineSpacingComputing = false;
- }
- }
- return layout;
-}
-boolean isSameLineSpacing(int lineIndex, int newLineSpacing) {
- if (layouts == null) {
- return false;
- }
- int layoutIndex = lineIndex - topIndex;
- if (0 <= layoutIndex && layoutIndex < layouts.length) {
- TextLayout layout = layouts[layoutIndex];
- return layout != null && !layout.isDisposed() && layout.getSpacing() == newLineSpacing;
- }
- return false;
-}
-
-private static final class StyleEntry {
- public final int start;
- public final int end;
- public final TextStyle style;
-
- public StyleEntry(TextStyle style, int start, int end) {
- this.style = style;
- this.start = start;
- this.end = end;
- }
-}
-
-TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpacing) {
- TextLayout layout = null;
- if (styledText != null) {
- int topIndex = styledText.topIndex > 0 ? styledText.topIndex - 1 : 0;
- if (layouts == null || topIndex != this.topIndex) {
- TextLayout[] newLayouts = new TextLayout[CACHE_SIZE];
- if (layouts != null) {
- for (int i = 0; i < layouts.length; i++) {
- if (layouts[i] != null) {
- int layoutIndex = (i + this.topIndex) - topIndex;
- if (0 <= layoutIndex && layoutIndex < newLayouts.length) {
- newLayouts[layoutIndex] = layouts[i];
- } else {
- layouts[i].dispose();
- }
- }
- }
- }
- if (bullets != null && bulletsIndices != null && topIndex != this.topIndex) {
- int delta = topIndex - this.topIndex;
- if (delta > 0) {
- if (delta < bullets.length) {
- System.arraycopy(bullets, delta, bullets, 0, bullets.length - delta);
- System.arraycopy(bulletsIndices, delta, bulletsIndices, 0, bulletsIndices.length - delta);
- }
- int startIndex = Math.max(0, bullets.length - delta);
- for (int i = startIndex; i < bullets.length; i++) bullets[i] = null;
- } else {
- if (-delta < bullets.length) {
- System.arraycopy(bullets, 0, bullets, -delta, bullets.length + delta);
- System.arraycopy(bulletsIndices, 0, bulletsIndices, -delta, bulletsIndices.length + delta);
- }
- int endIndex = Math.min(bullets.length, -delta);
- for (int i = 0; i < endIndex; i++) bullets[i] = null;
- }
- }
- this.topIndex = topIndex;
- layouts = newLayouts;
- }
- if (layouts != null) {
- int layoutIndex = lineIndex - topIndex;
- if (0 <= layoutIndex && layoutIndex < layouts.length) {
- layout = layouts[layoutIndex];
- if (layout != null) {
- // Bug 520374: lineIndex can be >= linesSize.length
- if(lineIndex < lineSizes.length && getLineSize(lineIndex).canLayout()) {
- return layout;
- }
- } else {
- layout = layouts[layoutIndex] = new TextLayout(device);
- }
- }
- }
- }
- if (layout == null) layout = new TextLayout(device);
- String line = content.getLine(lineIndex);
- int lineOffset = content.getOffsetAtLine(lineIndex);
- int[] segments = null;
- char[] segmentChars = null;
- int indent = 0;
- int wrapIndent = 0;
- int verticalIndent = 0;
- int alignment = SWT.LEFT;
- int textDirection = orientation;
- boolean justify = false;
- int[] tabs = {tabWidth};
- Bullet bullet = null;
- int[] ranges = null;
- StyleRange[] styles = null;
- int rangeStart = 0, styleCount = 0;
- StyledTextEvent event = null;
- if (styledText != null) {
- event = styledText.getBidiSegments(lineOffset, line);
- if (event != null) {
- segments = event.segments;
- segmentChars = event.segmentsChars;
- }
- event = styledText.getLineStyleData(lineOffset, line);
- indent = styledText.indent;
- wrapIndent = styledText.wrapIndent;
- alignment = styledText.alignment;
- if (styledText.isAutoDirection()) {
- textDirection = SWT.AUTO_TEXT_DIRECTION;
- } else if ((styledText.getStyle() & SWT.FLIP_TEXT_DIRECTION) != 0) {
- textDirection = orientation == SWT.RIGHT_TO_LEFT ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT;
- }
- justify = styledText.justify;
- if (styledText.tabs != null) tabs = styledText.tabs;
- }
- if (event != null) {
- indent = event.indent;
- verticalIndent = event.verticalIndent;
- wrapIndent = event.wrapIndent;
- alignment = event.alignment;
- justify = event.justify;
- bullet = event.bullet;
- ranges = event.ranges;
- styles = event.styles;
- if (event.tabStops != null) tabs = event.tabStops;
- if (styles != null) {
- styleCount = styles.length;
- if (styledText.isFixedLineHeight()) {
- for (int i = 0; i < styleCount; i++) {
- if (styles[i].isVariableHeight()) {
- styledText.hasStyleWithVariableHeight = true;
- styledText.verticalScrollOffset = -1;
- styledText.redraw();
- break;
- }
- }
- }
- }
- if (bullets == null || bulletsIndices == null) {
- bullets = new Bullet[CACHE_SIZE];
- bulletsIndices = new int[CACHE_SIZE];
- }
- int index = lineIndex - topIndex;
- if (0 <= index && index < CACHE_SIZE) {
- bullets[index] = bullet;
- bulletsIndices[index] = event.bulletIndex;
- }
- } else {
- if (lines != null) {
- LineInfo info = lines[lineIndex];
- if (info != null) {
- if ((info.flags & INDENT) != 0) indent = info.indent;
- if ((info.flags & VERTICAL_INDENT) != 0) verticalIndent = info.verticalIndent;
- if ((info.flags & WRAP_INDENT) != 0) wrapIndent = info.wrapIndent;
- if ((info.flags & ALIGNMENT) != 0) alignment = info.alignment;
- if ((info.flags & JUSTIFY) != 0) justify = info.justify;
- if ((info.flags & SEGMENTS) != 0) segments = info.segments;
- if ((info.flags & SEGMENT_CHARS) != 0) segmentChars = info.segmentsChars;
- if ((info.flags & TABSTOPS) != 0) tabs = info.tabStops;
- }
- }
- if (bulletsIndices != null) {
- bullets = null;
- bulletsIndices = null;
- }
- if (bullets != null) {
- for (Bullet b : bullets) {
- if (b.indexOf(lineIndex) != -1) {
- bullet = b;
- break;
- }
- }
- }
- ranges = this.ranges;
- styles = this.styles;
- styleCount = this.styleCount;
- if (ranges != null) {
- rangeStart = getRangeIndex(lineOffset, -1, styleCount << 1);
- } else {
- rangeStart = getRangeIndex(lineOffset, -1, styleCount);
- }
- }
- if (bullet != null) {
- StyleRange style = bullet.style;
- GlyphMetrics metrics = style.metrics;
- indent += metrics.width;
- }
-
- // prepare styles, as it may change the line content, do it before calling layout.setText()
- // This needs to happen early to handle the case of GlyphMetrics on \t.
- // The root cause is that TextLayout doesn't return the right value for the bounds when
- // GlyphMetrics are applied on \t. A better fix could be implemented directly in (all 3)
- // TextLayout classes.
- List styleEntries = new ArrayList<>();
- int lastOffset = 0;
- int length = line.length();
- if (styles != null) {
- if (ranges != null) {
- int rangeCount = styleCount << 1;
- for (int i = rangeStart; i < rangeCount; i += 2) {
- int start, end;
- if (lineOffset > ranges[i]) {
- start = 0;
- end = Math.min (length, ranges[i + 1] - lineOffset + ranges[i]);
- } else {
- start = ranges[i] - lineOffset;
- end = Math.min(length, start + ranges[i + 1]);
- }
- if (start >= length) break;
- if (lastOffset < start) {
- styleEntries.add(new StyleEntry(null, lastOffset, start - 1));
- }
- TextStyle style = getStyleRange(styles[i >> 1]);
- int endIndex = Math.max(start, Math.min(length, end + 1));
- if (style.metrics != null && line.substring(start, endIndex).contains("\t")) {
- line =
- line.substring(0, start) +
- line.substring(start, endIndex).replace('\t', ' ') +
- (end < line.length() ? line.substring(end + 1, line.length()) : "");
- }
- styleEntries.add(new StyleEntry(style, start, end));
- lastOffset = Math.max(lastOffset, end);
- }
- } else {
- for (int i = rangeStart; i < styleCount; i++) {
- int start, end;
- if (lineOffset > styles[i].start) {
- start = 0;
- end = Math.min (length, styles[i].length - lineOffset + styles[i].start);
- } else {
- start = styles[i].start - lineOffset;
- end = Math.min(length, start + styles[i].length);
- }
- if (start >= length) break;
- if (lastOffset < start) {
- styleEntries.add(new StyleEntry(null, lastOffset, start - 1));
- }
- TextStyle style = getStyleRange(styles[i]);
- int endIndex = Math.max(start, Math.min(length, end + 1));
- if (style.metrics != null && line.substring(start, endIndex).contains("\t")) {
- line =
- line.substring(0, start) +
- line.substring(start, endIndex).replace('\t', ' ') +
- (end < line.length() ? line.substring(end + 1, line.length()) : "");
- }
- styleEntries.add(new StyleEntry(style, start, end));
- lastOffset = Math.max(lastOffset, end);
- }
- }
- }
- if (lastOffset < length) styleEntries.add(new StyleEntry(null, lastOffset, length));
-
- layout.setFont(regularFont);
- layout.setAscent(ascent);
- layout.setDescent(descent);
- layout.setFixedLineMetrics(fixedLineMetrics);
- layout.setText(line);
- layout.setOrientation(orientation);
- layout.setSegments(segments);
- layout.setSegmentsChars(segmentChars);
- layout.setWidth(width);
- layout.setSpacing(lineSpacing);
- layout.setTabs(tabs);
- layout.setDefaultTabWidth(tabLength);
- layout.setIndent(indent);
- layout.setVerticalIndent(verticalIndent);
- layout.setWrapIndent(wrapIndent);
- layout.setAlignment(alignment);
- layout.setJustify(justify);
- layout.setTextDirection(textDirection);
- // apply styles, must be done after layout.setText()
- for (StyleEntry styleEntry : styleEntries) {
- layout.setStyle(styleEntry.style, styleEntry.start, styleEntry.end);
- }
-
- if (styledText != null && styledText.ime != null) {
- IME ime = styledText.ime;
- int compositionOffset = ime.getCompositionOffset();
- if (compositionOffset != -1 && compositionOffset <= content.getCharCount()) {
- int commitCount = ime.getCommitCount();
- int compositionLength = ime.getText().length();
- if (compositionLength != commitCount) {
- int compositionLine = content.getLineAtOffset(compositionOffset);
- if (compositionLine == lineIndex) {
- int[] imeRanges = ime.getRanges();
- TextStyle[] imeStyles = ime.getStyles();
- if (imeRanges.length > 0) {
- for (int i = 0; i < imeStyles.length; i++) {
- int start = imeRanges[i*2] - lineOffset;
- int end = imeRanges[i*2+1] - lineOffset;
- TextStyle imeStyle = imeStyles[i], userStyle;
- for (int j = start; j <= end; j++) {
- if (!(0 <= j && j < length)) break;
- userStyle = layout.getStyle(cap(layout, j));
- if (userStyle == null && j > 0) userStyle = layout.getStyle(cap(layout, j - 1));
- if (userStyle == null && j + 1 < length) userStyle = layout.getStyle(cap(layout, j + 1));
- if (userStyle == null) {
- layout.setStyle(imeStyle, j, j);
- } else {
- TextStyle newStyle = new TextStyle(imeStyle);
- if (newStyle.font == null) newStyle.font = userStyle.font;
- if (newStyle.foreground == null) newStyle.foreground = userStyle.foreground;
- if (newStyle.background == null) newStyle.background = userStyle.background;
- layout.setStyle(newStyle, j, j);
- }
- }
- }
- } else {
- int start = compositionOffset - lineOffset;
- int end = start + compositionLength - 1;
- TextStyle userStyle = layout.getStyle(cap(layout, start));
- if (userStyle == null) {
- if (start > 0) userStyle = layout.getStyle(cap(layout, start - 1));
- if (userStyle == null && end + 1 < length) userStyle = layout.getStyle(cap(layout, end + 1));
- if (userStyle != null) {
- TextStyle newStyle = new TextStyle();
- newStyle.font = userStyle.font;
- newStyle.foreground = userStyle.foreground;
- newStyle.background = userStyle.background;
- layout.setStyle(newStyle, start, end);
- }
- }
- }
- }
- }
- }
- }
-
- if (styledText != null && styledText.isFixedLineHeight()) {
- int index = -1;
- int lineCount = layout.getLineCount();
- int height = getLineHeight();
- for (int i = 0; i < lineCount; i++) {
- int lineHeight = layout.getLineBounds(i).height;
- if (lineHeight > height) {
- height = lineHeight;
- index = i;
- }
- }
- if (index != -1) {
- FontMetrics metrics = layout.getLineMetrics(index);
- ascent = metrics.getAscent() + metrics.getLeading();
- descent = metrics.getDescent();
- if (layouts != null) {
- for (TextLayout l : layouts) {
- if (l != null && l != layout) {
- l.setAscent(ascent);
- l.setDescent(descent);
- }
- }
- }
- styledText.calculateScrollBars();
- if (styledText.verticalScrollOffset != 0) {
- int topIndex = styledText.topIndex;
- int topIndexY = styledText.topIndexY;
- int lineHeight = getLineHeight();
- int newVerticalScrollOffset;
- if (topIndexY >= 0) {
- newVerticalScrollOffset = (topIndex - 1) * lineHeight + lineHeight - topIndexY;
- } else {
- newVerticalScrollOffset = topIndex * lineHeight - topIndexY;
- }
- styledText.scrollVertical(newVerticalScrollOffset - styledText.verticalScrollOffset, true);
- }
- if (styledText.isBidiCaret()) styledText.createCaretBitmaps();
- styledText.caretDirection = SWT.NULL;
- styledText.setCaretLocations();
- styledText.redraw();
- }
- }
- return layout;
-}
-int getWidth() {
- return maxWidth;
-}
-void reset() {
- if (layouts != null) {
- for (TextLayout layout : layouts) {
- if (layout != null) layout.dispose();
- }
- layouts = null;
- }
- topIndex = -1;
- stylesSetCount = styleCount = lineCount = 0;
- ranges = null;
- styles = null;
- stylesSet = null;
- lines = null;
- lineSizes = null;
- bullets = null;
- bulletsIndices = null;
- redrawLines = null;
- hasLinks = false;
-}
-void reset(int startLine, int lineCount) {
- int endLine = startLine + lineCount;
- if (startLine < 0 || endLine > lineSizes.length) return;
- SortedSet lines = new TreeSet<>();
- for (int i = startLine; i < endLine; i++) {
- lines.add(Integer.valueOf(i));
- }
- reset(lines);
-}
-void reset(Set lines) {
- if (lines == null || lines.isEmpty()) return;
- int resetLineCount = 0;
- for (Integer line : lines) {
- if (line >= 0 || line < lineCount) {
- resetLineCount++;
- getLineSize(line.intValue()).resetSize();
- }
- }
- if (linesInAverageLineHeight > resetLineCount) {
- linesInAverageLineHeight -= resetLineCount;
- } else {
- linesInAverageLineHeight = 0;
- averageLineHeight = 0.0f;
- }
- if (lines.contains(Integer.valueOf(maxWidthLineIndex))) {
- maxWidth = 0;
- maxWidthLineIndex = -1;
- if (resetLineCount != this.lineCount) {
- for (int i = 0; i < this.lineCount; i++) {
- LineSizeInfo lineSize = getLineSize(i);
- if (lineSize.width > maxWidth) {
- maxWidth = lineSize.width;
- maxWidthLineIndex = i;
- }
- }
- }
- }
-}
-void setContent(StyledTextContent content) {
- reset();
- this.content = content;
- lineCount = content.getLineCount();
- lineSizes = new LineSizeInfo[lineCount];
- maxWidth = 0;
- maxWidthLineIndex = -1;
- reset(0, lineCount);
-}
-
-/**
- * See {@link TextLayout#setFixedLineMetrics}
- *
- * @since 3.125
- */
-public void setFixedLineMetrics(FontMetrics metrics) {
- fixedLineMetrics = metrics;
-}
-
-void setFont(Font font, int tabs) {
- TextLayout layout = new TextLayout(device);
- layout.setFont(regularFont);
- tabLength = tabs;
- if (font != null) {
- if (boldFont != null) boldFont.dispose();
- if (italicFont != null) italicFont.dispose();
- if (boldItalicFont != null) boldItalicFont.dispose();
- boldFont = italicFont = boldItalicFont = null;
- regularFont = font;
- layout.setText(" ");
- layout.setFont(font);
- layout.setStyle(new TextStyle(getFont(SWT.NORMAL), null, null), 0, 0);
- layout.setStyle(new TextStyle(getFont(SWT.BOLD), null, null), 1, 1);
- layout.setStyle(new TextStyle(getFont(SWT.ITALIC), null, null), 2, 2);
- layout.setStyle(new TextStyle(getFont(SWT.BOLD | SWT.ITALIC), null, null), 3, 3);
- FontMetrics metrics = layout.getLineMetrics(0);
- ascent = metrics.getAscent() + metrics.getLeading();
- descent = metrics.getDescent();
- boldFont.dispose();
- italicFont.dispose();
- boldItalicFont.dispose();
- boldFont = italicFont = boldItalicFont = null;
- }
- layout.dispose();
- layout = new TextLayout(device);
- layout.setFont(regularFont);
- StringBuilder tabBuffer = new StringBuilder(tabs);
- for (int i = 0; i < tabs; i++) {
- tabBuffer.append(' ');
- }
- layout.setText(tabBuffer.toString());
- tabWidth = layout.getBounds().width;
- layout.dispose();
- if (styledText != null) {
- GC gc = new GC(styledText);
- averageCharWidth = (int) gc.getFontMetrics().getAverageCharacterWidth();
- fixedPitch = gc.stringExtent("l").x == gc.stringExtent("W").x; //$NON-NLS-1$ //$NON-NLS-2$
- gc.dispose();
- }
-}
-void setLineAlignment(int startLine, int count, int alignment) {
- if (lines == null) lines = new LineInfo[lineCount];
- for (int i = startLine; i < startLine + count; i++) {
- if (lines[i] == null) {
- lines[i] = new LineInfo();
- }
- lines[i].flags |= ALIGNMENT;
- lines[i].alignment = alignment;
- }
-}
-void setLineBackground(int startLine, int count, Color background) {
- if (lines == null) lines = new LineInfo[lineCount];
- for (int i = startLine; i < startLine + count; i++) {
- if (lines[i] == null) {
- lines[i] = new LineInfo();
- }
- lines[i].flags |= BACKGROUND;
- lines[i].background = background;
- }
-}
-void setLineBullet(int startLine, int count, Bullet bullet) {
- if (bulletsIndices != null) {
- bulletsIndices = null;
- bullets = null;
- }
- if (bullets == null) {
- if (bullet == null) return;
- bullets = new Bullet[1];
- bullets[0] = bullet;
- }
- int index = 0;
- while (index < bullets.length) {
- if (bullet == bullets[index]) break;
- index++;
- }
- if (bullet != null) {
- if (index == bullets.length) {
- Bullet[] newBulletsList = new Bullet[bullets.length + 1];
- System.arraycopy(bullets, 0, newBulletsList, 0, bullets.length);
- newBulletsList[index] = bullet;
- bullets = newBulletsList;
- }
- bullet.addIndices(startLine, count);
- } else {
- updateBullets(startLine, count, 0, false);
- styledText.redrawLinesBullet(redrawLines);
- redrawLines = null;
- }
-}
-void setLineIndent(int startLine, int count, int indent) {
- if (lines == null) lines = new LineInfo[lineCount];
- for (int i = startLine; i < startLine + count; i++) {
- if (lines[i] == null) {
- lines[i] = new LineInfo();
- }
- lines[i].flags |= INDENT;
- lines[i].indent = indent;
- }
-}
-void setLineVerticalIndent(int lineIndex, int verticalLineIndent) {
- if (lines == null)
- lines = new LineInfo[lineCount];
- if (lines[lineIndex] == null) {
- lines[lineIndex] = new LineInfo();
- }
- lines[lineIndex].flags |= VERTICAL_INDENT;
- int delta = verticalLineIndent - lines[lineIndex].verticalIndent;
- lines[lineIndex].verticalIndent = verticalLineIndent;
- LineSizeInfo info = getLineSize(lineIndex);
- if (!info.needsRecalculateHeight()) {
- info.height += delta;
- }
-}
-void setLineWrapIndent(int startLine, int count, int wrapIndent) {
- if (lines == null) lines = new LineInfo[lineCount];
- for (int i = startLine; i < startLine + count; i++) {
- if (lines[i] == null) {
- lines[i] = new LineInfo();
- }
- lines[i].flags |= WRAP_INDENT;
- lines[i].wrapIndent = wrapIndent;
- }
-}
-void setLineJustify(int startLine, int count, boolean justify) {
- if (lines == null) lines = new LineInfo[lineCount];
- for (int i = startLine; i < startLine + count; i++) {
- if (lines[i] == null) {
- lines[i] = new LineInfo();
- }
- lines[i].flags |= JUSTIFY;
- lines[i].justify = justify;
- }
-}
-void setLineSegments(int startLine, int count, int[] segments) {
- if (lines == null) lines = new LineInfo[lineCount];
- for (int i = startLine; i < startLine + count; i++) {
- if (lines[i] == null) {
- lines[i] = new LineInfo();
- }
- lines[i].flags |= SEGMENTS;
- lines[i].segments = segments;
- }
-}
-void setLineSegmentChars(int startLine, int count, char[] segmentChars) {
- if (lines == null) lines = new LineInfo[lineCount];
- for (int i = startLine; i < startLine + count; i++) {
- if (lines[i] == null) {
- lines[i] = new LineInfo();
- }
- lines[i].flags |= SEGMENT_CHARS;
- lines[i].segmentsChars = segmentChars;
- }
-}
-void setLineTabStops(int startLine, int count, int[] tabStops) {
- if (lines == null) lines = new LineInfo[lineCount];
- for (int i = startLine; i < startLine + count; i++) {
- if (lines[i] == null) {
- lines[i] = new LineInfo();
- }
- lines[i].flags |= TABSTOPS;
- lines[i].tabStops = tabStops;
- }
-}
-void setLineSpacingProvider(StyledTextLineSpacingProvider lineSpacingProvider) {
- this.lineSpacingProvider = lineSpacingProvider;
-}
-void setStyleRanges (int[] newRanges, StyleRange[] newStyles) {
- if (newStyles == null) {
- stylesSetCount = styleCount = 0;
- ranges = null;
- styles = null;
- stylesSet = null;
- hasLinks = false;
- return;
- }
- if (newRanges == null && COMPACT_STYLES) {
- newRanges = new int[newStyles.length << 1];
- StyleRange[] tmpStyles = new StyleRange[newStyles.length];
- if (stylesSet == null) stylesSet = new StyleRange[4];
- for (int i = 0, j = 0; i < newStyles.length; i++) {
- StyleRange newStyle = newStyles[i];
- newRanges[j++] = newStyle.start;
- newRanges[j++] = newStyle.length;
- int index = 0;
- while (index < stylesSetCount) {
- if (stylesSet[index].similarTo(newStyle)) break;
- index++;
- }
- if (index == stylesSetCount) {
- if (stylesSetCount == stylesSet.length) {
- StyleRange[] tmpStylesSet = new StyleRange[stylesSetCount + 4];
- System.arraycopy(stylesSet, 0, tmpStylesSet, 0, stylesSetCount);
- stylesSet = tmpStylesSet;
- }
- stylesSet[stylesSetCount++] = newStyle;
- }
- tmpStyles[i] = stylesSet[index];
- }
- newStyles = tmpStyles;
- }
-
- if (styleCount == 0) {
- if (newRanges != null) {
- ranges = new int[newRanges.length];
- System.arraycopy(newRanges, 0, ranges, 0, ranges.length);
- }
- styles = new StyleRange[newStyles.length];
- System.arraycopy(newStyles, 0, styles, 0, styles.length);
- styleCount = newStyles.length;
- return;
- }
- if (newRanges != null && ranges == null) {
- ranges = new int[styles.length << 1];
- for (int i = 0, j = 0; i < styleCount; i++) {
- ranges[j++] = styles[i].start;
- ranges[j++] = styles[i].length;
- }
- }
- if (newRanges == null && ranges != null) {
- newRanges = new int[newStyles.length << 1];
- for (int i = 0, j = 0; i < newStyles.length; i++) {
- newRanges[j++] = newStyles[i].start;
- newRanges[j++] = newStyles[i].length;
- }
- }
- if (ranges != null) {
- int rangeCount = styleCount << 1;
- int start = newRanges[0];
- int modifyStart = getRangeIndex(start, -1, rangeCount), modifyEnd;
- boolean insert = modifyStart == rangeCount;
- if (!insert) {
- int end = newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1];
- modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
- insert = modifyStart == modifyEnd && ranges[modifyStart] >= end;
- }
- if (insert) {
- addMerge(newRanges, newStyles, newRanges.length, modifyStart, modifyStart);
- return;
- }
- modifyEnd = modifyStart;
- int[] mergeRanges = new int[6];
- StyleRange[] mergeStyles = new StyleRange[3];
- for (int i = 0; i < newRanges.length; i += 2) {
- int newStart = newRanges[i];
- int newEnd = newStart + newRanges[i + 1];
- if (newStart == newEnd) continue;
- int modifyLast = 0, mergeCount = 0;
- while (modifyEnd < rangeCount) {
- if (newStart >= ranges[modifyStart] + ranges[modifyStart + 1]) modifyStart += 2;
- if (ranges[modifyEnd] + ranges[modifyEnd + 1] > newEnd) break;
- modifyEnd += 2;
- }
- if (ranges[modifyStart] < newStart && newStart < ranges[modifyStart] + ranges[modifyStart + 1]) {
- mergeStyles[mergeCount >> 1] = styles[modifyStart >> 1];
- mergeRanges[mergeCount] = ranges[modifyStart];
- mergeRanges[mergeCount + 1] = newStart - ranges[modifyStart];
- mergeCount += 2;
- }
- mergeStyles[mergeCount >> 1] = newStyles[i >> 1];
- mergeRanges[mergeCount] = newStart;
- mergeRanges[mergeCount + 1] = newRanges[i + 1];
- mergeCount += 2;
- if (modifyEnd < rangeCount && ranges[modifyEnd] < newEnd && newEnd < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
- mergeStyles[mergeCount >> 1] = styles[modifyEnd >> 1];
- mergeRanges[mergeCount] = newEnd;
- mergeRanges[mergeCount + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - newEnd;
- mergeCount += 2;
- modifyLast = 2;
- }
- int grow = addMerge(mergeRanges, mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast);
- rangeCount += grow;
- modifyStart = modifyEnd += grow;
- }
- } else {
- int start = newStyles[0].start;
- int modifyStart = getRangeIndex(start, -1, styleCount), modifyEnd;
- boolean insert = modifyStart == styleCount;
- if (!insert) {
- int end = newStyles[newStyles.length - 1].start + newStyles[newStyles.length - 1].length;
- modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
- insert = modifyStart == modifyEnd && styles[modifyStart].start >= end;
- }
- if (insert) {
- addMerge(newStyles, newStyles.length, modifyStart, modifyStart);
- return;
- }
- modifyEnd = modifyStart;
- StyleRange[] mergeStyles = new StyleRange[3];
- for (StyleRange newStyle : newStyles) {
- StyleRange style;
- int newStart = newStyle.start;
- int newEnd = newStart + newStyle.length;
- if (newStart == newEnd) continue;
- int modifyLast = 0, mergeCount = 0;
- while (modifyEnd < styleCount) {
- if (newStart >= styles[modifyStart].start + styles[modifyStart].length) modifyStart++;
- if (styles[modifyEnd].start + styles[modifyEnd].length > newEnd) break;
- modifyEnd++;
- }
- style = styles[modifyStart];
- if (style.start < newStart && newStart < style.start + style.length) {
- style = mergeStyles[mergeCount++] = (StyleRange)style.clone();
- style.length = newStart - style.start;
- }
- mergeStyles[mergeCount++] = newStyle;
- if (modifyEnd < styleCount) {
- style = styles[modifyEnd];
- if (style.start < newEnd && newEnd < style.start + style.length) {
- style = mergeStyles[mergeCount++] = (StyleRange)style.clone();
- style.length += style.start - newEnd;
- style.start = newEnd;
- modifyLast = 1;
- }
- }
- int grow = addMerge(mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast);
- modifyStart = modifyEnd += grow;
- }
- }
-}
-void textChanging(TextChangingEvent event) {
- int start = event.start;
- int newCharCount = event.newCharCount, replaceCharCount = event.replaceCharCount;
- int newLineCount = event.newLineCount, replaceLineCount = event.replaceLineCount;
-
- updateRanges(start, replaceCharCount, newCharCount);
-
- int startLine = content.getLineAtOffset(start);
- if (replaceCharCount == content.getCharCount()) lines = null;
- if (replaceLineCount == lineCount) {
- lineCount = newLineCount;
- lineSizes = new LineSizeInfo[lineCount];
- reset(0, lineCount);
- } else {
- int startIndex = startLine + replaceLineCount + 1;
- int endIndex = startLine + newLineCount + 1;
- if(lineCount < startLine) {
- SWT.error(SWT.ERROR_INVALID_RANGE, null, "bug 478020: lineCount < startLine: " + lineCount + ":" + startLine);
- }
- if(lineCount < startIndex) {
- SWT.error(SWT.ERROR_INVALID_RANGE, null, "bug 478020: lineCount < startIndex: " + lineCount + ":" + startIndex);
- }
- int delta = newLineCount - replaceLineCount;
- if (lineCount + delta > lineSizes.length) {
- LineSizeInfo[] newLineSizes = new LineSizeInfo[lineCount + delta + GROW];
- System.arraycopy(lineSizes, 0, newLineSizes, 0, lineCount);
- lineSizes = newLineSizes;
- }
- if (lines != null) {
- if (lineCount + delta > lines.length) {
- LineInfo[] newLines = new LineInfo[lineCount + delta + GROW];
- System.arraycopy(lines, 0, newLines, 0, lineCount);
- lines = newLines;
- }
- }
- System.arraycopy(lineSizes, startIndex, lineSizes, endIndex, lineCount - startIndex);
- for (int i = startLine; i < endIndex; i++) {
- lineSizes[i] = null;
- }
- for (int i = lineCount + delta; i < lineCount; i++) {
- lineSizes[i] = null;
- }
- if (layouts != null) {
- int layoutStartLine = startLine - topIndex;
- int layoutEndLine = layoutStartLine + replaceLineCount + 1;
- for (int i = layoutStartLine; i < layoutEndLine; i++) {
- if (0 <= i && i < layouts.length) {
- if (layouts[i] != null) layouts[i].dispose();
- layouts[i] = null;
- if (bullets != null && bulletsIndices != null) bullets[i] = null;
- }
- }
- if (delta > 0) {
- for (int i = layouts.length - 1; i >= layoutEndLine; i--) {
- if (0 <= i && i < layouts.length) {
- endIndex = i + delta;
- if (0 <= endIndex && endIndex < layouts.length) {
- layouts[endIndex] = layouts[i];
- layouts[i] = null;
- if (bullets != null && bulletsIndices != null) {
- bullets[endIndex] = bullets[i];
- bulletsIndices[endIndex] = bulletsIndices[i];
- bullets[i] = null;
- }
- } else {
- if (layouts[i] != null) layouts[i].dispose();
- layouts[i] = null;
- if (bullets != null && bulletsIndices != null) bullets[i] = null;
- }
- }
- }
- } else if (delta < 0) {
- for (int i = layoutEndLine; i < layouts.length; i++) {
- if (0 <= i && i < layouts.length) {
- endIndex = i + delta;
- if (0 <= endIndex && endIndex < layouts.length) {
- layouts[endIndex] = layouts[i];
- layouts[i] = null;
- if (bullets != null && bulletsIndices != null) {
- bullets[endIndex] = bullets[i];
- bulletsIndices[endIndex] = bulletsIndices[i];
- bullets[i] = null;
- }
- } else {
- if (layouts[i] != null) layouts[i].dispose();
- layouts[i] = null;
- if (bullets != null && bulletsIndices != null) bullets[i] = null;
- }
- }
- }
- }
- }
- if (replaceLineCount != 0 || newLineCount != 0) {
- int startLineOffset = content.getOffsetAtLine(startLine);
- if (startLineOffset != start) startLine++;
- updateBullets(startLine, replaceLineCount, newLineCount, true);
- if (lines != null) {
- startIndex = startLine + replaceLineCount;
- endIndex = startLine + newLineCount;
- System.arraycopy(lines, startIndex, lines, endIndex, lineCount - startIndex);
- for (int i = startLine; i < endIndex; i++) {
- lines[i] = null;
- }
- for (int i = lineCount + delta; i < lineCount; i++) {
- lines[i] = null;
- }
- }
- }
- lineCount += delta;
- if (maxWidthLineIndex != -1 && startLine <= maxWidthLineIndex && maxWidthLineIndex <= startLine + replaceLineCount) {
- maxWidth = 0;
- maxWidthLineIndex = -1;
- for (int i = 0; i < lineCount; i++) {
- LineSizeInfo lineSize = getLineSize(i);
- if (lineSize.width > maxWidth) {
- maxWidth = lineSize.width;
- maxWidthLineIndex = i;
- }
- }
- }
- }
-}
-void updateBullets(int startLine, int replaceLineCount, int newLineCount, boolean update) {
- if (bullets == null) return;
- if (bulletsIndices != null) return;
- for (Bullet bullet : bullets) {
- int[] lines = bullet.removeIndices(startLine, replaceLineCount, newLineCount, update);
- if (lines != null) {
- if (redrawLines == null) {
- redrawLines = lines;
- } else {
- int[] newRedrawBullets = new int[redrawLines.length + lines.length];
- System.arraycopy(redrawLines, 0, newRedrawBullets, 0, redrawLines.length);
- System.arraycopy(lines, 0, newRedrawBullets, redrawLines.length, lines.length);
- redrawLines = newRedrawBullets;
- }
- }
- }
- int removed = 0;
- for (Bullet bullet : bullets) {
- if (bullet.size() == 0) removed++;
- }
- if (removed > 0) {
- if (removed == bullets.length) {
- bullets = null;
- } else {
- Bullet[] newBulletsList = new Bullet[bullets.length - removed];
- for (int i = 0, j = 0; i < bullets.length; i++) {
- Bullet bullet = bullets[i];
- if (bullet.size() > 0) newBulletsList[j++] = bullet;
- }
- bullets = newBulletsList;
- }
- }
-}
-void updateRanges(int start, int replaceCharCount, int newCharCount) {
- if (styleCount == 0 || (replaceCharCount == 0 && newCharCount == 0)) return;
- if (ranges != null) {
- int rangeCount = styleCount << 1;
- int modifyStart = getRangeIndex(start, -1, rangeCount);
- if (modifyStart == rangeCount) return;
- int end = start + replaceCharCount;
- int modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
- int offset = newCharCount - replaceCharCount;
- if (modifyStart == modifyEnd && ranges[modifyStart] < start && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
- if (newCharCount == 0) {
- ranges[modifyStart + 1] -= replaceCharCount;
- modifyEnd += 2;
- } else {
- if (rangeCount + 2 > ranges.length) {
- int[] newRanges = new int[ranges.length + (GROW << 1)];
- System.arraycopy(ranges, 0, newRanges, 0, rangeCount);
- ranges = newRanges;
- StyleRange[] newStyles = new StyleRange[styles.length + GROW];
- System.arraycopy(styles, 0, newStyles, 0, styleCount);
- styles = newStyles;
- }
- System.arraycopy(ranges, modifyStart + 2, ranges, modifyStart + 4, rangeCount - (modifyStart + 2));
- System.arraycopy(styles, (modifyStart + 2) >> 1, styles, (modifyStart + 4) >> 1, styleCount - ((modifyStart + 2) >> 1));
- ranges[modifyStart + 3] = ranges[modifyStart] + ranges[modifyStart + 1] - end;
- ranges[modifyStart + 2] = start + newCharCount;
- ranges[modifyStart + 1] = start - ranges[modifyStart];
- styles[(modifyStart >> 1) + 1] = styles[modifyStart >> 1];
- rangeCount += 2;
- styleCount++;
- modifyEnd += 4;
- }
- if (offset != 0) {
- for (int i = modifyEnd; i < rangeCount; i += 2) {
- ranges[i] += offset;
- }
- }
- } else {
- if (ranges[modifyStart] < start && start < ranges[modifyStart] + ranges[modifyStart + 1]) {
- ranges[modifyStart + 1] = start - ranges[modifyStart];
- modifyStart += 2;
- }
- if (modifyEnd < rangeCount && ranges[modifyEnd] < end && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
- ranges[modifyEnd + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - end;
- ranges[modifyEnd] = end;
- }
- if (offset != 0) {
- for (int i = modifyEnd; i < rangeCount; i += 2) {
- ranges[i] += offset;
- }
- }
- System.arraycopy(ranges, modifyEnd, ranges, modifyStart, rangeCount - modifyEnd);
- System.arraycopy(styles, modifyEnd >> 1, styles, modifyStart >> 1, styleCount - (modifyEnd >> 1));
- styleCount -= (modifyEnd - modifyStart) >> 1;
- }
- } else {
- int modifyStart = getRangeIndex(start, -1, styleCount);
- if (modifyStart == styleCount) return;
- int end = start + replaceCharCount;
- int modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
- int offset = newCharCount - replaceCharCount;
- if (modifyStart == modifyEnd && styles[modifyStart].start < start && end < styles[modifyEnd].start + styles[modifyEnd].length) {
- if (newCharCount == 0) {
- styles[modifyStart].length -= replaceCharCount;
- modifyEnd++;
- } else {
- if (styleCount + 1 > styles.length) {
- StyleRange[] newStyles = new StyleRange[styles.length + GROW];
- System.arraycopy(styles, 0, newStyles, 0, styleCount);
- styles = newStyles;
- }
- System.arraycopy(styles, modifyStart + 1, styles, modifyStart + 2, styleCount - (modifyStart + 1));
- styles[modifyStart + 1] = (StyleRange)styles[modifyStart].clone();
- styles[modifyStart + 1].length = styles[modifyStart].start + styles[modifyStart].length - end;
- styles[modifyStart + 1].start = start + newCharCount;
- styles[modifyStart].length = start - styles[modifyStart].start;
- styleCount++;
- modifyEnd += 2;
- }
- if (offset != 0) {
- for (int i = modifyEnd; i < styleCount; i++) {
- styles[i].start += offset;
- }
- }
- } else {
- if (styles[modifyStart].start < start && start < styles[modifyStart].start + styles[modifyStart].length) {
- styles[modifyStart].length = start - styles[modifyStart].start;
- modifyStart++;
- }
- if (modifyEnd < styleCount && styles[modifyEnd].start < end && end < styles[modifyEnd].start + styles[modifyEnd].length) {
- styles[modifyEnd].length = styles[modifyEnd].start + styles[modifyEnd].length - end;
- styles[modifyEnd].start = end;
- }
- if (offset != 0) {
- for (int i = modifyEnd; i < styleCount; i++) {
- styles[i].start += offset;
- }
- }
- System.arraycopy(styles, modifyEnd, styles, modifyStart, styleCount - modifyEnd);
- styleCount -= modifyEnd - modifyStart;
- }
- }
-}
-
-public boolean hasVerticalIndent() {
- return Arrays.stream(lines).filter(Objects::nonNull) //
- .mapToInt(line -> line.verticalIndent) //
- .anyMatch(n -> n != 0);
-}
-
-
+// Device device;
+// StyledText styledText;
+// StyledTextContent content;
+//
+// /* Custom line spacing */
+// StyledTextLineSpacingProvider lineSpacingProvider;
+// boolean lineSpacingComputing;
+//
+// /* Custom line metrics */
+// private FontMetrics fixedLineMetrics;
+//
+// /* Font info */
+// Font regularFont, boldFont, italicFont, boldItalicFont;
+// int tabWidth;
+// int ascent, descent;
+// int averageCharWidth;
+// int tabLength; //tab length in spaces
+//
+// /* Line data */
+// int topIndex = -1;
+// TextLayout[] layouts;
+// int lineCount;
+// LineSizeInfo[] lineSizes;
+// LineInfo[] lines;
+// int maxWidth;
+// int maxWidthLineIndex;
+// float averageLineHeight;
+// int linesInAverageLineHeight;
+// boolean idleRunning;
+//
+// /* Bullet */
+// Bullet[] bullets;
+// int[] bulletsIndices;
+// int[] redrawLines;
+//
+// /* Style data */
+// int[] ranges;
+// int styleCount;
+// StyleRange[] styles;
+// StyleRange[] stylesSet;
+// int stylesSetCount = 0;
+// boolean hasLinks, fixedPitch;
+// final static int BULLET_MARGIN = 8;
+//
+// final static boolean COMPACT_STYLES = true;
+// final static boolean MERGE_STYLES = true;
+//
+// final static int GROW = 32;
+// final static int IDLE_TIME = 50;
+// final static int CACHE_SIZE = 300;
+//
+// final static int BACKGROUND = 1 << 0;
+// final static int ALIGNMENT = 1 << 1;
+// final static int INDENT = 1 << 2;
+// final static int JUSTIFY = 1 << 3;
+// final static int SEGMENTS = 1 << 5;
+// final static int TABSTOPS = 1 << 6;
+// final static int WRAP_INDENT = 1 << 7;
+// final static int SEGMENT_CHARS = 1 << 8;
+// final static int VERTICAL_INDENT = 1 << 9;
+//
+// static class LineSizeInfo {
+//
+// private static final int RESETED_SIZE = -1;
+//
+// /* Line size */
+// int height;
+// int width;
+//
+// public LineSizeInfo() {
+// resetSize();
+// }
+//
+// /**
+// * Reset the line size.
+// */
+// void resetSize() {
+// height = RESETED_SIZE;
+// width = RESETED_SIZE;
+// }
+//
+// /**
+// * Returns true if the TextLayout get from the layout pool can be directly used
+// * or must be refreshed with styles.
+// *
+// * @return true if the TextLayout get from the layout pool can be directly used
+// * or must be refreshed with styles.
+// */
+// boolean canLayout() {
+// return !needsRecalculateWidth();
+// }
+//
+// /**
+// * Returns true if it needs to recalculate the line size and false
+// * otherwise.
+// *
+// * @return true if it needs to recalculate the line size and false
+// * otherwise.
+// */
+// boolean needsRecalculateSize() {
+// return needsRecalculateWidth() || needsRecalculateHeight();
+// }
+//
+// /**
+// * Returns true if it needs to recalculate the line width and false
+// * otherwise.
+// *
+// * @return true if it needs to recalculate the line width and false
+// * otherwise.
+// */
+// boolean needsRecalculateWidth() {
+// return width == RESETED_SIZE;
+// }
+//
+// /**
+// * Returns true if it needs to recalculate the line height and false
+// * otherwise.
+// *
+// * @return true if it needs to recalculate the line height and false
+// * otherwise.
+// */
+// boolean needsRecalculateHeight() {
+// return height == RESETED_SIZE;
+// }
+// }
+//
+// static class LineInfo {
+// int flags;
+// Color background;
+// int alignment;
+// int indent;
+// int wrapIndent;
+// boolean justify;
+// int[] segments;
+// char[] segmentsChars;
+// int[] tabStops;
+// int verticalIndent;
+//
+// public LineInfo() {
+// }
+// public LineInfo(LineInfo info) {
+// if (info != null) {
+// flags = info.flags;
+// background = info.background;
+// alignment = info.alignment;
+// indent = info.indent;
+// wrapIndent = info.wrapIndent;
+// justify = info.justify;
+// segments = info.segments;
+// segmentsChars = info.segmentsChars;
+// tabStops = info.tabStops;
+// verticalIndent = info.verticalIndent;
+// }
+// }
+// }
+//
+// private record LineDrawInfo(int index, TextLayout layout, String text, int offset, int height) {
+//
+// }
+//
+// static int cap (TextLayout layout, int offset) {
+// if (layout == null) return offset;
+// return Math.min (layout.getText().length() -1, Math.max (0, offset));
+// }
+//
+//StyledTextRenderer(Device device, StyledText styledText) {
+// this.device = device;
+// this.styledText = styledText;
+//}
+//int addMerge(int[] mergeRanges, StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) {
+// int rangeCount = styleCount << 1;
+// StyleRange endStyle = null;
+// int endStart = 0, endLength = 0;
+// if (modifyEnd < rangeCount) {
+// endStyle = styles[modifyEnd >> 1];
+// endStart = ranges[modifyEnd];
+// endLength = ranges[modifyEnd + 1];
+// }
+// int grow = mergeCount - (modifyEnd - modifyStart);
+// if (rangeCount + grow >= ranges.length) {
+// int[] tmpRanges = new int[ranges.length + grow + (GROW << 1)];
+// System.arraycopy(ranges, 0, tmpRanges, 0, modifyStart);
+// StyleRange[] tmpStyles = new StyleRange[styles.length + (grow >> 1) + GROW];
+// System.arraycopy(styles, 0, tmpStyles, 0, modifyStart >> 1);
+// if (rangeCount > modifyEnd) {
+// System.arraycopy(ranges, modifyEnd, tmpRanges, modifyStart + mergeCount, rangeCount - modifyEnd);
+// System.arraycopy(styles, modifyEnd >> 1, tmpStyles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1));
+// }
+// ranges = tmpRanges;
+// styles = tmpStyles;
+// } else {
+// if (rangeCount > modifyEnd) {
+// System.arraycopy(ranges, modifyEnd, ranges, modifyStart + mergeCount, rangeCount - modifyEnd);
+// System.arraycopy(styles, modifyEnd >> 1, styles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1));
+// }
+// }
+// if (MERGE_STYLES) {
+// int j = modifyStart;
+// for (int i = 0; i < mergeCount; i += 2) {
+// if (j > 0 && ranges[j - 2] + ranges[j - 1] == mergeRanges[i] && mergeStyles[i >> 1].similarTo(styles[(j - 2) >> 1])) {
+// ranges[j - 1] += mergeRanges[i + 1];
+// } else {
+// styles[j >> 1] = mergeStyles[i >> 1];
+// ranges[j++] = mergeRanges[i];
+// ranges[j++] = mergeRanges[i + 1];
+// }
+// }
+// if (endStyle != null && ranges[j - 2] + ranges[j - 1] == endStart && endStyle.similarTo(styles[(j - 2) >> 1])) {
+// ranges[j - 1] += endLength;
+// modifyEnd += 2;
+// mergeCount += 2;
+// }
+// if (rangeCount > modifyEnd) {
+// System.arraycopy(ranges, modifyStart + mergeCount, ranges, j, rangeCount - modifyEnd);
+// System.arraycopy(styles, (modifyStart + mergeCount) >> 1, styles, j >> 1, styleCount - (modifyEnd >> 1));
+// }
+// grow = (j - modifyStart) - (modifyEnd - modifyStart);
+// } else {
+// System.arraycopy(mergeRanges, 0, ranges, modifyStart, mergeCount);
+// System.arraycopy(mergeStyles, 0, styles, modifyStart >> 1, mergeCount >> 1);
+// }
+// styleCount += grow >> 1;
+// return grow;
+//}
+//int addMerge(StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) {
+// int grow = mergeCount - (modifyEnd - modifyStart);
+// StyleRange endStyle = null;
+// if (modifyEnd < styleCount) endStyle = styles[modifyEnd];
+// if (styleCount + grow >= styles.length) {
+// StyleRange[] tmpStyles = new StyleRange[styles.length + grow + GROW];
+// System.arraycopy(styles, 0, tmpStyles, 0, modifyStart);
+// if (styleCount > modifyEnd) {
+// System.arraycopy(styles, modifyEnd, tmpStyles, modifyStart + mergeCount, styleCount - modifyEnd);
+// }
+// styles = tmpStyles;
+// } else {
+// if (styleCount > modifyEnd) {
+// System.arraycopy(styles, modifyEnd, styles, modifyStart + mergeCount, styleCount - modifyEnd);
+// }
+// }
+// if (MERGE_STYLES) {
+// int j = modifyStart;
+// for (int i = 0; i < mergeCount; i++) {
+// StyleRange newStyle = mergeStyles[i], style;
+// if (j > 0 && (style = styles[j - 1]).start + style.length == newStyle.start && newStyle.similarTo(style)) {
+// style.length += newStyle.length;
+// } else {
+// styles[j++] = newStyle;
+// }
+// }
+// StyleRange style = styles[j - 1];
+// if (endStyle != null && style.start + style.length == endStyle.start && endStyle.similarTo(style)) {
+// style.length += endStyle.length;
+// modifyEnd++;
+// mergeCount++;
+// }
+// if (styleCount > modifyEnd) {
+// System.arraycopy(styles, modifyStart + mergeCount, styles, j, styleCount - modifyEnd);
+// }
+// grow = (j - modifyStart) - (modifyEnd - modifyStart);
+// } else {
+// System.arraycopy(mergeStyles, 0, styles, modifyStart, mergeCount);
+// }
+// styleCount += grow;
+// return grow;
+//}
+//void calculate(int startLine, int lineCount) {
+// int endLine = startLine + lineCount;
+// if (startLine < 0 || endLine > lineSizes.length) {
+// return;
+// }
+// int hTrim = styledText.leftMargin + styledText.rightMargin + styledText.getCaretWidth();
+// for (int i = startLine; i < endLine; i++) {
+// LineSizeInfo line = getLineSize(i);
+// if (line.needsRecalculateSize()) {
+// TextLayout layout = getTextLayout(i);
+// Rectangle rect = layout.getBounds();
+// line.width = rect.width + hTrim;
+// line.height = rect.height;
+// averageLineHeight += (line.height - Math.round(averageLineHeight)) / ++linesInAverageLineHeight;
+// disposeTextLayout(layout);
+// }
+// if (line.width > maxWidth) {
+// maxWidth = line.width;
+// maxWidthLineIndex = i;
+// }
+// }
+//}
+//LineSizeInfo getLineSize(int i) {
+// if (lineSizes[i] == null) {
+// lineSizes[i] = new LineSizeInfo();
+// }
+// return lineSizes[i];
+//}
+//void calculateClientArea () {
+// int index = Math.max (0, styledText.getTopIndex());
+// int lineCount = content.getLineCount();
+// int height = styledText.getClientArea().height;
+// int y = 0;
+// /*
+// * There exists a possibility of ArrayIndexOutOfBounds Exception in
+// * below code, exact scenario not known. To avoid this exception added
+// * check for 'index' value, refer Bug 471192.
+// */
+// while (height > y && lineCount > index && lineSizes.length > index) {
+// calculate(index, 1);
+// y += lineSizes[index++].height;
+// }
+//}
+//void calculateIdle () {
+// if (idleRunning) return;
+// Runnable runnable = new Runnable() {
+// @Override
+// public void run() {
+// if (styledText == null) return;
+// int i;
+// long start = System.currentTimeMillis();
+// for (i = 0; i < lineCount; i++) {
+// LineSizeInfo line = getLineSize(i);
+// if (line.needsRecalculateSize()) {
+// calculate(i, 1);
+// if (System.currentTimeMillis() - start > IDLE_TIME) break;
+// }
+// }
+// if (i < lineCount) {
+// Display display = styledText.getDisplay();
+// display.asyncExec(this);
+// } else {
+// idleRunning = false;
+// styledText.setScrollBars(true);
+// ScrollBar bar = styledText.getVerticalBar();
+// if (bar != null) {
+// bar.setSelection(styledText.getVerticalScrollOffset());
+// }
+// }
+// }
+// };
+// Display display = styledText.getDisplay();
+// display.asyncExec(runnable);
+// idleRunning = true;
+//}
+//void clearLineBackground(int startLine, int count) {
+// if (lines == null) return;
+// for (int i = startLine; i < startLine + count; i++) {
+// LineInfo info = lines[i];
+// if (info != null) {
+// info.flags &= ~BACKGROUND;
+// info.background = null;
+// if (info.flags == 0) lines[i] = null;
+// }
+// }
+//}
+//void clearLineStyle(int startLine, int count) {
+// if (lines == null) return;
+// for (int i = startLine; i < startLine + count; i++) {
+// LineInfo info = lines[i];
+// if (info != null) {
+// info.flags &= ~(ALIGNMENT | INDENT | VERTICAL_INDENT | WRAP_INDENT | JUSTIFY | TABSTOPS);
+// if (info.flags == 0) lines[i] = null;
+// }
+// }
+//}
+//void copyInto(StyledTextRenderer renderer) {
+// if (ranges != null) {
+// int[] newRanges = renderer.ranges = new int[styleCount << 1];
+// System.arraycopy(ranges, 0, newRanges, 0, newRanges.length);
+// }
+// if (styles != null) {
+// StyleRange[] newStyles = renderer.styles = new StyleRange[styleCount];
+// for (int i = 0; i < newStyles.length; i++) {
+// newStyles[i] = (StyleRange)styles[i].clone();
+// }
+// renderer.styleCount = styleCount;
+// }
+// if (lines != null) {
+// LineInfo[] newLines = renderer.lines = new LineInfo[lineCount];
+// for (int i = 0; i < newLines.length; i++) {
+// newLines[i] = new LineInfo(lines[i]);
+// }
+// renderer.lineCount = lineCount;
+// }
+//}
+//void dispose() {
+// if (boldFont != null) boldFont.dispose();
+// if (italicFont != null) italicFont.dispose();
+// if (boldItalicFont != null) boldItalicFont.dispose();
+// boldFont = italicFont = boldItalicFont = null;
+// reset();
+// content = null;
+// device = null;
+// styledText = null;
+//}
+//void disposeTextLayout (TextLayout layout) {
+// if (layouts != null) {
+// for (TextLayout l : layouts) {
+// if (l == layout) return;
+// }
+// }
+// layout.dispose();
+//}
+//void drawBullet(Bullet bullet, GC gc, int paintX, int paintY, int index, int lineAscent, int lineDescent) {
+// StyleRange style = bullet.style;
+// GlyphMetrics metrics = style.metrics;
+// Color color = style.foreground;
+// if (color != null) gc.setForeground(color);
+// Font font = style.font;
+// if (font != null) gc.setFont(font);
+// String string = "";
+// int type = bullet.type & (ST.BULLET_DOT|ST.BULLET_NUMBER|ST.BULLET_LETTER_LOWER|ST.BULLET_LETTER_UPPER);
+// switch (type) {
+// case ST.BULLET_DOT: string = "\u2022"; break;
+// case ST.BULLET_NUMBER: string = String.valueOf(index + 1); break;
+// case ST.BULLET_LETTER_LOWER: string = String.valueOf((char) (index % 26 + 97)); break;
+// case ST.BULLET_LETTER_UPPER: string = String.valueOf((char) (index % 26 + 65)); break;
+// }
+// if ((bullet.type & ST.BULLET_TEXT) != 0) string += bullet.text;
+// Display display = styledText.getDisplay();
+// TextLayout layout = new TextLayout(display);
+// layout.setText(string);
+// layout.setAscent(lineAscent);
+// layout.setDescent(lineDescent);
+// style = (StyleRange)style.clone();
+// style.metrics = null;
+// if (style.font == null) style.font = getFont(style.fontStyle);
+// layout.setStyle(style, 0, string.length());
+// int x = paintX + Math.max(0, metrics.width - layout.getBounds().width - BULLET_MARGIN);
+// layout.draw(gc, x, paintY);
+// layout.dispose();
+//}
+//
+///**
+// * Caches draw-related info that may be expensive to calculate twice when
+// * drawing first background and then foreground.
+// */
+//private LineDrawInfo makeLineDrawInfo(int lineIndex) {
+// TextLayout layout = getTextLayout(lineIndex);
+// String text = content.getLine(lineIndex);
+// int offset = content.getOffsetAtLine(lineIndex);
+// int height = layout.getBounds().height;
+// return new LineDrawInfo(lineIndex, layout, text, offset, height);
+//}
+//
+//int drawLines(int startLine, int endLine, int begX, int begY, int endY, GC gc, Color widgetBackground, Color widgetForeground) {
+// // When fixed line metrics is in effect, tall unicode characters
+// // will not always fit line's height. In this case, they will
+// // draw out of line's bounds. To prevent them from being clipped
+// // by next line's background, paint entire background before any
+// // foreground.
+// // I considered to make this mode default, but was worried about
+// // potential regressions in various legacy code. For example, it
+// // could change something about line heights/colors during
+// // painting. While this doesn't sound like a good thing to do, yet
+// // still, I'd rather stay safe.
+// final boolean drawBackBeforeFore = (fixedLineMetrics != null);
+//
+// if (drawBackBeforeFore) {
+// // Cache drawing information
+// final List drawInfos = new ArrayList<>();
+// int y = begY;
+// for (int iLine = startLine; y < endY && iLine < endLine; iLine++) {
+// LineDrawInfo lineInfo = makeLineDrawInfo(iLine);
+// drawInfos.add(lineInfo);
+// y += lineInfo.height;
+// }
+//
+// // Draw background
+// y = begY;
+// for (LineDrawInfo lineInfo : drawInfos) {
+// drawLineBackground(lineInfo, y, gc, widgetBackground);
+// y += lineInfo.height;
+// }
+//
+// // Draw foreground
+// y = begY;
+// for (LineDrawInfo lineInfo : drawInfos) {
+// drawLineForeground(lineInfo, begX, y, gc, widgetForeground);
+// y += lineInfo.height;
+// }
+//
+// // cleanup
+// for (LineDrawInfo lineInfo : drawInfos) {
+// disposeTextLayout(lineInfo.layout);
+// }
+//
+// return y - begY;
+// }
+//
+// int y = begY;
+// for (int iLine = startLine; y < endY && iLine < endLine; iLine++) {
+// LineDrawInfo lineInfo = makeLineDrawInfo(iLine);
+// drawLineBackground(lineInfo, y, gc, widgetBackground);
+// drawLineForeground(lineInfo, begX, y, gc, widgetForeground);
+// disposeTextLayout(lineInfo.layout);
+// y += lineInfo.height;
+// }
+// return y - begY;
+//}
+//
+//private void drawLineBackground(LineDrawInfo lineInfo, int paintY, GC gc, Color widgetBackground) {
+// Rectangle client = styledText.getClientArea();
+// Color lineBackground = getLineBackground(lineInfo.index, null);
+// StyledTextEvent event = styledText.getLineBackgroundData(lineInfo.offset, lineInfo.text);
+// if (event != null && event.lineBackground != null) lineBackground = event.lineBackground;
+// int verticalIndent = lineInfo.layout.getVerticalIndent();
+//
+// if (lineBackground != null) {
+// if (verticalIndent > 0) {
+// gc.setBackground(widgetBackground);
+// gc.fillRectangle(client.x, paintY, client.width, verticalIndent);
+// }
+// gc.setBackground(lineBackground);
+// gc.fillRectangle(client.x, paintY + verticalIndent, client.width, lineInfo.height - verticalIndent);
+// } else {
+// gc.setBackground(widgetBackground);
+// styledText.drawBackground(gc, client.x, paintY, client.width, lineInfo.height);
+// }
+//}
+//
+//private void drawLineForeground(LineDrawInfo lineInfo, int paintX, int paintY, GC gc, Color widgetForeground) {
+// int lineLength = lineInfo.text.length();
+// gc.setForeground(widgetForeground);
+// Point[] selection = intersectingRelativeNonEmptySelections(lineInfo.offset, lineInfo.offset + lineLength);
+// if (styledText.getBlockSelection() || selection.length == 0) {
+// lineInfo.layout.draw(gc, paintX, paintY);
+// } else {
+// Color selectionFg = styledText.getSelectionForeground();
+// Color selectionBg = styledText.getSelectionBackground();
+// final int baseFlags = (styledText.getStyle() & SWT.FULL_SELECTION) != 0 ? SWT.FULL_SELECTION : SWT.DELIMITER_SELECTION;
+// for (Point relativeSelection : selection) {
+// int start = Math.max(0, relativeSelection.x);
+// int end = Math.min(lineLength, relativeSelection.y);
+// int flags = baseFlags;
+// if (relativeSelection.x <= lineLength && lineLength < relativeSelection.y ) {
+// flags |= SWT.LAST_LINE_SELECTION;
+// }
+// // TODO calling draw multiple times here prints line multiple times, overriding some colors
+// lineInfo.layout.draw(gc, paintX, paintY, start, end - 1, selectionFg, selectionBg, flags);
+// }
+// }
+//
+// // draw objects
+// Bullet bullet = null;
+// int bulletIndex = -1;
+// if (bullets != null) {
+// if (bulletsIndices != null) {
+// int index = lineInfo.index - topIndex;
+// if (0 <= index && index < CACHE_SIZE) {
+// bullet = bullets[index];
+// bulletIndex = bulletsIndices[index];
+// }
+// } else {
+// for (Bullet b : bullets) {
+// bullet = b;
+// bulletIndex = bullet.indexOf(lineInfo.index);
+// if (bulletIndex != -1) break;
+// }
+// }
+// }
+// if (bulletIndex != -1 && bullet != null) {
+// FontMetrics metrics = lineInfo.layout.getLineMetrics(0);
+// int lineAscent = metrics.getAscent() + metrics.getLeading();
+// if (bullet.type == ST.BULLET_CUSTOM) {
+// bullet.style.start = lineInfo.offset;
+// styledText.paintObject(gc, paintX, paintY, lineAscent, metrics.getDescent(), bullet.style, bullet, bulletIndex);
+// } else {
+// drawBullet(bullet, gc, paintX, paintY, bulletIndex, lineAscent, metrics.getDescent());
+// }
+// }
+// TextStyle[] styles = lineInfo.layout.getStyles();
+// int[] ranges = null;
+// for (int i = 0; i < styles.length; i++) {
+// if (styles[i].metrics != null) {
+// if (ranges == null) ranges = lineInfo.layout.getRanges();
+// int start = ranges[i << 1];
+// int length = ranges[(i << 1) + 1] - start + 1;
+// Point point = lineInfo.layout.getLocation(start, false);
+// FontMetrics metrics = lineInfo.layout.getLineMetrics(lineInfo.layout.getLineIndex(start));
+// StyleRange style = (StyleRange)((StyleRange)styles[i]).clone();
+// style.start = start + lineInfo.offset;
+// style.length = length;
+// int lineAscent = metrics.getAscent() + metrics.getLeading();
+// styledText.paintObject(gc, point.x + paintX, point.y + paintY, lineAscent, metrics.getDescent(), style, null, 0);
+// }
+// }
+//}
+//
+//private Point[] intersectingRelativeNonEmptySelections(int fromOffset, int toOffset) {
+// int[] selectionRanges = styledText.getSelectionRanges();
+// int lineLength = toOffset - fromOffset;
+// List res = new ArrayList<>();
+// for (int i = 0; i < selectionRanges.length; i += 2) {
+// // ranges are assumed to be sorted by start offset, then (positive)length or higher end offset
+// Point relativeSelection = new Point(selectionRanges[i] - fromOffset, selectionRanges[i] + selectionRanges[i + 1] - fromOffset);
+// if (relativeSelection.x != relativeSelection.y &&
+// relativeSelection.x <= lineLength && relativeSelection.y >= 0) {
+// res.add(relativeSelection);
+// }
+// }
+// return res.toArray(new Point[res.size()]);
+//}
+//
+//int getBaseline() {
+// return ascent;
+//}
+//int getCachedLineHeight(int lineIndex) {
+// return getLineHeight(lineIndex, false);
+//}
+//Font getFont(int style) {
+// switch (style) {
+// case SWT.BOLD:
+// if (boldFont != null) return boldFont;
+// return boldFont = new Font(device, getFontData(style));
+// case SWT.ITALIC:
+// if (italicFont != null) return italicFont;
+// return italicFont = new Font(device, getFontData(style));
+// case SWT.BOLD | SWT.ITALIC:
+// if (boldItalicFont != null) return boldItalicFont;
+// return boldItalicFont = new Font(device, getFontData(style));
+// default:
+// return regularFont;
+// }
+//}
+//FontData[] getFontData(int style) {
+// FontData[] fontDatas = regularFont.getFontData();
+// for (FontData fontData : fontDatas) {
+// fontData.setStyle(style);
+// }
+// return fontDatas;
+//}
+//int getHeight () {
+// int defaultLineHeight = getLineHeight();
+// if (styledText.isFixedLineHeight()) {
+// return lineCount * defaultLineHeight + styledText.topMargin + styledText.bottomMargin;
+// }
+// int totalHeight = 0;
+// int width = styledText.getWrapWidth();
+// for (int i = 0; i < lineCount; i++) {
+// LineSizeInfo line = getLineSize(i);
+// int height = line.height;
+// if (line.needsRecalculateHeight()) {
+// if (width > 0) {
+// int length = content.getLine(i).length();
+// height = ((length * averageCharWidth / width) + 1) * defaultLineHeight;
+// } else {
+// height = defaultLineHeight;
+// }
+// }
+// totalHeight += height;
+// }
+// return totalHeight + styledText.topMargin + styledText.bottomMargin;
+//}
+//boolean hasLink(int offset) {
+// if (offset == -1) return false;
+// int lineIndex = content.getLineAtOffset(offset);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// String line = content.getLine(lineIndex);
+// StyledTextEvent event = styledText.getLineStyleData(lineOffset, line);
+// if (event != null) {
+// StyleRange[] styles = event.styles;
+// if (styles != null) {
+// int[] ranges = event.ranges;
+// if (ranges != null) {
+// for (int i = 0; i < ranges.length; i+=2) {
+// if (ranges[i] <= offset && offset < ranges[i] + ranges[i+1] && styles[i >> 1].underline && styles[i >> 1].underlineStyle == SWT.UNDERLINE_LINK) {
+// return true;
+// }
+// }
+// } else {
+// for (StyleRange style : styles) {
+// if (style.start <= offset && offset < style.start + style.length && style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) {
+// return true;
+// }
+// }
+// }
+// }
+// } else {
+// if (ranges != null) {
+// int rangeCount = styleCount << 1;
+// int index = getRangeIndex(offset, -1, rangeCount);
+// if (index >= rangeCount) return false;
+// int rangeStart = ranges[index];
+// int rangeLength = ranges[index + 1];
+// StyleRange rangeStyle = styles[index >> 1];
+// if (rangeStart <= offset && offset < rangeStart + rangeLength && rangeStyle.underline && rangeStyle.underlineStyle == SWT.UNDERLINE_LINK) {
+// return true;
+// }
+// }
+// }
+// return false;
+//}
+//int getLineAlignment(int index, int defaultAlignment) {
+// if (lines == null) return defaultAlignment;
+// LineInfo info = lines[index];
+// if (info != null && (info.flags & ALIGNMENT) != 0) {
+// return info.alignment;
+// }
+// return defaultAlignment;
+//}
+//Color getLineBackground(int index, Color defaultBackground) {
+// if (lines == null) return defaultBackground;
+// LineInfo info = lines[index];
+// if (info != null && (info.flags & BACKGROUND) != 0) {
+// return info.background;
+// }
+// return defaultBackground;
+//}
+//Bullet getLineBullet (int index, Bullet defaultBullet) {
+// if (bullets == null) return defaultBullet;
+// if (bulletsIndices != null) return defaultBullet;
+// for (Bullet bullet : bullets) {
+// if (bullet.indexOf(index) != -1) return bullet;
+// }
+// return defaultBullet;
+//}
+//int getLineHeight() {
+// return ascent + descent;
+//}
+//int getLineHeight(int lineIndex) {
+// return getLineHeight(lineIndex, true);
+//}
+//int getLineHeight(int lineIndex, boolean exact) {
+// LineSizeInfo line = getLineSize(lineIndex);
+// if (line.needsRecalculateHeight()) {
+// // here we are in "variable line height", the call of calculate which uses TextLayout is very slow
+// // so use the average line height of all calculated lines when many heights are needed e.g. for scrolling.
+// if (isVariableHeight(lineIndex)) {
+// if (exact) {
+// calculate(lineIndex, 1);
+// } else {
+// return Math.round(averageLineHeight);
+// }
+// } else {
+// line.height = getLineHeight() + getLineSpacing(lineIndex) + getLineVerticalIndent(lineIndex);
+// }
+// }
+// return line.height;
+//}
+///**
+// * Returns true if the given line can use the default line height and false
+// * otherwise.
+// *
+// * @param lineIndex
+// * line index
+// * @return true if the given line can use the default line height and false
+// * otherwise.
+// */
+//private boolean isVariableHeight(int lineIndex) {
+// if (styledText.isWordWrap()) {
+// // In word wrap mode, the line height must be recomputed with TextLayout
+// return true;
+// }
+// StyleRange[] styles = getStylesForLine(lineIndex);
+// if (styles != null) {
+// for (StyleRange style : styles) {
+// if (style.isVariableHeight()) {
+// // style is variable height
+// return true;
+// }
+// }
+// }
+// return false;
+//}
+///**
+// * returns true if the given line index defines custom line spacing and false
+// * otherwise.
+// *
+// * @param lineIndex
+// * the line index.
+// * @return true if the given line index defines custom line spacing and false
+// * otherwise.
+// */
+//private int getLineSpacing(int lineIndex) {
+// if (styledText.lineSpacing > 0) {
+// return styledText.lineSpacing;
+// } else if (lineSpacingProvider != null) {
+// Integer lineSpacing = lineSpacingProvider.getLineSpacing(lineIndex);
+// if (lineSpacing != null) {
+// return lineSpacing;
+// }
+// }
+// return 0;
+//}
+///**
+// * Returns styles range for the given line index and null otherwise.
+// *
+// * @param lineIndex
+// * the line index.
+// * @return styles range for the given line index and null otherwise.
+// */
+//private StyleRange[] getStylesForLine(int lineIndex) {
+// int start = styledText.getOffsetAtLine(lineIndex);
+// int length = styledText.getLine(lineIndex).length();
+// return getStyleRanges(start, length, false);
+//}
+//int getLineIndent(int index, int defaultIndent) {
+// if (lines == null) return defaultIndent;
+// LineInfo info = lines[index];
+// if (info != null && (info.flags & INDENT) != 0) {
+// return info.indent;
+// }
+// return defaultIndent;
+//}
+//int getLineVerticalIndent(int index) {
+// if (lines == null) return 0;
+// LineInfo info = lines[index];
+// if (info != null && (info.flags & VERTICAL_INDENT) != 0) {
+// return info.verticalIndent;
+// }
+// return 0;
+//}
+//int getLineWrapIndent(int index, int defaultWrapIndent) {
+// if (lines == null) return defaultWrapIndent;
+// LineInfo info = lines[index];
+// if (info != null && (info.flags & WRAP_INDENT) != 0) {
+// return info.wrapIndent;
+// }
+// return defaultWrapIndent;
+//}
+//boolean getLineJustify(int index, boolean defaultJustify) {
+// if (lines == null) return defaultJustify;
+// LineInfo info = lines[index];
+// if (info != null && (info.flags & JUSTIFY) != 0) {
+// return info.justify;
+// }
+// return defaultJustify;
+//}
+//int[] getLineTabStops(int index, int[] defaultTabStops) {
+// if (lines == null) return defaultTabStops;
+// LineInfo info = lines[index];
+// if (info != null && (info.flags & TABSTOPS) != 0) {
+// return info.tabStops;
+// }
+// return defaultTabStops;
+//}
+//StyledTextLineSpacingProvider getLineSpacingProvider() {
+// return lineSpacingProvider;
+//}
+//int getRangeIndex(int offset, int low, int high) {
+// if (styleCount == 0) return 0;
+// if (ranges != null) {
+// while (high - low > 2) {
+// int index = ((high + low) / 2) / 2 * 2;
+// int end = ranges[index] + ranges[index + 1];
+// if (end > offset) {
+// high = index;
+// } else {
+// low = index;
+// }
+// }
+// } else {
+// while (high - low > 1) {
+// int index = ((high + low) / 2);
+// int end = styles[index].start + styles[index].length;
+// if (end > offset) {
+// high = index;
+// } else {
+// low = index;
+// }
+// }
+// }
+// return high;
+//}
+//int[] getRanges(int start, int length) {
+// if (length == 0) return null;
+// int[] newRanges;
+// int end = start + length - 1;
+// if (ranges != null) {
+// int rangeCount = styleCount << 1;
+// int rangeStart = getRangeIndex(start, -1, rangeCount);
+// if (rangeStart >= rangeCount) return null;
+// if (ranges[rangeStart] > end) return null;
+// int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount));
+// if (ranges[rangeEnd] > end) rangeEnd = Math.max(rangeStart, rangeEnd - 2);
+// newRanges = new int[rangeEnd - rangeStart + 2];
+// System.arraycopy(ranges, rangeStart, newRanges, 0, newRanges.length);
+// } else {
+// int rangeStart = getRangeIndex(start, -1, styleCount);
+// if (rangeStart >= styleCount) return null;
+// if (styles[rangeStart].start > end) return null;
+// int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount));
+// if (styles[rangeEnd].start > end) rangeEnd = Math.max(rangeStart, rangeEnd - 1);
+// newRanges = new int[(rangeEnd - rangeStart + 1) << 1];
+// for (int i = rangeStart, j = 0; i <= rangeEnd; i++, j += 2) {
+// StyleRange style = styles[i];
+// newRanges[j] = style.start;
+// newRanges[j + 1] = style.length;
+// }
+// }
+// if (start > newRanges[0]) {
+// newRanges[1] = newRanges[0] + newRanges[1] - start;
+// newRanges[0] = start;
+// }
+// if (end < newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1] - 1) {
+// newRanges[newRanges.length - 1] = end - newRanges[newRanges.length - 2] + 1;
+// }
+// return newRanges;
+//}
+//StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) {
+// if (length == 0) return null;
+// StyleRange[] newStyles;
+// int end = start + length - 1;
+// if (ranges != null) {
+// int rangeCount = styleCount << 1;
+// int rangeStart = getRangeIndex(start, -1, rangeCount);
+// if (rangeStart >= rangeCount) return null;
+// if (ranges[rangeStart] > end) return null;
+// int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount));
+// if (ranges[rangeEnd] > end) rangeEnd = Math.max(rangeStart, rangeEnd - 2);
+// newStyles = new StyleRange[((rangeEnd - rangeStart) >> 1) + 1];
+// if (includeRanges) {
+// for (int i = rangeStart, j = 0; i <= rangeEnd; i += 2, j++) {
+// newStyles[j] = (StyleRange)styles[i >> 1].clone();
+// newStyles[j].start = ranges[i];
+// newStyles[j].length = ranges[i + 1];
+// }
+// } else {
+// System.arraycopy(styles, rangeStart >> 1, newStyles, 0, newStyles.length);
+// }
+// } else {
+// int rangeStart = getRangeIndex(start, -1, styleCount);
+// if (rangeStart >= styleCount) return null;
+// if (styles[rangeStart].start > end) return null;
+// int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount));
+// if (styles[rangeEnd].start > end) rangeEnd = Math.max(rangeStart, rangeEnd - 1);
+// newStyles = new StyleRange[rangeEnd - rangeStart + 1];
+// System.arraycopy(styles, rangeStart, newStyles, 0, newStyles.length);
+// }
+// if (includeRanges || ranges == null) {
+// StyleRange style = newStyles[0];
+// if (start > style.start) {
+// newStyles[0] = style = (StyleRange)style.clone();
+// style.length = style.start + style.length - start;
+// style.start = start;
+// }
+// style = newStyles[newStyles.length - 1];
+// if (end < style.start + style.length - 1) {
+// newStyles[newStyles.length - 1] = style = (StyleRange)style.clone();
+// style.length = end - style.start + 1;
+// }
+// }
+// return newStyles;
+//}
+//StyleRange getStyleRange(StyleRange style) {
+// if (style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) hasLinks = true;
+// if (style.start == 0 && style.length == 0 && style.fontStyle == SWT.NORMAL) return style;
+// StyleRange clone = (StyleRange)style.clone();
+// clone.start = clone.length = 0;
+// clone.fontStyle = SWT.NORMAL;
+// if (clone.font == null) clone.font = getFont(style.fontStyle);
+// return clone;
+//}
+//TextLayout getTextLayout(int lineIndex) {
+// if (lineSpacingProvider == null) {
+// return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), styledText.lineSpacing);
+// }
+// // Compute line spacing for the given line index.
+// int newLineSpacing = styledText.lineSpacing;
+// Integer spacing = lineSpacingProvider.getLineSpacing(lineIndex);
+// if (spacing != null && spacing.intValue() >= 0) {
+// newLineSpacing = spacing;
+// }
+// // Check if line spacing has not changed
+// if (isSameLineSpacing(lineIndex, newLineSpacing)) {
+// return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), newLineSpacing);
+// }
+// // Get text layout with original StyledText line spacing.
+// TextLayout layout = getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(),
+// styledText.lineSpacing);
+// if (layout.getSpacing() != newLineSpacing) {
+// layout.setSpacing(newLineSpacing);
+// if (lineSpacingComputing) {
+// return layout;
+// }
+// try {
+// /* Call of resetCache, setCaretLocation, redraw call getTextLayout method
+// * To avoid having stack overflow, lineSpacingComputing flag is used to call
+// * resetCache, setCaretLocation, redraw methods only at the end of the compute of all lines spacing.
+// */
+// lineSpacingComputing = true;
+// styledText.resetCache(lineIndex, 1);
+// styledText.setCaretLocations();
+// styledText.redraw();
+// } finally {
+// lineSpacingComputing = false;
+// }
+// }
+// return layout;
+//}
+//boolean isSameLineSpacing(int lineIndex, int newLineSpacing) {
+// if (layouts == null) {
+// return false;
+// }
+// int layoutIndex = lineIndex - topIndex;
+// if (0 <= layoutIndex && layoutIndex < layouts.length) {
+// TextLayout layout = layouts[layoutIndex];
+// return layout != null && !layout.isDisposed() && layout.getSpacing() == newLineSpacing;
+// }
+// return false;
+//}
+//
+//private static final class StyleEntry {
+// public final int start;
+// public final int end;
+// public final TextStyle style;
+//
+// public StyleEntry(TextStyle style, int start, int end) {
+// this.style = style;
+// this.start = start;
+// this.end = end;
+// }
+//}
+//
+//TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpacing) {
+// TextLayout layout = null;
+// if (styledText != null) {
+// int topIndex = styledText.topIndex > 0 ? styledText.topIndex - 1 : 0;
+// if (layouts == null || topIndex != this.topIndex) {
+// TextLayout[] newLayouts = new TextLayout[CACHE_SIZE];
+// if (layouts != null) {
+// for (int i = 0; i < layouts.length; i++) {
+// if (layouts[i] != null) {
+// int layoutIndex = (i + this.topIndex) - topIndex;
+// if (0 <= layoutIndex && layoutIndex < newLayouts.length) {
+// newLayouts[layoutIndex] = layouts[i];
+// } else {
+// layouts[i].dispose();
+// }
+// }
+// }
+// }
+// if (bullets != null && bulletsIndices != null && topIndex != this.topIndex) {
+// int delta = topIndex - this.topIndex;
+// if (delta > 0) {
+// if (delta < bullets.length) {
+// System.arraycopy(bullets, delta, bullets, 0, bullets.length - delta);
+// System.arraycopy(bulletsIndices, delta, bulletsIndices, 0, bulletsIndices.length - delta);
+// }
+// int startIndex = Math.max(0, bullets.length - delta);
+// for (int i = startIndex; i < bullets.length; i++) bullets[i] = null;
+// } else {
+// if (-delta < bullets.length) {
+// System.arraycopy(bullets, 0, bullets, -delta, bullets.length + delta);
+// System.arraycopy(bulletsIndices, 0, bulletsIndices, -delta, bulletsIndices.length + delta);
+// }
+// int endIndex = Math.min(bullets.length, -delta);
+// for (int i = 0; i < endIndex; i++) bullets[i] = null;
+// }
+// }
+// this.topIndex = topIndex;
+// layouts = newLayouts;
+// }
+// if (layouts != null) {
+// int layoutIndex = lineIndex - topIndex;
+// if (0 <= layoutIndex && layoutIndex < layouts.length) {
+// layout = layouts[layoutIndex];
+// if (layout != null) {
+// // Bug 520374: lineIndex can be >= linesSize.length
+// if(lineIndex < lineSizes.length && getLineSize(lineIndex).canLayout()) {
+// return layout;
+// }
+// } else {
+// layout = layouts[layoutIndex] = new TextLayout(device);
+// }
+// }
+// }
+// }
+// if (layout == null) layout = new TextLayout(device);
+// String line = content.getLine(lineIndex);
+// int lineOffset = content.getOffsetAtLine(lineIndex);
+// int[] segments = null;
+// char[] segmentChars = null;
+// int indent = 0;
+// int wrapIndent = 0;
+// int verticalIndent = 0;
+// int alignment = SWT.LEFT;
+// int textDirection = orientation;
+// boolean justify = false;
+// int[] tabs = {tabWidth};
+// Bullet bullet = null;
+// int[] ranges = null;
+// StyleRange[] styles = null;
+// int rangeStart = 0, styleCount = 0;
+// StyledTextEvent event = null;
+// if (styledText != null) {
+// event = styledText.getBidiSegments(lineOffset, line);
+// if (event != null) {
+// segments = event.segments;
+// segmentChars = event.segmentsChars;
+// }
+// event = styledText.getLineStyleData(lineOffset, line);
+// indent = styledText.indent;
+// wrapIndent = styledText.wrapIndent;
+// alignment = styledText.alignment;
+// if (styledText.isAutoDirection()) {
+// textDirection = SWT.AUTO_TEXT_DIRECTION;
+// } else if ((styledText.getStyle() & SWT.FLIP_TEXT_DIRECTION) != 0) {
+// textDirection = orientation == SWT.RIGHT_TO_LEFT ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT;
+// }
+// justify = styledText.justify;
+// if (styledText.tabs != null) tabs = styledText.tabs;
+// }
+// if (event != null) {
+// indent = event.indent;
+// verticalIndent = event.verticalIndent;
+// wrapIndent = event.wrapIndent;
+// alignment = event.alignment;
+// justify = event.justify;
+// bullet = event.bullet;
+// ranges = event.ranges;
+// styles = event.styles;
+// if (event.tabStops != null) tabs = event.tabStops;
+// if (styles != null) {
+// styleCount = styles.length;
+// if (styledText.isFixedLineHeight()) {
+// for (int i = 0; i < styleCount; i++) {
+// if (styles[i].isVariableHeight()) {
+// styledText.hasStyleWithVariableHeight = true;
+// styledText.verticalScrollOffset = -1;
+// styledText.redraw();
+// break;
+// }
+// }
+// }
+// }
+// if (bullets == null || bulletsIndices == null) {
+// bullets = new Bullet[CACHE_SIZE];
+// bulletsIndices = new int[CACHE_SIZE];
+// }
+// int index = lineIndex - topIndex;
+// if (0 <= index && index < CACHE_SIZE) {
+// bullets[index] = bullet;
+// bulletsIndices[index] = event.bulletIndex;
+// }
+// } else {
+// if (lines != null) {
+// LineInfo info = lines[lineIndex];
+// if (info != null) {
+// if ((info.flags & INDENT) != 0) indent = info.indent;
+// if ((info.flags & VERTICAL_INDENT) != 0) verticalIndent = info.verticalIndent;
+// if ((info.flags & WRAP_INDENT) != 0) wrapIndent = info.wrapIndent;
+// if ((info.flags & ALIGNMENT) != 0) alignment = info.alignment;
+// if ((info.flags & JUSTIFY) != 0) justify = info.justify;
+// if ((info.flags & SEGMENTS) != 0) segments = info.segments;
+// if ((info.flags & SEGMENT_CHARS) != 0) segmentChars = info.segmentsChars;
+// if ((info.flags & TABSTOPS) != 0) tabs = info.tabStops;
+// }
+// }
+// if (bulletsIndices != null) {
+// bullets = null;
+// bulletsIndices = null;
+// }
+// if (bullets != null) {
+// for (Bullet b : bullets) {
+// if (b.indexOf(lineIndex) != -1) {
+// bullet = b;
+// break;
+// }
+// }
+// }
+// ranges = this.ranges;
+// styles = this.styles;
+// styleCount = this.styleCount;
+// if (ranges != null) {
+// rangeStart = getRangeIndex(lineOffset, -1, styleCount << 1);
+// } else {
+// rangeStart = getRangeIndex(lineOffset, -1, styleCount);
+// }
+// }
+// if (bullet != null) {
+// StyleRange style = bullet.style;
+// GlyphMetrics metrics = style.metrics;
+// indent += metrics.width;
+// }
+//
+// // prepare styles, as it may change the line content, do it before calling layout.setText()
+// // This needs to happen early to handle the case of GlyphMetrics on \t.
+// // The root cause is that TextLayout doesn't return the right value for the bounds when
+// // GlyphMetrics are applied on \t. A better fix could be implemented directly in (all 3)
+// // TextLayout classes.
+// List styleEntries = new ArrayList<>();
+// int lastOffset = 0;
+// int length = line.length();
+// if (styles != null) {
+// if (ranges != null) {
+// int rangeCount = styleCount << 1;
+// for (int i = rangeStart; i < rangeCount; i += 2) {
+// int start, end;
+// if (lineOffset > ranges[i]) {
+// start = 0;
+// end = Math.min (length, ranges[i + 1] - lineOffset + ranges[i]);
+// } else {
+// start = ranges[i] - lineOffset;
+// end = Math.min(length, start + ranges[i + 1]);
+// }
+// if (start >= length) break;
+// if (lastOffset < start) {
+// styleEntries.add(new StyleEntry(null, lastOffset, start - 1));
+// }
+// TextStyle style = getStyleRange(styles[i >> 1]);
+// int endIndex = Math.max(start, Math.min(length, end + 1));
+// if (style.metrics != null && line.substring(start, endIndex).contains("\t")) {
+// line =
+// line.substring(0, start) +
+// line.substring(start, endIndex).replace('\t', ' ') +
+// (end < line.length() ? line.substring(end + 1, line.length()) : "");
+// }
+// styleEntries.add(new StyleEntry(style, start, end));
+// lastOffset = Math.max(lastOffset, end);
+// }
+// } else {
+// for (int i = rangeStart; i < styleCount; i++) {
+// int start, end;
+// if (lineOffset > styles[i].start) {
+// start = 0;
+// end = Math.min (length, styles[i].length - lineOffset + styles[i].start);
+// } else {
+// start = styles[i].start - lineOffset;
+// end = Math.min(length, start + styles[i].length);
+// }
+// if (start >= length) break;
+// if (lastOffset < start) {
+// styleEntries.add(new StyleEntry(null, lastOffset, start - 1));
+// }
+// TextStyle style = getStyleRange(styles[i]);
+// int endIndex = Math.max(start, Math.min(length, end + 1));
+// if (style.metrics != null && line.substring(start, endIndex).contains("\t")) {
+// line =
+// line.substring(0, start) +
+// line.substring(start, endIndex).replace('\t', ' ') +
+// (end < line.length() ? line.substring(end + 1, line.length()) : "");
+// }
+// styleEntries.add(new StyleEntry(style, start, end));
+// lastOffset = Math.max(lastOffset, end);
+// }
+// }
+// }
+// if (lastOffset < length) styleEntries.add(new StyleEntry(null, lastOffset, length));
+//
+// layout.setFont(regularFont);
+// layout.setAscent(ascent);
+// layout.setDescent(descent);
+// layout.setFixedLineMetrics(fixedLineMetrics);
+// layout.setText(line);
+// layout.setOrientation(orientation);
+// layout.setSegments(segments);
+// layout.setSegmentsChars(segmentChars);
+// layout.setWidth(width);
+// layout.setSpacing(lineSpacing);
+// layout.setTabs(tabs);
+// layout.setDefaultTabWidth(tabLength);
+// layout.setIndent(indent);
+// layout.setVerticalIndent(verticalIndent);
+// layout.setWrapIndent(wrapIndent);
+// layout.setAlignment(alignment);
+// layout.setJustify(justify);
+// layout.setTextDirection(textDirection);
+// // apply styles, must be done after layout.setText()
+// for (StyleEntry styleEntry : styleEntries) {
+// layout.setStyle(styleEntry.style, styleEntry.start, styleEntry.end);
+// }
+//
+// if (styledText != null && styledText.ime != null) {
+// IME ime = styledText.ime;
+// int compositionOffset = ime.getCompositionOffset();
+// if (compositionOffset != -1 && compositionOffset <= content.getCharCount()) {
+// int commitCount = ime.getCommitCount();
+// int compositionLength = ime.getText().length();
+// if (compositionLength != commitCount) {
+// int compositionLine = content.getLineAtOffset(compositionOffset);
+// if (compositionLine == lineIndex) {
+// int[] imeRanges = ime.getRanges();
+// TextStyle[] imeStyles = ime.getStyles();
+// if (imeRanges.length > 0) {
+// for (int i = 0; i < imeStyles.length; i++) {
+// int start = imeRanges[i*2] - lineOffset;
+// int end = imeRanges[i*2+1] - lineOffset;
+// TextStyle imeStyle = imeStyles[i], userStyle;
+// for (int j = start; j <= end; j++) {
+// if (!(0 <= j && j < length)) break;
+// userStyle = layout.getStyle(cap(layout, j));
+// if (userStyle == null && j > 0) userStyle = layout.getStyle(cap(layout, j - 1));
+// if (userStyle == null && j + 1 < length) userStyle = layout.getStyle(cap(layout, j + 1));
+// if (userStyle == null) {
+// layout.setStyle(imeStyle, j, j);
+// } else {
+// TextStyle newStyle = new TextStyle(imeStyle);
+// if (newStyle.font == null) newStyle.font = userStyle.font;
+// if (newStyle.foreground == null) newStyle.foreground = userStyle.foreground;
+// if (newStyle.background == null) newStyle.background = userStyle.background;
+// layout.setStyle(newStyle, j, j);
+// }
+// }
+// }
+// } else {
+// int start = compositionOffset - lineOffset;
+// int end = start + compositionLength - 1;
+// TextStyle userStyle = layout.getStyle(cap(layout, start));
+// if (userStyle == null) {
+// if (start > 0) userStyle = layout.getStyle(cap(layout, start - 1));
+// if (userStyle == null && end + 1 < length) userStyle = layout.getStyle(cap(layout, end + 1));
+// if (userStyle != null) {
+// TextStyle newStyle = new TextStyle();
+// newStyle.font = userStyle.font;
+// newStyle.foreground = userStyle.foreground;
+// newStyle.background = userStyle.background;
+// layout.setStyle(newStyle, start, end);
+// }
+// }
+// }
+// }
+// }
+// }
+// }
+//
+// if (styledText != null && styledText.isFixedLineHeight()) {
+// int index = -1;
+// int lineCount = layout.getLineCount();
+// int height = getLineHeight();
+// for (int i = 0; i < lineCount; i++) {
+// int lineHeight = layout.getLineBounds(i).height;
+// if (lineHeight > height) {
+// height = lineHeight;
+// index = i;
+// }
+// }
+// if (index != -1) {
+// FontMetrics metrics = layout.getLineMetrics(index);
+// ascent = metrics.getAscent() + metrics.getLeading();
+// descent = metrics.getDescent();
+// if (layouts != null) {
+// for (TextLayout l : layouts) {
+// if (l != null && l != layout) {
+// l.setAscent(ascent);
+// l.setDescent(descent);
+// }
+// }
+// }
+// styledText.calculateScrollBars();
+// if (styledText.verticalScrollOffset != 0) {
+// int topIndex = styledText.topIndex;
+// int topIndexY = styledText.topIndexY;
+// int lineHeight = getLineHeight();
+// int newVerticalScrollOffset;
+// if (topIndexY >= 0) {
+// newVerticalScrollOffset = (topIndex - 1) * lineHeight + lineHeight - topIndexY;
+// } else {
+// newVerticalScrollOffset = topIndex * lineHeight - topIndexY;
+// }
+// styledText.scrollVertical(newVerticalScrollOffset - styledText.verticalScrollOffset, true);
+// }
+// if (styledText.isBidiCaret()) styledText.createCaretBitmaps();
+// styledText.caretDirection = SWT.NULL;
+// styledText.setCaretLocations();
+// styledText.redraw();
+// }
+// }
+// return layout;
+//}
+//int getWidth() {
+// return maxWidth;
+//}
+//void reset() {
+// if (layouts != null) {
+// for (TextLayout layout : layouts) {
+// if (layout != null) layout.dispose();
+// }
+// layouts = null;
+// }
+// topIndex = -1;
+// stylesSetCount = styleCount = lineCount = 0;
+// ranges = null;
+// styles = null;
+// stylesSet = null;
+// lines = null;
+// lineSizes = null;
+// bullets = null;
+// bulletsIndices = null;
+// redrawLines = null;
+// hasLinks = false;
+//}
+//void reset(int startLine, int lineCount) {
+// int endLine = startLine + lineCount;
+// if (startLine < 0 || endLine > lineSizes.length) return;
+// SortedSet lines = new TreeSet<>();
+// for (int i = startLine; i < endLine; i++) {
+// lines.add(Integer.valueOf(i));
+// }
+// reset(lines);
+//}
+//void reset(Set lines) {
+// if (lines == null || lines.isEmpty()) return;
+// int resetLineCount = 0;
+// for (Integer line : lines) {
+// if (line >= 0 || line < lineCount) {
+// resetLineCount++;
+// getLineSize(line.intValue()).resetSize();
+// }
+// }
+// if (linesInAverageLineHeight > resetLineCount) {
+// linesInAverageLineHeight -= resetLineCount;
+// } else {
+// linesInAverageLineHeight = 0;
+// averageLineHeight = 0.0f;
+// }
+// if (lines.contains(Integer.valueOf(maxWidthLineIndex))) {
+// maxWidth = 0;
+// maxWidthLineIndex = -1;
+// if (resetLineCount != this.lineCount) {
+// for (int i = 0; i < this.lineCount; i++) {
+// LineSizeInfo lineSize = getLineSize(i);
+// if (lineSize.width > maxWidth) {
+// maxWidth = lineSize.width;
+// maxWidthLineIndex = i;
+// }
+// }
+// }
+// }
+//}
+//void setContent(StyledTextContent content) {
+// reset();
+// this.content = content;
+// lineCount = content.getLineCount();
+// lineSizes = new LineSizeInfo[lineCount];
+// maxWidth = 0;
+// maxWidthLineIndex = -1;
+// reset(0, lineCount);
+//}
+//
+///**
+// * See {@link TextLayout#setFixedLineMetrics}
+// *
+// * @since 3.125
+// */
+//public void setFixedLineMetrics(FontMetrics metrics) {
+// fixedLineMetrics = metrics;
+//}
+//
+//void setFont(Font font, int tabs) {
+// TextLayout layout = new TextLayout(device);
+// layout.setFont(regularFont);
+// tabLength = tabs;
+// if (font != null) {
+// if (boldFont != null) boldFont.dispose();
+// if (italicFont != null) italicFont.dispose();
+// if (boldItalicFont != null) boldItalicFont.dispose();
+// boldFont = italicFont = boldItalicFont = null;
+// regularFont = font;
+// layout.setText(" ");
+// layout.setFont(font);
+// layout.setStyle(new TextStyle(getFont(SWT.NORMAL), null, null), 0, 0);
+// layout.setStyle(new TextStyle(getFont(SWT.BOLD), null, null), 1, 1);
+// layout.setStyle(new TextStyle(getFont(SWT.ITALIC), null, null), 2, 2);
+// layout.setStyle(new TextStyle(getFont(SWT.BOLD | SWT.ITALIC), null, null), 3, 3);
+// FontMetrics metrics = layout.getLineMetrics(0);
+// ascent = metrics.getAscent() + metrics.getLeading();
+// descent = metrics.getDescent();
+// boldFont.dispose();
+// italicFont.dispose();
+// boldItalicFont.dispose();
+// boldFont = italicFont = boldItalicFont = null;
+// }
+// layout.dispose();
+// layout = new TextLayout(device);
+// layout.setFont(regularFont);
+// StringBuilder tabBuffer = new StringBuilder(tabs);
+// for (int i = 0; i < tabs; i++) {
+// tabBuffer.append(' ');
+// }
+// layout.setText(tabBuffer.toString());
+// tabWidth = layout.getBounds().width;
+// layout.dispose();
+// if (styledText != null) {
+// GC gc = new GC(styledText);
+// averageCharWidth = (int) gc.getFontMetrics().getAverageCharacterWidth();
+// fixedPitch = gc.stringExtent("l").x == gc.stringExtent("W").x; //$NON-NLS-1$ //$NON-NLS-2$
+// gc.dispose();
+// }
+//}
+//void setLineAlignment(int startLine, int count, int alignment) {
+// if (lines == null) lines = new LineInfo[lineCount];
+// for (int i = startLine; i < startLine + count; i++) {
+// if (lines[i] == null) {
+// lines[i] = new LineInfo();
+// }
+// lines[i].flags |= ALIGNMENT;
+// lines[i].alignment = alignment;
+// }
+//}
+//void setLineBackground(int startLine, int count, Color background) {
+// if (lines == null) lines = new LineInfo[lineCount];
+// for (int i = startLine; i < startLine + count; i++) {
+// if (lines[i] == null) {
+// lines[i] = new LineInfo();
+// }
+// lines[i].flags |= BACKGROUND;
+// lines[i].background = background;
+// }
+//}
+//void setLineBullet(int startLine, int count, Bullet bullet) {
+// if (bulletsIndices != null) {
+// bulletsIndices = null;
+// bullets = null;
+// }
+// if (bullets == null) {
+// if (bullet == null) return;
+// bullets = new Bullet[1];
+// bullets[0] = bullet;
+// }
+// int index = 0;
+// while (index < bullets.length) {
+// if (bullet == bullets[index]) break;
+// index++;
+// }
+// if (bullet != null) {
+// if (index == bullets.length) {
+// Bullet[] newBulletsList = new Bullet[bullets.length + 1];
+// System.arraycopy(bullets, 0, newBulletsList, 0, bullets.length);
+// newBulletsList[index] = bullet;
+// bullets = newBulletsList;
+// }
+// bullet.addIndices(startLine, count);
+// } else {
+// updateBullets(startLine, count, 0, false);
+// styledText.redrawLinesBullet(redrawLines);
+// redrawLines = null;
+// }
+//}
+//void setLineIndent(int startLine, int count, int indent) {
+// if (lines == null) lines = new LineInfo[lineCount];
+// for (int i = startLine; i < startLine + count; i++) {
+// if (lines[i] == null) {
+// lines[i] = new LineInfo();
+// }
+// lines[i].flags |= INDENT;
+// lines[i].indent = indent;
+// }
+//}
+//void setLineVerticalIndent(int lineIndex, int verticalLineIndent) {
+// if (lines == null)
+// lines = new LineInfo[lineCount];
+// if (lines[lineIndex] == null) {
+// lines[lineIndex] = new LineInfo();
+// }
+// lines[lineIndex].flags |= VERTICAL_INDENT;
+// int delta = verticalLineIndent - lines[lineIndex].verticalIndent;
+// lines[lineIndex].verticalIndent = verticalLineIndent;
+// LineSizeInfo info = getLineSize(lineIndex);
+// if (!info.needsRecalculateHeight()) {
+// info.height += delta;
+// }
+//}
+//void setLineWrapIndent(int startLine, int count, int wrapIndent) {
+// if (lines == null) lines = new LineInfo[lineCount];
+// for (int i = startLine; i < startLine + count; i++) {
+// if (lines[i] == null) {
+// lines[i] = new LineInfo();
+// }
+// lines[i].flags |= WRAP_INDENT;
+// lines[i].wrapIndent = wrapIndent;
+// }
+//}
+//void setLineJustify(int startLine, int count, boolean justify) {
+// if (lines == null) lines = new LineInfo[lineCount];
+// for (int i = startLine; i < startLine + count; i++) {
+// if (lines[i] == null) {
+// lines[i] = new LineInfo();
+// }
+// lines[i].flags |= JUSTIFY;
+// lines[i].justify = justify;
+// }
+//}
+//void setLineSegments(int startLine, int count, int[] segments) {
+// if (lines == null) lines = new LineInfo[lineCount];
+// for (int i = startLine; i < startLine + count; i++) {
+// if (lines[i] == null) {
+// lines[i] = new LineInfo();
+// }
+// lines[i].flags |= SEGMENTS;
+// lines[i].segments = segments;
+// }
+//}
+//void setLineSegmentChars(int startLine, int count, char[] segmentChars) {
+// if (lines == null) lines = new LineInfo[lineCount];
+// for (int i = startLine; i < startLine + count; i++) {
+// if (lines[i] == null) {
+// lines[i] = new LineInfo();
+// }
+// lines[i].flags |= SEGMENT_CHARS;
+// lines[i].segmentsChars = segmentChars;
+// }
+//}
+//void setLineTabStops(int startLine, int count, int[] tabStops) {
+// if (lines == null) lines = new LineInfo[lineCount];
+// for (int i = startLine; i < startLine + count; i++) {
+// if (lines[i] == null) {
+// lines[i] = new LineInfo();
+// }
+// lines[i].flags |= TABSTOPS;
+// lines[i].tabStops = tabStops;
+// }
+//}
+//void setLineSpacingProvider(StyledTextLineSpacingProvider lineSpacingProvider) {
+// this.lineSpacingProvider = lineSpacingProvider;
+//}
+//void setStyleRanges (int[] newRanges, StyleRange[] newStyles) {
+// if (newStyles == null) {
+// stylesSetCount = styleCount = 0;
+// ranges = null;
+// styles = null;
+// stylesSet = null;
+// hasLinks = false;
+// return;
+// }
+// if (newRanges == null && COMPACT_STYLES) {
+// newRanges = new int[newStyles.length << 1];
+// StyleRange[] tmpStyles = new StyleRange[newStyles.length];
+// if (stylesSet == null) stylesSet = new StyleRange[4];
+// for (int i = 0, j = 0; i < newStyles.length; i++) {
+// StyleRange newStyle = newStyles[i];
+// newRanges[j++] = newStyle.start;
+// newRanges[j++] = newStyle.length;
+// int index = 0;
+// while (index < stylesSetCount) {
+// if (stylesSet[index].similarTo(newStyle)) break;
+// index++;
+// }
+// if (index == stylesSetCount) {
+// if (stylesSetCount == stylesSet.length) {
+// StyleRange[] tmpStylesSet = new StyleRange[stylesSetCount + 4];
+// System.arraycopy(stylesSet, 0, tmpStylesSet, 0, stylesSetCount);
+// stylesSet = tmpStylesSet;
+// }
+// stylesSet[stylesSetCount++] = newStyle;
+// }
+// tmpStyles[i] = stylesSet[index];
+// }
+// newStyles = tmpStyles;
+// }
+//
+// if (styleCount == 0) {
+// if (newRanges != null) {
+// ranges = new int[newRanges.length];
+// System.arraycopy(newRanges, 0, ranges, 0, ranges.length);
+// }
+// styles = new StyleRange[newStyles.length];
+// System.arraycopy(newStyles, 0, styles, 0, styles.length);
+// styleCount = newStyles.length;
+// return;
+// }
+// if (newRanges != null && ranges == null) {
+// ranges = new int[styles.length << 1];
+// for (int i = 0, j = 0; i < styleCount; i++) {
+// ranges[j++] = styles[i].start;
+// ranges[j++] = styles[i].length;
+// }
+// }
+// if (newRanges == null && ranges != null) {
+// newRanges = new int[newStyles.length << 1];
+// for (int i = 0, j = 0; i < newStyles.length; i++) {
+// newRanges[j++] = newStyles[i].start;
+// newRanges[j++] = newStyles[i].length;
+// }
+// }
+// if (ranges != null) {
+// int rangeCount = styleCount << 1;
+// int start = newRanges[0];
+// int modifyStart = getRangeIndex(start, -1, rangeCount), modifyEnd;
+// boolean insert = modifyStart == rangeCount;
+// if (!insert) {
+// int end = newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1];
+// modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
+// insert = modifyStart == modifyEnd && ranges[modifyStart] >= end;
+// }
+// if (insert) {
+// addMerge(newRanges, newStyles, newRanges.length, modifyStart, modifyStart);
+// return;
+// }
+// modifyEnd = modifyStart;
+// int[] mergeRanges = new int[6];
+// StyleRange[] mergeStyles = new StyleRange[3];
+// for (int i = 0; i < newRanges.length; i += 2) {
+// int newStart = newRanges[i];
+// int newEnd = newStart + newRanges[i + 1];
+// if (newStart == newEnd) continue;
+// int modifyLast = 0, mergeCount = 0;
+// while (modifyEnd < rangeCount) {
+// if (newStart >= ranges[modifyStart] + ranges[modifyStart + 1]) modifyStart += 2;
+// if (ranges[modifyEnd] + ranges[modifyEnd + 1] > newEnd) break;
+// modifyEnd += 2;
+// }
+// if (ranges[modifyStart] < newStart && newStart < ranges[modifyStart] + ranges[modifyStart + 1]) {
+// mergeStyles[mergeCount >> 1] = styles[modifyStart >> 1];
+// mergeRanges[mergeCount] = ranges[modifyStart];
+// mergeRanges[mergeCount + 1] = newStart - ranges[modifyStart];
+// mergeCount += 2;
+// }
+// mergeStyles[mergeCount >> 1] = newStyles[i >> 1];
+// mergeRanges[mergeCount] = newStart;
+// mergeRanges[mergeCount + 1] = newRanges[i + 1];
+// mergeCount += 2;
+// if (modifyEnd < rangeCount && ranges[modifyEnd] < newEnd && newEnd < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+// mergeStyles[mergeCount >> 1] = styles[modifyEnd >> 1];
+// mergeRanges[mergeCount] = newEnd;
+// mergeRanges[mergeCount + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - newEnd;
+// mergeCount += 2;
+// modifyLast = 2;
+// }
+// int grow = addMerge(mergeRanges, mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast);
+// rangeCount += grow;
+// modifyStart = modifyEnd += grow;
+// }
+// } else {
+// int start = newStyles[0].start;
+// int modifyStart = getRangeIndex(start, -1, styleCount), modifyEnd;
+// boolean insert = modifyStart == styleCount;
+// if (!insert) {
+// int end = newStyles[newStyles.length - 1].start + newStyles[newStyles.length - 1].length;
+// modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
+// insert = modifyStart == modifyEnd && styles[modifyStart].start >= end;
+// }
+// if (insert) {
+// addMerge(newStyles, newStyles.length, modifyStart, modifyStart);
+// return;
+// }
+// modifyEnd = modifyStart;
+// StyleRange[] mergeStyles = new StyleRange[3];
+// for (StyleRange newStyle : newStyles) {
+// StyleRange style;
+// int newStart = newStyle.start;
+// int newEnd = newStart + newStyle.length;
+// if (newStart == newEnd) continue;
+// int modifyLast = 0, mergeCount = 0;
+// while (modifyEnd < styleCount) {
+// if (newStart >= styles[modifyStart].start + styles[modifyStart].length) modifyStart++;
+// if (styles[modifyEnd].start + styles[modifyEnd].length > newEnd) break;
+// modifyEnd++;
+// }
+// style = styles[modifyStart];
+// if (style.start < newStart && newStart < style.start + style.length) {
+// style = mergeStyles[mergeCount++] = (StyleRange)style.clone();
+// style.length = newStart - style.start;
+// }
+// mergeStyles[mergeCount++] = newStyle;
+// if (modifyEnd < styleCount) {
+// style = styles[modifyEnd];
+// if (style.start < newEnd && newEnd < style.start + style.length) {
+// style = mergeStyles[mergeCount++] = (StyleRange)style.clone();
+// style.length += style.start - newEnd;
+// style.start = newEnd;
+// modifyLast = 1;
+// }
+// }
+// int grow = addMerge(mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast);
+// modifyStart = modifyEnd += grow;
+// }
+// }
+//}
+//void textChanging(TextChangingEvent event) {
+// int start = event.start;
+// int newCharCount = event.newCharCount, replaceCharCount = event.replaceCharCount;
+// int newLineCount = event.newLineCount, replaceLineCount = event.replaceLineCount;
+//
+// updateRanges(start, replaceCharCount, newCharCount);
+//
+// int startLine = content.getLineAtOffset(start);
+// if (replaceCharCount == content.getCharCount()) lines = null;
+// if (replaceLineCount == lineCount) {
+// lineCount = newLineCount;
+// lineSizes = new LineSizeInfo[lineCount];
+// reset(0, lineCount);
+// } else {
+// int startIndex = startLine + replaceLineCount + 1;
+// int endIndex = startLine + newLineCount + 1;
+// if(lineCount < startLine) {
+// SWT.error(SWT.ERROR_INVALID_RANGE, null, "bug 478020: lineCount < startLine: " + lineCount + ":" + startLine);
+// }
+// if(lineCount < startIndex) {
+// SWT.error(SWT.ERROR_INVALID_RANGE, null, "bug 478020: lineCount < startIndex: " + lineCount + ":" + startIndex);
+// }
+// int delta = newLineCount - replaceLineCount;
+// if (lineCount + delta > lineSizes.length) {
+// LineSizeInfo[] newLineSizes = new LineSizeInfo[lineCount + delta + GROW];
+// System.arraycopy(lineSizes, 0, newLineSizes, 0, lineCount);
+// lineSizes = newLineSizes;
+// }
+// if (lines != null) {
+// if (lineCount + delta > lines.length) {
+// LineInfo[] newLines = new LineInfo[lineCount + delta + GROW];
+// System.arraycopy(lines, 0, newLines, 0, lineCount);
+// lines = newLines;
+// }
+// }
+// System.arraycopy(lineSizes, startIndex, lineSizes, endIndex, lineCount - startIndex);
+// for (int i = startLine; i < endIndex; i++) {
+// lineSizes[i] = null;
+// }
+// for (int i = lineCount + delta; i < lineCount; i++) {
+// lineSizes[i] = null;
+// }
+// if (layouts != null) {
+// int layoutStartLine = startLine - topIndex;
+// int layoutEndLine = layoutStartLine + replaceLineCount + 1;
+// for (int i = layoutStartLine; i < layoutEndLine; i++) {
+// if (0 <= i && i < layouts.length) {
+// if (layouts[i] != null) layouts[i].dispose();
+// layouts[i] = null;
+// if (bullets != null && bulletsIndices != null) bullets[i] = null;
+// }
+// }
+// if (delta > 0) {
+// for (int i = layouts.length - 1; i >= layoutEndLine; i--) {
+// if (0 <= i && i < layouts.length) {
+// endIndex = i + delta;
+// if (0 <= endIndex && endIndex < layouts.length) {
+// layouts[endIndex] = layouts[i];
+// layouts[i] = null;
+// if (bullets != null && bulletsIndices != null) {
+// bullets[endIndex] = bullets[i];
+// bulletsIndices[endIndex] = bulletsIndices[i];
+// bullets[i] = null;
+// }
+// } else {
+// if (layouts[i] != null) layouts[i].dispose();
+// layouts[i] = null;
+// if (bullets != null && bulletsIndices != null) bullets[i] = null;
+// }
+// }
+// }
+// } else if (delta < 0) {
+// for (int i = layoutEndLine; i < layouts.length; i++) {
+// if (0 <= i && i < layouts.length) {
+// endIndex = i + delta;
+// if (0 <= endIndex && endIndex < layouts.length) {
+// layouts[endIndex] = layouts[i];
+// layouts[i] = null;
+// if (bullets != null && bulletsIndices != null) {
+// bullets[endIndex] = bullets[i];
+// bulletsIndices[endIndex] = bulletsIndices[i];
+// bullets[i] = null;
+// }
+// } else {
+// if (layouts[i] != null) layouts[i].dispose();
+// layouts[i] = null;
+// if (bullets != null && bulletsIndices != null) bullets[i] = null;
+// }
+// }
+// }
+// }
+// }
+// if (replaceLineCount != 0 || newLineCount != 0) {
+// int startLineOffset = content.getOffsetAtLine(startLine);
+// if (startLineOffset != start) startLine++;
+// updateBullets(startLine, replaceLineCount, newLineCount, true);
+// if (lines != null) {
+// startIndex = startLine + replaceLineCount;
+// endIndex = startLine + newLineCount;
+// System.arraycopy(lines, startIndex, lines, endIndex, lineCount - startIndex);
+// for (int i = startLine; i < endIndex; i++) {
+// lines[i] = null;
+// }
+// for (int i = lineCount + delta; i < lineCount; i++) {
+// lines[i] = null;
+// }
+// }
+// }
+// lineCount += delta;
+// if (maxWidthLineIndex != -1 && startLine <= maxWidthLineIndex && maxWidthLineIndex <= startLine + replaceLineCount) {
+// maxWidth = 0;
+// maxWidthLineIndex = -1;
+// for (int i = 0; i < lineCount; i++) {
+// LineSizeInfo lineSize = getLineSize(i);
+// if (lineSize.width > maxWidth) {
+// maxWidth = lineSize.width;
+// maxWidthLineIndex = i;
+// }
+// }
+// }
+// }
+//}
+//void updateBullets(int startLine, int replaceLineCount, int newLineCount, boolean update) {
+// if (bullets == null) return;
+// if (bulletsIndices != null) return;
+// for (Bullet bullet : bullets) {
+// int[] lines = bullet.removeIndices(startLine, replaceLineCount, newLineCount, update);
+// if (lines != null) {
+// if (redrawLines == null) {
+// redrawLines = lines;
+// } else {
+// int[] newRedrawBullets = new int[redrawLines.length + lines.length];
+// System.arraycopy(redrawLines, 0, newRedrawBullets, 0, redrawLines.length);
+// System.arraycopy(lines, 0, newRedrawBullets, redrawLines.length, lines.length);
+// redrawLines = newRedrawBullets;
+// }
+// }
+// }
+// int removed = 0;
+// for (Bullet bullet : bullets) {
+// if (bullet.size() == 0) removed++;
+// }
+// if (removed > 0) {
+// if (removed == bullets.length) {
+// bullets = null;
+// } else {
+// Bullet[] newBulletsList = new Bullet[bullets.length - removed];
+// for (int i = 0, j = 0; i < bullets.length; i++) {
+// Bullet bullet = bullets[i];
+// if (bullet.size() > 0) newBulletsList[j++] = bullet;
+// }
+// bullets = newBulletsList;
+// }
+// }
+//}
+//void updateRanges(int start, int replaceCharCount, int newCharCount) {
+// if (styleCount == 0 || (replaceCharCount == 0 && newCharCount == 0)) return;
+// if (ranges != null) {
+// int rangeCount = styleCount << 1;
+// int modifyStart = getRangeIndex(start, -1, rangeCount);
+// if (modifyStart == rangeCount) return;
+// int end = start + replaceCharCount;
+// int modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
+// int offset = newCharCount - replaceCharCount;
+// if (modifyStart == modifyEnd && ranges[modifyStart] < start && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+// if (newCharCount == 0) {
+// ranges[modifyStart + 1] -= replaceCharCount;
+// modifyEnd += 2;
+// } else {
+// if (rangeCount + 2 > ranges.length) {
+// int[] newRanges = new int[ranges.length + (GROW << 1)];
+// System.arraycopy(ranges, 0, newRanges, 0, rangeCount);
+// ranges = newRanges;
+// StyleRange[] newStyles = new StyleRange[styles.length + GROW];
+// System.arraycopy(styles, 0, newStyles, 0, styleCount);
+// styles = newStyles;
+// }
+// System.arraycopy(ranges, modifyStart + 2, ranges, modifyStart + 4, rangeCount - (modifyStart + 2));
+// System.arraycopy(styles, (modifyStart + 2) >> 1, styles, (modifyStart + 4) >> 1, styleCount - ((modifyStart + 2) >> 1));
+// ranges[modifyStart + 3] = ranges[modifyStart] + ranges[modifyStart + 1] - end;
+// ranges[modifyStart + 2] = start + newCharCount;
+// ranges[modifyStart + 1] = start - ranges[modifyStart];
+// styles[(modifyStart >> 1) + 1] = styles[modifyStart >> 1];
+// rangeCount += 2;
+// styleCount++;
+// modifyEnd += 4;
+// }
+// if (offset != 0) {
+// for (int i = modifyEnd; i < rangeCount; i += 2) {
+// ranges[i] += offset;
+// }
+// }
+// } else {
+// if (ranges[modifyStart] < start && start < ranges[modifyStart] + ranges[modifyStart + 1]) {
+// ranges[modifyStart + 1] = start - ranges[modifyStart];
+// modifyStart += 2;
+// }
+// if (modifyEnd < rangeCount && ranges[modifyEnd] < end && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+// ranges[modifyEnd + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - end;
+// ranges[modifyEnd] = end;
+// }
+// if (offset != 0) {
+// for (int i = modifyEnd; i < rangeCount; i += 2) {
+// ranges[i] += offset;
+// }
+// }
+// System.arraycopy(ranges, modifyEnd, ranges, modifyStart, rangeCount - modifyEnd);
+// System.arraycopy(styles, modifyEnd >> 1, styles, modifyStart >> 1, styleCount - (modifyEnd >> 1));
+// styleCount -= (modifyEnd - modifyStart) >> 1;
+// }
+// } else {
+// int modifyStart = getRangeIndex(start, -1, styleCount);
+// if (modifyStart == styleCount) return;
+// int end = start + replaceCharCount;
+// int modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
+// int offset = newCharCount - replaceCharCount;
+// if (modifyStart == modifyEnd && styles[modifyStart].start < start && end < styles[modifyEnd].start + styles[modifyEnd].length) {
+// if (newCharCount == 0) {
+// styles[modifyStart].length -= replaceCharCount;
+// modifyEnd++;
+// } else {
+// if (styleCount + 1 > styles.length) {
+// StyleRange[] newStyles = new StyleRange[styles.length + GROW];
+// System.arraycopy(styles, 0, newStyles, 0, styleCount);
+// styles = newStyles;
+// }
+// System.arraycopy(styles, modifyStart + 1, styles, modifyStart + 2, styleCount - (modifyStart + 1));
+// styles[modifyStart + 1] = (StyleRange)styles[modifyStart].clone();
+// styles[modifyStart + 1].length = styles[modifyStart].start + styles[modifyStart].length - end;
+// styles[modifyStart + 1].start = start + newCharCount;
+// styles[modifyStart].length = start - styles[modifyStart].start;
+// styleCount++;
+// modifyEnd += 2;
+// }
+// if (offset != 0) {
+// for (int i = modifyEnd; i < styleCount; i++) {
+// styles[i].start += offset;
+// }
+// }
+// } else {
+// if (styles[modifyStart].start < start && start < styles[modifyStart].start + styles[modifyStart].length) {
+// styles[modifyStart].length = start - styles[modifyStart].start;
+// modifyStart++;
+// }
+// if (modifyEnd < styleCount && styles[modifyEnd].start < end && end < styles[modifyEnd].start + styles[modifyEnd].length) {
+// styles[modifyEnd].length = styles[modifyEnd].start + styles[modifyEnd].length - end;
+// styles[modifyEnd].start = end;
+// }
+// if (offset != 0) {
+// for (int i = modifyEnd; i < styleCount; i++) {
+// styles[i].start += offset;
+// }
+// }
+// System.arraycopy(styles, modifyEnd, styles, modifyStart, styleCount - modifyEnd);
+// styleCount -= modifyEnd - modifyStart;
+// }
+// }
+//}
+//
+//public boolean hasVerticalIndent() {
+// return Arrays.stream(lines).filter(Objects::nonNull) //
+// .mapToInt(line -> line.verticalIndent) //
+// .anyMatch(n -> n != 0);
+//}
+//
+//
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextWriterBase.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextWriterBase.java
index b5400430724..e6f5fdcbfc3 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextWriterBase.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextWriterBase.java
@@ -13,9 +13,6 @@
*******************************************************************************/
package org.eclipse.swt.custom;
-import org.eclipse.swt.*;
-import org.eclipse.swt.graphics.*;
-
/**
* The base class encapsulating the logic used to write styled content as
* a rich format (HTML, RTF, maybe more). It contains the common parts:
@@ -30,247 +27,252 @@
* the stream like they are rendered by the widget. In addition, the
* widget font name and size is used for the whole text.
*/
+// TODO (visjee) SWING
abstract class StyledTextWriterBase extends TextWriter {
- final StyledText styledText;
- /**
- * Creates a writer that processed content starting at offset "start"
- * in the document. {@code start} and {@code length} can be set to specify
- * partial lines.
- *
- * @param start start offset of content to write, 0 based from beginning of document
- * @param length length of content to write
- * @param styledText the widget to produce the RTF from
- */
- public StyledTextWriterBase(StyledText styledText, int start, int length) {
+ public StyledTextWriterBase(int start, int length) {
super(start, length);
- this.styledText = styledText;
- }
-
- /**
- * Appends the specified segment of "string" to the output data.
- * Copy from {@code start} up to, but excluding, {@code end}.
- *
- * @param string string to copy a segment from. Must not contain line breaks.
- * Line breaks should be written using {@link #writeLineDelimiter()}
- * @param start start offset of segment. 0 based.
- * @param end end offset of segment
- */
- void writeEscaped(String string, int start, int end) {
- String textToWrite = string.substring(start, end);
- write(escapeText(textToWrite));
- }
-
- /**
- * Appends the specified line text to the output data. Lines will be formatted
- * using the styles queried from the LineStyleListener, if set, or those set
- * directly in the widget.
- *
- * @param line line text to write. Must not contain line breaks
- * Line breaks should be written using {@link #writeLineDelimiter(String)}
- * @param lineOffset offset of the line. 0 based from the start of the
- * widget document. Any text occurring before the start offset or after the
- * end offset specified during object creation is ignored.
- *
- * @throws SWTException {@code ERROR_IO} when the writer is closed.
- */
- @Override
- public void writeLine(String line, int lineOffset) {
- if (isClosed()) {
- SWT.error(SWT.ERROR_IO);
- }
-
- int lineIndex = styledText.content.getLineAtOffset(lineOffset);
- int lineAlignment;
- int lineIndent;
- boolean lineJustify;
- int verticalIndent;
- int[] ranges;
- StyleRange[] styles;
-
- StyledTextEvent event = styledText.getLineStyleData(lineOffset, line);
- if (event != null) {
- verticalIndent = event.verticalIndent;
- lineAlignment = event.alignment;
- lineIndent = event.indent;
- lineJustify = event.justify;
- ranges = event.ranges;
- styles = event.styles;
- } else {
- verticalIndent = styledText.renderer.getLineVerticalIndent(lineIndex);
- lineAlignment = styledText.renderer.getLineAlignment(lineIndex, styledText.alignment);
- lineIndent = styledText.renderer.getLineIndent(lineIndex, styledText.indent);
- lineJustify = styledText.renderer.getLineJustify(lineIndex, styledText.justify);
- ranges = styledText.renderer.getRanges(lineOffset, line.length());
- styles = styledText.renderer.getStyleRanges(lineOffset, line.length(), false);
- }
-
- if (styles == null) {
- styles = new StyleRange[0];
- }
-
- event = styledText.getLineBackgroundData(lineOffset, line);
- Color lineBackground = (event != null && event.lineBackground != null)
- ? event.lineBackground
- : styledText.renderer.getLineBackground(lineIndex, null);
-
- writeStyledLine(line, lineOffset, ranges, styles, lineBackground, lineIndent, verticalIndent, lineAlignment, lineJustify);
- }
-
- /**
- * Appends the specified line text to the output data.
- *
- *
Use the colors and font styles specified in {@code styles} and {@code lineBackground}.
- * Formatting is written to reflect the text rendering by the text widget.
- * Style background colors take precedence over the line background color.
- *
- * @param line line text to write as RTF. Must not contain line breaks
- * Line breaks should be written using writeLineDelimiter()
- * @param lineOffset offset of the line. 0 based from the start of the
- * widget document. Any text occurring before the start offset or after the
- * end offset specified during object creation is ignored.
- * @param styles styles to use for formatting. Must not be null.
- * @param lineBackground line background color to use for formatting.
- * May be null.
- */
- void writeStyledLine(String line, int lineOffset, int ranges[], StyleRange[] styles,
- Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) {
-
- int lineLength = line.length();
- int startOffset = getStart();
- int writeOffset = startOffset - lineOffset;
- if (writeOffset >= lineLength) {
- return;
- }
- int lineIndex = Math.max(0, writeOffset);
-
- String atLineEnd = writeLineStart(lineBackground, indent, verticalIndent, alignment, justify);
-
- int endOffset = startOffset + super.getCharCount();
-
- // We are already at the end, should not write an empty paragraph
- if (lineOffset >= endOffset) {
- return;
- }
-
- int lineEndOffset = Math.min(lineLength, endOffset - lineOffset);
-
- int outTextLen = 0; // collect the length of the text we output (unescaped)
- for (int i = 0; i < styles.length; i++) {
- StyleRange style = styles[i];
- int start, end;
- if (ranges != null) {
- start = ranges[i << 1] - lineOffset;
- end = start + ranges[(i << 1) + 1];
- } else {
- start = style.start - lineOffset;
- end = start + style.length;
- }
- // skip over partial first line
- if (end < writeOffset) {
- continue;
- }
- // style starts beyond line end or write end
- if (start >= lineEndOffset) {
- break;
- }
- // write any unstyled text
- if (lineIndex < start) {
- // copy to start of style
- // style starting beyond end of write range or end of line
- // is guarded against above.
- writeEscaped(line, lineIndex, start);
- outTextLen += start - lineIndex;
- lineIndex = start;
- }
- // write styled text
- String atSpanEnd = writeSpanStart(style);
-
- // copy to end of style or end of write range or end of line
- int copyEnd = Math.min(end, lineEndOffset);
- // guard against invalid styles and let style processing continue
- copyEnd = Math.max(copyEnd, lineIndex);
- writeEscaped(line, lineIndex, copyEnd);
- outTextLen += copyEnd - lineIndex;
-
- writeSpanEnd(atSpanEnd);
-
- lineIndex = copyEnd;
- }
-
- // write the unstyled text at the end of the line
- if (lineIndex < lineEndOffset) {
- writeEscaped(line, lineIndex, lineEndOffset);
- outTextLen += lineEndOffset - lineIndex;
- }
-
- if (outTextLen == 0) {
- writeEmptyLine();
- }
-
- writeLineEnd(atLineEnd);
- }
-
- /**
- * Writes the part that only shows once, at the beginning of the output data.
- */
- abstract void writeHeader();
-
- /**
- * Takes plain text and returns the same text escaped using the rules of the output format.
- * @param text the text to escape
- * @return the escaped text
- */
- abstract String escapeText(String text);
-
- /**
- * Invoked at the beginning of each line in the original widget.
- *
- *
It should output whatever tags are appropriate to start a new line in the output format.
- * It will return the text that has to be output at the end of the line.
- *
- * @return the text to append at the end of the line
- */
- abstract String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify);
-
- /**
- * Invoked at the end of of each line in the original widget.
- *
- *
It receives whatever text {@link #writeLineStart(Color,int,int,int,boolean)} returned
- * and it will output it. A class might override it to do more.
- *
- * @param prepared the leftover text prepared by {@code writeLineStart}
- */
- void writeLineEnd(String prepared) {
- write(prepared);
- }
-
- /**
- * Invoked at the end of each line, writeLineEnd, if there was no text output.
- *
- *
This is needed for HTML, which does not render empty paragraphs.
- */
- abstract void writeEmptyLine();
-
- /**
- * Invoked at the beginning of each styled span fragment in the original widget.
- *
- *
It should output whatever tags are appropriate to start a formatted span in the output format.
- * It will return the text that has to be output at the end of the span (to close it).
- *
- * @return the text to append at the end of the styled span
- */
- abstract String writeSpanStart(StyleRange style);
-
- /**
- * Invoked at the end of of each styled span fragment in the original widget.
- *
- *
It receives whatever text {@link #writeSpanStart(StyleRange)} returned
- * and it will output it. A class might override it to do more.
- *
- * @param prepared the leftover text prepared by {@code writeSpanStart}
- */
- void writeSpanEnd(String prepared) {
- write(prepared);
}
+// final StyledText styledText;
+//
+// /**
+// * Creates a writer that processed content starting at offset "start"
+// * in the document. {@code start} and {@code length} can be set to specify
+// * partial lines.
+// *
+// * @param start start offset of content to write, 0 based from beginning of document
+// * @param length length of content to write
+// * @param styledText the widget to produce the RTF from
+// */
+// public StyledTextWriterBase(StyledText styledText, int start, int length) {
+// super(start, length);
+// this.styledText = styledText;
+// }
+//
+// /**
+// * Appends the specified segment of "string" to the output data.
+// * Copy from {@code start} up to, but excluding, {@code end}.
+// *
+// * @param string string to copy a segment from. Must not contain line breaks.
+// * Line breaks should be written using {@link #writeLineDelimiter()}
+// * @param start start offset of segment. 0 based.
+// * @param end end offset of segment
+// */
+// void writeEscaped(String string, int start, int end) {
+// String textToWrite = string.substring(start, end);
+// write(escapeText(textToWrite));
+// }
+//
+// /**
+// * Appends the specified line text to the output data. Lines will be formatted
+// * using the styles queried from the LineStyleListener, if set, or those set
+// * directly in the widget.
+// *
+// * @param line line text to write. Must not contain line breaks
+// * Line breaks should be written using {@link #writeLineDelimiter(String)}
+// * @param lineOffset offset of the line. 0 based from the start of the
+// * widget document. Any text occurring before the start offset or after the
+// * end offset specified during object creation is ignored.
+// *
+// * @throws SWTException {@code ERROR_IO} when the writer is closed.
+// */
+// @Override
+// public void writeLine(String line, int lineOffset) {
+// if (isClosed()) {
+// SWT.error(SWT.ERROR_IO);
+// }
+//
+// int lineIndex = styledText.content.getLineAtOffset(lineOffset);
+// int lineAlignment;
+// int lineIndent;
+// boolean lineJustify;
+// int verticalIndent;
+// int[] ranges;
+// StyleRange[] styles;
+//
+// StyledTextEvent event = styledText.getLineStyleData(lineOffset, line);
+// if (event != null) {
+// verticalIndent = event.verticalIndent;
+// lineAlignment = event.alignment;
+// lineIndent = event.indent;
+// lineJustify = event.justify;
+// ranges = event.ranges;
+// styles = event.styles;
+// } else {
+// verticalIndent = styledText.renderer.getLineVerticalIndent(lineIndex);
+// lineAlignment = styledText.renderer.getLineAlignment(lineIndex, styledText.alignment);
+// lineIndent = styledText.renderer.getLineIndent(lineIndex, styledText.indent);
+// lineJustify = styledText.renderer.getLineJustify(lineIndex, styledText.justify);
+// ranges = styledText.renderer.getRanges(lineOffset, line.length());
+// styles = styledText.renderer.getStyleRanges(lineOffset, line.length(), false);
+// }
+//
+// if (styles == null) {
+// styles = new StyleRange[0];
+// }
+//
+// event = styledText.getLineBackgroundData(lineOffset, line);
+// Color lineBackground = (event != null && event.lineBackground != null)
+// ? event.lineBackground
+// : styledText.renderer.getLineBackground(lineIndex, null);
+//
+// writeStyledLine(line, lineOffset, ranges, styles, lineBackground, lineIndent, verticalIndent, lineAlignment, lineJustify);
+// }
+//
+// /**
+// * Appends the specified line text to the output data.
+// *
+// *
Use the colors and font styles specified in {@code styles} and {@code lineBackground}.
+// * Formatting is written to reflect the text rendering by the text widget.
+// * Style background colors take precedence over the line background color.
+// *
+// * @param line line text to write as RTF. Must not contain line breaks
+// * Line breaks should be written using writeLineDelimiter()
+// * @param lineOffset offset of the line. 0 based from the start of the
+// * widget document. Any text occurring before the start offset or after the
+// * end offset specified during object creation is ignored.
+// * @param styles styles to use for formatting. Must not be null.
+// * @param lineBackground line background color to use for formatting.
+// * May be null.
+// */
+// void writeStyledLine(String line, int lineOffset, int ranges[], StyleRange[] styles,
+// Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) {
+//
+// int lineLength = line.length();
+// int startOffset = getStart();
+// int writeOffset = startOffset - lineOffset;
+// if (writeOffset >= lineLength) {
+// return;
+// }
+// int lineIndex = Math.max(0, writeOffset);
+//
+// String atLineEnd = writeLineStart(lineBackground, indent, verticalIndent, alignment, justify);
+//
+// int endOffset = startOffset + super.getCharCount();
+//
+// // We are already at the end, should not write an empty paragraph
+// if (lineOffset >= endOffset) {
+// return;
+// }
+//
+// int lineEndOffset = Math.min(lineLength, endOffset - lineOffset);
+//
+// int outTextLen = 0; // collect the length of the text we output (unescaped)
+// for (int i = 0; i < styles.length; i++) {
+// StyleRange style = styles[i];
+// int start, end;
+// if (ranges != null) {
+// start = ranges[i << 1] - lineOffset;
+// end = start + ranges[(i << 1) + 1];
+// } else {
+// start = style.start - lineOffset;
+// end = start + style.length;
+// }
+// // skip over partial first line
+// if (end < writeOffset) {
+// continue;
+// }
+// // style starts beyond line end or write end
+// if (start >= lineEndOffset) {
+// break;
+// }
+// // write any unstyled text
+// if (lineIndex < start) {
+// // copy to start of style
+// // style starting beyond end of write range or end of line
+// // is guarded against above.
+// writeEscaped(line, lineIndex, start);
+// outTextLen += start - lineIndex;
+// lineIndex = start;
+// }
+// // write styled text
+// String atSpanEnd = writeSpanStart(style);
+//
+// // copy to end of style or end of write range or end of line
+// int copyEnd = Math.min(end, lineEndOffset);
+// // guard against invalid styles and let style processing continue
+// copyEnd = Math.max(copyEnd, lineIndex);
+// writeEscaped(line, lineIndex, copyEnd);
+// outTextLen += copyEnd - lineIndex;
+//
+// writeSpanEnd(atSpanEnd);
+//
+// lineIndex = copyEnd;
+// }
+//
+// // write the unstyled text at the end of the line
+// if (lineIndex < lineEndOffset) {
+// writeEscaped(line, lineIndex, lineEndOffset);
+// outTextLen += lineEndOffset - lineIndex;
+// }
+//
+// if (outTextLen == 0) {
+// writeEmptyLine();
+// }
+//
+// writeLineEnd(atLineEnd);
+// }
+//
+// /**
+// * Writes the part that only shows once, at the beginning of the output data.
+// */
+// abstract void writeHeader();
+//
+// /**
+// * Takes plain text and returns the same text escaped using the rules of the output format.
+// * @param text the text to escape
+// * @return the escaped text
+// */
+// abstract String escapeText(String text);
+//
+// /**
+// * Invoked at the beginning of each line in the original widget.
+// *
+// *
It should output whatever tags are appropriate to start a new line in the output format.
+// * It will return the text that has to be output at the end of the line.
+// *
+// * @return the text to append at the end of the line
+// */
+// abstract String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify);
+//
+// /**
+// * Invoked at the end of of each line in the original widget.
+// *
+// *
It receives whatever text {@link #writeLineStart(Color,int,int,int,boolean)} returned
+// * and it will output it. A class might override it to do more.
+// *
+// * @param prepared the leftover text prepared by {@code writeLineStart}
+// */
+// void writeLineEnd(String prepared) {
+// write(prepared);
+// }
+//
+// /**
+// * Invoked at the end of each line, writeLineEnd, if there was no text output.
+// *
+// *
This is needed for HTML, which does not render empty paragraphs.
+// */
+// abstract void writeEmptyLine();
+//
+// /**
+// * Invoked at the beginning of each styled span fragment in the original widget.
+// *
+// *
It should output whatever tags are appropriate to start a formatted span in the output format.
+// * It will return the text that has to be output at the end of the span (to close it).
+// *
+// * @return the text to append at the end of the styled span
+// */
+// abstract String writeSpanStart(StyleRange style);
+//
+// /**
+// * Invoked at the end of of each styled span fragment in the original widget.
+// *
+// *
It receives whatever text {@link #writeSpanStart(StyleRange)} returned
+// * and it will output it. A class might override it to do more.
+// *
+// * @param prepared the leftover text prepared by {@code writeSpanStart}
+// */
+// void writeSpanEnd(String prepared) {
+// write(prepared);
+// }
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledText.java
new file mode 100644
index 00000000000..8ac13558d3b
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledText.java
@@ -0,0 +1,8121 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.accessibility.*;
+import org.eclipse.swt.dnd.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.printing.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * A StyledText is an editable user interface object that displays lines
+ * of text. The following style attributes can be defined for the text:
+ *
+ *
foreground color
+ *
background color
+ *
font style (bold, italic, bold-italic, regular)
+ *
underline
+ *
strikeout
+ *
+ *
+ * In addition to text style attributes, the background color of a line may
+ * be specified.
+ *
+ * There are two ways to use this widget when specifying text style information.
+ * You may use the API that is defined for StyledText or you may define your own
+ * LineStyleListener. If you define your own listener, you will be responsible
+ * for maintaining the text style information for the widget. IMPORTANT: You may
+ * not define your own listener and use the StyledText API. The following
+ * StyledText API is not supported if you have defined a LineStyleListener:
+ *
+ *
getStyleRangeAtOffset(int)
+ *
getStyleRanges()
+ *
replaceStyleRanges(int,int,StyleRange[])
+ *
setStyleRange(StyleRange)
+ *
setStyleRanges(StyleRange[])
+ *
+ *
+ * There are two ways to use this widget when specifying line background colors.
+ * You may use the API that is defined for StyledText or you may define your own
+ * LineBackgroundListener. If you define your own listener, you will be responsible
+ * for maintaining the line background color information for the widget.
+ * IMPORTANT: You may not define your own listener and use the StyledText API.
+ * The following StyledText API is not supported if you have defined a
+ * LineBackgroundListener:
+ *
+ *
getLineBackground(int)
+ *
setLineBackground(int,int,Color)
+ *
+ *
+ * The content implementation for this widget may also be user-defined. To do so,
+ * you must implement the StyledTextContent interface and use the StyledText API
+ * setContent(StyledTextContent) to initialize the widget.
+ *
+ *
+ *
Styles:
FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+public class StyledText extends Canvas {
+ static final char TAB = '\t';
+ static final String PlatformLineDelimiter = System.getProperty("line.separator");
+ static final int BIDI_CARET_WIDTH = 3;
+ static final int DEFAULT_WIDTH = 64;
+ static final int DEFAULT_HEIGHT = 64;
+ static final int V_SCROLL_RATE = 50;
+ static final int H_SCROLL_RATE = 10;
+
+ static final int ExtendedModify = 3000;
+ static final int LineGetBackground = 3001;
+ static final int LineGetStyle = 3002;
+ static final int TextChanging = 3003;
+ static final int TextSet = 3004;
+ static final int VerifyKey = 3005;
+ static final int TextChanged = 3006;
+ static final int LineGetSegments = 3007;
+ static final int PaintObject = 3008;
+
+ static final int PREVIOUS_OFFSET_TRAILING = 0;
+ static final int OFFSET_LEADING = 1;
+
+ Color selectionBackground; // selection background color
+ Color selectionForeground; // selection foreground color
+ StyledTextContent content; // native content (default or user specified)
+ StyledTextRenderer renderer;
+ Listener listener;
+ TextChangeListener textChangeListener; // listener for TextChanging, TextChanged and TextSet events from StyledTextContent
+ int verticalScrollOffset = 0; // pixel based
+ int horizontalScrollOffset = 0; // pixel based
+ int topIndex = 0; // top visible line
+ int topIndexY;
+ int clientAreaHeight = 0; // the client area height. Needed to calculate content width for new visible lines during Resize callback
+ int clientAreaWidth = 0; // the client area width. Needed during Resize callback to determine if line wrap needs to be recalculated
+ int tabLength = 4; // number of characters in a tab
+ int leftMargin;
+ int topMargin;
+ int rightMargin;
+ int bottomMargin;
+ int columnX; // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935
+ int caretOffset = 0;
+ int caretAlignment;
+ Point selection = new Point(0, 0); // x and y are start and end caret offsets of selection
+ Point clipboardSelection; // x and y are start and end caret offsets of previous selection
+ int selectionAnchor; // position of selection anchor. 0 based offset from beginning of text
+ Point doubleClickSelection; // selection after last mouse double click
+ boolean editable = true;
+ boolean wordWrap = false;
+ boolean doubleClickEnabled = true; // see getDoubleClickEnabled
+ boolean overwrite = false; // insert/overwrite edit mode
+ int textLimit = -1; // limits the number of characters the user can type in the widget. Unlimited by default.
+ Hashtable keyActionMap = new Hashtable();
+ Color background = null; // workaround for bug 4791
+ Color foreground = null; //
+ Clipboard clipboard;
+ boolean mouseDown = false;
+ boolean mouseDoubleClick = false; // true=a double click ocurred. Don't do mouse swipe selection.
+ int autoScrollDirection = SWT.NULL; // the direction of autoscrolling (up, down, right, left)
+ int autoScrollDistance = 0;
+ int lastTextChangeStart; // cache data of the
+ int lastTextChangeNewLineCount; // last text changing
+ int lastTextChangeNewCharCount; // event for use in the
+ int lastTextChangeReplaceLineCount; // text changed handler
+ int lastTextChangeReplaceCharCount;
+ int lastLineBottom; // the bottom pixel of the last line been replaced
+ boolean isMirrored;
+ boolean bidiColoring = false; // apply the BIDI algorithm on text segments of the same color
+ Image leftCaretBitmap = null;
+ Image rightCaretBitmap = null;
+ int caretDirection = SWT.NULL;
+ Caret defaultCaret = null;
+ boolean updateCaretDirection = true;
+ boolean fixedLineHeight;
+ boolean dragDetect, dragging;
+
+ int alignment;
+ boolean justify;
+ int indent;
+ int lineSpacing;
+
+ final static boolean IS_CARBON, IS_GTK, IS_MOTIF;
+ static {
+ String platform = SWT.getPlatform();
+ IS_CARBON = "carbon".equals(platform);
+ IS_GTK = "gtk".equals(platform);
+ IS_MOTIF = "motif".equals(platform);
+ }
+
+ /**
+ * The Printing class implements printing of a range of text.
+ * An instance of Printing is returned in the
+ * StyledText#print(Printer) API. The run() method may be
+ * invoked from any thread.
+ */
+ static class Printing implements Runnable {
+ final static int LEFT = 0; // left aligned header/footer segment
+ final static int CENTER = 1; // centered header/footer segment
+ final static int RIGHT = 2; // right aligned header/footer segment
+
+ Printer printer;
+ StyledTextRenderer printerRenderer;
+ StyledTextPrintOptions printOptions;
+ Rectangle clientArea;
+ FontData fontData;
+ Font printerFont;
+ Hashtable resources;
+ int tabLength;
+ GC gc; // printer GC
+ int pageWidth; // width of a printer page in pixels
+ int startPage; // first page to print
+ int endPage; // last page to print
+ int startLine; // first (wrapped) line to print
+ int endLine; // last (wrapped) line to print
+ boolean singleLine; // widget single line mode
+ Point selection = null; // selected text
+ boolean mirrored; // indicates the printing gc should be mirrored
+ int lineSpacing;
+
+ /**
+ * Creates an instance of Printing.
+ * Copies the widget content and rendering data that needs
+ * to be requested from listeners.
+ *
+ * @param parent StyledText widget to print.
+ * @param printer printer device to print on.
+ * @param printOptions print options
+ */
+ Printing(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) {
+ this.printer = printer;
+ this.printOptions = printOptions;
+ this.mirrored = (styledText.getStyle() & SWT.MIRRORED) != 0;
+ singleLine = styledText.isSingleLine();
+ startPage = 1;
+ endPage = Integer.MAX_VALUE;
+ PrinterData data = printer.getPrinterData();
+ if (data.scope == PrinterData.PAGE_RANGE) {
+ startPage = data.startPage;
+ endPage = data.endPage;
+ if (endPage < startPage) {
+ int temp = endPage;
+ endPage = startPage;
+ startPage = temp;
+ }
+ } else if (data.scope == PrinterData.SELECTION) {
+ selection = styledText.getSelectionRange();
+ }
+ printerRenderer = new StyledTextRenderer(printer, null);
+ printerRenderer.setContent(copyContent(styledText.getContent()));
+ cacheLineData(styledText);
+
+ }
+ /**
+ * Caches all line data that needs to be requested from a listener.
+ *
+ * @param printerContent StyledTextContent to request
+ * line data for.
+ */
+ void cacheLineData(StyledText styledText) {
+ StyledTextRenderer renderer = styledText.renderer;
+ renderer.copyInto(printerRenderer);
+ fontData = styledText.getFont().getFontData()[0];
+ tabLength = styledText.tabLength;
+ int lineCount = printerRenderer.lineCount;
+ if (styledText.isListening(LineGetBackground) || (styledText.isBidi() && styledText.isListening(LineGetSegments)) || styledText.isListening(LineGetStyle)) {
+ StyledTextContent content = printerRenderer.content;
+ for (int i = 0; i < lineCount; i++) {
+ String line = content.getLine(i);
+ int lineOffset = content.getOffsetAtLine(i);
+ StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line);
+ if (event != null && event.lineBackground != null) {
+ printerRenderer.setLineBackground(i, 1, event.lineBackground);
+ }
+ if (styledText.isBidi()) {
+ int[] segments = styledText.getBidiSegments(lineOffset, line);
+ printerRenderer.setLineSegments(i, 1, segments);
+ }
+ event = styledText.getLineStyleData(lineOffset, line);
+ if (event != null) {
+ printerRenderer.setLineIndent(i, 1, event.indent);
+ printerRenderer.setLineAlignment(i, 1, event.alignment);
+ printerRenderer.setLineJustify(i, 1, event.justify);
+ printerRenderer.setLineBullet(i, 1, event.bullet);
+ StyleRange[] styles = event.styles;
+ if (styles != null && styles.length > 0) {
+ printerRenderer.setStyleRanges(event.ranges, styles);
+ }
+ }
+ }
+ }
+ Point screenDPI = styledText.getDisplay().getDPI();
+ Point printerDPI = printer.getDPI();
+ resources = new Hashtable ();
+ for (int i = 0; i < lineCount; i++) {
+ Color color = printerRenderer.getLineBackground(i, null);
+ if (color != null) {
+ if (printOptions.printLineBackground) {
+ Color printerColor = (Color)resources.get(color);
+ if (printerColor == null) {
+ printerColor = new Color (printer, color.getRGB());
+ resources.put(color, printerColor);
+ }
+ printerRenderer.setLineBackground(i, 1, printerColor);
+ } else {
+ printerRenderer.setLineBackground(i, 1, null);
+ }
+ }
+ int indent = printerRenderer.getLineIndent(i, 0);
+ if (indent != 0) {
+ printerRenderer.setLineIndent(i, 1, indent * printerDPI.x / screenDPI.x);
+ }
+ }
+ StyleRange[] styles = printerRenderer.styles;
+ for (int i = 0; i < printerRenderer.styleCount; i++) {
+ StyleRange style = styles[i];
+ Font font = style.font;
+ if (style.font != null) {
+ Font printerFont = (Font)resources.get(font);
+ if (printerFont == null) {
+ printerFont = new Font (printer, font.getFontData());
+ resources.put(font, printerFont);
+ }
+ style.font = printerFont;
+ }
+ Color color = style.foreground;
+ if (color != null) {
+ Color printerColor = (Color)resources.get(color);
+ if (printOptions.printTextForeground) {
+ if (printerColor == null) {
+ printerColor = new Color (printer, color.getRGB());
+ resources.put(color, printerColor);
+ }
+ style.foreground = printerColor;
+ } else {
+ style.foreground = null;
+ }
+ }
+ color = style.background;
+ if (color != null) {
+ Color printerColor = (Color)resources.get(color);
+ if (printOptions.printTextBackground) {
+ if (printerColor == null) {
+ printerColor = new Color (printer, color.getRGB());
+ resources.put(color, printerColor);
+ }
+ style.background = printerColor;
+ } else {
+ style.background = null;
+ }
+ }
+ if (!printOptions.printTextFontStyle) {
+ style.fontStyle = SWT.NORMAL;
+ }
+ style.rise = style.rise * printerDPI.y / screenDPI.y;
+ GlyphMetrics metrics = style.metrics;
+ if (metrics != null) {
+ metrics.ascent = metrics.ascent * printerDPI.y / screenDPI.y;
+ metrics.descent = metrics.descent * printerDPI.y / screenDPI.y;
+ metrics.width = metrics.width * printerDPI.x / screenDPI.x;
+ }
+ }
+ lineSpacing = styledText.lineSpacing * printerDPI.y / screenDPI.y;
+ }
+ /**
+ * Copies the text of the specified StyledTextContent.
+ *
+ * @param original the StyledTextContent to copy.
+ */
+ StyledTextContent copyContent(StyledTextContent original) {
+ StyledTextContent printerContent = new DefaultContent();
+ int insertOffset = 0;
+ for (int i = 0; i < original.getLineCount(); i++) {
+ int insertEndOffset;
+ if (i < original.getLineCount() - 1) {
+ insertEndOffset = original.getOffsetAtLine(i + 1);
+ } else {
+ insertEndOffset = original.getCharCount();
+ }
+ printerContent.replaceTextRange(insertOffset, 0, original.getTextRange(insertOffset, insertEndOffset - insertOffset));
+ insertOffset = insertEndOffset;
+ }
+ return printerContent;
+ }
+ /**
+ * Disposes of the resources and the PrintRenderer.
+ */
+ void dispose() {
+ if (gc != null) {
+ gc.dispose();
+ gc = null;
+ }
+ if (resources != null) {
+ Enumeration enumeration = resources.elements();
+ while (enumeration.hasMoreElements()) {
+ Resource resource = (Resource) enumeration.nextElement();
+ resource.dispose();
+ }
+ resources = null;
+ }
+ if (printerFont != null) {
+ printerFont.dispose();
+ printerFont = null;
+ }
+ if (printerRenderer != null) {
+ printerRenderer.dispose();
+ printerRenderer = null;
+ }
+ }
+ void init() {
+ Rectangle trim = printer.computeTrim(0, 0, 0, 0);
+ Point dpi = printer.getDPI();
+
+ printerFont = new Font(printer, fontData.getName(), fontData.getHeight(), SWT.NORMAL);
+ clientArea = printer.getClientArea();
+ pageWidth = clientArea.width;
+ // one inch margin around text
+ clientArea.x = dpi.x + trim.x;
+ clientArea.y = dpi.y + trim.y;
+ clientArea.width -= (clientArea.x + trim.width);
+ clientArea.height -= (clientArea.y + trim.height);
+
+ int style = mirrored ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
+ gc = new GC(printer, style);
+ gc.setFont(printerFont);
+ printerRenderer.setFont(printerFont, tabLength);
+ int lineHeight = printerRenderer.getLineHeight();
+ if (printOptions.header != null) {
+ clientArea.y += lineHeight * 2;
+ clientArea.height -= lineHeight * 2;
+ }
+ if (printOptions.footer != null) {
+ clientArea.height -= lineHeight * 2;
+ }
+
+ // TODO not wrapped
+ StyledTextContent content = printerRenderer.content;
+ startLine = 0;
+ endLine = singleLine ? 0 : content.getLineCount() - 1;
+ PrinterData data = printer.getPrinterData();
+ if (data.scope == PrinterData.PAGE_RANGE) {
+ int pageSize = clientArea.height / lineHeight;//WRONG
+ startLine = (startPage - 1) * pageSize;
+ } else if (data.scope == PrinterData.SELECTION) {
+ startLine = content.getLineAtOffset(selection.x);
+ if (selection.y > 0) {
+ endLine = content.getLineAtOffset(selection.x + selection.y - 1);
+ } else {
+ endLine = startLine - 1;
+ }
+ }
+ }
+ /**
+ * Prints the lines in the specified page range.
+ */
+ void print() {
+ Color background = gc.getBackground();
+ Color foreground = gc.getForeground();
+ int paintY = clientArea.y;
+ int paintX = clientArea.x;
+ int page = startPage;
+ int pageBottom = clientArea.y + clientArea.height;
+ int orientation = gc.getStyle() & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT);
+
+
+ for (int i = startLine; i <= endLine && page <= endPage; i++) {
+ if (paintY == clientArea.y) {
+ printer.startPage();
+ printDecoration(page, true);
+ }
+ TextLayout layout = printerRenderer.getTextLayout(i, orientation, clientArea.width, lineSpacing);
+ Color lineBackground = printerRenderer.getLineBackground(i, background);
+ int paragraphBottom = paintY + layout.getBounds().height;
+ if (paragraphBottom <= pageBottom) {
+ //normal case, the whole paragraph fits in the current page
+ printLine(paintX, paintY, gc, foreground, lineBackground, layout);
+ paintY = paragraphBottom;
+ } else {
+ int lineCount = layout.getLineCount();
+ while (paragraphBottom > pageBottom && lineCount > 0) {
+ lineCount--;
+ paragraphBottom -= layout.getLineBounds(lineCount).height + layout.getSpacing();
+ }
+ if (lineCount == 0) {
+ //the whole paragraph goes to the next page
+ printDecoration(page, false);
+ printer.endPage();
+ page++;
+ if (page <= endPage) {
+ printer.startPage();
+ printDecoration(page, true);
+ paintY = clientArea.y;
+ printLine(paintX, paintY, gc, foreground, lineBackground, layout);
+ paintY += layout.getBounds().height;
+ }
+ } else {
+ //draw paragraph top in the current page and paragraph bottom in the next
+ int height = paragraphBottom - paintY;
+ gc.setClipping(paintX, paintY, clientArea.width, height);
+ printLine(paintX, paintY, gc, foreground, lineBackground, layout);
+ printDecoration(page, false);
+ printer.endPage();
+ page++;
+ if (page <= endPage) {
+ printer.startPage();
+ printDecoration(page, true);
+ paintY = clientArea.y - height;
+ int layoutHeight = layout.getBounds().height;
+ gc.setClipping(paintX, clientArea.y, clientArea.width, layoutHeight - height);
+ printLine(paintX, paintY, gc, foreground, lineBackground, layout);
+ paintY += layoutHeight;
+ }
+ gc.setClipping((Rectangle)null);
+ }
+ }
+ printerRenderer.disposeTextLayout(layout);
+ }
+ if (paintY > clientArea.y) {
+ // close partial page
+ printDecoration(page, false);
+ printer.endPage();
+ }
+ }
+ /**
+ * Print header or footer decorations.
+ *
+ * @param page page number to print, if specified in the StyledTextPrintOptions header or footer.
+ * @param header true = print the header, false = print the footer
+ */
+ void printDecoration(int page, boolean header) {
+ String text = header ? printOptions.header : printOptions.footer;
+ if (text == null) return;
+ int lastSegmentIndex = 0;
+ int segmentCount = 3;
+ for (int i = 0; i < segmentCount; i++) {
+ int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex);
+ String segment;
+ if (segmentIndex == -1) {
+ segment = text.substring(lastSegmentIndex);
+ printDecorationSegment(segment, i, page, header);
+ break;
+ } else {
+ segment = text.substring(lastSegmentIndex, segmentIndex);
+ printDecorationSegment(segment, i, page, header);
+ lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length();
+ }
+ }
+ }
+ /**
+ * Print one segment of a header or footer decoration.
+ * Headers and footers have three different segments.
+ * One each for left aligned, centered, and right aligned text.
+ *
+ * @param segment decoration segment to print
+ * @param alignment alignment of the segment. 0=left, 1=center, 2=right
+ * @param page page number to print, if specified in the decoration segment.
+ * @param header true = print the header, false = print the footer
+ */
+ void printDecorationSegment(String segment, int alignment, int page, boolean header) {
+ int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG);
+ if (pageIndex != -1) {
+ int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length();
+ StringBuffer buffer = new StringBuffer(segment.substring (0, pageIndex));
+ buffer.append (page);
+ buffer.append (segment.substring(pageIndex + pageTagLength));
+ segment = buffer.toString();
+ }
+ if (segment.length() > 0) {
+ TextLayout layout = new TextLayout(printer);
+ layout.setText(segment);
+ layout.setFont(printerFont);
+ int segmentWidth = layout.getBounds().width;
+ int segmentHeight = printerRenderer.getLineHeight();
+ int drawX = 0, drawY;
+ if (alignment == LEFT) {
+ drawX = clientArea.x;
+ } else if (alignment == CENTER) {
+ drawX = (pageWidth - segmentWidth) / 2;
+ } else if (alignment == RIGHT) {
+ drawX = clientArea.x + clientArea.width - segmentWidth;
+ }
+ if (header) {
+ drawY = clientArea.y - segmentHeight * 2;
+ } else {
+ drawY = clientArea.y + clientArea.height + segmentHeight;
+ }
+ layout.draw(gc, drawX, drawY);
+ layout.dispose();
+ }
+ }
+ void printLine(int paintX, int paintY, GC gc, Color foreground, Color background, TextLayout layout) {
+ if (background != null) {
+ Rectangle rect = layout.getBounds();
+ gc.setBackground(background);
+ gc.fillRectangle(paintX, paintY, rect.width, rect.height);
+
+// int lineCount = layout.getLineCount();
+// for (int i = 0; i < lineCount; i++) {
+// Rectangle rect = layout.getLineBounds(i);
+// rect.x += paintX;
+// rect.y += paintY + layout.getSpacing();
+// rect.width = width;//layout bounds
+// gc.fillRectangle(rect);
+// }
+ }
+ gc.setForeground(foreground);
+ layout.draw(gc, paintX, paintY);
+ }
+ /**
+ * Starts a print job and prints the pages specified in the constructor.
+ */
+ public void run() {
+ String jobName = printOptions.jobName;
+ if (jobName == null) {
+ jobName = "Printing";
+ }
+ if (printer.startJob(jobName)) {
+ init();
+ print();
+ dispose();
+ printer.endJob();
+ }
+ }
+ }
+ /**
+ * The RTFWriter class is used to write widget content as
+ * rich text. The implementation complies with the RTF specification
+ * version 1.5.
+ *
+ * toString() is guaranteed to return a valid RTF string only after
+ * close() has been called.
+ *
+ * Whole and partial lines and line breaks can be written. Lines will be
+ * formatted using the styles queried from the LineStyleListener, if
+ * set, or those set directly in the widget. All styles are applied to
+ * the RTF stream like they are rendered by the widget. In addition, the
+ * widget font name and size is used for the whole text.
+ *
+ */
+ class RTFWriter extends TextWriter {
+ static final int DEFAULT_FOREGROUND = 0;
+ static final int DEFAULT_BACKGROUND = 1;
+ Vector colorTable, fontTable;
+ boolean WriteUnicode;
+
+ /**
+ * Creates a RTF writer that writes content starting at offset "start"
+ * in the document. start and lengthcan be set to specify partial
+ * lines.
+ *
+ * @param start start offset of content to write, 0 based from
+ * beginning of document
+ * @param length length of content to write
+ */
+ public RTFWriter(int start, int length) {
+ super(start, length);
+ colorTable = new Vector();
+ fontTable = new Vector();
+ colorTable.addElement(getForeground());
+ colorTable.addElement(getBackground());
+ fontTable.addElement(getFont());
+ setUnicode();
+ }
+ /**
+ * Closes the RTF writer. Once closed no more content can be written.
+ * NOTE:toString() does not return a valid RTF string until
+ * close() has been called.
+ */
+ public void close() {
+ if (!isClosed()) {
+ writeHeader();
+ write("\n}}\0");
+ super.close();
+ }
+ }
+ /**
+ * Returns the index of the specified color in the RTF color table.
+ *
+ * @param color the color
+ * @param defaultIndex return value if color is null
+ * @return the index of the specified color in the RTF color table
+ * or "defaultIndex" if "color" is null.
+ */
+ int getColorIndex(Color color, int defaultIndex) {
+ if (color == null) return defaultIndex;
+ int index = colorTable.indexOf(color);
+ if (index == -1) {
+ index = colorTable.size();
+ colorTable.addElement(color);
+ }
+ return index;
+ }
+ /**
+ * Returns the index of the specified color in the RTF color table.
+ *
+ * @param color the color
+ * @param defaultIndex return value if color is null
+ * @return the index of the specified color in the RTF color table
+ * or "defaultIndex" if "color" is null.
+ */
+ int getFontIndex(Font font) {
+ int index = fontTable.indexOf(font);
+ if (index == -1) {
+ index = fontTable.size();
+ fontTable.addElement(font);
+ }
+ return index;
+ }
+ /**
+ * Determines if Unicode RTF should be written.
+ * Don't write Unicode RTF on Windows 95/98/ME or NT.
+ */
+ void setUnicode() {
+ final String Win95 = "windows 95";
+ final String Win98 = "windows 98";
+ final String WinME = "windows me";
+ final String WinNT = "windows nt";
+ String osName = System.getProperty("os.name").toLowerCase();
+ String osVersion = System.getProperty("os.version");
+ int majorVersion = 0;
+
+ if (osName.startsWith(WinNT) && osVersion != null) {
+ int majorIndex = osVersion.indexOf('.');
+ if (majorIndex != -1) {
+ osVersion = osVersion.substring(0, majorIndex);
+ try {
+ majorVersion = Integer.parseInt(osVersion);
+ } catch (NumberFormatException exception) {
+ // ignore exception. version number remains unknown.
+ // will write without Unicode
+ }
+ }
+ }
+ WriteUnicode = !osName.startsWith(Win95) &&
+ !osName.startsWith(Win98) &&
+ !osName.startsWith(WinME) &&
+ (!osName.startsWith(WinNT) || majorVersion > 4);
+ }
+ /**
+ * Appends the specified segment of "string" to the RTF data.
+ * Copy from start up to, but excluding, end.
+ *
+ * @param string string to copy a segment from. Must not contain
+ * line breaks. Line breaks should be written using writeLineDelimiter()
+ * @param start start offset of segment. 0 based.
+ * @param end end offset of segment
+ */
+ void write(String string, int start, int end) {
+ for (int index = start; index < end; index++) {
+ char ch = string.charAt(index);
+ if (ch > 0xFF && WriteUnicode) {
+ // write the sub string from the last escaped character
+ // to the current one. Fixes bug 21698.
+ if (index > start) {
+ write(string.substring(start, index));
+ }
+ write("\\u");
+ write(Integer.toString((short) ch));
+ write(' '); // control word delimiter
+ start = index + 1;
+ } else if (ch == '}' || ch == '{' || ch == '\\') {
+ // write the sub string from the last escaped character
+ // to the current one. Fixes bug 21698.
+ if (index > start) {
+ write(string.substring(start, index));
+ }
+ write('\\');
+ write(ch);
+ start = index + 1;
+ }
+ }
+ // write from the last escaped character to the end.
+ // Fixes bug 21698.
+ if (start < end) {
+ write(string.substring(start, end));
+ }
+ }
+ /**
+ * Writes the RTF header including font table and color table.
+ */
+ void writeHeader() {
+ StringBuffer header = new StringBuffer();
+ FontData fontData = getFont().getFontData()[0];
+ header.append("{\\rtf1\\ansi");
+ // specify code page, necessary for copy to work in bidi
+ // systems that don't support Unicode RTF.
+ String cpg = System.getProperty("file.encoding").toLowerCase();
+ if (cpg.startsWith("cp") || cpg.startsWith("ms")) {
+ cpg = cpg.substring(2, cpg.length());
+ header.append("\\ansicpg");
+ header.append(cpg);
+ }
+ header.append("\\uc0\\deff0{\\fonttbl{\\f0\\fnil ");
+ header.append(fontData.getName());
+ header.append(";");
+ for (int i = 1; i < fontTable.size(); i++) {
+ header.append("\\f");
+ header.append(i);
+ header.append(" ");
+ FontData fd = ((Font)fontTable.elementAt(i)).getFontData()[0];
+ header.append(fd.getName());
+ header.append(";");
+ }
+ header.append("}}\n{\\colortbl");
+ for (int i = 0; i < colorTable.size(); i++) {
+ Color color = (Color) colorTable.elementAt(i);
+ header.append("\\red");
+ header.append(color.getRed());
+ header.append("\\green");
+ header.append(color.getGreen());
+ header.append("\\blue");
+ header.append(color.getBlue());
+ header.append(";");
+ }
+ // some RTF readers ignore the deff0 font tag. Explicitly
+ // set the font for the whole document to work around this.
+ header.append("}\n{\\f0\\fs");
+ // font size is specified in half points
+ header.append(fontData.getHeight() * 2);
+ header.append(" ");
+ write(header.toString(), 0);
+ }
+ /**
+ * Appends the specified line text to the RTF data. Lines will be formatted
+ * using the styles queried from the LineStyleListener, if set, or those set
+ * directly in the widget.
+ *
+ * @param line line text to write as RTF. Must not contain line breaks
+ * Line breaks should be written using writeLineDelimiter()
+ * @param lineOffset offset of the line. 0 based from the start of the
+ * widget document. Any text occurring before the start offset or after the
+ * end offset specified during object creation is ignored.
+ * @exception SWTException
+ */
+ public void writeLineDelimiter(String lineDelimiter) {
+ if (isClosed()) {
+ SWT.error(SWT.ERROR_IO);
+ }
+ write(lineDelimiter, 0, lineDelimiter.length());
+ write("\\par ");
+ }
+ /**
+ * Appends the specified line text to the RTF data.
+ *
+ * Use the colors and font styles specified in "styles" and "lineBackground".
+ * Formatting is written to reflect the text rendering by the text widget.
+ * Style background colors take precedence over the line background color.
+ * Background colors are written using the \highlight tag (vs. the \cb tag).
+ *
+ *
+ * @param line line text to write as RTF. Must not contain line breaks
+ * Line breaks should be written using writeLineDelimiter()
+ * @param lineOffset offset of the line. 0 based from the start of the
+ * widget document. Any text occurring before the start offset or after the
+ * end offset specified during object creation is ignored.
+ * @param styles styles to use for formatting. Must not be null.
+ * @param lineBackground line background color to use for formatting.
+ * May be null.
+ */
+ void writeStyledLine(String line, int lineOffset, int ranges[], StyleRange[] styles, Color lineBackground, int indent, int alignment, boolean justify) {
+ int lineLength = line.length();
+ int startOffset = getStart();
+ int writeOffset = startOffset - lineOffset;
+ if (writeOffset >= lineLength) return;
+ int lineIndex = Math.max(0, writeOffset);
+
+ write("\\fi");
+ write(indent);
+ switch (alignment) {
+ case SWT.LEFT: write("\\ql"); break;
+ case SWT.CENTER: write("\\qc"); break;
+ case SWT.RIGHT: write("\\qr"); break;
+ }
+ if (justify) write("\\qj");
+ write(" ");
+
+ if (lineBackground != null) {
+ write("{\\highlight");
+ write(getColorIndex(lineBackground, DEFAULT_BACKGROUND));
+ write(" ");
+ }
+ int endOffset = startOffset + super.getCharCount();
+ int lineEndOffset = Math.min(lineLength, endOffset - lineOffset);
+ for (int i = 0; i < styles.length; i++) {
+ StyleRange style = styles[i];
+ int start, end;
+ if (ranges != null) {
+ start = ranges[i << 1] - lineOffset;
+ end = start + ranges[(i << 1) + 1];
+ } else {
+ start = style.start - lineOffset;
+ end = start + style.length;
+ }
+ // skip over partial first line
+ if (end < writeOffset) {
+ continue;
+ }
+ // style starts beyond line end or RTF write end
+ if (start >= lineEndOffset) {
+ break;
+ }
+ // write any unstyled text
+ if (lineIndex < start) {
+ // copy to start of style
+ // style starting betond end of write range or end of line
+ // is guarded against above.
+ write(line, lineIndex, start);
+ lineIndex = start;
+ }
+ // write styled text
+ write("{\\cf");
+ write(getColorIndex(style.foreground, DEFAULT_FOREGROUND));
+ int colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND);
+ if (colorIndex != DEFAULT_BACKGROUND) {
+ write("\\highlight");
+ write(colorIndex);
+ }
+ Font font = style.font;
+ if (font != null) {
+ int fontIndex = getFontIndex(font);
+ write("\\f");
+ write(fontIndex);
+ FontData fontData = font.getFontData()[0];
+ write("\\fs");
+ write(fontData.getHeight() * 2);
+ } else {
+ if ((style.fontStyle & SWT.BOLD) != 0) {
+ write("\\b");
+ }
+ if ((style.fontStyle & SWT.ITALIC) != 0) {
+ write("\\i");
+ }
+ }
+ if (style.underline) {
+ write("\\ul");
+ }
+ if (style.strikeout) {
+ write("\\strike");
+ }
+ write(" ");
+ // copy to end of style or end of write range or end of line
+ int copyEnd = Math.min(end, lineEndOffset);
+ // guard against invalid styles and let style processing continue
+ copyEnd = Math.max(copyEnd, lineIndex);
+ write(line, lineIndex, copyEnd);
+ if (font == null) {
+ if ((style.fontStyle & SWT.BOLD) != 0) {
+ write("\\b0");
+ }
+ if ((style.fontStyle & SWT.ITALIC) != 0) {
+ write("\\i0");
+ }
+ }
+ if (style.underline) {
+ write("\\ul0");
+ }
+ if (style.strikeout) {
+ write("\\strike0");
+ }
+ write("}");
+ lineIndex = copyEnd;
+ }
+ // write unstyled text at the end of the line
+ if (lineIndex < lineEndOffset) {
+ write(line, lineIndex, lineEndOffset);
+ }
+ if (lineBackground != null) write("}");
+ }
+ }
+ /**
+ * The TextWriter class is used to write widget content to
+ * a string. Whole and partial lines and line breaks can be written. To write
+ * partial lines, specify the start and length of the desired segment
+ * during object creation.
+ *
+ * NOTE: toString() is guaranteed to return a valid string only after close()
+ * has been called.
+ *
+ */
+ class TextWriter {
+ private StringBuffer buffer;
+ private int startOffset; // offset of first character that will be written
+ private int endOffset; // offset of last character that will be written.
+ // 0 based from the beginning of the widget text.
+ private boolean isClosed = false;
+
+ /**
+ * Creates a writer that writes content starting at offset "start"
+ * in the document. start and length can be set to specify partial lines.
+ *
+ * @param start start offset of content to write, 0 based from beginning of document
+ * @param length length of content to write
+ */
+ public TextWriter(int start, int length) {
+ buffer = new StringBuffer(length);
+ startOffset = start;
+ endOffset = start + length;
+ }
+ /**
+ * Closes the writer. Once closed no more content can be written.
+ * NOTE:toString() is not guaranteed to return a valid string unless
+ * the writer is closed.
+ */
+ public void close() {
+ if (!isClosed) {
+ isClosed = true;
+ }
+ }
+ /**
+ * Returns the number of characters to write.
+ * @return the integer number of characters to write
+ */
+ public int getCharCount() {
+ return endOffset - startOffset;
+ }
+ /**
+ * Returns the offset where writing starts. 0 based from the start of
+ * the widget text. Used to write partial lines.
+ * @return the integer offset where writing starts
+ */
+ public int getStart() {
+ return startOffset;
+ }
+ /**
+ * Returns whether the writer is closed.
+ * @return a boolean specifying whether or not the writer is closed
+ */
+ public boolean isClosed() {
+ return isClosed;
+ }
+ /**
+ * Returns the string. close() must be called before toString()
+ * is guaranteed to return a valid string.
+ *
+ * @return the string
+ */
+ public String toString() {
+ return buffer.toString();
+ }
+ /**
+ * Appends the given string to the data.
+ */
+ void write(String string) {
+ buffer.append(string);
+ }
+ /**
+ * Inserts the given string to the data at the specified offset.
+ *
+ * Do nothing if "offset" is < 0 or > getCharCount()
+ *
+ *
+ * @param string text to insert
+ * @param offset offset in the existing data to insert "string" at.
+ */
+ void write(String string, int offset) {
+ if (offset < 0 || offset > buffer.length()) {
+ return;
+ }
+ buffer.insert(offset, string);
+ }
+ /**
+ * Appends the given int to the data.
+ */
+ void write(int i) {
+ buffer.append(i);
+ }
+ /**
+ * Appends the given character to the data.
+ */
+ void write(char i) {
+ buffer.append(i);
+ }
+ /**
+ * Appends the specified line text to the data.
+ *
+ * @param line line text to write. Must not contain line breaks
+ * Line breaks should be written using writeLineDelimiter()
+ * @param lineOffset offset of the line. 0 based from the start of the
+ * widget document. Any text occurring before the start offset or after the
+ * end offset specified during object creation is ignored.
+ * @exception SWTException
+ *
ERROR_IO when the writer is closed.
+ *
+ */
+ public void writeLine(String line, int lineOffset) {
+ if (isClosed) {
+ SWT.error(SWT.ERROR_IO);
+ }
+ int writeOffset = startOffset - lineOffset;
+ int lineLength = line.length();
+ int lineIndex;
+ if (writeOffset >= lineLength) {
+ return; // whole line is outside write range
+ } else if (writeOffset > 0) {
+ lineIndex = writeOffset; // line starts before write start
+ } else {
+ lineIndex = 0;
+ }
+ int copyEnd = Math.min(lineLength, endOffset - lineOffset);
+ if (lineIndex < copyEnd) {
+ write(line.substring(lineIndex, copyEnd));
+ }
+ }
+ /**
+ * Appends the specified line delmimiter to the data.
+ *
+ * @param lineDelimiter line delimiter to write
+ * @exception SWTException
+ *
ERROR_IO when the writer is closed.
+ *
+ */
+ public void writeLineDelimiter(String lineDelimiter) {
+ if (isClosed) {
+ SWT.error(SWT.ERROR_IO);
+ }
+ write(lineDelimiter);
+ }
+ }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
+ *
+ * @see SWT#FULL_SELECTION
+ * @see SWT#MULTI
+ * @see SWT#READ_ONLY
+ * @see SWT#SINGLE
+ * @see SWT#WRAP
+ * @see #getStyle
+ */
+public StyledText(Composite parent, int style) {
+ super(parent, checkStyle(style));
+ // set the fg in the OS to ensure that these are the same as StyledText, necessary
+ // for ensuring that the bg/fg the IME box uses is the same as what StyledText uses
+ super.setForeground(getForeground());
+ Display display = getDisplay();
+ isMirrored = (super.getStyle() & SWT.MIRRORED) != 0;
+ fixedLineHeight = true;
+ if ((style & SWT.READ_ONLY) != 0) {
+ setEditable(false);
+ }
+ leftMargin = rightMargin = isBidiCaret() ? BIDI_CARET_WIDTH - 1: 0;
+ if ((style & SWT.SINGLE) != 0 && (style & SWT.BORDER) != 0) {
+ leftMargin = topMargin = rightMargin = bottomMargin = 2;
+ }
+ alignment = style & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ if (alignment == 0) alignment = SWT.LEFT;
+ clipboard = new Clipboard(display);
+ installDefaultContent();
+ renderer = new StyledTextRenderer(getDisplay(), this);
+ renderer.setContent(content);
+ renderer.setFont(getFont(), tabLength);
+ defaultCaret = new Caret(this, SWT.NULL);
+ if ((style & SWT.WRAP) != 0) {
+ setWordWrap(true);
+ }
+ if (isBidiCaret()) {
+ createCaretBitmaps();
+ Runnable runnable = new Runnable() {
+ public void run() {
+ int direction = BidiUtil.getKeyboardLanguage() == BidiUtil.KEYBOARD_BIDI ? SWT.RIGHT : SWT.LEFT;
+ if (direction == caretDirection) return;
+ if (getCaret() != defaultCaret) return;
+ Point newCaretPos = getPointAtOffset(caretOffset);
+ setCaretLocation(newCaretPos, direction);
+ }
+ };
+ BidiUtil.addLanguageListener(handle, runnable);
+ }
+ setCaret(defaultCaret);
+ calculateScrollBars();
+ createKeyBindings();
+ setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM));
+ installListeners();
+ initializeAccessible();
+}
+/**
+ * Adds an extended modify listener. An ExtendedModify event is sent by the
+ * widget when the widget text has changed.
+ *
+ * @param extendedModifyListener the listener
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * A BidiSegmentEvent is sent
+ * whenever a line of text is measured or rendered. The user can
+ * specify text ranges in the line that should be treated as if they
+ * had a different direction than the surrounding text.
+ * This may be used when adjacent segments of right-to-left text should
+ * not be reordered relative to each other.
+ * E.g., Multiple Java string literals in a right-to-left language
+ * should generally remain in logical order to each other, that is, the
+ * way they are stored.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when listener is null
+ *
+ * @see BidiSegmentEvent
+ * @since 2.0
+ */
+public void addBidiSegmentListener(BidiSegmentListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ addListener(LineGetSegments, new StyledTextListener(listener));
+}
+/**
+ * Adds a line background listener. A LineGetBackground event is sent by the
+ * widget to determine the background color for a line.
+ *
+ * @param listener the listener
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void addLineBackgroundListener(LineBackgroundListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (!isListening(LineGetBackground)) {
+ renderer.clearLineBackground(0, content.getLineCount());
+ }
+ addListener(LineGetBackground, new StyledTextListener(listener));
+}
+/**
+ * Adds a line style listener. A LineGetStyle event is sent by the widget to
+ * determine the styles for a line.
+ *
+ * @param listener the listener
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void addLineStyleListener(LineStyleListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (!isListening(LineGetStyle)) {
+ setStyleRanges(0, 0, null, null, true);
+ renderer.clearLineStyle(0, content.getLineCount());
+ }
+ addListener(LineGetStyle, new StyledTextListener(listener));
+}
+/**
+ * Adds a modify listener. A Modify event is sent by the widget when the widget text
+ * has changed.
+ *
+ * @param modifyListener the listener
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void addModifyListener(ModifyListener modifyListener) {
+ checkWidget();
+ if (modifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ addListener(SWT.Modify, new TypedListener(modifyListener));
+}
+/**
+ * Adds a paint object listener. A paint object event is sent by the widget when an object
+ * needs to be drawn.
+ *
+ * @param listener the listener
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when listener is null
+ *
+ *
+ * @since 3.2
+ *
+ * @see PaintObjectListener
+ * @see PaintObjectEvent
+ */
+public void addPaintObjectListener(PaintObjectListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ addListener(PaintObject, new StyledTextListener(listener));
+}
+/**
+ * Adds a selection listener. A Selection event is sent by the widget when the
+ * selection has changed.
+ *
+ * When widgetSelected is called, the event x and y fields contain
+ * the start and end caret indices of the selection.
+ * widgetDefaultSelected is not called for StyledTexts.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ addListener(SWT.Selection, new TypedListener(listener));
+}
+/**
+ * Adds a verify key listener. A VerifyKey event is sent by the widget when a key
+ * is pressed. The widget ignores the key press if the listener sets the doit field
+ * of the event to false.
+ *
+ * @param listener the listener
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void addVerifyKeyListener(VerifyKeyListener listener) {
+ checkWidget();
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ addListener(VerifyKey, new StyledTextListener(listener));
+}
+/**
+ * Adds a verify listener. A Verify event is sent by the widget when the widget text
+ * is about to change. The listener can set the event text and the doit field to
+ * change the text that is set in the widget or to force the widget to ignore the
+ * text change.
+ *
+ * @param verifyListener the listener
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void addVerifyListener(VerifyListener verifyListener) {
+ checkWidget();
+ if (verifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ addListener(SWT.Verify, new TypedListener(verifyListener));
+}
+/**
+ * Appends a string to the text at the end of the widget.
+ *
+ * @param string the string to be appended
+ * @see #replaceTextRange(int,int,String)
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void append(String string) {
+ checkWidget();
+ if (string == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ int lastChar = Math.max(getCharCount(), 0);
+ replaceTextRange(lastChar, 0, string);
+}
+/**
+ * Calculates the scroll bars
+ */
+void calculateScrollBars() {
+ ScrollBar horizontalBar = getHorizontalBar();
+ ScrollBar verticalBar = getVerticalBar();
+ setScrollBars(true);
+ if (verticalBar != null) {
+ verticalBar.setIncrement(getVerticalIncrement());
+ }
+ if (horizontalBar != null) {
+ horizontalBar.setIncrement(getHorizontalIncrement());
+ }
+}
+/**
+ * Calculates the top index based on the current vertical scroll offset.
+ * The top index is the index of the topmost fully visible line or the
+ * topmost partially visible line if no line is fully visible.
+ * The top index starts at 0.
+ */
+void calculateTopIndex(int delta) {
+ int oldTopIndex = topIndex;
+ int oldTopIndexY = topIndexY;
+ if (isFixedLineHeight()) {
+ int verticalIncrement = getVerticalIncrement();
+ if (verticalIncrement == 0) {
+ return;
+ }
+ topIndex = Compatibility.ceil(getVerticalScrollOffset(), verticalIncrement);
+ // Set top index to partially visible top line if no line is fully
+ // visible but at least some of the widget client area is visible.
+ // Fixes bug 15088.
+ if (topIndex > 0) {
+ if (clientAreaHeight > 0) {
+ int bottomPixel = getVerticalScrollOffset() + clientAreaHeight;
+ int fullLineTopPixel = topIndex * verticalIncrement;
+ int fullLineVisibleHeight = bottomPixel - fullLineTopPixel;
+ // set top index to partially visible line if no line fully fits in
+ // client area or if space is available but not used (the latter should
+ // never happen because we use claimBottomFreeSpace)
+ if (fullLineVisibleHeight < verticalIncrement) {
+ topIndex--;
+ }
+ } else if (topIndex >= content.getLineCount()) {
+ topIndex = content.getLineCount() - 1;
+ }
+ }
+ } else {
+ if (delta >= 0) {
+ delta -= topIndexY;
+ int lineIndex = topIndex;
+ int lineCount = content.getLineCount();
+ while (lineIndex < lineCount) {
+ if (delta <= 0) break;
+ delta -= renderer.getLineHeight(lineIndex++);
+ }
+ if (lineIndex < lineCount && -delta + renderer.getLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) {
+ topIndex = lineIndex;
+ topIndexY = -delta;
+ } else {
+ topIndex = lineIndex - 1;
+ topIndexY = -renderer.getLineHeight(topIndex) - delta;
+ }
+ } else {
+ delta -= topIndexY;
+ int lineIndex = topIndex;
+ while (lineIndex > 0) {
+ int lineHeight = renderer.getLineHeight(lineIndex - 1);
+ if (delta + lineHeight > 0) break;
+ delta += lineHeight;
+ lineIndex--;
+ }
+ if (lineIndex == 0 || -delta + renderer.getLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) {
+ topIndex = lineIndex;
+ topIndexY = - delta;
+ } else {
+ topIndex = lineIndex - 1;
+ topIndexY = - renderer.getLineHeight(topIndex) - delta;
+ }
+ }
+ }
+ if (topIndex != oldTopIndex || oldTopIndexY != topIndexY) {
+ renderer.calculateClientArea();
+ setScrollBars(false);
+ }
+}
+/**
+ * Hides the scroll bars if widget is created in single line mode.
+ */
+static int checkStyle(int style) {
+ if ((style & SWT.SINGLE) != 0) {
+ style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP | SWT.MULTI);
+ } else {
+ style |= SWT.MULTI;
+ if ((style & SWT.WRAP) != 0) {
+ style &= ~SWT.H_SCROLL;
+ }
+ }
+ style |= SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND;
+ return style;
+}
+/**
+ * Scrolls down the text to use new space made available by a resize or by
+ * deleted lines.
+ */
+void claimBottomFreeSpace() {
+ int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin;
+ if (isFixedLineHeight()) {
+ int lineHeight = renderer.getLineHeight();
+ int newVerticalOffset = Math.max(0, content.getLineCount() * lineHeight - clientAreaHeight);
+ if (newVerticalOffset < getVerticalScrollOffset()) {
+ scrollVertical(newVerticalOffset - getVerticalScrollOffset(), true);
+ }
+ } else {
+ int bottomIndex = getPartialBottomIndex();
+ int height = getLinePixel(bottomIndex + 1);
+ if (clientAreaHeight > height) {
+ scrollVertical(-getAvailableHeightAbove(clientAreaHeight - height), true);
+ }
+ }
+}
+/**
+ * Scrolls text to the right to use new space made available by a resize.
+ */
+void claimRightFreeSpace() {
+ int newHorizontalOffset = Math.max(0, renderer.getWidth() - (clientAreaWidth - leftMargin - rightMargin));
+ if (newHorizontalOffset < horizontalScrollOffset) {
+ // item is no longer drawn past the right border of the client area
+ // align the right end of the item with the right border of the
+ // client area (window is scrolled right).
+ scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true);
+ }
+}
+/**
+ * Removes the widget selection.
+ *
+ * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset.
+ */
+void clearSelection(boolean sendEvent) {
+ int selectionStart = selection.x;
+ int selectionEnd = selection.y;
+ resetSelection();
+ // redraw old selection, if any
+ if (selectionEnd - selectionStart > 0) {
+ int length = content.getCharCount();
+ // called internally to remove selection after text is removed
+ // therefore make sure redraw range is valid.
+ int redrawStart = Math.min(selectionStart, length);
+ int redrawEnd = Math.min(selectionEnd, length);
+ if (redrawEnd - redrawStart > 0) {
+ internalRedrawRange(redrawStart, redrawEnd - redrawStart);
+ }
+ if (sendEvent) {
+ sendSelectionEvent();
+ }
+ }
+}
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget();
+ int lineCount = (getStyle() & SWT.SINGLE) != 0 ? 1 : content.getLineCount();
+ int width = 0;
+ int height = 0;
+ if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
+ Display display = getDisplay();
+ int maxHeight = display.getClientArea().height;
+ for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ if (wordWrap) layout.setWidth(wHint == 0 ? 1 : wHint);
+ Rectangle rect = layout.getBounds();
+ height += rect.height;
+ width = Math.max(width, rect.width);
+ renderer.disposeTextLayout(layout);
+ if (isFixedLineHeight() && height > maxHeight) break;
+ }
+ if (isFixedLineHeight()) {
+ height = lineCount * renderer.getLineHeight();
+ }
+ }
+ // Use default values if no text is defined.
+ if (width == 0) width = DEFAULT_WIDTH;
+ if (height == 0) height = DEFAULT_HEIGHT;
+ if (wHint != SWT.DEFAULT) width = wHint;
+ if (hHint != SWT.DEFAULT) height = hHint;
+ int wTrim = leftMargin + rightMargin + getCaretWidth();
+ int hTrim = topMargin + bottomMargin;
+ Rectangle rect = computeTrim(0, 0, width + wTrim, height + hTrim);
+ return new Point (rect.width, rect.height);
+}
+/**
+ * Copies the selected text to the DND.CLIPBOARD clipboard.
+ *
+ * The text will be put on the clipboard in plain text format and RTF format.
+ * The DND.CLIPBOARD clipboard is used for data that is
+ * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or
+ * by menu action.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void copy() {
+ checkWidget();
+ copy(DND.CLIPBOARD);
+}
+/**
+ * Copies the selected text to the specified clipboard. The text will be put in the
+ * clipboard in plain text format and RTF format.
+ *
+ * The clipboardType is one of the clipboard constants defined in class
+ * DND. The DND.CLIPBOARD clipboard is
+ * used for data that is transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V)
+ * or by menu action. The DND.SELECTION_CLIPBOARD
+ * clipboard is used for data that is transferred by selecting text and pasting
+ * with the middle mouse button.
+ *
+ *
+ * @param clipboardType indicates the type of clipboard
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void copy(int clipboardType) {
+ checkWidget();
+ if (clipboardType != DND.CLIPBOARD && clipboardType != DND.SELECTION_CLIPBOARD) return;
+ int length = selection.y - selection.x;
+ if (length > 0) {
+ try {
+ setClipboardContent(selection.x, length, clipboardType);
+ } catch (SWTError error) {
+ // Copy to clipboard failed. This happens when another application
+ // is accessing the clipboard while we copy. Ignore the error.
+ // Fixes 1GDQAVN
+ // Rethrow all other errors. Fixes bug 17578.
+ if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) {
+ throw error;
+ }
+ }
+ }
+}
+/**
+ * Returns the alignment of the widget.
+ *
+ * @return the alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getLineAlignment(int)
+ *
+ * @since 3.2
+ */
+public int getAlignment() {
+ checkWidget();
+ return alignment;
+}
+int getAvailableHeightAbove(int height) {
+ int maxHeight = verticalScrollOffset;
+ if (maxHeight == -1) {
+ int lineIndex = topIndex - 1;
+ maxHeight = -topIndexY;
+ if (topIndexY > 0) {
+ maxHeight += renderer.getLineHeight(lineIndex--);
+ }
+ while (height > maxHeight && lineIndex >= 0) {
+ maxHeight += renderer.getLineHeight(lineIndex--);
+ }
+ }
+ return Math.min(height, maxHeight);
+}
+int getAvailableHeightBellow(int height) {
+ int partialBottomIndex = getPartialBottomIndex();
+ int topY = getLinePixel(partialBottomIndex);
+ int lineHeight = renderer.getLineHeight(partialBottomIndex);
+ int availableHeight = 0;
+ int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin;
+ if (topY + lineHeight > clientAreaHeight) {
+ availableHeight = lineHeight - (clientAreaHeight - topY);
+ }
+ int lineIndex = partialBottomIndex + 1;
+ int lineCount = content.getLineCount();
+ while (height > availableHeight && lineIndex < lineCount) {
+ availableHeight += renderer.getLineHeight(lineIndex++);
+ }
+ return Math.min(height, availableHeight);
+}
+/**
+ * Returns a string that uses only the line delimiter specified by the
+ * StyledTextContent implementation.
+ *
+ * Returns only the first line if the widget has the SWT.SINGLE style.
+ *
+ *
+ * @param text the text that may have line delimiters that don't
+ * match the model line delimiter. Possible line delimiters
+ * are CR ('\r'), LF ('\n'), CR/LF ("\r\n")
+ * @return the converted text that only uses the line delimiter
+ * specified by the model. Returns only the first line if the widget
+ * has the SWT.SINGLE style.
+ */
+String getModelDelimitedText(String text) {
+ int length = text.length();
+ if (length == 0) {
+ return text;
+ }
+ int crIndex = 0;
+ int lfIndex = 0;
+ int i = 0;
+ StringBuffer convertedText = new StringBuffer(length);
+ String delimiter = getLineDelimiter();
+ while (i < length) {
+ if (crIndex != -1) {
+ crIndex = text.indexOf(SWT.CR, i);
+ }
+ if (lfIndex != -1) {
+ lfIndex = text.indexOf(SWT.LF, i);
+ }
+ if (lfIndex == -1 && crIndex == -1) { // no more line breaks?
+ break;
+ } else if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) {
+ convertedText.append(text.substring(i, crIndex));
+ if (lfIndex == crIndex + 1) { // CR/LF combination?
+ i = lfIndex + 1;
+ } else {
+ i = crIndex + 1;
+ }
+ } else { // LF occurs before CR!
+ convertedText.append(text.substring(i, lfIndex));
+ i = lfIndex + 1;
+ }
+ if (isSingleLine()) {
+ break;
+ }
+ convertedText.append(delimiter);
+ }
+ // copy remaining text if any and if not in single line mode or no
+ // text copied thus far (because there only is one line)
+ if (i < length && (!isSingleLine() || convertedText.length() == 0)) {
+ convertedText.append(text.substring(i));
+ }
+ return convertedText.toString();
+}
+/**
+ * Creates default key bindings.
+ */
+void createKeyBindings() {
+ int nextKey = isMirrored() ? SWT.ARROW_LEFT : SWT.ARROW_RIGHT;
+ int previousKey = isMirrored() ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
+
+ // Navigation
+ setKeyBinding(SWT.ARROW_UP, ST.LINE_UP);
+ setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN);
+ if (IS_CARBON) {
+ setKeyBinding(previousKey | SWT.MOD1, ST.LINE_START);
+ setKeyBinding(nextKey | SWT.MOD1, ST.LINE_END);
+ setKeyBinding(SWT.HOME, ST.TEXT_START);
+ setKeyBinding(SWT.END, ST.TEXT_END);
+ setKeyBinding(SWT.ARROW_UP | SWT.MOD1, ST.TEXT_START);
+ setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1, ST.TEXT_END);
+ setKeyBinding(nextKey | SWT.MOD3, ST.WORD_NEXT);
+ setKeyBinding(previousKey | SWT.MOD3, ST.WORD_PREVIOUS);
+ } else {
+ setKeyBinding(SWT.HOME, ST.LINE_START);
+ setKeyBinding(SWT.END, ST.LINE_END);
+ setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START);
+ setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END);
+ setKeyBinding(nextKey | SWT.MOD1, ST.WORD_NEXT);
+ setKeyBinding(previousKey | SWT.MOD1, ST.WORD_PREVIOUS);
+ }
+ setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP);
+ setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN);
+ setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START);
+ setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END);
+ setKeyBinding(nextKey, ST.COLUMN_NEXT);
+ setKeyBinding(previousKey, ST.COLUMN_PREVIOUS);
+
+ // Selection
+ setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP);
+ setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN);
+ if (IS_CARBON) {
+ setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_START);
+ setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_END);
+ setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_TEXT_START);
+ setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_TEXT_END);
+ setKeyBinding(SWT.ARROW_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START);
+ setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END);
+ setKeyBinding(nextKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_NEXT);
+ setKeyBinding(previousKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_PREVIOUS);
+ } else {
+ setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START);
+ setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END);
+ setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START);
+ setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END);
+ setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT);
+ setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS);
+ }
+ setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP);
+ setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN);
+ setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START);
+ setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END);
+ setKeyBinding(nextKey | SWT.MOD2, ST.SELECT_COLUMN_NEXT);
+ setKeyBinding(previousKey | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS);
+
+ // Modification
+ // Cut, Copy, Paste
+ setKeyBinding('X' | SWT.MOD1, ST.CUT);
+ setKeyBinding('C' | SWT.MOD1, ST.COPY);
+ setKeyBinding('V' | SWT.MOD1, ST.PASTE);
+ if (IS_CARBON) {
+ setKeyBinding(SWT.DEL | SWT.MOD2, ST.DELETE_NEXT);
+ setKeyBinding(SWT.BS | SWT.MOD3, ST.DELETE_WORD_PREVIOUS);
+ setKeyBinding(SWT.DEL | SWT.MOD3, ST.DELETE_WORD_NEXT);
+ } else {
+ // Cut, Copy, Paste Wordstar style
+ setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT);
+ setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY);
+ setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE);
+ }
+ setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS);
+ setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS);
+ setKeyBinding(SWT.DEL, ST.DELETE_NEXT);
+ setKeyBinding(SWT.BS | SWT.MOD1, ST.DELETE_WORD_PREVIOUS);
+ setKeyBinding(SWT.DEL | SWT.MOD1, ST.DELETE_WORD_NEXT);
+
+ // Miscellaneous
+ setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE);
+}
+/**
+ * Create the bitmaps to use for the caret in bidi mode. This
+ * method only needs to be called upon widget creation and when the
+ * font changes (the caret bitmap height needs to match font height).
+ */
+void createCaretBitmaps() {
+ int caretWidth = BIDI_CARET_WIDTH;
+ Display display = getDisplay();
+ if (leftCaretBitmap != null) {
+ if (defaultCaret != null && leftCaretBitmap.equals(defaultCaret.getImage())) {
+ defaultCaret.setImage(null);
+ }
+ leftCaretBitmap.dispose();
+ }
+ int lineHeight = renderer.getLineHeight();
+ leftCaretBitmap = new Image(display, caretWidth, lineHeight);
+ GC gc = new GC (leftCaretBitmap);
+ gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+ gc.fillRectangle(0, 0, caretWidth, lineHeight);
+ gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+ gc.drawLine(0,0,0,lineHeight);
+ gc.drawLine(0,0,caretWidth-1,0);
+ gc.drawLine(0,1,1,1);
+ gc.dispose();
+
+ if (rightCaretBitmap != null) {
+ if (defaultCaret != null && rightCaretBitmap.equals(defaultCaret.getImage())) {
+ defaultCaret.setImage(null);
+ }
+ rightCaretBitmap.dispose();
+ }
+ rightCaretBitmap = new Image(display, caretWidth, lineHeight);
+ gc = new GC (rightCaretBitmap);
+ gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+ gc.fillRectangle(0, 0, caretWidth, lineHeight);
+ gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+ gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight);
+ gc.drawLine(0,0,caretWidth-1,0);
+ gc.drawLine(caretWidth-1,1,1,1);
+ gc.dispose();
+}
+/**
+ * Moves the selected text to the clipboard. The text will be put in the
+ * clipboard in plain text format and RTF format.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void cut(){
+ checkWidget();
+ int length = selection.y - selection.x;
+ if (length > 0) {
+ try {
+ setClipboardContent(selection.x, length, DND.CLIPBOARD);
+ } catch (SWTError error) {
+ // Copy to clipboard failed. This happens when another application
+ // is accessing the clipboard while we copy. Ignore the error.
+ // Fixes 1GDQAVN
+ // Rethrow all other errors. Fixes bug 17578.
+ if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) {
+ throw error;
+ }
+ // Abort cut operation if copy to clipboard fails.
+ // Fixes bug 21030.
+ return;
+ }
+ doDelete();
+ }
+}
+boolean detectDrag(int x, int y, int button) {
+ if (!isListening(SWT.DragDetect)) return false;
+ if (IS_MOTIF) {
+ if (button != 2) return false;
+ } else {
+ if (button != 1) return false;
+ }
+ if (selection.x == selection.y) return false;
+ int offset = getOffsetAtPoint(x, y);
+ return offset > selection.x && offset < selection.y;
+}
+/**
+ * A mouse move event has occurred. See if we should start autoscrolling. If
+ * the move position is outside of the client area, initiate autoscrolling.
+ * Otherwise, we've moved back into the widget so end autoscrolling.
+ */
+void doAutoScroll(Event event) {
+ if (event.y > clientAreaHeight) {
+ doAutoScroll(SWT.DOWN, event.y - clientAreaHeight);
+ } else if (event.y < 0) {
+ doAutoScroll(SWT.UP, -event.y);
+ } else if (event.x < leftMargin && !wordWrap) {
+ doAutoScroll(ST.COLUMN_PREVIOUS, leftMargin - event.x);
+ } else if (event.x > clientAreaWidth - leftMargin - rightMargin && !wordWrap) {
+ doAutoScroll(ST.COLUMN_NEXT, event.x - (clientAreaWidth - leftMargin - rightMargin));
+ } else {
+ endAutoScroll();
+ }
+}
+/**
+ * Initiates autoscrolling.
+ *
+ * @param direction SWT.UP, SWT.DOWN, SWT.COLUMN_NEXT, SWT.COLUMN_PREVIOUS
+ */
+void doAutoScroll(int direction, int distance) {
+ autoScrollDistance = distance;
+ // If we're already autoscrolling in the given direction do nothing
+ if (autoScrollDirection == direction) {
+ return;
+ }
+
+ Runnable timer = null;
+ final Display display = getDisplay();
+ // Set a timer that will simulate the user pressing and holding
+ // down a cursor key (i.e., arrowUp, arrowDown).
+ if (direction == SWT.UP) {
+ timer = new Runnable() {
+ public void run() {
+ if (autoScrollDirection == SWT.UP) {
+ doSelectionPageUp(autoScrollDistance);
+ display.timerExec(V_SCROLL_RATE, this);
+ }
+ }
+ };
+ autoScrollDirection = direction;
+ display.timerExec(V_SCROLL_RATE, timer);
+ } else if (direction == SWT.DOWN) {
+ timer = new Runnable() {
+ public void run() {
+ if (autoScrollDirection == SWT.DOWN) {
+ doSelectionPageDown(autoScrollDistance);
+ display.timerExec(V_SCROLL_RATE, this);
+ }
+ }
+ };
+ autoScrollDirection = direction;
+ display.timerExec(V_SCROLL_RATE, timer);
+ } else if (direction == ST.COLUMN_NEXT) {
+ timer = new Runnable() {
+ public void run() {
+ if (autoScrollDirection == ST.COLUMN_NEXT) {
+ doVisualNext();
+ setMouseWordSelectionAnchor();
+ doMouseSelection();
+ display.timerExec(H_SCROLL_RATE, this);
+ }
+ }
+ };
+ autoScrollDirection = direction;
+ display.timerExec(H_SCROLL_RATE, timer);
+ } else if (direction == ST.COLUMN_PREVIOUS) {
+ timer = new Runnable() {
+ public void run() {
+ if (autoScrollDirection == ST.COLUMN_PREVIOUS) {
+ doVisualPrevious();
+ setMouseWordSelectionAnchor();
+ doMouseSelection();
+ display.timerExec(H_SCROLL_RATE, this);
+ }
+ }
+ };
+ autoScrollDirection = direction;
+ display.timerExec(H_SCROLL_RATE, timer);
+ }
+}
+/**
+ * Deletes the previous character. Delete the selected text if any.
+ * Move the caret in front of the deleted text.
+ */
+void doBackspace() {
+ Event event = new Event();
+ event.text = "";
+ if (selection.x != selection.y) {
+ event.start = selection.x;
+ event.end = selection.y;
+ sendKeyEvent(event);
+ } else if (caretOffset > 0) {
+ int lineIndex = content.getLineAtOffset(caretOffset);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ if (caretOffset == lineOffset) {
+ lineOffset = content.getOffsetAtLine(lineIndex - 1);
+ event.start = lineOffset + content.getLine(lineIndex - 1).length();
+ event.end = caretOffset;
+ } else {
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ int start = layout.getPreviousOffset(caretOffset - lineOffset, SWT.MOVEMENT_CHAR);
+ renderer.disposeTextLayout(layout);
+ event.start = start + lineOffset;
+ event.end = caretOffset;
+ }
+ sendKeyEvent(event);
+ }
+}
+/**
+ * Replaces the selection with the character or insert the character at the
+ * current caret position if no selection exists.
+ *
+ * If a carriage return was typed replace it with the line break character
+ * used by the widget on this platform.
+ *
+ *
+ * @param key the character typed by the user
+ */
+void doContent(char key) {
+ if (textLimit > 0 &&
+ content.getCharCount() - (selection.y - selection.x) >= textLimit) {
+ return;
+ }
+ Event event = new Event();
+ event.start = selection.x;
+ event.end = selection.y;
+ // replace a CR line break with the widget line break
+ // CR does not make sense on Windows since most (all?) applications
+ // don't recognize CR as a line break.
+ if (key == SWT.CR || key == SWT.LF) {
+ if (!isSingleLine()) {
+ event.text = getLineDelimiter();
+ }
+ } else if (selection.x == selection.y && overwrite && key != TAB) {
+ // no selection and overwrite mode is on and the typed key is not a
+ // tab character (tabs are always inserted without overwriting)?
+ int lineIndex = content.getLineAtOffset(event.end);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ String line = content.getLine(lineIndex);
+ // replace character at caret offset if the caret is not at the
+ // end of the line
+ if (event.end < lineOffset + line.length()) {
+ event.end++;
+ }
+ event.text = new String(new char[] {key});
+ } else {
+ event.text = new String(new char[] {key});
+ }
+ if (event.text != null) {
+ sendKeyEvent(event);
+ }
+}
+/**
+ * Moves the caret after the last character of the widget content.
+ */
+void doContentEnd() {
+ // place caret at end of first line if receiver is in single
+ // line mode. fixes 4820.
+ if (isSingleLine()) {
+ doLineEnd();
+ } else {
+ int length = content.getCharCount();
+ if (caretOffset < length) {
+ caretOffset = length;
+ showCaret();
+ }
+ }
+}
+/**
+ * Moves the caret in front of the first character of the widget content.
+ */
+void doContentStart() {
+ if (caretOffset > 0) {
+ caretOffset = 0;
+ showCaret();
+ }
+}
+/**
+ * Moves the caret to the start of the selection if a selection exists.
+ * Otherwise, if no selection exists move the cursor according to the
+ * cursor selection rules.
+ *
+ * @see #doSelectionCursorPrevious
+ */
+void doCursorPrevious() {
+ if (selection.y - selection.x > 0) {
+ caretOffset = selection.x;
+ caretAlignment = OFFSET_LEADING;
+ showCaret();
+ } else {
+ doSelectionCursorPrevious();
+ }
+}
+/**
+ * Moves the caret to the end of the selection if a selection exists.
+ * Otherwise, if no selection exists move the cursor according to the
+ * cursor selection rules.
+ *
+ * @see #doSelectionCursorNext
+ */
+void doCursorNext() {
+ if (selection.y - selection.x > 0) {
+ caretOffset = selection.y;
+ caretAlignment = PREVIOUS_OFFSET_TRAILING;
+ showCaret();
+ } else {
+ doSelectionCursorNext();
+ }
+}
+/**
+ * Deletes the next character. Delete the selected text if any.
+ */
+void doDelete() {
+ Event event = new Event();
+ event.text = "";
+ if (selection.x != selection.y) {
+ event.start = selection.x;
+ event.end = selection.y;
+ sendKeyEvent(event);
+ } else if (caretOffset < content.getCharCount()) {
+ int line = content.getLineAtOffset(caretOffset);
+ int lineOffset = content.getOffsetAtLine(line);
+ int lineLength = content.getLine(line).length();
+ if (caretOffset == lineOffset + lineLength) {
+ event.start = caretOffset;
+ event.end = content.getOffsetAtLine(line + 1);
+ } else {
+ event.start = caretOffset;
+ event.end = getClusterNext(caretOffset, line);
+ }
+ sendKeyEvent(event);
+ }
+}
+/**
+ * Deletes the next word.
+ */
+void doDeleteWordNext() {
+ if (selection.x != selection.y) {
+ // if a selection exists, treat the as if
+ // only the delete key was pressed
+ doDelete();
+ } else {
+ Event event = new Event();
+ event.text = "";
+ event.start = caretOffset;
+ event.end = getWordEnd(caretOffset);
+ sendKeyEvent(event);
+ }
+}
+/**
+ * Deletes the previous word.
+ */
+void doDeleteWordPrevious() {
+ if (selection.x != selection.y) {
+ // if a selection exists, treat as if
+ // only the backspace key was pressed
+ doBackspace();
+ } else {
+ Event event = new Event();
+ event.text = "";
+ event.start = getWordStart(caretOffset);
+ event.end = caretOffset;
+ sendKeyEvent(event);
+ }
+}
+/**
+ * Moves the caret one line down and to the same character offset relative
+ * to the beginning of the line. Move the caret to the end of the new line
+ * if the new line is shorter than the character offset.
+ *
+ * @return index of the new line relative to the first line in the document
+ */
+void doLineDown(boolean select) {
+ int caretLine = getCaretLine();
+ int lineCount = content.getLineCount();
+ int y = 0;
+ boolean lastLine = false;
+ if (wordWrap) {
+ int lineOffset = content.getOffsetAtLine(caretLine);
+ int offsetInLine = caretOffset - lineOffset;
+ TextLayout layout = renderer.getTextLayout(caretLine);
+ int lineIndex = getVisualLineIndex(layout, offsetInLine);
+ int layoutLineCount = layout.getLineCount();
+ if (lineIndex == layoutLineCount - 1) {
+ lastLine = caretLine == lineCount - 1;
+ caretLine++;
+ } else {
+ y = layout.getLineBounds(lineIndex + 1).y;
+ }
+ renderer.disposeTextLayout(layout);
+ } else {
+ lastLine = caretLine == lineCount - 1;
+ caretLine++;
+ }
+ if (lastLine) {
+ if (select) caretOffset = content.getCharCount();
+ } else {
+ caretOffset = getOffsetAtPoint(columnX, y, caretLine);
+ }
+ int oldColumnX = columnX;
+ int oldHScrollOffset = horizontalScrollOffset;
+ if (select) {
+ setMouseWordSelectionAnchor();
+ // select first and then scroll to reduce flash when key
+ // repeat scrolls lots of lines
+ doSelection(ST.COLUMN_NEXT);
+ }
+ showCaret();
+ int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+ columnX = oldColumnX + hScrollChange;
+}
+/**
+ * Moves the caret to the end of the line.
+ */
+void doLineEnd() {
+ int caretLine = getCaretLine();
+ int lineOffset = content.getOffsetAtLine(caretLine);
+ int lineEndOffset;
+ if (wordWrap) {
+ TextLayout layout = renderer.getTextLayout(caretLine);
+ int offsetInLine = caretOffset - lineOffset;
+ int lineIndex = getVisualLineIndex(layout, offsetInLine);
+ int[] offsets = layout.getLineOffsets();
+ lineEndOffset = lineOffset + offsets[lineIndex + 1];
+ renderer.disposeTextLayout(layout);
+ } else {
+ int lineLength = content.getLine(caretLine).length();
+ lineEndOffset = lineOffset + lineLength;
+ }
+ if (caretOffset < lineEndOffset) {
+ caretOffset = lineEndOffset;
+ caretAlignment = PREVIOUS_OFFSET_TRAILING;
+ showCaret();
+ }
+}
+/**
+ * Moves the caret to the beginning of the line.
+ */
+void doLineStart() {
+ int caretLine = getCaretLine();
+ int lineOffset = content.getOffsetAtLine(caretLine);
+ if (wordWrap) {
+ TextLayout layout = renderer.getTextLayout(caretLine);
+ int offsetInLine = caretOffset - lineOffset;
+ int lineIndex = getVisualLineIndex(layout, offsetInLine);
+ int[] offsets = layout.getLineOffsets();
+ lineOffset += offsets[lineIndex];
+ renderer.disposeTextLayout(layout);
+ }
+ if (caretOffset > lineOffset) {
+ caretOffset = lineOffset;
+ caretAlignment = OFFSET_LEADING;
+ showCaret();
+ }
+}
+/**
+ * Moves the caret one line up and to the same character offset relative
+ * to the beginning of the line. Move the caret to the end of the new line
+ * if the new line is shorter than the character offset.
+ *
+ * @return index of the new line relative to the first line in the document
+ */
+void doLineUp(boolean select) {
+ int caretLine = getCaretLine(), y = 0;
+ boolean firstLine = false;
+ if (wordWrap) {
+ int lineOffset = content.getOffsetAtLine(caretLine);
+ int offsetInLine = caretOffset - lineOffset;
+ TextLayout layout = renderer.getTextLayout(caretLine);
+ int lineIndex = getVisualLineIndex(layout, offsetInLine);
+ if (lineIndex == 0) {
+ firstLine = caretLine == 0;
+ if (!firstLine) {
+ caretLine--;
+ y = renderer.getLineHeight(caretLine) - 1;
+ }
+ } else {
+ y = layout.getLineBounds(lineIndex - 1).y;
+ }
+ renderer.disposeTextLayout(layout);
+ } else {
+ firstLine = caretLine == 0;
+ caretLine--;
+ }
+ if (firstLine) {
+ if (select) caretOffset = 0;
+ } else {
+ caretOffset = getOffsetAtPoint(columnX, y, caretLine);
+ }
+ int oldColumnX = columnX;
+ int oldHScrollOffset = horizontalScrollOffset;
+ if (select) setMouseWordSelectionAnchor();
+ showCaret();
+ if (select) doSelection(ST.COLUMN_PREVIOUS);
+ int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+ columnX = oldColumnX + hScrollChange;
+}
+/**
+ * Moves the caret to the specified location.
+ *
+ * @param x x location of the new caret position
+ * @param y y location of the new caret position
+ * @param select the location change is a selection operation.
+ * include the line delimiter in the selection
+ */
+void doMouseLocationChange(int x, int y, boolean select) {
+ int line = getLineIndex(y);
+
+ updateCaretDirection = true;
+ // allow caret to be placed below first line only if receiver is
+ // not in single line mode. fixes 4820.
+ if (line < 0 || (isSingleLine() && line > 0)) {
+ return;
+ }
+ int oldCaretAlignment = caretAlignment;
+ int newCaretOffset = getOffsetAtPoint(x, y);
+
+ if (mouseDoubleClick) {
+ // double click word select the previous/next word. fixes bug 15610
+ newCaretOffset = doMouseWordSelect(x, newCaretOffset, line);
+ }
+
+ int newCaretLine = content.getLineAtOffset(newCaretOffset);
+
+ // Is the mouse within the left client area border or on
+ // a different line? If not the autoscroll selection
+ // could be incorrectly reset. Fixes 1GKM3XS
+ if (0 <= y && y < clientAreaHeight &&
+ (0 <= x && x < clientAreaWidth || wordWrap ||
+ newCaretLine != content.getLineAtOffset(caretOffset))) {
+ if (newCaretOffset != caretOffset || caretAlignment != oldCaretAlignment) {
+ caretOffset = newCaretOffset;
+ if (select) doMouseSelection();
+ showCaret();
+ }
+ }
+ if (!select) {
+ caretOffset = newCaretOffset;
+ clearSelection(true);
+ }
+}
+/**
+ * Updates the selection based on the caret position
+ */
+void doMouseSelection() {
+ if (caretOffset <= selection.x ||
+ (caretOffset > selection.x &&
+ caretOffset < selection.y && selectionAnchor == selection.x)) {
+ doSelection(ST.COLUMN_PREVIOUS);
+ } else {
+ doSelection(ST.COLUMN_NEXT);
+ }
+}
+/**
+ * Returns the offset of the word at the specified offset.
+ * If the current selection extends from high index to low index
+ * (i.e., right to left, or caret is at left border of selecton on
+ * non-bidi platforms) the start offset of the word preceeding the
+ * selection is returned. If the current selection extends from
+ * low index to high index the end offset of the word following
+ * the selection is returned.
+ *
+ * @param x mouse x location
+ * @param newCaretOffset caret offset of the mouse cursor location
+ * @param line line index of the mouse cursor location
+ */
+int doMouseWordSelect(int x, int newCaretOffset, int line) {
+ // flip selection anchor based on word selection direction from
+ // base double click. Always do this here (and don't rely on doAutoScroll)
+ // because auto scroll only does not cover all possible mouse selections
+ // (e.g., mouse x < 0 && mouse y > caret line y)
+ if (newCaretOffset < selectionAnchor && selectionAnchor == selection.x) {
+ selectionAnchor = doubleClickSelection.y;
+ } else if (newCaretOffset > selectionAnchor && selectionAnchor == selection.y) {
+ selectionAnchor = doubleClickSelection.x;
+ }
+ if (0 <= x && x < clientAreaWidth) {
+ int wordOffset;
+ // find the previous/next word
+ if (caretOffset == selection.x) {
+ wordOffset = getWordStart(newCaretOffset);
+ } else {
+ wordOffset = getWordEndNoSpaces(newCaretOffset);
+ }
+ // mouse word select only on same line mouse cursor is on
+ if (content.getLineAtOffset(wordOffset) == line) {
+ newCaretOffset = wordOffset;
+ }
+ }
+ return newCaretOffset;
+}
+/**
+ * Scrolls one page down so that the last line (truncated or whole)
+ * of the current page becomes the fully visible top line.
+ *
+ * The caret is scrolled the same number of lines so that its location
+ * relative to the top line remains the same. The exception is the end
+ * of the text where a full page scroll is not possible. In this case
+ * the caret is moved after the last character.
+ *
+ *
+ * @param select whether or not to select the page
+ */
+void doPageDown(boolean select, int height) {
+ if (isSingleLine()) return;
+ int oldColumnX = columnX;
+ int oldHScrollOffset = horizontalScrollOffset;
+ if (isFixedLineHeight()) {
+ int lineCount = content.getLineCount();
+ int caretLine = getCaretLine();
+ if (caretLine < lineCount - 1) {
+ int lineHeight = renderer.getLineHeight();
+ int lines = (height == -1 ? clientAreaHeight : height) / lineHeight;
+ int scrollLines = Math.min(lineCount - caretLine - 1, lines);
+ // ensure that scrollLines never gets negative and at least one
+ // line is scrolled. fixes bug 5602.
+ scrollLines = Math.max(1, scrollLines);
+ caretOffset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines));
+ if (select) {
+ doSelection(ST.COLUMN_NEXT);
+ }
+ // scroll one page down or to the bottom
+ int verticalMaximum = lineCount * getVerticalIncrement();
+ int pageSize = clientAreaHeight;
+ int verticalScrollOffset = getVerticalScrollOffset();
+ int scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement();
+ if (scrollOffset + pageSize > verticalMaximum) {
+ scrollOffset = verticalMaximum - pageSize;
+ }
+ if (scrollOffset > verticalScrollOffset) {
+ scrollVertical(scrollOffset - verticalScrollOffset, true);
+ }
+ }
+ } else {
+ int lineCount = content.getLineCount();
+ int caretLine = getCaretLine();
+ int lineIndex, lineHeight;
+ if (height == -1) {
+ lineIndex = getPartialBottomIndex();
+ int topY = getLinePixel(lineIndex);
+ lineHeight = renderer.getLineHeight(lineIndex);
+ height = topY;
+ if (topY + lineHeight <= clientAreaHeight) {
+ height += lineHeight;
+ } else {
+ if (wordWrap) {
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ int y = clientAreaHeight - topY;
+ for (int i = 0; i < layout.getLineCount(); i++) {
+ Rectangle bounds = layout.getLineBounds(i);
+ if (bounds.contains(bounds.x, y)) {
+ height += bounds.y;
+ break;
+ }
+ }
+ renderer.disposeTextLayout(layout);
+ }
+ }
+ } else {
+ lineIndex = getLineIndex(height);
+ int topLineY = getLinePixel(lineIndex);
+ if (wordWrap) {
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ int y = height - topLineY;
+ for (int i = 0; i < layout.getLineCount(); i++) {
+ Rectangle bounds = layout.getLineBounds(i);
+ if (bounds.contains(bounds.x, y)) {
+ height = topLineY + bounds.y + bounds.height;
+ break;
+ }
+ }
+ renderer.disposeTextLayout(layout);
+ } else {
+ height = topLineY + renderer.getLineHeight(lineIndex);
+ }
+ }
+ int caretHeight = height;
+ if (wordWrap) {
+ TextLayout layout = renderer.getTextLayout(caretLine);
+ int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine);
+ lineIndex = getVisualLineIndex(layout, offsetInLine);
+ caretHeight += layout.getLineBounds(lineIndex).y;
+ renderer.disposeTextLayout(layout);
+ }
+ lineIndex = caretLine;
+ lineHeight = renderer.getLineHeight(lineIndex);
+ while (caretHeight - lineHeight >= 0 && lineIndex < lineCount - 1) {
+ caretHeight -= lineHeight;
+ lineHeight = renderer.getLineHeight(++lineIndex);
+ }
+ caretOffset = getOffsetAtPoint(columnX, caretHeight, lineIndex);
+ if (select) doSelection(ST.COLUMN_NEXT);
+ height = getAvailableHeightBellow(height);
+ scrollVertical(height, true);
+ if (height == 0) setCaretLocation();
+ }
+ showCaret();
+ int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+ columnX = oldColumnX + hScrollChange;
+}
+/**
+ * Moves the cursor to the end of the last fully visible line.
+ */
+void doPageEnd() {
+ // go to end of line if in single line mode. fixes 5673
+ if (isSingleLine()) {
+ doLineEnd();
+ } else {
+ int bottomOffset;
+ if (wordWrap) {
+ int lineIndex = getPartialBottomIndex();
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ int y = (clientAreaHeight - bottomMargin) - getLinePixel(lineIndex);
+ int index = layout.getLineCount() - 1;
+ while (index >= 0) {
+ Rectangle bounds = layout.getLineBounds(index);
+ if (y >= bounds.y + bounds.height) break;
+ index--;
+ }
+ if (index == -1 && lineIndex > 0) {
+ bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length();
+ } else {
+ bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1);
+ }
+ renderer.disposeTextLayout(layout);
+ } else {
+ int lineIndex = getBottomIndex();
+ bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length();
+ }
+ if (caretOffset < bottomOffset) {
+ caretOffset = bottomOffset;
+ caretAlignment = OFFSET_LEADING;
+ showCaret();
+ }
+ }
+}
+/**
+ * Moves the cursor to the beginning of the first fully visible line.
+ */
+void doPageStart() {
+ int topOffset;
+ if (wordWrap) {
+ int y, lineIndex;
+ if (topIndexY > 0) {
+ lineIndex = topIndex - 1;
+ y = renderer.getLineHeight(lineIndex) - topIndexY;
+ } else {
+ lineIndex = topIndex;
+ y = -topIndexY;
+ }
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ int index = 0;
+ int lineCount = layout.getLineCount();
+ while (index < lineCount) {
+ Rectangle bounds = layout.getLineBounds(index);
+ if (y <= bounds.y) break;
+ index++;
+ }
+ if (index == lineCount) {
+ topOffset = content.getOffsetAtLine(lineIndex + 1);
+ } else {
+ topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index];
+ }
+ renderer.disposeTextLayout(layout);
+ } else {
+ topOffset = content.getOffsetAtLine(topIndex);
+ }
+ if (caretOffset > topOffset) {
+ caretOffset = topOffset;
+ caretAlignment = OFFSET_LEADING;
+ showCaret();
+ }
+}
+/**
+ * Scrolls one page up so that the first line (truncated or whole)
+ * of the current page becomes the fully visible last line.
+ * The caret is scrolled the same number of lines so that its location
+ * relative to the top line remains the same. The exception is the beginning
+ * of the text where a full page scroll is not possible. In this case the
+ * caret is moved in front of the first character.
+ */
+void doPageUp(boolean select, int height) {
+ if (isSingleLine()) return;
+ int oldHScrollOffset = horizontalScrollOffset;
+ int oldColumnX = columnX;
+ if (isFixedLineHeight()) {
+ int caretLine = getCaretLine();
+ if (caretLine > 0) {
+ int lineHeight = renderer.getLineHeight();
+ int lines = (height == -1 ? clientAreaHeight : height) / lineHeight;
+ int scrollLines = Math.max(1, Math.min(caretLine, lines));
+ caretLine -= scrollLines;
+ caretOffset = getOffsetAtPoint(columnX, getLinePixel(caretLine));
+ if (select) {
+ doSelection(ST.COLUMN_PREVIOUS);
+ }
+ int verticalScrollOffset = getVerticalScrollOffset();
+ int scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement());
+ if (scrollOffset < verticalScrollOffset) {
+ scrollVertical(scrollOffset - verticalScrollOffset, true);
+ }
+ }
+ } else {
+ int caretLine = getCaretLine();
+ int lineHeight, lineIndex;
+ if (height == -1) {
+ if (topIndexY == 0) {
+ height = clientAreaHeight;
+ } else {
+ int y;
+ if (topIndex > 0) {
+ lineIndex = topIndex - 1;
+ lineHeight = renderer.getLineHeight(lineIndex);
+ height = clientAreaHeight - topIndexY;
+ y = lineHeight - topIndexY;
+ } else {
+ lineIndex = topIndex;
+ lineHeight = renderer.getLineHeight(lineIndex);
+ height = clientAreaHeight - (lineHeight + topIndexY);
+ y = -topIndexY;
+ }
+ if (wordWrap) {
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ for (int i = 0; i < layout.getLineCount(); i++) {
+ Rectangle bounds = layout.getLineBounds(i);
+ if (bounds.contains(bounds.x, y)) {
+ height += lineHeight - (bounds.y + bounds.height);
+ break;
+ }
+ }
+ renderer.disposeTextLayout(layout);
+ }
+ }
+ } else {
+ lineIndex = getLineIndex(clientAreaHeight - height);
+ int topLineY = getLinePixel(lineIndex);
+ if (wordWrap) {
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ int y = topLineY;
+ for (int i = 0; i < layout.getLineCount(); i++) {
+ Rectangle bounds = layout.getLineBounds(i);
+ if (bounds.contains(bounds.x, y)) {
+ height = clientAreaHeight - (topLineY + bounds.y);
+ break;
+ }
+ }
+ renderer.disposeTextLayout(layout);
+ } else {
+ height = clientAreaHeight - topLineY;
+ }
+ }
+ int caretHeight = height;
+ if (wordWrap) {
+ TextLayout layout = renderer.getTextLayout(caretLine);
+ int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine);
+ lineIndex = getVisualLineIndex(layout, offsetInLine);
+ caretHeight += layout.getBounds().height - layout.getLineBounds(lineIndex).y;
+ renderer.disposeTextLayout(layout);
+ }
+ lineIndex = caretLine;
+ lineHeight = renderer.getLineHeight(lineIndex);
+ while (caretHeight - lineHeight >= 0 && lineIndex > 0) {
+ caretHeight -= lineHeight;
+ lineHeight = renderer.getLineHeight(--lineIndex);
+ }
+ lineHeight = renderer.getLineHeight(lineIndex);
+ caretOffset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex);
+ if (select) doSelection(ST.COLUMN_PREVIOUS);
+ height = getAvailableHeightAbove(height);
+ scrollVertical(-height, true);
+ if (height == 0) setCaretLocation();
+ }
+ showCaret();
+ int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+ columnX = oldColumnX + hScrollChange;
+}
+/**
+ * Updates the selection to extend to the current caret position.
+ */
+void doSelection(int direction) {
+ int redrawStart = -1;
+ int redrawEnd = -1;
+ if (selectionAnchor == -1) {
+ selectionAnchor = selection.x;
+ }
+ if (direction == ST.COLUMN_PREVIOUS) {
+ if (caretOffset < selection.x) {
+ // grow selection
+ redrawEnd = selection.x;
+ redrawStart = selection.x = caretOffset;
+ // check if selection has reversed direction
+ if (selection.y != selectionAnchor) {
+ redrawEnd = selection.y;
+ selection.y = selectionAnchor;
+ }
+ // test whether selection actually changed. Fixes 1G71EO1
+ } else if (selectionAnchor == selection.x && caretOffset < selection.y) {
+ // caret moved towards selection anchor (left side of selection).
+ // shrink selection
+ redrawEnd = selection.y;
+ redrawStart = selection.y = caretOffset;
+ }
+ } else {
+ if (caretOffset > selection.y) {
+ // grow selection
+ redrawStart = selection.y;
+ redrawEnd = selection.y = caretOffset;
+ // check if selection has reversed direction
+ if (selection.x != selectionAnchor) {
+ redrawStart = selection.x;
+ selection.x = selectionAnchor;
+ }
+ // test whether selection actually changed. Fixes 1G71EO1
+ } else if (selectionAnchor == selection.y && caretOffset > selection.x) {
+ // caret moved towards selection anchor (right side of selection).
+ // shrink selection
+ redrawStart = selection.x;
+ redrawEnd = selection.x = caretOffset;
+ }
+ }
+ if (redrawStart != -1 && redrawEnd != -1) {
+ internalRedrawRange(redrawStart, redrawEnd - redrawStart);
+ sendSelectionEvent();
+ }
+}
+/**
+ * Moves the caret to the next character or to the beginning of the
+ * next line if the cursor is at the end of a line.
+ */
+void doSelectionCursorNext() {
+ int caretLine = getCaretLine();
+ int lineOffset = content.getOffsetAtLine(caretLine);
+ int offsetInLine = caretOffset - lineOffset;
+ if (offsetInLine < content.getLine(caretLine).length()) {
+ TextLayout layout = renderer.getTextLayout(caretLine);
+ offsetInLine = layout.getNextOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
+ int lineStart = layout.getLineOffsets()[layout.getLineIndex(offsetInLine)];
+ renderer.disposeTextLayout(layout);
+ caretOffset = offsetInLine + lineOffset;
+ caretAlignment = offsetInLine == lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING;
+ showCaret();
+ } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) {
+ caretLine++;
+ caretOffset = content.getOffsetAtLine(caretLine);
+ caretAlignment = PREVIOUS_OFFSET_TRAILING;
+ showCaret();
+ }
+}
+/**
+ * Moves the caret to the previous character or to the end of the previous
+ * line if the cursor is at the beginning of a line.
+ */
+void doSelectionCursorPrevious() {
+ int caretLine = getCaretLine();
+ int lineOffset = content.getOffsetAtLine(caretLine);
+ int offsetInLine = caretOffset - lineOffset;
+ caretAlignment = OFFSET_LEADING;
+ if (offsetInLine > 0) {
+ caretOffset = getClusterPrevious(caretOffset, caretLine);
+ showCaret();
+ } else if (caretLine > 0) {
+ caretLine--;
+ lineOffset = content.getOffsetAtLine(caretLine);
+ caretOffset = lineOffset + content.getLine(caretLine).length();
+ showCaret();
+ }
+}
+/**
+ * Moves the caret one line down and to the same character offset relative
+ * to the beginning of the line. Moves the caret to the end of the new line
+ * if the new line is shorter than the character offset.
+ * Moves the caret to the end of the text if the caret already is on the
+ * last line.
+ * Adjusts the selection according to the caret change. This can either add
+ * to or subtract from the old selection, depending on the previous selection
+ * direction.
+ */
+void doSelectionLineDown() {
+ int oldColumnX = columnX = getPointAtOffset(caretOffset).x;
+ doLineDown(true);
+ columnX = oldColumnX;
+}
+/**
+ * Moves the caret one line up and to the same character offset relative
+ * to the beginning of the line. Moves the caret to the end of the new line
+ * if the new line is shorter than the character offset.
+ * Moves the caret to the beginning of the document if it is already on the
+ * first line.
+ * Adjusts the selection according to the caret change. This can either add
+ * to or subtract from the old selection, depending on the previous selection
+ * direction.
+ */
+void doSelectionLineUp() {
+ int oldColumnX = columnX = getPointAtOffset(caretOffset).x;
+ doLineUp(true);
+ columnX = oldColumnX;
+}
+/**
+ * Scrolls one page down so that the last line (truncated or whole)
+ * of the current page becomes the fully visible top line.
+ *
+ * The caret is scrolled the same number of lines so that its location
+ * relative to the top line remains the same. The exception is the end
+ * of the text where a full page scroll is not possible. In this case
+ * the caret is moved after the last character.
+ *
+ * Adjusts the selection according to the caret change. This can either add
+ * to or subtract from the old selection, depending on the previous selection
+ * direction.
+ *
+ */
+void doSelectionPageDown(int pixels) {
+ int oldColumnX = columnX = getPointAtOffset(caretOffset).x;
+ doPageDown(true, pixels);
+ columnX = oldColumnX;
+}
+/**
+ * Scrolls one page up so that the first line (truncated or whole)
+ * of the current page becomes the fully visible last line.
+ *
+ * The caret is scrolled the same number of lines so that its location
+ * relative to the top line remains the same. The exception is the beginning
+ * of the text where a full page scroll is not possible. In this case the
+ * caret is moved in front of the first character.
+ *
+ * Adjusts the selection according to the caret change. This can either add
+ * to or subtract from the old selection, depending on the previous selection
+ * direction.
+ *
+ */
+void doSelectionPageUp(int pixels) {
+ int oldColumnX = columnX = getPointAtOffset(caretOffset).x;
+ doPageUp(true, pixels);
+ columnX = oldColumnX;
+}
+/**
+ * Moves the caret to the end of the next word .
+ */
+void doSelectionWordNext() {
+ int newCaretOffset = getWordEnd(caretOffset);
+ // Force symmetrical movement for word next and previous. Fixes 14536
+ caretAlignment = OFFSET_LEADING;
+ // don't change caret position if in single line mode and the cursor
+ // would be on a different line. fixes 5673
+ if (!isSingleLine() ||
+ content.getLineAtOffset(caretOffset) == content.getLineAtOffset(newCaretOffset)) {
+ caretOffset = newCaretOffset;
+ showCaret();
+ }
+}
+/**
+ * Moves the caret to the start of the previous word.
+ */
+void doSelectionWordPrevious() {
+ caretAlignment = OFFSET_LEADING;
+ caretOffset = getWordStart(caretOffset);
+ int caretLine = content.getLineAtOffset(caretOffset);
+ // word previous always comes from bottom line. when
+ // wrapping lines, stay on bottom line when on line boundary
+ if (wordWrap && caretLine < content.getLineCount() - 1 &&
+ caretOffset == content.getOffsetAtLine(caretLine + 1)) {
+ caretLine++;
+ }
+ showCaret();
+}
+/**
+ * Moves the caret one character to the left. Do not go to the previous line.
+ * When in a bidi locale and at a R2L character the caret is moved to the
+ * beginning of the R2L segment (visually right) and then one character to the
+ * left (visually left because it's now in a L2R segment).
+ */
+void doVisualPrevious() {
+ caretOffset = getClusterPrevious(caretOffset, getCaretLine());
+ showCaret();
+}
+/**
+ * Moves the caret one character to the right. Do not go to the next line.
+ * When in a bidi locale and at a R2L character the caret is moved to the
+ * end of the R2L segment (visually left) and then one character to the
+ * right (visually right because it's now in a L2R segment).
+ */
+void doVisualNext() {
+ caretOffset = getClusterNext(caretOffset, getCaretLine());
+ showCaret();
+}
+/**
+ * Moves the caret to the end of the next word.
+ * If a selection exists, move the caret to the end of the selection
+ * and remove the selection.
+ */
+void doWordNext() {
+ if (selection.y - selection.x > 0) {
+ caretOffset = selection.y;
+ showCaret();
+ } else {
+ doSelectionWordNext();
+ }
+}
+/**
+ * Moves the caret to the start of the previous word.
+ * If a selection exists, move the caret to the start of the selection
+ * and remove the selection.
+ */
+void doWordPrevious() {
+ if (selection.y - selection.x > 0) {
+ caretOffset = selection.x;
+ showCaret();
+ } else {
+ doSelectionWordPrevious();
+ }
+}
+/**
+ * Ends the autoscroll process.
+ */
+void endAutoScroll() {
+ autoScrollDirection = SWT.NULL;
+}
+public Color getBackground() {
+ checkWidget();
+ if (background == null) {
+ return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+ }
+ return background;
+}
+/**
+ * Returns the baseline, in pixels.
+ *
+ * Note: this API should not be used if a StyleRange attribute causes lines to
+ * have different heights (i.e. different fonts, rise, etc).
+ *
+ * @return baseline the baseline
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @since 3.0
+ *
+ * @see #getBaseline(int)
+ */
+public int getBaseline() {
+ checkWidget();
+ return renderer.getBaseline();
+}
+/**
+ * Returns the baseline at the given offset, in pixels.
+ *
+ * @param offset the offset
+ *
+ * @return baseline the baseline
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
+ *
+ *
+ * @since 3.2
+ */
+public int getBaseline(int offset) {
+ checkWidget();
+ if (!(0 <= offset && offset <= content.getCharCount())) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ if (isFixedLineHeight()) {
+ return renderer.getBaseline();
+ }
+ int lineIndex = content.getLineAtOffset(offset);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length()));
+ FontMetrics metrics = layout.getLineMetrics(lineInParagraph);
+ renderer.disposeTextLayout(layout);
+ return metrics.getAscent() + metrics.getLeading();
+}
+/**
+ * Gets the BIDI coloring mode. When true the BIDI text display
+ * algorithm is applied to segments of text that are the same
+ * color.
+ *
+ * @return the current coloring mode
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @deprecated use BidiSegmentListener instead.
+ */
+public boolean getBidiColoring() {
+ checkWidget();
+ return bidiColoring;
+}
+/**
+ * Returns the index of the last fully visible line.
+ *
+ * @return index of the last fully visible line.
+ */
+int getBottomIndex() {
+ int bottomIndex;
+ if (isFixedLineHeight()) {
+ int lineCount = 1;
+ int lineHeight = renderer.getLineHeight();
+ if (lineHeight != 0) {
+ // calculate the number of lines that are fully visible
+ int partialTopLineHeight = topIndex * lineHeight - getVerticalScrollOffset();
+ lineCount = (clientAreaHeight - partialTopLineHeight) / lineHeight;
+ }
+ bottomIndex = Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1));
+ } else {
+ int clientAreaHeight = this.clientAreaHeight - bottomMargin;
+ bottomIndex = getLineIndex(clientAreaHeight);
+ if (bottomIndex > 0) {
+ int linePixel = getLinePixel(bottomIndex);
+ int lineHeight = renderer.getLineHeight(bottomIndex);
+ if (linePixel + lineHeight > clientAreaHeight) {
+ if (getLinePixel(bottomIndex - 1) >= topMargin) {
+ bottomIndex--;
+ }
+ }
+ }
+ }
+ return bottomIndex;
+}
+Rectangle getBoundsAtOffset(int offset) {
+ int lineIndex = content.getLineAtOffset(offset);
+ String line = content.getLine(lineIndex);
+ Rectangle bounds;
+ if (line.length() != 0) {
+ int offsetInLine = offset - content.getOffsetAtLine(lineIndex);
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ bounds = layout.getBounds(offsetInLine, offsetInLine);
+ renderer.disposeTextLayout(layout);
+ } else {
+ bounds = new Rectangle (0, 0, 0, renderer.getLineHeight());
+ }
+ bounds.x += leftMargin - horizontalScrollOffset;
+ bounds.y += getLinePixel(lineIndex);
+ return bounds;
+}
+
+/**
+ * Returns the caret position relative to the start of the text.
+ *
+ * @return the caret position relative to the start of the text.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getCaretOffset() {
+ checkWidget();
+ return caretOffset;
+}
+/**
+ * Returns the caret width.
+ *
+ * @return the caret width, 0 if caret is null.
+ */
+int getCaretWidth() {
+ Caret caret = getCaret();
+ if (caret == null) return 0;
+ return caret.getSize().x;
+}
+Object getClipboardContent(int clipboardType) {
+ TextTransfer plainTextTransfer = TextTransfer.getInstance();
+ return clipboard.getContents(plainTextTransfer, clipboardType);
+}
+int getClusterNext(int offset, int lineIndex) {
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ offset -= lineOffset;
+ offset = layout.getNextOffset(offset, SWT.MOVEMENT_CLUSTER);
+ offset += lineOffset;
+ renderer.disposeTextLayout(layout);
+ return offset;
+}
+int getClusterPrevious(int offset, int lineIndex) {
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ offset -= lineOffset;
+ offset = layout.getPreviousOffset(offset, SWT.MOVEMENT_CLUSTER);
+ offset += lineOffset;
+ renderer.disposeTextLayout(layout);
+ return offset;
+}
+/**
+ * Returns the content implementation that is used for text storage
+ * or null if no user defined content implementation has been set.
+ *
+ * @return content implementation that is used for text storage or null
+ * if no user defined content implementation has been set.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public StyledTextContent getContent() {
+ checkWidget();
+ return content;
+}
+/**
+ * Returns whether the widget implements double click mouse behavior.
+ *
+ * @return true if double clicking a word selects the word, false if double clicks
+ * have the same effect as regular mouse clicks
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getDoubleClickEnabled() {
+ checkWidget();
+ return doubleClickEnabled;
+}
+/**
+ * Returns whether the widget content can be edited.
+ *
+ * @return true if content can be edited, false otherwise
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getEditable() {
+ checkWidget();
+ return editable;
+}
+public Color getForeground() {
+ checkWidget();
+ if (foreground == null) {
+ return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+ }
+ return foreground;
+}
+/**
+ * Returns the horizontal scroll increment.
+ *
+ * @return horizontal scroll increment.
+ */
+int getHorizontalIncrement() {
+ GC gc = new GC(this);
+ int increment = gc.getFontMetrics().getAverageCharWidth();
+ gc.dispose();
+ return increment;
+}
+/**
+ * Returns the horizontal scroll offset relative to the start of the line.
+ *
+ * @return horizontal scroll offset relative to the start of the line,
+ * measured in character increments starting at 0, if > 0 the content is scrolled
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getHorizontalIndex() {
+ checkWidget();
+ return horizontalScrollOffset / getHorizontalIncrement();
+}
+/**
+ * Returns the horizontal scroll offset relative to the start of the line.
+ *
+ * @return the horizontal scroll offset relative to the start of the line,
+ * measured in pixel starting at 0, if > 0 the content is scrolled.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getHorizontalPixel() {
+ checkWidget();
+ return horizontalScrollOffset;
+}
+/**
+ * Returns the line indentation of the widget.
+ *
+ * @return the line indentation
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getLineJustify(int)
+ *
+ * @since 3.2
+ */
+public boolean getJustify() {
+ checkWidget();
+ return justify;
+}
+/**
+ * Returns the action assigned to the key.
+ * Returns SWT.NULL if there is no action associated with the key.
+ *
+ * @param key a key code defined in SWT.java or a character.
+ * Optionally ORd with a state mask. Preferred state masks are one or more of
+ * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform
+ * differences. However, there may be cases where using the specific state masks
+ * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
+ * @return one of the predefined actions defined in ST.java or SWT.NULL
+ * if there is no action associated with the key.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getKeyBinding(int key) {
+ checkWidget();
+ Integer action = (Integer) keyActionMap.get(new Integer(key));
+ return action == null ? SWT.NULL : action.intValue();
+}
+/**
+ * Gets the number of characters.
+ *
+ * @return number of characters in the widget
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getCharCount() {
+ checkWidget();
+ return content.getCharCount();
+}
+/**
+ * Returns the alignment of the line at the given index.
+ *
+ * @param index the index of the line
+ *
+ * @return the line alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when the index is invalid
+ *
+ *
+ * @see #getAlignment()
+ *
+ * @since 3.2
+ */
+public int getLineAlignment(int index) {
+ checkWidget();
+ if (index < 0 || index > content.getLineCount()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ return renderer.getLineAlignment(index, alignment);
+}
+/**
+ * Returns the line at the specified offset in the text
+ * where 0 <= offset <= getCharCount() so that getLineAtOffset(getCharCount())
+ * returns the line of the insert location.
+ *
+ * @param offset offset relative to the start of the content.
+ * 0 <= offset <= getCharCount()
+ * @return line at the specified offset in the text
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
+ *
+ */
+public int getLineAtOffset(int offset) {
+ checkWidget();
+ if (offset < 0 || offset > getCharCount()) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ return content.getLineAtOffset(offset);
+}
+/**
+ * Returns the background color of the line at the given index.
+ * Returns null if a LineBackgroundListener has been set or if no background
+ * color has been specified for the line. Should not be called if a
+ * LineBackgroundListener has been set since the listener maintains the
+ * line background colors.
+ *
+ * @param index the index of the line
+ * @return the background color of the line at the given index.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when the index is invalid
+ *
+ */
+public Color getLineBackground(int index) {
+ checkWidget();
+ if (index < 0 || index > content.getLineCount()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ return isListening(LineGetBackground) ? null : renderer.getLineBackground(index, null);
+}
+/**
+ * Returns the bullet of the line at the given index.
+ *
+ * @param index the index of the line
+ *
+ * @return the line bullet
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when the index is invalid
+ *
+ *
+ * @since 3.2
+ */
+public Bullet getLineBullet(int index) {
+ checkWidget();
+ if (index < 0 || index > content.getLineCount()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ return isListening(LineGetStyle) ? null : renderer.getLineBullet(index, null);
+}
+/**
+ * Returns the line background data for the given line or null if
+ * there is none.
+ *
+ * @param lineOffset offset of the line start relative to the start
+ * of the content.
+ * @param line line to get line background data for
+ * @return line background data for the given line.
+ */
+StyledTextEvent getLineBackgroundData(int lineOffset, String line) {
+ return sendLineEvent(LineGetBackground, lineOffset, line);
+}
+/**
+ * Gets the number of text lines.
+ *
+ * @return the number of lines in the widget
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getLineCount() {
+ checkWidget();
+ return content.getLineCount();
+}
+/**
+ * Returns the number of lines that can be completely displayed in the
+ * widget client area.
+ *
+ * @return number of lines that can be completely displayed in the widget
+ * client area.
+ */
+int getLineCountWhole() {
+ if (isFixedLineHeight()) {
+ int lineHeight = renderer.getLineHeight();
+ return lineHeight != 0 ? clientAreaHeight / lineHeight : 1;
+ }
+ return getBottomIndex() - topIndex + 1;
+}
+/**
+ * Returns the line delimiter used for entering new lines by key down
+ * or paste operation.
+ *
+ * @return line delimiter used for entering new lines by key down
+ * or paste operation.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * Note: this API should not be used if a StyleRange attribute causes lines to
+ * have different heights (i.e. different fonts, rise, etc).
+ *
+ *
+ * @return line height in pixel.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @see #getLineHeight(int)
+ */
+public int getLineHeight() {
+ checkWidget();
+ return renderer.getLineHeight();
+}
+/**
+ * Returns the line height at the given offset.
+ *
+ * @param offset the offset
+ *
+ * @return line height in pixels
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
+ *
+ *
+ * @since 3.2
+ */
+public int getLineHeight(int offset) {
+ checkWidget();
+ if (!(0 <= offset && offset <= content.getCharCount())) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ if (isFixedLineHeight()) {
+ return renderer.getLineHeight();
+ }
+ int lineIndex = content.getLineAtOffset(offset);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length()));
+ int height = layout.getLineBounds(lineInParagraph).height;
+ renderer.disposeTextLayout(layout);
+ return height;
+}
+/**
+ * Returns the indentation of the line at the given index.
+ *
+ * @param index the index of the line
+ *
+ * @return the line indentation
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when the index is invalid
+ *
+ *
+ * @see #getIndent()
+ *
+ * @since 3.2
+ */
+public int getLineIndent(int index) {
+ checkWidget();
+ if (index < 0 || index > content.getLineCount()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ return isListening(LineGetStyle) ? 0 : renderer.getLineIndent(index, indent);
+}
+/**
+ * Returns whether the line at the given index is justified.
+ *
+ * @param index the index of the line
+ *
+ * @return whether the line is justified
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when the index is invalid
+ *
+ *
+ * @see #getJustify()
+ *
+ * @since 3.2
+ */
+public boolean getLineJustify(int index) {
+ checkWidget();
+ if (index < 0 || index > content.getLineCount()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ return isListening(LineGetStyle) ? false : renderer.getLineJustify(index, justify);
+}
+/**
+ * Returns the line spacing of the widget.
+ *
+ * @return the line spacing
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public int getLineSpacing() {
+ checkWidget();
+ return lineSpacing;
+}
+/**
+ * Returns the line style data for the given line or null if there is
+ * none.
+ *
+ * If there is a LineStyleListener but it does not set any styles,
+ * the StyledTextEvent.styles field will be initialized to an empty
+ * array.
+ *
+ *
+ * @param lineOffset offset of the line start relative to the start of
+ * the content.
+ * @param line line to get line styles for
+ * @return line style data for the given line. Styles may start before
+ * line start and end after line end
+ */
+StyledTextEvent getLineStyleData(int lineOffset, String line) {
+ return sendLineEvent(LineGetStyle, lineOffset, line);
+}
+/**
+ * Returns the top pixel, relative to the client area, of a given line.
+ * Clamps out of ranges index.
+ *
+ * @param lineIndex the line index, the max value is lineCount. If
+ * lineIndex == lineCount it returns the bottom pixel of the last line.
+ * It means this function can be used to retrieve the bottom pixel of any line.
+ *
+ * @since 3.2
+ */
+public int getLinePixel(int lineIndex) {
+ checkWidget();
+ int lineCount = content.getLineCount();
+ lineIndex = Math.max(0, Math.min(lineCount, lineIndex));
+ if (isFixedLineHeight()) {
+ int lineHeight = renderer.getLineHeight();
+ return lineIndex * lineHeight - getVerticalScrollOffset() + topMargin;
+ }
+ if (lineIndex == topIndex) return topIndexY + topMargin;
+ int height = topIndexY;
+ if (lineIndex > topIndex) {
+ for (int i = topIndex; i < lineIndex; i++) {
+ height += renderer.getLineHeight(i);
+ }
+ } else {
+ for (int i = topIndex - 1; i >= lineIndex; i--) {
+ height -= renderer.getLineHeight(i);
+ }
+ }
+ return height + topMargin;
+}
+/**
+ * Returns the line index for a y, relative to the client area.
+ * The line index returned is always in the range 0..lineCount - 1.
+ *
+ * @since 3.2
+ */
+public int getLineIndex(int y) {
+ checkWidget();
+ y -= topMargin;
+ if (isFixedLineHeight()) {
+ int lineHeight = renderer.getLineHeight();
+ int lineIndex = (y + getVerticalScrollOffset()) / lineHeight;
+ int lineCount = content.getLineCount();
+ lineIndex = Math.max(0, Math.min(lineCount - 1, lineIndex));
+ return lineIndex;
+ }
+ if (y == topIndexY) return topIndex;
+ int line = topIndex;
+ if (y < topIndexY) {
+ while (y < topIndexY && line > 0) {
+ y += renderer.getLineHeight(--line);
+ }
+ } else {
+ int lineCount = content.getLineCount();
+ int lineHeight = renderer.getLineHeight(line);
+ while (y - lineHeight >= topIndexY && line < lineCount - 1) {
+ y -= lineHeight;
+ lineHeight = renderer.getLineHeight(++line);
+ }
+ }
+ return line;
+}
+/**
+ * Returns the x, y location of the upper left corner of the character
+ * bounding box at the specified offset in the text. The point is
+ * relative to the upper left corner of the widget client area.
+ *
+ * @param offset offset relative to the start of the content.
+ * 0 <= offset <= getCharCount()
+ * @return x, y location of the upper left corner of the character
+ * bounding box at the specified offset in the text.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
+ *
+ */
+public Point getLocationAtOffset(int offset) {
+ checkWidget();
+ if (offset < 0 || offset > getCharCount()) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ return getPointAtOffset(offset);
+}
+/**
+ * Returns the character offset of the first character of the given line.
+ *
+ * @param lineIndex index of the line, 0 based relative to the first
+ * line in the content. 0 <= lineIndex < getLineCount(), except
+ * lineIndex may always be 0
+ * @return offset offset of the first character of the line, relative to
+ * the beginning of the document. The first character of the document is
+ * at offset 0.
+ * When there are not any lines, getOffsetAtLine(0) is a valid call that
+ * answers 0.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())
+ *
+ * @since 2.0
+ */
+public int getOffsetAtLine(int lineIndex) {
+ checkWidget();
+ if (lineIndex < 0 ||
+ (lineIndex > 0 && lineIndex >= content.getLineCount())) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ return content.getOffsetAtLine(lineIndex);
+}
+/**
+ * Returns the offset of the character at the given location relative
+ * to the first character in the document.
+ *
+ * The return value reflects the character offset that the caret will
+ * be placed at if a mouse click occurred at the specified location.
+ * If the x coordinate of the location is beyond the center of a character
+ * the returned offset will be behind the character.
+ *
+ *
+ * @param point the origin of character bounding box relative to
+ * the origin of the widget client area.
+ * @return offset of the character at the given location relative
+ * to the first character in the document.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when point is null
+ *
ERROR_INVALID_ARGUMENT when there is no character at the specified location
+ *
+ */
+public int getOffsetAtLocation(Point point) {
+ checkWidget();
+ if (point == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ // is y above first line or is x before first column?
+ if (point.y + getVerticalScrollOffset() < 0 || point.x + horizontalScrollOffset < 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int bottomIndex = getLineIndex(clientAreaHeight);
+ int height = getLinePixel(bottomIndex) + renderer.getLineHeight(bottomIndex);
+ if (point.y > height) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int lineIndex = getLineIndex(point.y);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ int[] trailing = new int[1];
+ int x = point.x + horizontalScrollOffset - leftMargin ;
+ int y = point.y - getLinePixel(lineIndex);
+ int offsetInLine = layout.getOffset(x, y, trailing);
+ String line = content.getLine(lineIndex);
+ if (offsetInLine != line.length() - 1) {
+ offsetInLine = Math.min(line.length(), offsetInLine + trailing[0]);
+ }
+ Rectangle rect = layout.getLineBounds(layout.getLineIndex(offsetInLine));
+ renderer.disposeTextLayout(layout);
+ if (x > rect.x + rect.width) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ return lineOffset + offsetInLine;
+}
+int getOffsetAtPoint(int x, int y) {
+ int lineIndex = getLineIndex(y);
+ y -= getLinePixel(lineIndex);
+ return getOffsetAtPoint(x, y, lineIndex);
+}
+/**
+ * Returns the offset at the specified x location in the specified line.
+ *
+ * @param x x location of the mouse location
+ * @param line line the mouse location is in
+ * @return the offset at the specified x location in the specified line,
+ * relative to the beginning of the document
+ */
+int getOffsetAtPoint(int x, int y, int lineIndex) {
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ x += horizontalScrollOffset - leftMargin;
+ int[] trailing = new int[1];
+ int offsetInLine = layout.getOffset(x, y, trailing);
+ caretAlignment = OFFSET_LEADING;
+ if (trailing[0] != 0) {
+ int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]);
+ //TODO handle bidi text
+ int lineStart = layout.getLineOffsets()[lineInParagraph];
+ if (offsetInLine + trailing[0] == lineStart) {
+ offsetInLine += trailing[0];
+ caretAlignment = PREVIOUS_OFFSET_TRAILING;
+ } else {
+ String line = content.getLine(lineIndex);
+ int level;
+ int offset = offsetInLine;
+ while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--;
+ if (offset == 0 && Character.isDigit(line.charAt(offset))) {
+ level = isMirrored() ? 1 : 0;
+ } else {
+ level = layout.getLevel(offset) & 0x1;
+ }
+ offsetInLine += trailing[0];
+ int trailingLevel = layout.getLevel(offsetInLine) & 0x1;
+ if ((level ^ trailingLevel) != 0) {
+ caretAlignment = PREVIOUS_OFFSET_TRAILING;
+ } else {
+ caretAlignment = OFFSET_LEADING;
+ }
+ }
+ }
+ renderer.disposeTextLayout(layout);
+ return offsetInLine + content.getOffsetAtLine(lineIndex);
+}
+/**
+ * Returns the orientation of the receiver.
+ *
+ * @return the orientation style
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.1.2
+ */
+public int getOrientation () {
+ checkWidget();
+ return isMirrored() ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
+}
+/**
+ * Returns the index of the last partially visible line.
+ *
+ * @return index of the last partially visible line.
+ */
+int getPartialBottomIndex() {
+ if (isFixedLineHeight()) {
+ int lineHeight = renderer.getLineHeight();
+ int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight);
+ return Math.min(content.getLineCount(), topIndex + partialLineCount) - 1;
+ }
+ return getLineIndex(clientAreaHeight - bottomMargin);
+}
+/**
+ * Returns the index of the first partially visible line.
+ *
+ * @return index of the first partially visible line.
+ */
+int getPartialTopIndex() {
+ if (isFixedLineHeight()) {
+ int lineHeight = renderer.getLineHeight();
+ return getVerticalScrollOffset() / lineHeight;
+ }
+ return topIndexY <= 0 ? topIndex : topIndex - 1;
+}
+/**
+ * Returns the content in the specified range using the platform line
+ * delimiter to separate lines.
+ *
+ * @param writer the TextWriter to write line text into
+ * @return the content in the specified range using the platform line
+ * delimiter to separate lines as written by the specified TextWriter.
+ */
+String getPlatformDelimitedText(TextWriter writer) {
+ int end = writer.getStart() + writer.getCharCount();
+ int startLine = content.getLineAtOffset(writer.getStart());
+ int endLine = content.getLineAtOffset(end);
+ String endLineText = content.getLine(endLine);
+ int endLineOffset = content.getOffsetAtLine(endLine);
+
+ for (int i = startLine; i <= endLine; i++) {
+ writer.writeLine(content.getLine(i), content.getOffsetAtLine(i));
+ if (i < endLine) {
+ writer.writeLineDelimiter(PlatformLineDelimiter);
+ }
+ }
+ if (end > endLineOffset + endLineText.length()) {
+ writer.writeLineDelimiter(PlatformLineDelimiter);
+ }
+ writer.close();
+ return writer.toString();
+}
+/**
+ * Returns all the ranges of text that have an associated StyleRange.
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ * The ranges array contains start and length pairs. Each pair refers to
+ * the corresponding style in the styles array. For example, the pair
+ * that starts at ranges[n] with length ranges[n+1] uses the style
+ * at styles[n/2] returned by getStyleRanges(int, int, boolean).
+ *
+ *
+ * @return the ranges or an empty array if a LineStyleListener has been set.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ *
+ * @see #getStyleRanges(boolean)
+ */
+public int[] getRanges() {
+ checkWidget();
+ if (!isListening(LineGetStyle)) {
+ int[] ranges = renderer.getRanges(0, content.getCharCount());
+ if (ranges != null) return ranges;
+ }
+ return new int[0];
+}
+/**
+ * Returns the ranges of text that have an associated StyleRange.
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ * The ranges array contains start and length pairs. Each pair refers to
+ * the corresponding style in the styles array. For example, the pair
+ * that starts at ranges[n] with length ranges[n+1] uses the style
+ * at styles[n/2] returned by getStyleRanges(int, int, boolean).
+ *
+ *
+ * @param start the start offset of the style ranges to return
+ * @param length the number of style ranges to return
+ *
+ * @return the ranges or an empty array if a LineStyleListener has been set.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE if start or length are outside the widget content
+ *
+ *
+ * @since 3.2
+ *
+ * @see #getStyleRanges(int, int, boolean)
+ */
+public int[] getRanges(int start, int length) {
+ checkWidget();
+ int contentLength = getCharCount();
+ int end = start + length;
+ if (start > end || start < 0 || end > contentLength) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ if (!isListening(LineGetStyle)) {
+ int[] ranges = renderer.getRanges(start, length);
+ if (ranges != null) return ranges;
+ }
+ return new int[0];
+}
+/**
+ * Returns the selection.
+ *
+ * Text selections are specified in terms of caret positions. In a text
+ * widget that contains N characters, there are N+1 caret positions,
+ * ranging from 0..N
+ *
+ *
+ * @return start and end of the selection, x is the offset of the first
+ * selected character, y is the offset after the last selected character.
+ * The selection values returned are visual (i.e., x will always always be
+ * <= y). To determine if a selection is right-to-left (RtoL) vs. left-to-right
+ * (LtoR), compare the caretOffset to the start and end of the selection
+ * (e.g., caretOffset == start of selection implies that the selection is RtoL).
+ * @see #getSelectionRange
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getSelection() {
+ checkWidget();
+ return new Point(selection.x, selection.y);
+}
+/**
+ * Returns the selection.
+ *
+ * @return start and length of the selection, x is the offset of the
+ * first selected character, relative to the first character of the
+ * widget content. y is the length of the selection.
+ * The selection values returned are visual (i.e., length will always always be
+ * positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right
+ * (LtoR), compare the caretOffset to the start and end of the selection
+ * (e.g., caretOffset == start of selection implies that the selection is RtoL).
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getSelectionRange() {
+ checkWidget();
+ return new Point(selection.x, selection.y - selection.x);
+}
+/**
+ * Returns the receiver's selection background color.
+ *
+ * @return the selection background color
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @since 2.1
+ */
+public Color getSelectionBackground() {
+ checkWidget();
+ if (selectionBackground == null) {
+ return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
+ }
+ return selectionBackground;
+}
+/**
+ * Gets the number of selected characters.
+ *
+ * @return the number of selected characters.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelectionCount() {
+ checkWidget();
+ return getSelectionRange().y;
+}
+/**
+ * Returns the receiver's selection foreground color.
+ *
+ * @return the selection foreground color
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @since 2.1
+ */
+public Color getSelectionForeground() {
+ checkWidget();
+ if (selectionForeground == null) {
+ return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
+ }
+ return selectionForeground;
+}
+/**
+ * Returns the selected text.
+ *
+ * @return selected text, or an empty String if there is no selection.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getSelectionText() {
+ checkWidget();
+ return content.getTextRange(selection.x, selection.y - selection.x);
+}
+public int getStyle() {
+ int style = super.getStyle();
+ style &= ~(SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT | SWT.MIRRORED);
+ if (isMirrored()) {
+ style |= SWT.RIGHT_TO_LEFT | SWT.MIRRORED;
+ } else {
+ style |= SWT.LEFT_TO_RIGHT;
+ }
+ return style;
+}
+
+/**
+ * Returns the text segments that should be treated as if they
+ * had a different direction than the surrounding text.
+ *
+ * @param lineOffset offset of the first character in the line.
+ * 0 based from the beginning of the document.
+ * @param line text of the line to specify bidi segments for
+ * @return text segments that should be treated as if they had a
+ * different direction than the surrounding text. Only the start
+ * index of a segment is specified, relative to the start of the
+ * line. Always starts with 0 and ends with the line length.
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the segment indices returned
+ * by the listener do not start with 0, are not in ascending order,
+ * exceed the line length or have duplicates
+ *
+ */
+int [] getBidiSegments(int lineOffset, String line) {
+ if (!isBidi()) return null;
+ if (!isListening(LineGetSegments)) {
+ return getBidiSegmentsCompatibility(line, lineOffset);
+ }
+ StyledTextEvent event = sendLineEvent(LineGetSegments, lineOffset, line);
+ int lineLength = line.length();
+ int[] segments;
+ if (event == null || event.segments == null || event.segments.length == 0) {
+ segments = new int[] {0, lineLength};
+ } else {
+ int segmentCount = event.segments.length;
+
+ // test segment index consistency
+ if (event.segments[0] != 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ for (int i = 1; i < segmentCount; i++) {
+ if (event.segments[i] <= event.segments[i - 1] || event.segments[i] > lineLength) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ }
+ // ensure that last segment index is line end offset
+ if (event.segments[segmentCount - 1] != lineLength) {
+ segments = new int[segmentCount + 1];
+ System.arraycopy(event.segments, 0, segments, 0, segmentCount);
+ segments[segmentCount] = lineLength;
+ } else {
+ segments = event.segments;
+ }
+ }
+ return segments;
+}
+/**
+ * @see #getBidiSegments
+ * Supports deprecated setBidiColoring API. Remove when API is removed.
+ */
+int [] getBidiSegmentsCompatibility(String line, int lineOffset) {
+ int lineLength = line.length();
+ if (!bidiColoring) {
+ return new int[] {0, lineLength};
+ }
+ StyleRange [] styles = null;
+ StyledTextEvent event = getLineStyleData(lineOffset, line);
+ if (event != null) {
+ styles = event.styles;
+ } else {
+ styles = renderer.getStyleRanges(lineOffset, lineLength, true);
+ }
+ if (styles == null || styles.length == 0) {
+ return new int[] {0, lineLength};
+ }
+ int k=0, count = 1;
+ while (k < styles.length && styles[k].start == 0 && styles[k].length == lineLength) {
+ k++;
+ }
+ int[] offsets = new int[(styles.length - k) * 2 + 2];
+ for (int i = k; i < styles.length; i++) {
+ StyleRange style = styles[i];
+ int styleLineStart = Math.max(style.start - lineOffset, 0);
+ int styleLineEnd = Math.max(style.start + style.length - lineOffset, styleLineStart);
+ styleLineEnd = Math.min (styleLineEnd, line.length ());
+ if (i > 0 && count > 1 &&
+ ((styleLineStart >= offsets[count-2] && styleLineStart <= offsets[count-1]) ||
+ (styleLineEnd >= offsets[count-2] && styleLineEnd <= offsets[count-1])) &&
+ style.similarTo(styles[i-1])) {
+ offsets[count-2] = Math.min(offsets[count-2], styleLineStart);
+ offsets[count-1] = Math.max(offsets[count-1], styleLineEnd);
+ } else {
+ if (styleLineStart > offsets[count - 1]) {
+ offsets[count] = styleLineStart;
+ count++;
+ }
+ offsets[count] = styleLineEnd;
+ count++;
+ }
+ }
+ // add offset for last non-colored segment in line, if any
+ if (lineLength > offsets[count-1]) {
+ offsets [count] = lineLength;
+ count++;
+ }
+ if (count == offsets.length) {
+ return offsets;
+ }
+ int [] result = new int [count];
+ System.arraycopy (offsets, 0, result, 0, count);
+ return result;
+}
+/**
+ * Returns the style range at the given offset.
+ *
+ * Returns null if a LineStyleListener has been set or if a style is not set
+ * for the offset.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ *
+ * @param offset the offset to return the style for.
+ * 0 <= offset < getCharCount() must be true.
+ * @return a StyleRange with start == offset and length == 1, indicating
+ * the style at the given offset. null if a LineStyleListener has been set
+ * or if a style is not set for the given offset.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ * Note: Because a StyleRange includes the start and length, the
+ * same instance cannot occur multiple times in the array of styles.
+ * If the same style attributes, such as font and color, occur in
+ * multiple StyleRanges, getStyleRanges(boolean)
+ * can be used to get the styles without the ranges.
+ *
+ *
+ * @return the styles or an empty array if a LineStyleListener has been set.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ * Note: When includeRanges is true, the start and length
+ * fields of each StyleRange will be valid, however the StyleRange
+ * objects may need to be cloned. When includeRanges is
+ * false, getRanges(int, int) can be used to get the
+ * associated ranges.
+ *
+ *
+ * @param includeRanges whether the start and length field of the StyleRanges should be set.
+ *
+ * @return the styles or an empty array if a LineStyleListener has been set.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ *
+ * @see #getRanges(int, int)
+ * @see #setStyleRanges(int[], StyleRange[])
+ */
+public StyleRange[] getStyleRanges(boolean includeRanges) {
+ checkWidget();
+ return getStyleRanges(0, content.getCharCount(), includeRanges);
+}
+/**
+ * Returns the styles for the given text range.
+ *
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ * Note: Because the StyleRange includes the start and length, the
+ * same instance cannot occur multiple times in the array of styles.
+ * If the same style attributes, such as font and color, occur in
+ * multiple StyleRanges, getStyleRanges(int, int, boolean)
+ * can be used to get the styles without the ranges.
+ *
+ * @param start the start offset of the style ranges to return
+ * @param length the number of style ranges to return
+ *
+ * @return the styles or an empty array if a LineStyleListener has
+ * been set. The returned styles will reflect the given range. The first
+ * returned StyleRange will have a starting offset >= start
+ * and the last returned StyleRange will have an ending
+ * offset <= start + length - 1
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
+ *
+ *
+ * @see #getStyleRanges(int, int, boolean)
+ *
+ * @since 3.0
+ */
+public StyleRange[] getStyleRanges(int start, int length) {
+ checkWidget();
+ return getStyleRanges(start, length, true);
+}
+/**
+ * Returns the styles for the given text range.
+ *
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ * Note: When includeRanges is true, the start and length
+ * fields of each StyleRange will be valid, however the StyleRange
+ * objects may need to be cloned. When includeRanges is
+ * false, getRanges(int, int) can be used to get the
+ * associated ranges.
+ *
+ *
+ * @param start the start offset of the style ranges to return
+ * @param length the number of style ranges to return
+ * @param includeRanges whether the start and length field of the StyleRanges should be set.
+ *
+ * @return the styles or an empty array if a LineStyleListener has
+ * been set. The returned styles will reflect the given range. The first
+ * returned StyleRange will have a starting offset >= start
+ * and the last returned StyleRange will have an ending
+ * offset <= start + length - 1
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
+ *
+ *
+ * @since 3.2
+ *
+ * @see #getRanges(int, int)
+ * @see #setStyleRanges(int[], StyleRange[])
+ */
+public StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) {
+ checkWidget();
+ int contentLength = getCharCount();
+ int end = start + length;
+ if (start > end || start < 0 || end > contentLength) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ if (!isListening(LineGetStyle)) {
+ StyleRange[] ranges = renderer.getStyleRanges(start, length, includeRanges);
+ if (ranges != null) return ranges;
+ }
+ return new StyleRange[0];
+}
+/**
+ * Returns the tab width measured in characters.
+ *
+ * @return tab width measured in characters
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getTabs() {
+ checkWidget();
+ return tabLength;
+}
+/**
+ * Returns a copy of the widget content.
+ *
+ * @return copy of the widget content
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getText() {
+ checkWidget();
+ return content.getTextRange(0, getCharCount());
+}
+/**
+ * Returns the widget content between the two offsets.
+ *
+ * @param start offset of the first character in the returned String
+ * @param end offset of the last character in the returned String
+ * @return widget content starting at start and ending at end
+ * @see #getTextRange(int,int)
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
+ *
+ */
+public String getText(int start, int end) {
+ checkWidget();
+ int contentLength = getCharCount();
+ if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ return content.getTextRange(start, end - start + 1);
+}
+/**
+ * Returns the smallest bounding rectangle that includes the characters between two offsets.
+ *
+ * @param start offset of the first character included in the bounding box
+ * @param end offset of the last character included in the bounding box
+ * @return bounding box of the text between start and end
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
+ *
+ * @since 3.1
+ */
+public Rectangle getTextBounds(int start, int end) {
+ checkWidget();
+ int contentLength = getCharCount();
+ if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ int lineStart = content.getLineAtOffset(start);
+ int lineEnd = content.getLineAtOffset(end);
+ Rectangle rect;
+ int y = getLinePixel(lineStart);
+ int height = 0;
+ int left = 0x7fffffff, right = 0;
+ for (int i = lineStart; i <= lineEnd; i++) {
+ int lineOffset = content.getOffsetAtLine(i);
+ TextLayout layout = renderer.getTextLayout(i);
+ if (i == lineStart && i == lineEnd) {
+ rect = layout.getBounds(start - lineOffset, end - lineOffset);
+ } else if (i == lineStart) {
+ String line = content.getLine(i);
+ rect = layout.getBounds(start - lineOffset, line.length());
+ } else if (i == lineEnd) {
+ rect = layout.getBounds(0, end - lineOffset);
+ } else {
+ rect = layout.getBounds();
+ }
+ left = Math.min (left, rect.x);
+ right = Math.max (right, rect.x + rect.width);
+ height += rect.height;
+ renderer.disposeTextLayout(layout);
+ }
+ rect = new Rectangle (left, y, right-left, height);
+ rect.x += leftMargin - horizontalScrollOffset;
+ return rect;
+}
+/**
+ * Returns the widget content starting at start for length characters.
+ *
+ * @param start offset of the first character in the returned String
+ * @param length number of characters to return
+ * @return widget content starting at start and extending length characters.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when start and/or length are outside the widget content
+ *
+ */
+public String getTextRange(int start, int length) {
+ checkWidget();
+ int contentLength = getCharCount();
+ int end = start + length;
+ if (start > end || start < 0 || end > contentLength) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ return content.getTextRange(start, length);
+}
+/**
+ * Returns the maximum number of characters that the receiver is capable of holding.
+ *
+ * @return the text limit
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getTextLimit() {
+ checkWidget();
+ return textLimit;
+}
+/**
+ * Gets the top index.
+ *
+ * The top index is the index of the fully visible line that is currently
+ * at the top of the widget or the topmost partially visible line if no line is fully visible.
+ * The top index changes when the widget is scrolled. Indexing is zero based.
+ *
+ *
+ * @return the index of the top line
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getTopIndex() {
+ checkWidget();
+ return topIndex;
+}
+/**
+ * Gets the top pixel.
+ *
+ * The top pixel is the pixel position of the line that is
+ * currently at the top of the widget. The text widget can be scrolled by pixels
+ * by dragging the scroll thumb so that a partial line may be displayed at the top
+ * the widget. The top pixel changes when the widget is scrolled. The top pixel
+ * does not include the widget trimming.
+ *
+ *
+ * @return pixel position of the top line
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getTopPixel() {
+ checkWidget();
+ return getVerticalScrollOffset();
+}
+/**
+ * Returns the vertical scroll increment.
+ *
+ * @return vertical scroll increment.
+ */
+int getVerticalIncrement() {
+ return renderer.getLineHeight();
+}
+int getVerticalScrollOffset() {
+ if (verticalScrollOffset == -1) {
+ renderer.calculate(0, topIndex);
+ int height = 0;
+ for (int i = 0; i < topIndex; i++) {
+ height += renderer.getLineHeight(i);
+ }
+ height -= topIndexY;
+ verticalScrollOffset = height;
+ }
+ return verticalScrollOffset;
+}
+int getVisualLineIndex(TextLayout layout, int offsetInLine) {
+ int lineIndex = layout.getLineIndex(offsetInLine);
+ int[] offsets = layout.getLineOffsets();
+ if (lineIndex != 0 && offsetInLine == offsets[lineIndex] && caretAlignment == PREVIOUS_OFFSET_TRAILING) {
+ lineIndex--;
+ }
+ return lineIndex;
+}
+int getCaretDirection() {
+ if (!isBidiCaret()) return SWT.DEFAULT;
+ if (!updateCaretDirection && caretDirection != SWT.NULL) return caretDirection;
+ updateCaretDirection = false;
+ int caretLine = getCaretLine();
+ int lineOffset = content.getOffsetAtLine(caretLine);
+ String line = content.getLine(caretLine);
+ int offset = caretOffset - lineOffset;
+ int lineLength = line.length();
+ if (lineLength == 0) return isMirrored() ? SWT.RIGHT : SWT.LEFT;
+ if (caretAlignment == PREVIOUS_OFFSET_TRAILING && offset > 0) offset--;
+ if (offset == lineLength && offset > 0) offset--;
+ while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--;
+ if (offset == 0 && Character.isDigit(line.charAt(offset))) {
+ return isMirrored() ? SWT.RIGHT : SWT.LEFT;
+ }
+ TextLayout layout = renderer.getTextLayout(caretLine);
+ int level = layout.getLevel(offset);
+ renderer.disposeTextLayout(layout);
+ return ((level & 1) != 0) ? SWT.RIGHT : SWT.LEFT;
+}
+/*
+ * Returns the index of the line the caret is on.
+ */
+int getCaretLine() {
+ return content.getLineAtOffset(caretOffset);
+}
+int getWrapWidth () {
+ if (wordWrap && !isSingleLine()) {
+ int width = clientAreaWidth - leftMargin - rightMargin;
+ return width > 0 ? width : 1;
+ }
+ return -1;
+}
+/**
+ * Returns the offset of the character after the word at the specified
+ * offset.
+ *
+ * There are two classes of words formed by a sequence of characters:
+ *
+ *
from 0-9 and A-z (ASCII 48-57 and 65-122)
+ *
every other character except line breaks
+ *
+ *
+ * Space characters ' ' (ASCII 20) are special as they are treated as
+ * part of the word leading up to the space character. Line breaks are
+ * treated as one word.
+ *
+ */
+int getWordEnd(int offset) {
+ if (offset >= getCharCount()) {
+ return offset;
+ }
+ int lineIndex = content.getLineAtOffset(offset);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ int lineLength = content.getLine(lineIndex).length();
+ if (offset == lineOffset + lineLength) {
+ offset = content.getOffsetAtLine(lineIndex + 1);
+ } else {
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ offset -= lineOffset;
+ offset = layout.getNextOffset(offset, SWT.MOVEMENT_WORD);
+ offset += lineOffset;
+ renderer.disposeTextLayout(layout);
+ }
+ return offset;
+}
+/**
+ * Returns the offset of the character after the word at the specified
+ * offset.
+ *
+ * There are two classes of words formed by a sequence of characters:
+ *
+ *
from 0-9 and A-z (ASCII 48-57 and 65-122)
+ *
every other character except line breaks
+ *
+ *
+ * Spaces are ignored and do not represent a word. Line breaks are treated
+ * as one word.
+ *
+ */
+int getWordEndNoSpaces(int offset) {
+ if (offset >= getCharCount()) {
+ return offset;
+ }
+ int line = content.getLineAtOffset(offset);
+ int lineOffset = content.getOffsetAtLine(line);
+ String lineText = content.getLine(line);
+ int lineLength = lineText.length();
+ if (offset == lineOffset + lineLength) {
+ line++;
+ offset = content.getOffsetAtLine(line);
+ } else {
+ offset -= lineOffset;
+ char ch = lineText.charAt(offset);
+ boolean letterOrDigit = Compatibility.isLetterOrDigit(ch);
+ while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && !Compatibility.isSpaceChar(ch)) {
+ offset++;
+ ch = lineText.charAt(offset);
+ }
+ if (offset == lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && !Compatibility.isSpaceChar(ch)) {
+ offset++;
+ }
+ offset += lineOffset;
+ }
+ return offset;
+}
+/**
+ * Returns the start offset of the word at the specified offset.
+ * There are two classes of words formed by a sequence of characters:
+ *
+ *
+ *
from 0-9 and A-z (ASCII 48-57 and 65-122)
+ *
every other character except line breaks
+ *
+ *
+ * Space characters ' ' (ASCII 20) are special as they are treated as
+ * part of the word leading up to the space character. Line breaks are treated
+ * as one word.
+ *
+ * NOTE: Does not return correct values for true italic fonts (vs. slanted fonts).
+ *
+ *
+ * @return location of the character at the given offset in the line.
+ */
+Point getPointAtOffset(int offset) {
+ int lineIndex = content.getLineAtOffset(offset);
+ String line = content.getLine(lineIndex);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ int offsetInLine = offset - lineOffset;
+ int lineLength = line.length();
+ if (lineIndex < content.getLineCount() - 1) {
+ int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1;
+ if (lineLength < offsetInLine && offsetInLine <= endLineOffset) {
+ offsetInLine = lineLength;
+ }
+ }
+ Point point;
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ if (lineLength != 0 && offsetInLine <= lineLength) {
+ if (offsetInLine == lineLength) {
+ point = layout.getLocation(offsetInLine - 1, true);
+ } else {
+ switch (caretAlignment) {
+ case OFFSET_LEADING:
+ point = layout.getLocation(offsetInLine, false);
+ break;
+ case PREVIOUS_OFFSET_TRAILING:
+ default:
+ if (offsetInLine == 0) {
+ point = layout.getLocation(offsetInLine, false);
+ } else {
+ point = layout.getLocation(offsetInLine - 1, true);
+ }
+ break;
+ }
+ }
+ } else {
+ point = new Point(layout.getIndent(), 0);
+ }
+ renderer.disposeTextLayout(layout);
+ point.x += leftMargin - horizontalScrollOffset;
+ point.y += getLinePixel(lineIndex);
+ return point;
+}
+/**
+ * Inserts a string. The old selection is replaced with the new text.
+ *
+ * @param string the string
+ * @see #replaceTextRange(int,int,String)
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when string is null
+ *
+ */
+public void insert(String string) {
+ checkWidget();
+ if (string == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ Point sel = getSelectionRange();
+ replaceTextRange(sel.x, sel.y, string);
+}
+/**
+ * Creates content change listeners and set the default content model.
+ */
+void installDefaultContent() {
+ textChangeListener = new TextChangeListener() {
+ public void textChanging(TextChangingEvent event) {
+ handleTextChanging(event);
+ }
+ public void textChanged(TextChangedEvent event) {
+ handleTextChanged(event);
+ }
+ public void textSet(TextChangedEvent event) {
+ handleTextSet(event);
+ }
+ };
+ content = new DefaultContent();
+ content.addTextChangeListener(textChangeListener);
+}
+/**
+ * Adds event listeners
+ */
+void installListeners() {
+ ScrollBar verticalBar = getVerticalBar();
+ ScrollBar horizontalBar = getHorizontalBar();
+
+ listener = new Listener() {
+ public void handleEvent(Event event) {
+ switch (event.type) {
+ case SWT.Dispose: handleDispose(event); break;
+ case SWT.DragDetect: handleDragDetect(event); break;
+ case SWT.KeyDown: handleKeyDown(event); break;
+ case SWT.KeyUp: handleKeyUp(event); break;
+ case SWT.MouseDown: handleMouseDown(event); break;
+ case SWT.MouseUp: handleMouseUp(event); break;
+ case SWT.MouseDoubleClick: handleMouseDoubleClick(event); break;
+ case SWT.MouseMove: handleMouseMove(event); break;
+ case SWT.Paint: handlePaint(event); break;
+ case SWT.Resize: handleResize(event); break;
+ case SWT.Traverse: handleTraverse(event); break;
+ }
+ }
+ };
+ addListener(SWT.Dispose, listener);
+ // do not hook SWT.DragDetect until required
+ addListener(SWT.KeyDown, listener);
+ addListener(SWT.KeyUp, listener);
+ addListener(SWT.MouseDown, listener);
+ addListener(SWT.MouseUp, listener);
+ addListener(SWT.MouseDoubleClick, listener);
+ addListener(SWT.MouseMove, listener);
+ addListener(SWT.Paint, listener);
+ addListener(SWT.Resize, listener);
+ addListener(SWT.Traverse, listener);
+ if (verticalBar != null) {
+ verticalBar.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ handleVerticalScroll(event);
+ }
+ });
+ }
+ if (horizontalBar != null) {
+ horizontalBar.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ handleHorizontalScroll(event);
+ }
+ });
+ }
+}
+void internalRedrawRange(int start, int length) {
+ if (length <= 0) return;
+ int end = start + length;
+ int startLine = content.getLineAtOffset(start);
+ int endLine = content.getLineAtOffset(end);
+ int partialBottomIndex = getPartialBottomIndex();
+ int partialTopIndex = getPartialTopIndex();
+ if (startLine > partialBottomIndex || endLine < partialTopIndex) {
+ return;
+ }
+ if (partialTopIndex > startLine) {
+ startLine = partialTopIndex;
+ start = 0;
+ } else {
+ start -= content.getOffsetAtLine(startLine);
+ }
+ if (partialBottomIndex < endLine) {
+ endLine = partialBottomIndex + 1;
+ end = 0;
+ } else {
+ end -= content.getOffsetAtLine(endLine);
+ }
+
+ TextLayout layout = renderer.getTextLayout(startLine);
+ int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine);
+ int[] offsets = layout.getLineOffsets();
+ int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length()));
+
+ /* Redraw end of line before start line if wrapped and start offset is first char */
+ if (wordWrap && startIndex > 0 && offsets[startIndex] == start) {
+ Rectangle rect = layout.getLineBounds(startIndex - 1);
+ rect.x = rect.width;
+ rect.width = clientAreaWidth - rightMargin - rect.x;
+ rect.x += lineX;
+ rect.y += startLineY;
+ super.redraw(rect.x, rect.y, rect.width, rect.height, false);
+ }
+
+ if (startLine == endLine) {
+ int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length()));
+ if (startIndex == endIndex) {
+ /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */
+ Rectangle rect = layout.getBounds(start, end - 1);
+ rect.x += lineX;
+ rect.y += startLineY;
+ super.redraw(rect.x, rect.y, rect.width, rect.height, false);
+ renderer.disposeTextLayout(layout);
+ return;
+ }
+ }
+
+ /* Redraw start line from the start offset to the end of client area */
+ Rectangle startRect = layout.getBounds(start, offsets[startIndex + 1] - 1);
+ if (startRect.height == 0) {
+ Rectangle bounds = layout.getLineBounds(startIndex);
+ startRect.x = bounds.width;
+ startRect.y = bounds.y;
+ startRect.height = bounds.height;
+ }
+ startRect.x += lineX;
+ startRect.y += startLineY;
+ startRect.width = clientAreaWidth - rightMargin - startRect.x;
+ super.redraw(startRect.x, startRect.y, startRect.width, startRect.height, false);
+
+ /* Redraw end line from the begining of the line to the end offset */
+ if (startLine != endLine) {
+ renderer.disposeTextLayout(layout);
+ layout = renderer.getTextLayout(endLine);
+ offsets = layout.getLineOffsets();
+ }
+ int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length()));
+ Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1);
+ if (endRect.height == 0) {
+ Rectangle bounds = layout.getLineBounds(endIndex);
+ endRect.y = bounds.y;
+ endRect.height = bounds.height;
+ }
+ endRect.x += lineX;
+ endRect.y += getLinePixel(endLine);
+ super.redraw(endRect.x, endRect.y, endRect.width, endRect.height, false);
+ renderer.disposeTextLayout(layout);
+
+ /* Redraw all lines in between start and end line */
+ int y = startRect.y + startRect.height;
+ if (endRect.y > y) {
+ super.redraw(leftMargin, y, clientAreaWidth - rightMargin - leftMargin, endRect.y - y, false);
+ }
+}
+/**
+ * Frees resources.
+ */
+void handleDispose(Event event) {
+ removeListener(SWT.Dispose, listener);
+ notifyListeners(SWT.Dispose, event);
+ event.type = SWT.None;
+
+ clipboard.dispose();
+ if (renderer != null) {
+ renderer.dispose();
+ renderer = null;
+ }
+ if (content != null) {
+ content.removeTextChangeListener(textChangeListener);
+ content = null;
+ }
+ if (defaultCaret != null) {
+ defaultCaret.dispose();
+ defaultCaret = null;
+ }
+ if (leftCaretBitmap != null) {
+ leftCaretBitmap.dispose();
+ leftCaretBitmap = null;
+ }
+ if (rightCaretBitmap != null) {
+ rightCaretBitmap.dispose();
+ rightCaretBitmap = null;
+ }
+ if (isBidiCaret()) {
+ BidiUtil.removeLanguageListener(handle);
+ }
+ selectionBackground = null;
+ selectionForeground = null;
+ textChangeListener = null;
+ selection = null;
+ doubleClickSelection = null;
+ keyActionMap = null;
+ background = null;
+ foreground = null;
+ clipboard = null;
+}
+void handleDragDetect(Event event) {
+ dragging = true;
+}
+/**
+ * Scrolls the widget horizontally.
+ */
+void handleHorizontalScroll(Event event) {
+ int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset;
+ scrollHorizontal(scrollPixel, false);
+}
+/**
+ * If an action has been registered for the key stroke execute the action.
+ * Otherwise, if a character has been entered treat it as new content.
+ *
+ * @param event keyboard event
+ */
+void handleKey(Event event) {
+ int action;
+ caretAlignment = PREVIOUS_OFFSET_TRAILING;
+ if (event.keyCode != 0) {
+ // special key pressed (e.g., F1)
+ action = getKeyBinding(event.keyCode | event.stateMask);
+ } else {
+ // character key pressed
+ action = getKeyBinding(event.character | event.stateMask);
+ if (action == SWT.NULL) {
+ // see if we have a control character
+ if ((event.stateMask & SWT.CTRL) != 0 && (event.character >= 0) && event.character <= 31) {
+ // get the character from the CTRL+char sequence, the control
+ // key subtracts 64 from the value of the key that it modifies
+ int c = event.character + 64;
+ action = getKeyBinding(c | event.stateMask);
+ }
+ }
+ }
+ if (action == SWT.NULL) {
+ boolean ignore = false;
+
+ if (IS_CARBON) {
+ // Ignore accelerator key combinations (we do not want to
+ // insert a character in the text in this instance). Do not
+ // ignore COMMAND+ALT combinations since that key sequence
+ // produces characters on the mac.
+ ignore = (event.stateMask ^ SWT.COMMAND) == 0 ||
+ (event.stateMask ^ (SWT.COMMAND | SWT.SHIFT)) == 0;
+ } else if (IS_MOTIF) {
+ // Ignore accelerator key combinations (we do not want to
+ // insert a character in the text in this instance). Do not
+ // ignore ALT combinations since this key sequence
+ // produces characters on motif.
+ ignore = (event.stateMask ^ SWT.CTRL) == 0 ||
+ (event.stateMask ^ (SWT.CTRL | SWT.SHIFT)) == 0;
+ } else {
+ // Ignore accelerator key combinations (we do not want to
+ // insert a character in the text in this instance). Don't
+ // ignore CTRL+ALT combinations since that is the Alt Gr
+ // key on some keyboards. See bug 20953.
+ ignore = (event.stateMask ^ SWT.ALT) == 0 ||
+ (event.stateMask ^ SWT.CTRL) == 0 ||
+ (event.stateMask ^ (SWT.ALT | SWT.SHIFT)) == 0 ||
+ (event.stateMask ^ (SWT.CTRL | SWT.SHIFT)) == 0;
+ }
+ // -ignore anything below SPACE except for line delimiter keys and tab.
+ // -ignore DEL
+ if (!ignore && event.character > 31 && event.character != SWT.DEL ||
+ event.character == SWT.CR || event.character == SWT.LF ||
+ event.character == TAB) {
+ doContent(event.character);
+ update();
+ }
+ } else {
+ invokeAction(action);
+ }
+}
+/**
+ * If a VerifyKey listener exists, verify that the key that was entered
+ * should be processed.
+ *
+ * @param event keyboard event
+ */
+void handleKeyDown(Event event) {
+ if (clipboardSelection == null) {
+ clipboardSelection = new Point(selection.x, selection.y);
+ }
+
+ Event verifyEvent = new Event();
+ verifyEvent.character = event.character;
+ verifyEvent.keyCode = event.keyCode;
+ verifyEvent.stateMask = event.stateMask;
+ verifyEvent.doit = true;
+ notifyListeners(VerifyKey, verifyEvent);
+ if (verifyEvent.doit) {
+ handleKey(event);
+ }
+}
+/**
+ * Update the Selection Clipboard.
+ *
+ * @param event keyboard event
+ */
+void handleKeyUp(Event event) {
+ if (clipboardSelection != null) {
+ if (clipboardSelection.x != selection.x || clipboardSelection.y != selection.y) {
+ try {
+ if (selection.y - selection.x > 0) {
+ setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD);
+ }
+ } catch (SWTError error) {
+ // Copy to clipboard failed. This happens when another application
+ // is accessing the clipboard while we copy. Ignore the error.
+ // Fixes 1GDQAVN
+ // Rethrow all other errors. Fixes bug 17578.
+ if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) {
+ throw error;
+ }
+ }
+ }
+ }
+ clipboardSelection = null;
+}
+/**
+ * Updates the caret location and selection if mouse button 1 has been
+ * pressed.
+ */
+void handleMouseDoubleClick(Event event) {
+ if (event.button != 1 || !doubleClickEnabled) {
+ return;
+ }
+ mouseDoubleClick = true;
+ caretOffset = getWordStart(caretOffset);
+ resetSelection();
+ caretOffset = getWordEndNoSpaces(caretOffset);
+ showCaret();
+ doMouseSelection();
+ doubleClickSelection = new Point(selection.x, selection.y);
+}
+/**
+ * Updates the caret location and selection if mouse button 1 has been
+ * pressed.
+ */
+void handleMouseDown(Event event) {
+ mouseDoubleClick = false;
+
+ //force focus (object support)
+ forceFocus();
+
+ dragging = false;
+ removeListener(SWT.DragDetect, listener);
+ dragDetect = detectDrag(event.x, event.y, event.button);
+ if (dragDetect) {
+ addListener(SWT.DragDetect, listener);
+ return;
+ }
+
+ mouseDown = true;
+ if (event.button == 2) {
+ String text = (String)getClipboardContent(DND.SELECTION_CLIPBOARD);
+ if (text != null && text.length() > 0) {
+ // position cursor
+ doMouseLocationChange(event.x, event.y, false);
+ // insert text
+ Event e = new Event();
+ e.start = selection.x;
+ e.end = selection.y;
+ e.text = getModelDelimitedText(text);
+ sendKeyEvent(e);
+ }
+ }
+ if ((event.button != 1) || (IS_CARBON && (event.stateMask & SWT.MOD4) != 0)) {
+ return;
+ }
+ boolean select = (event.stateMask & SWT.MOD2) != 0;
+ doMouseLocationChange(event.x, event.y, select);
+}
+/**
+ * Updates the caret location and selection if mouse button 1 is pressed
+ * during the mouse move.
+ */
+void handleMouseMove(Event event) {
+ if (!mouseDown) return;
+ if ((event.stateMask & SWT.BUTTON1) == 0) {
+ return;
+ }
+ doMouseLocationChange(event.x, event.y, true);
+ update();
+ doAutoScroll(event);
+}
+/**
+ * Autoscrolling ends when the mouse button is released.
+ */
+void handleMouseUp(Event event) {
+ mouseDown = false;
+ mouseDoubleClick = false;
+ endAutoScroll();
+ if (dragDetect) {
+ removeListener(SWT.DragDetect, listener);
+ if (!dragging) {
+ boolean select = (event.stateMask & SWT.MOD2) != 0;
+ doMouseLocationChange(event.x, event.y, select);
+ }
+ }
+ dragDetect = dragging = false;
+ if (event.button == 1) {
+ try {
+ if (selection.y - selection.x > 0) {
+ setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD);
+ }
+ } catch (SWTError error) {
+ // Copy to clipboard failed. This happens when another application
+ // is accessing the clipboard while we copy. Ignore the error.
+ // Fixes 1GDQAVN
+ // Rethrow all other errors. Fixes bug 17578.
+ if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) {
+ throw error;
+ }
+ }
+ }
+}
+/**
+ * Renders the invalidated area specified in the paint event.
+ *
+ * @param event paint event
+ */
+void handlePaint(Event event) {
+ if (event.width == 0 || event.height == 0) return;
+ if (clientAreaWidth == 0 || clientAreaHeight == 0) return;
+
+ int startLine = getLineIndex(event.y);
+ int y = getLinePixel(startLine);
+ int endY = event.y + event.height;
+ GC gc = event.gc;
+ Color background = getBackground();
+ Color foreground = getForeground();
+ if (endY > 0) {
+ int lineCount = isSingleLine() ? 1 : content.getLineCount();
+ int x = leftMargin - horizontalScrollOffset;
+ for (int i = startLine; y < endY && i < lineCount; i++) {
+ y += renderer.drawLine(i, x, y, gc, background, foreground);
+ }
+ if (y < endY) {
+ gc.setBackground(background);
+ drawBackground(gc, 0, y, clientAreaWidth, endY - y);
+ }
+ }
+ // fill the margin background
+ gc.setBackground(background);
+ if (topMargin > 0) {
+ drawBackground(gc, 0, 0, clientAreaWidth, topMargin);
+ }
+ if (bottomMargin > 0) {
+ drawBackground(gc, 0, clientAreaHeight - bottomMargin, clientAreaWidth, bottomMargin);
+ }
+ if (leftMargin > 0) {
+ drawBackground(gc, 0, 0, leftMargin, clientAreaHeight);
+ }
+ if (rightMargin > 0) {
+ drawBackground(gc, clientAreaWidth - rightMargin, 0, rightMargin, clientAreaHeight);
+ }
+}
+/**
+ * Recalculates the scroll bars. Rewraps all lines when in word
+ * wrap mode.
+ *
+ * @param event resize event
+ */
+void handleResize(Event event) {
+ int oldHeight = clientAreaHeight;
+ int oldWidth = clientAreaWidth;
+ Rectangle clientArea = getClientArea();
+ clientAreaHeight = clientArea.height;
+ clientAreaWidth = clientArea.width;
+ /* Redraw the old or new right/bottom margin if needed */
+ if (oldWidth != clientAreaWidth) {
+ if (rightMargin > 0) {
+ int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin;
+ super.redraw(x, 0, rightMargin, oldHeight, false);
+ }
+ }
+ if (oldHeight != clientAreaHeight) {
+ if (bottomMargin > 0) {
+ int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin;
+ super.redraw(0, y, oldWidth, bottomMargin, false);
+ }
+ }
+ if (wordWrap) {
+ if (oldWidth != clientAreaWidth) {
+ renderer.reset(0, content.getLineCount());
+ verticalScrollOffset = -1;
+ renderer.calculateIdle();
+ super.redraw();
+ }
+ if (oldHeight != clientAreaHeight) {
+ if (oldHeight == 0) topIndexY = 0;
+ setScrollBars(true);
+ }
+ setCaretLocation();
+ } else {
+ renderer.calculateClientArea();
+ setScrollBars(true);
+ claimRightFreeSpace();
+ }
+ claimBottomFreeSpace();
+ //TODO FIX TOP INDEX DURING RESIZE
+// if (oldHeight != clientAreaHeight || wordWrap) {
+// calculateTopIndex(0);
+// }
+}
+/**
+ * Updates the caret position and selection and the scroll bars to reflect
+ * the content change.
+ */
+void handleTextChanged(TextChangedEvent event) {
+ int firstLine = content.getLineAtOffset(lastTextChangeStart);
+ resetCache(firstLine, 0);
+ if (!isFixedLineHeight() && topIndex > firstLine) {
+ topIndex = firstLine;
+ topIndexY = 0;
+ super.redraw();
+ } else {
+ int lastLine = firstLine + lastTextChangeNewLineCount;
+ int firstLineTop = getLinePixel(firstLine);
+ int newLastLineBottom = getLinePixel(lastLine + 1);
+ if (lastLineBottom != newLastLineBottom) {
+ scrollText(lastLineBottom, newLastLineBottom);
+ if (wordWrap) setCaretLocation();
+ }
+ super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false);
+ redrawLinesBullet(renderer.redrawLines);
+ }
+ renderer.redrawLines = null;
+ // update selection/caret location after styles have been changed.
+ // otherwise any text measuring could be incorrect
+ //
+ // also, this needs to be done after all scrolling. Otherwise,
+ // selection redraw would be flushed during scroll which is wrong.
+ // in some cases new text would be drawn in scroll source area even
+ // though the intent is to scroll it.
+ updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount);
+ if (lastTextChangeReplaceLineCount > 0 || wordWrap) {
+ claimBottomFreeSpace();
+ }
+ if (lastTextChangeReplaceCharCount > 0) {
+ claimRightFreeSpace();
+ }
+}
+/**
+ * Updates the screen to reflect a pending content change.
+ *
+ * @param event.start the start offset of the change
+ * @param event.newText text that is going to be inserted or empty String
+ * if no text will be inserted
+ * @param event.replaceCharCount length of text that is going to be replaced
+ * @param event.newCharCount length of text that is going to be inserted
+ * @param event.replaceLineCount number of lines that are going to be replaced
+ * @param event.newLineCount number of new lines that are going to be inserted
+ */
+void handleTextChanging(TextChangingEvent event) {
+ if (event.replaceCharCount < 0) {
+ event.start += event.replaceCharCount;
+ event.replaceCharCount *= -1;
+ }
+ lastTextChangeStart = event.start;
+ lastTextChangeNewLineCount = event.newLineCount;
+ lastTextChangeNewCharCount = event.newCharCount;
+ lastTextChangeReplaceLineCount = event.replaceLineCount;
+ lastTextChangeReplaceCharCount = event.replaceCharCount;
+ int lineIndex = content.getLineAtOffset(event.start);
+ int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1);
+ int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight();
+ lastLineBottom = destY;
+ scrollText(srcY, destY);
+
+ renderer.textChanging(event);
+
+ // Update the caret offset if it is greater than the length of the content.
+ // This is necessary since style range API may be called between the
+ // handleTextChanging and handleTextChanged events and this API sets the
+ // caretOffset.
+ int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount;
+ if (caretOffset > newEndOfText) caretOffset = newEndOfText;
+}
+/**
+ * Called when the widget content is set programatically, overwriting
+ * the old content. Resets the caret position, selection and scroll offsets.
+ * Recalculates the content width and scroll bars. Redraws the widget.
+ *
+ * @param event text change event.
+ */
+void handleTextSet(TextChangedEvent event) {
+ reset();
+}
+/**
+ * Called when a traversal key is pressed.
+ * Allow tab next traversal to occur when the widget is in single
+ * line mode or in multi line and non-editable mode .
+ * When in editable multi line mode we want to prevent the tab
+ * traversal and receive the tab key event instead.
+ *
+ * @param event the event
+ */
+void handleTraverse(Event event) {
+ switch (event.detail) {
+ case SWT.TRAVERSE_ESCAPE:
+ case SWT.TRAVERSE_PAGE_NEXT:
+ case SWT.TRAVERSE_PAGE_PREVIOUS:
+ event.doit = true;
+ break;
+ case SWT.TRAVERSE_RETURN:
+ case SWT.TRAVERSE_TAB_NEXT:
+ case SWT.TRAVERSE_TAB_PREVIOUS:
+ if ((getStyle() & SWT.SINGLE) != 0) {
+ event.doit = true;
+ } else {
+ if (!editable || (event.stateMask & SWT.MODIFIER_MASK) != 0) {
+ event.doit = true;
+ }
+ }
+ break;
+ }
+}
+/**
+ * Scrolls the widget vertically.
+ */
+void handleVerticalScroll(Event event) {
+ int scrollPixel = getVerticalBar().getSelection() - getVerticalScrollOffset();
+ scrollVertical(scrollPixel, false);
+}
+/**
+ * Add accessibility support for the widget.
+ */
+void initializeAccessible() {
+ final Accessible accessible = getAccessible();
+ accessible.addAccessibleListener(new AccessibleAdapter() {
+ public void getName (AccessibleEvent e) {
+ String name = null;
+ Label label = getAssociatedLabel ();
+ if (label != null) {
+ name = stripMnemonic (label.getText());
+ }
+ e.result = name;
+ }
+ public void getHelp(AccessibleEvent e) {
+ e.result = getToolTipText();
+ }
+ public void getKeyboardShortcut(AccessibleEvent e) {
+ String shortcut = null;
+ Label label = getAssociatedLabel ();
+ if (label != null) {
+ String text = label.getText ();
+ if (text != null) {
+ char mnemonic = _findMnemonic (text);
+ if (mnemonic != '\0') {
+ shortcut = "Alt+"+mnemonic; //$NON-NLS-1$
+ }
+ }
+ }
+ e.result = shortcut;
+ }
+ });
+ accessible.addAccessibleTextListener(new AccessibleTextAdapter() {
+ public void getCaretOffset(AccessibleTextEvent e) {
+ e.offset = StyledText.this.getCaretOffset();
+ }
+ public void getSelectionRange(AccessibleTextEvent e) {
+ Point selection = StyledText.this.getSelectionRange();
+ e.offset = selection.x;
+ e.length = selection.y;
+ }
+ });
+ accessible.addAccessibleControlListener(new AccessibleControlAdapter() {
+ public void getRole(AccessibleControlEvent e) {
+ e.detail = ACC.ROLE_TEXT;
+ }
+ public void getState(AccessibleControlEvent e) {
+ int state = 0;
+ if (isEnabled()) state |= ACC.STATE_FOCUSABLE;
+ if (isFocusControl()) state |= ACC.STATE_FOCUSED;
+ if (!isVisible()) state |= ACC.STATE_INVISIBLE;
+ if (!getEditable()) state |= ACC.STATE_READONLY;
+ e.detail = state;
+ }
+ public void getValue(AccessibleControlEvent e) {
+ e.result = StyledText.this.getText();
+ }
+ });
+ addListener(SWT.FocusIn, new Listener() {
+ public void handleEvent(Event event) {
+ accessible.setFocus(ACC.CHILDID_SELF);
+ }
+ });
+}
+/*
+ * Return the Label immediately preceding the receiver in the z-order,
+ * or null if none.
+ */
+Label getAssociatedLabel () {
+ Control[] siblings = getParent ().getChildren ();
+ for (int i = 0; i < siblings.length; i++) {
+ if (siblings [i] == StyledText.this) {
+ if (i > 0 && siblings [i-1] instanceof Label) {
+ return (Label) siblings [i-1];
+ }
+ }
+ }
+ return null;
+}
+String stripMnemonic (String string) {
+ int index = 0;
+ int length = string.length ();
+ do {
+ while ((index < length) && (string.charAt (index) != '&')) index++;
+ if (++index >= length) return string;
+ if (string.charAt (index) != '&') {
+ return string.substring(0, index-1) + string.substring(index, length);
+ }
+ index++;
+ } while (index < length);
+ return string;
+}
+/*
+ * Return the lowercase of the first non-'&' character following
+ * an '&' character in the given string. If there are no '&'
+ * characters in the given string, return '\0'.
+ */
+char _findMnemonic (String string) {
+ if (string == null) return '\0';
+ int index = 0;
+ int length = string.length ();
+ do {
+ while (index < length && string.charAt (index) != '&') index++;
+ if (++index >= length) return '\0';
+ if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (index));
+ index++;
+ } while (index < length);
+ return '\0';
+}
+/**
+ * Executes the action.
+ *
+ * @param action one of the actions defined in ST.java
+ */
+public void invokeAction(int action) {
+ checkWidget();
+ updateCaretDirection = true;
+ switch (action) {
+ // Navigation
+ case ST.LINE_UP:
+ doLineUp(false);
+ clearSelection(true);
+ break;
+ case ST.LINE_DOWN:
+ doLineDown(false);
+ clearSelection(true);
+ break;
+ case ST.LINE_START:
+ doLineStart();
+ clearSelection(true);
+ break;
+ case ST.LINE_END:
+ doLineEnd();
+ clearSelection(true);
+ break;
+ case ST.COLUMN_PREVIOUS:
+ doCursorPrevious();
+ clearSelection(true);
+ break;
+ case ST.COLUMN_NEXT:
+ doCursorNext();
+ clearSelection(true);
+ break;
+ case ST.PAGE_UP:
+ doPageUp(false, -1);
+ clearSelection(true);
+ break;
+ case ST.PAGE_DOWN:
+ doPageDown(false, -1);
+ clearSelection(true);
+ break;
+ case ST.WORD_PREVIOUS:
+ doWordPrevious();
+ clearSelection(true);
+ break;
+ case ST.WORD_NEXT:
+ doWordNext();
+ clearSelection(true);
+ break;
+ case ST.TEXT_START:
+ doContentStart();
+ clearSelection(true);
+ break;
+ case ST.TEXT_END:
+ doContentEnd();
+ clearSelection(true);
+ break;
+ case ST.WINDOW_START:
+ doPageStart();
+ clearSelection(true);
+ break;
+ case ST.WINDOW_END:
+ doPageEnd();
+ clearSelection(true);
+ break;
+ // Selection
+ case ST.SELECT_LINE_UP:
+ doSelectionLineUp();
+ break;
+ case ST.SELECT_ALL:
+ selectAll();
+ break;
+ case ST.SELECT_LINE_DOWN:
+ doSelectionLineDown();
+ break;
+ case ST.SELECT_LINE_START:
+ doLineStart();
+ doSelection(ST.COLUMN_PREVIOUS);
+ break;
+ case ST.SELECT_LINE_END:
+ doLineEnd();
+ doSelection(ST.COLUMN_NEXT);
+ break;
+ case ST.SELECT_COLUMN_PREVIOUS:
+ doSelectionCursorPrevious();
+ doSelection(ST.COLUMN_PREVIOUS);
+ break;
+ case ST.SELECT_COLUMN_NEXT:
+ doSelectionCursorNext();
+ doSelection(ST.COLUMN_NEXT);
+ break;
+ case ST.SELECT_PAGE_UP:
+ doSelectionPageUp(-1);
+ break;
+ case ST.SELECT_PAGE_DOWN:
+ doSelectionPageDown(-1);
+ break;
+ case ST.SELECT_WORD_PREVIOUS:
+ doSelectionWordPrevious();
+ doSelection(ST.COLUMN_PREVIOUS);
+ break;
+ case ST.SELECT_WORD_NEXT:
+ doSelectionWordNext();
+ doSelection(ST.COLUMN_NEXT);
+ break;
+ case ST.SELECT_TEXT_START:
+ doContentStart();
+ doSelection(ST.COLUMN_PREVIOUS);
+ break;
+ case ST.SELECT_TEXT_END:
+ doContentEnd();
+ doSelection(ST.COLUMN_NEXT);
+ break;
+ case ST.SELECT_WINDOW_START:
+ doPageStart();
+ doSelection(ST.COLUMN_PREVIOUS);
+ break;
+ case ST.SELECT_WINDOW_END:
+ doPageEnd();
+ doSelection(ST.COLUMN_NEXT);
+ break;
+ // Modification
+ case ST.CUT:
+ cut();
+ break;
+ case ST.COPY:
+ copy();
+ break;
+ case ST.PASTE:
+ paste();
+ break;
+ case ST.DELETE_PREVIOUS:
+ doBackspace();
+ break;
+ case ST.DELETE_NEXT:
+ doDelete();
+ break;
+ case ST.DELETE_WORD_PREVIOUS:
+ doDeleteWordPrevious();
+ break;
+ case ST.DELETE_WORD_NEXT:
+ doDeleteWordNext();
+ break;
+ // Miscellaneous
+ case ST.TOGGLE_OVERWRITE:
+ overwrite = !overwrite; // toggle insert/overwrite mode
+ break;
+ }
+}
+/**
+ * Temporary until SWT provides this
+ */
+boolean isBidi() {
+ return IS_GTK || BidiUtil.isBidiPlatform() || isMirrored;
+}
+boolean isBidiCaret() {
+ return BidiUtil.isBidiPlatform();
+}
+boolean isFixedLineHeight() {
+ return fixedLineHeight;
+}
+/**
+ * Returns whether the given offset is inside a multi byte line delimiter.
+ * Example:
+ * "Line1\r\n" isLineDelimiter(5) == false but isLineDelimiter(6) == true
+ *
+ * @return true if the given offset is inside a multi byte line delimiter.
+ * false if the given offset is before or after a line delimiter.
+ */
+boolean isLineDelimiter(int offset) {
+ int line = content.getLineAtOffset(offset);
+ int lineOffset = content.getOffsetAtLine(line);
+ int offsetInLine = offset - lineOffset;
+ // offsetInLine will be greater than line length if the line
+ // delimiter is longer than one character and the offset is set
+ // in between parts of the line delimiter.
+ return offsetInLine > content.getLine(line).length();
+}
+/**
+ * Returns whether the widget is mirrored (right oriented/right to left
+ * writing order).
+ *
+ * @return isMirrored true=the widget is right oriented, false=the widget
+ * is left oriented
+ */
+boolean isMirrored() {
+ return isMirrored;
+}
+/**
+ * Returns whether the widget can have only one line.
+ *
+ * @return true if widget can have only one line, false if widget can have
+ * multiple lines
+ */
+boolean isSingleLine() {
+ return (getStyle() & SWT.SINGLE) != 0;
+}
+/**
+ * Sends the specified verify event, replace/insert text as defined by
+ * the event and send a modify event.
+ *
+ * @param event the text change event.
+ *
+ *
event.start - the replace start offset
+ *
event.end - the replace end offset
+ *
event.text - the new text
+ *
+ * @param updateCaret whether or not he caret should be set behind
+ * the new text
+ */
+void modifyContent(Event event, boolean updateCaret) {
+ event.doit = true;
+ notifyListeners(SWT.Verify, event);
+ if (event.doit) {
+ StyledTextEvent styledTextEvent = null;
+ int replacedLength = event.end - event.start;
+ if (isListening(ExtendedModify)) {
+ styledTextEvent = new StyledTextEvent(content);
+ styledTextEvent.start = event.start;
+ styledTextEvent.end = event.start + event.text.length();
+ styledTextEvent.text = content.getTextRange(event.start, replacedLength);
+ }
+ if (updateCaret) {
+ //Fix advancing flag for delete/backspace key on direction boundary
+ if (event.text.length() == 0) {
+ int lineIndex = content.getLineAtOffset(event.start);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ TextLayout layout = renderer.getTextLayout(lineIndex);
+ int levelStart = layout.getLevel(event.start - lineOffset);
+ int lineIndexEnd = content.getLineAtOffset(event.end);
+ if (lineIndex != lineIndexEnd) {
+ renderer.disposeTextLayout(layout);
+ lineOffset = content.getOffsetAtLine(lineIndexEnd);
+ layout = renderer.getTextLayout(lineIndexEnd);
+ }
+ int levelEnd = layout.getLevel(event.end - lineOffset);
+ renderer.disposeTextLayout(layout);
+ if (levelStart != levelEnd) {
+ caretAlignment = PREVIOUS_OFFSET_TRAILING;
+ } else {
+ caretAlignment = OFFSET_LEADING;
+ }
+ }
+ }
+ content.replaceTextRange(event.start, replacedLength, event.text);
+ // set the caret position prior to sending the modify event.
+ // fixes 1GBB8NJ
+ if (updateCaret) {
+ // always update the caret location. fixes 1G8FODP
+ setSelection(event.start + event.text.length(), 0, true);
+ showCaret();
+ }
+ sendModifyEvent(event);
+ if (isListening(ExtendedModify)) {
+ notifyListeners(ExtendedModify, styledTextEvent);
+ }
+ }
+}
+void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style, Bullet bullet, int bulletIndex) {
+ if (isListening(PaintObject)) {
+ StyledTextEvent event = new StyledTextEvent (content) ;
+ event.gc = gc;
+ event.x = x;
+ event.y = y;
+ event.ascent = ascent;
+ event.descent = descent;
+ event.style = style;
+ event.bullet = bullet;
+ event.bulletIndex = bulletIndex;
+ notifyListeners(PaintObject, event);
+ }
+}
+/**
+ * Replaces the selection with the text on the DND.CLIPBOARD
+ * clipboard or, if there is no selection, inserts the text at the current
+ * caret offset. If the widget has the SWT.SINGLE style and the
+ * clipboard text contains more than one line, only the first line without
+ * line delimiters is inserted in the widget.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void paste(){
+ checkWidget();
+ String text = (String) getClipboardContent(DND.CLIPBOARD);
+ if (text != null && text.length() > 0) {
+ Event event = new Event();
+ event.start = selection.x;
+ event.end = selection.y;
+ event.text = getModelDelimitedText(text);
+ sendKeyEvent(event);
+ }
+}
+/**
+ * Prints the widget's text to the default printer.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void print() {
+ checkWidget();
+ Printer printer = new Printer();
+ StyledTextPrintOptions options = new StyledTextPrintOptions();
+ options.printTextForeground = true;
+ options.printTextBackground = true;
+ options.printTextFontStyle = true;
+ options.printLineBackground = true;
+ new Printing(this, printer, options).run();
+ printer.dispose();
+}
+/**
+ * Returns a runnable that will print the widget's text
+ * to the specified printer.
+ *
+ * The runnable may be run in a non-UI thread.
+ *
+ *
+ * @param printer the printer to print to
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when printer is null
+ *
+ */
+public Runnable print(Printer printer) {
+ checkWidget();
+ if (printer == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ StyledTextPrintOptions options = new StyledTextPrintOptions();
+ options.printTextForeground = true;
+ options.printTextBackground = true;
+ options.printTextFontStyle = true;
+ options.printLineBackground = true;
+ return print(printer, options);
+}
+/**
+ * Returns a runnable that will print the widget's text
+ * to the specified printer.
+ *
+ * The runnable may be run in a non-UI thread.
+ *
+ *
+ * @param printer the printer to print to
+ * @param options print options to use during printing
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when printer or options is null
+ *
+ * @since 2.1
+ */
+public Runnable print(Printer printer, StyledTextPrintOptions options) {
+ checkWidget();
+ if (printer == null || options == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ return new Printing(this, printer, options);
+}
+/**
+ * Causes the entire bounds of the receiver to be marked
+ * as needing to be redrawn. The next time a paint request
+ * is processed, the control will be completely painted.
+ *
+ * Recalculates the content width for all lines in the bounds.
+ * When a LineStyleListener is used a redraw call
+ * is the only notification to the widget that styles have changed
+ * and that the content width may have changed.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Control#update
+ */
+public void redraw() {
+ super.redraw();
+ int itemCount = getPartialBottomIndex() - topIndex + 1;
+ renderer.reset(topIndex, itemCount);
+ renderer.calculate(topIndex, itemCount);
+ setScrollBars(false);
+}
+/**
+ * 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. If the all flag
+ * is true, any children of the receiver which
+ * intersect with the specified area will also paint their
+ * intersecting areas. If the all flag is
+ * false, the children will not be painted.
+ *
+ * Marks the content width of all lines in the specified rectangle
+ * as unknown. Recalculates the content width of all visible lines.
+ * When a LineStyleListener is used a redraw call
+ * is the only notification to the widget that styles have changed
+ * and that the content width may have changed.
+ *
+ *
+ * @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 true if children should redraw, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Control#update
+ */
+public void redraw(int x, int y, int width, int height, boolean all) {
+ super.redraw(x, y, width, height, all);
+ if (height > 0) {
+ int firstLine = getLineIndex(y);
+ int lastLine = getLineIndex(y + height);
+ resetCache(firstLine, lastLine - firstLine + 1);
+ }
+}
+void redrawLines(int startLine, int lineCount) {
+ // do nothing if redraw range is completely invisible
+ int partialBottomIndex = getPartialBottomIndex();
+ if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) {
+ return;
+ }
+ // only redraw visible lines
+ if (startLine < topIndex) {
+ lineCount -= topIndex - startLine;
+ startLine = topIndex;
+ }
+ if (startLine + lineCount - 1 > partialBottomIndex) {
+ lineCount = partialBottomIndex - startLine + 1;
+ }
+ startLine -= topIndex;
+ int redrawTop = getLinePixel(startLine);
+ int redrawBottom = getLinePixel(startLine + lineCount);
+ int redrawWidth = clientAreaWidth - leftMargin - rightMargin;
+ super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true);
+}
+void redrawLinesBullet (int[] redrawLines) {
+ if (redrawLines == null) return;
+ int topIndex = getPartialTopIndex();
+ int bottomIndex = getPartialBottomIndex();
+ for (int i = 0; i < redrawLines.length; i++) {
+ int lineIndex = redrawLines[i];
+ if (!(topIndex <= lineIndex && lineIndex <= bottomIndex)) continue;
+ int width = -1;
+ Bullet bullet = renderer.getLineBullet(lineIndex, null);
+ if (bullet != null) {
+ StyleRange style = bullet.style;
+ GlyphMetrics metrics = style.metrics;
+ width = metrics.width;
+ }
+ if (width == -1) width = getClientArea().width;
+ int height = renderer.getLineHeight(lineIndex);
+ int y = getLinePixel(lineIndex);
+ super.redraw(0, y, width, height, false);
+ }
+}
+/**
+ * Redraws the specified text range.
+ *
+ * @param start offset of the first character to redraw
+ * @param length number of characters to redraw
+ * @param clearBackground true if the background should be cleared as
+ * part of the redraw operation. If true, the entire redraw range will
+ * be cleared before anything is redrawn. If the redraw range includes
+ * the last character of a line (i.e., the entire line is redrawn) the
+ * line is cleared all the way to the right border of the widget.
+ * The redraw operation will be faster and smoother if clearBackground
+ * is set to false. Whether or not the flag can be set to false depends
+ * on the type of change that has taken place. If font styles or
+ * background colors for the redraw range have changed, clearBackground
+ * should be set to true. If only foreground colors have changed for
+ * the redraw range, clearBackground can be set to false.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when start and/or end are outside the widget content
+ *
+ */
+public void redrawRange(int start, int length, boolean clearBackground) {
+ checkWidget();
+ int end = start + length;
+ int contentLength = content.getCharCount();
+ if (start > end || start < 0 || end > contentLength) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ int firstLine = content.getLineAtOffset(start);
+ int lastLine = content.getLineAtOffset(end);
+ resetCache(firstLine, lastLine - firstLine + 1);
+ internalRedrawRange(start, length);
+}
+/**
+ * Removes the specified bidirectional segment listener.
+ *
+ * @param listener the listener
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void removeVerifyKeyListener(VerifyKeyListener listener) {
+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ removeListener(VerifyKey, listener);
+}
+/**
+ * Replaces the styles in the given range with new styles. This method
+ * effectively deletes the styles in the given range and then adds the
+ * the new styles.
+ *
+ * Note: Because a StyleRange includes the start and length, the
+ * same instance cannot occur multiple times in the array of styles.
+ * If the same style attributes, such as font and color, occur in
+ * multiple StyleRanges, setStyleRanges(int, int, int[], StyleRange[])
+ * can be used to share styles and reduce memory usage.
+ *
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ *
+ * @param start offset of first character where styles will be deleted
+ * @param length length of the range to delete styles in
+ * @param ranges StyleRange objects containing the new style information.
+ * The ranges should not overlap and should be within the specified start
+ * and length. The style rendering is undefined if the ranges do overlap
+ * or are ill-defined. Must not be null.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
+ *
ERROR_NULL_ARGUMENT when ranges is null
+ *
+ *
+ * @since 2.0
+ *
+ * @see #setStyleRanges(int, int, int[], StyleRange[])
+ */
+public void replaceStyleRanges(int start, int length, StyleRange[] ranges) {
+ checkWidget();
+ if (isListening(LineGetStyle)) return;
+ if (ranges == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ setStyleRanges(start, length, null, ranges, false);
+}
+/**
+ * Replaces the given text range with new text.
+ * If the widget has the SWT.SINGLE style and "text" contains more than
+ * one line, only the first line is rendered but the text is stored
+ * unchanged. A subsequent call to getText will return the same text
+ * that was set. Note that only a single line of text should be set when
+ * the SWT.SINGLE style is used.
+ *
+ * NOTE: During the replace operation the current selection is
+ * changed as follows:
+ *
+ *
selection before replaced text: selection unchanged
+ *
selection after replaced text: adjust the selection so that same text
+ * remains selected
+ *
selection intersects replaced text: selection is cleared and caret
+ * is placed after inserted text
+ *
+ *
+ *
+ * @param start offset of first character to replace
+ * @param length number of characters to replace. Use 0 to insert text
+ * @param text new text. May be empty to delete text.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())
+ *
ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter.
+ * Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported
+ *
ERROR_NULL_ARGUMENT when string is null
+ *
+ */
+public void replaceTextRange(int start, int length, String text) {
+ checkWidget();
+ if (text == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ int contentLength = getCharCount();
+ int end = start + length;
+ if (start > end || start < 0 || end > contentLength) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ Event event = new Event();
+ event.start = start;
+ event.end = end;
+ event.text = text;
+ modifyContent(event, false);
+}
+/**
+ * Resets the caret position, selection and scroll offsets. Recalculate
+ * the content width and scroll bars. Redraw the widget.
+ */
+void reset() {
+ ScrollBar verticalBar = getVerticalBar();
+ ScrollBar horizontalBar = getHorizontalBar();
+ caretOffset = 0;
+ topIndex = 0;
+ topIndexY = 0;
+ verticalScrollOffset = 0;
+ horizontalScrollOffset = 0;
+ resetSelection();
+ renderer.setContent(content);
+ if (verticalBar != null) {
+ verticalBar.setSelection(0);
+ }
+ if (horizontalBar != null) {
+ horizontalBar.setSelection(0);
+ }
+ resetCache(0, 0);
+ setCaretLocation();
+ super.redraw();
+}
+void resetCache(int firstLine, int count) {
+ renderer.reset(firstLine, count);
+ renderer.calculateClientArea();
+ setScrollBars(true);
+ if (!isFixedLineHeight()) {
+ if (topIndex > firstLine) {
+ verticalScrollOffset = -1;
+ }
+ renderer.calculateIdle();
+ }
+}
+/**
+ * Resets the selection.
+ */
+void resetSelection() {
+ selection.x = selection.y = caretOffset;
+ selectionAnchor = -1;
+}
+
+public void scroll(int destX, int destY, int x, int y, int width, int height, boolean all) {
+ super.scroll(destX, destY, x, y, width, height, false);
+ if (all) {
+ int deltaX = destX - x, deltaY = destY - y;
+ Control[] children = getChildren();
+ for (int i=0; i 0 = scroll left,
+ * < 0 scroll right
+ * @param adjustScrollBar
+ * true= the scroll thumb will be moved to reflect the new scroll offset.
+ * false = the scroll thumb will not be moved
+ * @return
+ * true=the widget was scrolled
+ * false=the widget was not scrolled, the given offset is not valid.
+ */
+boolean scrollHorizontal(int pixels, boolean adjustScrollBar) {
+ if (pixels == 0) {
+ return false;
+ }
+ ScrollBar horizontalBar = getHorizontalBar();
+ if (horizontalBar != null && adjustScrollBar) {
+ horizontalBar.setSelection(horizontalScrollOffset + pixels);
+ }
+ int scrollHeight = clientAreaHeight - topMargin - bottomMargin;
+ if (pixels > 0) {
+ int sourceX = leftMargin + pixels;
+ int scrollWidth = clientAreaWidth - sourceX - rightMargin;
+ if (scrollWidth > 0) {
+ scroll(leftMargin, topMargin, sourceX, topMargin, scrollWidth, scrollHeight, true);
+ }
+ if (sourceX > scrollWidth) {
+ super.redraw(leftMargin + scrollWidth, topMargin, pixels - scrollWidth, scrollHeight, true);
+ }
+ } else {
+ int destinationX = leftMargin - pixels;
+ int scrollWidth = clientAreaWidth - destinationX - rightMargin;
+ if (scrollWidth > 0) {
+ scroll(destinationX, topMargin, leftMargin, topMargin, scrollWidth, scrollHeight, true);
+ }
+ if (destinationX > scrollWidth) {
+ super.redraw(leftMargin + scrollWidth, topMargin, -pixels - scrollWidth, scrollHeight, true);
+ }
+ }
+ horizontalScrollOffset += pixels;
+ int oldColumnX = columnX;
+ setCaretLocation();
+ columnX = oldColumnX;
+ return true;
+}
+/**
+ * Scrolls the widget vertically.
+ *
+ * @param pixel the new vertical scroll offset
+ * @param adjustScrollBar
+ * true= the scroll thumb will be moved to reflect the new scroll offset.
+ * false = the scroll thumb will not be moved
+ * @return
+ * true=the widget was scrolled
+ * false=the widget was not scrolled
+ */
+boolean scrollVertical(int pixels, boolean adjustScrollBar) {
+ if (pixels == 0) {
+ return false;
+ }
+ if (verticalScrollOffset != -1) {
+ ScrollBar verticalBar = getVerticalBar();
+ if (verticalBar != null && adjustScrollBar) {
+ verticalBar.setSelection(verticalScrollOffset + pixels);
+ }
+ int scrollWidth = clientAreaWidth - leftMargin - rightMargin;
+ if (pixels > 0) {
+ int sourceY = topMargin + pixels;
+ int scrollHeight = clientAreaHeight - sourceY - bottomMargin;
+ if (scrollHeight > 0) {
+ scroll(leftMargin, topMargin, leftMargin, sourceY, scrollWidth, scrollHeight, true);
+ }
+ if (sourceY > scrollHeight) {
+ int redrawY = Math.max(0, topMargin + scrollHeight);
+ int redrawHeight = Math.min(clientAreaHeight, pixels - scrollHeight);
+ super.redraw(leftMargin, redrawY, scrollWidth, redrawHeight, true);
+ }
+ } else {
+ int destinationY = topMargin - pixels;
+ int scrollHeight = clientAreaHeight - destinationY - bottomMargin;
+ if (scrollHeight > 0) {
+ scroll(leftMargin, destinationY, leftMargin, topMargin, scrollWidth, scrollHeight, true);
+ }
+ if (destinationY > scrollHeight) {
+ int redrawY = Math.max(0, topMargin + scrollHeight);
+ int redrawHeight = Math.min(clientAreaHeight, -pixels - scrollHeight);
+ super.redraw(leftMargin, redrawY, scrollWidth, redrawHeight, true);
+ }
+ }
+ verticalScrollOffset += pixels;
+ calculateTopIndex(pixels);
+ } else {
+ calculateTopIndex(pixels);
+ super.redraw();
+ }
+ int oldColumnX = columnX;
+ setCaretLocation();
+ columnX = oldColumnX;
+ return true;
+}
+void scrollText(int srcY, int destY) {
+ if (srcY == destY) return;
+ int deltaY = destY - srcY;
+ int scrollWidth = clientAreaWidth - leftMargin - rightMargin, scrollHeight;
+ if (deltaY > 0) {
+ scrollHeight = clientAreaHeight - srcY - bottomMargin;
+ } else {
+ scrollHeight = clientAreaHeight - destY - bottomMargin;
+ }
+ scroll(leftMargin, destY, leftMargin, srcY, scrollWidth, scrollHeight, true);
+ if ((0 < srcY + scrollHeight) && (topMargin > srcY)) {
+ super.redraw(leftMargin, deltaY, scrollWidth, topMargin, false);
+ }
+ if ((0 < destY + scrollHeight) && (topMargin > destY)) {
+ super.redraw(leftMargin, 0, scrollWidth, topMargin, false);
+ }
+ if ((clientAreaHeight - bottomMargin < srcY + scrollHeight) && (clientAreaHeight > srcY)) {
+ super.redraw(leftMargin, clientAreaHeight - bottomMargin + deltaY, scrollWidth, bottomMargin, false);
+ }
+ if ((clientAreaHeight - bottomMargin < destY + scrollHeight) && (clientAreaHeight > destY)) {
+ super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false);
+ }
+}
+/**
+ * Selects all the text.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void selectAll() {
+ checkWidget();
+ setSelection(0, Math.max(getCharCount(),0));
+}
+/**
+ * Replaces/inserts text as defined by the event.
+ *
+ * @param event the text change event.
+ *
+ *
event.start - the replace start offset
+ *
event.end - the replace end offset
+ *
event.text - the new text
+ *
+ */
+void sendKeyEvent(Event event) {
+ if (editable) {
+ modifyContent(event, true);
+ }
+}
+/**
+ * Returns a StyledTextEvent that can be used to request data such
+ * as styles and background color for a line.
+ *
+ * The specified line may be a visual (wrapped) line if in word
+ * wrap mode. The returned object will always be for a logical
+ * (unwrapped) line.
+ *
+ *
+ * @param lineOffset offset of the line. This may be the offset of
+ * a visual line if the widget is in word wrap mode.
+ * @param line line text. This may be the text of a visualline if
+ * the widget is in word wrap mode.
+ * @return StyledTextEvent that can be used to request line data
+ * for the given line.
+ */
+StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) {
+ StyledTextEvent event = null;
+ if (isListening(eventType)) {
+ event = new StyledTextEvent(content);
+ event.detail = lineOffset;
+ event.text = line;
+ event.alignment = alignment;
+ event.indent = indent;
+ event.justify = justify;
+ notifyListeners(eventType, event);
+ }
+ return event;
+}
+void sendModifyEvent(Event event) {
+ Accessible accessible = getAccessible();
+ if (event.text.length() == 0) {
+ accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start);
+ } else {
+ if (event.start == event.end) {
+ accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length());
+ } else {
+ accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start);
+ accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length());
+ }
+ }
+ notifyListeners(SWT.Modify, event);
+}
+/**
+ * Sends the specified selection event.
+ */
+void sendSelectionEvent() {
+ getAccessible().textSelectionChanged();
+ Event event = new Event();
+ event.x = selection.x;
+ event.y = selection.y;
+ notifyListeners(SWT.Selection, event);
+}
+/**
+ * Sets the alignment of the widget. The argument should be one of SWT.LEFT,
+ * SWT.CENTER or SWT.RIGHT. The alignment applies for all lines.
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setCaret(Caret caret) {
+ checkWidget ();
+ super.setCaret(caret);
+ caretDirection = SWT.NULL;
+ if (caret != null) {
+ setCaretLocation();
+ }
+}
+/**
+ * Sets the BIDI coloring mode. When true the BIDI text display
+ * algorithm is applied to segments of text that are the same
+ * color.
+ *
+ * @param mode the new coloring mode
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @deprecated use BidiSegmentListener instead.
+ */
+public void setBidiColoring(boolean mode) {
+ checkWidget();
+ bidiColoring = mode;
+}
+/**
+ * Moves the Caret to the current caret offset.
+ */
+void setCaretLocation() {
+ Point newCaretPos = getPointAtOffset(caretOffset);
+ setCaretLocation(newCaretPos, getCaretDirection());
+}
+void setCaretLocation(Point location, int direction) {
+ Caret caret = getCaret();
+ if (caret != null) {
+ boolean isDefaultCaret = caret == defaultCaret;
+ int lineHeight = renderer.getLineHeight();
+ int caretHeight = lineHeight;
+ if (!isFixedLineHeight() && isDefaultCaret) {
+ caretHeight = getBoundsAtOffset(caretOffset).height;
+ if (caretHeight != lineHeight) {
+ direction = SWT.DEFAULT;
+ }
+ }
+ int imageDirection = direction;
+ if (isMirrored()) {
+ if (imageDirection == SWT.LEFT) {
+ imageDirection = SWT.RIGHT;
+ } else if (imageDirection == SWT.RIGHT) {
+ imageDirection = SWT.LEFT;
+ }
+ }
+ if (isDefaultCaret && imageDirection == SWT.RIGHT) {
+ location.x -= (caret.getSize().x - 1);
+ }
+ if (isDefaultCaret) {
+ caret.setBounds(location.x, location.y, 0, caretHeight);
+ } else {
+ caret.setLocation(location);
+ }
+ getAccessible().textCaretMoved(getCaretOffset());
+ if (direction != caretDirection) {
+ caretDirection = direction;
+ if (isDefaultCaret) {
+ if (imageDirection == SWT.DEFAULT) {
+ defaultCaret.setImage(null);
+ } else if (imageDirection == SWT.LEFT) {
+ defaultCaret.setImage(leftCaretBitmap);
+ } else if (imageDirection == SWT.RIGHT) {
+ defaultCaret.setImage(rightCaretBitmap);
+ }
+ }
+ if (caretDirection == SWT.LEFT) {
+ BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_NON_BIDI);
+ } else if (caretDirection == SWT.RIGHT) {
+ BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI);
+ }
+ }
+ }
+ columnX = location.x;
+}
+/**
+ * Sets the caret offset.
+ *
+ * @param offset caret offset, relative to the first character in the text.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
+ * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+ *
+ */
+public void setCaretOffset(int offset) {
+ checkWidget();
+ int length = getCharCount();
+ if (length > 0 && offset != caretOffset) {
+ if (offset < 0) {
+ caretOffset = 0;
+ } else if (offset > length) {
+ caretOffset = length;
+ } else {
+ if (isLineDelimiter(offset)) {
+ // offset is inside a multi byte line delimiter. This is an
+ // illegal operation and an exception is thrown. Fixes 1GDKK3R
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ caretOffset = offset;
+ }
+ // clear the selection if the caret is moved.
+ // don't notify listeners about the selection change.
+ clearSelection(false);
+ }
+ setCaretLocation();
+}
+/**
+ * Copies the specified text range to the clipboard. The text will be placed
+ * in the clipboard in plain text format and RTF format.
+ *
+ * @param start start index of the text
+ * @param length length of text to place in clipboard
+ *
+ * @exception SWTError, see Clipboard.setContents
+ * @see org.eclipse.swt.dnd.Clipboard#setContents
+ */
+void setClipboardContent(int start, int length, int clipboardType) throws SWTError {
+ if (clipboardType == DND.SELECTION_CLIPBOARD && !(IS_MOTIF || IS_GTK)) return;
+ TextTransfer plainTextTransfer = TextTransfer.getInstance();
+ TextWriter plainTextWriter = new TextWriter(start, length);
+ String plainText = getPlatformDelimitedText(plainTextWriter);
+ Object[] data;
+ Transfer[] types;
+ if (clipboardType == DND.SELECTION_CLIPBOARD) {
+ data = new Object[]{plainText};
+ types = new Transfer[]{plainTextTransfer};
+ } else {
+ RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ RTFWriter rtfWriter = new RTFWriter(start, length);
+ String rtfText = getPlatformDelimitedText(rtfWriter);
+ data = new Object[]{rtfText, plainText};
+ types = new Transfer[]{rtfTransfer, plainTextTransfer};
+ }
+ clipboard.setContents(data, types, clipboardType);
+}
+/**
+ * Sets the content implementation to use for text storage.
+ *
+ * @param newContent StyledTextContent implementation to use for text storage.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when listener is null
+ *
+ */
+public void setContent(StyledTextContent newContent) {
+ checkWidget();
+ if (newContent == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ if (content != null) {
+ content.removeTextChangeListener(textChangeListener);
+ }
+ content = newContent;
+ content.addTextChangeListener(textChangeListener);
+ reset();
+}
+/**
+ * Sets the receiver's cursor to the cursor specified by the
+ * argument. Overridden to handle the null case since the
+ * StyledText widget uses an ibeam as its default cursor.
+ *
+ * @see org.eclipse.swt.widgets.Control#setCursor
+ */
+public void setCursor (Cursor cursor) {
+ if (cursor == null) {
+ Display display = getDisplay();
+ super.setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM));
+ } else {
+ super.setCursor(cursor);
+ }
+}
+/**
+ * Sets whether the widget implements double click mouse behavior.
+ *
+ *
+ * @param enable if true double clicking a word selects the word, if false
+ * double clicks have the same effect as regular mouse clicks.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setDoubleClickEnabled(boolean enable) {
+ checkWidget();
+ doubleClickEnabled = enable;
+}
+/**
+ * Sets whether the widget content can be edited.
+ *
+ *
+ * @param editable if true content can be edited, if false content can not be
+ * edited
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setEditable(boolean editable) {
+ checkWidget();
+ this.editable = editable;
+}
+/**
+ * Sets a new font to render text with.
+ *
+ * NOTE: Italic fonts are not supported unless they have no overhang
+ * and the same baseline as regular fonts.
+ *
+ *
+ * @param font new font
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setFont(Font font) {
+ checkWidget();
+ int oldLineHeight = renderer.getLineHeight();
+ super.setFont(font);
+ renderer.setFont(getFont(), tabLength);
+ // keep the same top line visible. fixes 5815
+ if (isFixedLineHeight()) {
+ int lineHeight = renderer.getLineHeight();
+ if (lineHeight != oldLineHeight) {
+ int vscroll = (getVerticalScrollOffset() * lineHeight / oldLineHeight) - getVerticalScrollOffset();
+ scrollVertical(vscroll, true);
+ }
+ }
+ resetCache(0, content.getLineCount());
+ claimBottomFreeSpace();
+ calculateScrollBars();
+ if (isBidiCaret()) createCaretBitmaps();
+ caretDirection = SWT.NULL;
+ setCaretLocation();
+ super.redraw();
+}
+/**
+ * @see org.eclipse.swt.widgets.Control#setForeground
+ */
+public void setForeground(Color color) {
+ checkWidget();
+ foreground = color;
+ super.setForeground(getForeground());
+ super.redraw();
+}
+/**
+ * Sets the horizontal scroll offset relative to the start of the line.
+ * Do nothing if there is no text set.
+ *
+ * NOTE: The horizontal index is reset to 0 when new text is set in the
+ * widget.
+ *
+ *
+ * @param offset horizontal scroll offset relative to the start
+ * of the line, measured in character increments starting at 0, if
+ * equal to 0 the content is not scrolled, if > 0 = the content is scrolled.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setHorizontalIndex(int offset) {
+ checkWidget();
+ if (getCharCount() == 0) {
+ return;
+ }
+ if (offset < 0) {
+ offset = 0;
+ }
+ offset *= getHorizontalIncrement();
+ // allow any value if client area width is unknown or 0.
+ // offset will be checked in resize handler.
+ // don't use isVisible since width is known even if widget
+ // is temporarily invisible
+ if (clientAreaWidth > 0) {
+ int width = renderer.getWidth();
+ // prevent scrolling if the content fits in the client area.
+ // align end of longest line with right border of client area
+ // if offset is out of range.
+ if (offset > width - clientAreaWidth) {
+ offset = Math.max(0, width - clientAreaWidth);
+ }
+ }
+ scrollHorizontal(offset - horizontalScrollOffset, true);
+}
+/**
+ * Sets the horizontal pixel offset relative to the start of the line.
+ * Do nothing if there is no text set.
+ *
+ * NOTE: The horizontal pixel offset is reset to 0 when new text
+ * is set in the widget.
+ *
+ *
+ * @param pixel horizontal pixel offset relative to the start
+ * of the line.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @since 2.0
+ */
+public void setHorizontalPixel(int pixel) {
+ checkWidget();
+ if (getCharCount() == 0) {
+ return;
+ }
+ if (pixel < 0) {
+ pixel = 0;
+ }
+ // allow any value if client area width is unknown or 0.
+ // offset will be checked in resize handler.
+ // don't use isVisible since width is known even if widget
+ // is temporarily invisible
+ if (clientAreaWidth > 0) {
+ int width = renderer.getWidth();
+ // prevent scrolling if the content fits in the client area.
+ // align end of longest line with right border of client area
+ // if offset is out of range.
+ if (pixel > width - clientAreaWidth) {
+ pixel = Math.max(0, width - clientAreaWidth);
+ }
+ }
+ scrollHorizontal(pixel - horizontalScrollOffset, true);
+}
+/**
+ * Sets the line indentation of the widget.
+ *
+ * It is the amount of blank space, in pixels, at the beginning of each line.
+ * When a line wraps in several lines only the first one is indented.
+ *
+ *
+ * @param indent the new indent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * One action can be associated with N keys. However, each key can only
+ * have one action (key:action is N:1 relation).
+ *
+ *
+ * @param key a key code defined in SWT.java or a character.
+ * Optionally ORd with a state mask. Preferred state masks are one or more of
+ * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform
+ * differences. However, there may be cases where using the specific state masks
+ * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
+ * @param action one of the predefined actions defined in ST.java.
+ * Use SWT.NULL to remove a key binding.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setKeyBinding(int key, int action) {
+ checkWidget();
+ int modifierValue = key & SWT.MODIFIER_MASK;
+ char keyChar = (char)(key & SWT.KEY_MASK);
+ if (Compatibility.isLetter(keyChar)) {
+ // make the keybinding case insensitive by adding it
+ // in its upper and lower case form
+ char ch = Character.toUpperCase(keyChar);
+ int newKey = ch | modifierValue;
+ if (action == SWT.NULL) {
+ keyActionMap.remove(new Integer(newKey));
+ } else {
+ keyActionMap.put(new Integer(newKey), new Integer(action));
+ }
+ ch = Character.toLowerCase(keyChar);
+ newKey = ch | modifierValue;
+ if (action == SWT.NULL) {
+ keyActionMap.remove(new Integer(newKey));
+ } else {
+ keyActionMap.put(new Integer(newKey), new Integer(action));
+ }
+ } else {
+ if (action == SWT.NULL) {
+ keyActionMap.remove(new Integer(key));
+ } else {
+ keyActionMap.put(new Integer(key), new Integer(action));
+ }
+ }
+}
+/**
+ * Sets the alignment of the specified lines. The argument should be one of SWT.LEFT,
+ * SWT.CENTER or SWT.RIGHT.
+ *
+ * Should not be called if a LineStyleListener has been set since the listener
+ * maintains the line attributes.
+ *
+ * All line attributes are maintained relative to the line text, not the
+ * line index that is specified in this method call.
+ * During text changes, when entire lines are inserted or removed, the line
+ * attributes that are associated with the lines after the change
+ * will "move" with their respective text. An entire line is defined as
+ * extending from the first character on a line to the last and including the
+ * line delimiter.
+ *
+ * When two lines are joined by deleting a line delimiter, the top line
+ * attributes take precedence and the attributes of the bottom line are deleted.
+ * For all other text changes line attributes will remain unchanged.
+ *
+ * @param startLine first line the alignment is applied to, 0 based
+ * @param lineCount number of lines the alignment applies to.
+ * @param alignment line alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+ *
+ * @see #setAlignment(int)
+ * @since 3.2
+ */
+public void setLineAlignment(int startLine, int lineCount, int alignment) {
+ checkWidget();
+ if (isListening(LineGetStyle)) return;
+ if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ renderer.setLineAlignment(startLine, lineCount, alignment);
+ resetCache(startLine, lineCount);
+ redrawLines(startLine, lineCount);
+ int caretLine = getCaretLine();
+ if (startLine <= caretLine && caretLine < startLine + lineCount) {
+ setCaretLocation();
+ }
+}
+/**
+ * Sets the background color of the specified lines.
+ *
+ * The background color is drawn for the width of the widget. All
+ * line background colors are discarded when setText is called.
+ * The text background color if defined in a StyleRange overlays the
+ * line background color.
+ *
+ * Should not be called if a LineBackgroundListener has been set since the
+ * listener maintains the line backgrounds.
+ *
+ * All line attributes are maintained relative to the line text, not the
+ * line index that is specified in this method call.
+ * During text changes, when entire lines are inserted or removed, the line
+ * attributes that are associated with the lines after the change
+ * will "move" with their respective text. An entire line is defined as
+ * extending from the first character on a line to the last and including the
+ * line delimiter.
+ *
+ * When two lines are joined by deleting a line delimiter, the top line
+ * attributes take precedence and the attributes of the bottom line are deleted.
+ * For all other text changes line attributes will remain unchanged.
+ *
+ *
+ * @param startLine first line the color is applied to, 0 based
+ * @param lineCount number of lines the color applies to.
+ * @param background line background color
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+ *
+ */
+public void setLineBackground(int startLine, int lineCount, Color background) {
+ checkWidget();
+ if (isListening(LineGetBackground)) return;
+ if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (background != null) {
+ renderer.setLineBackground(startLine, lineCount, background);
+ } else {
+ renderer.clearLineBackground(startLine, lineCount);
+ }
+ redrawLines(startLine, lineCount);
+}
+/**
+ * Sets the bullet of the specified lines.
+ *
+ * Should not be called if a LineStyleListener has been set since the listener
+ * maintains the line attributes.
+ *
+ * All line attributes are maintained relative to the line text, not the
+ * line index that is specified in this method call.
+ * During text changes, when entire lines are inserted or removed, the line
+ * attributes that are associated with the lines after the change
+ * will "move" with their respective text. An entire line is defined as
+ * extending from the first character on a line to the last and including the
+ * line delimiter.
+ *
+ * When two lines are joined by deleting a line delimiter, the top line
+ * attributes take precedence and the attributes of the bottom line are deleted.
+ * For all other text changes line attributes will remain unchanged.
+ *
+ *
+ * @param startLine first line the bullet is applied to, 0 based
+ * @param lineCount number of lines the bullet applies to.
+ * @param bullet line bullet
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+ * Should not be called if a LineStyleListener has been set since the listener
+ * maintains the line attributes.
+ *
+ * All line attributes are maintained relative to the line text, not the
+ * line index that is specified in this method call.
+ * During text changes, when entire lines are inserted or removed, the line
+ * attributes that are associated with the lines after the change
+ * will "move" with their respective text. An entire line is defined as
+ * extending from the first character on a line to the last and including the
+ * line delimiter.
+ *
+ * When two lines are joined by deleting a line delimiter, the top line
+ * attributes take precedence and the attributes of the bottom line are deleted.
+ * For all other text changes line attributes will remain unchanged.
+ *
+ *
+ * @param startLine first line the indent is applied to, 0 based
+ * @param lineCount number of lines the indent applies to.
+ * @param indent line indent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+ *
+ * @see #setIndent(int)
+ * @since 3.2
+ */
+public void setLineIndent(int startLine, int lineCount, int indent) {
+ checkWidget();
+ if (isListening(LineGetStyle)) return;
+ if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ renderer.setLineIndent(startLine, lineCount, indent);
+ resetCache(startLine, lineCount);
+ redrawLines(startLine, lineCount);
+ int caretLine = getCaretLine();
+ if (startLine <= caretLine && caretLine < startLine + lineCount) {
+ setCaretLocation();
+ }
+}
+/**
+ * Sets the justify of the specified lines.
+ *
+ * Should not be called if a LineStyleListener has been set since the listener
+ * maintains the line attributes.
+ *
+ * All line attributes are maintained relative to the line text, not the
+ * line index that is specified in this method call.
+ * During text changes, when entire lines are inserted or removed, the line
+ * attributes that are associated with the lines after the change
+ * will "move" with their respective text. An entire line is defined as
+ * extending from the first character on a line to the last and including the
+ * line delimiter.
+ *
+ * When two lines are joined by deleting a line delimiter, the top line
+ * attributes take precedence and the attributes of the bottom line are deleted.
+ * For all other text changes line attributes will remain unchanged.
+ *
+ *
+ * @param startLine first line the justify is applied to, 0 based
+ * @param lineCount number of lines the justify applies to.
+ * @param justify true if lines should be justified
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when the specified line range is invalid
+ *
+ * @see #setJustify(boolean)
+ * @since 3.2
+ */
+public void setLineJustify(int startLine, int lineCount, boolean justify) {
+ checkWidget();
+ if (isListening(LineGetStyle)) return;
+ if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ renderer.setLineJustify(startLine, lineCount, justify);
+ resetCache(startLine, lineCount);
+ redrawLines(startLine, lineCount);
+ int caretLine = getCaretLine();
+ if (startLine <= caretLine && caretLine < startLine + lineCount) {
+ setCaretLocation();
+ }
+}
+/**
+ * Sets the line spacing of the widget. The line spacing applies for all lines.
+ *
+ * @param lineSpacing the line spacing
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @since 3.2
+ */
+public void setLineSpacing(int lineSpacing) {
+ checkWidget();
+ if (this.lineSpacing == lineSpacing || lineSpacing < 0) return;
+ this.lineSpacing = lineSpacing;
+ setVariableLineHeight();
+ resetCache(0, content.getLineCount());
+ setCaretLocation();
+ super.redraw();
+}
+void setMargins (int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
+ checkWidget();
+ this.leftMargin = leftMargin;
+ this.topMargin = topMargin;
+ this.rightMargin = rightMargin;
+ this.bottomMargin = bottomMargin;
+ setCaretLocation();
+}
+/**
+ * Flips selection anchor based on word selection direction.
+ */
+void setMouseWordSelectionAnchor() {
+ if (mouseDoubleClick) {
+ if (caretOffset < doubleClickSelection.x) {
+ selectionAnchor = doubleClickSelection.y;
+ } else if (caretOffset > doubleClickSelection.y) {
+ selectionAnchor = doubleClickSelection.x;
+ }
+ }
+}
+/**
+ * Sets the orientation of the receiver, which must be one
+ * of the constants SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT.
+ *
+ * @param orientation new orientation style
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.1.2
+ */
+public void setOrientation(int orientation) {
+ if ((orientation & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT)) == 0) {
+ return;
+ }
+ if ((orientation & SWT.RIGHT_TO_LEFT) != 0 && (orientation & SWT.LEFT_TO_RIGHT) != 0) {
+ return;
+ }
+ if ((orientation & SWT.RIGHT_TO_LEFT) != 0 && isMirrored()) {
+ return;
+ }
+ if ((orientation & SWT.LEFT_TO_RIGHT) != 0 && !isMirrored()) {
+ return;
+ }
+ if (!BidiUtil.setOrientation(handle, orientation)) {
+ return;
+ }
+ isMirrored = (orientation & SWT.RIGHT_TO_LEFT) != 0;
+ caretDirection = SWT.NULL;
+ setCaretLocation();
+ keyActionMap.clear();
+ createKeyBindings();
+ super.redraw();
+}
+/**
+ * Adjusts the maximum and the page size of the scroll bars to
+ * reflect content width/length changes.
+ *
+ * @param vertical indicates if the vertical scrollbar also needs to be set
+ */
+void setScrollBars(boolean vertical) {
+ int inactive = 1;
+ if (vertical || !isFixedLineHeight()) {
+ ScrollBar verticalBar = getVerticalBar();
+ if (verticalBar != null) {
+ int maximum = renderer.getHeight();
+ // only set the real values if the scroll bar can be used
+ // (ie. because the thumb size is less than the scroll maximum)
+ // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92
+ if (clientAreaHeight < maximum) {
+ verticalBar.setValues(
+ verticalBar.getSelection(),
+ verticalBar.getMinimum(),
+ maximum,
+ clientAreaHeight, // thumb size
+ verticalBar.getIncrement(),
+ clientAreaHeight); // page size
+ } else if (verticalBar.getThumb() != inactive || verticalBar.getMaximum() != inactive) {
+ verticalBar.setValues(
+ verticalBar.getSelection(),
+ verticalBar.getMinimum(),
+ inactive,
+ inactive,
+ verticalBar.getIncrement(),
+ inactive);
+ }
+ }
+ }
+ ScrollBar horizontalBar = getHorizontalBar();
+ if (horizontalBar != null && horizontalBar.getVisible()) {
+ int maximum = renderer.getWidth();
+ // only set the real values if the scroll bar can be used
+ // (ie. because the thumb size is less than the scroll maximum)
+ // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92
+ if (clientAreaWidth < maximum) {
+ horizontalBar.setValues(
+ horizontalBar.getSelection(),
+ horizontalBar.getMinimum(),
+ maximum,
+ clientAreaWidth - leftMargin - rightMargin, // thumb size
+ horizontalBar.getIncrement(),
+ clientAreaWidth - leftMargin - rightMargin); // page size
+ } else if (horizontalBar.getThumb() != inactive || horizontalBar.getMaximum() != inactive) {
+ horizontalBar.setValues(
+ horizontalBar.getSelection(),
+ horizontalBar.getMinimum(),
+ inactive,
+ inactive,
+ horizontalBar.getIncrement(),
+ inactive);
+ }
+ }
+}
+/**
+ * Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start).
+ *
+ * @param start new caret position
+ * @see #setSelection(int,int)
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
+ * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+ *
+ */
+public void setSelection(int start) {
+ // checkWidget test done in setSelectionRange
+ setSelection(start, start);
+}
+/**
+ * Sets the selection and scrolls it into view.
+ *
+ * Indexing is zero based. Text selections are specified in terms of
+ * caret positions. In a text widget that contains N characters, there are
+ * N+1 caret positions, ranging from 0..N
+ *
+ *
+ * @param point x=selection start offset, y=selection end offset
+ * The caret will be placed at the selection start when x > y.
+ * @see #setSelection(int,int)
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when point is null
+ *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
+ * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+ *
+ */
+public void setSelection(Point point) {
+ checkWidget();
+ if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ setSelection(point.x, point.y);
+}
+/**
+ * Sets the receiver's selection 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
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @since 2.1
+ */
+public void setSelectionBackground (Color color) {
+ checkWidget ();
+ if (color != null) {
+ if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ selectionBackground = color;
+ super.redraw();
+}
+/**
+ * Sets the receiver's selection 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
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @since 2.1
+ */
+public void setSelectionForeground (Color color) {
+ checkWidget ();
+ if (color != null) {
+ if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ selectionForeground = color;
+ super.redraw();
+}
+/**
+ * Sets the selection and scrolls it into view.
+ *
+ * Indexing is zero based. Text selections are specified in terms of
+ * caret positions. In a text widget that contains N characters, there are
+ * N+1 caret positions, ranging from 0..N
+ *
+ *
+ * @param start selection start offset. The caret will be placed at the
+ * selection start when start > end.
+ * @param end selection end offset
+ * @see #setSelectionRange(int,int)
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
+ * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+ *
+ */
+public void setSelection(int start, int end) {
+ setSelectionRange(start, end - start);
+ showSelection();
+}
+/**
+ * Sets the selection.
+ *
+ * The new selection may not be visible. Call showSelection to scroll
+ * the selection into view.
+ *
+ *
+ * @param start offset of the first selected character, start >= 0 must be true.
+ * @param length number of characters to select, 0 <= start + length
+ * <= getCharCount() must be true.
+ * A negative length places the caret at the selection start.
+ * @param sendEvent a Selection event is sent when set to true and when
+ * the selection is reset.
+ */
+void setSelection(int start, int length, boolean sendEvent) {
+ int end = start + length;
+ if (start > end) {
+ int temp = end;
+ end = start;
+ start = temp;
+ }
+ // is the selection range different or is the selection direction
+ // different?
+ if (selection.x != start || selection.y != end ||
+ (length > 0 && selectionAnchor != selection.x) ||
+ (length < 0 && selectionAnchor != selection.y)) {
+ clearSelection(sendEvent);
+ if (length < 0) {
+ selectionAnchor = selection.y = end;
+ caretOffset = selection.x = start;
+ } else {
+ selectionAnchor = selection.x = start;
+ caretOffset = selection.y = end;
+ }
+ internalRedrawRange(selection.x, selection.y - selection.x);
+ }
+}
+/**
+ * Sets the selection.
+ *
+ * The new selection may not be visible. Call showSelection to scroll the selection
+ * into view. A negative length places the caret at the visual start of the selection.
+ *
+ *
+ * @param start offset of the first selected character
+ * @param length number of characters to select
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
+ * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+ *
+ */
+public void setSelectionRange(int start, int length) {
+ checkWidget();
+ int contentLength = getCharCount();
+ start = Math.max(0, Math.min (start, contentLength));
+ int end = start + length;
+ if (end < 0) {
+ length = -start;
+ } else {
+ if (end > contentLength) length = contentLength - start;
+ }
+ if (isLineDelimiter(start) || isLineDelimiter(start + length)) {
+ // the start offset or end offset of the selection range is inside a
+ // multi byte line delimiter. This is an illegal operation and an exception
+ // is thrown. Fixes 1GDKK3R
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ setSelection(start, length, false);
+ setCaretLocation();
+}
+/**
+ * Adds the specified style.
+ *
+ * The new style overwrites existing styles for the specified range.
+ * Existing style ranges are adjusted if they partially overlap with
+ * the new style. To clear an individual style, call setStyleRange
+ * with a StyleRange that has null attributes.
+ *
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ *
+ * @param range StyleRange object containing the style information.
+ * Overwrites the old style in the given range. May be null to delete
+ * all styles.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())
+ *
+ */
+public void setStyleRange(StyleRange range) {
+ checkWidget();
+ if (isListening(LineGetStyle)) return;
+ if (range != null) {
+ if (range.isUnstyled()) {
+ setStyleRanges(range.start, range.length, null, null, false);
+ } else {
+ setStyleRanges(range.start, 0, null, new StyleRange[]{range}, false);
+ }
+ } else {
+ setStyleRanges(0, 0, null, null, true);
+ }
+}
+/**
+ * Clears the styles in the range specified by start and
+ * length and adds the new styles.
+ *
+ * The ranges array contains start and length pairs. Each pair refers to
+ * the corresponding style in the styles array. For example, the pair
+ * that starts at ranges[n] with length ranges[n+1] uses the style
+ * at styles[n/2]. The range fields within each StyleRange are ignored.
+ * If ranges or styles is null, the specified range is cleared.
+ *
+ * Note: It is expected that the same instance of a StyleRange will occur
+ * multiple times within the styles array, reducing memory usage.
+ *
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ *
+ * @param start offset of first character where styles will be deleted
+ * @param length length of the range to delete styles in
+ * @param ranges the array of ranges. The ranges must not overlap and must be in order.
+ * @param styles the array of StyleRanges. The range fields within the StyleRange are unused.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when an element in the styles array is null
+ *
ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
+ *
ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
+ *
ERROR_INVALID_RANGE when a range overlaps
+ *
+ *
+ * @since 3.2
+ */
+public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) {
+ checkWidget();
+ if (isListening(LineGetStyle)) return;
+ if (ranges == null || styles == null) {
+ setStyleRanges(start, length, null, null, false);
+ } else {
+ setStyleRanges(start, length, ranges, styles, false);
+ }
+}
+/**
+ * Sets styles to be used for rendering the widget content.
+ *
+ * All styles in the widget will be replaced with the given set of ranges and styles.
+ * The ranges array contains start and length pairs. Each pair refers to
+ * the corresponding style in the styles array. For example, the pair
+ * that starts at ranges[n] with length ranges[n+1] uses the style
+ * at styles[n/2]. The range fields within each StyleRange are ignored.
+ * If either argument is null, the styles are cleared.
+ *
+ * Note: It is expected that the same instance of a StyleRange will occur
+ * multiple times within the styles array, reducing memory usage.
+ *
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ *
+ * @param ranges the array of ranges. The ranges must not overlap and must be in order.
+ * @param styles the array of StyleRanges. The range fields within the StyleRange are unused.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when an element in the styles array is null
+ *
ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)
+ *
ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)
+ *
ERROR_INVALID_RANGE when a range overlaps
+ *
+ *
+ * @since 3.2
+ */
+public void setStyleRanges(int[] ranges, StyleRange[] styles) {
+ checkWidget();
+ if (isListening(LineGetStyle)) return;
+ if (ranges == null || styles == null) {
+ setStyleRanges(0, 0, null, null, true);
+ } else {
+ setStyleRanges(0, 0, ranges, styles, true);
+ }
+}
+void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles, boolean reset) {
+ int charCount = content.getCharCount();
+ int end = start + length;
+ if (start > end || start < 0) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ if (styles != null) {
+ if (end > charCount) {
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+ }
+ if (ranges != null) {
+ if (ranges.length != styles.length << 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int lastOffset = 0;
+ boolean variableHeight = false;
+ for (int i = 0; i < styles.length; i ++) {
+ if (styles[i] == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int rangeStart, rangeLength;
+ if (ranges != null) {
+ rangeStart = ranges[i << 1];
+ rangeLength = ranges[(i << 1) + 1];
+ } else {
+ rangeStart = styles[i].start;
+ rangeLength = styles[i].length;
+ }
+ if (rangeLength < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (lastOffset > rangeStart) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ variableHeight |= styles[i].isVariableHeight();
+ lastOffset = rangeStart + rangeLength;
+ }
+ if (variableHeight) setVariableLineHeight();
+ }
+ int rangeStart = start, rangeEnd = end;
+ if (styles != null && styles.length > 0) {
+ if (ranges != null) {
+ rangeStart = ranges[0];
+ rangeEnd = ranges[ranges.length - 2] + ranges[ranges.length - 1];
+ } else {
+ rangeStart = styles[0].start;
+ rangeEnd = styles[styles.length - 1].start + styles[styles.length - 1].length;
+ }
+ }
+ int lastLineBottom = 0;
+ if (!isFixedLineHeight() && !reset) {
+ int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
+ int partialTopIndex = getPartialTopIndex();
+ int partialBottomIndex = getPartialBottomIndex();
+ if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
+ lastLineBottom = getLinePixel(lineEnd + 1);
+ }
+ }
+ if (reset) {
+ renderer.setStyleRanges(null, null);
+ } else {
+ renderer.updateRanges(start, length, length);
+ }
+ if (styles != null && styles.length > 0) {
+ renderer.setStyleRanges(ranges, styles);
+ }
+ if (reset) {
+ resetCache(0, content.getLineCount());
+ super.redraw();
+ } else {
+ int lineStart = content.getLineAtOffset(Math.min(start, rangeStart));
+ int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
+ resetCache(lineStart, lineEnd - lineStart + 1);
+ int partialTopIndex = getPartialTopIndex();
+ int partialBottomIndex = getPartialBottomIndex();
+ if (!(lineStart > partialBottomIndex || lineEnd < partialTopIndex)) {
+ int y = 0;
+ int height = clientAreaHeight;
+ if (partialTopIndex <= lineStart && lineStart <= partialBottomIndex) {
+ int lineTop = Math.max(y, getLinePixel(lineStart));
+ y = lineTop;
+ height -= lineTop;
+ }
+ if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
+ int newLastLineBottom = getLinePixel(lineEnd + 1);
+ if (!isFixedLineHeight()) {
+ scrollText(lastLineBottom, newLastLineBottom);
+ }
+ height = newLastLineBottom - y;
+ }
+ super.redraw(0, y, clientAreaWidth, height, false);
+ }
+ }
+ setCaretLocation();
+}
+/**
+ * Sets styles to be used for rendering the widget content. All styles
+ * in the widget will be replaced with the given set of styles.
+ *
+ * Note: Because a StyleRange includes the start and length, the
+ * same instance cannot occur multiple times in the array of styles.
+ * If the same style attributes, such as font and color, occur in
+ * multiple StyleRanges, setStyleRanges(int[], StyleRange[])
+ * can be used to share styles and reduce memory usage.
+ *
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ *
+ *
+ * @param ranges StyleRange objects containing the style information.
+ * The ranges should not overlap. The style rendering is undefined if
+ * the ranges do overlap. Must not be null. The styles need to be in order.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when the list of ranges is null
+ *
ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setTabs(int tabs) {
+ checkWidget();
+ tabLength = tabs;
+ renderer.setFont(null, tabs);
+ if (caretOffset > 0) {
+ caretOffset = 0;
+ showCaret();
+ clearSelection(false);
+ }
+ resetCache(0, content.getLineCount());
+ super.redraw();
+}
+/**
+ * Sets the widget content.
+ * If the widget has the SWT.SINGLE style and "text" contains more than
+ * one line, only the first line is rendered but the text is stored
+ * unchanged. A subsequent call to getText will return the same text
+ * that was set.
+ *
+ * Note: Only a single line of text should be set when the SWT.SINGLE
+ * style is used.
+ *
+ *
+ * @param text new widget content. Replaces existing content. Line styles
+ * that were set using StyledText API are discarded. The
+ * current selection is also discarded.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT when string is null
+ *
+ */
+public void setText(String text) {
+ checkWidget();
+ if (text == null) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ Event event = new Event();
+ event.start = 0;
+ event.end = getCharCount();
+ event.text = text;
+ event.doit = true;
+ notifyListeners(SWT.Verify, event);
+ if (event.doit) {
+ StyledTextEvent styledTextEvent = null;
+ if (isListening(ExtendedModify)) {
+ styledTextEvent = new StyledTextEvent(content);
+ styledTextEvent.start = event.start;
+ styledTextEvent.end = event.start + event.text.length();
+ styledTextEvent.text = content.getTextRange(event.start, event.end - event.start);
+ }
+ content.setText(event.text);
+ sendModifyEvent(event);
+ if (styledTextEvent != null) {
+ notifyListeners(ExtendedModify, styledTextEvent);
+ }
+ }
+}
+/**
+ * Sets the text limit to the specified number of characters.
+ *
+ * The text limit specifies the amount of text that
+ * the user can type into the widget.
+ *
+ *
+ * @param limit the new text limit.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_CANNOT_BE_ZERO when limit is 0
+ *
+ */
+public void setTextLimit(int limit) {
+ checkWidget();
+ if (limit == 0) {
+ SWT.error(SWT.ERROR_CANNOT_BE_ZERO);
+ }
+ textLimit = limit;
+}
+/**
+ * Sets the top index. Do nothing if there is no text set.
+ *
+ * The top index is the index of the line that is currently at the top
+ * of the widget. The top index changes when the widget is scrolled.
+ * Indexing starts from zero.
+ * Note: The top index is reset to 0 when new text is set in the widget.
+ *
+ *
+ * @param topIndex new top index. Must be between 0 and
+ * getLineCount() - fully visible lines per page. If no lines are fully
+ * visible the maximum value is getLineCount() - 1. An out of range
+ * index will be adjusted accordingly.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setTopIndex(int topIndex) {
+ checkWidget();
+ if (getCharCount() == 0) {
+ return;
+ }
+ int lineCount = content.getLineCount(), pixel;
+ if (isFixedLineHeight()) {
+ int pageSize = Math.max(1, Math.min(lineCount, getLineCountWhole()));
+ if (topIndex < 0) {
+ topIndex = 0;
+ } else if (topIndex > lineCount - pageSize) {
+ topIndex = lineCount - pageSize;
+ }
+ pixel = getLinePixel(topIndex);
+ } else {
+ topIndex = Math.max(0, Math.min(lineCount - 1, topIndex));
+ pixel = getLinePixel(topIndex);
+ if (pixel > 0) {
+ pixel = getAvailableHeightBellow(pixel);
+ } else {
+ pixel = getAvailableHeightAbove(pixel);
+ }
+ }
+ scrollVertical(pixel, true);
+}
+/**
+ * Sets the top pixel offset. Do nothing if there is no text set.
+ *
+ * The top pixel offset is the vertical pixel offset of the widget. The
+ * widget is scrolled so that the given pixel position is at the top.
+ * The top index is adjusted to the corresponding top line.
+ * Note: The top pixel is reset to 0 when new text is set in the widget.
+ *
+ *
+ * @param pixel new top pixel offset. Must be between 0 and
+ * (getLineCount() - visible lines per page) / getLineHeight()). An out
+ * of range offset will be adjusted accordingly.
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * This overrides the creation style bit SWT.WRAP.
+ *
+ *
+ * @param wrap true=widget wraps lines, false=widget does not wrap lines
+ * @since 2.0
+ */
+public void setWordWrap(boolean wrap) {
+ checkWidget();
+ if ((getStyle() & SWT.SINGLE) != 0) return;
+ if (wordWrap == wrap) return;
+ wordWrap = wrap;
+ setVariableLineHeight();
+ resetCache(0, content.getLineCount());
+ horizontalScrollOffset = 0;
+ ScrollBar horizontalBar = getHorizontalBar();
+ if (horizontalBar != null) {
+ horizontalBar.setVisible(!wordWrap);
+ }
+ setScrollBars(true);
+ setCaretLocation();
+ super.redraw();
+}
+/**
+ * Scrolls the specified location into view.
+ *
+ * @param x the x coordinate that should be made visible.
+ * @param line the line that should be made visible. Relative to the
+ * first line in the document.
+ * @return
+ * true=the widget was scrolled to make the specified location visible.
+ * false=the specified location is already visible, the widget was
+ * not scrolled.
+ */
+boolean showLocation(Rectangle rect) {
+ int clientAreaWidth = this.clientAreaWidth - leftMargin - rightMargin;
+ int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin;
+ boolean scrolled = false;
+ if (rect.y <= topMargin) {
+ scrolled = scrollVertical(rect.y - topMargin, true);
+ } else if (rect.y + rect.height > clientAreaHeight) {
+ scrolled = scrollVertical(rect.y + rect.height - clientAreaHeight, true);
+ }
+ if (clientAreaWidth > 0) {
+ // always make 1/4 of a page visible
+ if (rect.x < leftMargin) {
+ int scrollWidth = Math.max(leftMargin - rect.x, clientAreaWidth / 4);
+ int maxScroll = horizontalScrollOffset;
+ scrolled = scrollHorizontal(-Math.min(maxScroll, scrollWidth), true);
+ } else if (rect.x + rect.width > clientAreaWidth) {
+ int scrollWidth = Math.max(rect.x + rect.width - clientAreaWidth, clientAreaWidth / 4);
+ int maxScroll = renderer.getWidth() - horizontalScrollOffset - this.clientAreaWidth;
+ scrolled = scrollHorizontal(Math.min(maxScroll, scrollWidth), true);
+ }
+ }
+ return scrolled;
+}
+/**
+ * Sets the caret location and scrolls the caret offset into view.
+ */
+void showCaret() {
+ Rectangle bounds = getBoundsAtOffset(caretOffset);
+ if (!showLocation(bounds)) {
+ setCaretLocation();
+ }
+}
+/**
+ * Scrolls the selection into view.
+ *
+ * The end of the selection will be scrolled into view.
+ * Note that if a right-to-left selection exists, the end of the selection is
+ * the visual beginning of the selection (i.e., where the caret is located).
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void showSelection() {
+ checkWidget();
+ // is selection from right-to-left?
+ boolean rightToLeft = caretOffset == selection.x;
+ int startOffset, endOffset;
+ if (rightToLeft) {
+ startOffset = selection.y;
+ endOffset = selection.x;
+ } else {
+ startOffset = selection.x;
+ endOffset = selection.y;
+ }
+
+ Rectangle startBounds = getBoundsAtOffset(startOffset);
+ Rectangle endBounds = getBoundsAtOffset(endOffset);
+
+ // can the selection be fully displayed within the widget's visible width?
+ int w = clientAreaWidth;
+ boolean selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w;
+ if (selectionFits) {
+ // show as much of the selection as possible by first showing
+ // the start of the selection
+ if (showLocation(startBounds)) {
+ // endX value could change if showing startX caused a scroll to occur
+ endBounds = getBoundsAtOffset(endOffset);
+ }
+ showLocation(endBounds);
+ } else {
+ // just show the end of the selection since the selection start
+ // will not be visible
+ showLocation(endBounds);
+ }
+}
+/**
+ * Updates the selection and caret position depending on the text change.
+ *
+ * If the selection intersects with the replaced text, the selection is
+ * reset and the caret moved to the end of the new text.
+ * If the selection is behind the replaced text it is moved so that the
+ * same text remains selected. If the selection is before the replaced text
+ * it is left unchanged.
+ *
+ *
+ * @param startOffset offset of the text change
+ * @param replacedLength length of text being replaced
+ * @param newLength length of new text
+ */
+void updateSelection(int startOffset, int replacedLength, int newLength) {
+ if (selection.y <= startOffset) {
+ // selection ends before text change
+ return;
+ }
+ if (selection.x < startOffset) {
+ // clear selection fragment before text change
+ internalRedrawRange(selection.x, startOffset - selection.x);
+ }
+ if (selection.y > startOffset + replacedLength && selection.x < startOffset + replacedLength) {
+ // clear selection fragment after text change.
+ // do this only when the selection is actually affected by the
+ // change. Selection is only affected if it intersects the change (1GDY217).
+ int netNewLength = newLength - replacedLength;
+ int redrawStart = startOffset + newLength;
+ internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart);
+ }
+ if (selection.y > startOffset && selection.x < startOffset + replacedLength) {
+ // selection intersects replaced text. set caret behind text change
+ setSelection(startOffset + newLength, 0, true);
+ } else {
+ // move selection to keep same text selected
+ setSelection(selection.x + newLength - replacedLength, selection.y - selection.x, true);
+ }
+ setCaretLocation();
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextContent.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextContent.java
new file mode 100644
index 00000000000..7d0135b78c5
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextContent.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+/**
+ * Clients may implement the StyledTextContent interface to provide a
+ * custom store for the StyledText widget content. The StyledText widget
+ * interacts with its StyledTextContent in order to access and update
+ * the text that is being displayed and edited in the widget.
+ * A custom content implementation can be set in the widget using the
+ * StyledText.setContent API.
+ */
+public interface StyledTextContent {
+
+/**
+ * Called by StyledText to add itself as an Observer to content changes.
+ * See TextChangeListener for a description of the listener methods that
+ * are called when text changes occur.
+ *
+ */
+public void addTextChangeListener(TextChangeListener listener);
+
+/**
+ * Return the number of characters in the content.
+ *
+ *
+ * @return the number of characters in the content.
+ */
+public int getCharCount();
+
+/**
+ * Return the line at the given line index without delimiters.
+ *
+ *
+ * @param lineIndex index of the line to return. Does not include
+ * delimiters of preceding lines. Index 0 is the first line of the
+ * content.
+ * @return the line text without delimiters
+ */
+public String getLine(int lineIndex);
+
+/**
+ * Return the line index at the given character offset.
+ *
+ *
+ * @param offset offset of the line to return. The first character of the
+ * document is at offset 0. An offset of getLength() is valid and should
+ * answer the number of lines.
+ * @return the line index. The first line is at index 0. If the character
+ * at offset is a delimiter character, answer the line index of the line
+ * that is delimited.
+ * For example, if text = "\r\n\r\n", and delimiter = "\r\n", then:
+ *
+ *
getLineAtOffset(0) == 0
+ *
getLineAtOffset(1) == 0
+ *
getLineAtOffset(2) == 1
+ *
getLineAtOffset(3) == 1
+ *
getLineAtOffset(4) == 2
+ *
+ */
+public int getLineAtOffset(int offset);
+
+/**
+ * Return the number of lines. Should answer 1 when no text is specified.
+ * The StyledText widget relies on this behavior for drawing the cursor.
+ *
+ *
+ * @return the number of lines. For example:
+ *
+ *
text value ==> getLineCount
+ *
null ==> 1
+ *
"" ==> 1
+ *
"a\n" ==> 2
+ *
"\n\n" ==> 3
+ *
+ */
+public int getLineCount();
+
+/**
+ * Return the line delimiter that should be used by the StyledText
+ * widget when inserting new lines. New lines entered using key strokes
+ * and paste operations use this line delimiter.
+ * Implementors may use System.getProperty("line.separator") to return
+ * the platform line delimiter.
+ *
+ *
+ * @return the line delimiter that should be used by the StyledText widget
+ * when inserting new lines.
+ */
+public String getLineDelimiter();
+
+/**
+ * Return the character offset of the first character of the given line.
+ *
+ * NOTE: When there is no text (i.e., no lines), getOffsetAtLine(0)
+ * is a valid call that should return 0.
+ *
+ *
+ * @param lineIndex index of the line. The first line is at index 0.
+ * @return offset offset of the first character of the line. The first
+ * character of the document is at offset 0. The return value should
+ * include line delimiters.
+ * For example, if text = "\r\ntest\r\n" and delimiter = "\r\n", then:
+ *
+ *
getOffsetAtLine(0) == 0
+ *
getOffsetAtLine(1) == 2
+ *
getOffsetAtLine(2) == 8
+ *
+ */
+public int getOffsetAtLine(int lineIndex);
+
+/**
+ * Returns a string representing the content at the given range.
+ *
+ *
+ * @param start the start offset of the text to return. Offset 0 is the
+ * first character of the document.
+ * @param length the length of the text to return
+ * @return the text at the given range
+ */
+public String getTextRange(int start, int length);
+
+/**
+ * Remove the specified text changed listener.
+ *
+ */
+public void removeTextChangeListener(TextChangeListener listener);
+
+/**
+ * Replace the text with "newText" starting at position "start"
+ * for a length of "replaceLength".
+ *
+ * Implementors have to notify the TextChangeListeners that were added
+ * using addTextChangeListener before and after the content
+ * is changed. A TextChangingEvent has to be sent to the
+ * textChanging method before the content is changed and a
+ * TextChangedEvent has to be sent to the textChanged method
+ * after the content has changed.
+ * The text change that occurs after the TextChangingEvent
+ * has been sent has to be consistent with the data provided in the
+ * TextChangingEvent.
+ * This data will be cached by the widget and will be used when the
+ * TextChangedEvent is received.
+ *
+ * The TextChangingEvent should be set as follows:
+ *
+ *
event.start = start of the replaced text
+ *
event.newText = text that is going to be inserted or empty String
+ * if no text will be inserted
+ *
event.replaceCharCount = length of text that is going to be replaced
+ *
event.newCharCount = length of text that is going to be inserted
+ *
event.replaceLineCount = number of lines that are going to be replaced
+ *
event.newLineCount = number of new lines that are going to be inserted
+ *
+ * NOTE: newLineCount is the number of inserted lines and replaceLineCount
+ * is the number of deleted lines based on the change that occurs visually.
+ * For example:
+ *
+ *
+ *
+ * @param start start offset of text to replace, none of the offsets include
+ * delimiters of preceding lines, offset 0 is the first character of the
+ * document
+ * @param replaceLength length of text to replace
+ * @param text text to replace
+ * @see TextChangeListener
+ */
+public void replaceTextRange(int start, int replaceLength, String text);
+
+/**
+ * Set text to "text".
+ * Implementors have to send a TextChangedEvent to the
+ * textSet method of the TextChangeListeners that were added using
+ * addTextChangeListener.
+ *
+ *
+ * @param text the new text
+ * @see TextChangeListener
+ */
+public void setText(String text);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextEvent.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextEvent.java
new file mode 100644
index 00000000000..30e70dde4f9
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextEvent.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ *
+ */
+class StyledTextEvent extends Event {
+ // used by LineStyleEvent
+ int[] ranges;
+ StyleRange[] styles;
+ int alignment;
+ int indent;
+ boolean justify;
+ Bullet bullet;
+ int bulletIndex;
+ // used by LineBackgroundEvent
+ Color lineBackground;
+ // used by BidiSegmentEvent
+ int[] segments;
+ // used by TextChangedEvent
+ int replaceCharCount;
+ int newCharCount;
+ int replaceLineCount;
+ int newLineCount;
+ // used by PaintObjectEvent
+ int x;
+ int y;
+ int ascent;
+ int descent;
+ GC gc;
+ StyleRange style;
+
+StyledTextEvent (StyledTextContent content) {
+ super();
+ data = content;
+}
+}
+
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextListener.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextListener.java
new file mode 100644
index 00000000000..c87e5b229ab
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextListener.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.internal.SWTEventListener;
+
+class StyledTextListener extends TypedListener {
+/**
+ */
+StyledTextListener(SWTEventListener listener) {
+ super(listener);
+}
+/**
+ * Process StyledText events by invoking the event's handler.
+ */
+public void handleEvent(Event e) {
+ TextChangedEvent textChangedEvent;
+
+ switch (e.type) {
+ case StyledText.ExtendedModify:
+ ExtendedModifyEvent extendedModifyEvent = new ExtendedModifyEvent((StyledTextEvent) e);
+ ((ExtendedModifyListener) eventListener).modifyText(extendedModifyEvent);
+ break;
+ case StyledText.LineGetBackground:
+ LineBackgroundEvent lineBgEvent = new LineBackgroundEvent((StyledTextEvent) e);
+ ((LineBackgroundListener) eventListener).lineGetBackground(lineBgEvent);
+ ((StyledTextEvent) e).lineBackground = lineBgEvent.lineBackground;
+ break;
+ case StyledText.LineGetSegments:
+ BidiSegmentEvent segmentEvent = new BidiSegmentEvent((StyledTextEvent) e);
+ ((BidiSegmentListener) eventListener).lineGetSegments(segmentEvent);
+ ((StyledTextEvent) e).segments = segmentEvent.segments;
+ break;
+ case StyledText.LineGetStyle:
+ LineStyleEvent lineStyleEvent = new LineStyleEvent((StyledTextEvent) e);
+ ((LineStyleListener) eventListener).lineGetStyle(lineStyleEvent);
+ ((StyledTextEvent) e).ranges = lineStyleEvent.ranges;
+ ((StyledTextEvent) e).styles = lineStyleEvent.styles;
+ ((StyledTextEvent) e).alignment = lineStyleEvent.alignment;
+ ((StyledTextEvent) e).indent = lineStyleEvent.indent;
+ ((StyledTextEvent) e).justify = lineStyleEvent.justify;
+ ((StyledTextEvent) e).bullet = lineStyleEvent.bullet;
+ ((StyledTextEvent) e).bulletIndex = lineStyleEvent.bulletIndex;
+ break;
+ case StyledText.PaintObject:
+ PaintObjectEvent paintObjectEvent = new PaintObjectEvent((StyledTextEvent) e);
+ ((PaintObjectListener) eventListener).paintObject(paintObjectEvent);
+ break;
+ case StyledText.VerifyKey:
+ VerifyEvent verifyEvent = new VerifyEvent(e);
+ ((VerifyKeyListener) eventListener).verifyKey(verifyEvent);
+ e.doit = verifyEvent.doit;
+ break;
+ case StyledText.TextChanged:
+ textChangedEvent = new TextChangedEvent((StyledTextContent) e.data);
+ ((TextChangeListener) eventListener).textChanged(textChangedEvent);
+ break;
+ case StyledText.TextChanging:
+ TextChangingEvent textChangingEvent = new TextChangingEvent((StyledTextContent) e.data, (StyledTextEvent) e);
+ ((TextChangeListener) eventListener).textChanging(textChangingEvent);
+ break;
+ case StyledText.TextSet:
+ textChangedEvent = new TextChangedEvent((StyledTextContent) e.data);
+ ((TextChangeListener) eventListener).textSet(textChangedEvent);
+ break;
+ }
+}
+}
+
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextPrintOptions.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextPrintOptions.java
new file mode 100644
index 00000000000..794cf0c33b2
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextPrintOptions.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+/**
+ * Use StyledTextPrintOptions to specify printing options for the
+ * StyledText.print(Printer, StyledTextPrintOptions) API.
+ *
+ * The following example prints a right aligned page number in the footer,
+ * sets the job name to "Example" and prints line background colors but no other
+ * formatting:
+ *
+ * @since 2.1
+ */
+public class StyledTextPrintOptions {
+ /**
+ * Page number placeholder constant for use in header
+ * and footer. Value is <page>
+ */
+ public static final String PAGE_TAG = "";
+ /**
+ * Separator constant for use in header and
+ * footer. Value is \t
+ */
+ public static final String SEPARATOR = "\t";
+ /**
+ * Formatted text to print in the header of each page.
+ *
"left '\t' center '\t' right"
+ *
left, center, right = <page> | #CDATA
+ *
Header and footer are defined as three separate regions for arbitrary
+ * text or the page number placeholder <page>
+ * (StyledTextPrintOptions.PAGE_TAG). The three regions are
+ * left aligned, centered and right aligned. They are separated by a tab
+ * character (StyledTextPrintOptions.SEPARATOR).
+ */
+ public String header = null;
+ /**
+ * Formatted text to print in the footer of each page.
+ *
"left '\t' center '\t' right"
+ *
left, center, right = <page> | #CDATA
+ *
Header and footer are defined as three separate regions for arbitrary
+ * text or the page number placeholder <page>
+ * (StyledTextPrintOptions.PAGE_TAG). The three regions are
+ * left aligned, centered and right aligned. They are separated by a tab
+ * character (StyledTextPrintOptions.SEPARATOR).
+ */
+ public String footer = null;
+ /**
+ * Name of the print job.
+ */
+ public String jobName = null;
+
+ /**
+ * Print the text foreground color. Default value is false.
+ */
+ public boolean printTextForeground = false;
+ /**
+ * Print the text background color. Default value is false.
+ */
+ public boolean printTextBackground = false;
+ /**
+ * Print the font styles. Default value is false.
+ */
+ public boolean printTextFontStyle = false;
+ /**
+ * Print the line background color. Default value is false.
+ */
+ public boolean printLineBackground = false;
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextRenderer.java
new file mode 100644
index 00000000000..966feaf1609
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/swing/org/eclipse/swt/custom/StyledTextRenderer.java
@@ -0,0 +1,1480 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.custom;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * A StyledTextRenderer renders the content of a StyledText widget.
+ * This class can be used to render to the display or to a printer.
+ */
+class StyledTextRenderer {
+ Device device;
+ StyledText styledText;
+ StyledTextContent content;
+
+ /* Font info */
+ Font regularFont, boldFont, italicFont, boldItalicFont;
+ int tabWidth;
+ int ascent, descent;
+ int lineEndSpaceWidth;
+ int averageCharWidth;
+
+ /* Line data */
+ int topIndex = -1;
+ TextLayout[] layouts;
+ int lineCount;
+ int[] lineWidth;
+ int[] lineHeight;
+ LineInfo[] lines;
+ int maxWidth;
+ int maxWidthLineIndex;
+ boolean idleRunning;
+
+ /* Bullet */
+ Bullet[] bullets;
+ int[] bulletsIndices;
+ int[] redrawLines;
+
+ /* Style data */
+ int[] ranges;
+ int styleCount;
+ StyleRange[] styles;
+ StyleRange[] stylesSet;
+ int stylesSetCount = 0;
+ final static int BULLET_MARGIN = 8;
+
+ final static boolean COMPACT_STYLES = true;
+ final static boolean MERGE_STYLES = true;
+
+ final static int GROW = 32;
+ final static int IDLE_TIME = 50;
+ final static int CACHE_SIZE = 128;
+
+ final static int BACKGROUND = 1 << 0;
+ final static int ALIGNMENT = 1 << 1;
+ final static int INDENT = 1 << 2;
+ final static int JUSTIFY = 1 << 3;
+ final static int SEGMENTS = 1 << 5;
+
+ static class LineInfo {
+ int flags;
+ Color background;
+ int alignment;
+ int indent;
+ boolean justify;
+ int[] segments;
+
+ public LineInfo() {
+ }
+ public LineInfo(LineInfo info) {
+ flags = info.flags;
+ background = info.background;
+ alignment = info.alignment;
+ indent = info.indent;
+ justify = info.justify;
+ segments = info.segments;
+ }
+ }
+
+StyledTextRenderer(Device device, StyledText styledText) {
+ this.device = device;
+ this.styledText = styledText;
+}
+int addMerge(int[] mergeRanges, StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) {
+ int rangeCount = styleCount << 1;
+ StyleRange endStyle = null;
+ int endStart = 0, endLength = 0;
+ if (modifyEnd < rangeCount) {
+ endStyle = styles[modifyEnd >> 1];
+ endStart = ranges[modifyEnd];
+ endLength = ranges[modifyEnd + 1];
+ }
+ int grow = mergeCount - (modifyEnd - modifyStart);
+ if (rangeCount + grow >= ranges.length) {
+ int[] tmpRanges = new int[ranges.length + grow + (GROW << 1)];
+ System.arraycopy(ranges, 0, tmpRanges, 0, modifyStart);
+ StyleRange[] tmpStyles = new StyleRange[styles.length + (grow >> 1) + GROW];
+ System.arraycopy(styles, 0, tmpStyles, 0, modifyStart >> 1);
+ if (rangeCount > modifyEnd) {
+ System.arraycopy(ranges, modifyEnd, tmpRanges, modifyStart + mergeCount, rangeCount - modifyEnd);
+ System.arraycopy(styles, modifyEnd >> 1, tmpStyles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1));
+ }
+ ranges = tmpRanges;
+ styles = tmpStyles;
+ } else {
+ if (rangeCount > modifyEnd) {
+ System.arraycopy(ranges, modifyEnd, ranges, modifyStart + mergeCount, rangeCount - modifyEnd);
+ System.arraycopy(styles, modifyEnd >> 1, styles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1));
+ }
+ }
+ if (MERGE_STYLES) {
+ int j = modifyStart;
+ for (int i = 0; i < mergeCount; i += 2) {
+ if (j > 0 && ranges[j - 2] + ranges[j - 1] == mergeRanges[i] && mergeStyles[i >> 1].similarTo(styles[(j - 2) >> 1])) {
+ ranges[j - 1] += mergeRanges[i + 1];
+ } else {
+ styles[j >> 1] = mergeStyles[i >> 1];
+ ranges[j++] = mergeRanges[i];
+ ranges[j++] = mergeRanges[i + 1];
+ }
+ }
+ if (endStyle != null && ranges[j - 2] + ranges[j - 1] == endStart && endStyle.similarTo(styles[(j - 2) >> 1])) {
+ ranges[j - 1] += endLength;
+ modifyEnd += 2;
+ mergeCount += 2;
+ }
+ if (rangeCount > modifyEnd) {
+ System.arraycopy(ranges, modifyStart + mergeCount, ranges, j, rangeCount - modifyEnd);
+ System.arraycopy(styles, (modifyStart + mergeCount) >> 1, styles, j >> 1, styleCount - (modifyEnd >> 1));
+ }
+ grow = (j - modifyStart) - (modifyEnd - modifyStart);
+ } else {
+ System.arraycopy(mergeRanges, 0, ranges, modifyStart, mergeCount);
+ System.arraycopy(mergeStyles, 0, styles, modifyStart >> 1, mergeCount >> 1);
+ }
+ styleCount += grow >> 1;
+ return grow;
+}
+int addMerge(StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) {
+ int grow = mergeCount - (modifyEnd - modifyStart);
+ StyleRange endStyle = null;
+ if (modifyEnd < styleCount) endStyle = styles[modifyEnd];
+ if (styleCount + grow >= styles.length) {
+ StyleRange[] tmpStyles = new StyleRange[styles.length + grow + GROW];
+ System.arraycopy(styles, 0, tmpStyles, 0, modifyStart);
+ if (styleCount > modifyEnd) {
+ System.arraycopy(styles, modifyEnd, tmpStyles, modifyStart + mergeCount, styleCount - modifyEnd);
+ }
+ styles = tmpStyles;
+ } else {
+ if (styleCount > modifyEnd) {
+ System.arraycopy(styles, modifyEnd, styles, modifyStart + mergeCount, styleCount - modifyEnd);
+ }
+ }
+ if (MERGE_STYLES) {
+ int j = modifyStart;
+ for (int i = 0; i < mergeCount; i++) {
+ StyleRange newStyle = mergeStyles[i], style;
+ if (j > 0 && (style = styles[j - 1]).start + style.length == newStyle.start && newStyle.similarTo(style)) {
+ style.length += newStyle.length;
+ } else {
+ styles[j++] = newStyle;
+ }
+ }
+ StyleRange style = styles[j - 1];
+ if (endStyle != null && style.start + style.length == endStyle.start && endStyle.similarTo(style)) {
+ style.length += endStyle.length;
+ modifyEnd++;
+ mergeCount++;
+ }
+ if (styleCount > modifyEnd) {
+ System.arraycopy(styles, modifyStart + mergeCount, styles, j, styleCount - modifyEnd);
+ }
+ grow = (j - modifyStart) - (modifyEnd - modifyStart);
+ } else {
+ System.arraycopy(mergeStyles, 0, styles, modifyStart, mergeCount);
+ }
+ styleCount += grow;
+ return grow;
+}
+void calculate(int startLine, int lineCount) {
+ int endLine = startLine + lineCount;
+ if (startLine < 0 || endLine > lineWidth.length) {
+ return;
+ }
+ int hTrim = styledText.leftMargin + styledText.rightMargin + styledText.getCaretWidth();
+ for (int i = startLine; i < endLine; i++) {
+ if (lineWidth[i] == -1 || lineHeight[i] == -1) {
+ TextLayout layout = getTextLayout(i);
+ Rectangle rect = layout.getBounds();
+ lineWidth[i] = rect.width + hTrim;
+ lineHeight[i] = rect.height;
+ disposeTextLayout(layout);
+ }
+ if (lineWidth[i] > maxWidth) {
+ maxWidth = lineWidth[i];
+ maxWidthLineIndex = i;
+ }
+ }
+}
+void calculateClientArea () {
+ int index = styledText.getTopIndex();
+ int lineCount = content.getLineCount();
+ int height = styledText.getClientArea().height;
+ int y = 0;
+ while (height > y && lineCount > index) {
+ calculate(index, 1);
+ y += lineHeight[index++];
+ }
+}
+void calculateIdle () {
+ if (idleRunning) return;
+ Runnable runnable = new Runnable() {
+ public void run() {
+ if (styledText == null) return;
+ int i;
+ long start = System.currentTimeMillis();
+ for (i = 0; i < lineCount; i++) {
+ if (lineHeight[i] == -1 || lineWidth[i] == -1) {
+ calculate(i, 1);
+ if (System.currentTimeMillis() - start > IDLE_TIME) break;
+ }
+ }
+ if (i < lineCount) {
+ Display display = styledText.getDisplay();
+ display.asyncExec(this);
+ } else {
+ idleRunning = false;
+ styledText.setScrollBars(true);
+ ScrollBar bar = styledText.getVerticalBar();
+ if (bar != null) {
+ bar.setSelection(styledText.getVerticalScrollOffset());
+ }
+ }
+ }
+ };
+ Display display = styledText.getDisplay();
+ display.asyncExec(runnable);
+ idleRunning = true;
+}
+void clearLineBackground(int startLine, int count) {
+ if (lines == null) return;
+ for (int i = startLine; i < startLine + count; i++) {
+ LineInfo info = lines[i];
+ if (info != null) {
+ info.flags &= ~BACKGROUND;
+ info.background = null;
+ if (info.flags == 0) lines[i] = null;
+ }
+ }
+}
+void clearLineStyle(int startLine, int count) {
+ if (lines == null) return;
+ for (int i = startLine; i < startLine + count; i++) {
+ LineInfo info = lines[i];
+ if (info != null) {
+ info.flags &= ~(ALIGNMENT | INDENT | JUSTIFY);
+ if (info.flags == 0) lines[i] = null;
+ }
+ }
+}
+void copyInto(StyledTextRenderer renderer) {
+ if (ranges != null) {
+ int[] newRanges = renderer.ranges = new int[styleCount << 1];
+ System.arraycopy(ranges, 0, newRanges, 0, newRanges.length);
+ }
+ if (styles != null) {
+ StyleRange[] newStyles = renderer.styles = new StyleRange[styleCount];
+ for (int i = 0; i < newStyles.length; i++) {
+ newStyles[i] = (StyleRange)styles[i].clone();
+ }
+ renderer.styleCount = styleCount;
+ }
+ if (lines != null) {
+ LineInfo[] newLines = renderer.lines = new LineInfo[lineCount];
+ for (int i = 0; i < newLines.length; i++) {
+ newLines[i] = new LineInfo(lines[i]);
+ }
+ renderer.lineCount = lineCount;
+ }
+}
+void dispose() {
+ if (boldFont != null) boldFont.dispose();
+ if (italicFont != null) italicFont.dispose();
+ if (boldItalicFont != null) boldItalicFont.dispose();
+ boldFont = italicFont = boldItalicFont = null;
+ reset();
+ content = null;
+ device = null;
+ styledText = null;
+}
+void disposeTextLayout (TextLayout layout) {
+ if (layouts != null) {
+ for (int i = 0; i < layouts.length; i++) {
+ if (layouts[i] == layout) return;
+ }
+ }
+ layout.dispose();
+}
+void drawBullet(Bullet bullet, GC gc, int paintX, int paintY, int index, int lineAscent, int lineDescent) {
+ StyleRange style = bullet.style;
+ GlyphMetrics metrics = style.metrics;
+ Color color = style.foreground;
+ if (color != null) gc.setForeground(color);
+ if ((bullet.type & ST.BULLET_DOT) != 0 && StyledText.IS_MOTIF) {
+ int size = Math.max(4, (lineAscent + lineDescent) / 4);
+ if ((size & 1) == 0) size++;
+ if (color == null) {
+ Display display = styledText.getDisplay();
+ color = display.getSystemColor(SWT.COLOR_BLACK);
+ }
+ gc.setBackground(color);
+ int x = paintX + Math.max(0, metrics.width - size - BULLET_MARGIN);
+ gc.fillArc(x, paintY + size, size + 1, size + 1, 0, 360);
+ return;
+ }
+ Font font = style.font;
+ if (font != null) gc.setFont(font);
+ String string = "";
+ int type = bullet.type & (ST.BULLET_DOT|ST.BULLET_NUMBER|ST.BULLET_LETTER_LOWER|ST.BULLET_LETTER_UPPER);
+ switch (type) {
+ case ST.BULLET_DOT: string = "\u2022"; break;
+ case ST.BULLET_NUMBER: string = String.valueOf(index); break;
+ case ST.BULLET_LETTER_LOWER: string = String.valueOf((char) (index % 26 + 97)); break;
+ case ST.BULLET_LETTER_UPPER: string = String.valueOf((char) (index % 26 + 65)); break;
+ }
+ if ((bullet.type & ST.BULLET_TEXT) != 0) string += bullet.text;
+ Display display = styledText.getDisplay();
+ TextLayout layout = new TextLayout(display);
+ layout.setText(string);
+ layout.setAscent(lineAscent);
+ layout.setDescent(lineDescent);
+ style = (StyleRange)style.clone();
+ style.metrics = null;
+ if (style.font == null) style.font = getFont(style.fontStyle);
+ layout.setStyle(style, 0, string.length());
+ int x = paintX + Math.max(0, metrics.width - layout.getBounds().width - BULLET_MARGIN);
+ layout.draw(gc, x, paintY);
+ layout.dispose();
+}
+int drawLine(int lineIndex, int paintX, int paintY, GC gc, Color widgetBackground, Color widgetForeground) {
+ TextLayout layout = getTextLayout(lineIndex);
+ String line = content.getLine(lineIndex);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ int lineLength = line.length();
+ Point selection = styledText.getSelection();
+ int selectionStart = selection.x;
+ int selectionEnd = selection.y;
+ Rectangle client = styledText.getClientArea();
+ Color lineBackground = getLineBackground(lineIndex, widgetBackground);
+ StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line);
+ if (event != null && event.lineBackground != null) lineBackground = event.lineBackground;
+
+ boolean fullSelection = (styledText.getStyle() & SWT.FULL_SELECTION) != 0;
+ if (!fullSelection || selectionStart > lineOffset || selectionEnd <= lineOffset + lineLength) {
+ // draw background if full selection is off or if line is not completely selected
+ gc.setBackground(lineBackground);
+ styledText.drawBackground(gc, client.x, paintY, client.width, layout.getBounds().height);
+ }
+ if (selectionStart != selectionEnd) {
+ int y = paintY;
+ gc.setBackground(styledText.getSelectionBackground());
+ int lineCount = layout.getLineCount();
+ if (fullSelection) {
+ int[] offsets = layout.getLineOffsets();
+ for (int i = 0; i < lineCount - 1; i++) {
+ int lineStart = offsets[i];
+ if (lineStart >= selectionEnd - lineOffset) break;
+ int lineEnd = offsets[i + 1];
+ Rectangle lineBounds = layout.getLineBounds(i);
+ if (selectionStart - lineOffset <= lineEnd && lineEnd <= selectionEnd - lineOffset) {
+ int x = paintX + lineBounds.x + lineBounds.width;
+ gc.fillRectangle(x, y, client.width - x, lineBounds.height);
+ }
+ y += lineBounds.height + layout.getSpacing();
+ }
+ }
+ if (selectionStart - lineOffset <= lineLength && lineLength < selectionEnd - lineOffset) {
+ Rectangle lineBounds = layout.getLineBounds(lineCount - 1);
+ int x = paintX + lineBounds.x + lineBounds.width;
+ if (fullSelection) {
+ gc.fillRectangle(x, paintY + lineBounds.y, client.width - styledText.rightMargin - x, lineBounds.height);
+ } else {
+ gc.fillRectangle(x, paintY + lineBounds.y, lineEndSpaceWidth, lineBounds.height);
+ }
+ }
+ }
+ gc.setForeground(widgetForeground);
+ gc.setBackground(lineBackground);
+ if (selectionStart == selectionEnd || (selectionEnd <= lineOffset && selectionStart > lineOffset + lineLength - 1)) {
+ layout.draw(gc, paintX, paintY);
+ } else {
+ int start = Math.max(0, selectionStart - lineOffset);
+ int end = Math.min(lineLength, selectionEnd - lineOffset);
+ Color selectionFg = styledText.getSelectionForeground();
+ Color selectionBg = styledText.getSelectionBackground();
+ layout.draw(gc, paintX, paintY, start, end - 1, selectionFg, selectionBg);
+ }
+
+ // draw objects
+ Bullet bullet = null;
+ int bulletIndex = -1;
+ if (bullets != null) {
+ if (bulletsIndices != null) {
+ int index = lineIndex - topIndex;
+ if (0 <= index && index < CACHE_SIZE) {
+ bullet = bullets[index];
+ bulletIndex = bulletsIndices[index];
+ }
+ } else {
+ for (int i = 0; i < bullets.length; i++) {
+ bullet = bullets[i];
+ bulletIndex = bullet.indexOf(lineIndex);
+ if (bulletIndex != -1) break;
+ }
+ }
+ }
+ if (bulletIndex != -1 && bullet != null) {
+ FontMetrics metrics = layout.getLineMetrics(0);
+ int lineAscent = metrics.getAscent() + metrics.getLeading();
+ if (bullet.type == ST.BULLET_CUSTOM) {
+ bullet.style.start = lineOffset;
+ styledText.paintObject(gc, paintX, paintY, lineAscent, metrics.getDescent(), bullet.style, bullet, bulletIndex);
+ } else {
+ drawBullet(bullet, gc, paintX, paintY, bulletIndex, lineAscent, metrics.getDescent());
+ }
+ }
+
+ TextStyle[] styles = layout.getStyles();
+ int[] ranges = null;
+ for (int i = 0; i < styles.length; i++) {
+ if (styles[i].metrics != null) {
+ if (ranges == null) ranges = layout.getRanges();
+ int start = ranges[i << 1];
+ int length = ranges[(i << 1) + 1] - start;
+ Point point = layout.getLocation(start, false);
+ FontMetrics metrics = layout.getLineMetrics(layout.getLineIndex(start));
+ StyleRange style = (StyleRange)((StyleRange)styles[i]).clone();
+ style.start = start + lineOffset;
+ style.length = length;
+ int lineAscent = metrics.getAscent() + metrics.getLeading();
+ styledText.paintObject(gc, point.x + paintX, point.y + paintY, lineAscent, metrics.getDescent(), style, null, 0);
+ }
+ }
+ int height = layout.getBounds().height;
+ disposeTextLayout(layout);
+ return height;
+}
+int getBaseline() {
+ return ascent;
+}
+Font getFont(int style) {
+ switch (style) {
+ case SWT.BOLD:
+ if (boldFont != null) return boldFont;
+ return boldFont = new Font(device, getFontData(style));
+ case SWT.ITALIC:
+ if (italicFont != null) return italicFont;
+ return italicFont = new Font(device, getFontData(style));
+ case SWT.BOLD | SWT.ITALIC:
+ if (boldItalicFont != null) return boldItalicFont;
+ return boldItalicFont = new Font(device, getFontData(style));
+ default:
+ return regularFont;
+ }
+}
+FontData[] getFontData(int style) {
+ FontData[] fontDatas = regularFont.getFontData();
+ for (int i = 0; i < fontDatas.length; i++) {
+ fontDatas[i].setStyle(style);
+ }
+ return fontDatas;
+}
+int getHeight () {
+ int defaultLineHeight = getLineHeight();
+ if (styledText.isFixedLineHeight()) {
+ return lineCount * defaultLineHeight;
+ }
+ int totalHeight = 0;
+ int width = styledText.getWrapWidth();
+ for (int i = 0; i < lineCount; i++) {
+ int height = lineHeight[i];
+ if (height == -1) {
+ if (width > 0) {
+ int length = content.getLine(i).length();
+ height = ((length * averageCharWidth / width) + 1) * defaultLineHeight;
+ } else {
+ height = defaultLineHeight;
+ }
+ }
+ totalHeight += height;
+ }
+ return totalHeight + styledText.topMargin + styledText.bottomMargin;
+}
+int getLineAlignment(int index, int defaultAlignment) {
+ if (lines == null) return defaultAlignment;
+ LineInfo info = lines[index];
+ if (info != null && (info.flags & ALIGNMENT) != 0) {
+ return info.alignment;
+ }
+ return defaultAlignment;
+}
+Color getLineBackground(int index, Color defaultBackground) {
+ if (lines == null) return defaultBackground;
+ LineInfo info = lines[index];
+ if (info != null && (info.flags & BACKGROUND) != 0) {
+ return info.background;
+ }
+ return defaultBackground;
+}
+Bullet getLineBullet (int index, Bullet defaultBullet) {
+ if (bullets == null) return defaultBullet;
+ if (bulletsIndices != null) return defaultBullet;
+ for (int i = 0; i < bullets.length; i++) {
+ Bullet bullet = bullets[i];
+ if (bullet.indexOf(index) != -1) return bullet;
+ }
+ return defaultBullet;
+}
+int getLineEndSpace() {
+ return lineEndSpaceWidth;
+}
+int getLineHeight() {
+ return ascent + descent;
+}
+int getLineHeight(int lineIndex) {
+ if (lineHeight[lineIndex] == -1) {
+ calculate(lineIndex, 1);
+ }
+ return lineHeight[lineIndex];
+}
+int getLineIndent(int index, int defaultIndent) {
+ if (lines == null) return defaultIndent;
+ LineInfo info = lines[index];
+ if (info != null && (info.flags & INDENT) != 0) {
+ return info.indent;
+ }
+ return defaultIndent;
+}
+boolean getLineJustify(int index, boolean defaultJustify) {
+ if (lines == null) return defaultJustify;
+ LineInfo info = lines[index];
+ if (info != null && (info.flags & JUSTIFY) != 0) {
+ return info.justify;
+ }
+ return defaultJustify;
+}
+int[] getLineSegments(int index, int[] defaultSegments) {
+ if (lines == null) return defaultSegments;
+ LineInfo info = lines[index];
+ if (info != null && (info.flags & SEGMENTS) != 0) {
+ return info.segments;
+ }
+ return defaultSegments;
+}
+int getRangeIndex(int offset, int low, int high) {
+ if (styleCount == 0) return 0;
+ if (ranges != null) {
+ while (high - low > 2) {
+ int index = ((high + low) / 2) / 2 * 2;
+ int end = ranges[index] + ranges[index + 1];
+ if (end > offset) {
+ high = index;
+ } else {
+ low = index;
+ }
+ }
+ } else {
+ while (high - low > 1) {
+ int index = ((high + low) / 2);
+ int end = styles[index].start + styles[index].length;
+ if (end > offset) {
+ high = index;
+ } else {
+ low = index;
+ }
+ }
+ }
+ return high;
+}
+int[] getRanges(int start, int length) {
+ int[] newRanges;
+ int end = start + length - 1;
+ if (ranges != null) {
+ int rangeCount = styleCount << 1;
+ int rangeStart = getRangeIndex(start, -1, rangeCount);
+ if (rangeStart >= rangeCount) return null;
+ if (ranges[rangeStart] > end) return null;
+ int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount) + 1);
+ newRanges = new int[rangeEnd - rangeStart + 2];
+ System.arraycopy(ranges, rangeStart, newRanges, 0, newRanges.length);
+ } else {
+ int rangeStart = getRangeIndex(start, -1, styleCount);
+ if (rangeStart >= styleCount) return null;
+ if (styles[rangeStart].start > end) return null;
+ int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount));
+ newRanges = new int[(rangeEnd - rangeStart + 1) << 1];
+ for (int i = rangeStart, j = 0; i <= rangeEnd; i++, j += 2) {
+ StyleRange style = styles[i];
+ newRanges[j] = style.start;
+ newRanges[j + 1] = style.length;
+ }
+ }
+ if (start > newRanges[0]) {
+ newRanges[1] = newRanges[0] + newRanges[1] - start;
+ newRanges[0] = start;
+ }
+ if (end < newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1] - 1) {
+ newRanges[newRanges.length - 1] = end - newRanges[newRanges.length - 2];
+ }
+ return newRanges;
+}
+StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) {
+ StyleRange[] newStyles;
+ int end = start + length - 1;
+ if (ranges != null) {
+ int rangeCount = styleCount << 1;
+ int rangeStart = getRangeIndex(start, -1, rangeCount);
+ if (rangeStart >= rangeCount) return null;
+ if (ranges[rangeStart] > end) return null;
+ int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount) + 1);
+ newStyles = new StyleRange[((rangeEnd - rangeStart) >> 1) + 1];
+ if (includeRanges) {
+ for (int i = rangeStart, j = 0; i <= rangeEnd; i += 2, j++) {
+ newStyles[j] = (StyleRange)styles[i >> 1].clone();
+ newStyles[j].start = ranges[i];
+ newStyles[j].length = ranges[i + 1];
+ }
+ } else {
+ System.arraycopy(styles, rangeStart >> 1, newStyles, 0, newStyles.length);
+ }
+ } else {
+ int rangeStart = getRangeIndex(start, -1, styleCount);
+ if (rangeStart >= styleCount) return null;
+ if (styles[rangeStart].start > end) return null;
+ int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount));
+ newStyles = new StyleRange[rangeEnd - rangeStart + 1];
+ System.arraycopy(styles, rangeStart, newStyles, 0, newStyles.length);
+ }
+ StyleRange style = newStyles[0];
+ if (start > style.start) {
+ if (!includeRanges || ranges == null) newStyles[0] = style = (StyleRange)style.clone();
+ style.length = style.start + style.length - start;
+ style.start = start;
+ }
+ style = newStyles[newStyles.length - 1];
+ if (end < style.start + style.length - 1) {
+ if (!includeRanges || ranges == null) newStyles[newStyles.length - 1] = style = (StyleRange)style.clone();
+ style.length = end - style.start + 1;
+ }
+ return newStyles;
+}
+StyleRange getStyleRange(StyleRange style) {
+ if (style.start == 0 && style.length == 0 && style.fontStyle == SWT.NORMAL) return style;
+ StyleRange clone = (StyleRange)style.clone();
+ clone.start = clone.length = 0;
+ clone.fontStyle = SWT.NORMAL;
+ if (clone.font == null) clone.font = getFont(style.fontStyle);
+ return clone;
+}
+TextLayout getTextLayout(int lineIndex) {
+ return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), styledText.lineSpacing);
+}
+TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpacing) {
+ TextLayout layout = null;
+ if (styledText != null) {
+ int topIndex = styledText.topIndex > 0 ? styledText.topIndex - 1 : 0;
+ if (layouts == null || topIndex != this.topIndex) {
+ TextLayout[] newLayouts = new TextLayout[CACHE_SIZE];
+ if (layouts != null) {
+ for (int i = 0; i < layouts.length; i++) {
+ if (layouts[i] != null) {
+ int layoutIndex = (i + this.topIndex) - topIndex;
+ if (0 <= layoutIndex && layoutIndex < newLayouts.length) {
+ newLayouts[layoutIndex] = layouts[i];
+ } else {
+ layouts[i].dispose();
+ }
+ }
+ }
+ }
+ if (bullets != null && bulletsIndices != null && topIndex != this.topIndex) {
+ int delta = topIndex - this.topIndex;
+ if (delta > 0) {
+ if (delta < bullets.length) {
+ System.arraycopy(bullets, delta, bullets, 0, bullets.length - delta);
+ System.arraycopy(bulletsIndices, delta, bulletsIndices, 0, bulletsIndices.length - delta);
+ }
+ int startIndex = Math.max(0, bullets.length - delta);
+ for (int i = startIndex; i < bullets.length; i++) bullets[i] = null;
+ } else {
+ if (-delta < bullets.length) {
+ System.arraycopy(bullets, 0, bullets, -delta, bullets.length + delta);
+ System.arraycopy(bulletsIndices, 0, bulletsIndices, -delta, bulletsIndices.length + delta);
+ }
+ int endIndex = Math.min(bullets.length, -delta);
+ for (int i = 0; i < endIndex; i++) bullets[i] = null;
+ }
+ }
+ this.topIndex = topIndex;
+ layouts = newLayouts;
+ }
+ if (layouts != null) {
+ int layoutIndex = lineIndex - topIndex;
+ if (0 <= layoutIndex && layoutIndex < layouts.length) {
+ layout = layouts[layoutIndex];
+ if (layout != null) {
+ if (lineWidth[lineIndex] != -1) return layout;
+ } else {
+ layout = layouts[layoutIndex] = new TextLayout(device);
+ }
+ }
+ }
+ }
+ if (layout == null) layout = new TextLayout(device);
+ String line = content.getLine(lineIndex);
+ int lineOffset = content.getOffsetAtLine(lineIndex);
+ int[] segments = null;
+ int indent = 0;
+ int alignment = SWT.LEFT;
+ boolean justify = false;
+ Bullet bullet = null;
+ int[] ranges = null;
+ StyleRange[] styles = null;
+ int rangeStart = 0, styleCount = 0;
+ StyledTextEvent event = null;
+ if (styledText != null) {
+ event = styledText.getLineStyleData(lineOffset, line);
+ segments = styledText.getBidiSegments(lineOffset, line);
+ indent = styledText.indent;
+ alignment = styledText.alignment;
+ justify = styledText.justify;
+ }
+ if (event != null) {
+ indent = event.indent;
+ alignment = event.alignment;
+ justify = event.justify;
+ bullet = event.bullet;
+ ranges = event.ranges;
+ styles = event.styles;
+ if (styles != null) {
+ styleCount = styles.length;
+ if (styledText.isFixedLineHeight()) {
+ for (int i = 0; i < styleCount; i++) {
+ if (styles[i].isVariableHeight()) {
+ styledText.verticalScrollOffset = -1;
+ styledText.setVariableLineHeight();
+ styledText.redraw();
+ break;
+ }
+ }
+ }
+ }
+ if (bullets == null || bulletsIndices == null) {
+ bullets = new Bullet[CACHE_SIZE];
+ bulletsIndices = new int[CACHE_SIZE];
+ }
+ int index = lineIndex - topIndex;
+ if (0 <= index && index < CACHE_SIZE) {
+ bullets[index] = bullet;
+ bulletsIndices[index] = event.bulletIndex;
+ }
+ } else {
+ if (lines != null) {
+ LineInfo info = lines[lineIndex];
+ if (info != null) {
+ if ((info.flags & INDENT) != 0) indent = info.indent;
+ if ((info.flags & ALIGNMENT) != 0) alignment = info.alignment;
+ if ((info.flags & JUSTIFY) != 0) justify = info.justify;
+ if ((info.flags & SEGMENTS) != 0) segments = info.segments;
+ }
+ }
+ if (bulletsIndices != null) {
+ bullets = null;
+ bulletsIndices = null;
+ }
+ if (bullets != null) {
+ for (int i = 0; i < bullets.length; i++) {
+ if (bullets[i].indexOf(lineIndex) != -1) {
+ bullet = bullets[i];
+ break;
+ }
+ }
+ }
+ ranges = this.ranges;
+ styles = this.styles;
+ styleCount = this.styleCount;
+ if (ranges != null) {
+ rangeStart = getRangeIndex(lineOffset, -1, styleCount << 1);
+ } else {
+ rangeStart = getRangeIndex(lineOffset, -1, styleCount);
+ }
+ }
+ if (bullet != null) {
+ StyleRange style = bullet.style;
+ GlyphMetrics metrics = style.metrics;
+ indent += metrics.width;
+ }
+ layout.setFont(regularFont);
+ layout.setAscent(ascent);
+ layout.setDescent(descent);
+ layout.setText(line);
+ layout.setOrientation(orientation);
+ layout.setSegments(segments);
+ layout.setWidth(width);
+ layout.setSpacing(lineSpacing);
+ layout.setTabs(new int[]{tabWidth});
+ layout.setIndent(indent);
+ layout.setAlignment(alignment);
+ layout.setJustify(justify);
+
+ int lastOffset = 0;
+ int length = line.length();
+ if (styles != null) {
+ if (ranges != null) {
+ int rangeCount = styleCount << 1;
+ for (int i = rangeStart; i < rangeCount; i += 2) {
+ int start, end;
+ if (lineOffset > ranges[i]) {
+ start = 0;
+ end = Math.min (length, ranges[i + 1] - lineOffset + ranges[i]);
+ } else {
+ start = ranges[i] - lineOffset;
+ end = Math.min(length, start + ranges[i + 1]);
+ }
+ if (start >= length) break;
+ if (lastOffset < start) {
+ layout.setStyle(null, lastOffset, start - 1);
+ }
+ layout.setStyle(getStyleRange(styles[i >> 1]), start, end);
+ lastOffset = Math.max(lastOffset, end);
+ }
+ } else {
+ for (int i = rangeStart; i < styleCount; i++) {
+ int start, end;
+ if (lineOffset > styles[i].start) {
+ start = 0;
+ end = Math.min (length, styles[i].length - lineOffset + styles[i].start);
+ } else {
+ start = styles[i].start - lineOffset;
+ end = Math.min(length, start + styles[i].length);
+ }
+ if (start >= length) break;
+ if (lastOffset < start) {
+ layout.setStyle(null, lastOffset, start - 1);
+ }
+ layout.setStyle(getStyleRange(styles[i]), start, end);
+ lastOffset = Math.max(lastOffset, end);
+ }
+ }
+ }
+ if (lastOffset < length) layout.setStyle(null, lastOffset, length);
+ if (styledText != null && styledText.isFixedLineHeight()) {
+ int index = -1;
+ int lineCount = layout.getLineCount();
+ int height = getLineHeight();
+ for (int i = 0; i < lineCount; i++) {
+ int lineHeight = layout.getLineBounds(i).height;
+ if (lineHeight > height) {
+ height = lineHeight;
+ index = i;
+ }
+ }
+ if (index != -1) {
+ FontMetrics metrics = layout.getLineMetrics(index);
+ ascent = metrics.getAscent() + metrics.getLeading();
+ descent = metrics.getDescent();
+ if (layouts != null) {
+ for (int i = 0; i < layouts.length; i++) {
+ if (layouts[i] != null && layouts[i] != layout) {
+ layouts[i].setAscent(ascent);
+ layouts[i].setDescent(descent);
+ }
+ }
+ }
+ if (styledText.verticalScrollOffset != 0) {
+ int topIndex = styledText.topIndex;
+ int topIndexY = styledText.topIndexY;
+ int lineHeight = getLineHeight();
+ if (topIndexY >= 0) {
+ styledText.verticalScrollOffset = (topIndex - 1) * lineHeight + lineHeight - topIndexY;
+ } else {
+ styledText.verticalScrollOffset = topIndex * lineHeight - topIndexY;
+ }
+ }
+ styledText.calculateScrollBars();
+ if (styledText.isBidiCaret()) styledText.createCaretBitmaps();
+ styledText.caretDirection = SWT.NULL;
+ styledText.setCaretLocation();
+ styledText.redraw();
+ }
+ }
+ return layout;
+}
+int getWidth() {
+ return maxWidth;
+}
+void reset() {
+ if (layouts != null) {
+ for (int i = 0; i < layouts.length; i++) {
+ TextLayout layout = layouts[i];
+ if (layout != null) layout.dispose();
+ }
+ layouts = null;
+ }
+ topIndex = -1;
+ stylesSetCount = styleCount = lineCount = 0;
+ ranges = null;
+ styles = null;
+ stylesSet = null;
+ lines = null;
+ lineWidth = null;
+ lineHeight = null;
+ bullets = null;
+ bulletsIndices = null;
+ redrawLines = null;
+}
+void reset(int startLine, int lineCount) {
+ int endLine = startLine + lineCount;
+ if (startLine < 0 || endLine > lineWidth.length) return;
+ for (int i = startLine; i < endLine; i++) {
+ lineWidth[i] = -1;
+ lineHeight[i] = -1;
+ }
+ if (startLine <= maxWidthLineIndex && maxWidthLineIndex < endLine) {
+ maxWidth = 0;
+ maxWidthLineIndex = -1;
+ if (lineCount != this.lineCount) {
+ for (int i = 0; i < this.lineCount; i++) {
+ if (lineWidth[i] > maxWidth) {
+ maxWidth = lineWidth[i];
+ maxWidthLineIndex = i;
+ }
+ }
+ }
+ }
+}
+void setContent(StyledTextContent content) {
+ reset();
+ this.content = content;
+ lineCount = content.getLineCount();
+ lineWidth = new int[lineCount];
+ lineHeight = new int[lineCount];
+ reset(0, lineCount);
+}
+void setFont(Font font, int tabs) {
+ TextLayout layout = new TextLayout(device);
+ layout.setFont(regularFont);
+ if (font != null) {
+ if (boldFont != null) boldFont.dispose();
+ if (italicFont != null) italicFont.dispose();
+ if (boldItalicFont != null) boldItalicFont.dispose();
+ boldFont = italicFont = boldItalicFont = null;
+ regularFont = font;
+ layout.setText(" ");
+ layout.setFont(font);
+ layout.setStyle(new TextStyle(getFont(SWT.NORMAL), null, null), 0, 0);
+ layout.setStyle(new TextStyle(getFont(SWT.BOLD), null, null), 1, 1);
+ layout.setStyle(new TextStyle(getFont(SWT.ITALIC), null, null), 2, 2);
+ layout.setStyle(new TextStyle(getFont(SWT.BOLD | SWT.ITALIC), null, null), 3, 3);
+ FontMetrics metrics = layout.getLineMetrics(0);
+ ascent = metrics.getAscent() + metrics.getLeading();
+ descent = metrics.getDescent();
+ lineEndSpaceWidth = layout.getBounds(0, 0).width;
+ boldFont.dispose();
+ italicFont.dispose();
+ boldItalicFont.dispose();
+ boldFont = italicFont = boldItalicFont = null;
+ }
+ layout.dispose();
+ layout = new TextLayout(device);
+ layout.setFont(regularFont);
+ StringBuffer tabBuffer = new StringBuffer(tabs);
+ for (int i = 0; i < tabs; i++) {
+ tabBuffer.append(' ');
+ }
+ layout.setText(tabBuffer.toString());
+ tabWidth = layout.getBounds().width;
+ layout.dispose();
+}
+void setLineAlignment(int startLine, int count, int alignment) {
+ if (lines == null) lines = new LineInfo[lineCount];
+ for (int i = startLine; i < startLine + count; i++) {
+ if (lines[i] == null) {
+ lines[i] = new LineInfo();
+ }
+ lines[i].flags |= ALIGNMENT;
+ lines[i].alignment = alignment;
+ }
+}
+void setLineBackground(int startLine, int count, Color background) {
+ if (lines == null) lines = new LineInfo[lineCount];
+ for (int i = startLine; i < startLine + count; i++) {
+ if (lines[i] == null) {
+ lines[i] = new LineInfo();
+ }
+ lines[i].flags |= BACKGROUND;
+ lines[i].background = background;
+ }
+}
+void setLineBullet(int startLine, int count, Bullet bullet) {
+ if (bulletsIndices != null) {
+ bulletsIndices = null;
+ bullets = null;
+ }
+ if (bullets == null) {
+ if (bullet == null) return;
+ bullets = new Bullet[1];
+ bullets[0] = bullet;
+ }
+ int index = 0;
+ while (index < bullets.length) {
+ if (bullet == bullets[index]) break;
+ index++;
+ }
+ if (bullet != null) {
+ if (index == bullets.length) {
+ Bullet[] newBulletsList = new Bullet[bullets.length + 1];
+ System.arraycopy(bullets, 0, newBulletsList, 0, bullets.length);
+ newBulletsList[index] = bullet;
+ bullets = newBulletsList;
+ }
+ bullet.addIndices(startLine, count);
+ } else {
+ updateBullets(startLine, count, 0, false);
+ styledText.redrawLinesBullet(redrawLines);
+ redrawLines = null;
+ }
+}
+void setLineIndent(int startLine, int count, int indent) {
+ if (lines == null) lines = new LineInfo[lineCount];
+ for (int i = startLine; i < startLine + count; i++) {
+ if (lines[i] == null) {
+ lines[i] = new LineInfo();
+ }
+ lines[i].flags |= INDENT;
+ lines[i].indent = indent;
+ }
+}
+void setLineJustify(int startLine, int count, boolean justify) {
+ if (lines == null) lines = new LineInfo[lineCount];
+ for (int i = startLine; i < startLine + count; i++) {
+ if (lines[i] == null) {
+ lines[i] = new LineInfo();
+ }
+ lines[i].flags |= JUSTIFY;
+ lines[i].justify = justify;
+ }
+}
+void setLineSegments(int startLine, int count, int[] segments) {
+ if (lines == null) lines = new LineInfo[lineCount];
+ for (int i = startLine; i < startLine + count; i++) {
+ if (lines[i] == null) {
+ lines[i] = new LineInfo();
+ }
+ lines[i].flags |= SEGMENTS;
+ lines[i].segments = segments;
+ }
+}
+void setStyleRanges (int[] newRanges, StyleRange[] newStyles) {
+ if (newStyles == null) {
+ stylesSetCount = styleCount = 0;
+ ranges = null;
+ styles = null;
+ stylesSet = null;
+ return;
+ }
+ if (newRanges == null && COMPACT_STYLES) {
+ newRanges = new int[newStyles.length << 1];
+ StyleRange[] tmpStyles = new StyleRange[newStyles.length];
+ if (stylesSet == null) stylesSet = new StyleRange[4];
+ for (int i = 0, j = 0; i < newStyles.length; i++) {
+ StyleRange newStyle = newStyles[i];
+ newRanges[j++] = newStyle.start;
+ newRanges[j++] = newStyle.length;
+ int index = 0;
+ while (index < stylesSetCount) {
+ if (stylesSet[index].similarTo(newStyle)) break;
+ index++;
+ }
+ if (index == stylesSetCount) {
+ if (stylesSetCount == stylesSet.length) {
+ StyleRange[] tmpStylesSet = new StyleRange[stylesSetCount + 4];
+ System.arraycopy(stylesSet, 0, tmpStylesSet, 0, stylesSetCount);
+ stylesSet = tmpStylesSet;
+ }
+ stylesSet[stylesSetCount++] = newStyle;
+ }
+ tmpStyles[i] = stylesSet[index];
+ }
+ newStyles = tmpStyles;
+ }
+
+ if (styleCount == 0) {
+ if (newRanges != null) {
+ ranges = new int[newRanges.length];
+ System.arraycopy(newRanges, 0, ranges, 0, ranges.length);
+ }
+ styles = new StyleRange[newStyles.length];
+ System.arraycopy(newStyles, 0, styles, 0, styles.length);
+ styleCount = newStyles.length;
+ return;
+ }
+ if (newRanges != null && ranges == null) {
+ ranges = new int[styles.length << 1];
+ for (int i = 0, j = 0; i < styleCount; i++) {
+ ranges[j++] = styles[i].start;
+ ranges[j++] = styles[i].length;
+ }
+ }
+ if (newRanges == null && ranges != null) {
+ newRanges = new int[newStyles.length << 1];
+ for (int i = 0, j = 0; i < newStyles.length; i++) {
+ newRanges[j++] = newStyles[i].start;
+ newRanges[j++] = newStyles[i].length;
+ }
+ }
+ if (ranges != null) {
+ int rangeCount = styleCount << 1;
+ int start = newRanges[0];
+ int modifyStart = getRangeIndex(start, -1, rangeCount), modifyEnd;
+ boolean insert = modifyStart == rangeCount;
+ if (!insert) {
+ int end = newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1];
+ modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
+ insert = modifyStart == modifyEnd && ranges[modifyStart] >= end;
+ }
+ if (insert) {
+ addMerge(newRanges, newStyles, newRanges.length, modifyStart, modifyStart);
+ return;
+ }
+ modifyEnd = modifyStart;
+ int[] mergeRanges = new int[6];
+ StyleRange[] mergeStyles = new StyleRange[3];
+ for (int i = 0; i < newRanges.length; i += 2) {
+ int newStart = newRanges[i];
+ int newEnd = newStart + newRanges[i + 1];
+ if (newStart == newEnd) continue;
+ int modifyLast = 0, mergeCount = 0;
+ while (modifyEnd < rangeCount) {
+ if (newStart >= ranges[modifyStart] + ranges[modifyStart + 1]) modifyStart += 2;
+ if (ranges[modifyEnd] + ranges[modifyEnd + 1] > newEnd) break;
+ modifyEnd += 2;
+ }
+ if (ranges[modifyStart] < newStart && newStart < ranges[modifyStart] + ranges[modifyStart + 1]) {
+ mergeStyles[mergeCount >> 1] = styles[modifyStart >> 1];
+ mergeRanges[mergeCount] = ranges[modifyStart];
+ mergeRanges[mergeCount + 1] = newStart - ranges[modifyStart];
+ mergeCount += 2;
+ }
+ mergeStyles[mergeCount >> 1] = newStyles[i >> 1];
+ mergeRanges[mergeCount] = newStart;
+ mergeRanges[mergeCount + 1] = newRanges[i + 1];
+ mergeCount += 2;
+ if (modifyEnd < rangeCount && ranges[modifyEnd] < newEnd && newEnd < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+ mergeStyles[mergeCount >> 1] = styles[modifyEnd >> 1];
+ mergeRanges[mergeCount] = newEnd;
+ mergeRanges[mergeCount + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - newEnd;
+ mergeCount += 2;
+ modifyLast = 2;
+ }
+ int grow = addMerge(mergeRanges, mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast);
+ rangeCount += grow;
+ modifyStart = modifyEnd += grow;
+ }
+ } else {
+ int start = newStyles[0].start;
+ int modifyStart = getRangeIndex(start, -1, styleCount), modifyEnd;
+ boolean insert = modifyStart == styleCount;
+ if (!insert) {
+ int end = newStyles[newStyles.length - 1].start + newStyles[newStyles.length - 1].length;
+ modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
+ insert = modifyStart == modifyEnd && styles[modifyStart].start >= end;
+ }
+ if (insert) {
+ addMerge(newStyles, newStyles.length, modifyStart, modifyStart);
+ return;
+ }
+ modifyEnd = modifyStart;
+ StyleRange[] mergeStyles = new StyleRange[3];
+ for (int i = 0; i < newStyles.length; i++) {
+ StyleRange newStyle = newStyles[i], style;
+ int newStart = newStyle.start;
+ int newEnd = newStart + newStyle.length;
+ if (newStart == newEnd) continue;
+ int modifyLast = 0, mergeCount = 0;
+ while (modifyEnd < styleCount) {
+ if (newStart >= styles[modifyStart].start + styles[modifyStart].length) modifyStart++;
+ if (styles[modifyEnd].start + styles[modifyEnd].length > newEnd) break;
+ modifyEnd++;
+ }
+ style = styles[modifyStart];
+ if (style.start < newStart && newStart < style.start + style.length) {
+ style = mergeStyles[mergeCount++] = (StyleRange)style.clone();
+ style.length = newStart - style.start;
+ }
+ mergeStyles[mergeCount++] = newStyle;
+ if (modifyEnd < styleCount) {
+ style = styles[modifyEnd];
+ if (style.start < newEnd && newEnd < style.start + style.length) {
+ style = mergeStyles[mergeCount++] = (StyleRange)style.clone();
+ style.length += style.start - newEnd;
+ style.start = newEnd;
+ modifyLast = 1;
+ }
+ }
+ int grow = addMerge(mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast);
+ modifyStart = modifyEnd += grow;
+ }
+ }
+}
+void textChanging(TextChangingEvent event) {
+ int start = event.start;
+ int newCharCount = event.newCharCount, replaceCharCount = event.replaceCharCount;
+ int newLineCount = event.newLineCount, replaceLineCount = event.replaceLineCount;
+
+ updateRanges(start, replaceCharCount, newCharCount);
+
+ int startLine = content.getLineAtOffset(start);
+ if (replaceCharCount == content.getCharCount()) lines = null;
+ if (replaceLineCount == lineCount) {
+ lineCount = newLineCount;
+ lineWidth = new int[lineCount];
+ lineHeight = new int[lineCount];
+ reset(0, lineCount);
+ } else {
+ int delta = newLineCount - replaceLineCount;
+ if (lineCount + delta > lineWidth.length) {
+ int[] newWidths = new int[lineCount + delta + GROW];
+ System.arraycopy(lineWidth, 0, newWidths, 0, lineCount);
+ lineWidth = newWidths;
+ int[] newHeights = new int[lineCount + delta + GROW];
+ System.arraycopy(lineHeight, 0, newHeights, 0, lineCount);
+ lineHeight = newHeights;
+ }
+ if (lines != null) {
+ if (lineCount + delta > lines.length) {
+ LineInfo[] newLines = new LineInfo[lineCount + delta + GROW];
+ System.arraycopy(lines, 0, newLines, 0, lineCount);
+ lines = newLines;
+ }
+ }
+ int startIndex = startLine + replaceLineCount + 1;
+ int endIndex = startLine + newLineCount + 1;
+ System.arraycopy(lineWidth, startIndex, lineWidth, endIndex, lineCount - startIndex);
+ System.arraycopy(lineHeight, startIndex, lineHeight, endIndex, lineCount - startIndex);
+ for (int i = startLine; i < endIndex; i++) {
+ lineWidth[i] = lineHeight[i] = -1;
+ }
+ for (int i = lineCount + delta; i < lineCount; i++) {
+ lineWidth[i] = lineHeight[i] = -1;
+ }
+ if (layouts != null) {
+ int layoutStartLine = startLine - topIndex;
+ int layoutEndLine = layoutStartLine + replaceLineCount + 1;
+ for (int i = layoutStartLine; i < layoutEndLine; i++) {
+ if (0 <= i && i < layouts.length) {
+ if (layouts[i] != null) layouts[i].dispose();
+ layouts[i] = null;
+ if (bullets != null && bulletsIndices != null) bullets[i] = null;
+ }
+ }
+ if (delta > 0) {
+ for (int i = layouts.length - 1; i >= layoutEndLine; i--) {
+ if (0 <= i && i < layouts.length) {
+ endIndex = i + delta;
+ if (0 <= endIndex && endIndex < layouts.length) {
+ layouts[endIndex] = layouts[i];
+ layouts[i] = null;
+ if (bullets != null && bulletsIndices != null) {
+ bullets[endIndex] = bullets[i];
+ bulletsIndices[endIndex] = bulletsIndices[i];
+ bullets[i] = null;
+ }
+ } else {
+ if (layouts[i] != null) layouts[i].dispose();
+ layouts[i] = null;
+ if (bullets != null && bulletsIndices != null) bullets[i] = null;
+ }
+ }
+ }
+ } else if (delta < 0) {
+ for (int i = layoutEndLine; i < layouts.length; i++) {
+ if (0 <= i && i < layouts.length) {
+ endIndex = i + delta;
+ if (0 <= endIndex && endIndex < layouts.length) {
+ layouts[endIndex] = layouts[i];
+ layouts[i] = null;
+ if (bullets != null && bulletsIndices != null) {
+ bullets[endIndex] = bullets[i];
+ bulletsIndices[endIndex] = bulletsIndices[i];
+ bullets[i] = null;
+ }
+ } else {
+ if (layouts[i] != null) layouts[i].dispose();
+ layouts[i] = null;
+ if (bullets != null && bulletsIndices != null) bullets[i] = null;
+ }
+ }
+ }
+ }
+ }
+ if (replaceLineCount != 0 || newLineCount != 0) {
+ int startLineOffset = content.getOffsetAtLine(startLine);
+ if (startLineOffset != start) startLine++;
+ updateBullets(startLine, replaceLineCount, newLineCount, true);
+ if (lines != null) {
+ startIndex = startLine + replaceLineCount;
+ endIndex = startLine + newLineCount;
+ System.arraycopy(lines, startIndex, lines, endIndex, lineCount - startIndex);
+ for (int i = startLine; i < endIndex; i++) {
+ lines[i] = null;
+ }
+ for (int i = lineCount + delta; i < lineCount; i++) {
+ lines[i] = null;
+ }
+ }
+ }
+ lineCount += delta;
+ if (maxWidthLineIndex != -1 && startLine <= maxWidthLineIndex && maxWidthLineIndex <= startLine + replaceLineCount) {
+ maxWidth = 0;
+ maxWidthLineIndex = -1;
+ for (int i = 0; i < lineCount; i++) {
+ if (lineWidth[i] > maxWidth) {
+ maxWidth = lineWidth[i];
+ maxWidthLineIndex = i;
+ }
+ }
+ }
+ }
+}
+void updateBullets(int startLine, int replaceLineCount, int newLineCount, boolean update) {
+ if (bullets == null) return;
+ if (bulletsIndices != null) return;
+ for (int i = 0; i < bullets.length; i++) {
+ Bullet bullet = bullets[i];
+ int[] lines = bullet.removeIndices(startLine, replaceLineCount, newLineCount, update);
+ if (lines != null) {
+ if (redrawLines == null) {
+ redrawLines = lines;
+ } else {
+ int[] newRedrawBullets = new int[redrawLines.length + lines.length];
+ System.arraycopy(redrawLines, 0, newRedrawBullets, 0, redrawLines.length);
+ System.arraycopy(lines, 0, newRedrawBullets, redrawLines.length, lines.length);
+ redrawLines = newRedrawBullets;
+ }
+ }
+ }
+ int removed = 0;
+ for (int i = 0; i < bullets.length; i++) {
+ if (bullets[i].size() == 0) removed++;
+ }
+ if (removed > 0) {
+ if (removed == bullets.length) {
+ bullets = null;
+ } else {
+ Bullet[] newBulletsList = new Bullet[bullets.length - removed];
+ for (int i = 0, j = 0; i < bullets.length; i++) {
+ Bullet bullet = bullets[i];
+ if (bullet.size() > 0) newBulletsList[j++] = bullet;
+ }
+ bullets = newBulletsList;
+ }
+ }
+}
+void updateRanges(int start, int replaceCharCount, int newCharCount) {
+ if (styleCount == 0 || (replaceCharCount == 0 && newCharCount == 0)) return;
+ if (ranges != null) {
+ int rangeCount = styleCount << 1;
+ int modifyStart = getRangeIndex(start, -1, rangeCount);
+ if (modifyStart == rangeCount) return;
+ int end = start + replaceCharCount;
+ int modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
+ int offset = newCharCount - replaceCharCount;
+ if (modifyStart == modifyEnd && ranges[modifyStart] < start && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+ if (newCharCount == 0) {
+ ranges[modifyStart + 1] -= replaceCharCount;
+ modifyEnd += 2;
+ } else {
+ if (rangeCount + 2 > ranges.length) {
+ int[] newRanges = new int[ranges.length + (GROW << 1)];
+ System.arraycopy(ranges, 0, newRanges, 0, rangeCount);
+ ranges = newRanges;
+ StyleRange[] newStyles = new StyleRange[styles.length + GROW];
+ System.arraycopy(styles, 0, newStyles, 0, styleCount);
+ styles = newStyles;
+ }
+ System.arraycopy(ranges, modifyStart + 2, ranges, modifyStart + 4, rangeCount - (modifyStart + 2));
+ System.arraycopy(styles, (modifyStart + 2) >> 1, styles, (modifyStart + 4) >> 1, styleCount - ((modifyStart + 2) >> 1));
+ ranges[modifyStart + 3] = ranges[modifyStart] + ranges[modifyStart + 1] - end;
+ ranges[modifyStart + 2] = start + newCharCount;
+ ranges[modifyStart + 1] = start - ranges[modifyStart];
+ styles[(modifyStart >> 1) + 1] = styles[modifyStart >> 1];
+ rangeCount += 2;
+ styleCount++;
+ modifyEnd += 4;
+ }
+ if (offset != 0) {
+ for (int i = modifyEnd; i < rangeCount; i += 2) {
+ ranges[i] += offset;
+ }
+ }
+ } else {
+ if (ranges[modifyStart] < start && start < ranges[modifyStart] + ranges[modifyStart + 1]) {
+ ranges[modifyStart + 1] = start - ranges[modifyStart];
+ modifyStart += 2;
+ }
+ if (modifyEnd < rangeCount && ranges[modifyEnd] < end && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+ ranges[modifyEnd + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - end;
+ ranges[modifyEnd] = end;
+ }
+ if (offset != 0) {
+ for (int i = modifyEnd; i < rangeCount; i += 2) {
+ ranges[i] += offset;
+ }
+ }
+ System.arraycopy(ranges, modifyEnd, ranges, modifyStart, rangeCount - modifyEnd);
+ System.arraycopy(styles, modifyEnd >> 1, styles, modifyStart >> 1, styleCount - (modifyEnd >> 1));
+ styleCount -= (modifyEnd - modifyStart) >> 1;
+ }
+ } else {
+ int modifyStart = getRangeIndex(start, -1, styleCount);
+ if (modifyStart == styleCount) return;
+ int end = start + replaceCharCount;
+ int modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
+ int offset = newCharCount - replaceCharCount;
+ if (modifyStart == modifyEnd && styles[modifyStart].start < start && end < styles[modifyEnd].start + styles[modifyEnd].length) {
+ if (newCharCount == 0) {
+ styles[modifyStart].length -= replaceCharCount;
+ modifyEnd++;
+ } else {
+ if (styleCount + 1 > styles.length) {
+ StyleRange[] newStyles = new StyleRange[styles.length + GROW];
+ System.arraycopy(styles, 0, newStyles, 0, styleCount);
+ styles = newStyles;
+ }
+ System.arraycopy(styles, modifyStart + 1, styles, modifyStart + 2, styleCount - (modifyStart + 1));
+ styles[modifyStart + 1] = (StyleRange)styles[modifyStart].clone();
+ styles[modifyStart + 1].length = styles[modifyStart].start + styles[modifyStart].length - end;
+ styles[modifyStart + 1].start = start + newCharCount;
+ styles[modifyStart].length = start - styles[modifyStart].start;
+ styleCount++;
+ modifyEnd += 2;
+ }
+ if (offset != 0) {
+ for (int i = modifyEnd; i < styleCount; i++) {
+ styles[i].start += offset;
+ }
+ }
+ } else {
+ if (styles[modifyStart].start < start && start < styles[modifyStart].start + styles[modifyStart].length) {
+ styles[modifyStart].length = start - styles[modifyStart].start;
+ modifyStart++;
+ }
+ if (modifyEnd < styleCount && styles[modifyEnd].start < end && end < styles[modifyEnd].start + styles[modifyEnd].length) {
+ styles[modifyEnd].length = styles[modifyEnd].start + styles[modifyEnd].length - end;
+ styles[modifyEnd].start = end;
+ }
+ if (offset != 0) {
+ for (int i = modifyEnd; i < styleCount; i++) {
+ styles[i].start += offset;
+ }
+ }
+ System.arraycopy(styles, modifyEnd, styles, modifyStart, styleCount - modifyEnd);
+ styleCount -= modifyEnd - modifyStart;
+ }
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/ByteArrayTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/ByteArrayTransfer.java
new file mode 100644
index 00000000000..73c4bf6f9e1
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/ByteArrayTransfer.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+
+
+/**
+ * The class ByteArrayTransfer provides a platform specific
+ * mechanism for converting a java byte[] to a platform
+ * specific representation of the byte array and vice versa. See
+ * Transfer for additional information.
+ *
+ *
ByteArrayTransfer is never used directly but is sub-classed
+ * by transfer agents that convert between data in a java format such as a
+ * String and a platform specific byte array.
+ *
+ *
If the data you are converting does not map to a
+ * byte[], you should sub-class Transfer directly
+ * and do your own mapping to a platform data type.
+ *
+ *
The following snippet shows a subclass of ByteArrayTransfer that transfers
+ * data defined by the class MyType.
+ *
+ *
+ * public class MyType {
+ * public String fileName;
+ * public long fileLength;
+ * public long lastModified;
+ * }
+ *
+ *
+ *
+ * public class MyTypeTransfer extends ByteArrayTransfer {
+ *
+ * private static final String MYTYPENAME = "my_type_name";
+ * private static final int MYTYPEID = registerType(MYTYPENAME);
+ * private static MyTypeTransfer _instance = new MyTypeTransfer();
+ *
+ * private MyTypeTransfer() {}
+ *
+ * public static MyTypeTransfer getInstance () {
+ * return _instance;
+ * }
+ * public void javaToNative (Object object, TransferData transferData) {
+ * if (object == null || !(object instanceof MyType[])) return;
+ *
+ * if (isSupportedType(transferData)) {
+ * MyType[] myTypes = (MyType[]) object;
+ * try {
+ * // write data to a byte array and then ask super to convert to pMedium
+ * ByteArrayOutputStream out = new ByteArrayOutputStream();
+ * DataOutputStream writeOut = new DataOutputStream(out);
+ * for (int i = 0, length = myTypes.length; i < length; i++){
+ * byte[] buffer = myTypes[i].fileName.getBytes();
+ * writeOut.writeInt(buffer.length);
+ * writeOut.write(buffer);
+ * writeOut.writeLong(myTypes[i].fileLength);
+ * writeOut.writeLong(myTypes[i].lastModified);
+ * }
+ * byte[] buffer = out.toByteArray();
+ * writeOut.close();
+ *
+ * super.javaToNative(buffer, transferData);
+ *
+ * } catch (IOException e) {
+ * }
+ * }
+ * }
+ * public Object nativeToJava(TransferData transferData){
+ *
+ * if (isSupportedType(transferData)) {
+ *
+ * byte[] buffer = (byte[])super.nativeToJava(transferData);
+ * if (buffer == null) return null;
+ *
+ * MyType[] myData = new MyType[0];
+ * try {
+ * ByteArrayInputStream in = new ByteArrayInputStream(buffer);
+ * DataInputStream readIn = new DataInputStream(in);
+ * while(readIn.available() > 20) {
+ * MyType datum = new MyType();
+ * int size = readIn.readInt();
+ * byte[] name = new byte[size];
+ * readIn.read(name);
+ * datum.fileName = new String(name);
+ * datum.fileLength = readIn.readLong();
+ * datum.lastModified = readIn.readLong();
+ * MyType[] newMyData = new MyType[myData.length + 1];
+ * System.arraycopy(myData, 0, newMyData, 0, myData.length);
+ * newMyData[myData.length] = datum;
+ * myData = newMyData;
+ * }
+ * readIn.close();
+ * } catch (IOException ex) {
+ * return null;
+ * }
+ * return myData;
+ * }
+ *
+ * return null;
+ * }
+ * protected String[] getTypeNames(){
+ * return new String[]{MYTYPENAME};
+ * }
+ * protected int[] getTypeIds(){
+ * return new int[] {MYTYPEID};
+ * }
+ * }
+ *
+ */
+public abstract class ByteArrayTransfer extends Transfer {
+
+public TransferData[] getSupportedTypes() {
+ TransferData transferData = new TransferData();
+ // TODO: how to obtain the list of types?
+ transferData.dataFlavor = byteArrayDataFlavor;
+ return new TransferData[] {transferData};
+// int[] types = getTypeNames();
+// TransferData[] data = new TransferData[names.length];
+// for (int i = 0; i < names.length; i++) {
+// data[i] = new TransferData();
+// data[i].type = types[i];
+// }
+// return data;
+}
+
+DataFlavor byteArrayDataFlavor = new DataFlavor(byte[].class, "Bytes");
+
+protected DataFlavor getDataFlavor() {
+ return byteArrayDataFlavor;
+}
+
+/**
+ * This implementation of javaToNative converts a java
+ * byte[] to a platform specific representation. For additional
+ * information see Transfer#javaToNative.
+ *
+ * @see Transfer#javaToNative
+ *
+ * @param object a java byte[] containing the data to be converted
+ * @param transferData an empty TransferData object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+protected void javaToNative (final Object object, TransferData transferData) {
+ if (!checkByteArray(object) && !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ transferData.transferable = new Transferable() {
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+ if(flavor != byteArrayDataFlavor) {
+ throw new UnsupportedFlavorException(flavor);
+ }
+ return object;
+ }
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[] {byteArrayDataFlavor};
+ }
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return flavor == byteArrayDataFlavor;
+ }
+ };
+}
+
+boolean checkByteArray(Object object) {
+ return (object != null && object instanceof byte[] && ((byte[])object).length > 0);
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Clipboard.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Clipboard.java
new file mode 100644
index 00000000000..2a3915acde4
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Clipboard.java
@@ -0,0 +1,614 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import javax.swing.SwingUtilities;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.swing.Compatibility;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * The Clipboard provides a mechanism for transferring data from one
+ * application to another or within an application.
+ *
+ *
IMPORTANT: This class is not intended to be subclassed.
+ */
+public class Clipboard {
+
+private Display display;
+
+/**
+ * Constructs a new instance of this class. Creating an instance of a Clipboard
+ * may cause system resources to be allocated depending on the platform. It is therefore
+ * mandatory that the Clipboard instance be disposed when no longer required.
+ *
+ * @param display the display on which to allocate the clipboard
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see Clipboard#dispose
+ * @see Clipboard#checkSubclass
+ */
+public Clipboard(Display display) {
+ checkSubclass ();
+ if (display == null) {
+ display = Display.getCurrent();
+ if (display == null) {
+ display = Display.getDefault();
+ }
+ }
+ if (display.getThread() != Thread.currentThread () && !SwingUtilities.isEventDispatchThread()) DND.error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ this.display = display;
+}
+
+/**
+ * Checks that this class can be subclassed.
+ *
+ * The SWT class library is intended to be subclassed
+ * only at specific, controlled points. This method enforces this
+ * rule unless it is overridden.
+ *
+ * IMPORTANT: By providing an implementation of this
+ * method that allows a subclass of a class which does not
+ * normally allow subclassing to be created, the implementer
+ * agrees to be fully responsible for the fact that any such
+ * subclass will likely fail between SWT releases and will be
+ * strongly platform specific. No support is provided for
+ * user-written classes which are implemented in this fashion.
+ *
+ * The ability to subclass outside of the allowed SWT classes
+ * is intended purely to enable those not on the SWT development
+ * team to implement patches in order to get around specific
+ * limitations in advance of when those limitations can be
+ * addressed by the team. Subclassing should not be attempted
+ * without an intimate and detailed understanding of the hierarchy.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+protected void checkSubclass () {
+ String name = getClass().getName ();
+ String validName = Clipboard.class.getName();
+ if (!validName.equals(name)) {
+ DND.error (SWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+
+/**
+ * Throws an SWTException if the receiver can not
+ * be accessed by the caller. This may include both checks on
+ * the state of the receiver and more generally on the entire
+ * execution context. This method should be called by
+ * widget implementors to enforce the standard SWT invariants.
+ *
+ * Currently, it is an error to invoke any method (other than
+ * isDisposed()) on a widget that has had its
+ * dispose() method called. It is also an error
+ * to call widget methods from any thread that is different
+ * from the thread that created the widget.
+ *
+ * In future releases of SWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+protected void checkWidget () {
+ Display display = this.display;
+ if (display == null) DND.error (SWT.ERROR_WIDGET_DISPOSED);
+ if (display.getThread() != Thread.currentThread () && !SwingUtilities.isEventDispatchThread()) DND.error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ if (display.isDisposed()) DND.error(SWT.ERROR_WIDGET_DISPOSED);
+}
+
+/**
+ * If this clipboard is currently the owner of the data on the system clipboard,
+ * clear the contents. If this clipboard is not the owner, then nothing is done.
+ * Note that there are clipboard assistant applications that take ownership of
+ * data or make copies of data when it is placed on the clipboard. In these
+ * cases, it may not be possible to clear the clipboard.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void clearContents() {
+ clearContents(DND.CLIPBOARD);
+}
+
+/**
+ * If this clipboard is currently the owner of the data on the specified
+ * clipboard, clear the contents. If this clipboard is not the owner, then
+ * nothing is done.
+ *
+ *
Note that there are clipboard assistant applications that take ownership
+ * of data or make copies of data when it is placed on the clipboard. In these
+ * cases, it may not be possible to clear the clipboard.
+ *
+ *
The clipboards value is either one of the clipboard constants defined in
+ * class DND, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those DND clipboard constants.
+ *
+ * @param clipboards to be cleared
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public void clearContents(int clipboards) {
+ checkWidget();
+ try {
+ if ((clipboards & DND.CLIPBOARD) != 0) {
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(null, null);
+ }
+ if ((clipboards & DND.SELECTION_CLIPBOARD) != 0) {
+ java.awt.datatransfer.Clipboard systemSelection = Toolkit.getDefaultToolkit().getSystemSelection();
+ if(systemSelection != null) {
+ systemSelection.setContents(null, null);
+ }
+ }
+ } catch(Exception e) {
+ DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
+ }
+}
+
+/**
+ * Disposes of the operating system resources associated with the clipboard.
+ * The data will still be available on the system clipboard after the dispose
+ * method is called.
+ *
+ *
NOTE: On some platforms the data will not be available once the application
+ * has exited or the display has been disposed.
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
+ */
+public void dispose () {
+ if (isDisposed()) return;
+ if (display.getThread() != Thread.currentThread () && !SwingUtilities.isEventDispatchThread()) DND.error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ display = null;
+}
+
+/**
+ * Retrieve the data of the specified type currently available on the system
+ * clipboard. Refer to the specific subclass of Transfer to
+ * determine the type of object returned.
+ *
+ *
The following snippet shows text and RTF text being retrieved from the
+ * clipboard:
+ *
+ *
+ * Clipboard clipboard = new Clipboard(display);
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * String textData = (String)clipboard.getContents(textTransfer);
+ * if (textData != null) System.out.println("Text is "+textData);
+ * RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ * String rtfData = (String)clipboard.getContents(rtfTransfer);
+ * if (rtfData != null) System.out.println("RTF Text is "+rtfData);
+ * clipboard.dispose();
+ *
+ *
+ * @param transfer the transfer agent for the type of data being requested
+ * @return the data obtained from the clipboard or null if no data of this type is available
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if transfer is null
+ *
+ *
+ * @see Transfer
+ */
+public Object getContents(Transfer transfer) {
+ return getContents(transfer, DND.CLIPBOARD);
+}
+/**
+ * Retrieve the data of the specified type currently available on the specified
+ * clipboard. Refer to the specific subclass of Transfer to
+ * determine the type of object returned.
+ *
+ *
The following snippet shows text and RTF text being retrieved from the
+ * clipboard:
+ *
+ *
+ * Clipboard clipboard = new Clipboard(display);
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * String textData = (String)clipboard.getContents(textTransfer);
+ * if (textData != null) System.out.println("Text is "+textData);
+ * RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ * String rtfData = (String)clipboard.getContents(rtfTransfer, DND.CLIPBOARD);
+ * if (rtfData != null) System.out.println("RTF Text is "+rtfData);
+ * clipboard.dispose();
+ *
+ *
+ *
The clipboards value is either one of the clipboard constants defined in
+ * class DND, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those DND clipboard constants.
+ *
+ * @param transfer the transfer agent for the type of data being requested
+ * @param clipboards on which to look for data
+ *
+ * @return the data obtained from the clipboard or null if no data of this type is available
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if transfer is null
+ *
+ *
+ * @see Transfer
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public Object getContents(Transfer transfer, int clipboards) {
+ checkWidget();
+ if (transfer == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+ ArrayList clipboardList = new ArrayList();
+ if ((clipboards & DND.SELECTION_CLIPBOARD) != 0) {
+ java.awt.datatransfer.Clipboard systemSelection = Toolkit.getDefaultToolkit().getSystemSelection();
+ if(systemSelection != null) {
+ clipboardList.add(systemSelection);
+ }
+ }
+ if ((clipboards & DND.CLIPBOARD) != 0) {
+ clipboardList.add(Toolkit.getDefaultToolkit().getSystemClipboard());
+ }
+ for(int i=clipboardList.size() - 1; i >= 0; i--) {
+ java.awt.datatransfer.Clipboard clipboard = (java.awt.datatransfer.Clipboard)clipboardList.get(i);
+ TransferData[] supportedTypes = transfer.getSupportedTypes();
+ for(int j=0; jtrue if the clipboard has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the clipboard.
+ * When a clipboard has been disposed, it is an error to
+ * invoke any other method using the clipboard.
+ *
+ *
+ * @return true when the widget is disposed and false otherwise
+ *
+ * @since 3.0
+ */
+public boolean isDisposed () {
+ return (display == null);
+}
+
+/**
+ * Place data of the specified type on the system clipboard. More than one type
+ * of data can be placed on the system clipboard at the same time. Setting the
+ * data clears any previous data from the system clipboard, regardless of type.
+ *
+ *
NOTE: On some platforms, the data is immediately copied to the system
+ * clipboard but on other platforms it is provided upon request. As a result,
+ * if the application modifes the data object it has set on the clipboard, that
+ * modification may or may not be available when the data is subsequently
+ * requested.
+ *
+ *
The following snippet shows text and RTF text being set on the copy/paste
+ * clipboard:
+ *
+ *
+ * @param data the data to be set in the clipboard
+ * @param dataTypes the transfer agents that will convert the data to its
+ * platform specific format; each entry in the data array must have a
+ * corresponding dataType
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if data is null or datatypes is null
+ * or the length of data is not the same as the length of dataTypes
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception SWTError
+ *
ERROR_CANNOT_SET_CLIPBOARD - if the clipboard is locked or otherwise unavailable
+ *
+ *
+ *
NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatability.
+ */
+public void setContents(Object[] data, Transfer[] dataTypes) {
+ setContents(data, dataTypes, DND.CLIPBOARD);
+}
+
+/**
+ * Place data of the specified type on the specified clipboard. More than one
+ * type of data can be placed on the specified clipboard at the same time.
+ * Setting the data clears any previous data from the specified
+ * clipboard, regardless of type.
+ *
+ *
NOTE: On some platforms, the data is immediately copied to the specified
+ * clipboard but on other platforms it is provided upon request. As a result,
+ * if the application modifes the data object it has set on the clipboard, that
+ * modification may or may not be available when the data is subsequently
+ * requested.
+ *
+ *
The clipboards value is either one of the clipboard constants defined in
+ * class DND, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those DND clipboard constants.
+ *
+ *
The following snippet shows text and RTF text being set on the copy/paste
+ * clipboard:
+ *
+ *
+ * @param data the data to be set in the clipboard
+ * @param dataTypes the transfer agents that will convert the data to its
+ * platform specific format; each entry in the data array must have a
+ * corresponding dataType
+ * @param clipboards on which to set the data
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if data is null or datatypes is null
+ * or the length of data is not the same as the length of dataTypes
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception SWTError
+ *
ERROR_CANNOT_SET_CLIPBOARD - if the clipboard is locked or otherwise unavailable
+ *
+ *
+ *
NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatability.
+ *
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public void setContents(Object[] data, Transfer[] dataTypes, int clipboards) {
+ checkWidget();
+ if (data == null || dataTypes == null || data.length != dataTypes.length || data.length == 0) {
+ DND.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ for (int i = 0; i < data.length; i++) {
+ if (data[i] == null || dataTypes[i] == null || !dataTypes[i].validate(data[i])) {
+ DND.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ }
+ ArrayList transferableList = new ArrayList();
+ ArrayList flavorList = new ArrayList();
+ for(int i=0; i= 0; i--) {
+ java.awt.datatransfer.Clipboard clipboard = (java.awt.datatransfer.Clipboard)clipboardList.get(i);
+ clipboard.setContents(transferable, null);
+ }
+//DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
+}
+
+/**
+ * Returns an array of the data types currently available on the system
+ * clipboard. Use with Transfer.isSupportedType.
+ *
+ * @return array of data types currently available on the system clipboard
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Transfer#isSupportedType
+ *
+ * @since 3.0
+ */
+public TransferData[] getAvailableTypes() {
+ return getAvailableTypes(DND.CLIPBOARD);
+}
+
+/**
+ * Returns an array of the data types currently available on the specified
+ * clipboard. Use with Transfer.isSupportedType.
+ *
+ *
The clipboards value is either one of the clipboard constants defined in
+ * class DND, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those DND clipboard constants.
+ *
+ * @param clipboards from which to get the data types
+ * @return array of data types currently available on the specified clipboard
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Transfer#isSupportedType
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public TransferData[] getAvailableTypes(int clipboards) {
+ checkWidget();
+ ArrayList clipboardList = new ArrayList();
+ if ((clipboards & DND.SELECTION_CLIPBOARD) != 0) {
+ java.awt.datatransfer.Clipboard systemSelection = Toolkit.getDefaultToolkit().getSystemSelection();
+ if(systemSelection != null) {
+ clipboardList.add(systemSelection);
+ }
+ }
+ if ((clipboards & DND.CLIPBOARD) != 0) {
+ clipboardList.add(Toolkit.getDefaultToolkit().getSystemClipboard());
+ }
+ for(int i=clipboardList.size() - 1; i >= 0; i--) {
+ java.awt.datatransfer.Clipboard clipboard = (java.awt.datatransfer.Clipboard)clipboardList.get(i);
+ DataFlavor[] dataFlavors = clipboard.getAvailableDataFlavors();
+ TransferData[] dataArray = new TransferData[dataFlavors.length];
+ for(int j=0; jNote: getAvailableTypeNames is a utility for writing a Transfer
+ * sub-class. It should NOT be used within an application because it provides
+ * platform specific information.
+ *
+ * @return a platform specific list of the data types currently available on the
+ * system clipboard
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String[] getAvailableTypeNames() {
+ checkWidget();
+ DataFlavor[] flavors = Toolkit.getDefaultToolkit().getSystemClipboard().getAvailableDataFlavors();
+ String[] typeNames = new String[flavors.length];
+ for(int i=0; iDragSource defines the source object for a drag and drop transfer.
+ *
+ *
IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
A drag source is the object which originates a drag and drop operation. For the specified widget,
+ * it defines the type of data that is available for dragging and the set of operations that can
+ * be performed on that data. The operations can be any bit-wise combination of DND.MOVE, DND.COPY or
+ * DND.LINK. The type of data that can be transferred is specified by subclasses of Transfer such as
+ * TextTransfer or FileTransfer. The type of data transferred can be a predefined system type or it
+ * can be a type defined by the application. For instructions on how to define your own transfer type,
+ * refer to ByteArrayTransfer.
+ *
+ *
You may have several DragSources in an application but you can only have one DragSource
+ * per Control. Data dragged from this DragSource can be dropped on a site within this application
+ * or it can be dropped on another application such as an external Text editor.
+ *
+ *
The application supplies the content of the data being transferred by implementing the
+ * DragSourceListener and associating it with the DragSource via DragSource#addDragListener.
+ *
+ *
When a successful move operation occurs, the application is required to take the appropriate
+ * action to remove the data from its display and remove any associated operating system resources or
+ * internal references. Typically in a move operation, the drop target makes a copy of the data
+ * and the drag source deletes the original. However, sometimes copying the data can take a long
+ * time (such as copying a large file). Therefore, on some platforms, the drop target may actually
+ * move the data in the operating system rather than make a copy. This is usually only done in
+ * file transfers. In this case, the drag source is informed in the DragEnd event that a
+ * DROP_TARGET_MOVE was performed. It is the responsibility of the drag source at this point to clean
+ * up its displayed information. No action needs to be taken on the operating system resources.
+ *
+ *
The following example shows a Label widget that allows text to be dragged from it.
+ *
+ *
+ * // Enable a label as a Drag Source
+ * Label label = new Label(shell, SWT.NONE);
+ * // This example will allow text to be dragged
+ * Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
+ * // This example will allow the text to be copied or moved to the drop target
+ * int operations = DND.DROP_MOVE | DND.DROP_COPY;
+ *
+ * DragSource source = new DragSource(label, operations);
+ * source.setTransfer(types);
+ * source.addDragListener(new DragSourceListener() {
+ * public void dragStart(DragSourceEvent e) {
+ * // Only start the drag if there is actually text in the
+ * // label - this text will be what is dropped on the target.
+ * if (label.getText().length() == 0) {
+ * event.doit = false;
+ * }
+ * };
+ * public void dragSetData(DragSourceEvent event) {
+ * // A drop has been performed, so provide the data of the
+ * // requested type.
+ * // (Checking the type of the requested data is only
+ * // necessary if the drag source supports more than
+ * // one data type but is shown here as an example).
+ * if (TextTransfer.getInstance().isSupportedType(event.dataType)){
+ * event.data = label.getText();
+ * }
+ * }
+ * public void dragFinished(DragSourceEvent event) {
+ * // A Move operation has been performed so remove the data
+ * // from the source
+ * if (event.detail == DND.DROP_MOVE)
+ * label.setText("");
+ * }
+ * });
+ *
+ */
+public class DragSource extends Widget {
+
+ // info for registering as a drag source
+ Control control;
+ Listener controlListener;
+ Transfer[] transferAgents = new Transfer[0];
+ DragAndDropEffect effect;
+// Composite topControl;
+
+ //workaround - track the operation performed by the drop target for DragEnd event
+ int dataEffect = DND.DROP_NONE;
+
+ static final String DRAGSOURCEID = "DragSource"; //$NON-NLS-1$
+// static final int CFSTR_PERFORMEDDROPEFFECT = Transfer.registerType("Performed DropEffect"); //$NON-NLS-1$
+
+/**
+ * Creates a new DragSource to handle dragging from the specified Control.
+ * Creating an instance of a DragSource may cause system resources to be allocated depending on the platform.
+ * It is therefore mandatory that the DragSource instance be disposed when no longer required.
+ *
+ * @param control the Control that the user clicks on to initiate the drag
+ * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of
+ * DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ * @exception SWTError
+ *
ERROR_CANNOT_INIT_DRAG - unable to initiate drag source; this will occur if more than one
+ * drag source is created for a control or if the operating system will not allow the creation
+ * of the drag source
+ *
+ *
+ *
NOTE: ERROR_CANNOT_INIT_DRAG should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatability.
dragStart is called when the user has begun the actions required to drag the widget.
+ * This event gives the application the chance to decide if a drag should be started.
+ *
dragSetData is called when the data is required from the drag source.
+ *
dragFinished is called when the drop has successfully completed (mouse up
+ * over a valid target) or has been terminated (such as hitting the ESC key). Perform cleanup
+ * such as removing data from the source side on a successful move operation.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DragSourceListener
+ * @see #removeDragListener
+ * @see DragSourceEvent
+ */
+public void addDragListener(DragSourceListener listener) {
+ if (listener == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+ DNDListener typedListener = new DNDListener(listener);
+ addListener(DND.DragStart, typedListener);
+ addListener(DND.DragSetData, typedListener);
+ addListener(DND.DragEnd, typedListener);
+}
+
+@Override
+protected void checkSubclass() {
+ String name = getClass().getName();
+ String validName = DragSource.class.getName();
+ if (!validName.equals(name)) {
+ DND.error(SWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+
+Image dragCursor;
+
+
+/**
+ * Returns the Control which is registered for this DragSource. This is the control that the
+ * user clicks in to initiate dragging.
+ *
+ * @return the Control which is registered for this DragSource
+ */
+public Control getControl() {
+ return control;
+}
+
+/**
+ * Returns the list of data types that can be transferred by this DragSource.
+ *
+ * @return the list of data types that can be transferred by this DragSource
+ */
+public Transfer[] getTransfer(){
+ return transferAgents;
+}
+
+private void onDispose() {
+ if (control == null) return;
+ if (controlListener != null){
+ control.removeListener(SWT.Dispose, controlListener);
+ control.removeListener(SWT.DragDetect, controlListener);
+ }
+ controlListener = null;
+ control.setData(DRAGSOURCEID, null);
+ control = null;
+ transferAgents = null;
+ // TODO: release resources?
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a drag and drop operation is in progress.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DragSourceListener
+ * @see #addDragListener
+ */
+public void removeDragListener(DragSourceListener listener) {
+ if (listener == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+ removeListener(DND.DragStart, listener);
+ removeListener(DND.DragSetData, listener);
+ removeListener(DND.DragEnd, listener);
+}
+
+/**
+ * Specifies the list of data types that can be transferred by this DragSource.
+ * The application must be able to provide data to match each of these types when
+ * a successful drop has occurred.
+ *
+ * @param transferAgents a list of Transfer objects which define the types of data that can be
+ * dragged from this source
+ */
+public void setTransfer(Transfer[] transferAgents){
+ this.transferAgents = transferAgents;
+}
+
+class SWTDragGestureRecognizer extends MouseDragGestureRecognizer {
+ protected SWTDragGestureRecognizer(java.awt.dnd.DragSource dragsource, Component component, int actions, DragGestureListener draggesturelistener) {
+ super(dragsource, component, actions, draggesturelistener);
+ }
+ @Override
+public void mouseClicked(MouseEvent e) {
+ }
+ @Override
+public void mousePressed(MouseEvent e) {
+ events.clear();
+ if(getDragAction(e) != 0) {
+ appendEvent(e);
+ }
+ }
+ @Override
+public void mouseReleased(MouseEvent e) {
+ events.clear();
+ }
+ @Override
+public void mouseEntered(MouseEvent e) {
+ events.clear();
+ }
+ @Override
+public void mouseExited(MouseEvent e) {
+ if(!events.isEmpty()) {
+ int dragAction = getDragAction(e);
+ if(dragAction == 0) {
+ events.clear();
+ }
+ }
+ }
+ @Override
+public void mouseDragged(MouseEvent e) {
+ if(!events.isEmpty()) {
+ int dragAction = getDragAction(e);
+ if(dragAction == 0) {
+ return;
+ }
+// MouseEvent me = (MouseEvent)events.get(0);
+// Point p1 = e.getPoint();
+// Point p2 = me.getPoint();
+// int j = Math.abs(p2.x - p1.x);
+// int k = Math.abs(p2.y - p1.y);
+// if(j > 0 || k > 0) {
+ fireDragGestureRecognized(dragAction, ((MouseEvent)getTriggerEvent()).getPoint());
+// } else {
+// appendEvent(e);
+// }
+ }
+ }
+ @Override
+public void mouseMoved(MouseEvent mouseevent) {
+ }
+ protected int getDragAction(MouseEvent e) {
+ int modifiers = e.getModifiersEx();
+ if((modifiers & MouseEvent.BUTTON1_DOWN_MASK) == 0) {
+ return 0;
+ }
+ int dropAction = 0;
+ int sourceActions = getSourceActions();
+ switch(modifiers & (MouseEvent.SHIFT_DOWN_MASK | MouseEvent.CTRL_DOWN_MASK)) {
+ case MouseEvent.CTRL_DOWN_MASK:
+ dropAction = DnDConstants.ACTION_COPY;
+ break;
+ case MouseEvent.SHIFT_DOWN_MASK:
+ dropAction = DnDConstants.ACTION_MOVE;
+ break;
+ case MouseEvent.SHIFT_DOWN_MASK | MouseEvent.CTRL_DOWN_MASK:
+ dropAction = DnDConstants.ACTION_LINK;
+ break;
+ default:
+ if((sourceActions & DnDConstants.ACTION_COPY) != 0) {
+ dropAction = DnDConstants.ACTION_COPY;
+ break;
+ }
+ if((sourceActions & DnDConstants.ACTION_MOVE) != 0) {
+ dropAction = DnDConstants.ACTION_MOVE;
+ break;
+ }
+ if((sourceActions & DnDConstants.ACTION_LINK) != 0)
+ dropAction = DnDConstants.ACTION_LINK;
+ break;
+ }
+ return dropAction & sourceActions;
+ }
+}
+
+class SWTDragGestureListener implements DragGestureListener {
+ @Override
+public void dragGestureRecognized(DragGestureEvent e) {
+ if (DragSource.this.isDisposed()) {
+ return;
+ }
+ java.awt.Point dragOrigin = e.getDragOrigin();
+ DNDEvent event = new DNDEvent();
+ event.widget = DragSource.this;
+ event.x = dragOrigin.x;
+ event.y = dragOrigin.y;
+ event.time = Utils.getCurrentTime();
+ event.doit = true;
+ notifyListeners(DND.DragStart,event);
+ if (!event.doit || transferAgents == null || transferAgents.length == 0 ) return;
+ TransferData transferData = new TransferData();
+ event = new DNDEvent();
+ event.widget = DragSource.this;
+ event.time = Utils.getCurrentTime();
+ event.dataType = transferData;
+ notifyListeners(DND.DragSetData,event);
+ // START - copy from clipboard
+ // TODO: refactor to share code?
+ ArrayList transferableList = new ArrayList();
+ ArrayList flavorList = new ArrayList();
+ for(int i=0; iDropTarget defines the target object for a drag and drop transfer.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
This class identifies the Control over which the user must position the cursor
+ * in order to drop the data being transferred. It also specifies what data types can be dropped on
+ * this control and what operations can be performed. You may have several DropTragets in an
+ * application but there can only be a one to one mapping between a Control and a DropTarget.
+ * The DropTarget can receive data from within the same application or from other applications
+ * (such as text dragged from a text editor like Word).
The application is notified of data being dragged over this control and of when a drop occurs by
+ * implementing the interface DropTargetListener which uses the class
+ * DropTargetEvent. The application can modify the type of drag being performed
+ * on this Control at any stage of the drag by modifying the event.detail field or the
+ * event.currentDataType field. When the data is dropped, it is the responsibility of
+ * the application to copy this data for its own purposes.
+ *
+ *
+ * target.addDropListener (new DropTargetListener() {
+ * public void dragEnter(DropTargetEvent event) {};
+ * public void dragOver(DropTargetEvent event) {};
+ * public void dragLeave(DropTargetEvent event) {};
+ * public void dragOperationChanged(DropTargetEvent event) {};
+ * public void dropAccept(DropTargetEvent event) {}
+ * public void drop(DropTargetEvent event) {
+ * // A drop has occurred, copy over the data
+ * if (event.data == null) { // no data to copy, indicate failure in event.detail
+ * event.detail = DND.DROP_NONE;
+ * return;
+ * }
+ * label.setText ((String) event.data); // data copied to label text
+ * }
+ * });
+ *
+ */
+public class DropTarget extends Widget {
+
+ Control control;
+ Listener controlListener;
+ Transfer[] transferAgents = new Transfer[0];
+ DragAndDropEffect effect;
+
+// // Track application selections
+// TransferData selectedDataType;
+// int selectedOperation;
+
+ static final String DROPTARGETID = "DropTarget"; //$NON-NLS-1$
+
+/**
+ * Creates a new DropTarget to allow data to be dropped on the specified
+ * Control.
+ * Creating an instance of a DropTarget may cause system resources to be allocated
+ * depending on the platform. It is therefore mandatory that the DropTarget instance
+ * be disposed when no longer required.
+ *
+ * @param control the Control over which the user positions the cursor to drop the data
+ * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of
+ * DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ * @exception SWTError
+ *
ERROR_CANNOT_INIT_DROP - unable to initiate drop target; this will occur if more than one
+ * drop target is created for a control or if the operating system will not allow the creation
+ * of the drop target
+ *
+ *
+ *
NOTE: ERROR_CANNOT_INIT_DROP should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatability.
+ *
+ * @see Widget#dispose
+ * @see DropTarget#checkSubclass
+ * @see DND#DROP_NONE
+ * @see DND#DROP_COPY
+ * @see DND#DROP_MOVE
+ * @see DND#DROP_LINK
+ */
+public DropTarget(Control control, int style) {
+ super (control, checkStyle(style));
+ this.control = control;
+ if (control.getData(DROPTARGETID) != null) {
+ DND.error(DND.ERROR_CANNOT_INIT_DROP);
+ }
+ control.setData(DROPTARGETID, this);
+ controlListener = event -> {
+ if (!DropTarget.this.isDisposed()){
+ DropTarget.this.dispose();
+ }
+ };
+ control.addListener (SWT.Dispose, controlListener);
+ this.addListener(SWT.Dispose, event -> onDispose());
+ new java.awt.dnd.DropTarget(((CControl)control.handle).getSwingComponent(), Utils.convertDnDActionsToSwing(style), new java.awt.dnd.DropTargetListener() {
+ @Override
+ public void dragEnter(java.awt.dnd.DropTargetDragEvent e) {
+ lastAction = DND.DROP_DEFAULT;
+ processDropTargetDragEvent(e, DND.DragEnter);
+ }
+ @Override
+ public void dragOver(DropTargetDragEvent e) {
+ processDropTargetDragEvent(e, DND.DragOver);
+ }
+ @Override
+ public void dropActionChanged(DropTargetDragEvent e) {
+ processDropTargetDragEvent(e, DND.DragOperationChanged);
+ }
+ public void processDropTargetDragEvent(java.awt.dnd.DropTargetDragEvent e, int notificationType) {
+ DNDEvent event = new DNDEvent();
+ if(setDragEventData(event, e)) {
+ int allowedOperations = event.operations;
+ notifyListeners(notificationType, event);
+ if(Utils.isLocalDragAndDropInProgress && !hasMetas()) {
+ lastAction = event.detail;
+ }
+ if (event.detail == DND.DROP_DEFAULT) {
+ event.detail = (allowedOperations & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE;
+ }
+ int action = 0;
+ if ((allowedOperations & event.detail) != 0) {
+ action = Utils.convertDnDActionsToSwing(event.detail);
+ }
+ if(action == 0) {
+ e.rejectDrag();
+ } else {
+ e.acceptDrag(action);
+ }
+ effect.showDropTargetEffect(event.feedback, event.x, event.y);
+ } else {
+ e.rejectDrag();
+ }
+ }
+ @Override
+ public void dragExit(java.awt.dnd.DropTargetEvent e) {
+ DNDEvent event = new DNDEvent();
+ event.widget = DropTarget.this;
+ event.time = Utils.getCurrentTime();
+ event.detail = DND.DROP_NONE;
+ notifyListeners(DND.DragLeave, event);
+ }
+ @Override
+ public void drop(DropTargetDropEvent e) {
+ DNDEvent event = new DNDEvent();
+ if(!setDropEventData(event, e)) {
+ e.rejectDrop();
+ e.dropComplete(false);
+ }
+ int allowedOperations = event.operations;
+ int action = 0;
+ if (event.detail == DND.DROP_DEFAULT) {
+ event.detail = (allowedOperations & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE;
+ }
+ if ((allowedOperations & event.detail) != 0) {
+ action = Utils.convertDnDActionsToSwing(event.detail);
+ }
+ if(action == 0) {
+ e.rejectDrop();
+ e.dropComplete(true);
+ return;
+ }
+ // We accept the drop as a move, to be able to move the data if the user changes the detail of the event to a move.
+ boolean isLocalTransfer = e.isLocalTransfer();
+ e.acceptDrop(isLocalTransfer? action: DnDConstants.ACTION_MOVE);
+ Object object = null;
+ for (int i = 0; i < transferAgents.length; i++){
+ if (transferAgents[i].isSupportedType(event.dataType)) {
+ object = transferAgents[i].nativeToJava(event.dataType);
+ break;
+ }
+ }
+ if (object == null){
+ event.detail = DND.DROP_NONE;
+ }
+ try {
+ event.data = object;
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ }
+ notifyListeners(DND.Drop, event);
+ // We validated the drop only if it is a move, so that the initiator deletes the data on its side.
+ if(event.detail == DND.DROP_MOVE) {
+ e.dropComplete(true);
+ }
+ effect.showDropTargetEffect(event.feedback, event.x, event.y);
+ }
+ }, true);
+ // Drag under effect
+// if (control instanceof Tree) {
+// effect = new TreeDragAndDropEffect((Tree)control);
+// } else if (control instanceof Table) {
+// effect = new TableDragAndDropEffect((Table)control);
+// } else if (control instanceof StyledText) {
+// effect = new StyledTextDragAndDropEffect((StyledText)control);
+// } else {
+ effect = new NoDragAndDropEffect(control);
+// }
+}
+
+protected int lastAction;
+
+protected boolean hasMetas() {
+ return (Utils.modifiersEx & (KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)) != 0;
+}
+
+boolean setDragEventData(DNDEvent event, java.awt.dnd.DropTargetDragEvent e) {
+ ArrayList transferDataList = new ArrayList();
+ Transferable transferable = e.getTransferable();
+ DataFlavor[] flavors = transferable.getTransferDataFlavors();
+ for(int i=0; iDropTargetListener
+ * interface.
+ *
+ *
+ *
dragEnter is called when the cursor has entered the drop target boundaries
+ *
dragLeave is called when the cursor has left the drop target boundaries and just before
+ * the drop occurs or is cancelled.
+ *
dragOperationChanged is called when the operation being performed has changed
+ * (usually due to the user changing the selected modifier key(s) while dragging)
+ *
dragOver is called when the cursor is moving over the drop target
+ *
dropAccept is called just before the drop is performed. The drop target is given
+ * the chance to change the nature of the drop or veto the drop by setting the event.detail field
+ *
drop is called when the data is being dropped
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DropTargetListener
+ * @see #removeDropListener
+ * @see DropTargetEvent
+ */
+public void addDropListener(DropTargetListener listener) {
+ if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT);
+ DNDListener typedListener = new DNDListener (listener);
+ addListener (DND.DragEnter, typedListener);
+ addListener (DND.DragLeave, typedListener);
+ addListener (DND.DragOver, typedListener);
+ addListener (DND.DragOperationChanged, typedListener);
+ addListener (DND.Drop, typedListener);
+ addListener (DND.DropAccept, typedListener);
+}
+
+@Override
+protected void checkSubclass () {
+ String name = getClass().getName ();
+ String validName = DropTarget.class.getName();
+ if (!validName.equals(name)) {
+ DND.error (SWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+
+/**
+ * Returns the Control which is registered for this DropTarget. This is the control over which the
+ * user positions the cursor to drop the data.
+ *
+ * @return the Control which is registered for this DropTarget
+ */
+public Control getControl () {
+ return control;
+}
+
+/**
+ * Returns a list of the data types that can be transferred to this DropTarget.
+ *
+ * @return a list of the data types that can be transferred to this DropTarget
+ */
+public Transfer[] getTransfer() {
+ return transferAgents;
+}
+
+void onDispose () {
+ if (control == null) return;
+ if (controlListener != null)
+ control.removeListener(SWT.Dispose, controlListener);
+ controlListener = null;
+ control.setData(DROPTARGETID, null);
+ transferAgents = null;
+ control = null;
+ // TODO: release resources?
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a drag and drop operation is in progress.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DropTargetListener
+ * @see #addDropListener
+ */
+public void removeDropListener(DropTargetListener listener) {
+ if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT);
+ removeListener (DND.DragEnter, listener);
+ removeListener (DND.DragLeave, listener);
+ removeListener (DND.DragOver, listener);
+ removeListener (DND.DragOperationChanged, listener);
+ removeListener (DND.Drop, listener);
+ removeListener (DND.DropAccept, listener);
+}
+
+/**
+ * Specifies the data types that can be transferred to this DropTarget. If data is
+ * being dragged that does not match one of these types, the drop target will be notified of
+ * the drag and drop operation but the currentDataType will be null and the operation
+ * will be DND.NONE.
+ *
+ * @param transferAgents a list of Transfer objects which define the types of data that can be
+ * dropped on this target
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if transferAgents is null
+ *
+ */
+public void setTransfer(Transfer[] transferAgents){
+ if (transferAgents == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+ this.transferAgents = transferAgents;
+}
+
+public DropTargetEffect getDropTargetEffect() {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/FileTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/FileTransfer.java
new file mode 100644
index 00000000000..d0215950d16
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/FileTransfer.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The class FileTransfer provides a platform specific mechanism
+ * for converting a list of files represented as a java String[] to a
+ * platform specific representation of the data and vice versa.
+ * Each String in the array contains the absolute path for a single
+ * file or directory.
+ * See Transfer for additional information.
+ *
+ *
An example of a java String[] containing a list of files is shown
+ * below:
+ */
+public class FileTransfer extends ByteArrayTransfer {
+
+ private static FileTransfer _instance = new FileTransfer();
+
+private FileTransfer() {}
+
+/**
+ * Returns the singleton instance of the FileTransfer class.
+ *
+ * @return the singleton instance of the FileTransfer class
+ */
+public static FileTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative converts a list of file names
+ * represented by a java String[] to a platform specific representation.
+ * Each String in the array contains the absolute path for a single
+ * file or directory. For additional information see
+ * Transfer#javaToNative.
+ *
+ * @param object a java String[] containing the file names to be
+ * converted
+ * @param transferData an empty TransferData object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+public void javaToNative(Object object, TransferData transferData) {
+ if (!checkFile(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ String[] fileNames = (String[]) object;
+ final List fileList = new ArrayList(fileNames.length);
+ for(int i=0; inativeToJava converts a platform specific
+ * representation of a list of file names to a java String[].
+ * Each String in the array contains the absolute path for a single file or directory.
+ * For additional information see Transfer#nativeToJava.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java String[] containing a list of file names if the
+ * conversion was successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData) || transferData.transferable == null) return null;
+ List fileList = (List)super.nativeToJava(transferData);
+ File[] files = (File[])fileList.toArray(new File[0]);
+ String[] fileNames = new String[files.length];
+ for(int i=0; iHTMLTransfer provides a platform specific mechanism
+ * for converting text in HTML format represented as a java String
+ * to a platform specific representation of the data and vice versa. See
+ * Transfer for additional information.
+ *
+ *
An example of a java String containing HTML text is shown
+ * below:
+ *
+ *
+ * String htmlData = "
This is a paragraph of text.
";
+ *
+ */
+public class HTMLTransfer extends Transfer {
+
+private static HTMLTransfer _instance = new HTMLTransfer();
+
+private HTMLTransfer() {}
+
+/**
+ * Returns the singleton instance of the HTMLTransfer class.
+ *
+ * @return the singleton instance of the HTMLTransfer class
+ */
+public static HTMLTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative converts HTML-formatted text
+ * represented by a java String to a platform specific representation.
+ * For additional information see Transfer#javaToNative.
+ *
+ * @param object a java String containing HTML text
+ * @param transferData an empty TransferData object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkHTML(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ transferData.transferable = new StringSelection((String)object);
+}
+
+/**
+ * This implementation of nativeToJava converts a platform specific
+ * representation of HTML text to a java String.
+ * For additional information see Transfer#nativeToJava.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java String containing HTML text if the
+ * conversion was successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData){
+ Object o = super.nativeToJava(transferData);
+ if(o instanceof Reader) {
+ StringBuilder sb = new StringBuilder();
+ Reader reader = (Reader)o;
+ char[] chars = new char[128];
+ try {
+ for(int i; (i=reader.read(chars)) != -1; ) {
+ sb.append(chars, 0, i);
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ return sb.toString();
+ }
+ return o;
+}
+
+boolean checkHTML(Object object) {
+ return (object != null && object instanceof String && ((String)object).length() > 0);
+}
+
+protected boolean validate(Object object) {
+ return checkHTML(object);
+}
+
+static DataFlavor HTML_FLAVOR_1 = new DataFlavor("text/html; class=java.lang.String", "HTML Text");
+//static DataFlavor HTML_FLAVOR_2 = new DataFlavor("text/html; class=java.io.Reader", "HTML Text");
+
+public TransferData[] getSupportedTypes() {
+ TransferData data1 = new TransferData();
+ data1.dataFlavor = HTML_FLAVOR_1;
+ return new TransferData[] {data1};
+// TransferData data2 = new TransferData();
+// data2.dataFlavor = HTML_FLAVOR_2;
+// return new TransferData[] {data1, data2};
+}
+
+protected DataFlavor getDataFlavor() {
+ return HTML_FLAVOR_1;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/NoDragAndDropEffect.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/NoDragAndDropEffect.java
new file mode 100644
index 00000000000..07e96a18ba3
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/NoDragAndDropEffect.java
@@ -0,0 +1,11 @@
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.widgets.*;
+
+public class NoDragAndDropEffect extends DragAndDropEffect {
+
+ public NoDragAndDropEffect(Control control) {
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/RTFTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/RTFTransfer.java
new file mode 100644
index 00000000000..f619b35825c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/RTFTransfer.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * The class RTFTransfer provides a platform specific mechanism
+ * for converting text in RTF format represented as a java String
+ * to a platform specific representation of the data and vice versa. See
+ * Transfer for additional information.
+ *
+ *
An example of a java String containing RTF text is shown
+ * below:
+ */
+public class RTFTransfer extends Transfer {
+
+private static RTFTransfer _instance = new RTFTransfer();
+
+private RTFTransfer() {}
+
+/**
+ * Returns the singleton instance of the RTFTransfer class.
+ *
+ * @return the singleton instance of the RTFTransfer class
+ */
+public static RTFTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative converts RTF-formatted text
+ * represented by a java String to a platform specific representation.
+ * For additional information see Transfer#javaToNative.
+ *
+ * @param object a java String containing RTF text
+ * @param transferData an empty TransferData object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+public void javaToNative (final Object object, TransferData transferData){
+ if (!checkRTF(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ transferData.transferable = new Transferable() {
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+ if(!isDataFlavorSupported(flavor)) {
+ throw new UnsupportedFlavorException(flavor);
+ }
+ return new ByteArrayInputStream(((String)object).getBytes());
+ }
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return getDataFlavor().equals(flavor);
+ }
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[] {getDataFlavor()};
+ }
+ };
+}
+
+/**
+ * This implementation of nativeToJava converts a platform specific
+ * representation of RTF text to a java String.
+ * For additional information see Transfer#nativeToJava.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java String containing RTF text if the
+ * conversion was successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.transferable == null) return null;
+ InputStreamReader reader = new InputStreamReader((ByteArrayInputStream)super.nativeToJava(transferData));
+ StringBuilder sb = new StringBuilder();
+ char[] chars = new char[128];
+ try {
+ for(int i; (i=reader.read(chars)) != -1; ) {
+ sb.append(chars, 0, i);
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ return sb.toString();
+}
+
+boolean checkRTF(Object object) {
+ return (object != null && object instanceof String && ((String)object).length() > 0);
+}
+
+protected boolean validate(Object object) {
+ return checkRTF(object);
+}
+
+static DataFlavor RTF_FLAVOR = new DataFlavor("text/rtf", "RTF Text");
+
+public TransferData[] getSupportedTypes() {
+ TransferData data = new TransferData();
+ data.dataFlavor = RTF_FLAVOR;
+ return new TransferData[] {data};
+}
+
+protected DataFlavor getDataFlavor() {
+ return RTF_FLAVOR;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TextTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TextTransfer.java
new file mode 100644
index 00000000000..14158e2f743
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TextTransfer.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+
+/**
+ * The class TextTransfer provides a platform specific mechanism
+ * for converting plain text represented as a java String
+ * to a platform specific representation of the data and vice versa.
+ *
+ *
An example of a java String containing plain text is shown
+ * below:
+ *
+ *
+ * String textData = "Hello World";
+ *
+ *
+ * @see Transfer
+ */
+public class TextTransfer extends Transfer {
+
+private static TextTransfer _instance = new TextTransfer();
+
+private TextTransfer() {}
+
+/**
+ * Returns the singleton instance of the TextTransfer class.
+ *
+ * @return the singleton instance of the TextTransfer class
+ */
+public static TextTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative converts plain text
+ * represented by a java String to a platform specific representation.
+ *
+ * @param object a java String containing text
+ * @param transferData an empty TransferData object; this object
+ * will be filled in on return with the platform specific format of the data
+ *
+ * @see Transfer#javaToNative
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkText(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ transferData.transferable = new StringSelection((String)object);
+}
+
+/**
+ * This implementation of nativeToJava converts a platform specific
+ * representation of plain text to a java String.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java String containing text if the conversion was successful; otherwise null
+ *
+ * @see Transfer#nativeToJava
+ */
+public Object nativeToJava(TransferData transferData){
+ return super.nativeToJava(transferData);
+}
+
+boolean checkText(Object object) {
+ return (object != null && object instanceof String && ((String)object).length() > 0);
+}
+
+protected boolean validate(Object object) {
+ return checkText(object);
+}
+
+public TransferData[] getSupportedTypes() {
+ TransferData data = new TransferData();
+ data.dataFlavor = DataFlavor.stringFlavor;
+ return new TransferData[] {data};
+}
+
+protected DataFlavor getDataFlavor() {
+ return DataFlavor.stringFlavor;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Transfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Transfer.java
new file mode 100644
index 00000000000..34fecc0973b
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/Transfer.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+
+/**
+ * Transfer provides a mechanism for converting between a java
+ * representation of data and a platform specific representation of data and
+ * vice versa. It is used in data transfer operations such as drag and drop and
+ * clipboard copy/paste.
+ *
+ *
You should only need to become familiar with this class if you are
+ * implementing a Transfer subclass and you are unable to subclass the
+ * ByteArrayTransfer class.
+ *
+ * @see ByteArrayTransfer
+ */
+public abstract class Transfer {
+
+abstract protected DataFlavor getDataFlavor();
+
+/**
+ * Returns a list of the platform specific data types that can be converted using
+ * this transfer agent.
+ *
+ *
Only the dataFlavor fields of the TransferData objects are filled
+ * in.
+ *
+ * @return a list of the data types that can be converted using this transfer agent
+ */
+abstract public TransferData[] getSupportedTypes();
+
+/**
+ * Returns true if the TransferData data type can be converted
+ * using this transfer agent, or false otherwise (including if transferData is
+ * null).
+ *
+ * @param transferData a platform specific description of a data type; only the
+ * dataFlavor fields of the TransferData object need to be filled in.
+ *
+ * @return true if the transferData data type can be converted using this transfer
+ * agent
+ */
+public boolean isSupportedType(TransferData transferData) {
+ TransferData[] types = getSupportedTypes();
+ for(int i=0; iOn a successful conversion, the transferData.result field will be set as follows:
+ *
+ *
Windows: COM.S_OK
+ *
Motif: 1
+ *
GTK: 1
+ *
Photon: 1
+ *
+ *
+ *
If this transfer agent is unable to perform the conversion, the transferData.result
+ * field will be set to a failure value as follows:
+ *
+ *
Windows: COM.DV_E_TYMED or COM.E_FAIL
+ *
Motif: 0
+ *
GTK: 0
+ *
Photon: 0
+ *
+ *
+ * @param object a java representation of the data to be converted; the type of
+ * Object that is passed in is dependant on the Transfer subclass.
+ *
+ * @param transferData an empty TransferData object; this object will be
+ * filled in on return with the platform specific representation of the data
+ *
+ * @exception org.eclipse.swt.SWTException
+ *
ERROR_INVALID_DATA - if object does not contain data in a valid format or is null
+ *
+ */
+abstract protected void javaToNative (Object object, TransferData transferData);
+
+/**
+ * Converts a platform specific representation of data to a java representation.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * converted
+ *
+ * @return a java representation of the converted data if the conversion was
+ * successful; otherwise null. If transferData is null then
+ * null is returned. The type of Object that is returned is
+ * dependant on the Transfer subclass.
+ */
+protected Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.transferable == null) return null;
+ try {
+ return transferData.transferable.getTransferData(getDataFlavor());
+ } catch(UnsupportedFlavorException e) {
+ } catch(IOException e) {}
+ return null;
+}
+
+/**
+ * Registers a name for a data type and returns the associated unique identifier.
+ *
+ *
You may register the same type more than once, the same unique identifier
+ * will be returned if the type has been previously registered.
+ *
+ *
Note: On windows, do not call this method with pre-defined
+ * Clipboard Format types such as CF_TEXT or CF_BITMAP because the
+ * pre-defined identifier will not be returned
+ *
+ * @param formatName the name of a data type
+ *
+ * @return the unique identifier associated with this data type
+ */
+public static int registerType(String formatName) {
+ return getTypeID(formatName);
+}
+
+static int getTypeID(String formatName) {
+ // copied from the Carbon's port Transfer class
+ int length = formatName.length();
+ // TODO - hashcode may not be unique - need another way
+ if (length > 4) return formatName.hashCode();
+ int type = 0;
+ if (length > 0) type |= (formatName.charAt(0) & 0xff) << 24;
+ if (length > 1) type |= (formatName.charAt(1) & 0xff) << 16;
+ if (length > 2) type |= (formatName.charAt(2) & 0xff) << 8;
+ if (length > 3) type |= formatName.charAt(3) & 0xff;
+ return type;
+}
+
+/**
+ * Test that the object is of the correct format for this Transfer class.
+ *
+ * @param object a java representation of the data to be converted
+ *
+ * @return true if object is of the correct form for this transfer type
+ *
+ * @since 3.1
+ */
+protected boolean validate(Object object) {
+ return true;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TransferData.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TransferData.java
new file mode 100644
index 00000000000..27b029ab4e8
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/TransferData.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import java.awt.datatransfer.*;
+
+/**
+ * The TransferData class is a platform specific data structure for
+ * describing the type and the contents of data being converted by a transfer agent.
+ *
+ *
As an application writer, you do not need to know the specifics of
+ * TransferData. TransferData instances are passed to a subclass of Transfer
+ * and the Transfer object manages the platform specific issues.
+ * You can ask a Transfer subclass if it can handle this data by calling
+ * Transfer.isSupportedType(transferData).
+ *
+ *
You should only need to become familiar with the fields in this class if you
+ * are implementing a Transfer subclass and you are unable to subclass the
+ * ByteArrayTransfer class.
+ */
+public class TransferData {
+ /**
+ * The dataFlavor is a unique identifier of a system format or user defined format.
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public DataFlavor dataFlavor;
+
+ /**
+ * The transferable is a unique identifier of a system format or user defined format.
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public Transferable transferable;
+
+ /**
+ * The type is a unique identifier of a system format or user defined format.
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ *
+ * @noreference This field is not intended to be referenced by clients.
+ */
+ public int type;
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/URLTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/URLTransfer.java
new file mode 100644
index 00000000000..fad26cacd13
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/swing/org/eclipse/swt/dnd/URLTransfer.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.dnd;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.net.URL;
+
+/**
+ * The class URLTransfer provides a platform specific mechanism
+ * for converting text in URL format represented as a java String[]
+ * to a platform specific representation of the data and vice versa. See
+ * Transfer for additional information. The first string in the
+ * array is mandatory and must contain the fully specified url. The second
+ * string in the array is optional and if present contains the title for the
+ * page.
+ *
+ *
An example of a java String[] containing a URL is shown
+ * below:
+ *
+ *
+ * String[] urlData = new String[] {"http://www.eclipse.org", "Eclipse.org Main Page"};
+ *
+ * Application code must explicitly invoke the Color.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ *
+ * @see RGB
+ * @see Device#getSystemColor
+ */
+
+public final class Color extends Resource {
+
+ /**
+ * the handle to the OS color resource
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public java.awt.Color handle;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Color() {
+}
+
+/**
+ * Constructs a new instance of this class given a device and the
+ * desired red, green and blue values expressed as ints in the range
+ * 0 to 255 (where 0 is black and 255 is full brightness). On limited
+ * color devices, the color instance created by this call may not have
+ * the same RGB values as the ones specified by the arguments. The
+ * RGB values on the returned instance will be the color values of
+ * the operating system color.
+ *
+ * You must dispose the color when it is no longer required.
+ *
+ *
+ * @param device the device on which to allocate the color
+ * @param red the amount of red in the color
+ * @param green the amount of green in the color
+ * @param blue the amount of blue in the color
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255
+ *
+ *
+ * @see #dispose
+ */
+public Color (Device device, int red, int green, int blue) {
+ if (device == null) device = Device.getDevice ();
+ if (device == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ init (device, red, green, blue);
+ if (device.tracking) device.new_Object (this);
+}
+
+/**
+ * Constructs a new instance of this class given a device and an
+ * RGB describing the desired red, green and blue values.
+ * On limited color devices, the color instance created by this call
+ * may not have the same RGB values as the ones specified by the
+ * argument. The RGB values on the returned instance will be the color
+ * values of the operating system color.
+ *
+ * You must dispose the color when it is no longer required.
+ *
+ *
+ * @param device the device on which to allocate the color
+ * @param rgb the RGB values of the desired color
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if the rgb argument is null
+ *
ERROR_INVALID_ARGUMENT - if the red, green or blue components of the argument are not between 0 and 255
+ *
+ *
+ * @see #dispose
+ */
+public Color (Device device, RGB rgb) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (rgb == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init (device, rgb.red, rgb.green, rgb.blue);
+ if (device.tracking) device.new_Object(this);
+}
+
+public Color(int red, int green, int blue) {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+
+public Color(RGB closeFill) {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+
+private void init (Device device, int red, int green, int blue) {
+ if (!(0 <= red && red <= 255) || !(0 <= green && green <= 255)
+ || !(0 <= blue && blue <= 255))
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ this.device = device;
+ this.handle = new java.awt.Color (red, green, blue);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the color. Applications must dispose of all colors which
+ * they allocate.
+ */
+@Override
+public void dispose() {
+ if (handle == null) return;
+ if (device.isDisposed()) return;
+ handle = null;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the same object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return true if the object is the same as this object and false otherwise
+ *
+ * @see #hashCode
+ */
+@Override
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Color)) return false;
+ Color color = (Color) object;
+ return device == color.device && handle.equals(color.handle);
+}
+
+/**
+ * Returns the amount of blue in the color, from 0 to 255.
+ *
+ * @return the blue component of the color
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getBlue () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return handle.getBlue();
+}
+
+/**
+ * Returns the amount of green in the color, from 0 to 255.
+ *
+ * @return the green component of the color
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getGreen () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return handle.getGreen();
+}
+
+/**
+ * Returns the amount of red in the color, from 0 to 255.
+ *
+ * @return the red component of the color
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getRed () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return handle.getRed();
+}
+
+/**
+ * Returns an RGB representing the receiver.
+ *
+ * @return the RGB for the color
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public RGB getRGB () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return new RGB(handle.getRed(), handle.getGreen(), handle.getBlue());
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects which return true when passed to
+ * equals must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+@Override
+public int hashCode () {
+ return handle == null? 0: handle.hashCode();
+}
+
+/**
+ * Returns true if the color has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the color.
+ * When a color has been disposed, it is an error to
+ * invoke any other method using the color.
+ *
+ * @return true when the color is disposed and false otherwise
+ */
+@Override
+public boolean isDisposed() {
+ return handle == null;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+@Override
+public String toString () {
+ if (isDisposed()) return "Color {*DISPOSED*}"; //$NON-NLS-1$
+ return "Color {" + getRed() + ", " + getGreen() + ", " + getBlue() + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new color.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Color. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param device the device on which to allocate the color
+ * @param handle the handle for the color
+ * @return a new color object containing the specified device and handle
+ */
+public static Color swing_new(Device device, java.awt.Color handle) {
+ if (device == null) device = Device.getDevice();
+ Color color = new Color();
+ color.handle = handle;
+ color.device = device;
+ return color;
+}
+
+public int getAlpha() {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Cursor.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Cursor.java
new file mode 100644
index 00000000000..9a3f04868a2
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Cursor.java
@@ -0,0 +1,446 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.MissingResourceException;
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+
+import javax.swing.ImageIcon;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+
+/**
+ * Instances of this class manage operating system resources that
+ * specify the appearance of the on-screen pointer. To create a
+ * cursor you specify the device and either a simple cursor style
+ * describing one of the standard operating system provided cursors
+ * or the image and mask data for the desired appearance.
+ *
+ * Application code must explicitly invoke the Cursor.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ * Note: Only one of the above styles may be specified.
+ *
+ */
+
+public final class Cursor extends Resource {
+
+ /**
+ * the handle to the OS cursor resource
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public java.awt.Cursor handle;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Cursor() {
+}
+
+/**
+ * Constructs a new cursor given a device and a style
+ * constant describing the desired cursor appearance.
+ *
+ * You must dispose the cursor when it is no longer required.
+ *
+ *
+ * @param device the device on which to allocate the cursor
+ * @param style the style of cursor to allocate
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_INVALID_ARGUMENT - when an unknown style is specified
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation
+ *
+ *
+ * @see SWT#CURSOR_ARROW
+ * @see SWT#CURSOR_WAIT
+ * @see SWT#CURSOR_CROSS
+ * @see SWT#CURSOR_APPSTARTING
+ * @see SWT#CURSOR_HELP
+ * @see SWT#CURSOR_SIZEALL
+ * @see SWT#CURSOR_SIZENESW
+ * @see SWT#CURSOR_SIZENS
+ * @see SWT#CURSOR_SIZENWSE
+ * @see SWT#CURSOR_SIZEWE
+ * @see SWT#CURSOR_SIZEN
+ * @see SWT#CURSOR_SIZES
+ * @see SWT#CURSOR_SIZEE
+ * @see SWT#CURSOR_SIZEW
+ * @see SWT#CURSOR_SIZENE
+ * @see SWT#CURSOR_SIZESE
+ * @see SWT#CURSOR_SIZESW
+ * @see SWT#CURSOR_SIZENW
+ * @see SWT#CURSOR_UPARROW
+ * @see SWT#CURSOR_IBEAM
+ * @see SWT#CURSOR_NO
+ * @see SWT#CURSOR_HAND
+ */
+public Cursor(Device device, int style) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ switch (style) {
+ case SWT.CURSOR_HAND: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.HAND_CURSOR); break;
+ case SWT.CURSOR_ARROW: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR); break;
+ case SWT.CURSOR_WAIT: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR); break;
+ case SWT.CURSOR_CROSS: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.CROSSHAIR_CURSOR); break;
+ case SWT.CURSOR_SIZEALL: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.MOVE_CURSOR); break;
+ case SWT.CURSOR_SIZEN: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.N_RESIZE_CURSOR); break;
+ case SWT.CURSOR_SIZES: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.S_RESIZE_CURSOR); break;
+ case SWT.CURSOR_SIZEE: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.E_RESIZE_CURSOR); break;
+ case SWT.CURSOR_SIZEW: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.W_RESIZE_CURSOR); break;
+ case SWT.CURSOR_SIZENE: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.NE_RESIZE_CURSOR); break;
+ case SWT.CURSOR_SIZESE: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.SE_RESIZE_CURSOR); break;
+ case SWT.CURSOR_SIZESW: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.SW_RESIZE_CURSOR); break;
+ case SWT.CURSOR_SIZENW: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.NW_RESIZE_CURSOR); break;
+ case SWT.CURSOR_IBEAM: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.TEXT_CURSOR); break;
+ // Cursor that do not fit exactly with the description:
+ case SWT.CURSOR_APPSTARTING: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR); break;
+ case SWT.CURSOR_SIZEWE: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.E_RESIZE_CURSOR); break;
+ case SWT.CURSOR_SIZENS: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.N_RESIZE_CURSOR); break;
+ case SWT.CURSOR_SIZENESW: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.NE_RESIZE_CURSOR); break;
+ case SWT.CURSOR_SIZENWSE: handle = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.NW_RESIZE_CURSOR); break;
+ // Custom cursors
+ case SWT.CURSOR_UPARROW:
+ case SWT.CURSOR_NO:
+ case SWT.CURSOR_HELP:
+ handle = createCursor(style);
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (device.tracking) device.new_Object(this);
+}
+
+java.awt.Cursor createCursor(int type) {
+ String name = "";
+ switch(type) {
+ case SWT.CURSOR_UPARROW: name = "UpCursor"; break;
+ case SWT.CURSOR_NO: name = "NoCursor"; break;
+ case SWT.CURSOR_HELP: name = "HelpCursor"; break;
+ default: return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.HAND_CURSOR);
+ }
+ // Get the Property file
+ InputStream is = getClass().getResourceAsStream("resources/" + name + ".properties");
+ if (is == null) {
+ return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR);
+ }
+ String gifFile = null;
+ String hotspot = null;
+ try {
+ ResourceBundle resource = new PropertyResourceBundle(is);
+ gifFile = "resources/" + resource.getString("Cursor.File");
+ hotspot = resource.getString("Cursor.HotSpot");
+ } catch (MissingResourceException e) {
+ return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR);
+ } catch (IOException e2) {
+ return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR);
+ }
+ // Create the icon
+ byte[] buffer = null;
+ try {
+ InputStream resource = getClass().getResourceAsStream(gifFile);
+ if (resource == null) {
+ return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR);
+ }
+ BufferedInputStream in = new BufferedInputStream(resource);
+ ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
+ buffer = new byte[1024];
+ int n;
+ while ((n = in.read(buffer)) > 0) {
+ out.write(buffer, 0, n);
+ }
+ in.close();
+ out.flush();
+ buffer = out.toByteArray();
+ if (buffer.length == 0) {
+ return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR);
+ }
+ } catch (IOException ioe) {
+ return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR);
+ }
+ ImageIcon icon = new ImageIcon(buffer);
+ // create the point
+ int k = hotspot.indexOf(',');
+ java.awt.Point point = new java.awt.Point(Integer.parseInt(hotspot.substring(0, k)), Integer.parseInt(hotspot.substring(k + 1)));
+ try {
+ return Toolkit.getDefaultToolkit().createCustomCursor(icon.getImage(), point, name);
+ } catch (NoSuchMethodError err) {
+ // return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
+ return java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR);
+ }
+}
+
+/**
+ * Constructs a new cursor given a device, image and mask
+ * data describing the desired cursor appearance, and the x
+ * and y coordinates of the hotspot (that is, the point
+ * within the area covered by the cursor which is considered
+ * to be where the on-screen pointer is "pointing").
+ *
+ * The mask data is allowed to be null, but in this case the source
+ * must be an ImageData representing an icon that specifies both
+ * color data and mask data.
+ *
+ * You must dispose the cursor when it is no longer required.
+ *
+ *
+ * @param device the device on which to allocate the cursor
+ * @param source the color data for the cursor
+ * @param mask the mask data for the cursor (or null)
+ * @param hotspotX the x coordinate of the cursor's hotspot
+ * @param hotspotY the y coordinate of the cursor's hotspot
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if the source is null
+ *
ERROR_NULL_ARGUMENT - if the mask is null and the source does not have a mask
+ *
ERROR_INVALID_ARGUMENT - if the source and the mask are not the same
+ * size, or if the hotspot is outside the bounds of the image
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation
+ *
+ */
+public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (mask == null) {
+ if (source.getTransparencyType() != SWT.TRANSPARENCY_MASK) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ mask = source.getTransparencyMask();
+ }
+ /* Check the bounds. Mask must be the same size as source */
+ if (mask.width != source.width || mask.height != source.height) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ /* Check the hotspots */
+ if (hotspotX >= source.width || hotspotX < 0 ||
+ hotspotY >= source.height || hotspotY < 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ /* Convert depth to 1 */
+ mask = ImageData.convertMask(mask);
+ source = ImageData.convertMask(source);
+
+ BufferedImage image = new BufferedImage(source.width, source.height, BufferedImage.TYPE_INT_ARGB);
+ PaletteData palette = source.palette;
+ if (palette.isDirect) {
+ for(int x=0; x 0) {
+ pixel = pixel & 0x00FFFFFF | alpha << 24;
+ image.setRGB(x, y, pixel);
+ }
+ }
+ }
+ }
+ } else {
+ for(int x=0; x 0) {
+ image.setRGB(x, y, 0xFFFFFFFF);
+ } else {
+ image.setRGB(x, y, 0xFF000000);
+ }
+ }
+ }
+ }
+ }
+
+// /* Make sure source and mask scanline pad is 2 */
+// byte[] sourceData = ImageData.convertPad(source.data, source.width, source.height, source.depth, source.scanlinePad, 2);
+// byte[] maskData = ImageData.convertPad(mask.data, mask.width, mask.height, mask.depth, mask.scanlinePad, 2);
+ createCursor(image, hotspotX, hotspotY);
+ if (device.tracking) device.new_Object(this);
+}
+
+protected void createCursor(BufferedImage image, int hotspotX, int hotspotY) {
+ handle = Toolkit.getDefaultToolkit().createCustomCursor(image, new java.awt.Point(hotspotX, hotspotY), "Custom Cursor");
+}
+
+/**
+ * Constructs a new cursor given a device, image data describing
+ * the desired cursor appearance, and the x and y coordinates of
+ * the hotspot (that is, the point within the area
+ * covered by the cursor which is considered to be where the
+ * on-screen pointer is "pointing").
+ *
+ * You must dispose the cursor when it is no longer required.
+ *
+ *
+ * @param device the device on which to allocate the cursor
+ * @param source the image data for the cursor
+ * @param hotspotX the x coordinate of the cursor's hotspot
+ * @param hotspotY the y coordinate of the cursor's hotspot
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if the image is null
+ *
ERROR_INVALID_ARGUMENT - if the hotspot is outside the bounds of the
+ * image
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation
+ *
+ *
+ * @since 3.0
+ */
+public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ /* Check the hotspots */
+ if (hotspotX >= source.width || hotspotX < 0 ||
+ hotspotY >= source.height || hotspotY < 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ createCursor(new Image(device, source).handle, hotspotX, hotspotY);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the cursor. Applications must dispose of all cursors which
+ * they allocate.
+ */
+public void dispose () {
+ if (handle == null) return;
+ if (device.isDisposed()) return;
+ handle = null;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the same object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return true if the object is the same as this object and false otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Cursor)) return false;
+ Cursor cursor = (Cursor) object;
+ return device == cursor.device && handle == cursor.handle;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects which return true when passed to
+ * equals must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle == null? 0: handle.hashCode();
+}
+
+/**
+ * Returns true if the cursor has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the cursor.
+ * When a cursor has been disposed, it is an error to
+ * invoke any other method using the cursor.
+ *
+ * @return true when the cursor is disposed and false otherwise
+ */
+public boolean isDisposed() {
+ return handle == null;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Cursor {*DISPOSED*}";
+ return "Cursor {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new cursor.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Cursor. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param device the device on which to allocate the color
+ * @param handle the handle for the cursor
+ * @return a new cursor object containing the specified device and handle
+ */
+public static Cursor swing_new(Device device, java.awt.Cursor handle) {
+ if (device == null) device = Device.getDevice();
+ Cursor cursor = new Cursor();
+ cursor.handle = handle;
+ cursor.device = device;
+ return cursor;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Device.java
new file mode 100644
index 00000000000..04ed1c7d22c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Device.java
@@ -0,0 +1,829 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.awt.DisplayMode;
+import java.awt.GraphicsEnvironment;
+import java.awt.Toolkit;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.swing.CGC;
+import org.eclipse.swt.internal.swing.LookAndFeelUtils;
+
+/**
+ * This class is the abstract superclass of all device objects,
+ * such as the Display device and the Printer device. Devices
+ * can have a graphics context (GC) created for them, and they
+ * can be drawn on by sending messages to the associated GC.
+ */
+public abstract class Device implements Drawable {
+
+ /* Debugging */
+ public static boolean DEBUG;
+ boolean debug = DEBUG;
+ boolean tracking = DEBUG;
+ Error [] errors;
+ Object [] objects;
+
+// /**
+// * Palette
+// * (Warning: This field is platform dependent)
+// *
+// * IMPORTANT: This field is not part of the SWT
+// * public API. It is marked public only so that it can be shared
+// * within the packages provided by SWT. It is not available on all
+// * platforms and should never be accessed from application code.
+// *
+// */
+// public int hPalette = 0;
+// int [] colorRefCount;
+
+// /* Font Enumeration */
+// int nFonts = 256;
+// LOGFONT [] logFonts;
+
+// /* Scripts */
+// int [] scripts;
+
+// /* Advanced Graphics */
+// int [] gdipToken;
+
+ boolean disposed;
+
+ final static Object CREATE_LOCK = new Object();
+
+ /*
+ * TEMPORARY CODE. When a graphics object is
+ * created and the device parameter is null,
+ * the current Display is used. This presents
+ * a problem because SWT graphics does not
+ * reference classes in SWT widgets. The correct
+ * fix is to remove this feature. Unfortunately,
+ * too many application programs rely on this
+ * feature.
+ *
+ * This code will be removed in the future.
+ */
+ protected static Device CurrentDevice;
+ protected static Runnable DeviceFinder;
+ static {
+ try {
+ Class.forName ("org.eclipse.swt.widgets.Display"); //$NON-NLS-1$
+ } catch (Throwable e) {}
+ }
+
+/*
+* TEMPORARY CODE.
+*/
+static synchronized Device getDevice () {
+ if (DeviceFinder != null) DeviceFinder.run();
+ Device device = CurrentDevice;
+ CurrentDevice = null;
+ return device;
+}
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * You must dispose the device when it is no longer required.
+ *
+ *
+ * @see #create
+ * @see #init
+ *
+ * @since 3.1
+ */
+public Device() {
+ this(null);
+}
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * You must dispose the device when it is no longer required.
+ *
+ *
+ * @param data the DeviceData which describes the receiver
+ *
+ * @see #create
+ * @see #init
+ * @see DeviceData
+ */
+public Device(DeviceData data) {
+ synchronized (CREATE_LOCK) {
+ if (data != null) {
+ debug = data.debug;
+ tracking = data.tracking;
+ }
+ create (data);
+ init ();
+ if (tracking) {
+ errors = new Error [128];
+ objects = new Object [128];
+ }
+ }
+}
+
+/**
+ * Throws an SWTException if the receiver can not
+ * be accessed by the caller. This may include both checks on
+ * the state of the receiver and more generally on the entire
+ * execution context. This method should be called by
+ * device implementors to enforce the standard SWT invariants.
+ *
+ * Currently, it is an error to invoke any method (other than
+ * isDisposed() and dispose()) on a
+ * device that has had its dispose() method called.
+ *
+ * In future releases of SWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
+ */
+protected void checkDevice () {
+ if (disposed) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
+}
+
+//void checkGDIP() {
+// if (gdipToken != null) return;
+// int oldErrorMode = OS.SetErrorMode (OS.SEM_FAILCRITICALERRORS);
+// try {
+// int [] token = new int [1];
+// GdiplusStartupInput input = new GdiplusStartupInput ();
+// input.GdiplusVersion = 1;
+// if (Gdip.GdiplusStartup (token, input, 0) == 0) {
+// gdipToken = token;
+// }
+// } catch (Throwable t) {
+// SWT.error (SWT.ERROR_NO_GRAPHICS_LIBRARY, t);
+// } finally {
+// OS.SetErrorMode (oldErrorMode);
+// }
+//}
+
+/**
+ * Creates the device in the operating system. If the device
+ * does not have a handle, this method may do nothing depending
+ * on the device.
+ *
+ * This method is called before init.
+ *
+ * Subclasses are supposed to reimplement this method and not
+ * call the super implementation.
+ *
+ *
+ * @param data the DeviceData which describes the receiver
+ *
+ * @see #init
+ */
+protected void create (DeviceData data) {
+}
+
+//int computePixels(int height) {
+// int hDC = internal_new_GC (null);
+// int pixels = -Compatibility.round(height * OS.GetDeviceCaps(hDC, OS.LOGPIXELSY), 72);
+// internal_dispose_GC (hDC, null);
+// return pixels;
+//}
+//
+//int computePoints(LOGFONT logFont) {
+// int hDC = internal_new_GC (null);
+// int logPixelsY = OS.GetDeviceCaps(hDC, OS.LOGPIXELSY);
+// int pixels = 0;
+// if (logFont.lfHeight > 0) {
+// /*
+// * Feature in Windows. If the lfHeight of the LOGFONT structure
+// * is positive, the lfHeight measures the height of the entire
+// * cell, including internal leading, in logical units. Since the
+// * height of a font in points does not include the internal leading,
+// * we must subtract the internal leading, which requires a TEXTMETRIC,
+// * which in turn requires font creation.
+// */
+// int hFont = OS.CreateFontIndirect(logFont);
+// int oldFont = OS.SelectObject(hDC, hFont);
+// TEXTMETRIC lptm = OS.IsUnicode ? (TEXTMETRIC)new TEXTMETRICW() : new TEXTMETRICA();
+// OS.GetTextMetrics(hDC, lptm);
+// OS.SelectObject(hDC, oldFont);
+// OS.DeleteObject(hFont);
+// pixels = logFont.lfHeight - lptm.tmInternalLeading;
+// } else {
+// pixels = -logFont.lfHeight;
+// }
+// internal_dispose_GC (hDC, null);
+//
+// return Compatibility.round(pixels * 72, logPixelsY);
+//}
+
+/**
+ * Destroys the device in the operating system and releases
+ * the device's handle. If the device does not have a handle,
+ * this method may do nothing depending on the device.
+ *
+ * This method is called after release.
+ *
+ * Subclasses are supposed to reimplement this method and not
+ * call the super implementation.
+ *
+ *
+ * @see #dispose
+ * @see #release
+ */
+protected void destroy () {
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the receiver. After this method has been invoked, the receiver
+ * will answer true when sent the message
+ * isDisposed().
+ *
+ * @see #release
+ * @see #destroy
+ * @see #checkDevice
+ */
+public void dispose () {
+ if (isDisposed()) return;
+ checkDevice ();
+ release ();
+ destroy ();
+ disposed = true;
+ if (tracking) {
+ objects = null;
+ errors = null;
+ }
+}
+
+void dispose_Object (Object object) {
+ for (int i=0; i
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Rectangle getBounds () {
+ checkDevice ();
+ //TODO: implement method
+ throw new IllegalStateException("Not implemented!");
+// int hDC = internal_new_GC (null);
+// int width = OS.GetDeviceCaps (hDC, OS.HORZRES);
+// int height = OS.GetDeviceCaps (hDC, OS.VERTRES);
+// internal_dispose_GC (hDC, null);
+// return new Rectangle (0, 0, width, height);
+}
+
+/**
+ * Returns a DeviceData based on the receiver.
+ * Modifications made to this DeviceData will not
+ * affect the receiver.
+ *
+ * @return a DeviceData containing the device's data and attributes
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see DeviceData
+ */
+public DeviceData getDeviceData () {
+ checkDevice();
+ DeviceData data = new DeviceData ();
+ data.debug = debug;
+ data.tracking = tracking;
+ int count = 0, length = 0;
+ if (tracking) length = objects.length;
+ for (int i=0; i
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getBounds
+ */
+public Rectangle getClientArea () {
+ return getBounds ();
+}
+
+/**
+ * Returns the bit depth of the screen, which is the number of
+ * bits it takes to represent the number of unique colors that
+ * the screen is currently capable of displaying. This number
+ * will typically be one of 1, 8, 15, 16, 24 or 32.
+ *
+ * @return the depth of the screen
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getDepth () {
+ checkDevice ();
+// int hDC = internal_new_GC (null);
+// int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
+// int planes = OS.GetDeviceCaps (hDC, OS.PLANES);
+// internal_dispose_GC (hDC, null);
+// return bits * planes;
+ // TODO: is this correct?
+ DisplayMode displayMode = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode();
+ if(displayMode == null) {
+ return 32;
+ }
+ int bitDepth = displayMode.getBitDepth();
+ return bitDepth == DisplayMode.BIT_DEPTH_MULTI? 32: bitDepth;
+}
+
+/**
+ * Returns a point whose x coordinate is the horizontal
+ * dots per inch of the display, and whose y coordinate
+ * is the vertical dots per inch of the display.
+ *
+ * @return the horizontal and vertical DPI
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Point getDPI () {
+ checkDevice ();
+ return getDPI_();
+// int hDC = internal_new_GC (null);
+// int dpiX = OS.GetDeviceCaps (hDC, OS.LOGPIXELSX);
+// int dpiY = OS.GetDeviceCaps (hDC, OS.LOGPIXELSY);
+// internal_dispose_GC (hDC, null);
+// return new Point (dpiX, dpiY);
+}
+
+protected Point getDPI_() {
+ int resolution = Toolkit.getDefaultToolkit().getScreenResolution();
+ return new Point(resolution, resolution);
+}
+
+/**
+ * Returns FontData objects which describe
+ * the fonts that match the given arguments. If the
+ * faceName is null, all fonts will be returned.
+ *
+ * @param faceName the name of the font to look for, or null
+ * @param scalable if true only scalable fonts are returned, otherwise only non-scalable fonts are returned.
+ * @return the matching font data
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public FontData [] getFontList (String faceName, boolean scalable) {
+ checkDevice ();
+ if(!scalable) {
+ return new FontData[0];
+ }
+ // TODO: propose all styles?
+ java.awt.Font[] fonts;
+ if(faceName != null) {
+ java.awt.Font font = new java.awt.Font(faceName, java.awt.Font.PLAIN, 1);
+ if(!"Dialog".equals(faceName) && "Dialog".equals(font.getFamily())) {
+ fonts = new java.awt.Font[0];
+ } else {
+ fonts = new java.awt.Font[] {font};
+ }
+ } else {
+ fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
+ }
+ FontData[] results = new FontData[fonts.length];
+ for(int i=0; iSWT. Any value other
+ * than one of the SWT color constants which is passed
+ * in will result in the color black. This color should
+ * not be freed because it was allocated by the system,
+ * not the application.
+ *
+ * @param id the color constant
+ * @return the matching color
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see SWT
+ */
+public Color getSystemColor (int id) {
+ checkDevice ();
+ java.awt.Color pixel = java.awt.Color.BLACK;
+ switch (id) {
+ case SWT.COLOR_WHITE: pixel = java.awt.Color.WHITE; break;
+ case SWT.COLOR_BLACK: pixel = java.awt.Color.BLACK; break;
+ case SWT.COLOR_RED: pixel = java.awt.Color.RED; break;
+ case SWT.COLOR_DARK_RED: pixel = java.awt.Color.RED.darker(); break;
+ case SWT.COLOR_GREEN: pixel = java.awt.Color.GREEN; break;
+ case SWT.COLOR_DARK_GREEN: pixel = java.awt.Color.GREEN.darker(); break;
+ case SWT.COLOR_YELLOW: pixel = java.awt.Color.YELLOW; break;
+ case SWT.COLOR_DARK_YELLOW: pixel = java.awt.Color.YELLOW.darker(); break;
+ case SWT.COLOR_BLUE: pixel = java.awt.Color.BLUE; break;
+ case SWT.COLOR_DARK_BLUE: pixel = java.awt.Color.BLUE.darker(); break;
+ case SWT.COLOR_MAGENTA: pixel = java.awt.Color.MAGENTA; break;
+ case SWT.COLOR_DARK_MAGENTA: pixel = java.awt.Color.MAGENTA.darker(); break;
+ case SWT.COLOR_CYAN: pixel = java.awt.Color.CYAN; break;
+ case SWT.COLOR_DARK_CYAN: pixel = java.awt.Color.CYAN.darker(); break;
+ case SWT.COLOR_GRAY: pixel = java.awt.Color.GRAY; break;
+ case SWT.COLOR_DARK_GRAY: pixel = java.awt.Color.GRAY.darker(); break;
+ }
+ return Color.swing_new (this, pixel);
+}
+
+/**
+ * Returns a reasonable font for applications to use.
+ * On some platforms, this will match the "default font"
+ * or "system font" if such can be found. This font
+ * should not be freed because it was allocated by the
+ * system, not the application.
+ *
+ * Typically, applications which want the default look
+ * should simply not set the font on the widgets they
+ * create. Widgets are always created with the correct
+ * default font for the class of user-interface component
+ * they represent.
+ *
+ *
+ * @return a font
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Font getSystemFont () {
+ checkDevice ();
+ return Font.swing_new (this, LookAndFeelUtils.getSystemFont());
+}
+
+/**
+ * Returns true if the underlying window system prints out
+ * warning messages on the console, and setWarnings
+ * had previously been called with true.
+ *
+ * @return trueif warnings are being handled, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public boolean getWarnings () {
+ checkDevice ();
+ return false;
+}
+
+/**
+ * Initializes any internal resources needed by the
+ * device.
+ *
+ * This method is called after create.
+ *
+ * If subclasses reimplement this method, they must
+ * call the super implementation.
+ *
+ *
+ * @see #create
+ */
+protected void init () {
+// if (debug) {
+// if (!OS.IsWinCE) OS.GdiSetBatchLimit(1);
+// }
+//
+// /* Initialize scripts list */
+// if (!OS.IsWinCE) {
+// int [] ppSp = new int [1];
+// int [] piNumScripts = new int [1];
+// OS.ScriptGetProperties (ppSp, piNumScripts);
+// scripts = new int [piNumScripts [0]];
+// OS.MoveMemory (scripts, ppSp [0], scripts.length * 4);
+// }
+//
+// /*
+// * If we're not on a device which supports palettes,
+// * don't create one.
+// */
+// int hDC = internal_new_GC (null);
+// int rc = OS.GetDeviceCaps (hDC, OS.RASTERCAPS);
+// int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
+// int planes = OS.GetDeviceCaps (hDC, OS.PLANES);
+//
+// bits *= planes;
+// if ((rc & OS.RC_PALETTE) == 0 || bits != 8) {
+// internal_dispose_GC (hDC, null);
+// return;
+// }
+//
+// int numReserved = OS.GetDeviceCaps (hDC, OS.NUMRESERVED);
+// int numEntries = OS.GetDeviceCaps (hDC, OS.SIZEPALETTE);
+//
+// if (OS.IsWinCE) {
+// /*
+// * Feature on WinCE. For some reason, certain 8 bit WinCE
+// * devices return 0 for the number of reserved entries in
+// * the system palette. Their system palette correctly contains
+// * the usual 20 system colors. The workaround is to assume
+// * there are 20 reserved system colors instead of 0.
+// */
+// if (numReserved == 0 && numEntries >= 20) numReserved = 20;
+// }
+//
+// /* Create the palette and reference counter */
+// colorRefCount = new int [numEntries];
+//
+// /* 4 bytes header + 4 bytes per entry * numEntries entries */
+// byte [] logPalette = new byte [4 + 4 * numEntries];
+//
+// /* 2 bytes = special header */
+// logPalette [0] = 0x00;
+// logPalette [1] = 0x03;
+//
+// /* 2 bytes = number of colors, LSB first */
+// logPalette [2] = 0;
+// logPalette [3] = 1;
+//
+// /*
+// * Create a palette which contains the system entries
+// * as they are located in the system palette. The
+// * MSDN article 'Memory Device Contexts' describes
+// * where system entries are located. On an 8 bit
+// * display with 20 reserved colors, the system colors
+// * will be the first 10 entries and the last 10 ones.
+// */
+// byte[] lppe = new byte [4 * numEntries];
+// OS.GetSystemPaletteEntries (hDC, 0, numEntries, lppe);
+// /* Copy all entries from the system palette */
+// System.arraycopy (lppe, 0, logPalette, 4, 4 * numEntries);
+// /* Lock the indices corresponding to the system entries */
+// for (int i = 0; i < numReserved / 2; i++) {
+// colorRefCount [i] = 1;
+// colorRefCount [numEntries - 1 - i] = 1;
+// }
+// internal_dispose_GC (hDC, null);
+// hPalette = OS.CreatePalette (logPalette);
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Device. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+public abstract CGC internal_new_GC (GCData data);
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Device. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param handle the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public abstract void internal_dispose_GC (CGC handle, GCData data);
+
+/**
+ * Returns true if the device has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the device.
+ * When a device has been disposed, it is an error to
+ * invoke any other method using the device.
+ *
+ * @return true when the device is disposed and false otherwise
+ */
+public boolean isDisposed () {
+ return disposed;
+}
+
+void new_Object (Object object) {
+ for (int i=0; i
+ * When a device is destroyed, resources that were acquired
+ * on behalf of the programmer need to be returned to the
+ * operating system. For example, if the device allocated a
+ * font to be used as the system font, this font would be
+ * freed in release. Also,to assist the garbage
+ * collector and minimize the amount of memory that is not
+ * reclaimed when the programmer keeps a reference to a
+ * disposed device, all fields except the handle are zero'd.
+ * The handle is needed by destroy.
+ *
+ * This method is called before destroy.
+ *
+ * If subclasses reimplement this method, they must
+ * call the super implementation.
+ *
+ *
+ * @see #dispose
+ * @see #destroy
+ */
+protected void release () {
+// if (gdipToken != null) {
+// Gdip.GdiplusShutdown (gdipToken);
+// }
+// gdipToken = null;
+// scripts = null;
+// if (hPalette != 0) OS.DeleteObject (hPalette);
+// hPalette = 0;
+// colorRefCount = null;
+// logFonts = null;
+// nFonts = 0;
+}
+
+/**
+ * If the underlying window system supports printing warning messages
+ * to the console, setting warnings to true prevents these
+ * messages from being printed. If the argument is false
+ * message printing is not blocked.
+ *
+ * @param warnings trueif warnings should be handled, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setWarnings (boolean warnings) {
+ checkDevice ();
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/DeviceData.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/DeviceData.java
new file mode 100644
index 00000000000..593b25584db
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/DeviceData.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+public class DeviceData {
+ /*
+ * Debug fields - may not be honoured
+ * on some SWT platforms.
+ */
+ public boolean debug;
+ public boolean tracking;
+ public Error [] errors;
+ public Object [] objects;
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Font.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Font.java
new file mode 100644
index 00000000000..7b201c260ed
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Font.java
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.awt.font.TextAttribute;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+
+/**
+ * Instances of this class manage operating system resources that
+ * define how text looks when it is displayed. Fonts may be constructed
+ * by providing a device and either name, size and style information
+ * or a FontData object which encapsulates this data.
+ *
+ * Application code must explicitly invoke the Font.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ *
+ * @see FontData
+ */
+
+public final class Font extends Resource {
+
+ /**
+ * the handle to the OS font resource
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public java.awt.Font handle;
+
+ FontData fontData;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Font() {
+}
+
+/**
+ * Constructs a new font given a device and font data
+ * which describes the desired font's appearance.
+ *
+ * You must dispose the font when it is no longer required.
+ *
+ *
+ * @param device the device to create the font on
+ * @param fd the FontData that describes the desired font (must not be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if the fd argument is null
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES - if a font could not be created from the given font data
+ *
+ */
+public Font(Device device, FontData fd) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, fd);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new font given a device and an array
+ * of font data which describes the desired font's
+ * appearance.
+ *
+ * You must dispose the font when it is no longer required.
+ *
+ *
+ * @param device the device to create the font on
+ * @param fds the array of FontData that describes the desired font (must not be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if the fds argument is null
+ *
ERROR_INVALID_ARGUMENT - if the length of fds is zero
+ *
ERROR_NULL_ARGUMENT - if any fd in the array is null
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES - if a font could not be created from the given font data
+ *
+ *
+ * @since 2.1
+ */
+public Font(Device device, FontData[] fds) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (fds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (fds.length == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ for (int i=0; i
+ * You must dispose the font when it is no longer required.
+ *
+ *
+ * @param device the device to create the font on
+ * @param name the name of the font (must not be null)
+ * @param height the font height in points
+ * @param style a bit or combination of NORMAL, BOLD, ITALIC
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if the name argument is null
+ *
ERROR_INVALID_ARGUMENT - if the height is negative
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES - if a font could not be created from the given arguments
+ *
+ */
+public Font(Device device, String name, int height, int style) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, new FontData (name, height, style));
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the font. Applications must dispose of all fonts which
+ * they allocate.
+ */
+public void dispose() {
+ if (handle == null) return;
+ if (device.isDisposed()) return;
+ handle = null;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the same object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return true if the object is the same as this object and false otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals(Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Font)) return false;
+ Font font = (Font) object;
+ return device == font.device && handle == font.handle;
+}
+
+/**
+ * Returns an array of FontDatas representing the receiver.
+ * On Windows, only one FontData will be returned per font. On X however,
+ * a Font object may be composed of multiple X
+ * fonts. To support this case, we return an array of font data objects.
+ *
+ * @return an array of font data objects describing the receiver
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public FontData[] getFontData() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return new FontData[] {new FontData(fontData)};
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true when passed to
+ * equals must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle == null? 0: handle.hashCode();
+}
+
+void init (Device device, FontData fd) {
+ if (fd == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ fontData = new FontData(fd);
+ int style = fd.getStyle();
+ int height = Math.round(fd.getHeight() * device.getDPI().x / 72.0f);
+ if(fontData.data != null) {
+ Map attributeMap = new HashMap(fontData.data);
+ attributeMap.put(TextAttribute.FAMILY, fd.getName());
+ attributeMap.put(TextAttribute.POSTURE, (style & SWT.ITALIC) != 0? TextAttribute.POSTURE_OBLIQUE: TextAttribute.POSTURE_REGULAR);
+ attributeMap.put(TextAttribute.WEIGHT, (style & SWT.BOLD) != 0? TextAttribute.WEIGHT_BOLD: TextAttribute.WEIGHT_REGULAR);
+ handle = new java.awt.Font(attributeMap);
+ } else {
+ handle = new java.awt.Font(fd.getName(), 0
+ | (((style & SWT.ITALIC) != 0 ? java.awt.Font.ITALIC : 0))
+ | (((style & SWT.BOLD) != 0 ? java.awt.Font.BOLD : 0)), height);
+ }
+// handle = new java.awt.Font(fd.getName(), 0 | (((style & SWT.ITALIC) != 0? java.awt.Font.ITALIC: 0)) | (((style & SWT.BOLD) != 0? java.awt.Font.BOLD: 0)), fd.getHeight());
+}
+
+/**
+ * Returns true if the font has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the font.
+ * When a font has been disposed, it is an error to
+ * invoke any other method using the font.
+ *
+ * @return true when the font is disposed and false otherwise
+ */
+public boolean isDisposed() {
+ return handle == null;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Font {*DISPOSED*}";
+ return "Font {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new font.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Font. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param device the device on which to allocate the font
+ * @param handle the handle for the font
+ * @return a new font object containing the specified device and handle
+ */
+public static Font swing_new(Device device, java.awt.Font handle) {
+ if (device == null) device = Device.getDevice();
+ Font font = new Font();
+ font.handle = handle;
+ font.device = device;
+ int style = handle.getStyle();
+ int height = Math.round(handle.getSize() * 72.0f / device.getDPI_().x);
+ font.fontData = new FontData(handle.getName(), height, 0 | (((style & java.awt.Font.ITALIC) != 0? SWT.ITALIC: 0)) | (((style & java.awt.Font.BOLD) != 0? SWT.BOLD: 0)));
+ return font;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontData.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontData.java
new file mode 100644
index 00000000000..6bbc1f8146b
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontData.java
@@ -0,0 +1,445 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+
+/**
+ * Instances of this class describe operating system fonts.
+ *
+ * For platform-independent behaviour, use the get and set methods
+ * corresponding to the following properties:
+ *
+ *
height
the height of the font in points
+ *
name
the face name of the font, which may include the foundry
+ *
style
A bitwise combination of NORMAL, ITALIC and BOLD
+ *
+ * If extra, platform-dependent functionality is required:
+ *
+ *
On Windows, the data member of the FontData
+ * corresponds to a Windows LOGFONT structure whose fields
+ * may be retrieved and modified.
+ *
On X, the fields of the FontData correspond
+ * to the entries in the font's XLFD name and may be retrieved and modified.
+ *
+ * Application code does not need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no dispose() method is provided.
+ *
+ * @see Font
+ */
+
+public final class FontData {
+
+ /**
+ * A Swing font Map of TextAttributes
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public Map data;
+
+ /**
+ * The height of the font data in points
+ * (Warning: This field is platform dependent)
+ */
+ int height;
+
+ /**
+ * The style of the font data
+ * (Warning: This field is platform dependent)
+ */
+ int style;
+
+ /**
+ * The name of the font data
+ * (Warning: This field is platform dependent)
+ */
+ String name;
+
+ /**
+ * The locale of the font data
+ * (Warning: This field is platform dependent)
+ */
+ java.util.Locale locale;
+
+/**
+ * Constructs a new un-initialized font data.
+ */
+public FontData() {
+ height = 12;
+}
+
+/**
+ * Constructs a new font data given the Swing Font
+ * that it should represent.
+ *
+ * @param font the Font for the result
+ */
+FontData(FontData fontData) {
+ this.height = fontData.height;
+ this.style = fontData.style;
+ this.name = fontData.name;
+ this.locale = fontData.locale;
+ this.data = fontData.data;
+}
+
+/**
+ * Constructs a new FontData given a string representation
+ * in the form generated by the FontData.toString
+ * method.
+ *
+ * Note that the representation varies between platforms,
+ * and a FontData can only be created from a string that was
+ * generated on the same platform.
+ *
+ *
+ * @param string the string representation of a FontData (must not be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
ERROR_INVALID_ARGUMENT - if the argument does not represent a valid description
+ *
+ *
+ * @see #toString
+ */
+public FontData(String string) {
+ if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int start = 0;
+ int end = string.indexOf('|');
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ String version1 = string.substring(start, end);
+ try {
+ if (Integer.parseInt(version1) != 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ } catch (NumberFormatException e) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ String name = string.substring(start, end);
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int height = 0;
+ try {
+ height = Integer.parseInt(string.substring(start, end));
+ } catch (NumberFormatException e) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int style = 0;
+ try {
+ style = Integer.parseInt(string.substring(start, end));
+ } catch (NumberFormatException e) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ setName(name);
+ setHeight(height);
+ setStyle(style);
+ if (end == -1) return;
+ setLocale(string.substring(start, end));
+}
+
+/**
+ * Constructs a new font data given a font name,
+ * the height of the desired font in points,
+ * and a font style.
+ *
+ * @param name the name of the font (must not be null)
+ * @param height the font height in points
+ * @param style a bit or combination of NORMAL, BOLD, ITALIC
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - when the font name is null
+ *
ERROR_INVALID_ARGUMENT - if the height is negative
+ *
+ */
+public FontData(String name, int height, int style) {
+ if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ setName(name);
+ setHeight(height);
+ setStyle(style);
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the same object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return true if the object is the same as this object and false otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof FontData)) return false;
+ FontData fd = (FontData)object;
+ return height == fd.height &&
+ style == fd.style &&
+ (name == null && fd.name == null || name != null && name.equals(fd.name));
+}
+
+/**
+ * Returns the height of the receiver in points.
+ *
+ * @return the height of this FontData
+ *
+ * @see #setHeight
+ */
+public int getHeight() {
+ return height;
+}
+
+/**
+ * Returns the locale of the receiver.
+ *
+ * The locale determines which platform character set this
+ * font is going to use. Widgets and graphics operations that
+ * use this font will convert UNICODE strings to the platform
+ * character set of the specified locale.
+ *
+ *
+ * On platforms where there are multiple character sets for a
+ * given language/country locale, the variant portion of the
+ * locale will determine the character set.
+ *
+ *
+ * @return the String representing a Locale object
+ * @since 3.0
+ */
+public String getLocale () {
+ StringBuffer buffer = new StringBuffer ();
+ char sep = '_';
+ if (locale != null && !"".equals(locale.getLanguage())) {
+ buffer.append (locale.getLanguage());
+ buffer.append (sep);
+ }
+ if (locale != null && !"".equals(locale.getCountry())) {
+ buffer.append (locale.getCountry());
+ buffer.append (sep);
+ }
+ if (locale != null && !"".equals(locale.getVariant())) {
+ buffer.append (locale.getVariant());
+ }
+
+ String result = buffer.toString ();
+ int length = result.length ();
+ if (length > 0) {
+ if (result.charAt (length - 1) == sep) {
+ result = result.substring (0, length - 1);
+ }
+ }
+ return result;
+}
+
+/**
+ * Returns the name of the receiver.
+ * On platforms that support font foundries, the return value will
+ * be the foundry followed by a dash ("-") followed by the face name.
+ *
+ * @return the name of this FontData
+ *
+ * @see #setName
+ */
+public String getName() {
+ return name;
+}
+
+/**
+ * Returns the style of the receiver which is a bitwise OR of
+ * one or more of the SWT constants NORMAL, BOLD
+ * and ITALIC.
+ *
+ * @return the style of this FontData
+ *
+ * @see #setStyle
+ */
+public int getStyle() {
+ return style;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true when passed to
+ * equals must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return height ^ style ^ (locale == null? 0: locale.hashCode()) ^ getName().hashCode();
+}
+
+/**
+ * Sets the height of the receiver. The parameter is
+ * specified in terms of points, where a point is one
+ * seventy-second of an inch.
+ *
+ * @param height the height of the FontData
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the height is negative
+ *
+ *
+ * @see #getHeight
+ */
+public void setHeight(int height) {
+ if (height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ this.height = height;
+}
+
+/**
+ * Sets the locale of the receiver.
+ *
+ * The locale determines which platform character set this
+ * font is going to use. Widgets and graphics operations that
+ * use this font will convert UNICODE strings to the platform
+ * character set of the specified locale.
+ *
+ *
+ * On platforms where there are multiple character sets for a
+ * given language/country locale, the variant portion of the
+ * locale will determine the character set.
+ *
+ *
+ * @param locale the String representing a Locale object
+ * @see java.util.Locale#toString
+ */
+public void setLocale(String locale) {
+ if (locale != null) {
+ char sep = '_';
+ int length = locale.length();
+ int firstSep, secondSep;
+
+ firstSep = locale.indexOf(sep);
+ if (firstSep == -1) {
+ firstSep = secondSep = length;
+ } else {
+ secondSep = locale.indexOf(sep, firstSep + 1);
+ if (secondSep == -1) secondSep = length;
+ }
+ String lang = "";
+ String country = "";
+ String variant = "";
+ if (firstSep > 0) lang = locale.substring(0, firstSep);
+ if (secondSep > firstSep + 1) country = locale.substring(firstSep + 1, secondSep);
+ if (length > secondSep + 1) variant = locale.substring(secondSep + 1);
+ this.locale = new java.util.Locale(lang, country, variant);
+ }
+}
+
+/**
+ * Sets the name of the receiver.
+ *
+ * Some platforms support font foundries. On these platforms, the name
+ * of the font specified in setName() may have one of the following forms:
+ *
+ *
a face name (for example, "courier")
+ *
a foundry followed by a dash ("-") followed by a face name (for example, "adobe-courier")
+ *
+ * In either case, the name returned from getName() will include the
+ * foundry.
+ *
+ *
+ * On platforms that do not support font foundries, only the face name
+ * (for example, "courier") is used in setName() and
+ * getName().
+ *
+ *
+ * @param name the name of the font data (must not be null)
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - when the font name is null
+ *
+ *
+ * @see #getName
+ */
+public void setName(String name) {
+ if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.name = name;
+}
+
+/**
+ * Sets the style of the receiver to the argument which must
+ * be a bitwise OR of one or more of the SWT
+ * constants NORMAL, BOLD and ITALIC. All other style bits are
+ * ignored.
+ *
+ * @param style the new style for this FontData
+ *
+ * @see #getStyle
+ */
+public void setStyle(int style) {
+ this.style = style;
+}
+
+/**
+ * Returns a string representation of the receiver which is suitable
+ * for constructing an equivalent instance using the
+ * FontData(String) constructor.
+ *
+ * @return a string representation of the FontData
+ *
+ * @see FontData
+ */
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("1|"); //$NON-NLS-1$
+ buffer.append(getName());
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(getHeight());
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(getStyle());
+ buffer.append("|"); //$NON-NLS-1$
+ String locale = getLocale();
+ if(locale != null) {
+ buffer.append(locale);
+ buffer.append("|"); //$NON-NLS-1$
+ }
+ return buffer.toString();
+}
+
+///**
+// * Invokes platform specific functionality to allocate a new font data.
+// *
+// * IMPORTANT: This method is not part of the public
+// * API for FontData. It is marked public only so that
+// * it can be shared within the packages provided by SWT. It is not
+// * available on all platforms, and should never be called from
+// * application code.
+// *
+// *
+// * @param font the Font for the font data
+// * @return a new font data object containing the specified LOGFONT and height
+// */
+//public static FontData swing_new(FontData fontData) {
+// return new FontData(fontData);
+//}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontMetrics.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontMetrics.java
new file mode 100644
index 00000000000..11a9278634f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/FontMetrics.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+/**
+ * Instances of this class provide measurement information
+ * about fonts including ascent, descent, height, leading
+ * space between rows, and average character width.
+ * FontMetrics are obtained from GCs
+ * using the getFontMetrics() method.
+ *
+ * @see GC#getFontMetrics
+ */
+
+public final class FontMetrics {
+
+ /**
+ * On Windows, handle is a Win32 TEXTMETRIC struct
+ * On Photon, handle is a Photon FontQueryInfo struct
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public java.awt.FontMetrics handle;
+
+ int ascent;
+ int descent;
+ int height;
+ int leading;
+ int averageCharWidth;
+
+/**
+ * Prevents instances from being created outside the package.
+ */
+FontMetrics() {
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the same object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return true if the object is the same as this object and false otherwise
+ *
+ * @see #hashCode
+ */
+@Override
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof FontMetrics)) return false;
+ return ((FontMetrics)object).handle.equals(handle);
+// TEXTMETRIC metric = ((FontMetrics)object).handle;
+// return handle.tmHeight == metric.tmHeight &&
+// handle.tmAscent == metric.tmAscent &&
+// handle.tmDescent == metric.tmDescent &&
+// handle.tmInternalLeading == metric.tmInternalLeading &&
+// handle.tmExternalLeading == metric.tmExternalLeading &&
+// handle.tmAveCharWidth == metric.tmAveCharWidth &&
+// handle.tmMaxCharWidth == metric.tmMaxCharWidth &&
+// handle.tmWeight == metric.tmWeight &&
+// handle.tmOverhang == metric.tmOverhang &&
+// handle.tmDigitizedAspectX == metric.tmDigitizedAspectX &&
+// handle.tmDigitizedAspectY == metric.tmDigitizedAspectY &&
+//// handle.tmFirstChar == metric.tmFirstChar &&
+//// handle.tmLastChar == metric.tmLastChar &&
+//// handle.tmDefaultChar == metric.tmDefaultChar &&
+//// handle.tmBreakChar == metric.tmBreakChar &&
+// handle.tmItalic == metric.tmItalic &&
+// handle.tmUnderlined == metric.tmUnderlined &&
+// handle.tmStruckOut == metric.tmStruckOut &&
+// handle.tmPitchAndFamily == metric.tmPitchAndFamily &&
+// handle.tmCharSet == metric.tmCharSet;
+}
+
+/**
+ * Returns the ascent of the font described by the receiver. A
+ * font's ascent is the distance from the baseline to the
+ * top of actual characters, not including any of the leading area,
+ * measured in pixels.
+ *
+ * @return the ascent of the font
+ */
+public int getAscent() {
+ return handle == null? ascent: handle.getAscent();
+}
+
+/**
+ * Returns the average character width, measured in pixels,
+ * of the font described by the receiver.
+ *
+ * @return the average character width of the font
+ */
+public int getAverageCharWidth() {
+ // Use a letter that looks average
+ return handle == null? averageCharWidth: handle.charWidth('c');
+}
+
+/**
+ * Returns the descent of the font described by the receiver. A
+ * font's descent is the distance from the baseline to the
+ * bottom of actual characters, not including any of the leading area,
+ * measured in pixels.
+ *
+ * @return the descent of the font
+ */
+public int getDescent() {
+ return handle == null? descent: handle.getDescent();
+}
+
+/**
+ * Returns the height of the font described by the receiver,
+ * measured in pixels. A font's height is the sum of
+ * its ascent, descent and leading area.
+ *
+ * @return the height of the font
+ *
+ * @see #getAscent
+ * @see #getDescent
+ * @see #getLeading
+ */
+public int getHeight() {
+ return handle == null? height: handle.getHeight();
+}
+
+/**
+ * Returns the leading area of the font described by the
+ * receiver. A font's leading area is the space
+ * above its ascent which may include accents or other marks.
+ *
+ * @return the leading space of the font
+ */
+public int getLeading() {
+ return handle == null? leading: handle.getLeading();
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true when passed to
+ * equals must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+@Override
+public int hashCode() {
+ return (handle == null? 0: handle.hashCode()) ^ getAscent() ^ getDescent() ^ getHeight() ^ getLeading() ^ getAverageCharWidth();
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new font metrics.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for FontMetrics. It is marked public only so that
+ * it can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param handle the TEXTMETRIC containing information about a font
+ * @return a new font metrics object containing the specified TEXTMETRIC
+ */
+public static FontMetrics swing_new(java.awt.FontMetrics handle) {
+ FontMetrics fontMetrics = new FontMetrics();
+ fontMetrics.handle = handle;
+ return fontMetrics;
+}
+
+static FontMetrics internal_new(int ascent, int descent, int averageCharWidth, int leading, int height) {
+ FontMetrics fontMetrics = new FontMetrics();
+ fontMetrics.ascent = ascent;
+ fontMetrics.descent = descent;
+ fontMetrics.height = height;
+ fontMetrics.leading = leading;
+ fontMetrics.averageCharWidth = averageCharWidth;
+ return fontMetrics;
+}
+
+public int getAverageCharacterWidth() {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GC.java
new file mode 100644
index 00000000000..4071b4be731
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GC.java
@@ -0,0 +1,3880 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.awt.AWTException;
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.GradientPaint;
+import java.awt.Graphics;
+import java.awt.Paint;
+import java.awt.RenderingHints;
+import java.awt.Robot;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.font.FontRenderContext;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.swing.CGC;
+import org.eclipse.swt.internal.swing.LookAndFeelUtils;
+import org.eclipse.swt.internal.swing.Utils;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Class GC is where all of the drawing capabilities that are
+ * supported by SWT are located. Instances are used to draw on either an
+ * Image, a Control, or directly on a Display.
+ *
+ *
Styles:
+ *
LEFT_TO_RIGHT, RIGHT_TO_LEFT
+ *
+ *
+ *
+ * The SWT drawing coordinate system is the two-dimensional space with the origin
+ * (0,0) at the top left corner of the drawing area and with (x,y) values increasing
+ * to the right and downward respectively.
+ *
+ *
+ *
+ * Application code must explicitly invoke the GC.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required. This is particularly
+ * important on Windows95 and Windows98 where the operating system has a limited
+ * number of device contexts available.
+ *
+ *
+ *
+ * Note: Only one of LEFT_TO_RIGHT and RIGHT_TO_LEFT may be specified.
+ *
+ *
+ * @see org.eclipse.swt.events.PaintEvent
+ */
+
+public final class GC extends Resource {
+
+ /**
+ * the handle to the OS device context
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public CGC handle;
+
+ Drawable drawable;
+ GCData data;
+
+ // Saved Affine Transform
+ private AffineTransform saveAT, gcAT;
+
+ // Fill Rule
+ private int fillRule = SWT.FILL_EVEN_ODD;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+GC() {
+}
+
+/**
+ * Constructs a new instance of this class which has been
+ * configured to draw on the specified drawable. Sets the
+ * foreground and background color in the GC to match those
+ * in the drawable.
+ *
+ * You must dispose the graphics context when it is no longer required.
+ *
+ * @param drawable the drawable to draw on
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the drawable is null
+ *
ERROR_NULL_ARGUMENT - if there is no current device
+ *
ERROR_INVALID_ARGUMENT
+ * - if the drawable is an image that is not a bitmap or an icon
+ * - if the drawable is an image or printer that is already selected
+ * into another graphics context
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for GC creation
+ *
+ */
+public GC(Drawable drawable) {
+ this(drawable, SWT.NONE);
+}
+
+/**
+ * Constructs a new instance of this class which has been
+ * configured to draw on the specified drawable. Sets the
+ * foreground and background color in the GC to match those
+ * in the drawable.
+ *
+ * You must dispose the graphics context when it is no longer required.
+ *
+ *
+ * @param drawable the drawable to draw on
+ * @param style the style of GC to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the drawable is null
+ *
ERROR_NULL_ARGUMENT - if there is no current device
+ *
ERROR_INVALID_ARGUMENT
+ * - if the drawable is an image that is not a bitmap or an icon
+ * - if the drawable is an image or printer that is already selected
+ * into another graphics context
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for GC creation
+ *
+ *
+ * @since 2.1.2
+ */
+public GC(Drawable drawable, int style) {
+ if (drawable == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ GCData data = new GCData ();
+ data.style = checkStyle(style);
+ Device device = data.device;
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = data.device = device;
+ CGC handle = drawable.internal_new_GC(data);
+ if (handle == null) SWT.error(SWT.ERROR_NO_HANDLES);
+ data.background = java.awt.Color.WHITE;
+ init (drawable, data, handle);
+ if (device.tracking) device.new_Object(this);
+}
+
+static int checkStyle(int style) {
+ if ((style & SWT.LEFT_TO_RIGHT) != 0) style &= ~SWT.RIGHT_TO_LEFT;
+ return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+}
+
+/**
+ * Copies a rectangular area of the receiver at the specified
+ * position into the image, which must be of type SWT.BITMAP.
+ *
+ * @param image the image to copy into
+ * @param x the x coordinate in the receiver of the area to be copied
+ * @param y the y coordinate in the receiver of the area to be copied
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the image is null
+ *
ERROR_INVALID_ARGUMENT - if the image is not a bitmap or has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void copyArea(Image image, int x, int y) {
+ if (drawable instanceof Control) {
+ Control control = (Control) drawable;
+ Graphics graphics = image.handle.getGraphics();
+ graphics.translate(-x, -y);
+ control.handle.paint(graphics);
+ graphics.translate(x, y);
+ return;
+ }
+ if (drawable instanceof Display) {
+ // TODO: better way?
+ Rectangle r = image.getBounds();
+ try {
+ image.handle = new Robot().createScreenCapture(new java.awt.Rectangle(r.x, r.y, r.width, r.height));
+ } catch (AWTException e) {
+ e.printStackTrace();
+ }
+ return;
+ }
+ // TODO: what about other cases?
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (image.type != SWT.BITMAP || image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+ // TODO: check that it works
+ java.awt.Composite oldComposite = handle.getComposite();
+ java.awt.Composite newComposite = new java.awt.Composite() {
+ public java.awt.CompositeContext createContext(java.awt.image.ColorModel srcColorModel, java.awt.image.ColorModel dstColorModel, java.awt.RenderingHints hints) {
+ return new java.awt.CompositeContext() {
+ public void compose(java.awt.image.Raster src, java.awt.image.Raster dstIn, java.awt.image.WritableRaster dstOut) {
+ // TODO: do the composition
+ }
+ public void dispose() {
+ }
+ };
+ }
+ };
+ handle.setComposite(newComposite);
+ // TODO: find how to flush
+ handle.setComposite(oldComposite);
+//
+//
+// /* Get the HDC for the device */
+// Device device = data.device;
+// int hDC = device.internal_new_GC(null);
+//
+// /* Copy the bitmap area */
+// Rectangle rect = image.getBounds();
+// int memHdc = OS.CreateCompatibleDC(hDC);
+// int hOldBitmap = OS.SelectObject(memHdc, image.handle);
+// OS.BitBlt(memHdc, 0, 0, rect.width, rect.height, handle, x, y, OS.SRCCOPY);
+// OS.SelectObject(memHdc, hOldBitmap);
+// OS.DeleteDC(memHdc);
+//
+// /* Release the HDC for the device */
+// device.internal_dispose_GC(hDC, null);
+}
+
+/**
+ * Copies a rectangular area of the receiver at the source
+ * position onto the receiver at the destination position.
+ *
+ * @param srcX the x coordinate in the receiver of the area to be copied
+ * @param srcY the y coordinate in the receiver of the area to be copied
+ * @param width the width of the area to copy
+ * @param height the height of the area to copy
+ * @param destX the x coordinate in the receiver of the area to copy to
+ * @param destY the y coordinate in the receiver of the area to copy to
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY) {
+ copyArea(srcX, srcY, width, height, destX, destY, true);
+}
+
+/**
+ * Copies a rectangular area of the receiver at the source
+ * position onto the receiver at the destination position.
+ *
+ * @param srcX the x coordinate in the receiver of the area to be copied
+ * @param srcY the y coordinate in the receiver of the area to be copied
+ * @param width the width of the area to copy
+ * @param height the height of the area to copy
+ * @param destX the x coordinate in the receiver of the area to copy to
+ * @param destY the y coordinate in the receiver of the area to copy to
+ * @param paint if true paint events will be generated for old and obscured areas
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY, boolean paint) {
+ // TODO: check what to do with the paint argument
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.copyArea(srcX, srcY, width, height, destX - srcX, destY - srcY);
+// ensureAreaClean(destX, destY, width, height);
+}
+
+//int createDIB(int width, int height) {
+// short depth = 32;
+//
+// BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
+// bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+// bmiHeader.biWidth = width;
+// bmiHeader.biHeight = -height;
+// bmiHeader.biPlanes = 1;
+// bmiHeader.biBitCount = depth;
+// if (OS.IsWinCE) bmiHeader.biCompression = OS.BI_BITFIELDS;
+// else bmiHeader.biCompression = OS.BI_RGB;
+// byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + (OS.IsWinCE ? 12 : 0)];
+// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+// /* Set the rgb colors into the bitmap info */
+// if (OS.IsWinCE) {
+// int redMask = 0xFF00;
+// int greenMask = 0xFF0000;
+// int blueMask = 0xFF000000;
+// /* big endian */
+// int offset = BITMAPINFOHEADER.sizeof;
+// bmi[offset] = (byte)((redMask & 0xFF000000) >> 24);
+// bmi[offset + 1] = (byte)((redMask & 0xFF0000) >> 16);
+// bmi[offset + 2] = (byte)((redMask & 0xFF00) >> 8);
+// bmi[offset + 3] = (byte)((redMask & 0xFF) >> 0);
+// bmi[offset + 4] = (byte)((greenMask & 0xFF000000) >> 24);
+// bmi[offset + 5] = (byte)((greenMask & 0xFF0000) >> 16);
+// bmi[offset + 6] = (byte)((greenMask & 0xFF00) >> 8);
+// bmi[offset + 7] = (byte)((greenMask & 0xFF) >> 0);
+// bmi[offset + 8] = (byte)((blueMask & 0xFF000000) >> 24);
+// bmi[offset + 9] = (byte)((blueMask & 0xFF0000) >> 16);
+// bmi[offset + 10] = (byte)((blueMask & 0xFF00) >> 8);
+// bmi[offset + 11] = (byte)((blueMask & 0xFF) >> 0);
+// }
+//
+// int[] pBits = new int[1];
+// int hDib = OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+// if (hDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// return hDib;
+//}
+//
+//int createGdipBrush() {
+// int colorRef = OS.GetBkColor (handle);
+// int rgb = ((colorRef >> 16) & 0xFF) | (colorRef & 0xFF00) | ((colorRef & 0xFF) << 16);
+// int color = Gdip.Color_new(data.alpha << 24 | rgb);
+// if (color == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// int brush = Gdip.SolidBrush_new(color);
+// if (brush == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// Gdip.Color_delete(color);
+// return brush;
+//}
+//
+//int createGdipPen() {
+// int style, colorRef, width, size, hPen = OS.GetCurrentObject(handle, OS.OBJ_PEN);
+// if ((size = OS.GetObject(hPen, 0, (LOGPEN)null)) == LOGPEN.sizeof) {
+// LOGPEN logPen = new LOGPEN();
+// OS.GetObject(hPen, LOGPEN.sizeof, logPen);
+// colorRef = logPen.lopnColor;
+// width = logPen.x;
+// style = logPen.lopnStyle;
+// } else {
+// EXTLOGPEN logPen = new EXTLOGPEN();
+// if (size <= EXTLOGPEN.sizeof) {
+// OS.GetObject(hPen, size, logPen);
+// } else {
+// int hHeap = OS.GetProcessHeap();
+// int ptr = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, size);
+// OS.GetObject(hPen, size, ptr);
+// OS.MoveMemory(logPen, ptr, EXTLOGPEN.sizeof);
+// OS.HeapFree(hHeap, 0, ptr);
+// }
+// colorRef = logPen.elpColor;
+// width = logPen.elpWidth;
+// style = logPen.elpPenStyle;
+// }
+// int rgb = ((colorRef >> 16) & 0xFF) | (colorRef & 0xFF00) | ((colorRef & 0xFF) << 16);
+// int color = Gdip.Color_new(data.alpha << 24 | rgb);
+// int pen = Gdip.Pen_new(color, width);
+// Gdip.Color_delete(color);
+// int dashStyle = 0;
+// switch (style & OS.PS_STYLE_MASK) {
+// case OS.PS_SOLID: dashStyle = Gdip.DashStyleSolid; break;
+// case OS.PS_DOT: dashStyle = Gdip.DashStyleDot; break;
+// case OS.PS_DASH: dashStyle = Gdip.DashStyleDash; break;
+// case OS.PS_DASHDOT: dashStyle = Gdip.DashStyleDashDot; break;
+// case OS.PS_DASHDOTDOT: dashStyle = Gdip.DashStyleDashDotDot; break;
+// case OS.PS_USERSTYLE: {
+// if (data.dashes != null) {
+// float[] pattern = new float[data.dashes.length];
+// for (int i = 0; i < pattern.length; i++) {
+// pattern[i] = (float)data.dashes[i] / width;
+// }
+// Gdip.Pen_SetDashPattern(pen, pattern, pattern.length);
+// dashStyle = Gdip.DashStyleCustom;
+// } else {
+// dashStyle = Gdip.DashStyleSolid;
+// }
+// }
+// }
+// if (dashStyle != Gdip.DashStyleCustom) Gdip.Pen_SetDashStyle(pen, dashStyle);
+// int joinStyle = 0;
+// switch (style & OS.PS_JOIN_MASK) {
+// case OS.PS_JOIN_MITER: joinStyle = Gdip.LineJoinMiter; break;
+// case OS.PS_JOIN_BEVEL: joinStyle = Gdip.LineJoinBevel; break;
+// case OS.PS_JOIN_ROUND: joinStyle = Gdip.LineJoinRound; break;
+// }
+// Gdip.Pen_SetLineJoin(pen, joinStyle);
+// int dashCap = Gdip.DashCapFlat, capStyle = 0;
+// switch (style & OS.PS_ENDCAP_MASK) {
+// case OS.PS_ENDCAP_FLAT: capStyle = Gdip.LineCapFlat; break;
+// case OS.PS_ENDCAP_ROUND: capStyle = Gdip.LineCapRound; dashCap = Gdip.DashCapRound; break;
+// case OS.PS_ENDCAP_SQUARE: capStyle = Gdip.LineCapSquare; break;
+// }
+// Gdip.Pen_SetLineCap(pen, capStyle, capStyle, dashCap);
+// return pen;
+//}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the graphics context. Applications must dispose of all GCs
+ * which they allocate.
+ */
+public void dispose() {
+ if (this.handle == null) return;
+// if (data.device.isDisposed()) return;
+
+// if (data.gdipGraphics != 0) Gdip.Graphics_delete(data.gdipGraphics);
+// if (data.gdipPen != 0) Gdip.Pen_delete(data.gdipPen);
+// if (data.gdipBrush != 0) Gdip.SolidBrush_delete(data.gdipBrush);
+// data.gdipBrush = data.gdipPen = data.gdipGraphics = 0;
+//
+// /* Select stock pen and brush objects and free resources */
+// if (data.hPen != 0) {
+// int nullPen = OS.GetStockObject(OS.NULL_PEN);
+// OS.SelectObject(handle, nullPen);
+// OS.DeleteObject(data.hPen);
+// data.hPen = 0;
+// }
+// if (data.hBrush != 0) {
+// int nullBrush = OS.GetStockObject(OS.NULL_BRUSH);
+// OS.SelectObject(handle, nullBrush);
+// OS.DeleteObject(data.hBrush);
+// data.hBrush = 0;
+// }
+
+// /*
+// * Put back the original bitmap into the device context.
+// * This will ensure that we have not left a bitmap
+// * selected in it when we delete the HDC.
+// */
+// int hNullBitmap = data.hNullBitmap;
+// if (hNullBitmap != 0) {
+// OS.SelectObject(handle, hNullBitmap);
+// data.hNullBitmap = 0;
+// }
+// Image image = data.image;
+// if (image != null) image.memGC = null;
+//
+// /*
+// * Dispose the HDC.
+// */
+ handle.dispose();
+ Device device = data.device;
+ if (drawable != null) drawable.internal_dispose_GC(handle, data);
+ drawable = null;
+ handle = null;
+// data.image = null;
+// data.ps = null;
+ if (device.tracking) device.dispose_Object(this);
+// data.device = null;
+ data = null;
+}
+
+/**
+ * Draws the outline of a circular or elliptical arc
+ * within the specified rectangular area.
+ *
+ * The resulting arc begins at startAngle and extends
+ * for arcAngle degrees, using the current color.
+ * Angles are interpreted such that 0 degrees is at the 3 o'clock
+ * position. A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ *
+ * The center of the arc is the center of the rectangle whose origin
+ * is (x, y) and whose size is specified by the
+ * width and height arguments.
+ *
+ * The resulting arc covers an area width + 1 pixels wide
+ * by height + 1 pixels tall.
+ *
+ *
+ * @param x the x coordinate of the upper-left corner of the arc to be drawn
+ * @param y the y coordinate of the upper-left corner of the arc to be drawn
+ * @param width the width of the arc to be drawn
+ * @param height the height of the arc to be drawn
+ * @param startAngle the beginning angle
+ * @param arcAngle the angular extent of the arc, relative to the start angle
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawArc (int x, int y, int width, int height, int startAngle, int arcAngle) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (width == 0 || height == 0 || arcAngle == 0) return;
+ handle.drawArc(x, y, width, height, startAngle, arcAngle);
+// ensureAreaClean(x, y, width, height);
+}
+
+/**
+ * Draws a rectangle, based on the specified arguments, which has
+ * the appearance of the platform's focus rectangle if the
+ * platform supports such a notion, and otherwise draws a simple
+ * rectangle in the receiver's foreground color.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void drawFocus (int x, int y, int width, int height) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ java.awt.Color oldColor = handle.getColor();
+ handle.setColor(LookAndFeelUtils.getFocusColor());
+ handle.drawRect(x, y, width, height);
+ handle.setColor(oldColor);
+// ensureAreaClean(x, y, width, height);
+}
+
+/**
+ * Draws the given image in the receiver at the specified
+ * coordinates.
+ *
+ * @param image the image to draw
+ * @param x the x coordinate of where to draw
+ * @param y the y coordinate of where to draw
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the image is null
+ *
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
ERROR_INVALID_ARGUMENT - if the given coordinates are outside the bounds of the image
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES - if no handles are available to perform the operation
+ *
+ */
+public void drawImage(Image image, int x, int y) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ drawImage(image, 0, 0, -1, -1, x, y, -1, -1, true);
+}
+
+/**
+ * Copies a rectangular area from the source image into a (potentially
+ * different sized) rectangular area in the receiver. If the source
+ * and destination areas are of differing sizes, then the source
+ * area will be stretched or shrunk to fit the destination area
+ * as it is copied. The copy fails if any part of the source rectangle
+ * lies outside the bounds of the source image, or if any of the width
+ * or height arguments are negative.
+ *
+ * @param image the source image
+ * @param srcX the x coordinate in the source image to copy from
+ * @param srcY the y coordinate in the source image to copy from
+ * @param srcWidth the width in pixels to copy from the source
+ * @param srcHeight the height in pixels to copy from the source
+ * @param destX the x coordinate in the destination to copy to
+ * @param destY the y coordinate in the destination to copy to
+ * @param destWidth the width in pixels of the destination rectangle
+ * @param destHeight the height in pixels of the destination rectangle
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the image is null
+ *
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
ERROR_INVALID_ARGUMENT - if any of the width or height arguments are negative.
+ *
ERROR_INVALID_ARGUMENT - if the source rectangle is not contained within the bounds of the source image
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES - if no handles are available to perform the operation
+ *
+ */
+public void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (srcWidth == 0 || srcHeight == 0 || destWidth == 0 || destHeight == 0) return;
+ if (srcX < 0 || srcY < 0 || srcWidth < 0 || srcHeight < 0 || destWidth < 0 || destHeight < 0) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ drawImage(image, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, false);
+}
+
+void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
+ if(srcWidth == -1) {
+ srcWidth = srcImage.handle.getWidth();
+ }
+ if(srcHeight == -1) {
+ srcHeight = srcImage.handle.getHeight();
+ }
+ if(destWidth == -1) {
+ destWidth = srcWidth;
+ }
+ if(destHeight == -1) {
+ destHeight = srcHeight;
+ }
+ // Simple == no stretch
+ if(!simple || srcWidth == destWidth && srcHeight == destHeight) {
+ handle.drawImage(srcImage.handle, destX, destY, destX + destWidth, destY + destHeight, srcX, srcY, srcX + srcWidth, srcY + srcHeight, null);
+ } else {
+// Shape oldClip = handle.getClip();
+// handle.setClip(systemClip);
+// handle.clipRect(destX, destY, destWidth, destHeight);
+ handle.drawImage(srcImage.handle, destX, destY, destX + destWidth, destY + destHeight, srcX, srcY, srcX + srcWidth, srcY + srcHeight, null);
+// handle.setClip(oldClip);
+ }
+// ensureAreaClean(destX, destY, destWidth, destHeight);
+// switch (srcImage.type) {
+// case SWT.BITMAP:
+// drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple);
+// break;
+// case SWT.ICON:
+// drawIcon(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple);
+// break;
+// default:
+// SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+// }
+}
+//
+//void drawIcon(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
+// int technology = OS.GetDeviceCaps(handle, OS.TECHNOLOGY);
+//
+// /* Simple case: no stretching, entire icon */
+// if (simple && technology != OS.DT_RASPRINTER) {
+// OS.DrawIconEx(handle, destX, destY, srcImage.handle, 0, 0, 0, 0, OS.DI_NORMAL);
+// return;
+// }
+//
+// /* Get the icon info */
+// ICONINFO srcIconInfo = new ICONINFO();
+// if (OS.IsWinCE) {
+// Image.GetIconInfo(srcImage, srcIconInfo);
+// } else {
+// OS.GetIconInfo(srcImage.handle, srcIconInfo);
+// }
+//
+// /* Get the icon width and height */
+// int hBitmap = srcIconInfo.hbmColor;
+// if (hBitmap == 0) hBitmap = srcIconInfo.hbmMask;
+// BITMAP bm = new BITMAP();
+// OS.GetObject(hBitmap, BITMAP.sizeof, bm);
+// int iconWidth = bm.bmWidth, iconHeight = bm.bmHeight;
+// if (hBitmap == srcIconInfo.hbmMask) iconHeight /= 2;
+//
+// if (simple) {
+// srcWidth = destWidth = iconWidth;
+// srcHeight = destHeight = iconHeight;
+// }
+//
+// /* Draw the icon */
+// boolean failed = srcX + srcWidth > iconWidth || srcY + srcHeight > iconHeight;
+// if (!failed) {
+// simple = srcX == 0 && srcY == 0 &&
+// srcWidth == destWidth && srcHeight == destHeight &&
+// srcWidth == iconWidth && srcHeight == iconHeight;
+// if (simple && technology != OS.DT_RASPRINTER) {
+// /* Simple case: no stretching, entire icon */
+// OS.DrawIconEx(handle, destX, destY, srcImage.handle, 0, 0, 0, 0, OS.DI_NORMAL);
+// } else {
+// /* Get the HDC for the device */
+// Device device = data.device;
+// int hDC = device.internal_new_GC(null);
+//
+// /* Create the icon info and HDC's */
+// ICONINFO newIconInfo = new ICONINFO();
+// newIconInfo.fIcon = true;
+// int srcHdc = OS.CreateCompatibleDC(hDC);
+// int dstHdc = OS.CreateCompatibleDC(hDC);
+//
+// /* Blt the color bitmap */
+// int srcColorY = srcY;
+// int srcColor = srcIconInfo.hbmColor;
+// if (srcColor == 0) {
+// srcColor = srcIconInfo.hbmMask;
+// srcColorY += iconHeight;
+// }
+// int oldSrcBitmap = OS.SelectObject(srcHdc, srcColor);
+// newIconInfo.hbmColor = OS.CreateCompatibleBitmap(srcHdc, destWidth, destHeight);
+// if (newIconInfo.hbmColor == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// int oldDestBitmap = OS.SelectObject(dstHdc, newIconInfo.hbmColor);
+// boolean stretch = !simple && (srcWidth != destWidth || srcHeight != destHeight);
+// if (stretch) {
+// if (!OS.IsWinCE) OS.SetStretchBltMode(dstHdc, OS.COLORONCOLOR);
+// OS.StretchBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcColorY, srcWidth, srcHeight, OS.SRCCOPY);
+// } else {
+// OS.BitBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcColorY, OS.SRCCOPY);
+// }
+//
+// /* Blt the mask bitmap */
+// OS.SelectObject(srcHdc, srcIconInfo.hbmMask);
+// newIconInfo.hbmMask = OS.CreateBitmap(destWidth, destHeight, 1, 1, null);
+// if (newIconInfo.hbmMask == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// OS.SelectObject(dstHdc, newIconInfo.hbmMask);
+// if (stretch) {
+// OS.StretchBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCCOPY);
+// } else {
+// OS.BitBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, OS.SRCCOPY);
+// }
+//
+// if (technology == OS.DT_RASPRINTER) {
+// OS.SelectObject(srcHdc, newIconInfo.hbmColor);
+// OS.SelectObject(dstHdc, srcIconInfo.hbmMask);
+// drawBitmapTransparentByClipping(srcHdc, dstHdc, 0, 0, destWidth, destHeight, destX, destY, destWidth, destHeight, true, destWidth, destHeight);
+// OS.SelectObject(srcHdc, oldSrcBitmap);
+// OS.SelectObject(dstHdc, oldDestBitmap);
+// } else {
+// OS.SelectObject(srcHdc, oldSrcBitmap);
+// OS.SelectObject(dstHdc, oldDestBitmap);
+// int hIcon = OS.CreateIconIndirect(newIconInfo);
+// if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// OS.DrawIconEx(handle, destX, destY, hIcon, destWidth, destHeight, 0, 0, OS.DI_NORMAL);
+// OS.DestroyIcon(hIcon);
+// }
+//
+// /* Destroy the new icon src and mask and hdc's*/
+// OS.DeleteObject(newIconInfo.hbmMask);
+// OS.DeleteObject(newIconInfo.hbmColor);
+// OS.DeleteDC(dstHdc);
+// OS.DeleteDC(srcHdc);
+//
+// /* Release the HDC for the device */
+// device.internal_dispose_GC(hDC, null);
+// }
+// }
+//
+// /* Free icon info */
+// OS.DeleteObject(srcIconInfo.hbmMask);
+// if (srcIconInfo.hbmColor != 0) {
+// OS.DeleteObject(srcIconInfo.hbmColor);
+// }
+//
+// if (failed) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+//}
+//
+//void drawBitmap(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
+// BITMAP bm = new BITMAP();
+// OS.GetObject(srcImage.handle, BITMAP.sizeof, bm);
+// int imgWidth = bm.bmWidth;
+// int imgHeight = bm.bmHeight;
+// if (simple) {
+// srcWidth = destWidth = imgWidth;
+// srcHeight = destHeight = imgHeight;
+// } else {
+// if (srcX + srcWidth > imgWidth || srcY + srcHeight > imgHeight) {
+// SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+// }
+// simple = srcX == 0 && srcY == 0 &&
+// srcWidth == destWidth && destWidth == imgWidth &&
+// srcHeight == destHeight && destHeight == imgHeight;
+// }
+// boolean mustRestore = false;
+// GC memGC = srcImage.memGC;
+// if (memGC != null && !memGC.isDisposed()) {
+// mustRestore = true;
+// GCData data = memGC.data;
+// if (data.hNullBitmap != 0) {
+// OS.SelectObject(memGC.handle, data.hNullBitmap);
+// data.hNullBitmap = 0;
+// }
+// }
+// if (srcImage.alpha != -1 || srcImage.alphaData != null) {
+// drawBitmapAlpha(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
+// } else if (srcImage.transparentPixel != -1) {
+// drawBitmapTransparent(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
+// } else {
+// drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
+// }
+// if (mustRestore) {
+// int hOldBitmap = OS.SelectObject(memGC.handle, srcImage.handle);
+// memGC.data.hNullBitmap = hOldBitmap;
+// }
+//}
+//
+//void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, BITMAP bm, int imgWidth, int imgHeight) {
+// /* Simple cases */
+// if (srcImage.alpha == 0) return;
+// if (srcImage.alpha == 255) {
+// drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
+// return;
+// }
+//
+// /* Check clipping */
+// Rectangle rect = getClipping();
+// rect = rect.intersection(new Rectangle(destX, destY, destWidth, destHeight));
+// if (rect.isEmpty()) return;
+//
+// /*
+// * Optimization. Recalculate src and dest rectangles so that
+// * only the clipping area is drawn.
+// */
+// int sx1 = srcX + (((rect.x - destX) * srcWidth) / destWidth);
+// int sx2 = srcX + ((((rect.x + rect.width) - destX) * srcWidth) / destWidth);
+// int sy1 = srcY + (((rect.y - destY) * srcHeight) / destHeight);
+// int sy2 = srcY + ((((rect.y + rect.height) - destY) * srcHeight) / destHeight);
+// destX = rect.x;
+// destY = rect.y;
+// destWidth = rect.width;
+// destHeight = rect.height;
+// srcX = sx1;
+// srcY = sy1;
+// srcWidth = Math.max(1, sx2 - sx1);
+// srcHeight = Math.max(1, sy2 - sy1);
+//
+// /* Create resources */
+// int srcHdc = OS.CreateCompatibleDC(handle);
+// int oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle);
+// int memHdc = OS.CreateCompatibleDC(handle);
+// int memDib = createDIB(Math.max(srcWidth, destWidth), Math.max(srcHeight, destHeight));
+// int oldMemBitmap = OS.SelectObject(memHdc, memDib);
+//
+// BITMAP dibBM = new BITMAP();
+// OS.GetObject(memDib, BITMAP.sizeof, dibBM);
+// int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
+//
+// /* Get the background pixels */
+// OS.BitBlt(memHdc, 0, 0, destWidth, destHeight, handle, destX, destY, OS.SRCCOPY);
+// byte[] destData = new byte[sizeInBytes];
+// OS.MoveMemory(destData, dibBM.bmBits, sizeInBytes);
+//
+// /* Get the foreground pixels */
+// OS.BitBlt(memHdc, 0, 0, srcWidth, srcHeight, srcHdc, srcX, srcY, OS.SRCCOPY);
+// byte[] srcData = new byte[sizeInBytes];
+// OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes);
+//
+// /* Merge the alpha channel in place */
+// int alpha = srcImage.alpha;
+// final boolean hasAlphaChannel = (srcImage.alpha == -1);
+// if (hasAlphaChannel) {
+// final int apinc = imgWidth - srcWidth;
+// final int spinc = dibBM.bmWidthBytes - srcWidth * 4;
+// int ap = srcY * imgWidth + srcX, sp = 3;
+// byte[] alphaData = srcImage.alphaData;
+// for (int y = 0; y < srcHeight; ++y) {
+// for (int x = 0; x < srcWidth; ++x) {
+// srcData[sp] = alphaData[ap++];
+// sp += 4;
+// }
+// ap += apinc;
+// sp += spinc;
+// }
+// }
+//
+// /* Scale the foreground pixels with alpha */
+// OS.MoveMemory(dibBM.bmBits, srcData, sizeInBytes);
+// /*
+// * Bug in WinCE and Win98. StretchBlt does not correctly stretch when
+// * the source and destination HDCs are the same. The workaround is to
+// * stretch to a temporary HDC and blit back into the original HDC.
+// * Note that on WinCE StretchBlt correctly compresses the image when the
+// * source and destination HDCs are the same.
+// */
+// if ((OS.IsWinCE && (destWidth > srcWidth || destHeight > srcHeight)) || (!OS.IsWinNT && !OS.IsWinCE)) {
+// int tempHdc = OS.CreateCompatibleDC(handle);
+// int tempDib = createDIB(destWidth, destHeight);
+// int oldTempBitmap = OS.SelectObject(tempHdc, tempDib);
+// if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) {
+// if (!OS.IsWinCE) OS.SetStretchBltMode(memHdc, OS.COLORONCOLOR);
+// OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
+// } else {
+// OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, OS.SRCCOPY);
+// }
+// OS.BitBlt(memHdc, 0, 0, destWidth, destHeight, tempHdc, 0, 0, OS.SRCCOPY);
+// OS.SelectObject(tempHdc, oldTempBitmap);
+// OS.DeleteObject(tempDib);
+// OS.DeleteDC(tempHdc);
+// } else {
+// if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) {
+// if (!OS.IsWinCE) OS.SetStretchBltMode(memHdc, OS.COLORONCOLOR);
+// OS.StretchBlt(memHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
+// } else {
+// OS.BitBlt(memHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, OS.SRCCOPY);
+// }
+// }
+// OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes);
+//
+// /* Compose the pixels */
+// final int dpinc = dibBM.bmWidthBytes - destWidth * 4;
+// int dp = 0;
+// for (int y = 0; y < destHeight; ++y) {
+// for (int x = 0; x < destWidth; ++x) {
+// if (hasAlphaChannel) alpha = srcData[dp + 3] & 0xff;
+// destData[dp] += ((srcData[dp] & 0xff) - (destData[dp] & 0xff)) * alpha / 255;
+// destData[dp + 1] += ((srcData[dp + 1] & 0xff) - (destData[dp + 1] & 0xff)) * alpha / 255;
+// destData[dp + 2] += ((srcData[dp + 2] & 0xff) - (destData[dp + 2] & 0xff)) * alpha / 255;
+// dp += 4;
+// }
+// dp += dpinc;
+// }
+//
+// /* Draw the composed pixels */
+// OS.MoveMemory(dibBM.bmBits, destData, sizeInBytes);
+// OS.BitBlt(handle, destX, destY, destWidth, destHeight, memHdc, 0, 0, OS.SRCCOPY);
+//
+// /* Free resources */
+// OS.SelectObject(memHdc, oldMemBitmap);
+// OS.DeleteDC(memHdc);
+// OS.DeleteObject(memDib);
+// OS.SelectObject(srcHdc, oldSrcBitmap);
+// OS.DeleteDC(srcHdc);
+//}
+//
+//void drawBitmapTransparentByClipping(int srcHdc, int maskHdc, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imgWidth, int imgHeight) {
+// int rgn = OS.CreateRectRgn(0, 0, 0, 0);
+// for (int y=0; y> 16;
+// transGreen = (color & 0xFF00) >> 8;
+// transRed = color & 0xFF;
+// } else {
+// int maxColors = 1 << bm.bmBitsPixel;
+// byte[] oldColors = new byte[maxColors * 4];
+// OS.GetDIBColorTable(srcHdc, 0, maxColors, oldColors);
+// int offset = srcImage.transparentPixel * 4;
+// byte[] newColors = new byte[oldColors.length];
+// transRed = transGreen = transBlue = 0xff;
+// newColors[offset] = (byte)transBlue;
+// newColors[offset+1] = (byte)transGreen;
+// newColors[offset+2] = (byte)transRed;
+// OS.SetDIBColorTable(srcHdc, 0, maxColors, newColors);
+// originalColors = oldColors;
+// }
+// } else {
+// /* Palette-based bitmap */
+// int numColors = 1 << bm.bmBitsPixel;
+// /* Set the few fields necessary to get the RGB data out */
+// BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
+// bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+// bmiHeader.biPlanes = bm.bmPlanes;
+// bmiHeader.biBitCount = bm.bmBitsPixel;
+// byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
+// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+// OS.GetDIBits(srcHdc, srcImage.handle, 0, 0, 0, bmi, OS.DIB_RGB_COLORS);
+// int offset = BITMAPINFOHEADER.sizeof + 4 * srcImage.transparentPixel;
+// transRed = bmi[offset + 2] & 0xFF;
+// transGreen = bmi[offset + 1] & 0xFF;
+// transBlue = bmi[offset] & 0xFF;
+// }
+// } else {
+// /* Direct color image */
+// int pixel = srcImage.transparentPixel;
+// switch (bm.bmBitsPixel) {
+// case 16:
+// transBlue = (pixel & 0x1F) << 3;
+// transGreen = (pixel & 0x3E0) >> 2;
+// transRed = (pixel & 0x7C00) >> 7;
+// break;
+// case 24:
+// transBlue = (pixel & 0xFF0000) >> 16;
+// transGreen = (pixel & 0xFF00) >> 8;
+// transRed = pixel & 0xFF;
+// break;
+// case 32:
+// transBlue = (pixel & 0xFF000000) >>> 24;
+// transGreen = (pixel & 0xFF0000) >> 16;
+// transRed = (pixel & 0xFF00) >> 8;
+// break;
+// }
+// }
+//
+// if (OS.IsWinCE) {
+// /*
+// * Note in WinCE. TransparentImage uses the first entry of a palette
+// * based image when there are multiple entries that have the same
+// * transparent color.
+// */
+// int transparentColor = transBlue << 16 | transGreen << 8 | transRed;
+// OS.TransparentImage(handle, destX, destY, destWidth, destHeight,
+// srcHdc, srcX, srcY, srcWidth, srcHeight, transparentColor);
+// } else {
+// /* Create the mask for the source image */
+// int maskHdc = OS.CreateCompatibleDC(hDC);
+// int maskBitmap = OS.CreateBitmap(imgWidth, imgHeight, 1, 1, null);
+// int oldMaskBitmap = OS.SelectObject(maskHdc, maskBitmap);
+// OS.SetBkColor(srcHdc, (transBlue << 16) | (transGreen << 8) | transRed);
+// OS.BitBlt(maskHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
+// if (originalColors != null) OS.SetDIBColorTable(srcHdc, 0, 1 << bm.bmBitsPixel, originalColors);
+//
+// if (OS.GetDeviceCaps(handle, OS.TECHNOLOGY) == OS.DT_RASPRINTER) {
+// /* Most printers do not support BitBlt(), draw the source bitmap transparently using clipping */
+// drawBitmapTransparentByClipping(srcHdc, maskHdc, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, imgWidth, imgHeight);
+// } else {
+// /* Draw the source bitmap transparently using invert/and mask/invert */
+// int tempHdc = OS.CreateCompatibleDC(hDC);
+// int tempBitmap = OS.CreateCompatibleBitmap(hDC, destWidth, destHeight);
+// int oldTempBitmap = OS.SelectObject(tempHdc, tempBitmap);
+// OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, handle, destX, destY, OS.SRCCOPY);
+// if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) {
+// if (!OS.IsWinCE) OS.SetStretchBltMode(tempHdc, OS.COLORONCOLOR);
+// OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCINVERT);
+// OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, maskHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCAND);
+// OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCINVERT);
+// } else {
+// OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, OS.SRCINVERT);
+// OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, maskHdc, srcX, srcY, OS.SRCAND);
+// OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, OS.SRCINVERT);
+// }
+// OS.BitBlt(handle, destX, destY, destWidth, destHeight, tempHdc, 0, 0, OS.SRCCOPY);
+// OS.SelectObject(tempHdc, oldTempBitmap);
+// OS.DeleteDC(tempHdc);
+// OS.DeleteObject(tempBitmap);
+// }
+// OS.SelectObject(maskHdc, oldMaskBitmap);
+// OS.DeleteDC(maskHdc);
+// OS.DeleteObject(maskBitmap);
+// }
+// OS.SelectObject(srcHdc, oldSrcBitmap);
+// if (hBitmap != srcImage.handle) OS.DeleteObject(hBitmap);
+// OS.DeleteDC(srcHdc);
+//
+// /* Release the HDC for the device */
+// device.internal_dispose_GC(hDC, null);
+//}
+//
+//void drawBitmap(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, BITMAP bm, int imgWidth, int imgHeight) {
+// if (data.gdipGraphics != 0) {
+// //TODO - cache bitmap
+// int img = Gdip.Bitmap_new(srcImage.handle, 0);
+// Rect rect = new Rect();
+// rect.X = destX;
+// rect.Y = destY;
+// rect.Width = destWidth;
+// rect.Height = destHeight;
+// Gdip.Graphics_DrawImage(data.gdipGraphics, img, rect, srcX, srcY, srcWidth, srcHeight, Gdip.UnitPixel, 0, 0, 0);
+// Gdip.Bitmap_delete(img);
+// return;
+// }
+// int srcHdc = OS.CreateCompatibleDC(handle);
+// int oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle);
+// int rop2 = 0;
+// if (!OS.IsWinCE) {
+// rop2 = OS.GetROP2(handle);
+// } else {
+// rop2 = OS.SetROP2 (handle, OS.R2_COPYPEN);
+// OS.SetROP2 (handle, rop2);
+// }
+// int dwRop = rop2 == OS.R2_XORPEN ? OS.SRCINVERT : OS.SRCCOPY;
+// if (!simple && (srcWidth != destWidth || srcHeight != destHeight)) {
+// int mode = 0;
+// if (!OS.IsWinCE) mode = OS.SetStretchBltMode(handle, OS.COLORONCOLOR);
+// OS.StretchBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, dwRop);
+// if (!OS.IsWinCE) OS.SetStretchBltMode(handle, mode);
+// } else {
+// OS.BitBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, dwRop);
+// }
+// OS.SelectObject(srcHdc, oldSrcBitmap);
+// OS.DeleteDC(srcHdc);
+//}
+
+/**
+ * Draws a line, using the foreground color, between the points
+ * (x1, y1) and (x2, y2).
+ *
+ * @param x1 the first point's x coordinate
+ * @param y1 the first point's y coordinate
+ * @param x2 the second point's x coordinate
+ * @param y2 the second point's y coordinate
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawLine (int x1, int y1, int x2, int y2) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.drawLine(x1, y1, x2, y2);
+// Point p1 = new Point(Math.min(x1, x2), Math.min(y1, y2));
+// Point p2 = new Point(Math.max(x1, x2), Math.max(y1, y2));
+// ensureAreaClean(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);
+}
+
+/**
+ * Draws the outline of an oval, using the foreground color,
+ * within the specified rectangular area.
+ *
+ * The result is a circle or ellipse that fits within the
+ * rectangle specified by the x, y,
+ * width, and height arguments.
+ *
+ * The oval covers an area that is width + 1
+ * pixels wide and height + 1 pixels tall.
+ *
+ *
+ * @param x the x coordinate of the upper left corner of the oval to be drawn
+ * @param y the y coordinate of the upper left corner of the oval to be drawn
+ * @param width the width of the oval to be drawn
+ * @param height the height of the oval to be drawn
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawOval (int x, int y, int width, int height) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.drawOval(x, y, width, height);
+// ensureAreaClean(x, y, width, height);
+}
+
+/**
+ * Draws the path described by the parameter.
+ *
+ * @param path the path to draw
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parameter is null
+ *
ERROR_INVALID_ARGUMENT - if the parameter has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Path
+ *
+ * @since 3.1
+ */
+public void drawPath (Path path) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (path.handle == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle.draw(path.handle);
+// java.awt.Rectangle bounds = path.handle.getBounds();
+// ensureAreaClean(bounds.x, bounds.y, bounds.width, bounds.height);
+}
+
+/**
+ * Draws a pixel, using the foreground color, at the specified
+ * point (x, y).
+ *
+ * Note that the receiver's line attributes do not affect this
+ * operation.
+ *
+ *
+ * @param x the point's x coordinate
+ * @param y the point's y coordinate
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void drawPoint (int x, int y) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.drawLine(x, y, x, y);
+// ensureAreaClean(x, y, 1, 1);
+}
+
+/**
+ * Draws the closed polygon which is defined by the specified array
+ * of integer coordinates, using the receiver's foreground color. The array
+ * contains alternating x and y values which are considered to represent
+ * points which are the vertices of the polygon. Lines are drawn between
+ * each consecutive pair, and between the first pair and last pair in the
+ * array.
+ *
+ * @param pointArray an array of alternating x and y values which are the vertices of the polygon
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT if pointArray is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawPolygon(int[] pointArray) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// int maxX = Integer.MIN_VALUE;
+// int maxY = Integer.MIN_VALUE;
+// int minX = Integer.MAX_VALUE;
+// int minY = Integer.MAX_VALUE;
+ int[] xPoints = new int[pointArray.length/2];
+ int[] yPoints = new int[xPoints.length];
+ for(int i=0; i
+ *
ERROR_NULL_ARGUMENT - if the point array is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawPolyline(int[] pointArray) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// int maxX = Integer.MIN_VALUE;
+// int maxY = Integer.MIN_VALUE;
+// int minX = Integer.MAX_VALUE;
+// int minY = Integer.MAX_VALUE;
+ int[] xPoints = new int[pointArray.length/2];
+ int[] yPoints = new int[xPoints.length];
+ for(int i=0; ix and x + width.
+ * The top and bottom edges are at y and y + height.
+ *
+ * @param x the x coordinate of the rectangle to be drawn
+ * @param y the y coordinate of the rectangle to be drawn
+ * @param width the width of the rectangle to be drawn
+ * @param height the height of the rectangle to be drawn
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawRectangle (int x, int y, int width, int height) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.drawRect(x, y, width, height);
+// ensureAreaClean(x, y, width, height);
+}
+
+/**
+ * Draws the outline of the specified rectangle, using the receiver's
+ * foreground color. The left and right edges of the rectangle are at
+ * rect.x and rect.x + rect.width. The top
+ * and bottom edges are at rect.y and
+ * rect.y + rect.height.
+ *
+ * @param rect the rectangle to draw
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the rectangle is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawRectangle (Rectangle rect) {
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ drawRectangle (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Draws the outline of the round-cornered rectangle specified by
+ * the arguments, using the receiver's foreground color. The left and
+ * right edges of the rectangle are at x and x + width.
+ * The top and bottom edges are at y and y + height.
+ * The roundness of the corners is specified by the
+ * arcWidth and arcHeight arguments, which
+ * are respectively the width and height of the ellipse used to draw
+ * the corners.
+ *
+ * @param x the x coordinate of the rectangle to be drawn
+ * @param y the y coordinate of the rectangle to be drawn
+ * @param width the width of the rectangle to be drawn
+ * @param height the height of the rectangle to be drawn
+ * @param arcWidth the width of the arc
+ * @param arcHeight the height of the arc
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
+// ensureAreaClean(x, y, width, height);
+}
+
+//void drawRoundRectangleGdip (int gdipGraphics, int brush, int x, int y, int width, int height, int arcWidth, int arcHeight) {
+// int nx = x;
+// int ny = y;
+// int nw = width;
+// int nh = height;
+// int naw = arcWidth;
+// int nah = arcHeight;
+//
+// if (nw < 0) {
+// nw = 0 - nw;
+// nx = nx - nw;
+// }
+// if (nh < 0) {
+// nh = 0 - nh;
+// ny = ny - nh;
+// }
+// if (naw < 0)
+// naw = 0 - naw;
+// if (nah < 0)
+// nah = 0 - nah;
+//
+// int naw2 = naw / 2;
+// int nah2 = nah / 2;
+//
+// if (nw > naw) {
+// if (nh > nah) {
+// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny, naw, nah, -90, -90);
+// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + naw2, ny, nx + nw - naw2, ny);
+// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx + nw - naw, ny, naw, nah, 0, -90);
+// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + nw, ny + nah2, nx + nw, ny + nh - nah2);
+// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90);
+// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + naw2, ny + nh, nx + nw - naw2, ny + nh);
+// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny + nh - nah, naw, nah, -180, -90);
+// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx, ny + nah2, nx, ny + nh - nah2);
+// } else {
+// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny, naw, nh, 90, -180);
+// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + naw2, ny, nx + nw - naw2, ny);
+// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx + nw - naw, ny, naw, nh, 270, -180);
+// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + naw2, ny + nh, nx + nw - naw2, ny + nh);
+// }
+// } else {
+// if (nh > nah) {
+// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny, nw, nah, 0, -180);
+// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx + nw, ny + nah2, nx + nw, ny + nh - nah2);
+// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny + nh - nah, nw, nah, -180, -180);
+// Gdip.Graphics_DrawLine(gdipGraphics, brush, nx, ny + nah2, nx, ny + nh - nah2);
+// } else {
+// Gdip.Graphics_DrawArc(gdipGraphics, brush, nx, ny, nw, nh, 0, 360);
+// }
+// }
+//}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. No tab expansion or carriage return processing
+ * will be performed. The background of the rectangular area where
+ * the string is being drawn will be filled with the receiver's
+ * background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawString (String string, int x, int y) {
+ drawString(string, x, y, false);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. No tab expansion or carriage return processing
+ * will be performed. If isTransparent is true,
+ * then the background of the rectangular area where the string is being
+ * drawn will not be modified, otherwise it will be filled with the
+ * receiver's background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
+ * @param isTransparent if true the background will be transparent, otherwise it will be opaque
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawString (String string, int x, int y, boolean isTransparent) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ drawText(string, x, y, isTransparent? SWT.DRAW_TRANSPARENT: 0);
+// if(!isTransparent) {
+// java.awt.Color oldColor = handle.getColor();
+// handle.setColor(data.background);
+// Point extent = stringExtent(string);
+// fillRectangle(x, y, extent.x, extent.y);
+// handle.setColor(oldColor);
+// }
+// handle.drawString(string, x, y + handle.getFontMetrics().getMaxAscent());
+// // TODO: optimize if the ensureAreaClean works
+// Point extent = stringExtent(string);
+// ensureAreaClean(x, y, extent.x, extent.y);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. Tab expansion and carriage return processing
+ * are performed. The background of the rectangular area where
+ * the text is being drawn will be filled with the receiver's
+ * background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawText (String string, int x, int y) {
+ drawText(string, x, y, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. Tab expansion and carriage return processing
+ * are performed. If isTransparent is true,
+ * then the background of the rectangular area where the text is being
+ * drawn will not be modified, otherwise it will be filled with the
+ * receiver's background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param isTransparent if true the background will be transparent, otherwise it will be opaque
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawText (String string, int x, int y, boolean isTransparent) {
+ int flags = SWT.DRAW_DELIMITER | SWT.DRAW_TAB;
+ if (isTransparent) flags |= SWT.DRAW_TRANSPARENT;
+ drawText(string, x, y, flags);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. Tab expansion, line delimiter and mnemonic
+ * processing are performed according to the specified flags. If
+ * flags includes DRAW_TRANSPARENT,
+ * then the background of the rectangular area where the text is being
+ * drawn will not be modified, otherwise it will be filled with the
+ * receiver's background color.
+ *
+ * The parameter flags may be a combination of:
+ *
+ *
DRAW_DELIMITER
+ *
draw multiple lines
+ *
DRAW_TAB
+ *
expand tabs
+ *
DRAW_MNEMONIC
+ *
underline the mnemonic character
+ *
DRAW_TRANSPARENT
+ *
transparent background
+ *
+ *
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param flags the flags specifing how to process the text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void drawText (String string, int x, int y, int flags) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (string.length() == 0) return;
+ if((flags & SWT.DRAW_TAB) != 0) {
+ string = string.replaceAll("\t", " ");
+ }
+ int mnemonicIndex = -1;
+ if((flags & SWT.DRAW_MNEMONIC) != 0) {
+ // Copied from Label
+ mnemonicIndex = findMnemonicIndex(string);
+ if(mnemonicIndex > 0) {
+ String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&");
+ string = s + string.substring(mnemonicIndex).replaceAll("&&", "&");
+ mnemonicIndex -= mnemonicIndex - 1 - s.length();
+ mnemonicIndex--;
+ } else {
+ string = string.replaceAll("&&", "&");
+ }
+ // TODO: if the mnemonic index is not -1, then draw a line under the char.
+ }
+ String[] tokens;
+ if((flags & SWT.DRAW_DELIMITER) != 0) {
+ tokens = string.split("\n");
+ } else {
+ tokens = new String[] {string};
+ }
+ boolean isTransparent = (flags & SWT.DRAW_TRANSPARENT) != 0;
+ java.awt.FontMetrics fm = handle.getFontMetrics();
+ int fmHeight = fm.getHeight();
+ int maxAscent = fm.getMaxAscent();
+ int currentHeight = 0;
+ for(int i=0; i= length) return -1;
+ if (string.charAt (index) != '&') return index;
+ index++;
+ } while (index < length);
+ return -1;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the same object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return true if the object is the same as this object and false otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ return (object == this) || ((object instanceof GC) && (handle == ((GC)object).handle));
+}
+
+/**
+ * Fills the interior of a circular or elliptical arc within
+ * the specified rectangular area, with the receiver's background
+ * color.
+ *
+ * The resulting arc begins at startAngle and extends
+ * for arcAngle degrees, using the current color.
+ * Angles are interpreted such that 0 degrees is at the 3 o'clock
+ * position. A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ *
+ * The center of the arc is the center of the rectangle whose origin
+ * is (x, y) and whose size is specified by the
+ * width and height arguments.
+ *
+ * The resulting arc covers an area width + 1 pixels wide
+ * by height + 1 pixels tall.
+ *
+ *
+ * @param x the x coordinate of the upper-left corner of the arc to be filled
+ * @param y the y coordinate of the upper-left corner of the arc to be filled
+ * @param width the width of the arc to be filled
+ * @param height the height of the arc to be filled
+ * @param startAngle the beginning angle
+ * @param arcAngle the angular extent of the arc, relative to the start angle
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #drawArc
+ */
+public void fillArc (int x, int y, int width, int height, int startAngle, int arcAngle) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (width == 0 || height == 0 || arcAngle == 0) return;
+ java.awt.Color oldColor = handle.getColor();
+ handle.setColor(data.background);
+ handle.fillArc(x, y, width, height, startAngle, arcAngle);
+ handle.setColor(oldColor);
+// ensureAreaClean(x, y, width, height);
+// if (data.gdipGraphics != 0) {
+// initGdip(false, true);
+// Gdip.Graphics_FillPie(data.gdipGraphics, data.gdipBrush, x, y, width, height, -startAngle, -arcAngle);
+// return;
+// }
+//
+// /*
+// * Feature in WinCE. The function Pie is not present in the
+// * WinCE SDK. The fix is to emulate it by using Polygon.
+// */
+// if (OS.IsWinCE) {
+// /* compute arc with a simple linear interpolation */
+// if (arcAngle < 0) {
+// startAngle += arcAngle;
+// arcAngle = -arcAngle;
+// }
+// boolean drawSegments = true;
+// if (arcAngle >= 360) {
+// arcAngle = 360;
+// drawSegments = false;
+// }
+// int[] points = new int[(arcAngle + 1) * 2 + (drawSegments ? 4 : 0)];
+// int cteX = 2 * x + width;
+// int cteY = 2 * y + height;
+// int index = (drawSegments ? 2 : 0);
+// for (int i = 0; i <= arcAngle; i++) {
+// points[index++] = (Compatibility.cos(startAngle + i, width) + cteX) >> 1;
+// points[index++] = (cteY - Compatibility.sin(startAngle + i, height)) >> 1;
+// }
+// if (drawSegments) {
+// points[0] = points[points.length - 2] = cteX >> 1;
+// points[1] = points[points.length - 1] = cteY >> 1;
+// }
+// int nullPen = OS.GetStockObject(OS.NULL_PEN);
+// int oldPen = OS.SelectObject(handle, nullPen);
+// OS.Polygon(handle, points, points.length / 2);
+// OS.SelectObject(handle, oldPen);
+// } else {
+// int x1, y1, x2, y2,tmp;
+// boolean isNegative;
+// if (arcAngle >= 360 || arcAngle <= -360) {
+// x1 = x2 = x + width;
+// y1 = y2 = y + height / 2;
+// } else {
+// isNegative = arcAngle < 0;
+//
+// arcAngle = arcAngle + startAngle;
+// if (isNegative) {
+// // swap angles
+// tmp = startAngle;
+// startAngle = arcAngle;
+// arcAngle = tmp;
+// }
+// x1 = Compatibility.cos(startAngle, width) + x + width/2;
+// y1 = -1 * Compatibility.sin(startAngle, height) + y + height/2;
+//
+// x2 = Compatibility.cos(arcAngle, width) + x + width/2;
+// y2 = -1 * Compatibility.sin(arcAngle, height) + y + height/2;
+// }
+//
+// int nullPen = OS.GetStockObject(OS.NULL_PEN);
+// int oldPen = OS.SelectObject(handle, nullPen);
+// OS.Pie(handle, x, y, x + width + 1, y + height + 1, x1, y1, x2, y2);
+// OS.SelectObject(handle, oldPen);
+// }
+}
+
+/**
+ * Fills the interior of the specified rectangle with a gradient
+ * sweeping from left to right or top to bottom progressing
+ * from the receiver's foreground color to its background color.
+ *
+ * @param x the x coordinate of the rectangle to be filled
+ * @param y the y coordinate of the rectangle to be filled
+ * @param width the width of the rectangle to be filled, may be negative
+ * (inverts direction of gradient if horizontal)
+ * @param height the height of the rectangle to be filled, may be negative
+ * (inverts direction of gradient if vertical)
+ * @param vertical if true sweeps from top to bottom, else
+ * sweeps from left to right
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void fillGradientRectangle(int x, int y, int width, int height, boolean vertical) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width == 0 || height == 0) return;
+ java.awt.Color fromColor = handle.getColor();
+ java.awt.Color toColor = handle.getBackground();
+ Paint oldPaint = handle.getPaint();
+ java.awt.Point p1;
+ java.awt.Point p2;
+ if(vertical) {
+ p1 = new java.awt.Point(x, y);
+ p2 = new java.awt.Point(x, y + height);
+ } else {
+ p1 = new java.awt.Point(x, y);
+ p2 = new java.awt.Point(x + width, y);
+ }
+// java.awt.Color oldColor = handle.getColor();
+// handle.setColor(data.background);
+ handle.setPaint(new GradientPaint(p1, fromColor, p2, toColor));
+ handle.fill(new java.awt.Rectangle(x, y, width, height));
+// handle.setColor(oldColor);
+ handle.setPaint(oldPaint);
+// ensureAreaClean(x, y, width, height);
+}
+
+/**
+ * Fills the interior of an oval, within the specified
+ * rectangular area, with the receiver's background
+ * color.
+ *
+ * @param x the x coordinate of the upper left corner of the oval to be filled
+ * @param y the y coordinate of the upper left corner of the oval to be filled
+ * @param width the width of the oval to be filled
+ * @param height the height of the oval to be filled
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #drawOval
+ */
+public void fillOval (int x, int y, int width, int height) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ java.awt.Color oldColor = handle.getColor();
+ handle.setColor(data.background);
+ handle.fillOval(x, y, width, height);
+ handle.setColor(oldColor);
+// ensureAreaClean(x, y, width, height);
+// if (data.gdipGraphics != 0) {
+// initGdip(false, true);
+// Gdip.Graphics_FillEllipse(data.gdipGraphics, data.gdipBrush, x, y, width, height);
+// return;
+// }
+// /* Assumes that user sets the background color. */
+// int nullPen = OS.GetStockObject(OS.NULL_PEN);
+// int oldPen = OS.SelectObject(handle, nullPen);
+// OS.Ellipse(handle, x, y, x + width + 1, y + height + 1);
+// OS.SelectObject(handle,oldPen);
+}
+
+/**
+ * Fills the path described by the parameter.
+ *
+ * @param path the path to fill
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parameter is null
+ *
ERROR_INVALID_ARGUMENT - if the parameter has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Path
+ *
+ * @since 3.1
+ */
+public void fillPath (Path path) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (path.handle == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ // Set fill(winding) rule
+ int windingRule = fillRule == SWT.FILL_EVEN_ODD ? GeneralPath.WIND_EVEN_ODD: GeneralPath.WIND_NON_ZERO;
+ path.handle.setWindingRule(windingRule);
+ // Use background color for paint.
+ Paint old = handle.getPaint();
+ handle.setPaint(handle.getBackground());
+ handle.fill(path.handle);
+ handle.setPaint(old);
+// java.awt.Rectangle bounds = path.handle.getBounds();
+// ensureAreaClean(bounds.x, bounds.y, bounds.width, bounds.height);
+}
+
+/**
+ * Fills the interior of the closed polygon which is defined by the
+ * specified array of integer coordinates, using the receiver's
+ * background color. The array contains alternating x and y values
+ * which are considered to represent points which are the vertices of
+ * the polygon. Lines are drawn between each consecutive pair, and
+ * between the first pair and last pair in the array.
+ *
+ * @param pointArray an array of alternating x and y values which are the vertices of the polygon
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT if pointArray is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #drawPolygon
+ */
+public void fillPolygon(int[] pointArray) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int maxX = Integer.MIN_VALUE;
+ int maxY = Integer.MIN_VALUE;
+ int minX = Integer.MAX_VALUE;
+ int minY = Integer.MAX_VALUE;
+ int[] xPoints = new int[pointArray.length/2];
+ int[] yPoints = new int[xPoints.length];
+ for(int i=0; i
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void fillRectangle (int x, int y, int width, int height) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ java.awt.Color oldColor = handle.getColor();
+ handle.setColor(data.background);
+ handle.fillRect(x, y, width, height);
+ handle.setColor(oldColor);
+// ensureAreaClean(x, y, width, height);
+// if (data.gdipGraphics != 0) {
+// initGdip(false, true);
+// Gdip.Graphics_FillRectangle(data.gdipGraphics, data.gdipBrush, x, y, width, height);
+// return;
+// }
+// int rop2 = 0;
+// if (OS.IsWinCE) {
+// rop2 = OS.SetROP2(handle, OS.R2_COPYPEN);
+// OS.SetROP2(handle, rop2);
+// } else {
+// rop2 = OS.GetROP2(handle);
+// }
+// int dwRop = rop2 == OS.R2_XORPEN ? OS.PATINVERT : OS.PATCOPY;
+// OS.PatBlt(handle, x, y, width, height, dwRop);
+}
+
+/**
+ * Fills the interior of the specified rectangle, using the receiver's
+ * background color.
+ *
+ * @param rect the rectangle to be filled
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the rectangle is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void fillRectangle (Rectangle rect) {
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ java.awt.Color oldColor = handle.getColor();
+ handle.setColor(data.background);
+ fillRectangle (rect.x, rect.y, rect.width, rect.height);
+ handle.setColor(oldColor);
+}
+
+/**
+ * Fills the interior of the round-cornered rectangle specified by
+ * the arguments, using the receiver's background color.
+ *
+ * @param x the x coordinate of the rectangle to be filled
+ * @param y the y coordinate of the rectangle to be filled
+ * @param width the width of the rectangle to be filled
+ * @param height the height of the rectangle to be filled
+ * @param arcWidth the width of the arc
+ * @param arcHeight the height of the arc
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #drawRoundRectangle
+ */
+public void fillRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ java.awt.Color oldColor = handle.getColor();
+ handle.setColor(data.background);
+ handle.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
+ handle.setColor(oldColor);
+// ensureAreaClean(x, y, width, height);
+// if (data.gdipGraphics != 0) {
+// initGdip(false, true);
+// fillRoundRectangleGdip(data.gdipGraphics, data.gdipBrush, x, y, width, height, arcWidth, arcHeight);
+// return;
+// }
+// int nullPen = OS.GetStockObject(OS.NULL_PEN);
+// int oldPen = OS.SelectObject(handle, nullPen);
+// OS.RoundRect(handle, x,y,x+width+1,y+height+1,arcWidth, arcHeight);
+// OS.SelectObject(handle,oldPen);
+}
+
+//void fillRoundRectangleGdip (int gdipGraphics, int brush, int x, int y, int width, int height, int arcWidth, int arcHeight) {
+// int nx = x;
+// int ny = y;
+// int nw = width;
+// int nh = height;
+// int naw = arcWidth;
+// int nah = arcHeight;
+//
+// if (nw < 0) {
+// nw = 0 - nw;
+// nx = nx - nw;
+// }
+// if (nh < 0) {
+// nh = 0 - nh;
+// ny = ny -nh;
+// }
+// if (naw < 0)
+// naw = 0 - naw;
+// if (nah < 0)
+// nah = 0 - nah;
+//
+// int naw2 = naw / 2;
+// int nah2 = nah / 2;
+//
+// if (nw > naw) {
+// if (nh > nah) {
+// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny, naw, nah, -90, -90);
+// Gdip.Graphics_FillRectangle(gdipGraphics, brush, nx + naw2, ny, nw - naw2 * 2, nah2);
+// Gdip.Graphics_FillPie(gdipGraphics, brush, nx + nw - naw, ny, naw, nah, 0, -90);
+// Gdip.Graphics_FillRectangle(gdipGraphics, brush, nx, ny + nah2, nw, nh - nah2 * 2);
+// Gdip.Graphics_FillPie(gdipGraphics, brush, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90);
+// Gdip.Graphics_FillRectangle(gdipGraphics, brush, nx + naw2, ny + nh - nah2, nw - naw2 * 2, nah2);
+// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny + nh - nah, naw, nah, -180, -90);
+// } else {
+// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny, naw, nh, -90, -180);
+// Gdip.Graphics_FillRectangle(gdipGraphics, brush, nx + naw2, ny, nw - naw2 * 2, nh);
+// Gdip.Graphics_FillPie(gdipGraphics, brush, nx + nw - naw, ny, naw, nh, -270, -180);
+// }
+// } else {
+// if (nh > nah) {
+// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny, nw, nah, 0, -180);
+// Gdip.Graphics_FillRectangle(gdipGraphics, brush, nx, ny + nah2, nw, nh - nah2 * 2);
+// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny + nh - nah, nw, nah, -180, -180);
+// } else {
+// Gdip.Graphics_FillPie(gdipGraphics, brush, nx, ny, nw, nh, 0, 360);
+// }
+// }
+//}
+
+/**
+ * Returns the advance width of the specified character in
+ * the font which is currently selected into the receiver.
+ *
+ * The advance width is defined as the horizontal distance the cursor
+ * should move after printing the character in the selected font.
+ *
+ *
+ * @param ch the character to measure
+ * @return the distance in the x direction to move past the character before painting the next
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getAdvanceWidth(char ch) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return handle.getFontMetrics().charWidth(ch);
+// if (OS.IsWinCE) {
+// SIZE size = new SIZE();
+// OS.GetTextExtentPoint32W(handle, new char[]{ch}, 1, size);
+// return size.cx;
+// }
+// int tch = ch;
+// if (ch > 0x7F) {
+// TCHAR buffer = new TCHAR(getCodePage(), ch, false);
+// tch = buffer.tcharAt(0);
+// }
+// int[] width = new int[1];
+// OS.GetCharWidth(handle, tch, tch, width);
+// return width[0];
+}
+
+/**
+ * Returns true if receiver is using the operating system's
+ * advanced graphics subsystem. Otherwise, false is returned
+ * to indicate that normal graphics are in use.
+ *
+ * Advanced graphics may not be installed for the operating system. In this
+ * case, false is always returned. Some operating system have
+ * only one graphics subsystem. If this subsystem supports advanced graphics,
+ * then true is always returned. If any graphics operation such
+ * as alpha, antialias, patterns, interpolation, paths, clipping or transformation
+ * has caused the receiver to switch from regular to advanced graphics mode,
+ * true is returned. If the receiver has been explicitly switched
+ * to advanced mode and this mode is supported, true is returned.
+ *
+ *
+ * @return the advanced value
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Color getBackground() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return Color.swing_new(data.device, handle.getBackground());
+// int color = OS.GetBkColor(handle);
+// if (color == OS.CLR_INVALID) {
+// color = OS.GetSysColor(OS.COLOR_WINDOW);
+// }
+// return Color.win32_new(data.device, color);
+}
+
+/**
+ * Returns the background pattern. The default value is
+ * null.
+ *
+ * @return the receiver's background pattern
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Pattern
+ *
+ * @since 3.1
+ */
+public Pattern getBackgroundPattern() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.backgroundPattern;
+}
+
+/**
+ * Returns the width of the specified character in the font
+ * selected into the receiver.
+ *
+ * The width is defined as the space taken up by the actual
+ * character, not including the leading and tailing whitespace
+ * or overhang.
+ *
+ *
+ * @param ch the character to measure
+ * @return the width of the character
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getCharWidth(char ch) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ // TODO: find the difference between advance width and char width
+ return handle.getFontMetrics().charWidth(ch);
+//
+// /* GetCharABCWidths only succeeds on truetype fonts */
+// if (!OS.IsWinCE) {
+// int tch = ch;
+// if (ch > 0x7F) {
+// TCHAR buffer = new TCHAR(getCodePage(), ch, false);
+// tch = buffer.tcharAt (0);
+// }
+// int[] width = new int[3];
+// if (OS.GetCharABCWidths(handle, tch, tch, width)) {
+// return width[1];
+// }
+// }
+//
+// /* It wasn't a truetype font */
+// TEXTMETRIC lptm = OS.IsUnicode ? (TEXTMETRIC)new TEXTMETRICW() : new TEXTMETRICA();
+// OS.GetTextMetrics(handle, lptm);
+// SIZE size = new SIZE();
+// OS.GetTextExtentPoint32W(handle, new char[]{ch}, 1, size);
+// return size.cx - lptm.tmOverhang;
+}
+
+/**
+ * Returns the bounding rectangle of the receiver's clipping
+ * region. If no clipping region is set, the return value
+ * will be a rectangle which covers the entire bounds of the
+ * object the receiver is drawing on.
+ *
+ * @return the bounding rectangle of the clipping region
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Rectangle getClipping() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ Shape userClip = handle.getUserClip();
+ java.awt.Rectangle bounds;
+ if(userClip != null) {
+ bounds = userClip.getBounds();
+ } else {
+ bounds = new java.awt.Rectangle(handle.getDeviceSize());
+ }
+ return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
+}
+
+/**
+ * Sets the region managed by the argument to the current
+ * clipping region of the receiver.
+ *
+ * @param region the region to fill with the clipping region
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the region is null
+ *
ERROR_INVALID_ARGUMENT - if the region is disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void getClipping (Region region) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ Shape userClip = handle.getUserClip();
+ if(userClip == null) {
+ userClip = new java.awt.Rectangle(handle.getDeviceSize());
+ }
+ region.add(new Region(data.device, userClip));
+// int result = OS.GetClipRgn (handle, region.handle);
+// if (result != 1) {
+// RECT rect = new RECT();
+// OS.GetClipBox(handle, rect);
+// OS.SetRectRgn(region.handle, rect.left, rect.top, rect.right, rect.bottom);
+// }
+// if (!OS.IsWinCE) {
+// int flags = 0;
+// if (OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+// flags = OS.GetLayout(handle);
+// }
+// int hwnd = data.hwnd;
+// if (hwnd != 0 && data.ps != null && (flags & OS.LAYOUT_RTL) == 0) {
+// int sysRgn = OS.CreateRectRgn (0, 0, 0, 0);
+// if (OS.GetRandomRgn (handle, sysRgn, OS.SYSRGN) == 1) {
+// if (OS.IsWinNT) {
+// POINT pt = new POINT();
+// OS.MapWindowPoints(0, hwnd, pt, 1);
+// OS.OffsetRgn(sysRgn, pt.x, pt.y);
+// }
+// OS.CombineRgn (region.handle, sysRgn, region.handle, OS.RGN_AND);
+// }
+// OS.DeleteObject(sysRgn);
+// }
+// }
+}
+
+//int getCodePage () {
+// if (OS.IsUnicode) return OS.CP_ACP;
+// int[] lpCs = new int[8];
+// int cs = OS.GetTextCharset(handle);
+// OS.TranslateCharsetInfo(cs, lpCs, OS.TCI_SRCCHARSET);
+// return lpCs[1];
+//}
+
+/**
+ * Returns the receiver's fill rule, which will be one of
+ * SWT.FILL_EVEN_ODD or SWT.FILL_WINDING.
+ *
+ * @return the receiver's fill rule
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public int getFillRule() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return fillRule;
+}
+
+/**
+ * Returns the font currently being used by the receiver
+ * to draw and measure text.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Font getFont () {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return Font.swing_new(data.device, handle.getFont());
+}
+
+/**
+ * Returns a FontMetrics which contains information
+ * about the font currently being used by the receiver
+ * to draw and measure text.
+ *
+ * @return font metrics for the receiver's font
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public FontMetrics getFontMetrics() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return FontMetrics.swing_new(handle.getFontMetrics());
+}
+
+/**
+ * Returns the receiver's foreground color.
+ *
+ * @return the color used for drawing foreground things
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Color getForeground() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return Color.swing_new(data.device, handle.getColor());
+}
+
+/**
+ * Returns the foreground pattern. The default value is
+ * null.
+ *
+ * @return the receiver's foreground pattern
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ * IMPORTANT: This method is not part of the public
+ * API for GC. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see GCData
+ *
+ * @since 3.2
+ */
+public GCData getGCData() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data;
+}
+
+/**
+ * Returns the receiver's interpolation setting, which will be one of
+ * SWT.DEFAULT, SWT.NONE,
+ * SWT.LOW or SWT.HIGH.
+ *
+ * @return the receiver's interpolation setting
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public int getInterpolation() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ Utils.notImplemented(); return SWT.DEFAULT;
+// if (data.gdipGraphics == 0) return SWT.DEFAULT;
+// int mode = Gdip.Graphics_GetInterpolationMode(data.gdipGraphics);
+// switch (mode) {
+// case Gdip.InterpolationModeDefault: return SWT.DEFAULT;
+// case Gdip.InterpolationModeNearestNeighbor: return SWT.NONE;
+// case Gdip.InterpolationModeBilinear:
+// case Gdip.InterpolationModeLowQuality: return SWT.LOW;
+// case Gdip.InterpolationModeBicubic:
+// case Gdip.InterpolationModeHighQualityBilinear:
+// case Gdip.InterpolationModeHighQualityBicubic:
+// case Gdip.InterpolationModeHighQuality: return SWT.HIGH;
+// }
+// return SWT.DEFAULT;
+}
+
+/**
+ * Returns the receiver's line cap style, which will be one
+ * of the constants SWT.CAP_FLAT, SWT.CAP_ROUND,
+ * or SWT.CAP_SQUARE.
+ *
+ * @return the cap style used for drawing lines
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public int getLineCap() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch(getCurrentBasicStroke().getEndCap()) {
+ case BasicStroke.CAP_ROUND:
+ return SWT.CAP_ROUND;
+ case BasicStroke.CAP_SQUARE:
+ return SWT.CAP_SQUARE;
+ }
+ return SWT.CAP_FLAT;
+}
+
+/**
+ * Returns the receiver's line dash style. The default value is
+ * null.
+ *
+ * @return the line dash style used for drawing lines
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public int getLineJoin() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch(getCurrentBasicStroke().getLineJoin()) {
+ case BasicStroke.JOIN_BEVEL:
+ return SWT.JOIN_BEVEL;
+ case BasicStroke.JOIN_ROUND:
+ return SWT.JOIN_ROUND;
+ }
+ return SWT.JOIN_MITER;
+}
+
+/**
+ * Returns the receiver's line style, which will be one
+ * of the constants SWT.LINE_SOLID, SWT.LINE_DASH,
+ * SWT.LINE_DOT, SWT.LINE_DASHDOT or
+ * SWT.LINE_DASHDOTDOT.
+ *
+ * @return the style used for drawing lines
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getLineStyle() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ float[] dashArray = getCurrentBasicStroke().getDashArray();
+ if(dashArray == null) {
+ return SWT.LINE_SOLID;
+ } else if(dashArray == lineDashArray) {
+ return SWT.LINE_DASH;
+ } else if(dashArray == lineDotArray) {
+ return SWT.LINE_DOT;
+ } else if(dashArray == lineDashDotArray) {
+ return SWT.LINE_DASHDOT;
+ } else if(dashArray == lineDashDotDotArray) {
+ return SWT.LINE_DASHDOTDOT;
+ } else if(dashArray != null && dashArray == data.dashes) {
+ return SWT.LINE_CUSTOM;
+ }
+ return SWT.LINE_SOLID;
+//
+// int style, size;
+// int hPen = OS.GetCurrentObject(handle, OS.OBJ_PEN);
+// if ((size = OS.GetObject(hPen, 0, (LOGPEN)null)) == LOGPEN.sizeof) {
+// LOGPEN logPen = new LOGPEN();
+// OS.GetObject(hPen, LOGPEN.sizeof, logPen);
+// style = logPen.lopnStyle;
+// } else {
+// EXTLOGPEN logPen = new EXTLOGPEN();
+// if (size <= EXTLOGPEN.sizeof) {
+// OS.GetObject(hPen, size, logPen);
+// } else {
+// int hHeap = OS.GetProcessHeap();
+// int ptr = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, size);
+// OS.GetObject(hPen, size, ptr);
+// OS.MoveMemory(logPen, ptr, EXTLOGPEN.sizeof);
+// OS.HeapFree(hHeap, 0, ptr);
+// }
+// style = logPen.elpPenStyle & OS.PS_STYLE_MASK;
+// }
+// switch (style) {
+// case OS.PS_SOLID: return SWT.LINE_SOLID;
+// case OS.PS_DASH: return SWT.LINE_DASH;
+// case OS.PS_DOT: return SWT.LINE_DOT;
+// case OS.PS_DASHDOT: return SWT.LINE_DASHDOT;
+// case OS.PS_DASHDOTDOT: return SWT.LINE_DASHDOTDOT;
+// case OS.PS_USERSTYLE: return SWT.LINE_CUSTOM;
+// default: return SWT.LINE_SOLID;
+// }
+}
+
+/**
+ * Returns the width that will be used when drawing lines
+ * for all of the figure drawing operations (that is,
+ * drawLine, drawRectangle,
+ * drawPolyline, and so forth.
+ *
+ * @return the receiver's line width
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getLineWidth() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return (int)getCurrentBasicStroke().getLineWidth();
+}
+
+/**
+ * Returns the receiver's style information.
+ *
+ * Note that the value which is returned by this method may
+ * not match the value which was provided to the constructor
+ * when the receiver was created. This can occur when the underlying
+ * operating system does not support a particular combination of
+ * requested styles.
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 2.1.2
+ */
+public int getStyle () {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.style;
+}
+
+/**
+ * Returns the receiver's text drawing anti-aliasing setting value,
+ * which will be one of SWT.DEFAULT, SWT.OFF or
+ * SWT.ON. Note that this controls anti-aliasing
+ * only for text drawing operations.
+ *
+ * @return the anti-aliasing setting
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getAntialias
+ *
+ * @since 3.1
+ */
+public int getTextAntialias() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ Object value = handle.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING);
+ if(value == RenderingHints.VALUE_TEXT_ANTIALIAS_OFF) return SWT.OFF;
+ if(value == RenderingHints.VALUE_TEXT_ANTIALIAS_ON) return SWT.ON;
+ return SWT.DEFAULT;
+}
+
+/**
+ * Sets the parameter to the transform that is currently being
+ * used by the receiver.
+ *
+ * @param transform the destination to copy the transform into
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parameter is null
+ *
ERROR_INVALID_ARGUMENT - if the parameter has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Transform
+ *
+ * @since 3.1
+ */
+public void getTransform(Transform transform) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (transform == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if(gcAT == null) {
+ transform.handle = new AffineTransform();
+ } else {
+ transform.handle = new AffineTransform(gcAT);
+ }
+}
+
+boolean isXORMode = false;
+
+/**
+ * Returns true if this GC is drawing in the mode
+ * where the resulting color in the destination is the
+ * exclusive or of the color values in the source
+ * and the destination, and false if it is
+ * drawing in the mode where the destination color is being
+ * replaced with the source color value.
+ *
+ * @return true true if the receiver is in XOR mode, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public boolean getXORMode() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ // TODO: Not a solution because if swing is used directly in future implementation, this does not detect.
+ return isXORMode;
+// int rop2 = 0;
+// if (OS.IsWinCE) {
+// rop2 = OS.SetROP2 (handle, OS.R2_COPYPEN);
+// OS.SetROP2 (handle, rop2);
+// } else {
+// rop2 = OS.GetROP2(handle);
+// }
+// return rop2 == OS.R2_XORPEN;
+}
+
+//void initGdip(boolean draw, boolean fill) {
+// data.device.checkGDIP();
+// int gdipGraphics = data.gdipGraphics;
+// if (gdipGraphics == 0) gdipGraphics = data.gdipGraphics = Gdip.Graphics_new(handle);
+// if (gdipGraphics == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// if (draw && data.gdipPen == 0) data.gdipPen = createGdipPen();
+// if (fill && data.gdipBrush == 0) data.gdipBrush = createGdipBrush();
+//}
+
+void init(Drawable drawable, GCData data, CGC handle) {
+ if(data.foreground != null) {
+ handle.setColor(data.foreground);
+ }
+ if(data.background != null) {
+ handle.setBackground(data.background);
+ }
+ if(data.hFont != null) {
+ handle.setFont(data.hFont);
+ }
+// int foreground = data.foreground;
+// if (foreground != -1 && OS.GetTextColor(hDC) != foreground) {
+// OS.SetTextColor(hDC, foreground);
+// int newPen = OS.CreatePen(OS.PS_SOLID, 0, foreground);
+// OS.SelectObject(hDC, newPen);
+// if (data.hPen != 0) OS.DeleteObject(data.hPen);
+// data.hPen = newPen;
+// }
+// int background = data.background;
+// if (background != -1 && OS.GetBkColor(hDC) != background) {
+// OS.SetBkColor(hDC, background);
+// int newBrush = OS.CreateSolidBrush(background);
+// OS.SelectObject(hDC, newBrush);
+// if (data.hBrush != 0) OS.DeleteObject (data.hBrush);
+// data.hBrush = newBrush;
+// }
+// int hFont = data.hFont;
+// if (hFont != 0) OS.SelectObject (hDC, hFont);
+// int hPalette = data.device.hPalette;
+// if (hPalette != 0) {
+// OS.SelectPalette(hDC, hPalette, true);
+// OS.RealizePalette(hDC);
+// }
+// Image image = data.image;
+// if (image != null) {
+// data.hNullBitmap = OS.SelectObject(hDC, image.handle);
+// image.memGC = this;
+// }
+// int layout = data.layout;
+// if (layout != -1) {
+// if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+// int flags = OS.GetLayout(hDC);
+// if ((flags & OS.LAYOUT_RTL) != (layout & OS.LAYOUT_RTL)) {
+// flags &= ~OS.LAYOUT_RTL;
+// OS.SetLayout(hDC, flags | layout);
+// }
+// if ((data.style & SWT.RIGHT_TO_LEFT) != 0) data.style |= SWT.MIRRORED;
+// }
+// }
+ this.drawable = drawable;
+ this.data = data;
+ this.handle = handle;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true when passed to
+ * equals must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle == null? 0: handle.hashCode();
+}
+
+/**
+ * Returns true if the receiver has a clipping
+ * region set into it, and false otherwise.
+ * If this method returns false, the receiver will draw on all
+ * available space in the destination. If it returns true,
+ * it will draw only in the area that is covered by the region
+ * that can be accessed with getClipping(region).
+ *
+ * @return true if the GC has a clipping region, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public boolean isClipped() {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return handle.getUserClip() != null;
+}
+
+/**
+ * Returns true if the GC has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the GC.
+ * When a GC has been disposed, it is an error to
+ * invoke any other method using the GC.
+ *
+ * @return true when the GC is disposed and false otherwise
+ */
+public boolean isDisposed() {
+ return handle == null;
+}
+
+//boolean isIdentity(float[] xform) {
+// return xform[0] == 1 && xform[1] == 0 && xform[2] == 0 &&
+// xform[3] == 1 && xform[4] == 0 && xform[5] == 0;
+//}
+
+/**
+ * Sets the receiver to always use the operating system's advanced graphics
+ * subsystem for all graphics operations if the argument is true.
+ * If the argument is false, the advanced graphics subsystem is
+ * no longer used, advanced graphics state is cleared and the normal graphics
+ * subsystem is used from now on.
+ *
+ * Normally, the advanced graphics subsystem is invoked automatically when
+ * any one of the alpha, antialias, patterns, interpolation, paths, clipping
+ * or transformation operations in the receiver is requested. When the receiver
+ * is switched into advanced mode, the advanced graphics subsystem performs both
+ * advanced and normal graphics operations. Because the two subsystems are
+ * different, their output may differ. Switching to advanced graphics before
+ * any graphics operations are performed ensures that the output is consistent.
+ *
+ *
+ * Advanced graphics may not be installed for the operating system. In this
+ * case, this operation does nothing. Some operating system have only one
+ * graphics subsystem, so switching from normal to advanced graphics does
+ * nothing. However, switching from advanced to normal graphics will always
+ * clear the advanced graphics state, even for operating systems that have
+ * only one graphics subsystem.
+ *
+ *
+ * @param advanced the new advanced graphics state
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #setAlpha
+ * @see #setAntialias
+ * @see #setBackgroundPattern
+ * @see #setClipping(Path)
+ * @see #setForegroundPattern
+ * @see #setInterpolation
+ * @see #setTextAntialias
+ * @see #setTransform
+ * @see #getAdvanced
+ *
+ * @since 3.1
+ */
+public void setAdvanced(boolean advanced) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ data.advanced = advanced;
+}
+
+/**
+ * Sets the receiver's anti-aliasing value to the parameter,
+ * which must be one of SWT.DEFAULT, SWT.OFF
+ * or SWT.ON. Note that this controls anti-aliasing for all
+ * non-text drawing operations.
+ *
+ * @param antialias the anti-aliasing setting
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the parameter is not one of SWT.DEFAULT,
+ * SWT.OFF or SWT.ON
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void setAlpha(int alpha) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ data.alpha = alpha & 0xFF;
+ AlphaComposite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, data.alpha / 255.0f);
+ handle.setComposite(comp);
+}
+
+/**
+ * Sets the background color. The background color is used
+ * for fill operations and as the background color when text
+ * is drawn.
+ *
+ * @param color the new background color for the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the color is null
+ *
ERROR_INVALID_ARGUMENT - if the color has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setBackground (Color color) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ data.background = color.handle;
+ handle.setBackground(color.handle);
+// if (OS.GetBkColor(handle) == color.handle) return;
+// data.background = color.handle;
+// OS.SetBkColor (handle, color.handle);
+// int newBrush = OS.CreateSolidBrush (color.handle);
+// OS.SelectObject (handle, newBrush);
+// if (data.hBrush != 0) OS.DeleteObject (data.hBrush);
+// data.hBrush = newBrush;
+// if (data.gdipBrush != 0) {
+// Gdip.SolidBrush_delete(data.gdipBrush);
+// data.gdipBrush = 0;
+// }
+}
+
+/**
+ * Sets the background pattern. The default value is null.
+ *
+ * @param pattern the new background pattern
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the parameter has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Pattern
+ *
+ * @since 3.1
+ */
+public void setBackgroundPattern (Pattern pattern) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pattern != null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ Utils.notImplemented();
+// if (data.gdipGraphics == 0 && pattern == null) return;
+// initGdip(false, false);
+// if (data.gdipBrush != 0) destroyGdipBrush(data.gdipBrush);
+// if (pattern != null) {
+// data.gdipBrush = Gdip.Brush_Clone(pattern.handle);
+// } else {
+// data.gdipBrush = 0;
+// }
+ data.backgroundPattern = pattern;
+}
+
+//void setClipping(int clipRgn) {
+// int hRgn = clipRgn;
+// int gdipGraphics = data.gdipGraphics;
+// if (hRgn != 0) {
+// boolean result;
+// float[] xform = new float[]{1, 0, 0, 1, 0, 0};
+// if (gdipGraphics != 0) {
+// int matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+// result = Gdip.Graphics_GetTransform(gdipGraphics, matrix) == 0;
+// Gdip.Matrix_GetElements(matrix, xform);
+// Gdip.Matrix_delete(matrix);
+// } else {
+// result = OS.GetWorldTransform(handle, xform);
+// }
+// if (result && !isIdentity(xform)) {
+// int count = OS.GetRegionData(hRgn, 0, null);
+// int[] lpRgnData = new int[count / 4];
+// OS.GetRegionData(hRgn, count, lpRgnData);
+// hRgn = OS.ExtCreateRegion(xform, count, lpRgnData);
+// }
+// }
+// OS.SelectClipRgn (handle, hRgn);
+// if (gdipGraphics != 0) {
+// if (hRgn != 0) {
+// Gdip.Graphics_SetClip(gdipGraphics, hRgn, Gdip.CombineModeReplace);
+// } else {
+// Gdip.Graphics_ResetClip(gdipGraphics);
+// }
+// }
+// if (hRgn != 0 && hRgn != clipRgn) {
+// OS.DeleteObject(hRgn);
+// }
+//}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the rectangular area specified
+ * by the arguments.
+ *
+ * @param x the x coordinate of the clipping rectangle
+ * @param y the y coordinate of the clipping rectangle
+ * @param width the width of the clipping rectangle
+ * @param height the height of the clipping rectangle
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setClipping (int x, int y, int width, int height) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ setClipping(new Rectangle(x, y, width, height));
+}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the path specified
+ * by the argument.
+ *
+ * @param path the clipping path.
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the path has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Path
+ *
+ * @since 3.1
+ */
+public void setClipping (Path path) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (path != null && path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle.setUserClip(path.handle);
+}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the rectangular area specified
+ * by the argument. Specifying null for the
+ * rectangle reverts the receiver's clipping area to its
+ * original value.
+ *
+ * @param rect the clipping rectangle or null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setClipping (Rectangle rect) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ java.awt.Rectangle userClip = rect == null? null: new java.awt.Rectangle(rect.x, rect.y, rect.width, rect.height);
+ handle.setUserClip(userClip);
+}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the region specified
+ * by the argument. Specifying null for the
+ * region reverts the receiver's clipping area to its
+ * original value.
+ *
+ * @param region the clipping region or null
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the region has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setClipping (Region region) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region != null && region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle.setUserClip(region.handle);
+}
+
+/**
+ * Sets the receiver's fill rule to the parameter, which must be one of
+ * SWT.FILL_EVEN_ODD or SWT.FILL_WINDING.
+ *
+ * @param rule the new fill rule
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the rule is not one of SWT.FILL_EVEN_ODD
+ * or SWT.FILL_WINDING
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void setFillRule(int rule) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch (rule) {
+ case SWT.FILL_WINDING:
+ case SWT.FILL_EVEN_ODD:
+ fillRule = rule;
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+}
+
+/**
+ * Sets the font which will be used by the receiver
+ * to draw and measure text to the argument. If the
+ * argument is null, then a default font appropriate
+ * for the platform will be used instead.
+ *
+ * @param font the new font for the receiver, or null to indicate a default font
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the font has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setFont (Font font) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (font == null) {
+ handle.setFont(LookAndFeelUtils.getSystemFont());
+ } else {
+ if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle.setFont(font.handle);
+ }
+}
+
+/**
+ * Sets the foreground color. The foreground color is used
+ * for drawing operations including when text is drawn.
+ *
+ * @param color the new foreground color for the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the color is null
+ *
ERROR_INVALID_ARGUMENT - if the color has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setForeground (Color color) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ data.foreground = color.handle;
+ handle.setColor(color.handle);
+}
+
+/**
+ * Sets the foreground pattern. The default value is null.
+ *
+ * @param pattern the new foreground pattern
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the parameter has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Pattern
+ *
+ * @since 3.1
+ */
+public void setForegroundPattern (Pattern pattern) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pattern != null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ Utils.notImplemented();
+// if (data.gdipGraphics == 0 && pattern == null) return;
+// initGdip(false, false);
+// if (pattern != null) {
+// if (data.gdipPen != 0) Gdip.Pen_SetBrush(data.gdipPen, pattern.handle);
+// } else {
+// if (data.gdipPen != 0) {
+// Gdip.Pen_delete(data.gdipPen);
+// data.gdipPen = 0;
+// }
+// }
+ data.foregroundPattern = pattern;
+}
+
+/**
+ * Sets the receiver's interpolation setting to the parameter, which
+ * must be one of SWT.DEFAULT, SWT.NONE,
+ * SWT.LOW or SWT.HIGH.
+ *
+ * @param interpolation the new interpolation setting
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the rule is not one of SWT.DEFAULT,
+ * SWT.NONE, SWT.LOW or SWT.HIGH
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void setInterpolation(int interpolation) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ Utils.notImplemented();
+// if (data.gdipGraphics == 0 && interpolation == SWT.DEFAULT) return;
+// int mode = 0;
+// switch (interpolation) {
+// case SWT.DEFAULT: mode = Gdip.InterpolationModeDefault; break;
+// case SWT.NONE: mode = Gdip.InterpolationModeNearestNeighbor; break;
+// case SWT.LOW: mode = Gdip.InterpolationModeLowQuality; break;
+// case SWT.HIGH: mode = Gdip.InterpolationModeHighQuality; break;
+// default:
+// SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// }
+// initGdip(false, false);
+// Gdip.Graphics_SetInterpolationMode(data.gdipGraphics, mode);
+}
+
+/**
+ * Sets the receiver's line cap style to the argument, which must be one
+ * of the constants SWT.CAP_FLAT, SWT.CAP_ROUND,
+ * or SWT.CAP_SQUARE.
+ *
+ * @param cap the cap style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the style is not valid
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void setLineCap(int cap) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ BasicStroke stroke = getCurrentBasicStroke();
+ int capStyle = 0;
+ switch (cap) {
+ case SWT.CAP_ROUND:
+ capStyle = BasicStroke.CAP_ROUND;
+ break;
+ case SWT.CAP_FLAT:
+ capStyle = BasicStroke.CAP_BUTT;
+ break;
+ case SWT.CAP_SQUARE:
+ capStyle = BasicStroke.CAP_SQUARE;
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ handle.setStroke(new BasicStroke(stroke.getLineWidth(), capStyle, stroke.getLineJoin(), stroke.getMiterLimit(), stroke.getDashArray(), 0));
+}
+
+/**
+ * Sets the receiver's line dash style to the argument. The default
+ * value is null. If the argument is not null,
+ * the receiver's line style is set to SWT.LINE_CUSTOM, otherwise
+ * it is set to SWT.LINE_SOLID.
+ *
+ * @param dashes the dash style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if any of the values in the array is less than or equal 0
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void setLineDash(int[] dashes) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ BasicStroke stroke = getCurrentBasicStroke();
+ if(dashes == null) dashes = new int[0];
+ data.dashes = new float[dashes.length];
+ for(int i=0; iSWT.JOIN_MITER, SWT.JOIN_ROUND,
+ * or SWT.JOIN_BEVEL.
+ *
+ * @param join the join style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the style is not valid
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void setLineJoin(int join) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ BasicStroke stroke = getCurrentBasicStroke();
+ int joinStyle = 0;
+ switch (join) {
+ case SWT.JOIN_MITER:
+ joinStyle = BasicStroke.JOIN_MITER;
+ break;
+ case SWT.JOIN_ROUND:
+ joinStyle = BasicStroke.JOIN_ROUND;
+ break;
+ case SWT.JOIN_BEVEL:
+ joinStyle = BasicStroke.JOIN_BEVEL;
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ handle.setStroke(new BasicStroke(stroke.getLineWidth(), stroke.getEndCap(), joinStyle, stroke.getMiterLimit(), stroke.getDashArray(), 0));
+}
+
+/**
+ * Sets the receiver's line style to the argument, which must be one
+ * of the constants SWT.LINE_SOLID, SWT.LINE_DASH,
+ * SWT.LINE_DOT, SWT.LINE_DASHDOT or
+ * SWT.LINE_DASHDOTDOT.
+ *
+ * @param lineStyle the style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the style is not valid
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setLineStyle(int lineStyle) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ BasicStroke stroke = getCurrentBasicStroke();
+ float[] array = null;
+ switch(lineStyle) {
+ case SWT.LINE_SOLID:
+ break;
+ case SWT.LINE_DASH:
+ array = lineDashArray;
+ break;
+ case SWT.LINE_DOT:
+ array = lineDotArray;
+ break;
+ case SWT.LINE_DASHDOT:
+ array = lineDashDotArray;
+ break;
+ case SWT.LINE_DASHDOTDOT:
+ array = lineDashDotDotArray;
+ break;
+ case SWT.LINE_CUSTOM:
+ array = data.dashes;
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ handle.setStroke(new BasicStroke(stroke.getLineWidth(), stroke.getEndCap(), stroke.getLineJoin(), stroke.getMiterLimit(), array, 0));
+}
+
+/**
+ * Sets the width that will be used when drawing lines
+ * for all of the figure drawing operations (that is,
+ * drawLine, drawRectangle,
+ * drawPolyline, and so forth.
+ *
+ * Note that line width of zero is used as a hint to
+ * indicate that the fastest possible line drawing
+ * algorithms should be used. This means that the
+ * output may be different from line width one.
+ *
+ *
+ * @param lineWidth the width of a line
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setLineWidth(int lineWidth) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ BasicStroke stroke = getCurrentBasicStroke();
+ handle.setStroke(new BasicStroke(lineWidth, stroke.getEndCap(), stroke.getLineJoin(), stroke.getMiterLimit(), stroke.getDashArray(), stroke.getDashPhase()));
+}
+
+//void setPen(int newColor, int newWidth, int lineStyle, int capStyle, int joinStyle, int[] dashes) {
+// boolean extPen = false, changed = false;
+// int style, color, width, size, hPen = OS.GetCurrentObject(handle, OS.OBJ_PEN);
+// if ((size = OS.GetObject(hPen, 0, (LOGPEN)null)) == LOGPEN.sizeof) {
+// LOGPEN logPen = new LOGPEN();
+// OS.GetObject(hPen, LOGPEN.sizeof, logPen);
+// color = logPen.lopnColor;
+// width = logPen.x;
+// style = logPen.lopnStyle;
+// /*
+// * Feature in Windows. The default end caps is PS_ENDCAP_ROUND
+// * and the default line join is PS_JOIN_ROUND which are different
+// * from other platforms. The fix is to change these values when
+// * line width is widened.
+// */
+// if (width <= 1 && (newWidth > 1 || lineStyle == OS.PS_USERSTYLE)) {
+// if (capStyle == -1) capStyle = OS.PS_ENDCAP_FLAT;
+// if (joinStyle == -1) joinStyle = OS.PS_JOIN_MITER;
+// }
+// } else {
+// EXTLOGPEN logPen = new EXTLOGPEN();
+// if (size <= EXTLOGPEN.sizeof) {
+// OS.GetObject(hPen, size, logPen);
+// } else {
+// int hHeap = OS.GetProcessHeap();
+// int ptr = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, size);
+// OS.GetObject(hPen, size, ptr);
+// OS.MoveMemory(logPen, ptr, EXTLOGPEN.sizeof);
+// OS.HeapFree(hHeap, 0, ptr);
+// }
+// color = logPen.elpColor;
+// width = logPen.elpWidth;
+// style = logPen.elpPenStyle;
+// extPen = true;
+// if (newWidth == 0 || newWidth == 1) {
+// if (dashes == null && (style & OS.PS_ENDCAP_MASK) == OS.PS_ENDCAP_FLAT && (style & OS.PS_JOIN_MASK) == OS.PS_JOIN_MITER) {
+// style &= ~(OS.PS_ENDCAP_MASK | OS.PS_JOIN_MASK | OS.PS_TYPE_MASK);
+// extPen = false;
+// }
+// }
+// }
+// if (newColor != -1) {
+// if (newColor != color) {
+// color = newColor;
+// changed = true;
+// }
+// }
+// if (newWidth != -1) {
+// if (newWidth != width) {
+// width = newWidth;
+// changed = true;
+// }
+// }
+// if (lineStyle != -1) {
+// if ((style & OS.PS_STYLE_MASK) != lineStyle || (style & OS.PS_STYLE_MASK) == OS.PS_USERSTYLE) {
+// style = (style & ~OS.PS_STYLE_MASK) | lineStyle;
+// changed = true;
+// }
+// }
+// if (capStyle != -1) {
+// if ((style & OS.PS_ENDCAP_MASK) != capStyle) {
+// style = (style & ~OS.PS_ENDCAP_MASK) | capStyle;
+// changed = true;
+// }
+// }
+// if (joinStyle != -1) {
+// if ((style & OS.PS_JOIN_MASK) != joinStyle) {
+// style = (style & ~OS.PS_JOIN_MASK) | joinStyle;
+// changed = true;
+// }
+// }
+// if (!changed) return;
+// if ((style & OS.PS_STYLE_MASK) != OS.PS_USERSTYLE) dashes = null;
+// /*
+// * Feature in Windows. Windows does not honour line styles other then
+// * PS_SOLID for pens wider than 1 pixel created with CreatePen(). The fix
+// * is to use ExtCreatePen() instead.
+// */
+// int newPen;
+// if (!OS.IsWinCE && (extPen || width > 1 || (style & OS.PS_STYLE_MASK) == OS.PS_USERSTYLE)) {
+// LOGBRUSH logBrush = new LOGBRUSH();
+// logBrush.lbStyle = OS.BS_SOLID;
+// logBrush.lbColor = color;
+// /* Feature in Windows. PS_GEOMETRIC pens cannot have zero width. */
+// newPen = OS.ExtCreatePen (style | OS.PS_GEOMETRIC, Math.max(1, width), logBrush, dashes != null ? dashes.length : 0, dashes);
+// } else {
+// newPen = OS.CreatePen(style, width, color);
+// }
+// OS.SelectObject(handle, newPen);
+// if (data.hPen != 0) OS.DeleteObject(data.hPen);
+// data.hPen = newPen;
+// data.lineWidth = width;
+// if (data.gdipPen != 0) {
+// Gdip.Pen_delete(data.gdipPen);
+// data.gdipPen = 0;
+// }
+//}
+
+/**
+ * If the argument is true, puts the receiver
+ * in a drawing mode where the resulting color in the destination
+ * is the exclusive or of the color values in the source
+ * and the destination, and if the argument is false,
+ * puts the receiver in a drawing mode where the destination color
+ * is replaced with the source color value.
+ *
+ * Note that this mode in fundamentally unsupportable on certain
+ * platforms, notably Carbon (Mac OS X). Clients that want their
+ * code to run on all platforms need to avoid this method.
+ *
+ *
+ * @param xor if true, then xor mode is used, otherwise source copy mode is used
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @deprecated this functionality is not supported on some platforms
+ */
+public void setXORMode(boolean xor) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if(xor) {
+ // need to check if "handle.setXORMode(getBackground().handle)" must be called any time the background color changes.
+ handle.setXORMode(getBackground().handle);
+ } else {
+ handle.setPaintMode();
+ }
+ isXORMode = xor;
+}
+
+/**
+ * Sets the receiver's text anti-aliasing value to the parameter,
+ * which must be one of SWT.DEFAULT, SWT.OFF
+ * or SWT.ON. Note that this controls anti-aliasing only
+ * for all text drawing operations.
+ *
+ * @param antialias the anti-aliasing setting
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the parameter is not one of SWT.DEFAULT,
+ * SWT.OFF or SWT.ON
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #setAntialias
+ *
+ * @since 3.1
+ */
+public void setTextAntialias(int antialias) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch (antialias) {
+ case SWT.DEFAULT:
+ handle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
+ break;
+ case SWT.OFF:
+ handle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+ break;
+ case SWT.ON:
+ handle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+}
+
+/**
+ * Sets the transform that is currently being used by the receiver. If
+ * the argument is null, the current transform is set to
+ * the identity transform.
+ *
+ * @param transform the transform to set
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the parameter has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Transform
+ *
+ * @since 3.1
+ */
+public void setTransform(Transform transform) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (saveAT == null) {
+ saveAT = handle.getTransform();
+ } else {
+ handle.setTransform(saveAT);
+ }
+ AffineTransform at;
+ if (transform == null) {
+ at = new AffineTransform();
+ gcAT = null;
+ } else {
+ at = transform.handle;
+ gcAT = at;
+ }
+ handle.transform(at);
+}
+
+/**
+ * Returns the extent of the given string. No tab
+ * expansion or carriage return processing will be performed.
+ *
+ * The extent of a string is the width and height of
+ * the rectangular area it would cover if drawn in a particular
+ * font (in this case, the current font in the receiver).
+ *
+ *
+ * @param string the string to measure
+ * @return a point containing the extent of the string
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Point stringExtent(String string) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return textExtent(string, 0);
+// java.awt.FontMetrics fm = handle.getFontMetrics();
+// // TODO: check why the StyledText queries the stringExtent and this is null sometimes (cf RSSOwl)
+// if(fm == null) return new Point(0, 0);
+// return new Point(fm.stringWidth(string), fm.getMaxAscent() + fm.getMaxDescent());
+}
+
+/**
+ * Returns the extent of the given string. Tab expansion and
+ * carriage return processing are performed.
+ *
+ * The extent of a string is the width and height of
+ * the rectangular area it would cover if drawn in a particular
+ * font (in this case, the current font in the receiver).
+ *
+ *
+ * @param string the string to measure
+ * @return a point containing the extent of the string
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Point textExtent(String string) {
+ return textExtent(string, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
+}
+
+/**
+ * Returns the extent of the given string. Tab expansion, line
+ * delimiter and mnemonic processing are performed according to
+ * the specified flags, which can be a combination of:
+ *
+ *
DRAW_DELIMITER
+ *
draw multiple lines
+ *
DRAW_TAB
+ *
expand tabs
+ *
DRAW_MNEMONIC
+ *
underline the mnemonic character
+ *
DRAW_TRANSPARENT
+ *
transparent background
+ *
+ *
+ * The extent of a string is the width and height of
+ * the rectangular area it would cover if drawn in a particular
+ * font (in this case, the current font in the receiver).
+ *
+ *
+ * @param string the string to measure
+ * @param flags the flags specifing how to process the text
+ * @return a point containing the extent of the string
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Point textExtent(String string, int flags) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if((flags & SWT.DRAW_TAB) != 0) {
+ string = string.replaceAll("\t", " ");
+ }
+ int mnemonicIndex = -1;
+ if((flags & SWT.DRAW_MNEMONIC) != 0) {
+ // Copied from Label
+ mnemonicIndex = findMnemonicIndex(string);
+ if(mnemonicIndex > 0) {
+ String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&");
+ string = s + string.substring(mnemonicIndex).replaceAll("&&", "&");
+ mnemonicIndex -= mnemonicIndex - 1 - s.length();
+ mnemonicIndex--;
+ } else {
+ string = string.replaceAll("&&", "&");
+ }
+ }
+ String[] tokens;
+ if((flags & SWT.DRAW_DELIMITER) != 0) {
+ tokens = string.split("\n");
+ } else {
+ tokens = new String[] {string};
+ }
+// boolean isTransparent = (flags & SWT.DRAW_TRANSPARENT) != 0;
+ java.awt.FontMetrics fm = handle.getFontMetrics();
+ int fmHeight = fm.getHeight();
+ int currentHeight = fmHeight;
+ int maxWidth = 0;
+ int maxHeight = 0;
+ FontRenderContext fontRenderContext = handle.getFontRenderContext();
+ java.awt.Font font = handle.getFont();
+ for(int i=0; i
+ * IMPORTANT: This method is not part of the public
+ * API for GC. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param drawable the Drawable for the receiver.
+ * @param data the data for the receiver.
+ *
+ * @return a new GC
+ */
+public static GC swing_new(Drawable drawable, GCData data) {
+ GC gc = new GC();
+ CGC handle = drawable.internal_new_GC(data);
+ gc.init(drawable, data, handle);
+ return gc;
+}
+
+/**
+ * Invokes platform specific functionality to wrap a graphics context.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for GC. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param hDC the Windows HDC.
+ * @param data the data for the receiver.
+ *
+ * @return a new GC
+ */
+public static GC swing_new(CGC handle, GCData data) {
+ GC gc = new GC();
+ gc.init(null, data, handle);
+ return gc;
+}
+
+static final float[] lineDashArray = new float[] {18, 6};
+static final float[] lineDotArray = new float[] {3, 3};
+static final float[] lineDashDotArray = new float[] {9, 6, 3, 6};
+static final float[] lineDashDotDotArray = new float[] {9, 3, 3, 3, 3, 3};
+
+BasicStroke getCurrentBasicStroke() {
+ Stroke stroke = handle.getStroke();
+ if(stroke instanceof BasicStroke) {
+ return (BasicStroke)stroke;
+ }
+ return new BasicStroke();
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GCData.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GCData.java
new file mode 100644
index 00000000000..eeba6b8adfb
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/GCData.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.awt.Component;
+
+/**
+ * Instances of this class are descriptions of GCs in terms
+ * of unallocated platform-specific data fields.
+ *
+ * IMPORTANT: This class is not part of the public
+ * API for SWT. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms, and should never be called from application code.
+ *
+ */
+
+public final class GCData {
+ public Device device;
+ public int style;
+ public Image image;
+ public java.awt.Color foreground = java.awt.Color.BLACK;
+ public java.awt.Color background = java.awt.Color.BLACK;
+ public int hPen;
+ public int lineWidth;
+ public float[] dashes;
+ public int hBrush;
+ public java.awt.Font hFont;
+ public int hNullBitmap;
+ public Component hwnd;
+ public boolean layout = true;
+ public int alpha = 0xFF;
+ public boolean advanced;
+// public int gdipGraphics;
+ public int gdipPen;
+ public int gdipBrush;
+ public Pattern foregroundPattern;
+ public Pattern backgroundPattern;
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Image.java
new file mode 100644
index 00000000000..cc234a7aa8e
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Image.java
@@ -0,0 +1,1867 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.awt.*;
+import java.awt.image.*;
+import java.io.*;
+
+import javax.swing.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.DPIUtil.*;
+import org.eclipse.swt.internal.swing.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * Instances of this class are graphics which have been prepared
+ * for display on a specific device. That is, they are ready
+ * to paint using methods such as GC.drawImage()
+ * and display on widgets with, for example, Button.setImage().
+ *
+ * If loaded from a file format that supports it, an
+ * Image may have transparency, meaning that certain
+ * pixels are specified as being transparent when drawn. Examples
+ * of file formats that support transparency are GIF and PNG.
+ *
+ * There are two primary ways to use Images.
+ * The first is to load a graphic file from disk and create an
+ * Image from it. This is done using an Image
+ * constructor, for example:
+ *
+ * Image i = new Image(device, "C:\\graphic.bmp");
+ *
+ * A graphic file may contain a color table specifying which
+ * colors the image was intended to possess. In the above example,
+ * these colors will be mapped to the closest available color in
+ * SWT. It is possible to get more control over the mapping of
+ * colors as the image is being created, using code of the form:
+ *
+ * ImageData data = new ImageData("C:\\graphic.bmp");
+ * RGB[] rgbs = data.getRGBs();
+ * // At this point, rgbs contains specifications of all
+ * // the colors contained within this image. You may
+ * // allocate as many of these colors as you wish by
+ * // using the Color constructor Color(RGB), then
+ * // create the image:
+ * Image i = new Image(device, data);
+ *
+ *
+ * Applications which require even greater control over the image
+ * loading process should use the support provided in class
+ * ImageLoader.
+ *
+ * Application code must explicitly invoke the Image.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ *
+ * @see Color
+ * @see ImageData
+ * @see ImageLoader
+ */
+
+public final class Image extends Resource implements Drawable {
+
+ /**
+ * specifies whether the receiver is a bitmap or an icon
+ * (one of SWT.BITMAP, SWT.ICON)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public int type;
+
+ /**
+ * the handle to the OS image resource
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public BufferedImage handle;
+
+// /**
+// * specifies the transparent pixel
+// */
+// int transparentPixel = -1;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Image () {
+}
+
+/**
+ * Constructs an empty instance of this class with the
+ * specified width and height. The result may be drawn upon
+ * by creating a GC and using any of its drawing operations,
+ * as shown in the following example:
+ *
+ * Image i = new Image(device, width, height);
+ * GC gc = new GC(i);
+ * gc.drawRectangle(0, 0, 50, 50);
+ * gc.dispose();
+ *
+ *
+ * Note: Some platforms may have a limitation on the size
+ * of image that can be created (size depends on width, height,
+ * and depth). For example, Windows 95, 98, and ME do not allow
+ * images larger than 16M.
+ *
+ *
+ * @param device the device on which to create the image
+ * @param width the width of the new image
+ * @param height the height of the new image
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_INVALID_ARGUMENT - if either the width or height is negative or zero
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for image creation
+ *
+ */
+public Image(Device device, int width, int height) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, width, height);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new instance of this class based on the
+ * provided image, with an appearance that varies depending
+ * on the value of the flag. The possible flag values are:
+ *
+ *
IMAGE_COPY
+ *
the result is an identical copy of srcImage
+ *
IMAGE_DISABLE
+ *
the result is a copy of srcImage which has a disabled look
+ *
IMAGE_GRAY
+ *
the result is a copy of srcImage which has a gray scale look
+ *
+ *
+ * @param device the device on which to create the image
+ * @param srcImage the image to use as the source
+ * @param flag the style, either IMAGE_COPY, IMAGE_DISABLE or IMAGE_GRAY
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if srcImage is null
+ *
ERROR_INVALID_ARGUMENT - if the flag is not one of IMAGE_COPY, IMAGE_DISABLE or IMAGE_GRAY
+ *
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon, or is otherwise in an invalid state
+ *
ERROR_UNSUPPORTED_DEPTH - if the depth of the image is not supported
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for image creation
+ *
+ */
+public Image(Device device, Image srcImage, int flag) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ if (srcImage == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (srcImage.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ switch (flag) {
+ case SWT.IMAGE_COPY: {
+ handle = new BufferedImage(srcImage.handle.getWidth(), srcImage.handle.getHeight(), BufferedImage.TYPE_INT_ARGB);
+ Graphics g = handle.getGraphics();
+ g.drawImage(srcImage.handle, 0, 0, null);
+ g.dispose();
+ if (device.tracking) device.new_Object(this);
+ return;
+ }
+ case SWT.IMAGE_DISABLE:
+ case SWT.IMAGE_GRAY: {
+ // TODO: test the method below and see if results are different. If so, associate each method to a different case.
+// ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
+// ColorConvertOp op = new ColorConvertOp(cs, null);
+// bufferedImage = op.filter(bufferedImage, null);
+ // ImageIcon is used to ensure that the image is loaded
+ java.awt.Image image = new ImageIcon(GrayFilter.createDisabledImage(srcImage.handle)).getImage();
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice gs = ge.getDefaultScreenDevice();
+ GraphicsConfiguration gc = gs.getDefaultConfiguration();
+ handle = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), srcImage.handle.getColorModel().getTransparency());
+ Graphics g = handle.createGraphics();
+ g.drawImage(image, 0, 0, null);
+ g.dispose();
+// init (device, newData);
+ if (device.tracking) device.new_Object(this);
+ return;
+ }
+ default:
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ // TODO: Set image data?
+}
+
+/**
+ * Constructs an empty instance of this class with the
+ * width and height of the specified rectangle. The result
+ * may be drawn upon by creating a GC and using any of its
+ * drawing operations, as shown in the following example:
+ *
+ * Image i = new Image(device, boundsRectangle);
+ * GC gc = new GC(i);
+ * gc.drawRectangle(0, 0, 50, 50);
+ * gc.dispose();
+ *
+ *
+ * Note: Some platforms may have a limitation on the size
+ * of image that can be created (size depends on width, height,
+ * and depth). For example, Windows 95, 98, and ME do not allow
+ * images larger than 16M.
+ *
+ *
+ * @param device the device on which to create the image
+ * @param bounds a rectangle specifying the image's width and height (must not be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if the bounds rectangle is null
+ *
ERROR_INVALID_ARGUMENT - if either the rectangle's width or height is negative
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for image creation
+ *
+ */
+public Image(Device device, Rectangle bounds) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, bounds.width, bounds.height);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs an instance of this class from the given
+ * ImageData.
+ *
+ * @param device the device on which to create the image
+ * @param data the image data to create the image from (must not be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if the image data is null
+ *
+ * @exception SWTException
+ *
ERROR_UNSUPPORTED_DEPTH - if the depth of the ImageData is not supported
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for image creation
+ *
+ */
+public Image(Device device, ImageData data) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, data);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs an instance of this class, whose type is
+ * SWT.ICON, from the two given ImageData
+ * objects. The two images must be the same size. Pixel transparency
+ * in either image will be ignored.
+ *
+ * The mask image should contain white wherever the icon is to be visible,
+ * and black wherever the icon is to be transparent. In addition,
+ * the source image should contain black wherever the icon is to be
+ * transparent.
+ *
+ *
+ * @param device the device on which to create the icon
+ * @param source the color data for the icon
+ * @param mask the mask data for the icon
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if either the source or mask is null
+ *
ERROR_INVALID_ARGUMENT - if source and mask are different sizes
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for image creation
+ *
+ */
+public Image(Device device, ImageData source, ImageData mask) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (mask == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (source.width != mask.width || source.height != mask.height) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ mask = ImageData.convertMask(mask);
+ init(device, this, source, mask);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs an instance of this class by loading its representation
+ * from the specified input stream. Throws an error if an error
+ * occurs while loading the image, or if the result is an image
+ * of an unsupported type. Application code is still responsible
+ * for closing the input stream.
+ *
+ * This constructor is provided for convenience when loading a single
+ * image only. If the stream contains multiple images, only the first
+ * one will be loaded. To load multiple images, use
+ * ImageLoader.load().
+ *
+ * This constructor may be used to load a resource as follows:
+ *
+ *
+ * @param device the device on which to create the image
+ * @param stream the input stream to load the image from
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if the stream is null
+ *
+ * @exception SWTException
+ *
ERROR_IO - if an IO error occurs while reading from the stream
+ *
ERROR_INVALID_IMAGE - if the image stream contains invalid data
+ *
ERROR_UNSUPPORTED_DEPTH - if the image stream describes an image with an unsupported depth
+ *
ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for image creation
+ *
+ */
+public Image (Device device, InputStream stream) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, new ImageData(stream));
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs an instance of this class by loading its representation
+ * from the file with the specified name. Throws an error if an error
+ * occurs while loading the image, or if the result is an image
+ * of an unsupported type.
+ *
+ * This constructor is provided for convenience when loading
+ * a single image only. If the specified file contains
+ * multiple images, only the first one will be used.
+ *
+ * @param device the device on which to create the image
+ * @param filename the name of the file to load the image from
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
ERROR_NULL_ARGUMENT - if the file name is null
+ *
+ * @exception SWTException
+ *
ERROR_IO - if an IO error occurs while reading from the file
+ *
ERROR_INVALID_IMAGE - if the image file contains invalid data
+ *
ERROR_UNSUPPORTED_DEPTH - if the image file describes an image with an unsupported depth
+ *
ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for image creation
+ *
+ */
+public Image (Device device, String filename) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, new ImageData(filename));
+ if (device.tracking) device.new_Object(this);
+}
+
+///**
+// * Create a DIB from a DDB without using GetDIBits. Note that
+// * the DDB should not be selected into a HDC.
+// */
+//int createDIBFromDDB(int hDC, int hBitmap, int width, int height) {
+//
+// /* Determine the DDB depth */
+// int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
+// int planes = OS.GetDeviceCaps (hDC, OS.PLANES);
+// int depth = bits * planes;
+//
+// /* Determine the DIB palette */
+// boolean isDirect = depth > 8;
+// RGB[] rgbs = null;
+// if (!isDirect) {
+// int numColors = 1 << depth;
+// byte[] logPalette = new byte[4 * numColors];
+// OS.GetPaletteEntries(device.hPalette, 0, numColors, logPalette);
+// rgbs = new RGB[numColors];
+// for (int i = 0; i < numColors; i++) {
+// rgbs[i] = new RGB(logPalette[i] & 0xFF, logPalette[i + 1] & 0xFF, logPalette[i + 2] & 0xFF);
+// }
+// }
+//
+// boolean useBitfields = OS.IsWinCE && (depth == 16 || depth == 32);
+// BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
+// bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+// bmiHeader.biWidth = width;
+// bmiHeader.biHeight = -height;
+// bmiHeader.biPlanes = 1;
+// bmiHeader.biBitCount = (short)depth;
+// if (useBitfields) bmiHeader.biCompression = OS.BI_BITFIELDS;
+// else bmiHeader.biCompression = OS.BI_RGB;
+// byte[] bmi;
+// if (isDirect) bmi = new byte[BITMAPINFOHEADER.sizeof + (useBitfields ? 12 : 0)];
+// else bmi = new byte[BITMAPINFOHEADER.sizeof + rgbs.length * 4];
+// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+//
+// /* Set the rgb colors into the bitmap info */
+// int offset = BITMAPINFOHEADER.sizeof;
+// if (isDirect) {
+// if (useBitfields) {
+// int redMask = 0;
+// int greenMask = 0;
+// int blueMask = 0;
+// switch (depth) {
+// case 16:
+// redMask = 0x7C00;
+// greenMask = 0x3E0;
+// blueMask = 0x1F;
+// /* little endian */
+// bmi[offset] = (byte)((redMask & 0xFF) >> 0);
+// bmi[offset + 1] = (byte)((redMask & 0xFF00) >> 8);
+// bmi[offset + 2] = (byte)((redMask & 0xFF0000) >> 16);
+// bmi[offset + 3] = (byte)((redMask & 0xFF000000) >> 24);
+// bmi[offset + 4] = (byte)((greenMask & 0xFF) >> 0);
+// bmi[offset + 5] = (byte)((greenMask & 0xFF00) >> 8);
+// bmi[offset + 6] = (byte)((greenMask & 0xFF0000) >> 16);
+// bmi[offset + 7] = (byte)((greenMask & 0xFF000000) >> 24);
+// bmi[offset + 8] = (byte)((blueMask & 0xFF) >> 0);
+// bmi[offset + 9] = (byte)((blueMask & 0xFF00) >> 8);
+// bmi[offset + 10] = (byte)((blueMask & 0xFF0000) >> 16);
+// bmi[offset + 11] = (byte)((blueMask & 0xFF000000) >> 24);
+// break;
+// case 32:
+// redMask = 0xFF00;
+// greenMask = 0xFF0000;
+// blueMask = 0xFF000000;
+// /* big endian */
+// bmi[offset] = (byte)((redMask & 0xFF000000) >> 24);
+// bmi[offset + 1] = (byte)((redMask & 0xFF0000) >> 16);
+// bmi[offset + 2] = (byte)((redMask & 0xFF00) >> 8);
+// bmi[offset + 3] = (byte)((redMask & 0xFF) >> 0);
+// bmi[offset + 4] = (byte)((greenMask & 0xFF000000) >> 24);
+// bmi[offset + 5] = (byte)((greenMask & 0xFF0000) >> 16);
+// bmi[offset + 6] = (byte)((greenMask & 0xFF00) >> 8);
+// bmi[offset + 7] = (byte)((greenMask & 0xFF) >> 0);
+// bmi[offset + 8] = (byte)((blueMask & 0xFF000000) >> 24);
+// bmi[offset + 9] = (byte)((blueMask & 0xFF0000) >> 16);
+// bmi[offset + 10] = (byte)((blueMask & 0xFF00) >> 8);
+// bmi[offset + 11] = (byte)((blueMask & 0xFF) >> 0);
+// break;
+// default:
+// SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+// }
+// }
+// } else {
+// for (int j = 0; j < rgbs.length; j++) {
+// bmi[offset] = (byte)rgbs[j].blue;
+// bmi[offset + 1] = (byte)rgbs[j].green;
+// bmi[offset + 2] = (byte)rgbs[j].red;
+// bmi[offset + 3] = 0;
+// offset += 4;
+// }
+// }
+// int[] pBits = new int[1];
+// int hDib = OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+// if (hDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+//
+// /* Bitblt DDB into DIB */
+// int hdcSource = OS.CreateCompatibleDC(hDC);
+// int hdcDest = OS.CreateCompatibleDC(hDC);
+// int hOldSrc = OS.SelectObject(hdcSource, hBitmap);
+// int hOldDest = OS.SelectObject(hdcDest, hDib);
+// OS.BitBlt(hdcDest, 0, 0, width, height, hdcSource, 0, 0, OS.SRCCOPY);
+// OS.SelectObject(hdcSource, hOldSrc);
+// OS.SelectObject(hdcDest, hOldDest);
+// OS.DeleteDC(hdcSource);
+// OS.DeleteDC(hdcDest);
+//
+// return hDib;
+//}
+
+public Image(Display display, AutoScaleImageDataProvider autoScaleImageDataProvider) {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+
+public Image(Device device, ImageDataProvider imageDataProvider) {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the image. Applications must dispose of all images which
+ * they allocate.
+ */
+@Override
+public void dispose () {
+ if (handle == null) return;
+ if (device.isDisposed()) return;
+ handle = null;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the same object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return true if the object is the same as this object and false otherwise
+ *
+ * @see #hashCode
+ */
+@Override
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Image)) return false;
+ Image image = (Image) object;
+ return device == image.device && handle == image.handle;
+}
+
+/**
+ * Returns the color to which to map the transparent pixel, or null if
+ * the receiver has no transparent pixel.
+ *
+ * There are certain uses of Images that do not support transparency
+ * (for example, setting an image into a button or label). In these cases,
+ * it may be desired to simulate transparency by using the background
+ * color of the widget to paint the transparent pixels of the image.
+ * Use this method to check which color will be used in these cases
+ * in place of transparency. This value may be set with setBackground().
+ *
+ *
+ * @return the background color of the image, or null if there is no transparency in the image
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Color getBackground() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ // TODO: see setBackground...
+ return null;
+// if (transparentPixel == -1) return null;
+//
+// /* Get the HDC for the device */
+// int hDC = device.internal_new_GC(null);
+//
+// /* Compute the background color */
+// BITMAP bm = new BITMAP();
+// OS.GetObject(handle, BITMAP.sizeof, bm);
+// int hdcMem = OS.CreateCompatibleDC(hDC);
+// int hOldObject = OS.SelectObject(hdcMem, handle);
+// int red = 0, green = 0, blue = 0;
+// if (bm.bmBitsPixel <= 8) {
+// if (OS.IsWinCE) {
+// byte[] pBits = new byte[1];
+// OS.MoveMemory(pBits, bm.bmBits, 1);
+// byte oldValue = pBits[0];
+// int mask = (0xFF << (8 - bm.bmBitsPixel)) & 0x00FF;
+// pBits[0] = (byte)((transparentPixel << (8 - bm.bmBitsPixel)) | (pBits[0] & ~mask));
+// OS.MoveMemory(bm.bmBits, pBits, 1);
+// int color = OS.GetPixel(hdcMem, 0, 0);
+// pBits[0] = oldValue;
+// OS.MoveMemory(bm.bmBits, pBits, 1);
+// blue = (color & 0xFF0000) >> 16;
+// green = (color & 0xFF00) >> 8;
+// red = color & 0xFF;
+// } else {
+// byte[] color = new byte[4];
+// OS.GetDIBColorTable(hdcMem, transparentPixel, 1, color);
+// blue = color[0] & 0xFF;
+// green = color[1] & 0xFF;
+// red = color[2] & 0xFF;
+// }
+// } else {
+// switch (bm.bmBitsPixel) {
+// case 16:
+// blue = (transparentPixel & 0x1F) << 3;
+// green = (transparentPixel & 0x3E0) >> 2;
+// red = (transparentPixel & 0x7C00) >> 7;
+// break;
+// case 24:
+// blue = (transparentPixel & 0xFF0000) >> 16;
+// green = (transparentPixel & 0xFF00) >> 8;
+// red = transparentPixel & 0xFF;
+// break;
+// case 32:
+// blue = (transparentPixel & 0xFF000000) >>> 24;
+// green = (transparentPixel & 0xFF0000) >> 16;
+// red = (transparentPixel & 0xFF00) >> 8;
+// break;
+// default:
+// return null;
+// }
+// }
+// OS.SelectObject(hdcMem, hOldObject);
+// OS.DeleteDC(hdcMem);
+//
+// /* Release the HDC for the device */
+// device.internal_dispose_GC(hDC, null);
+// return Color.win32_new(device, 0x02000000 | (blue << 16) | (green << 8) | red);
+}
+
+/**
+ * Returns the bounds of the receiver. The rectangle will always
+ * have x and y values of 0, and the width and height of the
+ * image.
+ *
+ * @return a rectangle specifying the image's bounds
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon
+ *
+ */
+public Rectangle getBounds() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return new Rectangle(0, 0, handle.getWidth(), handle.getHeight());
+}
+
+/**
+ * Returns an ImageData based on the receiver
+ * Modifications made to this ImageData will not
+ * affect the Image.
+ *
+ * @return an ImageData containing the image's data and attributes
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon
+ *
+ *
+ * @see ImageData
+ */
+public ImageData getImageData() {
+ ColorModel colorModel = handle.getColorModel();
+ PaletteData paletteData = new PaletteData(0xFF0000, 0xFF00, 0xFF);
+ int width = handle.getWidth();
+ ImageData imageData = new ImageData(width, handle.getHeight(), colorModel.getPixelSize(), paletteData);
+ int height = handle.getHeight();
+ byte[] maskData = new byte[(width + 7) / 8 * height];
+ for(int x=width-1; x >= 0; x--) {
+ for(int y=height-1; y >= 0; y--) {
+ int rgb = handle.getRGB(x, y);
+ int pixel = paletteData.getPixel(new RGB((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF));
+ imageData.setPixel(x, y, pixel);
+ int alpha = (rgb >> 24) & 0xFF;
+ imageData.setAlpha(x, y, alpha);
+ if(alpha != 0) {
+ int index = x + y * ((width + 7) / 8) * 8;
+ maskData[index / 8] |= (byte)(1 << (7 - (index % 8)));
+ }
+ }
+ }
+ imageData.maskPad = 1;
+ imageData.maskData = maskData;
+// ByteArrayOutputStream baos = new ByteArrayOutputStream();
+// ImageWriter writer = (ImageWriter)ImageIO.getImageWritersBySuffix("jpg").next();
+// try {
+// writer.setOutput(ImageIO.createImageOutputStream(baos));
+// writer.write(handle);
+// return new ImageData(new ByteArrayInputStream(baos.toByteArray()));
+// } catch(Exception e) {
+// e.printStackTrace();
+// }
+ return imageData;
+// if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+// BITMAP bm;
+// int depth, width, height;
+// switch (type) {
+// case SWT.ICON: {
+// if (OS.IsWinCE) return data;
+// ICONINFO info = new ICONINFO();
+// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+// OS.GetIconInfo(handle, info);
+// /* Get the basic BITMAP information */
+// int hBitmap = info.hbmColor;
+// if (hBitmap == 0) hBitmap = info.hbmMask;
+// bm = new BITMAP();
+// OS.GetObject(hBitmap, BITMAP.sizeof, bm);
+// depth = bm.bmPlanes * bm.bmBitsPixel;
+// width = bm.bmWidth;
+// if (hBitmap == info.hbmMask) bm.bmHeight /= 2;
+// height = bm.bmHeight;
+// int numColors = 0;
+// if (depth <= 8) numColors = 1 << depth;
+// /* Create the BITMAPINFO */
+// BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
+// bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+// bmiHeader.biWidth = width;
+// bmiHeader.biHeight = -height;
+// bmiHeader.biPlanes = 1;
+// bmiHeader.biBitCount = (short)depth;
+// bmiHeader.biCompression = OS.BI_RGB;
+// byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
+// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+//
+// /* Get the HDC for the device */
+// int hDC = device.internal_new_GC(null);
+//
+// /* Create the DC and select the bitmap */
+// int hBitmapDC = OS.CreateCompatibleDC(hDC);
+// int hOldBitmap = OS.SelectObject(hBitmapDC, hBitmap);
+// /* Select the palette if necessary */
+// int oldPalette = 0;
+// if (depth <= 8) {
+// int hPalette = device.hPalette;
+// if (hPalette != 0) {
+// oldPalette = OS.SelectPalette(hBitmapDC, hPalette, false);
+// OS.RealizePalette(hBitmapDC);
+// }
+// }
+// /* Find the size of the image and allocate data */
+// int imageSize;
+// /* Call with null lpBits to get the image size */
+// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+// OS.GetDIBits(hBitmapDC, hBitmap, 0, height, 0, bmi, OS.DIB_RGB_COLORS);
+// OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof);
+// imageSize = bmiHeader.biSizeImage;
+// byte[] data = new byte[imageSize];
+// /* Get the bitmap data */
+// int hHeap = OS.GetProcessHeap();
+// int lpvBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize);
+// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+// OS.GetDIBits(hBitmapDC, hBitmap, 0, height, lpvBits, bmi, OS.DIB_RGB_COLORS);
+// OS.MoveMemory(data, lpvBits, imageSize);
+// /* Calculate the palette */
+// PaletteData palette = null;
+// if (depth <= 8) {
+// RGB[] rgbs = new RGB[numColors];
+// int srcIndex = 40;
+// for (int i = 0; i < numColors; i++) {
+// rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF);
+// srcIndex += 4;
+// }
+// palette = new PaletteData(rgbs);
+// } else if (depth == 16) {
+// palette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+// } else if (depth == 24) {
+// palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+// } else if (depth == 32) {
+// palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+// } else {
+// SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+// }
+//
+// /* Do the mask */
+// byte [] maskData = null;
+// if (info.hbmColor == 0) {
+// /* Do the bottom half of the mask */
+// maskData = new byte[imageSize];
+// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+// OS.GetDIBits(hBitmapDC, hBitmap, height, height, lpvBits, bmi, OS.DIB_RGB_COLORS);
+// OS.MoveMemory(maskData, lpvBits, imageSize);
+// } else {
+// /* Do the entire mask */
+// /* Create the BITMAPINFO */
+// bmiHeader = new BITMAPINFOHEADER();
+// bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+// bmiHeader.biWidth = width;
+// bmiHeader.biHeight = -height;
+// bmiHeader.biPlanes = 1;
+// bmiHeader.biBitCount = 1;
+// bmiHeader.biCompression = OS.BI_RGB;
+// bmi = new byte[BITMAPINFOHEADER.sizeof + 8];
+// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+//
+// /* First color black, second color white */
+// int offset = BITMAPINFOHEADER.sizeof;
+// bmi[offset + 4] = bmi[offset + 5] = bmi[offset + 6] = (byte)0xFF;
+// bmi[offset + 7] = 0;
+// OS.SelectObject(hBitmapDC, info.hbmMask);
+// /* Call with null lpBits to get the image size */
+// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+// OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, 0, bmi, OS.DIB_RGB_COLORS);
+// OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof);
+// imageSize = bmiHeader.biSizeImage;
+// maskData = new byte[imageSize];
+// int lpvMaskBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize);
+// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+// OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, lpvMaskBits, bmi, OS.DIB_RGB_COLORS);
+// OS.MoveMemory(maskData, lpvMaskBits, imageSize);
+// OS.HeapFree(hHeap, 0, lpvMaskBits);
+// /* Loop to invert the mask */
+// for (int i = 0; i < maskData.length; i++) {
+// maskData[i] ^= -1;
+// }
+// /* Make sure mask scanlinePad is 2 */
+// int maskPad;
+// int bpl = imageSize / height;
+// for (maskPad = 1; maskPad < 128; maskPad++) {
+// int calcBpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad;
+// if (calcBpl == bpl) break;
+// }
+// maskData = ImageData.convertPad(maskData, width, height, 1, maskPad, 2);
+// }
+// /* Clean up */
+// OS.HeapFree(hHeap, 0, lpvBits);
+// OS.SelectObject(hBitmapDC, hOldBitmap);
+// if (oldPalette != 0) {
+// OS.SelectPalette(hBitmapDC, oldPalette, false);
+// OS.RealizePalette(hBitmapDC);
+// }
+// OS.DeleteDC(hBitmapDC);
+//
+// /* Release the HDC for the device */
+// device.internal_dispose_GC(hDC, null);
+//
+// if (info.hbmColor != 0) OS.DeleteObject(info.hbmColor);
+// if (info.hbmMask != 0) OS.DeleteObject(info.hbmMask);
+// /* Construct and return the ImageData */
+// ImageData imageData = new ImageData(width, height, depth, palette, 4, data);
+// imageData.maskData = maskData;
+// imageData.maskPad = 2;
+// return imageData;
+// }
+// case SWT.BITMAP: {
+// /* Get the basic BITMAP information */
+// bm = new BITMAP();
+// OS.GetObject(handle, BITMAP.sizeof, bm);
+// depth = bm.bmPlanes * bm.bmBitsPixel;
+// width = bm.bmWidth;
+// height = bm.bmHeight;
+// /* Find out whether this is a DIB or a DDB. */
+// boolean isDib = (bm.bmBits != 0);
+// /* Get the HDC for the device */
+// int hDC = device.internal_new_GC(null);
+//
+// /*
+// * Feature in WinCE. GetDIBits is not available in WinCE. The
+// * workaround is to create a temporary DIB from the DDB and use
+// * the bmBits field of DIBSECTION to retrieve the image data.
+// */
+// int handle = this.handle;
+// if (OS.IsWinCE) {
+// if (!isDib) {
+// boolean mustRestore = false;
+// if (memGC != null && !memGC.isDisposed()) {
+// mustRestore = true;
+// GCData data = memGC.data;
+// if (data.hNullBitmap != 0) {
+// OS.SelectObject(memGC.handle, data.hNullBitmap);
+// data.hNullBitmap = 0;
+// }
+// }
+// handle = createDIBFromDDB(hDC, this.handle, width, height);
+// if (mustRestore) {
+// int hOldBitmap = OS.SelectObject(memGC.handle, this.handle);
+// memGC.data.hNullBitmap = hOldBitmap;
+// }
+// isDib = true;
+// }
+// }
+// DIBSECTION dib = null;
+// if (isDib) {
+// dib = new DIBSECTION();
+// OS.GetObject(handle, DIBSECTION.sizeof, dib);
+// }
+// /* Calculate number of colors */
+// int numColors = 0;
+// if (depth <= 8) {
+// if (isDib) {
+// numColors = dib.biClrUsed;
+// } else {
+// numColors = 1 << depth;
+// }
+// }
+// /* Create the BITMAPINFO */
+// byte[] bmi = null;
+// BITMAPINFOHEADER bmiHeader = null;
+// if (!isDib) {
+// bmiHeader = new BITMAPINFOHEADER();
+// bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+// bmiHeader.biWidth = width;
+// bmiHeader.biHeight = -height;
+// bmiHeader.biPlanes = 1;
+// bmiHeader.biBitCount = (short)depth;
+// bmiHeader.biCompression = OS.BI_RGB;
+// bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
+// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+// }
+//
+// /* Create the DC and select the bitmap */
+// int hBitmapDC = OS.CreateCompatibleDC(hDC);
+// int hOldBitmap = OS.SelectObject(hBitmapDC, handle);
+// /* Select the palette if necessary */
+// int oldPalette = 0;
+// if (!isDib && depth <= 8) {
+// int hPalette = device.hPalette;
+// if (hPalette != 0) {
+// oldPalette = OS.SelectPalette(hBitmapDC, hPalette, false);
+// OS.RealizePalette(hBitmapDC);
+// }
+// }
+// /* Find the size of the image and allocate data */
+// int imageSize;
+// if (isDib) {
+// imageSize = dib.biSizeImage;
+// } else {
+// /* Call with null lpBits to get the image size */
+// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+// OS.GetDIBits(hBitmapDC, handle, 0, height, 0, bmi, OS.DIB_RGB_COLORS);
+// OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof);
+// imageSize = bmiHeader.biSizeImage;
+// }
+// byte[] data = new byte[imageSize];
+// /* Get the bitmap data */
+// if (isDib) {
+// if (OS.IsWinCE && this.handle != handle) {
+// /* get image data from the temporary DIB */
+// OS.MoveMemory(data, dib.bmBits, imageSize);
+// } else {
+// OS.MoveMemory(data, bm.bmBits, imageSize);
+// }
+// } else {
+// int hHeap = OS.GetProcessHeap();
+// int lpvBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize);
+// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+// OS.GetDIBits(hBitmapDC, handle, 0, height, lpvBits, bmi, OS.DIB_RGB_COLORS);
+// OS.MoveMemory(data, lpvBits, imageSize);
+// OS.HeapFree(hHeap, 0, lpvBits);
+// }
+// /* Calculate the palette */
+// PaletteData palette = null;
+// if (depth <= 8) {
+// RGB[] rgbs = new RGB[numColors];
+// if (isDib) {
+// if (OS.IsWinCE) {
+// /*
+// * Feature on WinCE. GetDIBColorTable is not supported.
+// * The workaround is to set a pixel to the desired
+// * palette index and use getPixel to get the corresponding
+// * RGB value.
+// */
+// int red = 0, green = 0, blue = 0;
+// byte[] pBits = new byte[1];
+// OS.MoveMemory(pBits, bm.bmBits, 1);
+// byte oldValue = pBits[0];
+// int mask = (0xFF << (8 - bm.bmBitsPixel)) & 0x00FF;
+// for (int i = 0; i < numColors; i++) {
+// pBits[0] = (byte)((i << (8 - bm.bmBitsPixel)) | (pBits[0] & ~mask));
+// OS.MoveMemory(bm.bmBits, pBits, 1);
+// int color = OS.GetPixel(hBitmapDC, 0, 0);
+// blue = (color & 0xFF0000) >> 16;
+// green = (color & 0xFF00) >> 8;
+// red = color & 0xFF;
+// rgbs[i] = new RGB(red, green, blue);
+// }
+// pBits[0] = oldValue;
+// OS.MoveMemory(bm.bmBits, pBits, 1);
+// } else {
+// byte[] colors = new byte[numColors * 4];
+// OS.GetDIBColorTable(hBitmapDC, 0, numColors, colors);
+// int colorIndex = 0;
+// for (int i = 0; i < rgbs.length; i++) {
+// rgbs[i] = new RGB(colors[colorIndex + 2] & 0xFF, colors[colorIndex + 1] & 0xFF, colors[colorIndex] & 0xFF);
+// colorIndex += 4;
+// }
+// }
+// } else {
+// int srcIndex = BITMAPINFOHEADER.sizeof;
+// for (int i = 0; i < numColors; i++) {
+// rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF);
+// srcIndex += 4;
+// }
+// }
+// palette = new PaletteData(rgbs);
+// } else if (depth == 16) {
+// palette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+// } else if (depth == 24) {
+// palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+// } else if (depth == 32) {
+// palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+// } else {
+// SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+// }
+// /* Clean up */
+// OS.SelectObject(hBitmapDC, hOldBitmap);
+// if (oldPalette != 0) {
+// OS.SelectPalette(hBitmapDC, oldPalette, false);
+// OS.RealizePalette(hBitmapDC);
+// }
+// if (OS.IsWinCE) {
+// if (handle != this.handle) {
+// /* free temporary DIB */
+// OS.DeleteObject (handle);
+// }
+// }
+// OS.DeleteDC(hBitmapDC);
+//
+// /* Release the HDC for the device */
+// device.internal_dispose_GC(hDC, null);
+//
+// /* Construct and return the ImageData */
+// ImageData imageData = new ImageData(width, height, depth, palette, 4, data);
+// imageData.transparentPixel = this.transparentPixel;
+// imageData.alpha = alpha;
+// if (alpha == -1 && alphaData != null) {
+// imageData.alphaData = new byte[alphaData.length];
+// System.arraycopy(alphaData, 0, imageData.alphaData, 0, alphaData.length);
+// }
+// return imageData;
+// }
+// default:
+// SWT.error(SWT.ERROR_INVALID_IMAGE);
+// return null;
+// }
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true when passed to
+ * equals must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+@Override
+public int hashCode () {
+ return handle == null? 0: handle.hashCode();
+}
+
+void init(Device device, int width, int height) {
+ if (width <= 0 || height <= 0) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.device = device;
+ type = SWT.BITMAP;
+ handle = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ if(!(device instanceof Display)) {
+ Graphics g = handle.getGraphics();
+ g.setColor(java.awt.Color.WHITE);
+ ((Graphics2D)g).setBackground(java.awt.Color.WHITE);
+ g.fillRect(0, 0, width, height);
+ }
+}
+
+static void init(Device device, Image image, ImageData data) {
+// BufferedImage bufferedImage;
+// if (data.palette.isDirect) {
+// bufferedImage = createBufferedImageDirectPalette(data, data.palette);
+// } else {
+// bufferedImage = createBufferedImageIndexPalette (data, data.palette);
+// }
+// image.handle = bufferedImage;
+// image.device = null;
+//// SImageData.serialize(image, data);
+// if(true) return;
+ image.device = device;
+ if(image.handle == null) {
+ BufferedImage bufferedImage = new BufferedImage(data.width, data.height, BufferedImage.TYPE_INT_ARGB);
+ image.handle = bufferedImage;
+ if(!(device instanceof Display)) {
+ Graphics g = bufferedImage.getGraphics();
+ g.setColor(java.awt.Color.WHITE);
+ ((Graphics2D)g).setBackground(java.awt.Color.WHITE);
+ g.fillRect(0, 0, data.width, data.height);
+ }
+ }
+ ImageData transparencyMask = data.getTransparencyMask();
+ for(int x=image.handle.getWidth()-1; x >= 0; x--) {
+ for(int y=image.handle.getHeight()-1; y >= 0; y--) {
+ RGB rgb = data.palette.getRGB(data.getPixel(x, y));
+ int pixel = rgb.red << 16 | rgb.green << 8 | rgb.blue;
+ rgb = transparencyMask.palette.getRGB(transparencyMask.getPixel(x, y));
+ int mask = rgb.red << 16 | rgb.green << 8 | rgb.blue;
+ if(mask != 0) {
+ int alpha = data.getAlpha(x, y);
+ if(alpha > 0) {
+ pixel = pixel & 0x00FFFFFF | alpha << 24;
+ image.handle.setRGB(x, y, pixel);
+ }
+ }
+ }
+ }
+// SImageData.serialize(image, data);
+// /*
+// * BUG in Windows 98:
+// * A monochrome DIBSection will display as solid black
+// * on Windows 98 machines, even though it contains the
+// * correct data. The fix is to convert 1-bit ImageData
+// * into 4-bit ImageData before creating the image.
+// */
+// /* Windows does not support 2-bit images. Convert to 4-bit image. */
+// if ((i.depth == 1 && i.getTransparencyType() != SWT.TRANSPARENCY_MASK) || i.depth == 2) {
+// ImageData img = new ImageData(i.width, i.height, 4, i.palette);
+// ImageData.blit(ImageData.BLIT_SRC,
+// i.data, i.depth, i.bytesPerLine, i.getByteOrder(), 0, 0, i.width, i.height, null, null, null,
+// ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+// img.data, img.depth, img.bytesPerLine, i.getByteOrder(), 0, 0, img.width, img.height, null, null, null,
+// false, false);
+// img.transparentPixel = i.transparentPixel;
+// img.maskPad = i.maskPad;
+// img.maskData = i.maskData;
+// img.alpha = i.alpha;
+// img.alphaData = i.alphaData;
+// i = img;
+// }
+// /*
+// * Windows supports 16-bit mask of (0x7C00, 0x3E0, 0x1F),
+// * 24-bit mask of (0xFF0000, 0xFF00, 0xFF) and 32-bit mask
+// * (0x00FF0000, 0x0000FF00, 0x000000FF) as documented in
+// * MSDN BITMAPINFOHEADER. Make sure the image is
+// * Windows-supported.
+// */
+// /*
+// * Note on WinCE. CreateDIBSection requires the biCompression
+// * field of the BITMAPINFOHEADER to be set to BI_BITFIELDS for
+// * 16 and 32 bit direct images (see MSDN for CreateDIBSection).
+// * In this case, the color mask can be set to any value. For
+// * consistency, it is set to the same mask used by non WinCE
+// * platforms in BI_RGB mode.
+// */
+// if (i.palette.isDirect) {
+// final PaletteData palette = i.palette;
+// final int redMask = palette.redMask;
+// final int greenMask = palette.greenMask;
+// final int blueMask = palette.blueMask;
+// int newDepth = i.depth;
+// int newOrder = ImageData.MSB_FIRST;
+// PaletteData newPalette = null;
+//
+// switch (i.depth) {
+// case 8:
+// newDepth = 16;
+// newOrder = ImageData.LSB_FIRST;
+// newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+// break;
+// case 16:
+// newOrder = ImageData.LSB_FIRST;
+// if (!(redMask == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F)) {
+// newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+// }
+// break;
+// case 24:
+// if (!(redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000)) {
+// newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+// }
+// break;
+// case 32:
+// if (!(redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000)) {
+// newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+// }
+// break;
+// default:
+// SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+// }
+// if (newPalette != null) {
+// ImageData img = new ImageData(i.width, i.height, newDepth, newPalette);
+// ImageData.blit(ImageData.BLIT_SRC,
+// i.data, i.depth, i.bytesPerLine, i.getByteOrder(), 0, 0, i.width, i.height, redMask, greenMask, blueMask,
+// ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+// img.data, img.depth, img.bytesPerLine, newOrder, 0, 0, img.width, img.height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+// false, false);
+// if (i.transparentPixel != -1) {
+// img.transparentPixel = newPalette.getPixel(palette.getRGB(i.transparentPixel));
+// }
+// img.maskPad = i.maskPad;
+// img.maskData = i.maskData;
+// img.alpha = i.alpha;
+// img.alphaData = i.alphaData;
+// i = img;
+// }
+// }
+// /* Construct bitmap info header by hand */
+// RGB[] rgbs = i.palette.getRGBs();
+// boolean useBitfields = OS.IsWinCE && (i.depth == 16 || i.depth == 32);
+// BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
+// bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+// bmiHeader.biWidth = i.width;
+// bmiHeader.biHeight = -i.height;
+// bmiHeader.biPlanes = 1;
+// bmiHeader.biBitCount = (short)i.depth;
+// if (useBitfields) bmiHeader.biCompression = OS.BI_BITFIELDS;
+// else bmiHeader.biCompression = OS.BI_RGB;
+// bmiHeader.biClrUsed = rgbs == null ? 0 : rgbs.length;
+// byte[] bmi;
+// if (i.palette.isDirect)
+// bmi = new byte[BITMAPINFOHEADER.sizeof + (useBitfields ? 12 : 0)];
+// else
+// bmi = new byte[BITMAPINFOHEADER.sizeof + rgbs.length * 4];
+// OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+// /* Set the rgb colors into the bitmap info */
+// int offset = BITMAPINFOHEADER.sizeof;
+// if (i.palette.isDirect) {
+// if (useBitfields) {
+// PaletteData palette = i.palette;
+// int redMask = palette.redMask;
+// int greenMask = palette.greenMask;
+// int blueMask = palette.blueMask;
+// /*
+// * The color masks must be written based on the
+// * endianness of the ImageData.
+// */
+// if (i.getByteOrder() == ImageData.LSB_FIRST) {
+// bmi[offset] = (byte)((redMask & 0xFF) >> 0);
+// bmi[offset + 1] = (byte)((redMask & 0xFF00) >> 8);
+// bmi[offset + 2] = (byte)((redMask & 0xFF0000) >> 16);
+// bmi[offset + 3] = (byte)((redMask & 0xFF000000) >> 24);
+// bmi[offset + 4] = (byte)((greenMask & 0xFF) >> 0);
+// bmi[offset + 5] = (byte)((greenMask & 0xFF00) >> 8);
+// bmi[offset + 6] = (byte)((greenMask & 0xFF0000) >> 16);
+// bmi[offset + 7] = (byte)((greenMask & 0xFF000000) >> 24);
+// bmi[offset + 8] = (byte)((blueMask & 0xFF) >> 0);
+// bmi[offset + 9] = (byte)((blueMask & 0xFF00) >> 8);
+// bmi[offset + 10] = (byte)((blueMask & 0xFF0000) >> 16);
+// bmi[offset + 11] = (byte)((blueMask & 0xFF000000) >> 24);
+// } else {
+// bmi[offset] = (byte)((redMask & 0xFF000000) >> 24);
+// bmi[offset + 1] = (byte)((redMask & 0xFF0000) >> 16);
+// bmi[offset + 2] = (byte)((redMask & 0xFF00) >> 8);
+// bmi[offset + 3] = (byte)((redMask & 0xFF) >> 0);
+// bmi[offset + 4] = (byte)((greenMask & 0xFF000000) >> 24);
+// bmi[offset + 5] = (byte)((greenMask & 0xFF0000) >> 16);
+// bmi[offset + 6] = (byte)((greenMask & 0xFF00) >> 8);
+// bmi[offset + 7] = (byte)((greenMask & 0xFF) >> 0);
+// bmi[offset + 8] = (byte)((blueMask & 0xFF000000) >> 24);
+// bmi[offset + 9] = (byte)((blueMask & 0xFF0000) >> 16);
+// bmi[offset + 10] = (byte)((blueMask & 0xFF00) >> 8);
+// bmi[offset + 11] = (byte)((blueMask & 0xFF) >> 0);
+// }
+// }
+// } else {
+// for (int j = 0; j < rgbs.length; j++) {
+// bmi[offset] = (byte)rgbs[j].blue;
+// bmi[offset + 1] = (byte)rgbs[j].green;
+// bmi[offset + 2] = (byte)rgbs[j].red;
+// bmi[offset + 3] = 0;
+// offset += 4;
+// }
+// }
+// int[] pBits = new int[1];
+// int hDib = OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
+// if (hDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// /* In case of a scanline pad other than 4, do the work to convert it */
+// byte[] data = i.data;
+// if (i.scanlinePad != 4 && (i.bytesPerLine % 4 != 0)) {
+// data = ImageData.convertPad(data, i.width, i.height, i.depth, i.scanlinePad, 4);
+// }
+// OS.MoveMemory(pBits[0], data, data.length);
+//
+// int[] result = null;
+// if (i.getTransparencyType() == SWT.TRANSPARENCY_MASK) {
+// /* Get the HDC for the device */
+// int hDC = device.internal_new_GC(null);
+//
+// /* Create the color bitmap */
+// int hdcSrc = OS.CreateCompatibleDC(hDC);
+// OS.SelectObject(hdcSrc, hDib);
+// int hBitmap = OS.CreateCompatibleBitmap(hDC, i.width, i.height);
+// if (hBitmap == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// int hdcDest = OS.CreateCompatibleDC(hDC);
+// OS.SelectObject(hdcDest, hBitmap);
+// OS.BitBlt(hdcDest, 0, 0, i.width, i.height, hdcSrc, 0, 0, OS.SRCCOPY);
+//
+// /* Release the HDC for the device */
+// device.internal_dispose_GC(hDC, null);
+//
+// /* Create the mask. Windows requires icon masks to have a scanline pad of 2. */
+// byte[] maskData = ImageData.convertPad(i.maskData, i.width, i.height, 1, i.maskPad, 2);
+// int hMask = OS.CreateBitmap(i.width, i.height, 1, 1, maskData);
+// if (hMask == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// OS.SelectObject(hdcSrc, hMask);
+// OS.PatBlt(hdcSrc, 0, 0, i.width, i.height, OS.DSTINVERT);
+// OS.DeleteDC(hdcSrc);
+// OS.DeleteDC(hdcDest);
+// OS.DeleteObject(hDib);
+//
+// if (image == null) {
+// result = new int[]{hBitmap, hMask};
+// } else {
+// /* Create the icon */
+// ICONINFO info = new ICONINFO();
+// info.fIcon = true;
+// info.hbmColor = hBitmap;
+// info.hbmMask = hMask;
+// int hIcon = OS.CreateIconIndirect(info);
+// if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// OS.DeleteObject(hBitmap);
+// OS.DeleteObject(hMask);
+// image.handle = hIcon;
+// image.type = SWT.ICON;
+// if (OS.IsWinCE) image.data = i;
+// }
+// } else {
+// if (image == null) {
+// result = new int[]{hDib};
+// } else {
+// image.handle = hDib;
+// image.type = SWT.BITMAP;
+// image.transparentPixel = i.transparentPixel;
+// if (image.transparentPixel == -1) {
+// image.alpha = i.alpha;
+// if (i.alpha == -1 && i.alphaData != null) {
+// int length = i.alphaData.length;
+// image.alphaData = new byte[length];
+// System.arraycopy(i.alphaData, 0, image.alphaData, 0, length);
+// }
+// }
+// }
+// }
+// return result;
+}
+
+static void init(Device device, Image image, ImageData source, ImageData mask) {
+ /* Create a temporary image and locate the black pixel */
+ ImageData imageData;
+ int blackIndex = 0;
+ if (source.palette.isDirect) {
+ imageData = new ImageData(source.width, source.height, source.depth, source.palette);
+ } else {
+ RGB black = new RGB(0, 0, 0);
+ RGB[] rgbs = source.getRGBs();
+ if (source.transparentPixel != -1) {
+ /*
+ * The source had transparency, so we can use the transparent pixel
+ * for black.
+ */
+ RGB[] newRGBs = new RGB[rgbs.length];
+ System.arraycopy(rgbs, 0, newRGBs, 0, rgbs.length);
+ if (source.transparentPixel >= newRGBs.length) {
+ /* Grow the palette with black */
+ rgbs = new RGB[source.transparentPixel + 1];
+ System.arraycopy(newRGBs, 0, rgbs, 0, newRGBs.length);
+ for (int i = newRGBs.length; i <= source.transparentPixel; i++) {
+ rgbs[i] = new RGB(0, 0, 0);
+ }
+ } else {
+ newRGBs[source.transparentPixel] = black;
+ rgbs = newRGBs;
+ }
+ blackIndex = source.transparentPixel;
+ imageData = new ImageData(source.width, source.height, source.depth, new PaletteData(rgbs));
+ } else {
+ while (blackIndex < rgbs.length) {
+ if (rgbs[blackIndex].equals(black)) break;
+ blackIndex++;
+ }
+ if (blackIndex == rgbs.length) {
+ /*
+ * We didn't find black in the palette, and there is no transparent
+ * pixel we can use.
+ */
+ if ((1 << source.depth) > rgbs.length) {
+ /* We can grow the palette and add black */
+ RGB[] newRGBs = new RGB[rgbs.length + 1];
+ System.arraycopy(rgbs, 0, newRGBs, 0, rgbs.length);
+ newRGBs[rgbs.length] = black;
+ rgbs = newRGBs;
+ } else {
+ /* No room to grow the palette */
+ blackIndex = -1;
+ }
+ }
+ imageData = new ImageData(source.width, source.height, source.depth, new PaletteData(rgbs));
+ }
+ }
+ if (blackIndex == -1) {
+ /* There was no black in the palette, so just copy the data over */
+ System.arraycopy(source.data, 0, imageData.data, 0, imageData.data.length);
+ } else {
+ /* Modify the source image to contain black wherever the mask is 0 */
+ int[] imagePixels = new int[imageData.width];
+ int[] maskPixels = new int[mask.width];
+ for (int y = 0; y < imageData.height; y++) {
+ source.getPixels(0, y, imageData.width, imagePixels, 0);
+ mask.getPixels(0, y, mask.width, maskPixels, 0);
+ for (int i = 0; i < imagePixels.length; i++) {
+ if (maskPixels[i] == 0) imagePixels[i] = blackIndex;
+ }
+ imageData.setPixels(0, y, source.width, imagePixels, 0);
+ }
+ }
+ imageData.maskPad = mask.scanlinePad;
+ imageData.maskData = mask.data;
+ init(device, image, imageData);
+}
+
+void init(Device device, ImageData i) {
+ if (i == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, this, i);
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Image. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+@Override
+public CGC internal_new_GC (GCData data) {
+ if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if(data != null) {
+ int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ if ((data.style & mask) != 0) {
+ data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? false : true;
+ } else {
+ data.style |= SWT.LEFT_TO_RIGHT;
+ }
+ data.device = device;
+ data.image = this;
+ data.hFont = LookAndFeelUtils.getSystemFont();
+ }
+ final Graphics2D g = (Graphics2D)handle.getGraphics();
+ if(g == null) {
+ return null;
+ }
+ return new CGC.CGCGraphics2D() {
+ @Override
+ public Graphics2D getGraphics() {
+ return g;
+ }
+ @Override
+ public Dimension getDeviceSize() {
+ return new Dimension(handle.getWidth(), handle.getHeight());
+ }
+ };
+}
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Image. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public void internal_dispose_GC (CGC handle, GCData data) {
+ handle.dispose();
+}
+
+/**
+ * Returns true if the image has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the image.
+ * When an image has been disposed, it is an error to
+ * invoke any other method using the image.
+ *
+ * @return true when the image is disposed and false otherwise
+ */
+@Override
+public boolean isDisposed() {
+ return handle == null;
+}
+
+/**
+ * Sets the color to which to map the transparent pixel.
+ *
+ * There are certain uses of Images that do not support
+ * transparency (for example, setting an image into a button or label).
+ * In these cases, it may be desired to simulate transparency by using
+ * the background color of the widget to paint the transparent pixels
+ * of the image. This method specifies the color that will be used in
+ * these cases. For example:
+ *
+ * Button b = new Button();
+ * image.setBackground(b.getBackground());
+ * b.setImage(image);
+ *
+ *
+ * The image may be modified by this operation (in effect, the
+ * transparent regions may be filled with the supplied color). Hence
+ * this operation is not reversible and it is not legal to call
+ * this function twice or with a null argument.
+ *
+ * This method has no effect if the receiver does not have a transparent
+ * pixel value.
+ *
+ *
+ * @param color the color to use when a transparent pixel is specified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the color is null
+ *
ERROR_INVALID_ARGUMENT - if the color has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setBackground(Color color) {
+ // TODO: change all pixels with alpha channel == 1.0 to the defined value?
+ // if(colorModel instanceof IndexColorModel) {return colorModel.getTransparentPixel();}
+ return;
+// /*
+// * Note. Not implemented on WinCE.
+// */
+// if (OS.IsWinCE) return;
+// if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+// if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+// if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+// if (transparentPixel == -1) return;
+//
+// /* Get the HDC for the device */
+// int hDC = device.internal_new_GC(null);
+//
+// /* Change the background color in the image */
+// BITMAP bm = new BITMAP();
+// OS.GetObject(handle, BITMAP.sizeof, bm);
+// int hdcMem = OS.CreateCompatibleDC(hDC);
+// OS.SelectObject(hdcMem, handle);
+// int maxColors = 1 << bm.bmBitsPixel;
+// byte[] colors = new byte[maxColors * 4];
+// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+// int numColors = OS.GetDIBColorTable(hdcMem, 0, maxColors, colors);
+// int offset = transparentPixel * 4;
+// colors[offset] = (byte)color.getBlue();
+// colors[offset + 1] = (byte)color.getGreen();
+// colors[offset + 2] = (byte)color.getRed();
+// if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+// OS.SetDIBColorTable(hdcMem, 0, numColors, colors);
+// OS.DeleteDC(hdcMem);
+//
+// /* Release the HDC for the device */
+// device.internal_dispose_GC(hDC, null);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+@Override
+public String toString () {
+ if (isDisposed()) return "Image {*DISPOSED*}";
+ return "Image {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new image.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Image. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param device the device on which to allocate the color
+ * @param type the type of the image (SWT.BITMAP or SWT.ICON)
+ * @param handle the OS handle for the image
+ * @return a new image object containing the specified device, type and handle
+ */
+public static Image swing_new(Device device, int type, java.awt.Image handle) {
+ if (device == null) device = Device.getDevice();
+ Image image = new Image();
+ image.type = type;
+ image.handle = duplicateImage(handle);
+ image.device = device;
+ return image;
+}
+
+static BufferedImage duplicateImage(java.awt.Image handle) {
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice gs = ge.getDefaultScreenDevice();
+ GraphicsConfiguration gc = gs.getDefaultConfiguration();
+ int transparency;
+ if(handle instanceof BufferedImage) {
+ transparency = ((BufferedImage)handle).getColorModel().getTransparency();
+ } else {
+ PixelGrabber pg = new PixelGrabber(handle, 0, 0, 1, 1, false);
+ try {
+ pg.grabPixels();
+ } catch (InterruptedException e) {}
+ transparency = pg.getColorModel().getTransparency();
+ }
+ BufferedImage bHandle = gc.createCompatibleImage(handle.getWidth(null), handle.getHeight(null), transparency);
+ Graphics g = bHandle.createGraphics();
+ g.drawImage(handle, 0, 0, null);
+ g.dispose();
+ return bHandle;
+}
+
+public ImageData getImageData(int deviceZoom) {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+
+//private static BufferedImage createBufferedImageIndexPalette(ImageData data, PaletteData p) {
+// RGB[] rgbs = p.getRGBs();
+// byte[] red = new byte[rgbs.length];
+// byte[] green = new byte[rgbs.length];
+// byte[] blue = new byte[rgbs.length];
+// for(int i = 0; i < rgbs.length; i++) {
+// RGB rgb = rgbs[i];
+// red[i] = (byte) rgb.red;
+// green[i] = (byte) rgb.green;
+// blue[i] = (byte) rgb.blue;
+// }
+// ColorModel cM;
+// if(data.transparentPixel != -1) {
+// cM = new IndexColorModel(data.depth, rgbs.length, red, green, blue, data.transparentPixel);
+// } else {
+// cM = new IndexColorModel(data.depth, rgbs.length, red, green, blue);
+// }
+// BufferedImage bi = new BufferedImage(cM, cM.createCompatibleWritableRaster(data.width, data.height), false, null);
+// WritableRaster r = bi.getRaster();
+// int[] pA = new int[1];
+// for (int y = 0; y < data.height; y++) {
+// for (int x = 0; x < data.width; x++) {
+// int pixel = data.getPixel(x, y);
+// pA[0] = pixel;
+// r.setPixel(x, y, pA);
+// }
+// }
+// // System.out.println("data.transparentPixel: "
+// // + data.transparentPixel);
+// // System.out.println(colorModel);
+// // System.out.println(bufferedImage);
+// // System.out.println();
+// return bi;
+//}
+//
+//private static BufferedImage createBufferedImageDirectPalette(ImageData data, PaletteData p) {
+// // Added ColorModel.TRANSLUCENT to create a ColorModel with
+// // transparency and resulting in a ARGB BufferedImage
+// // TODO: Check if true: Still Transparency-Gradients may be
+// // impossible with standard JavaIO & BufferedImages since
+// // ColorModel.TRANSLUCENT is either opaque or transparent.
+// ColorModel cM = new DirectColorModel(data.depth, p.redMask, p.greenMask, p.blueMask, 0);
+// BufferedImage bi = new BufferedImage(cM, cM.createCompatibleWritableRaster(data.width, data.height), false, null);
+// WritableRaster r = bi.getRaster();
+// int[] pA = new int[4];
+// for (int y = 0; y < data.height; y++) {
+// for (int x = 0; x < data.width; x++) {
+// int pixel = data.getPixel(x, y);
+// RGB rgb = p.getRGB(pixel);
+// pA[0] = rgb.red;
+// pA[1] = rgb.green;
+// pA[2] = rgb.blue;
+// pA[3] = data.getAlpha(x, y);
+// // Line is a bugfix which is actually for Problems with
+// // detecting Transparency in BufferedImages. Also using the
+// // normal ImageIO.read(...) method results in this bug and
+// // can be tested using comment.png from Azureus
+// if (data.transparentPixel != -1 && pixel == data.transparentPixel) {
+// pA[3] = 0;
+// }
+// // System.out.println(pixelArray[3]);
+// r.setPixels(x, y, 1, 1, pA);
+// }
+// }
+// // System.out.println("data.transparentPixel: "
+// // + data.transparentPixel);
+// // System.out.println(colorModel);
+// // System.out.println(bufferedImage);
+// // System.out.println();
+// return bi;
+//}
+
+//public static class SImageData implements java.io.Serializable {
+// public static class SPaletteData implements java.io.Serializable {
+// public boolean isDirect;
+// public RGB[] colors;
+// public int redMask;
+// public int greenMask;
+// public int blueMask;
+// public int redShift;
+// public int greenShift;
+// public int blueShift;
+// SPaletteData(PaletteData data) {
+// this.colors = data.colors;
+// this.isDirect = data.isDirect;
+// this.redMask = data.redMask;
+// this.greenMask = data.greenMask;
+// this.blueMask = data.blueMask;
+// this.redShift = data.redShift;
+// this.greenShift = data.greenShift;
+// this.blueShift = data.blueShift;
+// }
+// public PaletteData createPaletteData() {
+// PaletteData paletteData = new PaletteData(new RGB[0]);
+// paletteData.colors = colors;
+// paletteData.isDirect = isDirect;
+// paletteData.redMask = redMask;
+// paletteData.greenMask = greenMask;
+// paletteData.blueMask = blueMask;
+// paletteData.redShift = redShift;
+// paletteData.greenShift = greenShift;
+// paletteData.blueShift = blueShift;
+// return paletteData;
+// }
+// public String toString() {
+// StringBuilder sb = new StringBuilder("PaletteData:");
+// try {
+// java.lang.reflect.Field[] fields = getClass().getDeclaredFields();
+// for(int i=0; i
+ * Currently supported image formats are:
+ *
+ *
BMP (Windows or OS/2 Bitmap)
+ *
ICO (Windows Icon)
+ *
JPEG
+ *
GIF
+ *
PNG
+ *
TIFF
+ *
+ * ImageLoaders can be used to:
+ *
+ *
load/save single images in all formats
+ *
load/save multiple images (GIF/ICO/TIFF)
+ *
load/save animated GIF images
+ *
load interlaced GIF/PNG images
+ *
load progressive JPEG images
+ *
+ *
+ *
+ * NOTE: ImageLoader is implemented in Java on some platforms, which has
+ * certain performance implications. Performance and memory sensitive applications may
+ * benefit from using one of the constructors provided by Image, as these
+ * are implemented natively.
+ *
+ * @see SWT Example: ImageAnalyzer
+ * @see Sample code and further information
+ */
+public class ImageLoader {
+
+ /**
+ * the array of ImageData objects in this ImageLoader.
+ * This array is read in when the load method is called,
+ * and it is written out when the save method is called
+ */
+ public ImageData[] data;
+
+ /**
+ * the width of the logical screen on which the images
+ * reside, in pixels (this corresponds to the GIF89a
+ * Logical Screen Width value)
+ */
+ public int logicalScreenWidth;
+
+ /**
+ * the height of the logical screen on which the images
+ * reside, in pixels (this corresponds to the GIF89a
+ * Logical Screen Height value)
+ */
+ public int logicalScreenHeight;
+
+ /**
+ * the background pixel for the logical screen (this
+ * corresponds to the GIF89a Background Color Index value).
+ * The default is -1 which means 'unspecified background'
+ */
+ public int backgroundPixel;
+
+ /**
+ * the number of times to repeat the display of a sequence
+ * of animated images (this corresponds to the commonly-used
+ * GIF application extension for "NETSCAPE 2.0 01").
+ * The default is 1. A value of 0 means 'display repeatedly'
+ */
+ public int repeatCount;
+
+ /**
+ * This is the compression used when saving jpeg and png files.
+ *
+ * When saving jpeg files, the value is from 1 to 100,
+ * where 1 is very high compression but low quality, and 100 is
+ * no compression and high quality; default is 75.
+ *
+ * When saving png files, the value is from 0 to 3, but they do not impact the quality
+ * because PNG is lossless compression. 0 is uncompressed, 1 is low compression and fast,
+ * 2 is default compression, and 3 is high compression but slow.
+ *
+ *
+ * @since 3.8
+ */
+ public int compression;
+
+ /*
+ * the set of ImageLoader event listeners, created on demand
+ */
+ List imageLoaderListeners;
+
+/**
+ * Construct a new empty ImageLoader.
+ */
+public ImageLoader() {
+ reset();
+}
+
+/**
+ * Resets the fields of the ImageLoader, except for the
+ * imageLoaderListeners field.
+ */
+void reset() {
+ data = null;
+ logicalScreenWidth = 0;
+ logicalScreenHeight = 0;
+ backgroundPixel = -1;
+ repeatCount = 1;
+ compression = -1;
+}
+
+/**
+ * Loads an array of ImageData objects from the
+ * specified input stream. Throws an error if either an error
+ * occurs while loading the images, or if the images are not
+ * of a supported type. Returns the loaded image data array.
+ *
+ * @param stream the input stream to load the images from
+ * @return an array of ImageData objects loaded from the specified input stream
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the stream is null
+ *
+ * @exception SWTException
+ *
ERROR_IO - if an IO error occurs while reading from the stream
+ *
ERROR_INVALID_IMAGE - if the image stream contains invalid data
+ *
ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format
+ *
+ */
+public ImageData[] load(InputStream stream) {
+ if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ reset();
+ data = FileFormat.load(stream, this);
+ return data;
+}
+
+/**
+ * Loads an array of ImageData objects from the
+ * file with the specified name. Throws an error if either
+ * an error occurs while loading the images, or if the images are
+ * not of a supported type. Returns the loaded image data array.
+ *
+ * @param filename the name of the file to load the images from
+ * @return an array of ImageData objects loaded from the specified file
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the file name is null
+ *
+ * @exception SWTException
+ *
ERROR_IO - if an IO error occurs while reading from the file
+ *
ERROR_INVALID_IMAGE - if the image file contains invalid data
+ *
ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format
+ *
+ */
+public ImageData[] load(String filename) {
+ if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ try (InputStream stream = new FileInputStream(filename)) {
+ return load(stream);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ return null;
+}
+
+/**
+ * Saves the image data in this ImageLoader to the specified stream.
+ * The format parameter can have one of the following values:
+ *
+ *
IMAGE_BMP
+ *
Windows BMP file format, no compression
+ *
IMAGE_BMP_RLE
+ *
Windows BMP file format, RLE compression if appropriate
+ *
IMAGE_GIF
+ *
GIF file format
+ *
IMAGE_ICO
+ *
Windows ICO file format
+ *
IMAGE_JPEG
+ *
JPEG file format
+ *
IMAGE_PNG
+ *
PNG file format
+ *
+ *
+ * @param stream the output stream to write the images to
+ * @param format the format to write the images in
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the stream is null
+ *
+ * @exception SWTException
+ *
ERROR_IO - if an IO error occurs while writing to the stream
+ *
ERROR_INVALID_IMAGE - if the image data contains invalid data
+ *
ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format
+ *
+ */
+public void save(OutputStream stream, int format) {
+ if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ FileFormat.save(stream, format, this);
+}
+
+/**
+ * Saves the image data in this ImageLoader to a file with the specified name.
+ * The format parameter can have one of the following values:
+ *
+ *
IMAGE_BMP
+ *
Windows BMP file format, no compression
+ *
IMAGE_BMP_RLE
+ *
Windows BMP file format, RLE compression if appropriate
+ *
IMAGE_GIF
+ *
GIF file format
+ *
IMAGE_ICO
+ *
Windows ICO file format
+ *
IMAGE_JPEG
+ *
JPEG file format
+ *
IMAGE_PNG
+ *
PNG file format
+ *
+ *
+ * @param filename the name of the file to write the images to
+ * @param format the format to write the images in
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the file name is null
+ *
+ * @exception SWTException
+ *
ERROR_IO - if an IO error occurs while writing to the file
+ *
ERROR_INVALID_IMAGE - if the image data contains invalid data
+ *
ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format
+ *
+ */
+public void save(String filename, int format) {
+ if (filename == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ try (OutputStream stream = new FileOutputStream(filename)) {
+ save(stream, format);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when image data is either partially or completely loaded.
+ *
+ * An ImageLoaderListener should be added before invoking
+ * one of the receiver's load methods. The listener's
+ * imageDataLoaded method is called when image
+ * data has been partially loaded, as is supported by interlaced
+ * GIF/PNG or progressive JPEG images.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @see ImageLoaderListener
+ * @see ImageLoaderEvent
+ */
+public void addImageLoaderListener(ImageLoaderListener listener) {
+ if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (imageLoaderListeners == null) {
+ imageLoaderListeners = new ArrayList<>();
+ }
+ imageLoaderListeners.add(listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will be
+ * notified when image data is either partially or completely loaded.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ *
+ * @see #addImageLoaderListener(ImageLoaderListener)
+ */
+public void removeImageLoaderListener(ImageLoaderListener listener) {
+ if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (imageLoaderListeners == null) return;
+ imageLoaderListeners.remove(listener);
+}
+
+/**
+ * Returns true if the receiver has image loader
+ * listeners, and false otherwise.
+ *
+ * @return true if there are ImageLoaderListeners, and false otherwise
+ *
+ * @see #addImageLoaderListener(ImageLoaderListener)
+ * @see #removeImageLoaderListener(ImageLoaderListener)
+ */
+public boolean hasListeners() {
+ return imageLoaderListeners != null && imageLoaderListeners.size() > 0;
+}
+
+/**
+ * Notifies all image loader listeners that an image loader event
+ * has occurred. Pass the specified event object to each listener.
+ *
+ * @param event the ImageLoaderEvent to send to each ImageLoaderListener
+ */
+public void notifyListeners(ImageLoaderEvent event) {
+ if (!hasListeners()) return;
+ int size = imageLoaderListeners.size();
+ for (int i = 0; i < size; i++) {
+ ImageLoaderListener listener = imageLoaderListeners.get(i);
+ listener.imageDataLoaded(event);
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Path.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Path.java
new file mode 100644
index 00000000000..422302f351d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Path.java
@@ -0,0 +1,489 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.LineMetrics;
+import java.awt.geom.Arc2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+
+/**
+ * Instances of this class represent paths through the two-dimensional
+ * coordinate system. Paths do not have to be continuous, and can be
+ * described using lines, rectangles, arcs, cubic or quadratic bezier curves,
+ * glyphs, or other paths.
+ *
+ * Application code must explicitly invoke the Path.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ *
+ * @since 3.1
+ */
+public class Path extends Resource {
+
+ /**
+ * the OS resource for the Path
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public GeneralPath handle;
+
+/**
+ * Constructs a new empty Path.
+ *
+ * @param device the device on which to allocate the path
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the device is null and there is no current device
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle for the path could not be obtained/li>
+ *
+ *
+ * @see #dispose()
+ */
+public Path (Device device) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ handle = new GeneralPath();
+ if (handle == null) SWT.error(SWT.ERROR_NO_HANDLES);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Adds to the receiver a circular or elliptical arc that lies within
+ * the specified rectangular area.
+ *
+ * The resulting arc begins at startAngle and extends
+ * for arcAngle degrees.
+ * Angles are interpreted such that 0 degrees is at the 3 o'clock
+ * position. A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ *
+ * The center of the arc is the center of the rectangle whose origin
+ * is (x, y) and whose size is specified by the
+ * width and height arguments.
+ *
+ * The resulting arc covers an area width + 1 pixels wide
+ * by height + 1 pixels tall.
+ *
+ *
+ * @param x the x coordinate of the upper-left corner of the arc
+ * @param y the y coordinate of the upper-left corner of the arc
+ * @param width the width of the arc
+ * @param height the height of the arc
+ * @param startAngle the beginning angle
+ * @param arcAngle the angular extent of the arc, relative to the start angle
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void addArc(float x, float y, float width, float height, float startAngle, float arcAngle) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (width == 0 || height == 0 || arcAngle == 0) return;
+ handle.append(new Arc2D.Float(x, y, width, height, startAngle,
+ arcAngle, Arc2D.OPEN), true);
+}
+
+/**
+ * Adds to the receiver the path described by the parameter.
+ *
+ * @param path the path to add to the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parameter is null
+ *
ERROR_INVALID_ARGUMENT - if the parameter has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void addPath(Path path) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ //TODO - expose connect?
+ handle.append(path.handle, true);
+}
+
+/**
+ * Adds to the receiver the rectangle specified by x, y, width and height.
+ *
+ * @param x the x coordinate of the rectangle to add
+ * @param y the y coordinate of the rectangle to add
+ * @param width the width of the rectangle to add
+ * @param height the height of the rectangle to add
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void addRectangle(float x, float y, float width, float height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.append(new Rectangle2D.Float(x, y, width, height), true);
+}
+
+/**
+ * Adds to the receiver the pattern of glyphs generated by drawing
+ * the given string using the given font starting at the point (x, y).
+ *
+ * @param string the text to use
+ * @param x the x coordinate of the starting point
+ * @param y the y coordinate of the starting point
+ * @param font the font to use
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the font is null
+ *
ERROR_INVALID_ARGUMENT - if the font has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void addString(String string, float x, float y, org.eclipse.swt.graphics.Font font) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ FontRenderContext frc = new FontRenderContext(null, true, true);
+ GlyphVector glyph = font.handle.createGlyphVector(frc, string);
+ LineMetrics lm = font.handle.getLineMetrics(string, frc);
+ handle.append(glyph.getOutline(x, y + lm.getAscent()), true);
+}
+
+/**
+ * Closes the current sub path by adding to the receiver a line
+ * from the current point of the path back to the starting point
+ * of the sub path.
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void close() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.closePath();
+}
+
+/**
+ * Returns true if the specified point is contained by
+ * the receiver and false otherwise.
+ *
+ * If outline is true, the point (x, y) checked for containment in
+ * the receiver's outline. If outline is false, the point is
+ * checked to see if it is contained within the bounds of the (closed) area
+ * covered by the receiver.
+ *
+ * @param x the x coordinate of the point to test for containment
+ * @param y the y coordinate of the point to test for containment
+ * @param gc the GC to use when testing for containment
+ * @param outline controls whether to check the outline or contained area of the path
+ * @return true if the path contains the point and false otherwise
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the gc is null
+ *
ERROR_INVALID_ARGUMENT - if the gc has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public boolean contains(float x, float y, GC gc, boolean outline) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (gc == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ //TODO - should use GC transformation
+ // TODO support outline
+ return handle.contains(x, y);
+}
+
+/**
+ * Adds to the receiver a cubic bezier curve based on the parameters.
+ *
+ * @param cx1 the x coordinate of the first control point of the spline
+ * @param cy1 the y coordinate of the first control of the spline
+ * @param cx2 the x coordinate of the second control of the spline
+ * @param cy2 the y coordinate of the second control of the spline
+ * @param x the x coordinate of the end point of the spline
+ * @param y the y coordinate of the end point of the spline
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.curveTo(cx1, cy1, cx2, cy2, x, y);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the Path. Applications must dispose of all Paths that
+ * they allocate.
+ */
+public void dispose() {
+ if (handle == null) return;
+ if (device.isDisposed()) return;
+ handle = null;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Replaces the first four elements in the parameter with values that
+ * describe the smallest rectangle that will completely contain the
+ * receiver (i.e. the bounding box).
+ *
+ * @param bounds the array to hold the result
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parameter is null
+ *
ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the bounding box
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void getBounds(float[] bounds) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (bounds.length < 4) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ Rectangle2D boundingBox = handle.getBounds2D();
+ bounds[0] = (float)boundingBox.getX();
+ bounds[1] = (float)boundingBox.getY();
+ bounds[2] = (float)boundingBox.getWidth();
+ bounds[3] = (float)boundingBox.getHeight();
+}
+
+/**
+ * Replaces the first two elements in the parameter with values that
+ * describe the current point of the path.
+ *
+ * @param point the array to hold the result
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parameter is null
+ *
ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the end point
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void getCurrentPoint(float[] point) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (point == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (point.length < 2) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ Point2D p = handle.getCurrentPoint();
+ point[0] = (float) p.getX();
+ point[1] = (float) p.getY();
+}
+
+/**
+ * Returns a device independent representation of the receiver.
+ *
+ * @return the PathData for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see PathData
+ */
+public PathData getPathData() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ List typeList = new ArrayList();
+ List pointList = new ArrayList();
+ float[] values = new float[6];
+ for(PathIterator pathIterator = handle.getPathIterator(null); !pathIterator.isDone(); pathIterator.next()) {
+ switch(pathIterator.currentSegment(values)) {
+ case PathIterator.SEG_MOVETO:
+ typeList.add(new Byte((byte)SWT.PATH_MOVE_TO));
+ break;
+ case PathIterator.SEG_LINETO:
+ typeList.add(new Byte((byte)SWT.PATH_LINE_TO));
+ pointList.add(new Float(values[0]));
+ pointList.add(new Float(values[1]));
+ break;
+ case PathIterator.SEG_QUADTO:
+ typeList.add(new Byte((byte)SWT.PATH_QUAD_TO));
+ pointList.add(new Float(values[0]));
+ pointList.add(new Float(values[1]));
+ pointList.add(new Float(values[2]));
+ pointList.add(new Float(values[3]));
+ break;
+ case PathIterator.SEG_CUBICTO:
+ typeList.add(new Byte((byte)SWT.PATH_CUBIC_TO));
+ pointList.add(new Float(values[0]));
+ pointList.add(new Float(values[1]));
+ pointList.add(new Float(values[2]));
+ pointList.add(new Float(values[3]));
+ pointList.add(new Float(values[4]));
+ pointList.add(new Float(values[5]));
+ break;
+ case PathIterator.SEG_CLOSE:
+ typeList.add(new Byte((byte)SWT.PATH_CLOSE));
+ break;
+ }
+ }
+ byte[] types = new byte[typeList.size()];
+ for(int i=typeList.size()-1; i>=0; i--) {
+ types[i] = ((Byte)typeList.get(i)).byteValue();
+ }
+ float[] points = new float[pointList.size()];
+ for(int i=pointList.size()-1; i>=0; i--) {
+ points[i] = ((Float)typeList.get(i)).floatValue();
+ }
+ PathData result = new PathData();
+ result.types = types;
+ result.points = points;
+ return result;
+// int count = Gdip.GraphicsPath_GetPointCount(handle);
+// byte[] gdipTypes = new byte[count];
+// float[] points = new float[count * 2];
+// Gdip.GraphicsPath_GetPathTypes(handle, gdipTypes, count);
+// Gdip.GraphicsPath_GetPathPoints(handle, points, count);
+// byte[] types = new byte[count * 2];
+// int index = 0, typesIndex = 0;
+// while (index < count) {
+// byte type = gdipTypes[index];
+// boolean close = false;
+// switch (type & Gdip.PathPointTypePathTypeMask) {
+// case Gdip.PathPointTypeStart:
+// types[typesIndex++] = SWT.PATH_MOVE_TO;
+// close = (type & Gdip.PathPointTypeCloseSubpath) != 0;
+// index += 1;
+// break;
+// case Gdip.PathPointTypeLine:
+// types[typesIndex++] = SWT.PATH_LINE_TO;
+// close = (type & Gdip.PathPointTypeCloseSubpath) != 0;
+// index += 1;
+// break;
+// case Gdip.PathPointTypeBezier:
+// types[typesIndex++] = SWT.PATH_CUBIC_TO;
+// close = (gdipTypes[index + 2] & Gdip.PathPointTypeCloseSubpath) != 0;
+// index += 3;
+// break;
+// default:
+// index++;
+// }
+// if (close) {
+// types[typesIndex++] = SWT.PATH_CLOSE;
+// }
+// }
+// if (typesIndex != types.length) {
+// byte[] newTypes = new byte[typesIndex];
+// System.arraycopy(types, 0, newTypes, 0, typesIndex);
+// types = newTypes;
+// }
+// PathData result = new PathData();
+// result.types = types;
+// result.points = points;
+// return result;
+}
+
+/**
+ * Adds to the receiver a line from the current point to
+ * the point specified by (x, y).
+ *
+ * @param x the x coordinate of the end of the line to add
+ * @param y the y coordinate of the end of the line to add
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void lineTo(float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.lineTo(x, y);
+}
+
+/**
+ * Returns true if the Path has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the Path.
+ * When a Path has been disposed, it is an error to
+ * invoke any other method using the Path.
+ *
+ * @return true when the Path is disposed, and false otherwise
+ */
+public boolean isDisposed() {
+ return handle == null;
+}
+
+/**
+ * Sets the current point of the receiver to the point
+ * specified by (x, y). Note that this starts a new
+ * sub path.
+ *
+ * @param x the x coordinate of the new end point
+ * @param y the y coordinate of the new end point
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void moveTo(float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.moveTo(x, y);
+}
+
+/**
+ * Adds to the receiver a quadratic curve based on the parameters.
+ *
+ * @param cx the x coordinate of the control point of the spline
+ * @param cy the y coordinate of the control point of the spline
+ * @param x the x coordinate of the end point of the spline
+ * @param y the y coordinate of the end point of the spline
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void quadTo(float cx, float cy, float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.quadTo(cx, cy, x, y);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString() {
+ if (isDisposed()) return "Path {*DISPOSED*}";
+ return "Path {" + handle + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Pattern.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Pattern.java
new file mode 100644
index 00000000000..bab4084355d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Pattern.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.swing.Utils;
+
+/**
+ * Instances of this class represent patterns to use while drawing. Patterns
+ * can be specified either as bitmaps or gradients.
+ *
+ * Application code must explicitly invoke the Pattern.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ *
+ * @since 3.1
+ */
+public class Pattern extends Resource {
+
+ /**
+ * the OS resource for the Pattern
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public int handle;
+
+/**
+ * Constructs a new Pattern given an image. Drawing with the resulting
+ * pattern will cause the image to be tiled over the resulting area.
+ *
+ * @param device the device on which to allocate the pattern
+ * @param image the image that the pattern will draw
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the device is null and there is no current device, or the image is null
+ *
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle for the pattern could not be obtained/li>
+ *
+ *
+ * @see #dispose()
+ */
+public Pattern(Device device, Image image) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ this.device = device;
+ Utils.notImplemented();
+// device.checkGDIP();
+// int[] gdipImage = image.createGdipImage();
+// int img = gdipImage[0];
+// int width = Gdip.Image_GetWidth(img);
+// int height = Gdip.Image_GetHeight(img);
+// handle = Gdip.TextureBrush_new(img, Gdip.WrapModeTile, 0, 0, width, height);
+// Gdip.Bitmap_delete(img);
+// if (gdipImage[1] != 0) {
+// int hHeap = OS.GetProcessHeap ();
+// OS.HeapFree(hHeap, 0, gdipImage[1]);
+// }
+// if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new Pattern that represents a linear, two color
+ * gradient. Drawing with the pattern will cause the resulting area to be
+ * tiled with the gradient specified by the arguments.
+ *
+ * @param device the device on which to allocate the pattern
+ * @param x1 the x coordinate of the starting corner of the gradient
+ * @param y1 the y coordinate of the starting corner of the gradient
+ * @param x2 the x coordinate of the ending corner of the gradient
+ * @param y2 the y coordinate of the ending corner of the gradient
+ * @param color1 the starting color of the gradient
+ * @param color2 the ending color of the gradient
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the device is null and there is no current device,
+ * or if either color1 or color2 is null
+ *
ERROR_INVALID_ARGUMENT - if either color1 or color2 has been disposed
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle for the pattern could not be obtained/li>
+ *
+ *
+ * @see #dispose()
+ */
+public Pattern(Device device, float x1, float y1, float x2, float y2, Color color1, Color color2) {
+ this(device, x1, y1, x2, y2, color1, 0xFF, color2, 0xFF);
+}
+
+/**
+ * Constructs a new Pattern that represents a linear, two color
+ * gradient. Drawing with the pattern will cause the resulting area to be
+ * tiled with the gradient specified by the arguments.
+ *
+ * @param device the device on which to allocate the pattern
+ * @param x1 the x coordinate of the starting corner of the gradient
+ * @param y1 the y coordinate of the starting corner of the gradient
+ * @param x2 the x coordinate of the ending corner of the gradient
+ * @param y2 the y coordinate of the ending corner of the gradient
+ * @param color1 the starting color of the gradient
+ * @param alpha1 the starting alpha value of the gradient
+ * @param color2 the ending color of the gradient
+ * @param alpha2 the ending alpha value of the gradient
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the device is null and there is no current device,
+ * or if either color1 or color2 is null
+ *
ERROR_INVALID_ARGUMENT - if either color1 or color2 has been disposed
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle for the pattern could not be obtained/li>
+ *
+ *
+ * @see #dispose()
+ *
+ * @since 3.2
+ */
+public Pattern(Device device, float x1, float y1, float x2, float y2, Color color1, int alpha1, Color color2, int alpha2) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color1 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color1.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (color2 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color2.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ this.device = device;
+ Utils.notImplemented();
+// device.checkGDIP();
+// int colorRef1 = color1.handle;
+// int rgb = ((colorRef1 >> 16) & 0xFF) | (colorRef1 & 0xFF00) | ((colorRef1 & 0xFF) << 16);
+// int foreColor = Gdip.Color_new((alpha1 & 0xFF) << 24 | rgb);
+// int colorRef2 = color2.handle;
+// rgb = ((colorRef2 >> 16) & 0xFF) | (colorRef2 & 0xFF00) | ((colorRef2 & 0xFF) << 16);
+// int backColor = Gdip.Color_new((alpha2 & 0xFF) << 24 | rgb);
+// PointF p1 = new PointF();
+// p1.X = x1;
+// p1.Y = y1;
+// PointF p2 = new PointF();
+// p2.X = x2;
+// p2.Y = y2;
+// handle = Gdip.LinearGradientBrush_new(p1, p2, foreColor, backColor);
+// if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+// if (alpha1 != 0xFF || alpha2 != 0xFF) {
+// int a = (int)((alpha1 & 0xFF) * 0.5f + (alpha2 & 0xFF) * 0.5f);
+// int r = (int)(((colorRef1 & 0xFF) >> 0) * 0.5f + ((colorRef2 & 0xFF) >> 0) * 0.5f);
+// int g = (int)(((colorRef1 & 0xFF00) >> 8) * 0.5f + ((colorRef2 & 0xFF00) >> 8) * 0.5f);
+// int b = (int)(((colorRef1 & 0xFF0000) >> 16) * 0.5f + ((colorRef2 & 0xFF0000) >> 16) * 0.5f);
+// int midColor = Gdip.Color_new(a << 24 | r << 16 | g << 8 | b);
+// Gdip.LinearGradientBrush_SetInterpolationColors(handle, new int[]{foreColor, midColor, backColor}, new float[]{0, 0.5f, 1}, 3);
+// Gdip.Color_delete(midColor);
+// }
+// Gdip.Color_delete(foreColor);
+// Gdip.Color_delete(backColor);
+// if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the Pattern. Applications must dispose of all Patterns that
+ * they allocate.
+ */
+public void dispose() {
+ if (handle == 0) return;
+ if (device.isDisposed()) return;
+// int type = Gdip.Brush_GetType(handle);
+// switch (type) {
+// case Gdip.BrushTypeSolidColor:
+// Gdip.SolidBrush_delete(handle);
+// break;
+// case Gdip.BrushTypeHatchFill:
+// Gdip.HatchBrush_delete(handle);
+// break;
+// case Gdip.BrushTypeLinearGradient:
+// Gdip.LinearGradientBrush_delete(handle);
+// break;
+// case Gdip.BrushTypeTextureFill:
+// Gdip.TextureBrush_delete(handle);
+// break;
+// }
+ handle = 0;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Returns true if the Pattern has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the Pattern.
+ * When a Pattern has been disposed, it is an error to
+ * invoke any other method using the Pattern.
+ *
+ * @return true when the Pattern is disposed, and false otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString() {
+ if (isDisposed()) return "Pattern {*DISPOSED*}";
+ return "Pattern {" + handle + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Region.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Region.java
new file mode 100644
index 00000000000..63c544152c4
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Region.java
@@ -0,0 +1,600 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class represent areas of an x-y coordinate
+ * system that are aggregates of the areas covered by a number
+ * of polygons.
+ *
+ * Application code must explicitly invoke the Region.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ */
+
+public final class Region extends Resource {
+
+ /**
+ * the OS resource for the region
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public Area handle;
+
+/**
+ * Constructs a new empty region.
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for region creation
+ *
+ */
+public Region () {
+ this(null);
+}
+
+/**
+ * Constructs a new empty region.
+ *
+ * You must dispose the region when it is no longer required.
+ *
+ *
+ * @param device the device on which to allocate the region
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for region creation
+ *
+ *
+ * @see #dispose
+ *
+ * @since 3.0
+ */
+public Region (Device device) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ handle = new Area();
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new region given a handle to the operating
+ * system resources that it should represent.
+ *
+ * @param handle the handle for the result
+ */
+Region(Device device, Shape handle) {
+ this.device = device;
+ this.handle = new Area(handle);
+}
+
+/**
+ * Adds the given polygon to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param pointArray points that describe the polygon to merge with the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.0
+*
+ */
+public void add (int[] pointArray) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int[] xPoints = new int[pointArray.length/2];
+ int[] yPoints = new int[xPoints.length];
+ for (int i = 0; i < xPoints.length; i++) {
+ xPoints[i] = pointArray[i * 2];
+ yPoints[i] = pointArray[i * 2 + 1];
+ }
+ handle.add(new Area(new java.awt.Polygon(xPoints, yPoints, xPoints.length)));
+}
+
+/**
+ * Adds the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to merge with the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void add (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ add (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Adds the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void add (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle.add(new Area(new java.awt.Rectangle(x, y, width, height)));
+}
+
+/**
+ * Adds all of the polygons which make up the area covered
+ * by the argument to the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to merge
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void add (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle.add(region.handle);
+}
+
+/**
+ * Returns true if the point specified by the
+ * arguments is inside the area specified by the receiver,
+ * and false otherwise.
+ *
+ * @param x the x coordinate of the point to test for containment
+ * @param y the y coordinate of the point to test for containment
+ * @return true if the region contains the point and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public boolean contains (int x, int y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return handle.contains(new java.awt.Point(x, y));
+}
+
+/**
+ * Returns true if the given point is inside the
+ * area specified by the receiver, and false
+ * otherwise.
+ *
+ * @param pt the point to test for containment
+ * @return true if the region contains the point and false otherwise
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public boolean contains (Point pt) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return contains(pt.x, pt.y);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the region. Applications must dispose of all regions which
+ * they allocate.
+ */
+public void dispose () {
+ if (handle == null) return;
+ if (device.isDisposed()) return;
+ handle = null;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the same object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return true if the object is the same as this object and false otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (this == object) return true;
+ if (!(object instanceof Region)) return false;
+ Region rgn = (Region)object;
+ return handle == rgn.handle;
+}
+
+/**
+ * Returns a rectangle which represents the rectangular
+ * union of the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @return a bounding rectangle for the region
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Rectangle#union
+ */
+public Rectangle getBounds() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ java.awt.Rectangle bounds = handle.getBounds();
+ return new Rectangle((int)bounds.getX(), (int)bounds.getY(), (int)bounds.getWidth(), (int)bounds.getHeight());
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return true when passed to
+ * equals must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle == null? 0: handle.hashCode();
+}
+
+/**
+ * Intersects the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to intersect with the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void intersect (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ intersect (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Intersects the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void intersect (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle.intersect(new Area(new java.awt.Rectangle(x, y, width, height)));
+}
+
+/**
+ * Intersects all of the polygons which make up the area covered
+ * by the argument to the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to intersect
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void intersect (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle.intersect(region.handle);
+}
+
+/**
+ * Returns true if the rectangle described by the
+ * arguments intersects with any of the polygons the receiver
+ * maintains to describe its area, and false otherwise.
+ *
+ * @param x the x coordinate of the origin of the rectangle
+ * @param y the y coordinate of the origin of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ * @return true if the rectangle intersects with the receiver, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Rectangle#intersects(Rectangle)
+ */
+public boolean intersects (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return handle.intersects(x, y, width, height);
+}
+
+/**
+ * Returns true if the given rectangle intersects
+ * with any of the polygons the receiver maintains to describe
+ * its area and false otherwise.
+ *
+ * @param rect the rectangle to test for intersection
+ * @return true if the rectangle intersects with the receiver, and false otherwise
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Rectangle#intersects(Rectangle)
+ */
+public boolean intersects (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return intersects(rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Returns true if the region has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the region.
+ * When a region has been disposed, it is an error to
+ * invoke any other method using the region.
+ *
+ * @return true when the region is disposed, and false otherwise
+ */
+public boolean isDisposed() {
+ return handle == null;
+}
+
+/**
+ * Returns true if the receiver does not cover any
+ * area in the (x, y) coordinate plane, and false if
+ * the receiver does cover some area in the plane.
+ *
+ * @return true if the receiver is empty, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public boolean isEmpty () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return handle.isEmpty();
+}
+
+/**
+ * Subtracts the given polygon from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param pointArray points that describe the polygon to merge with the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void subtract (int[] pointArray) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int[] xPoints = new int[pointArray.length/2];
+ int[] yPoints = new int[xPoints.length];
+ for (int i = 0; i < xPoints.length; i++) {
+ xPoints[i] = pointArray[i * 2];
+ yPoints[i] = pointArray[i * 2 + 1];
+ }
+ handle.subtract(new Area(new java.awt.Polygon(xPoints, yPoints, xPoints.length)));
+}
+
+/**
+ * Subtracts the given rectangle from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to subtract from the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void subtract (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ subtract (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Subtracts the given rectangle from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void subtract (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle.subtract(new Area(new java.awt.Rectangle(x, y, width, height)));
+}
+
+/**
+ * Subtracts all of the polygons which make up the area covered
+ * by the argument from the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to subtract
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public void subtract (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle.subtract(region.handle);
+}
+
+/**
+ * Translate all of the polygons the receiver maintains to describe
+ * its area by the specified point.
+ *
+ * @param x the x coordinate of the point to translate
+ * @param y the y coordinate of the point to translate
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void translate (int x, int y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.transform(AffineTransform.getTranslateInstance(x, y));
+}
+
+/**
+ * Translate all of the polygons the receiver maintains to describe
+ * its area by the specified point.
+ *
+ * @param pt the point to translate
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the argument is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.1
+ */
+public void translate (Point pt) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ translate (pt.x, pt.y);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Region {*DISPOSED*}";
+ return "Region {" + handle + "}";
+}
+
+///**
+// * Invokes platform specific functionality to allocate a new region.
+// *
+// * IMPORTANT: This method is not part of the public
+// * API for Region. It is marked public only so that it
+// * can be shared within the packages provided by SWT. It is not
+// * available on all platforms, and should never be called from
+// * application code.
+// *
+// *
+// * @param device the device on which to allocate the region
+// * @param handle the handle for the region
+// * @return a new region object containing the specified device and handle
+// */
+//public static Region win32_new(Device device, int handle) {
+// return new Region(device, handle);
+//}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/TextLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/TextLayout.java
new file mode 100644
index 00000000000..2dea926eb81
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/TextLayout.java
@@ -0,0 +1,1726 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import org.eclipse.swt.*;
+
+/**
+ * TextLayout is a graphic object that represents
+ * styled text.
+ *
+ * Instances of this class provide support for drawing, cursor
+ * navigation, hit testing, text wrapping, alignment, tab expansion
+ * line breaking, etc. These are aspects required for rendering internationalized text.
+ *
+ * Application code must explicitly invoke the TextLayout#dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ *
+ * @since 3.0
+ */
+public final class TextLayout extends Resource {
+ Device device;
+ Font font;
+ String text;
+ int lineSpacing;
+ int ascent, descent;
+ int alignment;
+ int wrapWidth;
+ int orientation;
+ int indent;
+ boolean justify;
+ int[] tabs;
+ int[] segments;
+ StyleItem[] styles;
+
+ StyleItem[][] runs;
+ int[] lineOffset, lineY, lineWidth;
+
+ static class StyleItem {
+ TextStyle style;
+ int start, length, width, ascent, descent;
+ boolean lineBreak, softBreak, tab;
+ @Override
+ public String toString () {
+ return "StyleItem {" + start + ", " + style + "}";
+ }
+ }
+
+/**
+ * Constructs a new instance of this class on the given device.
+ *
+ * You must dispose the text layout when it is no longer required.
+ *
+ *
+ * @param device the device on which to allocate the text layout
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
+ *
+ * @see #dispose()
+ */
+public TextLayout (Device device) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ wrapWidth = ascent = descent = -1;
+ lineSpacing = 0;
+ orientation = SWT.LEFT_TO_RIGHT;
+ styles = new StyleItem[2];
+ styles[0] = new StyleItem();
+ styles[1] = new StyleItem();
+ text = ""; //$NON-NLS-1$
+ if (device.tracking) device.new_Object(this);
+}
+
+void checkLayout () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+}
+
+void computeRuns (GC gc) {
+ if (runs != null) return;
+ boolean newGC = gc == null;
+ if (newGC) gc = new GC (device);
+ StyleItem[] allRuns = itemize();
+ for (int i=0; i lineWidth) {
+ run.width = tabs[j] - lineWidth;
+ break;
+ }
+ }
+ if (j == tabsLength) {
+ int tabX = tabs[tabsLength-1];
+ int lastTabWidth = tabsLength > 1 ? tabs[tabsLength-1] - tabs[tabsLength-2] : tabs[0];
+ if (lastTabWidth > 0) {
+ while (tabX <= lineWidth) tabX += lastTabWidth;
+ run.width = tabX - lineWidth;
+ }
+ }
+ break;
+ }
+ case '\n':
+ run.lineBreak = true;
+ run.width = 0;
+ break;
+ case '\r':
+ run.lineBreak = true;
+ run.width = 0;
+ StyleItem next = allRuns[i + 1];
+ if (next.length != 0 && text.charAt(next.start) == '\n') {
+ run.length += 1;
+ i++;
+ }
+ break;
+ }
+ }
+ if (wrapWidth != -1 && lineWidth + run.width > wrapWidth && !run.tab) {
+ int start = 0;
+ gc.setFont(getItemFont(run));
+ char[] chars = new char[run.length];
+ text.getChars(run.start, run.start + run.length, chars, 0);
+ if (!(run.style != null && run.style.metrics != null)) {
+ int width = 0, maxWidth = wrapWidth - lineWidth;
+ int charWidth = gc.stringExtent(String.valueOf(chars[start])).x;
+ while (width + charWidth < maxWidth) {
+ width += charWidth;
+ start++;
+ charWidth = gc.stringExtent(String.valueOf(chars[start])).x;
+ }
+ }
+ int firstStart = start;
+ int firstIndice = i;
+ while (i >= lineStart) {
+ chars = new char[run.length];
+ text.getChars(run.start, run.start + run.length, chars, 0);
+ while(start >= 0) {
+ if (Character.isSpaceChar(chars[start]) || Character.isWhitespace(chars[start])) break;
+ start--;
+ }
+ if (start >= 0 || i == lineStart) break;
+ run = allRuns[--i];
+ start = run.length - 1;
+ }
+ if (start == 0 && i != lineStart) {
+ run = allRuns[--i];
+ } else if (start <= 0 && i == lineStart) {
+ i = firstIndice;
+ run = allRuns[i];
+ start = Math.max(1, firstStart);
+ }
+ chars = new char[run.length];
+ text.getChars(run.start, run.start + run.length, chars, 0);
+ while (start < run.length) {
+ if (!Character.isWhitespace(chars[start])) break;
+ start++;
+ }
+ if (0 < start && start < run.length) {
+ StyleItem newRun = new StyleItem();
+ newRun.start = run.start + start;
+ newRun.length = run.length - start;
+ newRun.style = run.style;
+ run.length = start;
+ gc.setFont(getItemFont(run));
+ place (gc, run);
+ place (gc, newRun);
+ StyleItem[] newAllRuns = new StyleItem[allRuns.length + 1];
+ System.arraycopy(allRuns, 0, newAllRuns, 0, i + 1);
+ System.arraycopy(allRuns, i + 1, newAllRuns, i + 2, allRuns.length - i - 1);
+ allRuns = newAllRuns;
+ allRuns[i + 1] = newRun;
+ }
+ if (i != allRuns.length - 2) {
+ run.softBreak = run.lineBreak = true;
+ }
+ }
+ lineWidth += run.width;
+ if (run.lineBreak) {
+ lineStart = i + 1;
+ lineWidth = 0;
+ lineCount++;
+ }
+ }
+ lineWidth = 0;
+ runs = new StyleItem[lineCount][];
+ lineOffset = new int[lineCount + 1];
+ lineY = new int[lineCount + 1];
+ this.lineWidth = new int[lineCount];
+ int lineRunCount = 0, line = 0;
+ int ascent = Math.max(0, this.ascent);
+ int descent = Math.max(0, this.descent);
+ StyleItem[] lineRuns = new StyleItem[allRuns.length];
+ for (int i=0; i
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the gc is null
+ *
+ */
+public void draw (GC gc, int x, int y) {
+ draw(gc, x, y, -1, -1, null, null);
+}
+
+/**
+ * Draws the receiver's text using the specified GC at the specified
+ * point.
+ *
+ * @param gc the GC to draw
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param selectionStart the offset where the selections starts, or -1 indicating no selection
+ * @param selectionEnd the offset where the selections ends, or -1 indicating no selection
+ * @param selectionForeground selection foreground, or NULL to use the system default color
+ * @param selectionBackground selection background, or NULL to use the system default color
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the gc is null
+ *
+ */
+public void draw (GC gc, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground) {
+ checkLayout();
+ if (gc == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (selectionForeground != null && selectionForeground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (selectionBackground != null && selectionBackground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int length = text.length();
+ if (length == 0) return;
+ computeRuns(gc);
+ boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+ if (hasSelection) {
+ selectionStart = Math.min(Math.max(0, selectionStart), length - 1);
+ selectionEnd = Math.min(Math.max(0, selectionEnd), length - 1);
+ if (selectionForeground == null) selectionForeground = device.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
+ if (selectionBackground == null) selectionBackground = device.getSystemColor(SWT.COLOR_LIST_SELECTION);
+ }
+ final Color foreground = gc.getForeground();
+ final Color background = gc.getBackground();
+ final Font gcFont = gc.getFont();
+ Rectangle clip = gc.getClipping();
+ for (int line=0; line clip.x + clip.width) continue;
+ if (drawX + lineWidth[line] < clip.x) continue;
+ int baseline = Math.max(0, this.ascent);
+ for (int i = 0; i < lineRuns.length; i++) {
+ baseline = Math.max(baseline, lineRuns[i].ascent);
+ }
+ int lineHeight = lineY[line+1] - lineY[line];
+ Font lastFont = null, currentFont = null;
+ int drawRunY = 0;
+ for (int i = 0; i < lineRuns.length; i++) {
+ StyleItem run = lineRuns[i];
+ if (run.length == 0) continue;
+ if (drawX > clip.x + clip.width) break;
+ if (drawX + run.width >= clip.x) {
+ if (!run.lineBreak || run.softBreak) {
+ currentFont = getItemFont(run);
+ if (!currentFont.equals(lastFont)) {
+ gc.setFont(currentFont);
+ lastFont = currentFont;
+ }
+ drawRunY = drawY + (baseline - run.ascent);
+ int end = run.start + run.length - 1;
+ boolean fullSelection = hasSelection && selectionStart <= run.start && selectionEnd >= end;
+ if (fullSelection) {
+ gc.setBackground(selectionBackground);
+ gc.fillRectangle(drawX, drawY, run.width, lineHeight);
+ if (!run.tab && !(run.style != null && run.style.metrics != null)) {
+ gc.setForeground(selectionForeground);
+ String string = text.substring(run.start, run.start + run.length);
+ gc.drawString(string, drawX, drawRunY, true);
+ if (run.style != null && run.style.underline) {
+ int underlineY = drawRunY + run.ascent + 1 - run.style.rise;
+ gc.drawLine (drawX, underlineY, drawX + run.width, underlineY);
+ }
+ if (run.style != null && run.style.strikeout) {
+ int strikeoutY = drawRunY + (run.ascent + run.descent) - (run.ascent + run.descent)/2 - 1;
+ gc.drawLine (drawX, strikeoutY, drawX + run.width, strikeoutY);
+ }
+ }
+ } else {
+ if (run.style != null && run.style.background != null) {
+ Color bg = run.style.background;
+ gc.setBackground(bg);
+ gc.fillRectangle(drawX, drawRunY, run.width, run.ascent + run.descent);
+ }
+ if (!run.tab) {
+ Color fg = foreground;
+ if (run.style != null && run.style.foreground != null) fg = run.style.foreground;
+ gc.setForeground(fg);
+ String string = text.substring(run.start, run.start + run.length);
+ if (!(run.style != null && run.style.metrics != null)) {
+ gc.drawString(string, drawX, drawRunY, true);
+ if (run.style != null && run.style.underline) {
+ int underlineY = drawRunY + run.ascent + 1 - run.style.rise;
+ gc.drawLine (drawX, underlineY, drawX + run.width, underlineY);
+ }
+ if (run.style != null && run.style.strikeout) {
+ int strikeoutY = drawRunY + (run.ascent + run.descent) - (run.ascent + run.descent)/2 - 1;
+ gc.drawLine (drawX, strikeoutY, drawX + run.width, strikeoutY);
+ }
+ }
+ boolean partialSelection = hasSelection && !(selectionStart > end || run.start > selectionEnd);
+ if (partialSelection) {
+ int selStart = Math.max(selectionStart, run.start);
+ int selEnd = Math.min(selectionEnd, end);
+ string = text.substring(run.start, selStart);
+ int selX = drawX + gc.stringExtent(string).x;
+ string = text.substring(selStart, selEnd + 1);
+ int selWidth = gc.stringExtent(string).x;
+ gc.setBackground(selectionBackground);
+ gc.fillRectangle(selX, drawY, selWidth, lineHeight);
+ if (fg != selectionForeground && !(run.style != null && run.style.metrics != null)) {
+ gc.setForeground(selectionForeground);
+ gc.drawString(string, selX, drawRunY, true);
+ if (run.style != null && run.style.underline) {
+ int underlineY = drawRunY + run.ascent + 1 - run.style.rise;
+ gc.drawLine (selX, underlineY, selX + selWidth, underlineY);
+ }
+ if (run.style != null && run.style.strikeout) {
+ int strikeoutY = drawRunY + (run.ascent + run.descent) - (run.ascent + run.descent)/2 - 1;
+ gc.drawLine (selX, strikeoutY, selX + selWidth, strikeoutY);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ drawX += run.width;
+ }
+ }
+ gc.setForeground(foreground);
+ gc.setBackground(background);
+ gc.setFont(gcFont);
+}
+
+void freeRuns() {
+ runs = null;
+}
+
+/**
+ * Returns the receiver's horizontal text alignment, which will be one
+ * of SWT.LEFT, SWT.CENTER or
+ * SWT.RIGHT.
+ *
+ * @return the alignment used to positioned text horizontally
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getAlignment () {
+ checkLayout();
+ return alignment;
+}
+
+/**
+ * Returns the ascent of the receiver.
+ *
+ * @return the ascent
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getDescent()
+ * @see #setDescent(int)
+ * @see #setAscent(int)
+ * @see #getLineMetrics(int)
+ */
+public int getAscent () {
+ checkLayout();
+ return ascent;
+}
+
+/**
+ * Returns the bounds of the receiver.
+ *
+ * @return the bounds of the receiver
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Rectangle getBounds () {
+ checkLayout();
+ computeRuns(null);
+ int width = 0;
+ if (wrapWidth != -1) {
+ width = wrapWidth;
+ } else {
+ for (int line=0; line
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Rectangle getBounds (int start, int end) {
+ checkLayout();
+ int length = text.length();
+ if (length == 0) return new Rectangle(0, 0, 0, 0);
+ if (start > end) return new Rectangle(0, 0, 0, 0);
+ start = Math.min(Math.max(0, start), length - 1);
+ end = Math.min(Math.max(0, end), length - 1);
+ computeRuns(null);
+ int startLine = getLineIndex(start);
+ int endLine = getLineIndex(end);
+
+ Rectangle rect = new Rectangle(0, 0, 0, 0);
+ rect.y = lineY[startLine];
+ rect.height = lineY[endLine + 1] - rect.y - lineSpacing;
+ if (startLine == endLine) {
+ rect.x = getLocation(start, false).x;
+ rect.width = getLocation(end, true).x - rect.x;
+ } else {
+ while (startLine <= endLine) {
+ rect.width = Math.max(rect.width, lineWidth[startLine++]);
+ }
+ }
+ return rect;
+}
+
+/**
+ * Returns the descent of the receiver.
+ *
+ * @return the descent
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getAscent()
+ * @see #setAscent(int)
+ * @see #setDescent(int)
+ * @see #getLineMetrics(int)
+ */
+public int getDescent () {
+ checkLayout();
+ return descent;
+}
+
+/**
+ * Returns the default font currently being used by the receiver
+ * to draw and measure text.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+*
+*
+* @since 3.2
+*/
+public boolean getJustify () {
+ checkLayout();
+ return justify;
+}
+
+/**
+ * Returns the embedding level for the specified character offset. The
+ * embedding level is usually used to determine the directionality of a
+ * character in bidirectional text.
+ *
+ * @param offset the charecter offset
+ * @return the embedding level
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the character offset is out of range
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ */
+public int getLevel (int offset) {
+ checkLayout();
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ return 0;
+}
+
+/**
+ * Returns the line offsets. Each value in the array is the
+ * offset for the first character in a line except for the last
+ * value, which contains the length of the text.
+ *
+ * @return the line offsets
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int[] getLineOffsets () {
+ checkLayout();
+ computeRuns(null);
+ int[] offsets = new int[lineOffset.length];
+ System.arraycopy(lineOffset, 0, offsets, 0, offsets.length);
+ return offsets;
+}
+
+/**
+ * Returns the bounds of the line for the specified line index.
+ *
+ * @param lineIndex the line index
+ * @return the line bounds
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the line index is out of range
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Rectangle getLineBounds(int lineIndex) {
+ checkLayout();
+ computeRuns(null);
+ if (!(0 <= lineIndex && lineIndex < runs.length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ int x = getLineIndent(lineIndex);
+ int y = lineY[lineIndex];
+ int width = lineWidth[lineIndex];
+ int height = lineY[lineIndex + 1] - y - lineSpacing;
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the receiver's line count. This includes lines caused
+ * by wrapping.
+ *
+ * @return the line count
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getLineCount () {
+ checkLayout();
+ computeRuns(null);
+ return runs.length;
+}
+
+int getLineIndent (int lineIndex) {
+ int lineIndent = 0;
+ if (lineIndex == 0) {
+ lineIndent = indent;
+ } else {
+ StyleItem[] previousLine = runs[lineIndex - 1];
+ StyleItem previousRun = previousLine[previousLine.length - 1];
+ if (previousRun.lineBreak && !previousRun.softBreak) {
+ lineIndent = indent;
+ }
+ }
+ if (wrapWidth != -1) {
+ boolean partialLine = true;
+// if (justify) {
+// StyleItem[] lineRun = runs[lineIndex];
+// if (lineRun[lineRun.length - 1].softBreak) {
+// partialLine = false;
+// }
+// }
+ if (partialLine) {
+ int lineWidth = this.lineWidth[lineIndex] + lineIndent;
+ switch (alignment) {
+ case SWT.CENTER: lineIndent += (wrapWidth - lineWidth) / 2; break;
+ case SWT.RIGHT: lineIndent += wrapWidth - lineWidth; break;
+ }
+ }
+ }
+ return lineIndent;
+}
+
+/**
+ * Returns the index of the line that contains the specified
+ * character offset.
+ *
+ * @param offset the character offset
+ * @return the line index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the character offset is out of range
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getLineIndex (int offset) {
+ checkLayout();
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ computeRuns(null);
+ for (int line=0; line offset) {
+ return line;
+ }
+ }
+ return runs.length - 1;
+}
+
+/**
+ * Returns the font metrics for the specified line index.
+ *
+ * @param lineIndex the line index
+ * @return the font metrics
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the line index is out of range
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public FontMetrics getLineMetrics (int lineIndex) {
+ checkLayout();
+ computeRuns(null);
+ if (!(0 <= lineIndex && lineIndex < runs.length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ GC gc = new GC(device);
+ gc.setFont(this.font != null ? this.font : device.getSystemFont());
+ FontMetrics metrics = gc.getFontMetrics();
+ // This is a bug in SWT: the leading is omited...
+ // TODO: Check if SWT 3.3+ has added this fix
+ int ascent = Math.max(metrics.getAscent() + metrics.getLeading(), this.ascent);
+// int ascent = Math.max(metrics.getAscent(), this.ascent);
+ int descent = Math.max(metrics.getDescent(), this.descent);
+ if (text.length() != 0) {
+ StyleItem[] lineRuns = runs[lineIndex];
+ for (int i = 0; i < lineRuns.length; i++) {
+ StyleItem run = lineRuns[i];
+ if (run.style != null) {
+ int runAscent = 0;
+ int runDescent = 0;
+ if (run.style.metrics != null) {
+ GlyphMetrics glyphMetrics = run.style.metrics;
+ runAscent = glyphMetrics.ascent;
+ runDescent = glyphMetrics.descent;
+ } else if (run.style.font != null) {
+ gc.setFont(run.style.font);
+ metrics = gc.getFontMetrics();
+ runAscent = metrics.getAscent();
+ runDescent = metrics.getDescent();
+ }
+ ascent = Math.max(ascent, runAscent + run.style.rise);
+ descent = Math.max(descent, runDescent - run.style.rise);
+ }
+ }
+ }
+ gc.dispose();
+ return FontMetrics.internal_new(ascent, descent, 0, 0, ascent + descent);
+}
+
+/**
+ * Returns the location for the specified character offset. The
+ * trailing argument indicates whether the offset
+ * corresponds to the leading or trailing edge of the cluster.
+ *
+ * @param offset the character offset
+ * @param trailing the trailing flag
+ * @return the location of the character offset
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getOffset(Point, int[])
+ * @see #getOffset(int, int, int[])
+ */
+public Point getLocation (int offset, boolean trailing) {
+ checkLayout();
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ computeRuns(null);
+ int line;
+ for (line=0; line offset) break;
+ }
+ line = Math.min(line, runs.length - 1);
+ StyleItem[] lineRuns = runs[line];
+ Point result = null;
+ if (offset == length) {
+ result = new Point(lineWidth[line], lineY[line]);
+ } else {
+ int width = 0;
+ for (int i=0; iSWT.MOVEMENT_CHAR,
+ * SWT.MOVEMENT_CLUSTER or SWT.MOVEMENT_WORD.
+ *
+ * @param offset the start offset
+ * @param movement the movement type
+ * @return the next offset
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the offset is out of range
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getPreviousOffset(int, int)
+ */
+public int getNextOffset (int offset, int movement) {
+ checkLayout();
+ computeRuns(null);
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ if (offset == length) return length;
+ if ((movement & (SWT.MOVEMENT_CHAR | SWT.MOVEMENT_CLUSTER)) != 0) return offset + 1;
+ int lineEnd = 0;
+ for (int i=1; i offset) {
+ lineEnd = Math.max(lineOffset[i - 1], lineOffset[i] - 1);
+ if (i == runs.length) lineEnd++;
+ break;
+ }
+ }
+ boolean previousSpaceChar = !Character.isLetterOrDigit(text.charAt(offset));
+ offset++;
+ while (offset < lineEnd) {
+ boolean spaceChar = !Character.isLetterOrDigit(text.charAt(offset));
+ if (!spaceChar && previousSpaceChar) break;
+ previousSpaceChar = spaceChar;
+ offset++;
+ }
+ return offset;
+}
+
+/**
+ * Returns the character offset for the specified point.
+ * For a typical character, the trailing argument will be filled in to
+ * indicate whether the point is closer to the leading edge (0) or
+ * the trailing edge (1). When the point is over a cluster composed
+ * of multiple characters, the trailing argument will be filled with the
+ * position of the character in the cluster that is closest to
+ * the point.
+ *
+ * @param point the point
+ * @param trailing the trailing buffer
+ * @return the character offset
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the trailing length is less than 1
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getLocation(int, boolean)
+ */
+public int getOffset (Point point, int[] trailing) {
+ checkLayout();
+ if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return getOffset (point.x, point.y, trailing);
+}
+
+/**
+ * Returns the character offset for the specified point.
+ * For a typical character, the trailing argument will be filled in to
+ * indicate whether the point is closer to the leading edge (0) or
+ * the trailing edge (1). When the point is over a cluster composed
+ * of multiple characters, the trailing argument will be filled with the
+ * position of the character in the cluster that is closest to
+ * the point.
+ *
+ * @param x the x coordinate of the point
+ * @param y the y coordinate of the point
+ * @param trailing the trailing buffer
+ * @return the character offset
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the trailing length is less than 1
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getLocation(int, boolean)
+ */
+public int getOffset (int x, int y, int[] trailing) {
+ checkLayout();
+ if (trailing != null && trailing.length < 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ computeRuns(null);
+ int line;
+ int lineCount = runs.length;
+ for (line=0; line y) break;
+ }
+ line = Math.min(line, runs.length - 1);
+ x -= getLineIndent(line);
+ if (x >= lineWidth[line]) x = lineWidth[line] - 1;
+ if (x < 0) x = 0;
+ StyleItem[] lineRuns = runs[line];
+ int width = 0;
+ for (int i = 0; i < lineRuns.length; i++) {
+ StyleItem run = lineRuns[i];
+ if (run.lineBreak && !run.softBreak) return run.start;
+ if (width + run.width > x) {
+ if (run.style != null && run.style.metrics != null) {
+ int xRun = x - width;
+ GlyphMetrics metrics = run.style.metrics;
+ if (metrics.width > 0) {
+ if (trailing != null) {
+ trailing[0] = (xRun % metrics.width < metrics.width / 2) ? 0 : 1;
+ }
+ return run.start + xRun / metrics.width;
+ }
+ }
+ if (run.tab) {
+ if (trailing != null) {
+ trailing[0] = x < (width + run.width / 2) ? 0 : 1;
+ }
+ return run.start;
+ }
+ int offset = 0;
+ GC gc = new GC(device);
+ gc.setFont(getItemFont(run));
+ char[] chars = new char[run.length];
+ text.getChars(run.start, run.start + run.length, chars, 0);
+ for (offset = 0; offset < chars.length; offset++) {
+ int charWidth = gc.stringExtent(String.valueOf(chars[offset])).x;
+ if (width + charWidth > x) {
+ if (trailing != null) {
+ trailing[0] = x < (width + charWidth / 2) ? 0 : 1;
+ }
+ break;
+ }
+ width += charWidth;
+ }
+ gc.dispose();
+ return run.start + offset;
+ }
+ width += run.width;
+ }
+ if (trailing != null) trailing[0] = 0;
+ return lineOffset[line + 1];
+}
+
+/**
+ * Returns the orientation of the receiver.
+ *
+ * @return the orientation style
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getOrientation () {
+ checkLayout();
+ return orientation;
+}
+
+/**
+ * Returns the previous offset for the specified offset and movement
+ * type. The movement is one of SWT.MOVEMENT_CHAR,
+ * SWT.MOVEMENT_CLUSTER or SWT.MOVEMENT_WORD.
+ *
+ * @param offset the start offset
+ * @param movement the movement type
+ * @return the previous offset
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the offset is out of range
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getNextOffset(int, int)
+ */
+public int getPreviousOffset (int offset, int movement) {
+ checkLayout();
+ computeRuns(null);
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ if (offset == 0) return 0;
+ if ((movement & (SWT.MOVEMENT_CHAR | SWT.MOVEMENT_CLUSTER)) != 0) return offset - 1;
+ int lineStart = 0;
+ for (int i=0; i offset) {
+ lineStart = lineOffset[i];
+ break;
+ }
+ }
+ offset--;
+ boolean previousSpaceChar = !Character.isLetterOrDigit(text.charAt(offset));
+ while (lineStart < offset) {
+ boolean spaceChar = !Character.isLetterOrDigit(text.charAt(offset - 1));
+ if (spaceChar && !previousSpaceChar) break;
+ offset--;
+ previousSpaceChar = spaceChar;
+ }
+ return offset;
+}
+
+/**
+ * Gets the ranges of text that are associated with a TextStyle.
+ *
+ * @return the ranges, an array of offsets representing the start and end of each
+ * text style.
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getStyles()
+ *
+ * @since 3.2
+ */
+public int[] getRanges () {
+ checkLayout();
+ int[] result = new int[styles.length * 2];
+ int count = 0;
+ for (int i=0; i
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getSpacing () {
+ checkLayout();
+ return lineSpacing;
+}
+
+/**
+ * Returns the text segments offsets of the receiver.
+ *
+ * @return the text segments offsets
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int[] getSegments() {
+ checkLayout();
+ return segments;
+}
+
+/**
+ * Gets the style of the receiver at the specified character offset.
+ *
+ * @param offset the text offset
+ * @return the style or null if not set
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the character offset is out of range
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public TextStyle getStyle (int offset) {
+ checkLayout();
+ int length = text.length();
+ if (!(0 <= offset && offset < length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ for (int i=1; i offset) {
+ return styles[i - 1].style;
+ }
+ }
+ return null;
+}
+
+/**
+ * Gets all styles of the receiver.
+ *
+ * @return the styles
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getRanges()
+ *
+ * @since 3.2
+ */
+public TextStyle[] getStyles () {
+ checkLayout();
+ TextStyle[] result = new TextStyle[styles.length];
+ int count = 0;
+ for (int i=0; i
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int[] getTabs () {
+ checkLayout();
+ return tabs;
+}
+
+/**
+ * Gets the receiver's text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public String getText () {
+ checkLayout();
+ return text;
+}
+
+/**
+ * Returns the width of the receiver.
+ *
+ * @return the width
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getWidth () {
+ checkLayout();
+ return wrapWidth;
+}
+
+/**
+ * Returns true if the text layout has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the text layout.
+ * When a text layout has been disposed, it is an error to
+ * invoke any other method using the text layout.
+ *
+ *
+ * @return true when the text layout is disposed and false otherwise
+ */
+@Override
+public boolean isDisposed () {
+ return device == null;
+}
+
+/*
+ * Itemize the receiver text, create run for
+ */
+StyleItem[] itemize () {
+ int length = text.length();
+ if (length == 0) {
+ return new StyleItem[]{new StyleItem(), new StyleItem()};
+ }
+ int runCount = 0, start = 0;
+ StyleItem[] runs = new StyleItem[length];
+ char[] chars = text.toCharArray();
+ for (int i = 0; iSWT.LEFT, SWT.RIGHT or SWT.CENTER.
+ *
+ * The default alignment is SWT.LEFT. Note that the receiver's
+ * width must be set in order to use SWT.RIGHT or SWT.CENTER
+ * alignment.
+ *
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #setWidth(int)
+ */
+public void setAlignment (int alignment) {
+ checkLayout();
+ int mask = SWT.LEFT | SWT.CENTER | SWT.RIGHT;
+ alignment &= mask;
+ if (alignment == 0) return;
+ if ((alignment & SWT.LEFT) != 0) alignment = SWT.LEFT;
+ if ((alignment & SWT.RIGHT) != 0) alignment = SWT.RIGHT;
+ freeRuns();
+ this.alignment = alignment;
+}
+
+/**
+ * Sets the ascent of the receiver. The ascent is distance in pixels
+ * from the baseline to the top of the line and it is applied to all
+ * lines. The default value is -1 which means that the
+ * ascent is calculated from the line fonts.
+ *
+ * @param ascent the new ascent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the ascent is less than -1
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #setDescent(int)
+ * @see #getLineMetrics(int)
+ */
+public void setAscent (int ascent) {
+ checkLayout();
+ if (ascent < -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.ascent == ascent) return;
+ freeRuns();
+ this.ascent = ascent;
+}
+
+/**
+ * Sets the descent of the receiver. The descent is distance in pixels
+ * from the baseline to the bottom of the line and it is applied to all
+ * lines. The default value is -1 which means that the
+ * descent is calculated from the line fonts.
+ *
+ * @param descent the new descent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the descent is less than -1
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #setAscent(int)
+ * @see #getLineMetrics(int)
+ */
+public void setDescent (int descent) {
+ checkLayout();
+ if (descent < -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.descent == descent) return;
+ freeRuns();
+ this.descent = descent;
+}
+
+/**
+ * Sets the default font which will be used by the receiver
+ * to draw and measure text. If the
+ * argument is null, then a default font appropriate
+ * for the platform will be used instead. Note that a text
+ * style can override the default font.
+ *
+ * @param font the new font for the receiver, or null to indicate a default font
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the font has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setFont (Font font) {
+ checkLayout ();
+ if (font != null && font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.font == font) return;
+ if (font != null && font.equals(this.font)) return;
+ freeRuns();
+ this.font = font;
+}
+
+/**
+ * Sets the indent of the receiver. This indent it applied of the first line of
+ * each paragraph.
+ *
+ * @param indent new indent
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.2
+ */
+public void setIndent (int indent) {
+ checkLayout();
+ if (indent < 0) return;
+ if (this.indent == indent) return;
+ freeRuns();
+ this.indent = indent;
+}
+
+/**
+ * Sets the justification of the receiver. Note that the receiver's
+ * width must be set in order to use justification.
+ *
+ * @param justify new justify
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.2
+ */
+public void setJustify (boolean justify) {
+ checkLayout();
+ if (this.justify == justify) return;
+ freeRuns();
+ this.justify = justify;
+}
+
+/**
+ * Sets the orientation of the receiver, which must be one
+ * of SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT.
+ *
+ * @param orientation new orientation style
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setOrientation (int orientation) {
+ checkLayout();
+ int mask = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
+ orientation &= mask;
+ if (orientation == 0) return;
+ if ((orientation & SWT.LEFT_TO_RIGHT) != 0) orientation = SWT.LEFT_TO_RIGHT;
+ this.orientation = orientation;
+}
+
+/**
+ * Sets the line spacing of the receiver. The line spacing
+ * is the space left between lines.
+ *
+ * @param spacing the new line spacing
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the spacing is negative
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setSpacing (int spacing) {
+ checkLayout();
+ if (spacing < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.lineSpacing == spacing) return;
+ freeRuns();
+ this.lineSpacing = spacing;
+}
+
+/**
+ * Sets the offsets of the receiver's text segments. Text segments are used to
+ * override the default behaviour of the bidirectional algorithm.
+ * Bidirectional reordering can happen within a text segment but not
+ * between two adjacent segments.
+ *
+ * Each text segment is determined by two consecutive offsets in the
+ * segments arrays. The first element of the array should
+ * always be zero and the last one should always be equals to length of
+ * the text.
+ *
+ *
+ * @param segments the text segments offset
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setSegments(int[] segments) {
+ checkLayout();
+ if (this.segments == null && segments == null) return;
+ if (this.segments != null && segments !=null) {
+ if (this.segments.length == segments.length) {
+ int i;
+ for (i = 0; i
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setStyle (TextStyle style, int start, int end) {
+ checkLayout();
+ int length = text.length();
+ if (length == 0) return;
+ if (start > end) return;
+ start = Math.min(Math.max(0, start), length - 1);
+ end = Math.min(Math.max(0, end), length - 1);
+ int low = -1;
+ int high = styles.length;
+ while (high - low > 1) {
+ int index = (high + low) / 2;
+ if (styles[index + 1].start > start) {
+ high = index;
+ } else {
+ low = index;
+ }
+ }
+ if (0 <= high && high < styles.length) {
+ StyleItem item = styles[high];
+ if (item.start == start && styles[high + 1].start - 1 == end) {
+ if (style == null) {
+ if (item.style == null) return;
+ } else {
+ if (style.equals(item.style)) return;
+ }
+ }
+ }
+ freeRuns();
+ int modifyStart = high;
+ int modifyEnd = modifyStart;
+ while (modifyEnd < styles.length) {
+ if (styles[modifyEnd + 1].start > end) break;
+ modifyEnd++;
+ }
+ if (modifyStart == modifyEnd) {
+ int styleStart = styles[modifyStart].start;
+ int styleEnd = styles[modifyEnd + 1].start - 1;
+ if (styleStart == start && styleEnd == end) {
+ styles[modifyStart].style = style;
+ return;
+ }
+ if (styleStart != start && styleEnd != end) {
+ StyleItem[] newStyles = new StyleItem[styles.length + 2];
+ System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1);
+ StyleItem item = new StyleItem();
+ item.start = start;
+ item.style = style;
+ newStyles[modifyStart + 1] = item;
+ item = new StyleItem();
+ item.start = end + 1;
+ item.style = styles[modifyStart].style;
+ newStyles[modifyStart + 2] = item;
+ System.arraycopy(styles, modifyEnd + 1, newStyles, modifyEnd + 3, styles.length - modifyEnd - 1);
+ styles = newStyles;
+ return;
+ }
+ }
+ if (start == styles[modifyStart].start) modifyStart--;
+ if (end == styles[modifyEnd + 1].start - 1) modifyEnd++;
+ int newLength = styles.length + 1 - (modifyEnd - modifyStart - 1);
+ StyleItem[] newStyles = new StyleItem[newLength];
+ System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1);
+ StyleItem item = new StyleItem();
+ item.start = start;
+ item.style = style;
+ newStyles[modifyStart + 1] = item;
+ styles[modifyEnd].start = end + 1;
+ System.arraycopy(styles, modifyEnd, newStyles, modifyStart + 2, styles.length - modifyEnd);
+ styles = newStyles;
+}
+
+/**
+ * Sets the receiver's tab list. Each value in the tab list specifies
+ * the space in pixels from the origin of the text layout to the respective
+ * tab stop. The last tab stop width is repeated continuously.
+ *
+ * @param tabs the new tab list
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setTabs (int[] tabs) {
+ checkLayout();
+ if (this.tabs == null && tabs == null) return;
+ if (this.tabs != null && tabs !=null) {
+ if (this.tabs.length == tabs.length) {
+ int i;
+ for (i = 0; i
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setText (String text) {
+ checkLayout();
+ if (text == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (text.equals(this.text)) return;
+ freeRuns();
+ this.text = text;
+ styles = new StyleItem[2];
+ styles[0] = new StyleItem();
+ styles[1] = new StyleItem();
+ styles[1].start = text.length();
+}
+
+/**
+ * Sets the line width of the receiver, which determines how
+ * text should be wrapped and aligned. The default value is
+ * -1 which means wrapping is disabled.
+ *
+ * @param width the new width
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the width is 0 or less than -1
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #setAlignment(int)
+ */
+public void setWidth (int width) {
+ checkLayout();
+ if (width < -1 || width == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.wrapWidth == width) return;
+ freeRuns();
+ this.wrapWidth = width;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+@Override
+public String toString () {
+ if (isDisposed()) return "TextLayout {*DISPOSED*}";
+ return "TextLayout {}";
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Transform.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Transform.java
new file mode 100644
index 00000000000..6f64fcb1bc9
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/Transform.java
@@ -0,0 +1,324 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.graphics;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+
+import org.eclipse.swt.SWT;
+
+/**
+ * Instances of this class represent transformation matrices for
+ * points expressed as (x, y) pairs of floating point numbers.
+ *
+ * Application code must explicitly invoke the Transform.dispose()
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ *
+ *
+ * @since 3.1
+ */
+public class Transform extends Resource {
+
+ /**
+ * the OS resource for the Transform
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public AffineTransform handle;
+
+/**
+ * Constructs a new identity Transform.
+ *
+ * @param device the device on which to allocate the Transform
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle for the Transform could not be obtained/li>
+ *
+ *
+ * @see #dispose()
+ */
+public Transform (Device device) {
+ this(device, 1, 0, 0, 1, 0, 0);
+}
+
+/**
+ * Constructs a new Transform given an array of elements that represent the
+ * matrix that describes the transformation.
+ *
+ * @param device the device on which to allocate the Transform
+ * @param elements an array of floats that describe the transformation matrix
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device, or the elements array is null
+ *
ERROR_INVALID_ARGUMENT - if the elements array is too small to hold the matrix values
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle for the Transform could not be obtained/li>
+ *
+ *
+ * @see #dispose()
+ */
+public Transform(Device device, float[] elements) {
+ this (device, checkTransform(elements)[0], elements[1], elements[2], elements[3], elements[4], elements[5]);
+}
+
+/**
+ * Constructs a new Transform given all of the elements that represent the
+ * matrix that describes the transformation.
+ *
+ * @param device the device on which to allocate the Transform
+ * @param m11 the first element of the first row of the matrix
+ * @param m12 the second element of the first row of the matrix
+ * @param m21 the first element of the second row of the matrix
+ * @param m22 the second element of the second row of the matrix
+ * @param dx the third element of the first row of the matrix
+ * @param dy the third element of the second row of the matrix
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle for the Transform could not be obtained/li>
+ *
+ *
+ * @see #dispose()
+ */
+public Transform (Device device, float m11, float m12, float m21, float m22, float dx, float dy) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ handle = new AffineTransform(m11, m12, m21, m22, dx, dy);
+ if (handle == null) SWT.error(SWT.ERROR_NO_HANDLES);
+ if (device.tracking) device.new_Object(this);
+}
+
+static float[] checkTransform(float[] elements) {
+ if (elements == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ return elements;
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the Transform. Applications must dispose of all Transforms that
+ * they allocate.
+ */
+public void dispose() {
+ if (handle == null) return;
+ if (device.isDisposed()) return;
+ handle = null;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Fills the parameter with the values of the transformation matrix
+ * that the receiver represents, in the order {m11, m12, m21, m22, dx, dy}.
+ *
+ * @param elements array to hold the matrix values
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parameter is null
+ *
ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the matrix values
+ *
+ */
+public void getElements(float[] elements) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (elements == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ double[] matrix = new double[6];
+ handle.getMatrix(matrix);
+ for (int i = 0; i < 6; i++) {
+ elements[i] = (float) matrix[i];
+ }
+}
+
+/**
+ * Modifies the receiver such that the matrix it represents becomes the
+ * the mathematical inverse of the matrix it previously represented.
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
ERROR_CANNOT_INVERT_MATRIX - if the matrix is not invertable
+ *
+ */
+public void invert() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ try {
+ handle = handle.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ SWT.error(SWT.ERROR_CANNOT_INVERT_MATRIX);
+ }
+}
+
+/**
+ * Returns true if the Transform has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the Transform.
+ * When a Transform has been disposed, it is an error to
+ * invoke any other method using the Transform.
+ *
+ * @return true when the Transform is disposed, and false otherwise
+ */
+public boolean isDisposed() {
+ return handle == null;
+}
+
+/**
+ * Returns true if the Transform represents the identity matrix
+ * and false otherwise.
+ *
+ * @return true if the receiver is an identity Transform, and false otherwise
+ */
+public boolean isIdentity() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return handle.isIdentity();
+}
+
+/**
+ * Modifies the receiver such that the matrix it represents becomes the
+ * the result of multiplying the matrix it previously represented by the
+ * argument.
+ *
+ * @param matrix the matrix to multiply the receiver by
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parameter is null
+ *
ERROR_INVALID_ARGUMENT - if the parameter has been disposed
+ *
+ */
+public void multiply(Transform matrix) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (matrix == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (matrix.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ handle.concatenate(matrix.handle);
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation rotated by the specified angle.
+ * The angle is specified in degrees and for the identity transform 0 degrees
+ * is at the 3 o'clock position. A positive value indicates a clockwise rotation
+ * while a negative value indicates a counter-clockwise rotation.
+ *
+ * @param angle the angle to rotate the transformation by
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void rotate(float angle) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.rotate(angle * Math.PI / 180);
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation scaled by (scaleX, scaleY).
+ *
+ * @param scaleX the amount to scale in the X direction
+ * @param scaleY the amount to scale in the Y direction
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void scale(float scaleX, float scaleY) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.scale(scaleX, scaleY);
+}
+
+/**
+ * Modifies the receiver to represent a new transformation given all of
+ * the elements that represent the matrix that describes that transformation.
+ *
+ * @param m11 the first element of the first row of the matrix
+ * @param m12 the second element of the first row of the matrix
+ * @param m21 the first element of the second row of the matrix
+ * @param m22 the second element of the second row of the matrix
+ * @param dx the third element of the first row of the matrix
+ * @param dy the third element of the second row of the matrix
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void setElements(float m11, float m12, float m21, float m22, float dx, float dy) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.setTransform(m11, m12, m21, m22, dx, dy);
+}
+
+/**
+ * Given an array containing points described by alternating x and y values,
+ * modify that array such that each point has been replaced with the result of
+ * applying the transformation represented by the receiver to that point.
+ *
+ * @param pointArray an array of alternating x and y values to be transformed
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point array is null
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void transform(float[] pointArray) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ handle.transform(pointArray, 0, pointArray, 0, pointArray.length);
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation translated by (offsetX, offsetY).
+ *
+ * @param offsetX the distance to translate in the X direction
+ * @param offsetY the distance to translate in the Y direction
+ *
+ * @exception SWTException
+ *
ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void translate(float offsetX, float offsetY) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ handle.translate(offsetX, offsetY);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString() {
+ if (isDisposed()) return "Transform {*DISPOSED*}";
+ float[] elements = new float[6];
+ getElements(elements);
+ return "Transform {" + elements [0] + "," + elements [1] + "," +elements [2] + "," +elements [3] + "," +elements [4] + "," +elements [5] + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.gif b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ddc2ea121f059c7823a6ac5ebab1bd9464d7e3b1
GIT binary patch
literal 176
zcmZ?wbhEHbRA5kGIK%(~XU_ajOPiUNmS$|6_W%F?GeG|T|B63Z7`YhO8FWA@Kx!G7
zODlHW`DbuyC&OO8h%=5iWS(*+Nc1kzT)5JBkK%1D{lvr5ZTQO)g-b
an(7N%xvM+6dwTo&Crq3)d5Rz>gEav2Ur2QT
literal 0
HcmV?d00001
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.properties b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.properties
new file mode 100644
index 00000000000..cc41f6118c8
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/HelpCursor.properties
@@ -0,0 +1,13 @@
+#
+# @(#) OnItemCursor.properties 1.2 - last change made 07/07/98
+#
+# Cursors Properties file
+#
+# Names GIF89 sources for Custom Cursors and their associated HotSpots
+#
+#
+# The syntax is: Cursor.File=
+# Cursor.HotSpot=,
+#
+Cursor.File=HelpCursor.gif
+Cursor.HotSpot=5,2
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/NoCursor.gif b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/graphics/resources/NoCursor.gif
new file mode 100644
index 0000000000000000000000000000000000000000..692b1b357edd68150930154ba03ead712e7f3c5f
GIT binary patch
literal 1341
zcmcK3`%jZ+6bJC4ZQou2DPXxMr4+EGTv~dy;ApAbid=_Z+eA#A!)>T7sV@!s*F=dXgVY_A|veTZ+??0bL5{sW^QTPM6^H
z6hB=8uvCDh;aCceN&T2~B``A5aYh=>PRH39fFlDOIpAi3U^yP9h7npAsfE$m5R(He
z9bg#%lL1VQW9g8g01O#m$Z>`YGL?Xt3786;DT6E(U@0LxKn>V(z|I701-8wgu)^1)XakDQeI2DoF}Wzlh+>UsLmu3qM;r4|d?6AB6hUDDNGL+00236MP+}2E
zG@+zzXj3T?mmomu!4q|-~fykxVNboY`w`pBLAWJ^EUdI&OWh*J=OVSFMu^q|GFViZKq6R8zkkUfvY(#bg
zk<&!z9Z>IBHaKyk3v6{S8(ll(-3q>7+HG*(**E$^rf=-IVo!|J&e(&3
zKEba4en5HQ*3~QYvoq+zn*KhTo81<3dojHKI(9bV;0RT8_;M#E`L=1UwP$*mdRY>-
ze4oiUJX@7=Vqh?6ns&Cls4w}&)wa#nprH`qgyX^i6vlT)H=*
zi4P9{OO?Vp;$EEH`;wM~uQVT{oToDw;g^2eST;Uc-2H^pl!x_XClsVQy9BmwV!_+T
zeDu6|TS7bE>ox9}@b+VC`5)PY9w_i;^7mv8@)gsse4*p;;`wf`&)ci!4K>$v3TZjR^ytt
zW@VsaVT_TGyjxtO4-Xm-4;2p&6rZ2Cx3|)ekff!hv&hKH&d$%Hq{V7%jg^> 8) & 0xFF);
+// byte transBlue = (byte)((background >> 16) & 0xFF);
+// final int spinc = dibBM.bmWidthBytes - srcWidth * 4;
+// int sp = 3;
+// for (int y = 0; y < srcHeight; ++y) {
+// for (int x = 0; x < srcWidth; ++x) {
+// srcData [sp] = (srcData[sp-1] == transRed && srcData[sp-2] == transGreen && srcData[sp-3] == transBlue) ? 0 : (byte)255;
+// sp += 4;
+// }
+// sp += spinc;
+// }
+// }
+// OS.MoveMemory (dibBM.bmBits, srcData, sizeInBytes);
+//
+// /* Stretch and free resources */
+// if (srcWidth != destWidth || srcHeight != destHeight) {
+// BITMAPINFOHEADER bmiHeader2 = new BITMAPINFOHEADER ();
+// bmiHeader2.biSize = BITMAPINFOHEADER.sizeof;
+// bmiHeader2.biWidth = destWidth;
+// bmiHeader2.biHeight = -destHeight;
+// bmiHeader2.biPlanes = 1;
+// bmiHeader2.biBitCount = 32;
+// bmiHeader2.biCompression = OS.BI_RGB;
+// byte [] bmi2 = new byte[BITMAPINFOHEADER.sizeof];
+// OS.MoveMemory (bmi2, bmiHeader2, BITMAPINFOHEADER.sizeof);
+// long [] pBits2 = new long [1];
+// long memDib2 = OS.CreateDIBSection (0, bmi2, OS.DIB_RGB_COLORS, pBits2, 0, 0);
+// long memHdc2 = OS.CreateCompatibleDC (hdc);
+// long oldMemBitmap2 = OS.SelectObject (memHdc2, memDib2);
+// OS.SetStretchBltMode(memHdc2, OS.COLORONCOLOR);
+// OS.StretchBlt (memHdc2, 0, 0, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
+// OS.SelectObject (memHdc2, oldMemBitmap2);
+// OS.DeleteDC (memHdc2);
+// OS.SelectObject (memHdc, oldMemBitmap);
+// OS.DeleteDC (memHdc);
+// OS.DeleteObject (memDib);
+// memDib = memDib2;
+// } else {
+// OS.SelectObject (memHdc, oldMemBitmap);
+// OS.DeleteDC (memHdc);
+// }
+// OS.SelectObject (srcHdc, oldSrcBitmap);
+// OS.DeleteDC (srcHdc);
+// OS.ReleaseDC (0, hdc);
+// return memDib;
+//}
+//
+//long createMaskFromAlpha (ImageData data, int destWidth, int destHeight) {
+// int srcWidth = data.width;
+// int srcHeight = data.height;
+// ImageData mask = ImageData.internal_new (srcWidth, srcHeight, 1,
+// new PaletteData(new RGB [] {new RGB (0, 0, 0), new RGB (0xff, 0xff, 0xff)}),
+// 2, null, 1, null, null, -1, -1, -1, 0, 0, 0, 0);
+// int ap = 0;
+// for (int y = 0; y < mask.height; y++) {
+// for (int x = 0; x < mask.width; x++) {
+// mask.setPixel (x, y, (data.alphaData [ap++] & 0xff) <= 127 ? 1 : 0);
+// }
+// }
+// long hMask = OS.CreateBitmap (srcWidth, srcHeight, 1, 1, mask.data);
+// if (srcWidth != destWidth || srcHeight != destHeight) {
+// long hdc = OS.GetDC (0);
+// long hdc1 = OS.CreateCompatibleDC (hdc);
+// OS.SelectObject (hdc1, hMask);
+// long hdc2 = OS.CreateCompatibleDC (hdc);
+// long hMask2 = OS.CreateBitmap (destWidth, destHeight, 1, 1, null);
+// OS.SelectObject (hdc2, hMask2);
+// OS.SetStretchBltMode(hdc2, OS.COLORONCOLOR);
+// OS.StretchBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
+// OS.DeleteDC (hdc1);
+// OS.DeleteDC (hdc2);
+// OS.ReleaseDC (0, hdc);
+// OS.DeleteObject(hMask);
+// hMask = hMask2;
+// }
+// return hMask;
+//}
+//
+//long createMask (long hBitmap, int destWidth, int destHeight, int background, int transparentPixel) {
+// BITMAP bm = new BITMAP ();
+// OS.GetObject (hBitmap, BITMAP.sizeof, bm);
+// int srcWidth = bm.bmWidth;
+// int srcHeight = bm.bmHeight;
+// long hMask = OS.CreateBitmap (destWidth, destHeight, 1, 1, null);
+// long hDC = OS.GetDC (0);
+// long hdc1 = OS.CreateCompatibleDC (hDC);
+// if (background != -1) {
+// OS.SelectObject (hdc1, hBitmap);
+//
+// /*
+// * If the image has a palette with multiple entries having
+// * the same color and one of those entries is the transparentPixel,
+// * only the first entry becomes transparent. To avoid this
+// * problem, temporarily change the image palette to a palette
+// * where the transparentPixel is white and everything else is
+// * black.
+// */
+// boolean isDib = bm.bmBits != 0;
+// byte[] originalColors = null;
+// if (transparentPixel != -1 && isDib && bm.bmBitsPixel <= 8) {
+// int maxColors = 1 << bm.bmBitsPixel;
+// byte[] oldColors = new byte[maxColors * 4];
+// OS.GetDIBColorTable(hdc1, 0, maxColors, oldColors);
+// int offset = transparentPixel * 4;
+// byte[] newColors = new byte[oldColors.length];
+// newColors[offset] = (byte)0xFF;
+// newColors[offset+1] = (byte)0xFF;
+// newColors[offset+2] = (byte)0xFF;
+// OS.SetDIBColorTable(hdc1, 0, maxColors, newColors);
+// originalColors = oldColors;
+// OS.SetBkColor (hdc1, 0xFFFFFF);
+// } else {
+// OS.SetBkColor (hdc1, background);
+// }
+//
+// long hdc2 = OS.CreateCompatibleDC (hDC);
+// OS.SelectObject (hdc2, hMask);
+// if (destWidth != srcWidth || destHeight != srcHeight) {
+// OS.SetStretchBltMode (hdc2, OS.COLORONCOLOR);
+// OS.StretchBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
+// } else {
+// OS.BitBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, OS.SRCCOPY);
+// }
+// OS.DeleteDC (hdc2);
+//
+// /* Put back the original palette */
+// if (originalColors != null) OS.SetDIBColorTable(hdc1, 0, 1 << bm.bmBitsPixel, originalColors);
+// } else {
+// long hOldBitmap = OS.SelectObject (hdc1, hMask);
+// OS.PatBlt (hdc1, 0, 0, destWidth, destHeight, OS.BLACKNESS);
+// OS.SelectObject (hdc1, hOldBitmap);
+// }
+// OS.ReleaseDC (0, hDC);
+// OS.DeleteDC (hdc1);
+// return hMask;
+//}
+//
+public void dispose () {
+// if (handle != 0) OS.ImageList_Destroy (handle);
+// handle = 0;
+// images = null;
+}
+//
+//public Image get (int index) {
+// return images [index];
+//}
+//
+//public int getStyle () {
+// return style;
+//}
+//
+//public long getHandle () {
+// return handle;
+//}
+//
+//public Point getImageSize() {
+// int [] cx = new int [1], cy = new int [1];
+// OS.ImageList_GetIconSize (handle, cx, cy);
+// return new Point (cx [0], cy [0]);
+//}
+//
+//public int indexOf (Image image) {
+// int count = OS.ImageList_GetImageCount (handle);
+// for (int i=0; i
+ *
Styles:
+ *
ARROW, CHECK, PUSH, RADIO, TOGGLE, FLAT
+ *
UP, DOWN, LEFT, RIGHT, CENTER
+ *
Events:
+ *
Selection
+ *
+ *
+ * Note: Only one of the styles ARROW, CHECK, PUSH, RADIO, and TOGGLE
+ * may be specified.
+ *
+ * Note: Only one of the styles LEFT, RIGHT, and CENTER may be specified.
+ *
+ * Note: Only one of the styles UP, DOWN, LEFT, and RIGHT may be specified
+ * when the ARROW style is specified.
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+
+public class Button extends Control {
+ Image image;
+ ImageList imageList;
+ boolean ignoreMouse;
+ String text;
+// static final int ButtonProc;
+// static final TCHAR ButtonClass = new TCHAR (0,"BUTTON", true);
+// static final char [] SCROLLBAR = new char [] {'S', 'C', 'R', 'O', 'L', 'L', 'B', 'A', 'R', 0};
+// static final int CheckWidth, CheckHeight;
+// static {
+// int hBitmap = OS.LoadBitmap (0, OS.OBM_CHECKBOXES);
+// if (hBitmap == 0) {
+// CheckWidth = OS.GetSystemMetrics (OS.IsWinCE ? OS.SM_CXSMICON : OS.SM_CXVSCROLL);
+// CheckHeight = OS.GetSystemMetrics (OS.IsWinCE ? OS.SM_CYSMICON : OS.SM_CYVSCROLL);
+// } else {
+// BITMAP bitmap = new BITMAP ();
+// OS.GetObject (hBitmap, BITMAP.sizeof, bitmap);
+// OS.DeleteObject (hBitmap);
+// CheckWidth = bitmap.bmWidth / 4;
+// CheckHeight = bitmap.bmHeight / 3;
+// }
+// WNDCLASS lpWndClass = new WNDCLASS ();
+// OS.GetClassInfo (0, ButtonClass, lpWndClass);
+// ButtonProc = lpWndClass.lpfnWndProc;
+// }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#ARROW
+ * @see SWT#CHECK
+ * @see SWT#PUSH
+ * @see SWT#RADIO
+ * @see SWT#TOGGLE
+ * @see SWT#FLAT
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Button (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * 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 SelectionListener
+ * interface.
+ *
+ * widgetSelected is called when the control is selected.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+//int callWindowProc (int hwnd, int msg, int wParam, int lParam) {
+// if (handle == 0) return 0;
+// return OS.CallWindowProc (ButtonProc, hwnd, msg, wParam, lParam);
+//}
+
+static int checkStyle (int style) {
+ style = checkBits (style, SWT.PUSH, SWT.ARROW, SWT.CHECK, SWT.RADIO, SWT.TOGGLE, 0);
+ if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) {
+ return checkBits (style, SWT.CENTER, SWT.LEFT, SWT.RIGHT, 0, 0, 0);
+ }
+ if ((style & (SWT.CHECK | SWT.RADIO)) != 0) {
+ return checkBits (style, SWT.LEFT, SWT.RIGHT, SWT.CENTER, 0, 0, 0);
+ }
+ if ((style & SWT.ARROW) != 0) {
+ style |= SWT.NO_FOCUS;
+ return checkBits (style, SWT.UP, SWT.DOWN, SWT.LEFT, SWT.RIGHT, 0, 0);
+ }
+ return style;
+}
+
+void click () {
+ ((CButton)handle).doClick();
+// /*
+// * Feature in Windows. BM_CLICK sends a fake WM_LBUTTONDOWN and
+// * WM_LBUTTONUP in order to click the button. This causes the
+// * application to get unexpected mouse events. The fix is to
+// * ignore mouse events when they are caused by BM_CLICK.
+// */
+// ignoreMouse = true;
+// OS.SendMessage (handle, OS.BM_CLICK, 0, 0);
+// ignoreMouse = false;
+}
+
+//public Point computeSize (int wHint, int hHint, boolean changed) {
+// checkWidget ();
+// int border = getBorderWidth ();
+// int width = 0, height = 0;
+// if ((style & SWT.ARROW) != 0) {
+// if ((style & (SWT.UP | SWT.DOWN)) != 0) {
+// width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+// height += OS.GetSystemMetrics (OS.SM_CYVSCROLL);
+// } else {
+// width += OS.GetSystemMetrics (OS.SM_CXHSCROLL);
+// height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+// }
+// if (wHint != SWT.DEFAULT) width = wHint;
+// if (hHint != SWT.DEFAULT) height = hHint;
+// width += border * 2; height += border * 2;
+// return new Point (width, height);
+// }
+// int extra = 0;
+// boolean hasImage;
+// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+// BUTTON_IMAGELIST buttonImageList = new BUTTON_IMAGELIST();
+// OS.SendMessage (handle, OS.BCM_GETIMAGELIST, 0, buttonImageList);
+// hasImage = buttonImageList.himl != 0;
+// } else {
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// hasImage = (bits & (OS.BS_BITMAP | OS.BS_ICON)) != 0;
+// }
+// if (!hasImage) {
+// int oldFont = 0;
+// int hDC = OS.GetDC (handle);
+// int newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+// TEXTMETRIC lptm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA ();
+// OS.GetTextMetrics (hDC, lptm);
+// int length = OS.GetWindowTextLength (handle);
+// if (length == 0) {
+// height += lptm.tmHeight;
+// } else {
+// extra = Math.max (8, lptm.tmAveCharWidth);
+// TCHAR buffer = new TCHAR (getCodePage (), length + 1);
+// OS.GetWindowText (handle, buffer, length + 1);
+// RECT rect = new RECT ();
+// int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE;
+// OS.DrawText (hDC, buffer, length, rect, flags);
+// width += rect.right - rect.left;
+// height += rect.bottom - rect.top;
+// }
+// if (newFont != 0) OS.SelectObject (hDC, oldFont);
+// OS.ReleaseDC (handle, hDC);
+// } else {
+// if (image != null) {
+// Rectangle rect = image.getBounds ();
+// width = rect.width;
+// height = rect.height;
+// extra = 8;
+// }
+// }
+// if ((style & (SWT.CHECK | SWT.RADIO)) != 0) {
+// width += CheckWidth + extra;
+// height = Math.max (height, CheckHeight + 3);
+// }
+// if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) {
+// width += 12; height += 10;
+// }
+// if (wHint != SWT.DEFAULT) width = wHint;
+// if (hHint != SWT.DEFAULT) height = hHint;
+// width += border * 2; height += border * 2;
+// return new Point (width, height);
+//}
+
+@Override
+public Point computeSize(int wHint, int hHint, boolean changed) {
+ Point size = super.computeSize(wHint, hHint, changed);
+ if ((style & SWT.ARROW) != 0) {
+ if(wHint == SWT.DEFAULT) {
+ size.x = size.y;
+ } else if(hHint == SWT.DEFAULT) {
+ size.y = size.x;
+ } else {
+ size.x = size.y;
+ }
+ }
+ return size;
+}
+
+@Override
+Container createHandle () {
+ return (Container)CButton.Factory.newInstance(this, style);
+}
+
+//int defaultBackground () {
+// if ((style & (SWT.PUSH | SWT.TOGGLE)) != 0) {
+// return OS.GetSysColor (OS.COLOR_BTNFACE);
+// }
+// return super.defaultBackground ();
+//}
+
+//int defaultForeground () {
+// return OS.GetSysColor (OS.COLOR_BTNTEXT);
+//}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * LEFT, RIGHT or CENTER
+ * unless the receiver is an ARROW button, in
+ * which case, the alignment will indicate the direction of
+ * the arrow (one of LEFT, RIGHT,
+ * UP or DOWN).
+ *
+ * @return the alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getAlignment () {
+ checkWidget ();
+ if ((style & SWT.ARROW) != 0) {
+ if ((style & SWT.UP) != 0) return SWT.UP;
+ if ((style & SWT.DOWN) != 0) return SWT.DOWN;
+ if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+ if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+ return SWT.UP;
+ }
+ if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+ if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+ if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+ return SWT.LEFT;
+}
+
+//boolean getDefault () {
+// if ((style & SWT.PUSH) == 0) return false;
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// return (bits & OS.BS_DEFPUSHBUTTON) != 0;
+//}
+
+/**
+ * Returns the receiver's image if it has one, or null
+ * if it does not.
+ *
+ * @return the receiver's image
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * When the receiver is of type CHECK or RADIO,
+ * it is selected when it is checked. When it is of type TOGGLE,
+ * it is selected when it is pushed in. If the receiver is of any other type,
+ * this method returns false.
+ *
+ * @return the selection state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getSelection () {
+ checkWidget ();
+ if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) == 0) return false;
+ return ((CButton)handle).isSelected();
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set or if the receiver is
+ * an ARROW button.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getText () {
+ checkWidget ();
+ if ((style & SWT.ARROW) != 0) return "";
+ return text == null? "": text;
+}
+
+@Override
+boolean isTabItem () {
+ //TEMPORARY CODE
+ //if ((style & SWT.PUSH) != 0) return true;
+ return super.isTabItem ();
+}
+
+@Override
+boolean isTabGroup() {
+ return (style & SWT.RADIO) == 0;
+}
+
+@Override
+boolean mnemonicHit (char ch) {
+ if (!setFocus ()) return false;
+ /*
+ * Feature in Windows. When a radio button gets focus,
+ * it selects the button in WM_SETFOCUS. Therefore, it
+ * is not necessary to click the button or send events
+ * because this has already happened in WM_SETFOCUS.
+ */
+// if ((style & SWT.RADIO) == 0) click ();
+ return true;
+}
+
+@Override
+boolean mnemonicMatch (char key) {
+ char mnemonic = findMnemonic (getText ());
+ if (mnemonic == '\0') return false;
+ return Character.toUpperCase (key) == Character.toUpperCase (mnemonic);
+}
+
+@Override
+void releaseWidget () {
+ super.releaseWidget ();
+ image = null;
+ if (imageList != null) imageList.dispose ();
+ imageList = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+//void selectRadio () {
+// /*
+// * This code is intentionally commented. When two groups
+// * of radio buttons with the same parent are separated by
+// * another control, the correct behavior should be that
+// * the two groups act independently. This is consistent
+// * with radio tool and menu items. The commented code
+// * implements this behavior.
+// */
+//// int index = 0;
+//// Control [] children = parent._getChildren ();
+//// while (index < children.length && children [index] != this) index++;
+//// int i = index - 1;
+//// while (i >= 0 && children [i].setRadioSelection (false)) --i;
+//// int j = index + 1;
+//// while (j < children.length && children [j].setRadioSelection (false)) j++;
+//// setSelection (true);
+// Control [] children = parent._getChildren ();
+// for (int i=0; iLEFT, RIGHT or CENTER
+ * unless the receiver is an ARROW button, in
+ * which case, the argument indicates the direction of
+ * the arrow (one of LEFT, RIGHT,
+ * UP or DOWN).
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setImage (Image image) {
+ checkWidget ();
+ if (image != null && image.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ this.image = image;
+ ImageIcon icon = null;
+ if (image != null && image.handle != null) {
+ icon = new ImageIcon (image.handle);
+ }
+ ((CButton) handle).setIcon (icon);
+}
+
+@Override
+boolean setRadioFocus () {
+ if ((style & SWT.RADIO) == 0 || !getSelection ()) return false;
+ return setFocus ();
+}
+
+@Override
+boolean setRadioSelection (boolean value) {
+ if ((style & SWT.RADIO) == 0) return false;
+ if (getSelection () != value) {
+ setSelection (value);
+ sendEvent (SWT.Selection);
+ }
+ return true;
+}
+
+//boolean setSavedFocus () {
+// /*
+// * Feature in Windows. When a radio button gets focus,
+// * it selects the button in WM_SETFOCUS. If the previous
+// * saved focus widget was a radio button, allowing the shell
+// * to automatically restore the focus to the previous radio
+// * button will unexpectedly check that button. The fix is
+// * to disallow focus to be restored to radio button that is
+// * not selected.
+// */
+// if ((style & SWT.RADIO) != 0 && !getSelection ()) return false;
+// return super.setSavedFocus ();
+//}
+
+boolean isAdjustingSelection;
+
+/**
+ * Sets the selection state of the receiver, if it is of type CHECK,
+ * RADIO, or TOGGLE.
+ *
+ *
+ * When the receiver is of type CHECK or RADIO,
+ * it is selected when it is checked. When it is of type TOGGLE,
+ * it is selected when it is pushed in.
+ *
+ * @param selected the new selection state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * This method sets the button label. The label may include
+ * the mnemonic character but must not contain line delimiters.
+ *
+ *
+ * Mnemonics are indicated by an '&' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasised in a platform specific
+ * manner. The mnemonic indicator character '&' can be
+ * escaped by doubling it in the string, causing a single
+ * '&' to be displayed.
+ *
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if ((style & SWT.ARROW) != 0) return;
+ this.text = string;
+ int mnemonicIndex = findMnemonicIndex(string);
+ if(mnemonicIndex > 0) {
+ String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&");
+ string = s + string.substring(mnemonicIndex).replaceAll("&&", "&");
+ mnemonicIndex -= mnemonicIndex - 1 - s.length();
+ mnemonicIndex--;
+ } else {
+ string = string.replaceAll("&&", "&");
+ }
+ CButton cButton = (CButton)handle;
+ cButton.setText(string);
+ if(mnemonicIndex >= 0) {
+ cButton.setMnemonic(string.charAt(mnemonicIndex));
+ }
+ cButton.setDisplayedMnemonicIndex(mnemonicIndex);
+}
+
+//int widgetStyle () {
+// int bits = super.widgetStyle ();
+// if ((style & SWT.FLAT) != 0) bits |= OS.BS_FLAT;
+// if ((style & SWT.ARROW) != 0) return bits | OS.BS_OWNERDRAW;
+// if ((style & SWT.LEFT) != 0) bits |= OS.BS_LEFT;
+// if ((style & SWT.CENTER) != 0) bits |= OS.BS_CENTER;
+// if ((style & SWT.RIGHT) != 0) bits |= OS.BS_RIGHT;
+// if ((style & SWT.PUSH) != 0) return bits | OS.BS_PUSHBUTTON | OS.WS_TABSTOP;
+// if ((style & SWT.CHECK) != 0) return bits | OS.BS_CHECKBOX | OS.WS_TABSTOP;
+// if ((style & SWT.RADIO) != 0) return bits | OS.BS_RADIOBUTTON;
+// if ((style & SWT.TOGGLE) != 0) return bits | OS.BS_PUSHLIKE | OS.BS_CHECKBOX;
+// return bits | OS.BS_PUSHBUTTON | OS.WS_TABSTOP;
+//}
+//
+//TCHAR windowClass () {
+// return ButtonClass;
+//}
+//
+//int windowProc () {
+// return ButtonProc;
+//}
+//
+//LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+// LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+// if (result != null) return result;
+// if ((style & SWT.ARROW) != 0) {
+// return new LRESULT (OS.DLGC_STATIC);
+// }
+// return result;
+//}
+//
+//LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+// LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+// if ((style & SWT.PUSH) != 0 && getDefault ()) {
+// menuShell ().setDefaultButton (null, false);
+// }
+// return result;
+//}
+//
+//LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+// if (ignoreMouse) return null;
+// return super.WM_LBUTTONDOWN (wParam, lParam);
+//}
+//
+//LRESULT WM_LBUTTONUP (int wParam, int lParam) {
+// if (ignoreMouse) return null;
+// return super.WM_LBUTTONUP (wParam, lParam);
+//}
+//
+//LRESULT WM_SETFOCUS (int wParam, int lParam) {
+// /*
+// * Feature in Windows. When Windows sets focus to
+// * a radio button, it sets the WM_TABSTOP style.
+// * This is undocumented and unwanted. The fix is
+// * to save and restore the window style bits.
+// */
+// int bits = 0;
+// if ((style & SWT.RADIO) != 0) {
+// bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// }
+// LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+// if ((style & SWT.RADIO) != 0) {
+// OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+// }
+// if ((style & SWT.PUSH) != 0) {
+// menuShell ().setDefaultButton (this, false);
+// }
+// return result;
+//}
+//
+//LRESULT wmColorChild (int wParam, int lParam) {
+// LRESULT result = super.wmColorChild (wParam, lParam);
+// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+// Control control = findThemeControl ();
+// if (control != null) {
+// OS.SetBkMode (wParam, OS.TRANSPARENT);
+// RECT rect = new RECT ();
+// OS.GetClientRect (control.handle, rect);
+// OS.MapWindowPoints (control.handle, handle, rect, 2);
+// control.drawThemeBackground (wParam, rect);
+// return new LRESULT (OS.GetStockObject (OS.NULL_BRUSH));
+// }
+// }
+// return result;
+//}
+//
+//LRESULT wmCommandChild (int wParam, int lParam) {
+// int code = wParam >> 16;
+// switch (code) {
+// case OS.BN_CLICKED:
+// case OS.BN_DOUBLECLICKED:
+// if ((style & (SWT.CHECK | SWT.TOGGLE)) != 0) {
+// setSelection (!getSelection ());
+// } else {
+// if ((style & SWT.RADIO) != 0) {
+// if ((parent.getStyle () & SWT.NO_RADIO_GROUP) != 0) {
+// setSelection (!getSelection ());
+// } else {
+// selectRadio ();
+// }
+// }
+// }
+// postEvent (SWT.Selection);
+// }
+// return super.wmCommandChild (wParam, lParam);
+//}
+//
+//LRESULT wmDrawChild (int wParam, int lParam) {
+// if ((style & SWT.ARROW) == 0) return super.wmDrawChild (wParam, lParam);
+// DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
+// OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
+// RECT rect = new RECT ();
+// OS.SetRect (rect, struct.left, struct.top, struct.right, struct.bottom);
+// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+// int hTheme = OS.OpenThemeData (handle, SCROLLBAR);
+// int iStateId = OS.ABS_LEFTNORMAL;
+// switch (style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) {
+// case SWT.UP: iStateId = OS.ABS_UPNORMAL; break;
+// case SWT.DOWN: iStateId = OS.ABS_DOWNNORMAL; break;
+// case SWT.LEFT: iStateId = OS.ABS_LEFTNORMAL; break;
+// case SWT.RIGHT: iStateId = OS.ABS_RIGHTNORMAL; break;
+// }
+// /*
+// * NOTE: The normal, hot, pressed and disabled state is
+// * computed relying on the fact that the increment between
+// * the direction states is invariant (always separated by 4).
+// */
+// if (!getEnabled ()) iStateId += OS.ABS_UPDISABLED - OS.ABS_UPNORMAL;
+// if ((struct.itemState & OS.ODS_SELECTED) != 0) iStateId += OS.ABS_UPPRESSED - OS.ABS_UPNORMAL;
+// OS.DrawThemeBackground (hTheme, struct.hDC, OS.SBP_ARROWBTN, iStateId, rect, null);
+// OS.CloseThemeData (hTheme);
+// } else {
+// int uState = OS.DFCS_SCROLLLEFT;
+// switch (style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) {
+// case SWT.UP: uState = OS.DFCS_SCROLLUP; break;
+// case SWT.DOWN: uState = OS.DFCS_SCROLLDOWN; break;
+// case SWT.LEFT: uState = OS.DFCS_SCROLLLEFT; break;
+// case SWT.RIGHT: uState = OS.DFCS_SCROLLRIGHT; break;
+// }
+// if (!getEnabled ()) uState |= OS.DFCS_INACTIVE;
+// if ((style & SWT.FLAT) == SWT.FLAT) uState |= OS.DFCS_FLAT;
+// if ((struct.itemState & OS.ODS_SELECTED) != 0) uState |= OS.DFCS_PUSHED;
+// OS.DrawFrameControl (struct.hDC, rect, OS.DFC_SCROLL, uState);
+// }
+// return null;
+//}
+
+@Override
+public void processEvent(AWTEvent e) {
+ int id = e.getID();
+ switch(id) {
+ case ActionEvent.ACTION_PERFORMED: if((style & SWT.RADIO) == 0 && (isAdjustingSelection || !hooks(SWT.Selection))) { super.processEvent(e); return; } break;
+ case ItemEvent.ITEM_STATE_CHANGED: if(isAdjustingSelection || !hooks(SWT.Selection)) { super.processEvent(e); return; } break;
+ case KeyEvent.KEY_PRESSED:
+ if((style & SWT.RADIO) != 0) {
+ switch(((KeyEvent)e).getKeyCode()) {
+ case KeyEvent.VK_UP:
+ case KeyEvent.VK_LEFT:
+ case KeyEvent.VK_DOWN:
+ case KeyEvent.VK_RIGHT:
+ break;
+ default:
+ super.processEvent(e);
+ return;
+ }
+ }
+ break;
+ default: { super.processEvent(e); return; }
+ }
+ if(isDisposed()) {
+ super.processEvent(e);
+ return;
+ }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ switch(id) {
+ case ActionEvent.ACTION_PERFORMED:
+ if((style & SWT.RADIO) != 0) {
+ if(!getSelection()) {
+ ((CButton)handle).setSelected(true);
+ }
+ if((parent.getStyle () & SWT.NO_RADIO_GROUP) == 0) {
+ Component[] components = handle.getParent().getComponents();
+ for(int i=0; i
+ *
Styles:
+ *
(none)
+ *
Events:
+ *
(none)
+ *
+ *
+ * This class may be subclassed by custom control implementors
+ * who are building controls that are not constructed
+ * from aggregates of other controls. That is, they are either
+ * painted using SWT graphics calls or are handled by native
+ * methods.
+ *
+ *
+ * @see Composite
+ */
+
+public class Canvas extends Composite {
+ Caret caret;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Canvas () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Canvas (Composite parent, int style) {
+ super (parent, style);
+}
+
+///*
+//* Not currently used.
+//*/
+//void clearArea (int x, int y, int width, int height) {
+// checkWidget ();
+// if (OS.IsWindowVisible (handle)) return;
+// RECT rect = new RECT ();
+// OS.SetRect (rect, x, y, x + width, y + height);
+// int hDC = OS.GetDCEx (handle, 0, OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS);
+// drawBackground (hDC, rect);
+// OS.ReleaseDC (handle, hDC);
+//}
+
+/**
+ * Returns the caret.
+ *
+ * The caret for the control is automatically hidden
+ * and shown when the control is painted or resized,
+ * when focus is gained or lost and when an the control
+ * is scrolled. To avoid drawing on top of the caret,
+ * the programmer must hide and show the caret when
+ * drawing in the window any other time.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Caret getCaret () {
+ checkWidget ();
+ return caret;
+}
+
+void releaseChildren (boolean destroy) {
+ if (caret != null) {
+ caret.release (false);
+ caret = null;
+ }
+ super.releaseChildren (destroy);
+}
+
+/**
+ * Fills the interior of the rectangle specified by the arguments,
+ * with the receiver's background.
+ *
+ * @param gc the gc where the rectangle is to be filled
+ * @param x the x coordinate of the rectangle to be filled
+ * @param y the y coordinate of the rectangle to be filled
+ * @param width the width of the rectangle to be filled
+ * @param height the height of the rectangle to be filled
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the gc is null
+ *
ERROR_INVALID_ARGUMENT - if the gc has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void drawBackground (GC gc, int x, int y, int width, int height) {
+ checkWidget ();
+ if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ Graphics2D g = gc.handle.getGraphics();
+ if(backgroundImage != null) {
+ Shape clip = g.getClip();
+ g.clipRect(x, y, width, height);
+ Dimension size = handle.getSize();
+ Utils.paintTiledImage(g, new ImageIcon(backgroundImage.handle), 0, 0, size.width, size.height);
+ g.setClip(clip);
+ } else {
+ java.awt.Color oldColor = g.getColor();
+ g.setColor(getBackground().handle);
+ g.fillRect(x, y, width, height);
+ g.setColor(oldColor);
+ }
+}
+
+/**
+ * Scrolls a rectangular area of the receiver by first copying
+ * the source area to the destination and then causing the area
+ * of the source which is not covered by the destination to
+ * be repainted. Children that intersect the rectangle are
+ * optionally moved during the operation. In addition, outstanding
+ * paint events are flushed before the source area is copied to
+ * ensure that the contents of the canvas are drawn correctly.
+ *
+ * @param destX the x coordinate of the destination
+ * @param destY the y coordinate of the destination
+ * @param x the x coordinate of the source
+ * @param y the y coordinate of the source
+ * @param width the width of the area
+ * @param height the height of the area
+ * @param all trueif children should be scrolled, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void scroll (int destX, int destY, int x, int y, int width, int height, boolean all) {
+ checkWidget ();
+// forceResize ();
+ boolean isFocus = caret != null && caret.isFocusCaret ();
+ if (isFocus) caret.killFocus ();
+// handle.repaint();
+ Container clientArea = ((CControl)handle).getClientArea();
+ java.awt.Graphics g = clientArea.getGraphics();
+ int dx = destX - x;
+ int dy = destY - y;
+ g.copyArea(x, y, width, height, dx, dy);
+ java.awt.Dimension size = clientArea.getSize();
+ if(dx < 0) {
+ clientArea.repaint(size.width + dx, 0, -dx, size.height);
+ } else if(dx > 0) {
+ clientArea.repaint(0, 0, dx, size.height);
+ }
+ if(dy < 0) {
+ clientArea.repaint(0, size.height + dy, size.width, -dy);
+ } else if(dy > 0) {
+ clientArea.repaint(0, 0, size.width, dy);
+ }
+// RECT sourceRect = new RECT ();
+// OS.SetRect (sourceRect, x, y, x + width, y + height);
+// RECT clientRect = new RECT ();
+// OS.GetClientRect (handle, clientRect);
+// if (OS.IntersectRect (clientRect, sourceRect, clientRect)) {
+// if (OS.IsWinCE) {
+// OS.UpdateWindow (handle);
+// } else {
+// int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+// OS.RedrawWindow (handle, null, 0, flags);
+// }
+// }
+ int deltaX = destX - x, deltaY = destY - y;
+// int flags = OS.SW_INVALIDATE | OS.SW_ERASE;
+// /*
+// * Feature in Windows. If any child in the widget tree partially
+// * intersects the scrolling rectangle, Windows moves the child
+// * and copies the bits that intersect the scrolling rectangle but
+// * does not redraw the child.
+// *
+// * Feature in Windows. When any child in the widget tree does not
+// * intersect the scrolling rectangle but the parent does intersect,
+// * Windows does not move the child. This is the documented (but
+// * strange) Windows behavior.
+// *
+// * The fix is to not use SW_SCROLLCHILDREN and move the children
+// * explicitly after scrolling.
+// */
+//// if (all) flags |= OS.SW_SCROLLCHILDREN;
+// OS.ScrollWindowEx (handle, deltaX, deltaY, sourceRect, null, 0, null, flags);
+ if (all) {
+ Control [] children = _getChildren ();
+ for (int i=0; i= Math.max (x, rect.x) &&
+ Math.min (y + height, rect.y + rect.height) >= Math.max (y, rect.y)) {
+ child.setLocation (rect.x + deltaX, rect.y + deltaY);
+ }
+ }
+ }
+ if (isFocus) caret.setFocus ();
+}
+
+/**
+ * Sets the receiver's caret.
+ *
+ * The caret for the control is automatically hidden
+ * and shown when the control is painted or resized,
+ * when focus is gained or lost and when an the control
+ * is scrolled. To avoid drawing on top of the caret,
+ * the programmer must hide and show the caret when
+ * drawing in the window any other time.
+ *
+ * @param caret the new caret for the receiver, may be null
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the caret has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setCaret (Caret caret) {
+ checkWidget ();
+ Caret newCaret = caret;
+ Caret oldCaret = this.caret;
+ this.caret = newCaret;
+ if (isFocusControl ()) {
+ if (oldCaret != null) oldCaret.killFocus ();
+ if (newCaret != null) {
+ if (newCaret.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ newCaret.setFocus ();
+ }
+ }
+}
+
+public void setFont (Font font) {
+ checkWidget ();
+ if (caret != null) caret.setFont (font);
+ super.setFont (font);
+}
+
+//LRESULT WM_INPUTLANGCHANGE (int wParam, int lParam) {
+// LRESULT result = super.WM_INPUTLANGCHANGE (wParam, lParam);
+// if (caret != null) caret.resizeIME ();
+// return result;
+//}
+//
+//LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+// LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+// if (caret != null) caret.killFocus ();
+// return result;
+//}
+//
+//LRESULT WM_SETFOCUS (int wParam, int lParam) {
+// LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+// if (caret != null) caret.setFocus ();
+// return result;
+//}
+//
+//LRESULT WM_SIZE (int wParam, int lParam) {
+// LRESULT result = super.WM_SIZE (wParam, lParam);
+// if (caret != null) caret.resizeIME ();
+// return result;
+//}
+//
+//LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) {
+// LRESULT result = super.WM_WINDOWPOSCHANGED (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Bug in Windows. When a window with style WS_EX_LAYOUTRTL
+// * that contains a caret is resized, Windows does not move the
+// * caret in relation to the mirrored origin in the top right.
+// * The fix is to hide the caret in WM_WINDOWPOSCHANGING and
+// * show the caret in WM_WINDOWPOSCHANGED.
+// */
+// boolean isFocus = (style & SWT.RIGHT_TO_LEFT) != 0 && caret != null && caret.isFocusCaret ();
+// if (isFocus) caret.setFocus ();
+// return result;
+//}
+//
+//LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+// LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Bug in Windows. When a window with style WS_EX_LAYOUTRTL
+// * that contains a caret is resized, Windows does not move the
+// * caret in relation to the mirrored origin in the top right.
+// * The fix is to hide the caret in WM_WINDOWPOSCHANGING and
+// * show the caret in WM_WINDOWPOSCHANGED.
+// */
+// boolean isFocus = (style & SWT.RIGHT_TO_LEFT) != 0 && caret != null && caret.isFocusCaret ();
+// if (isFocus) caret.killFocus ();
+// return result;
+//}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Caret.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Caret.java
new file mode 100644
index 00000000000..2177f1fbcd8
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Caret.java
@@ -0,0 +1,641 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.Timer;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.swing.LookAndFeelUtils;
+
+/**
+ * Instances of this class provide an i-beam that is typically used
+ * as the insertion point for text.
+ *
+ *
Styles:
+ *
(none)
+ *
Events:
+ *
(none)
+ *
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+
+public class Caret extends Widget {
+ Canvas parent;
+ int x, y, width, height;
+ boolean moved, resized;
+ boolean isVisible;
+ Image image;
+ Font font;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Caret (Canvas parent, int style) {
+ super (parent, style);
+ this.parent = parent;
+ createWidget ();
+}
+
+void createWidget () {
+ isVisible = true;
+ if (parent.getCaret () == null) {
+ parent.setCaret (this);
+ }
+}
+
+Timer timer = new Timer (LookAndFeelUtils.getCaretBlinkRate(), new ActionListener () {
+ public void actionPerformed (ActionEvent e) {
+ Caret.this.blink = !Caret.this.blink;
+ if (Caret.this.parent != null && Caret.this.parent.caret == Caret.this) {
+ // XXX redraw rect is not correct. for now, redraw all.
+ // Rectangle r = Caret.this.getBounds();
+ // Caret.this.parent.redraw(x, r.y, r.width, r.height, true);
+ // redraw causes GC to throw exceptions in some conditions. Let's directly call the Swing component
+ Caret.this.parent.handle.repaint();
+ } else {
+ timer.stop();
+ }
+ }
+}) {
+ public void stop() {
+ super.stop();
+ blink = true;
+ if(Caret.this.parent != null) {
+// Caret.this.parent.redraw ();
+ Caret.this.parent.handle.repaint();
+ }
+ }
+};
+
+private boolean blink;
+
+void paintCaret (GC gc) {
+ if (blink && isVisible()) {
+ if(display == null) return;
+ gc.setXORMode (true);
+ gc.setBackground (display.getSystemColor (SWT.COLOR_BLACK));
+ if (image != null) {
+ gc.drawImage (image, x, y);
+ }
+ gc.fillRectangle (x, y, Math.max(1, width), height);
+ gc.setXORMode (false);
+ }
+}
+
+java.awt.Font defaultFont () {
+ return parent.handle.getFont ();
+// int hwnd = parent.handle;
+// int hwndIME = OS.ImmGetDefaultIMEWnd (hwnd);
+// int hFont = 0;
+// if (hwndIME != 0) {
+// hFont = OS.SendMessage (hwndIME, OS.WM_GETFONT, 0, 0);
+// }
+// if (hFont == 0) {
+// hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+// }
+// if (hFont == 0) return parent.defaultFont ();
+// return hFont;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent (or its display if its parent is null).
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Rectangle getBounds () {
+ checkWidget();
+ if (image != null) {
+ Rectangle rect = image.getBounds ();
+ return new Rectangle (x, y, rect.width, rect.height);
+ }
+ return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Font getFont () {
+ checkWidget ();
+ if (font == null) {
+ return Font.swing_new (display, defaultFont ());
+ }
+ return font;
+// checkWidget();
+// if (font == null) {
+// int hFont = defaultFont ();
+// return Font.win32_new (display, hFont);
+// }
+// return font;
+}
+
+/**
+ * Returns the image that the receiver will use to paint the caret.
+ *
+ * @return the receiver's image
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Image getImage () {
+ checkWidget();
+ return image;
+}
+
+/**
+ * Returns a point describing the receiver's location relative
+ * to its parent (or its display if its parent is null).
+ *
+ * @return the receiver's location
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getLocation () {
+ checkWidget();
+ return new Point (x, y);
+}
+
+/**
+ * Returns the receiver's parent, which must be a Canvas.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Canvas getParent () {
+ checkWidget();
+ return parent;
+}
+
+/**
+ * Returns a point describing the receiver's size.
+ *
+ * @return the receiver's size
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getSize () {
+ checkWidget();
+ if (image != null) {
+ Rectangle rect = image.getBounds ();
+ return new Point (rect.width, rect.height);
+ }
+ return new Point (width, height);
+}
+
+/**
+ * Returns true if the receiver is visible, and
+ * false otherwise.
+ *
+ * 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.
+ *
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getVisible () {
+ checkWidget();
+ return isVisible;
+}
+
+boolean hasFocus () {
+ return parent.isFocusControl();
+// return parent.handle == OS.GetFocus ();
+}
+
+boolean isFocusCaret () {
+ return parent.caret == this && hasFocus ();
+}
+
+/**
+ * Returns true if the receiver is visible and all
+ * of the receiver's ancestors are visible and false
+ * otherwise.
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getVisible
+ */
+public boolean isVisible () {
+ checkWidget();
+ return isVisible && parent.isVisible () && hasFocus ();
+}
+
+void killFocus () {
+ timer.stop ();
+// OS.DestroyCaret ();
+// if (font != null) restoreIMEFont ();
+}
+
+void move () {
+// moved = false;
+// if (!OS.SetCaretPos (x, y)) return;
+// resizeIME ();
+ blink = true;
+}
+
+void resizeIME () {
+//TODO
+// if (!OS.IsDBLocale) return;
+// POINT ptCurrentPos = new POINT ();
+// if (!OS.GetCaretPos (ptCurrentPos)) return;
+// int hwnd = parent.handle;
+// RECT rect = new RECT ();
+// OS.GetClientRect (hwnd, rect);
+// COMPOSITIONFORM lpCompForm = new COMPOSITIONFORM ();
+// lpCompForm.dwStyle = OS.CFS_RECT;
+// lpCompForm.x = ptCurrentPos.x;
+// lpCompForm.y = ptCurrentPos.y;
+// lpCompForm.left = rect.left;
+// lpCompForm.right = rect.right;
+// lpCompForm.top = rect.top;
+// lpCompForm.bottom = rect.bottom;
+// int hIMC = OS.ImmGetContext (hwnd);
+// OS.ImmSetCompositionWindow (hIMC, lpCompForm);
+// OS.ImmReleaseContext (hwnd, hIMC);
+}
+
+void releaseParent () {
+ super.releaseParent ();
+ if (this == parent.getCaret ()) parent.setCaret (null);
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ parent = null;
+ image = null;
+ font = null;
+// oldFont = null;
+}
+
+void resize () {
+// TODO
+// resized = false;
+// int hwnd = parent.handle;
+// OS.DestroyCaret ();
+// int hBitmap = image != null ? image.handle : 0;
+// OS.CreateCaret (hwnd, hBitmap, width, height);
+// OS.SetCaretPos (x, y);
+// OS.ShowCaret (hwnd);
+// move ();
+}
+
+void restoreIMEFont () {
+//TODO
+// if (!OS.IsDBLocale) return;
+// if (oldFont == null) return;
+// int hwnd = parent.handle;
+// int hIMC = OS.ImmGetContext (hwnd);
+// OS.ImmSetCompositionFont (hIMC, oldFont);
+// OS.ImmReleaseContext (hwnd, hIMC);
+// oldFont = null;
+}
+
+void saveIMEFont () {
+//TODO
+// if (!OS.IsDBLocale) return;
+// if (oldFont != null) return;
+// int hwnd = parent.handle;
+// int hIMC = OS.ImmGetContext (hwnd);
+// oldFont = OS.IsUnicode ? (LOGFONT) new LOGFONTW () : new LOGFONTA ();
+// if (!OS.ImmGetCompositionFont (hIMC, oldFont)) oldFont = null;
+// OS.ImmReleaseContext (hwnd, hIMC);
+}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the arguments. The x and
+ * y arguments are relative to the receiver's
+ * parent (or its display if its parent is null).
+ *
+ * @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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setBounds (int x, int y, int width, int height) {
+ checkWidget();
+ boolean samePosition = this.x == x && this.y == y;
+ boolean sameExtent = this.width == width && this.height == height;
+ if (samePosition && sameExtent) return;
+ timer.stop();
+ this.x = x; this.y = y;
+ this.width = width; this.height = height;
+ if (sameExtent) {
+ moved = true;
+ if (isVisible && hasFocus ()) move ();
+ } else {
+ resized = true;
+ if (isVisible && hasFocus ()) resize ();
+ }
+ timer.start();
+}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the argument. The x and
+ * y fields of the rectangle are relative to
+ * the receiver's parent (or its display if its parent is null).
+ *
+ * @param rect the new bounds for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setBounds (Rectangle rect) {
+ if (rect == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setBounds (rect.x, rect.y, rect.width, rect.height);
+}
+
+void setFocus () {
+ timer.start ();
+//TODO
+// int hwnd = parent.handle;
+// int hBitmap = 0;
+// if (image != null) hBitmap = image.handle;
+// OS.CreateCaret (hwnd, hBitmap, width, height);
+// move ();
+// if (OS.IsDBLocale) {
+// int hFont = 0;
+// if (font != null) hFont = font.handle;
+// if (hFont == 0) hFont = defaultFont ();
+// saveIMEFont ();
+// setIMEFont (hFont);
+// }
+// if (isVisible) OS.ShowCaret (hwnd);
+}
+
+/**
+ * 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
+ *
ERROR_INVALID_ARGUMENT - if the font has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setFont (Font font) {
+//TODO
+// checkWidget();
+// if (font != null && font.isDisposed ()) {
+// error (SWT.ERROR_INVALID_ARGUMENT);
+// }
+// this.font = font;
+// if (isVisible && hasFocus ()) {
+// int hFont = 0;
+// if (font != null) hFont = font.handle;
+// if (hFont == 0) hFont = defaultFont ();
+// saveIMEFont ();
+// setIMEFont (hFont);
+// }
+}
+
+/**
+ * Sets the image that the receiver will use to paint the caret
+ * to the image specified by the argument, or to the default
+ * which is a filled rectangle if the argument is null
+ *
+ * @param image the new image (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setImage (Image image) {
+ checkWidget();
+ if (image != null && image.isDisposed ()) {
+ error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.image = image;
+ if (isVisible && hasFocus ()) resize ();
+}
+
+void setIMEFont (int hFont) {
+//TODO
+// if (!OS.IsDBLocale) return;
+// LOGFONT logFont = OS.IsUnicode ? (LOGFONT) new LOGFONTW () : new LOGFONTA ();
+// if (OS.GetObject (hFont, LOGFONT.sizeof, logFont) != 0) {
+// int hwnd = parent.handle;
+// int hIMC = OS.ImmGetContext (hwnd);
+// OS.ImmSetCompositionFont (hIMC, logFont);
+// OS.ImmReleaseContext (hwnd, hIMC);
+// }
+}
+
+/**
+ * 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).
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setLocation (int x, int y) {
+ checkWidget();
+ if (this.x == x && this.y == y) return;
+ timer.stop();
+ this.x = x; this.y = y;
+ moved = true;
+ if (isVisible && hasFocus ()) move ();
+ timer.start();
+}
+
+/**
+ * Sets the receiver's location to the point specified by
+ * the argument which is relative to the receiver's
+ * parent (or its display if its parent is null).
+ *
+ * @param location the new location for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setLocation (Point location) {
+ checkWidget();
+ if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setLocation (location.x, location.y);
+}
+
+/**
+ * Sets the receiver's size to the point specified by the arguments.
+ *
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSize (int width, int height) {
+ checkWidget();
+ if (this.width == width && this.height == height) return;
+ this.width = width; this.height = height;
+ resized = true;
+ if (isVisible && hasFocus ()) resize ();
+}
+
+/**
+ * Sets the receiver's size to the point specified by the argument.
+ *
+ * @param size the new extent for the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSize (Point size) {
+ checkWidget();
+ if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSize (size.x, size.y);
+}
+
+/**
+ * Marks the receiver as visible if the argument is true,
+ * and marks it invisible otherwise.
+ *
+ * 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.
+ *
+ *
+ * @param visible the new visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setVisible (boolean visible) {
+ checkWidget ();
+ if (visible == isVisible) return;
+ isVisible = visible;
+//TODO
+// checkWidget();
+// if (visible == isVisible) return;
+// isVisible = visible;
+// int hwnd = parent.handle;
+// if (OS.GetFocus () != hwnd) return;
+// if (!isVisible) {
+// OS.HideCaret (hwnd);
+// } else {
+// if (resized) {
+// resize ();
+// } else {
+// if (moved) move ();
+// }
+// OS.ShowCaret (hwnd);
+// }
+ // TODO activate or deactivate caret timer.
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ColorDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ColorDialog.java
new file mode 100644
index 00000000000..4a94f00663d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ColorDialog.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import javax.swing.JColorChooser;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * Instances of this class allow the user to select a color
+ * from a predefined set of available colors.
+ *
+ *
Styles:
+ *
(none)
+ *
Events:
+ *
(none)
+ *
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+
+public class ColorDialog extends Dialog {
+ RGB rgb;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a composite control which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ColorDialog (Shell parent) {
+ this (parent, SWT.PRIMARY_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ColorDialog (Shell parent, int style) {
+ super (parent, style);
+ checkSubclass ();
+}
+
+/**
+ * Returns the currently selected color in the receiver.
+ *
+ * @return the RGB value for the selected color, may be null
+ *
+ * @see PaletteData#getRGBs
+ */
+public RGB getRGB () {
+ return rgb;
+}
+
+/**
+ * Makes the receiver visible and brings it to the front
+ * of the display.
+ *
+ * @return the selected color, or null if the dialog was
+ * cancelled, no color was selected, or an error
+ * occurred
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public RGB open () {
+// JColorChooser cc = new JColorChooser();
+// cc.addPropertyChangeListener(new PropertyChangeListener() {
+// public void propertyChange(PropertyChangeEvent e) {
+// if("color".equals(e.getPropertyName())) {
+// Color color = (Color)e.getNewValue();
+// if(color != null) {
+// rgb = new RGB(color.getRed(), color.getGreen(), color.getBlue());
+// }
+// }
+// }
+// });
+ java.awt.Color color = null;
+ if(rgb != null) {
+ color = new java.awt.Color(rgb.red, rgb.green, rgb.blue);
+ }
+ color = JColorChooser.showDialog(getParent().handle, null, color);
+ if(color == null) return null;
+ rgb = new RGB(color.getRed(), color.getGreen(), color.getBlue());
+ return rgb;
+}
+
+/**
+ * Sets the receiver's selected color to be the argument.
+ *
+ * @param rgb the new RGB value for the selected color, may be
+ * null to let the platform select a default when
+ * open() is called
+ * @see PaletteData#getRGBs
+ */
+public void setRGB (RGB rgb) {
+ this.rgb = rgb;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Combo.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Combo.java
new file mode 100644
index 00000000000..584caaac25c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Combo.java
@@ -0,0 +1,1176 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.AWTEvent;
+import java.awt.ComponentOrientation;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ItemEvent;
+
+import javax.swing.JButton;
+import javax.swing.RootPaneContainer;
+
+import org.eclipse.swt.internal.swing.CCombo;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+import org.eclipse.swt.internal.swing.Utils;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class are controls that allow the user
+ * to choose an item from a list of items, or optionally
+ * enter a new value by typing it into an editable text
+ * field. Often, Combos are used in the same place
+ * where a single selection List widget could
+ * be used but space is limited. A Combo takes
+ * less space than a List widget and shows
+ * similar information.
+ *
+ * Note: Since Combos can contain both a list
+ * and an editable text field, it is possible to confuse methods
+ * which access one versus the other (compare for example,
+ * clearSelection() and deselectAll()).
+ * The API documentation is careful to indicate either "the
+ * receiver's list" or the "the receiver's text field" to
+ * distinguish between the two cases.
+ *
+ * Note that although this class is a subclass of Composite,
+ * it does not make sense to add children to it, or set a layout on it.
+ *
+ *
+ *
Styles:
+ *
DROP_DOWN, READ_ONLY, SIMPLE
+ *
Events:
+ *
DefaultSelection, Modify, Selection
+ *
+ *
+ * Note: Only one of the styles DROP_DOWN and SIMPLE may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @see List
+ */
+
+public class Combo extends Composite {
+
+ /**
+ * the operating system limit for the number of characters
+ * that the text field in an instance of this class can hold
+ */
+ public static final int LIMIT;
+
+ /*
+ * These values can be different on different platforms.
+ * Therefore they are not initialized in the declaration
+ * to stop the compiler from inlining.
+ */
+ static {
+ LIMIT = 0x7FFFFFFF;
+ }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#DROP_DOWN
+ * @see SWT#READ_ONLY
+ * @see SWT#SIMPLE
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Combo (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param string the new item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #add(String,int)
+ */
+public void add (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ isAdjustingSelection = true;
+ ((CCombo)handle).addItem(string);
+ isAdjustingSelection = false;
+}
+
+/**
+ * Adds the argument to the receiver's list at the given
+ * zero-relative index.
+ *
+ * Note: To add an item at the end of the list, use the
+ * result of calling getItemCount() as the
+ * index or use add(String).
+ *
+ *
+ * @param string the new item
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #add(String)
+ */
+public void add (String string, int index) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ isAdjustingSelection = true;
+ ((CCombo)handle).insertElementAt(string, index);
+ isAdjustingSelection = false;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is modified, by sending
+ * it one of the messages defined in the ModifyListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ModifyListener
+ * @see #removeModifyListener
+ */
+public void addModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Modify, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's selection changes, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * widgetSelected is called when the combo's list selection changes.
+ * widgetDefaultSelected is typically called when ENTER is pressed the combo's text area.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is verified, by sending
+ * it one of the messages defined in the VerifyListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see VerifyListener
+ * @see #removeVerifyListener
+ *
+ * @since 3.1
+ */
+public void addVerifyListener (VerifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Verify, typedListener);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+static int checkStyle (int style) {
+ /*
+ * Even though it is legal to create this widget
+ * with scroll bars, they serve no useful purpose
+ * because they do not automatically scroll the
+ * widget's client area. The fix is to clear
+ * the SWT style.
+ */
+ style &= ~(SWT.H_SCROLL | SWT.V_SCROLL);
+ style = checkBits (style, SWT.DROP_DOWN, SWT.SIMPLE, 0, 0, 0, 0);
+ if ((style & SWT.SIMPLE) != 0) return style & ~SWT.READ_ONLY;
+ return style;
+}
+
+/**
+ * Sets the selection in the receiver's text field to an empty
+ * selection starting just before the first character. If the
+ * text field is editable, this has the effect of placing the
+ * i-beam at the start of the text.
+ *
+ * Note: To clear the selected items in the receiver's list,
+ * use deselectAll().
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * The current selection is first copied to the
+ * clipboard and then deleted from the widget.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.1
+ */
+public void cut () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return;
+ ((CCombo)handle).cutEditor();
+}
+
+/**
+ * Deselects the item at the given zero-relative index in the receiver's
+ * list. If the item at the index was already deselected, it remains
+ * deselected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to deselect
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void deselect (int index) {
+ checkWidget ();
+ CCombo cCombo = (CCombo)handle;
+ if(index == cCombo.getSelectedIndex()) {
+ isAdjustingSelection = true;
+ cCombo.setSelectedIndex(-1);
+ isAdjustingSelection = false;
+ sendEvent (SWT.Modify);
+ }
+ // widget could be disposed at this point
+}
+
+/**
+ * Deselects all selected items in the receiver's list.
+ *
+ * Note: To clear the selection in the receiver's text field,
+ * use clearSelection().
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #clearSelection
+ */
+public void deselectAll () {
+ checkWidget ();
+ isAdjustingSelection = true;
+ ((CCombo)handle).clearEditorSelection();
+ isAdjustingSelection = false;
+ sendEvent (SWT.Modify);
+ // widget could be disposed at this point
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver's list. Throws an exception if the index is out
+ * of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getItem (int index) {
+ checkWidget ();
+ int count = getItemCount();
+ if (!(0 <= index && index < count)) error (SWT.ERROR_CANNOT_GET_ITEM);
+ try {
+ return (String)((CCombo)handle).getItemAt(index);
+ } catch(Exception e) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ return "";
+}
+
+/**
+ * Returns the number of items contained in the receiver's list.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemCount () {
+ checkWidget ();
+ return ((CCombo)handle).getItemCount();
+}
+
+/**
+ * Returns the height of the area which would be used to
+ * display one of the items in the receiver's list.
+ *
+ * @return the height of one item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemHeight () {
+ checkWidget ();
+ Utils.notImplemented(); return 15;
+// int result = OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, 0, 0);
+// if (result == OS.CB_ERR) error (SWT.ERROR_CANNOT_GET_ITEM_HEIGHT);
+// return result;
+}
+
+/**
+ * Returns a (possibly empty) array of Strings which are
+ * the items in the receiver's list.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the items in the receiver's list
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String [] getItems () {
+ checkWidget ();
+ int count = getItemCount ();
+ String [] result = new String [count];
+ for (int i=0; i
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.1.2
+ */
+public int getOrientation () {
+ checkWidget();
+ return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+}
+
+/**
+ * Returns a Point whose x coordinate is the
+ * character position representing the start of the selection
+ * in the receiver's text field, and whose y coordinate is the
+ * character position representing the end of the selection.
+ * An "empty" selection is indicated by the x and y coordinates
+ * having the same value.
+ *
+ * Indexing is zero based. The range of a selection is from
+ * 0..N where N is the number of characters in the widget.
+ *
+ *
+ * @return a point representing the selection start and end
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getSelection () {
+ checkWidget ();
+ if ((style & SWT.DROP_DOWN) != 0 && (style & SWT.READ_ONLY) != 0) {
+ return new Point (0, getText().length());
+ }
+ CCombo cCombo = (CCombo)handle;
+ return new Point (cCombo.getEditorSelectionStart(), cCombo.getEditorSelectionEnd());
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver's list, or -1 if no item is selected.
+ *
+ * @return the index of the selected item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelectionIndex () {
+ checkWidget ();
+ return ((CCombo)handle).getSelectedIndex();
+}
+
+/**
+ * Returns a string containing a copy of the contents of the
+ * receiver's text field, or an empty string if there are no
+ * contents.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getText () {
+ checkWidget ();
+ return ((CCombo)handle).getEditorText();
+}
+
+/**
+ * Returns the height of the receivers's text field.
+ *
+ * @return the text height
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getTextHeight () {
+ checkWidget ();
+ return ((CCombo)handle).getEditorSize().height;
+}
+
+/**
+ * Returns the maximum number of characters that the receiver's
+ * text field is capable of holding. If this has not been changed
+ * by setTextLimit(), it will be the constant
+ * Combo.LIMIT.
+ *
+ * @return the text limit
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #LIMIT
+ */
+public int getTextLimit () {
+ checkWidget ();
+ return ((CCombo)handle).getEditorTextLimit();
+}
+
+/**
+ * Gets the number of items that are visible in the drop
+ * down portion of the receiver's list.
+ *
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ *
+ *
+ * @return the number of items that are visible
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public int getVisibleItemCount () {
+ checkWidget ();
+ return ((CCombo)handle).getMaximumRowCount();
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param string the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int indexOf (String string) {
+ return indexOf (string, 0);
+}
+
+/**
+ * Searches the receiver's list starting at the given,
+ * zero-relative index until an item is found that is equal
+ * to the argument, and returns the index of that item. If
+ * no item is found or the starting index is out of range,
+ * returns -1.
+ *
+ * @param string the search item
+ * @param start the zero-relative index at which to begin the search
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int indexOf (String string, int start) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int count = getItemCount ();
+ for (int i=start; i
+ * The selected text is deleted from the widget
+ * and new text inserted from the clipboard.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.1
+ */
+public void paste () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return;
+ ((CCombo)handle).pasteEditor();
+}
+
+/**
+ * Removes the item from the receiver's list at the given
+ * zero-relative index.
+ *
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void remove (int index) {
+ checkWidget ();
+ int count = getItemCount();
+ if (!(0 <= index && index < count)) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ isAdjustingSelection = true;
+ ((CCombo)handle).removeItemAt(index);
+ isAdjustingSelection = false;
+ sendEvent (SWT.Modify);
+}
+
+/**
+ * Removes the items from the receiver's list which are
+ * between the given zero-relative start and end
+ * indices (inclusive).
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void remove (int start, int end) {
+ checkWidget ();
+ if (start > end) return;
+ int count = getItemCount();
+ if (!(0 <= start && start <= end && end < count)) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ isAdjustingSelection = true;
+ CCombo cCombo = (CCombo)handle;
+ for (int i=start; i<=end; i++) {
+ cCombo.removeItemAt(i);
+ }
+ isAdjustingSelection = false;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * until an item is found that is equal to the argument,
+ * and removes that item from the list.
+ *
+ * @param string the item to remove
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
ERROR_INVALID_ARGUMENT - if the string is not found in the list
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void remove (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int index = indexOf (string, 0);
+ if (index == -1) error (SWT.ERROR_INVALID_ARGUMENT);
+ remove (index);
+}
+
+/**
+ * Removes all of the items from the receiver's list and clear the
+ * contents of receiver's text field.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void removeAll () {
+ checkWidget ();
+ isAdjustingSelection = true;
+ ((CCombo)handle).removeAllItems();
+ isAdjustingSelection = false;
+ sendEvent (SWT.Modify);
+ // widget could be disposed at this point
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's text is modified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ModifyListener
+ * @see #addModifyListener
+ */
+public void removeModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Modify, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's selection changes.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is verified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see VerifyListener
+ * @see #addVerifyListener
+ *
+ * @since 3.1
+ */
+public void removeVerifyListener (VerifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Verify, listener);
+}
+
+boolean isAdjustingSelection;
+
+/**
+ * Selects the item at the given zero-relative index in the receiver's
+ * list. If the item at the index was already selected, it remains
+ * selected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void select (int index) {
+ checkWidget ();
+ int count = getItemCount();
+ if (0 <= index && index < count) {
+ CCombo cCombo = (CCombo)handle;
+ if(index != cCombo.getSelectedIndex()) {
+ isAdjustingSelection = true;
+ cCombo.setSelectedIndex(index);
+ isAdjustingSelection = false;
+ sendEvent (SWT.Modify);
+ }
+ }
+}
+
+/**
+ * Sets the text of the item in the receiver's list at the given
+ * zero-relative index to the string argument. This is equivalent
+ * to removing the old item at the index, and then adding the new
+ * item at that index.
+ *
+ * @param index the index for the item
+ * @param string the new text for the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setItem (int index, String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ remove (index);
+ /*
+ * It is possible (but unlikely), that application
+ * code could have disposed the widget in the modify
+ * event that might be sent when the index is removed.
+ * If this happens, just exit.
+ */
+ if (isDisposed ()) return;
+ add (string, index);
+}
+
+/**
+ * Sets the receiver's list to be the given array of items.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the items array is null
+ *
ERROR_INVALID_ARGUMENT - if an item in the items array is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setItems (String [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ for (int i=0; iSWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.1.2
+ */
+public void setOrientation (int orientation) {
+ checkWidget();
+ int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
+ if ((orientation & flags) == 0 || (orientation & flags) == flags) return;
+ style &= ~flags;
+ style |= orientation & flags;
+ ComponentOrientation o;
+ if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+ o = ComponentOrientation.RIGHT_TO_LEFT;
+ } else {
+ o = ComponentOrientation.LEFT_TO_RIGHT;
+ }
+ ((CCombo)handle).setComponentOrientation(o);
+}
+
+/**
+ * Sets the selection in the receiver's text field to the
+ * range specified by the argument whose x coordinate is the
+ * start of the selection and whose y coordinate is the end
+ * of the selection.
+ *
+ * @param selection a point representing the new selection start and end
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (Point selection) {
+ checkWidget ();
+ if (selection == null) error (SWT.ERROR_NULL_ARGUMENT);
+ CCombo cCombo = (CCombo)handle;
+ cCombo.setEditorSelectionStart(selection.x);
+ cCombo.setEditorSelectionEnd(selection.y);
+}
+
+/**
+ * Sets the contents of the receiver's text field to the
+ * given string.
+ *
+ * Note: The text field in a Combo is typically
+ * only capable of displaying a single line of text. Thus,
+ * setting the text to a string containing line breaks or
+ * other special characters will probably cause it to
+ * display incorrectly.
+ *
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if ((style & SWT.READ_ONLY) != 0) {
+ int index = indexOf (string);
+ if (index != -1) select (index);
+ return;
+ }
+ ((CCombo)handle).setEditorText(string);
+ sendEvent (SWT.Modify);
+ // widget could be disposed at this point
+}
+
+/**
+ * Sets the maximum number of characters that the receiver's
+ * text field is capable of holding to be the argument.
+ *
+ * To reset this value to the default, use setTextLimit(Combo.LIMIT).
+ * Specifying a limit value larger than Combo.LIMIT sets the
+ * receiver's limit to Combo.LIMIT.
+ *
+ * @param limit new text limit
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_CANNOT_BE_ZERO - if the limit is zero
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #LIMIT
+ */
+public void setTextLimit (int limit) {
+ checkWidget ();
+ if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
+ ((CCombo)handle).setEditorTextLimit(limit);
+}
+
+/**
+ * Sets the number of items that are visible in the drop
+ * down portion of the receiver's list.
+ *
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ *
+ *
+ * @param count the new number of items to be visible
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public void setVisibleItemCount (int count) {
+ checkWidget ();
+ if (count < 0) return;
+ ((CCombo)handle).setMaximumRowCount(count);
+}
+
+boolean traverseEscape () {
+ if ((style & SWT.DROP_DOWN) != 0) {
+ return ((CCombo)handle).isPopupVisible();
+// if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) != 0) {
+// OS.SendMessage (handle, OS.CB_SHOWDROPDOWN, 0, 0);
+// return true;
+// }
+ }
+ return super.traverseEscape ();
+}
+
+public void processEvent(AWTEvent e) {
+ int id = e.getID();
+ switch(id) {
+ case ActionEvent.ACTION_PERFORMED: if(!hooks(SWT.Traverse) && !hooks(SWT.DefaultSelection)) {
+ super.processEvent(e);
+ JButton defaultButton = ((RootPaneContainer)getShell().handle).getRootPane().getDefaultButton();
+ if(defaultButton != null) {
+ defaultButton.doClick();
+ }
+ return;
+ }
+ break;
+ case ItemEvent.ITEM_STATE_CHANGED: if(!hooks(SWT.Selection) || isAdjustingSelection) { super.processEvent(e); return; } break;
+ default: { super.processEvent(e); return; }
+ }
+ if(isDisposed()) {
+ super.processEvent(e);
+ return;
+ }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ switch(id) {
+ case ActionEvent.ACTION_PERFORMED:
+ Event event = new Event();
+ event.detail = SWT.TRAVERSE_RETURN;
+ sendEvent(SWT.Traverse, event);
+ boolean isSending = true;
+ if(event.doit) {
+ JButton defaultButton = ((RootPaneContainer)getShell().handle).getRootPane().getDefaultButton();
+ if(defaultButton != null) {
+ isSending = false;
+ defaultButton.doClick();
+ }
+ }
+ if(isSending) {
+ sendEvent(SWT.DefaultSelection);
+ }
+ break;
+ case ItemEvent.ITEM_STATE_CHANGED:
+ sendEvent(SWT.Selection);
+ break;
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Composite.java
new file mode 100644
index 00000000000..4f29a12ff80
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Composite.java
@@ -0,0 +1,1428 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.swing.*;
+
+/**
+ * Instances of this class are controls which are capable
+ * of containing other controls.
+ *
+ * Note: The NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS,
+ * and NO_REDRAW_RESIZE styles are intended for use with Canvas.
+ * They can be used with Composite if you are drawing your own, but their
+ * behavior is undefined if they are used with subclasses of Composite other
+ * than Canvas.
+ *
+ * Note: The CENTER style, although undefined for composites, has the
+ * same value as EMBEDDED (which is used to embed widgets from other
+ * widget toolkits into SWT). On some operating systems (GTK, Motif), this may cause
+ * the children of this composite to be obscured. The EMBEDDED style
+ * is for use by other widget toolkits and should normally never be used.
+ *
+ * This class may be subclassed by custom control implementors
+ * who are building controls that are constructed from aggregates
+ * of other controls.
+ *
+ *
+ * @see Canvas
+ */
+
+public class Composite extends Scrollable {
+ Layout layout;
+ int font;
+// WINDOWPOS [] lpwp;
+ Control [] tabList;
+ int layoutCount = 0;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Composite () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed
+ *
ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void changed (Control[] changed) {
+ checkWidget ();
+ if (changed == null) error (SWT.ERROR_INVALID_ARGUMENT);
+ for (int i=0; i 0 || parent == null? this : parent.findDeferredControl ();
+}
+
+//Menu [] findMenus (Control control) {
+// if (control == this) return new Menu [0];
+// Menu result [] = super.findMenus (control);
+// Control [] children = _getChildren ();
+// for (int i=0; iSWT:
+ * INHERIT_NONE, INHERIT_DEFAULT,
+ * INHERTIT_FORCE.
+ *
+ * @return the background mode
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT
+ *
+ * @since 3.2
+ */
+public int getBackgroundMode () {
+ checkWidget ();
+ return backgroundMode;
+}
+
+/**
+ * Returns a (possibly empty) array containing the receiver's children.
+ * Children are returned in the order that they are drawn. The topmost
+ * control appears at the beginning of the array. Subsequent controls
+ * draw beneath this control and appear later in the array.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of children, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return an array of children
+ *
+ * @see Control#moveAbove
+ * @see Control#moveBelow
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Control [] getChildren () {
+ checkWidget ();
+ return _getChildren ();
+}
+
+//int getChildrenCount () {
+// /*
+// * NOTE: The current implementation will count
+// * non-registered children.
+// */
+// int count = 0;
+// int hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+// while (hwndChild != 0) {
+// count++;
+// hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+// }
+// return count;
+//}
+
+/**
+ * Returns layout which is associated with the receiver, or
+ * null if one has not been set.
+ *
+ * @return the receiver's layout or null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Layout getLayout () {
+ checkWidget ();
+ return layout;
+}
+
+/**
+ * Gets the (possibly empty) tabbing order for the control.
+ *
+ * @return tabList the ordered list of controls representing the tab order
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setTabList
+ */
+public Control [] getTabList () {
+ checkWidget ();
+ Control [] tabList = _getTabList ();
+ if (tabList == null) {
+ int count = 0;
+ Control [] list =_getChildren ();
+ for (int i=0; itrue if the receiver has deferred
+ * the performing of layout, and false otherwise.
+ *
+ * @return the receiver's deferred layout state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setLayoutDeferred(boolean)
+ * @see #isLayoutDeferred()
+ *
+ * @since 3.1
+ */
+public boolean getLayoutDeferred () {
+ checkWidget ();
+ return layoutCount > 0 ;
+}
+
+/**
+ * Returns true if the receiver or any ancestor
+ * up to and including the receiver's nearest ancestor shell
+ * has deferred the performing of layouts. Otherwise, false
+ * is returned.
+ *
+ * @return the receiver's deferred layout state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setLayoutDeferred(boolean)
+ * @see #getLayoutDeferred()
+ *
+ * @since 3.1
+ */
+public boolean isLayoutDeferred () {
+ checkWidget ();
+ return findDeferredControl () != null;
+}
+
+protected boolean isLayoutManaged() {
+ return false;
+}
+
+/**
+ * If the receiver has a layout, asks the layout to lay out
+ * (that is, set the size and location of) the receiver's children.
+ * If the receiver does not have a layout, do nothing.
+ *
+ * This is equivalent to calling layout(true).
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void layout () {
+ checkWidget ();
+ layout (true);
+}
+
+/**
+ * If the receiver has a layout, asks the layout to lay out
+ * (that is, set the size and location of) the receiver's children.
+ * If the argument is true the layout must not rely
+ * on any information it has cached about the immediate children. If it
+ * is false the layout may (potentially) optimize the
+ * work it is doing by assuming that none of the receiver's
+ * children has changed state since the last layout.
+ * If the receiver does not have a layout, do nothing.
+ *
+ * If a child is resized as a result of a call to layout, the
+ * resize event will invoke the layout of the child. The layout
+ * will cascade down through all child widgets in the receiver's widget
+ * tree until a child is encountered that does not resize. Note that
+ * a layout due to a resize will not flush any cached information
+ * (same as layout(false)).
+ *
+ * @param changed true if the layout must flush its caches, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void layout (boolean changed) {
+ checkWidget ();
+ if (layout == null) return;
+ layout (changed, false);
+}
+
+/**
+ * If the receiver has a layout, asks the layout to lay out
+ * (that is, set the size and location of) the receiver's children.
+ * If the changed argument is true the layout must not rely
+ * on any information it has cached about its children. If it
+ * is false the layout may (potentially) optimize the
+ * work it is doing by assuming that none of the receiver's
+ * children has changed state since the last layout.
+ * If the all argument is true the layout will cascade down
+ * through all child widgets in the receiver's widget tree, regardless of
+ * whether the child has changed size. The changed argument is applied to
+ * all layouts. If the all argument is false, the layout will
+ * not cascade down through all child widgets in the receiver's widget
+ * tree. However, if a child is resized as a result of a call to layout, the
+ * resize event will invoke the layout of the child. Note that
+ * a layout due to a resize will not flush any cached information
+ * (same as layout(false)).
+ *
+ * @param changed true if the layout must flush its caches, and false otherwise
+ * @param all true if all children in the receiver's widget tree should be laid out, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void layout (boolean changed, boolean all) {
+ checkWidget ();
+ if (layout == null && !all) return;
+ markLayout (changed, all);
+ updateLayout (true, all);
+}
+
+/**
+ * Forces a lay out (that is, sets the size and location) of all widgets that
+ * are in the parent hierarchy of the changed control up to and including the
+ * receiver. The layouts in the hierarchy must not rely on any information
+ * cached about the changed control or any of its ancestors. The layout may
+ * (potentially) optimize the work it is doing by assuming that none of the
+ * peers of the changed control have changed state since the last layout.
+ * If an ancestor does not have a layout, skip it.
+ *
+ * @param changed a control that has had a state change which requires a recalculation of its size
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed
+ *
ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void layout (Control [] changed) {
+ checkWidget ();
+ if (changed == null) error (SWT.ERROR_INVALID_ARGUMENT);
+ for (int i=0; i=0; i--) {
+ update [i].updateLayout (true, false);
+ }
+}
+
+@Override
+void markLayout (boolean changed, boolean all) {
+ if (layout != null) {
+ state |= LAYOUT_NEEDED;
+ if (changed) state |= LAYOUT_CHANGED;
+ }
+ if (all) {
+ Control [] children = _getChildren ();
+ for (int i=0; i 1) {
+//// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+//// if ((bits & OS.WS_CLIPSIBLINGS) == 0) wp.flags |= OS.SWP_NOCOPYBITS;
+//// }
+// if (defer) {
+// hdwp = DeferWindowPos (hdwp, wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+// if (hdwp == 0) return false;
+// } else {
+// SetWindowPos (wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+// }
+// }
+// }
+// if (defer) return OS.EndDeferWindowPos (hdwp);
+// return true;
+//}
+//
+//void resizeEmbeddedHandle(int embeddedHandle, int width, int height) {
+// if (embeddedHandle == 0) return;
+// int [] processID = new int [1];
+// int threadId = OS.GetWindowThreadProcessId (embeddedHandle, processID);
+// if (threadId != OS.GetCurrentThreadId ()) {
+// if (processID [0] == OS.GetCurrentProcessId ()) {
+// if (display.msgHook == 0) {
+// if (!OS.IsWinCE) {
+// display.getMsgCallback = new Callback (display, "getMsgProc", 3);
+// display.getMsgProc = display.getMsgCallback.getAddress ();
+// if (display.getMsgProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+// display.msgHook = OS.SetWindowsHookEx (OS.WH_GETMESSAGE, display.getMsgProc, OS.GetLibraryHandle(), threadId);
+// OS.PostThreadMessage (threadId, OS.WM_NULL, 0, 0);
+// }
+// }
+// }
+// int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE | OS.SWP_ASYNCWINDOWPOS;
+// OS.SetWindowPos (embeddedHandle, 0, 0, 0, width, height, flags);
+// }
+//}
+
+int backgroundMode;
+
+/**
+ * Sets the background drawing mode to the argument which should
+ * be one of the following constants defined in class SWT:
+ * INHERIT_NONE, INHERIT_DEFAULT,
+ * INHERIT_FORCE.
+ *
+ * @param mode the new background mode
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT
+ *
+ * @since 3.2
+ */
+public void setBackgroundMode (int mode) {
+ checkWidget ();
+ if(backgroundMode == mode) return;
+ backgroundMode = mode;
+ Control [] children = _getChildren ();
+ for (int i = 0; i < children.length; i++) {
+ children [i].updateBackgroundMode ();
+ }
+ handle.repaint();
+}
+
+@Override
+public boolean setFocus () {
+ checkWidget ();
+ Control [] children = _getChildren ();
+ for (int i=0; i
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setLayout (Layout layout) {
+ checkWidget ();
+ this.layout = layout;
+}
+
+/**
+ * If the argument is true, causes subsequent layout
+ * operations in the receiver or any of its children to be ignored.
+ * No layout of any kind can occur in the receiver or any of its
+ * children until the flag is set to false.
+ * Layout operations that occurred while the flag was
+ * true are remembered and when the flag is set to
+ * false, the layout operations are performed in an
+ * optimized manner. Nested calls to this method are stacked.
+ *
+ * @param defer the new defer state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #layout(boolean)
+ * @see #layout(Control[])
+ *
+ * @since 3.1
+ */
+public void setLayoutDeferred (boolean defer) {
+ if (!defer) {
+ if (--layoutCount == 0) {
+ if ((state & LAYOUT_CHILD) != 0 || (state & LAYOUT_NEEDED) != 0) {
+ updateLayout (true, true);
+ }
+ }
+ } else {
+ layoutCount++;
+ }
+}
+/**
+ * Sets the tabbing order for the specified controls to
+ * match the order that they occur in the argument list.
+ *
+ * @param tabList the ordered list of controls representing the tab order or null
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed
+ *
ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setTabList (Control [] tabList) {
+ checkWidget ();
+ if (tabList != null) {
+ for (int i=0; i 1 && lpwp == null) {
+// lpwp = new WINDOWPOS [count];
+// }
+// }
+//}
+
+@Override
+boolean setTabGroupFocus () {
+ if (isTabItem ()) return setTabItemFocus ();
+ boolean takeFocus = (style & SWT.NO_FOCUS) == 0;
+ if ((state & CANVAS) != 0) {
+ takeFocus = hooksKeys ();
+ if ((style & SWT.EMBEDDED) != 0) takeFocus = true;
+ }
+ if (takeFocus && setTabItemFocus ()) return true;
+ Control [] children = _getChildren ();
+ for (int i=0; i= 6 && OS.IsAppThemed ()) {
+// if (findThemeControl () != null) {
+// int hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+// while (hwndChild != 0) {
+// int flags = OS.RDW_ERASE | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+// OS.RedrawWindow (hwndChild, null, 0, flags);
+// hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+// }
+// }
+// }
+// }
+//
+// /* Resize the embedded window */
+// if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
+// resizeEmbeddedHandle (OS.GetWindow (handle, OS.GW_CHILD), lParam & 0xFFFF, lParam >> 16);
+// }
+// return result;
+//}
+//
+//LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
+// int hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+// while (hwndChild != 0) {
+// OS.SendMessage (hwndChild, OS.WM_SYSCOLORCHANGE, 0, 0);
+// hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+// }
+// return null;
+//}
+//
+//LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
+// LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
+// if (result != null) return result;
+//
+// /*
+// * Check to see if the command is a system command or
+// * a user menu item that was added to the system menu.
+// */
+// if ((wParam & 0xF000) == 0) return result;
+//
+// /*
+// * Bug in Windows. When a vertical or horizontal scroll bar is
+// * hidden or shown while the opposite scroll bar is being scrolled
+// * by the user (with WM_HSCROLL code SB_LINEDOWN), the scroll bar
+// * does not redraw properly. The fix is to detect this case and
+// * redraw the non-client area.
+// */
+// if (!OS.IsWinCE) {
+// int cmd = wParam & 0xFFF0;
+// switch (cmd) {
+// case OS.SC_HSCROLL:
+// case OS.SC_VSCROLL:
+// boolean showHBar = horizontalBar != null && horizontalBar.getVisible ();
+// boolean showVBar = verticalBar != null && verticalBar.getVisible ();
+// int code = callWindowProc (handle, OS.WM_SYSCOMMAND, wParam, lParam);
+// if ((showHBar != (horizontalBar != null && horizontalBar.getVisible ())) ||
+// (showVBar != (verticalBar != null && verticalBar.getVisible ()))) {
+// int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_UPDATENOW;
+// OS.RedrawWindow (handle, null, 0, flags);
+// }
+// if (code == 0) return LRESULT.ZERO;
+// return new LRESULT (code);
+// }
+// }
+// /* Return the result */
+// return result;
+//}
+
+@Override
+public void processEvent(AWTEvent e) {
+ int id = e.getID();
+ switch(id) {
+ case ComponentEvent.COMPONENT_RESIZED: if(layout == null) { super.processEvent(e); return; } break;
+ default: { super.processEvent(e); return; }
+ }
+ if(isDisposed()) {
+ super.processEvent(e);
+ return;
+ }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ switch(id) {
+ case ComponentEvent.COMPONENT_RESIZED:
+ if(layout != null) {
+ markLayout(false, false);
+ updateLayout(false, false);
+// ((CControl)handle).getClientArea().invalidate();
+// handle.validate();
+// if(handle instanceof JComponent) {
+// ((JComponent)handle).revalidate();
+// } else {
+// handle.invalidate();
+// handle.validate();
+// }
+ handle.repaint();
+ }
+ break;
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+public int getOrientation() {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+
+public void setOrientation(int a) {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Control.java
new file mode 100644
index 00000000000..b9f42a432d6
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Control.java
@@ -0,0 +1,4818 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Insets;
+import java.awt.KeyboardFocusManager;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.event.ComponentEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseWheelEvent;
+import java.util.EventObject;
+
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.JViewport;
+import javax.swing.RootPaneContainer;
+import javax.swing.SwingUtilities;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.accessibility.Accessible;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.HelpListener;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.PaintListener;
+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.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.swing.CControl;
+import org.eclipse.swt.internal.swing.CGC;
+import org.eclipse.swt.internal.swing.Compatibility;
+import org.eclipse.swt.internal.swing.DisabledStatePanel;
+import org.eclipse.swt.internal.swing.NullGraphics2D;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+import org.eclipse.swt.internal.swing.Utils;
+
+/**
+ * Control is the abstract superclass of all windowed user interface classes.
+ *
+ * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+
+public abstract class Control extends Widget implements Drawable {
+ /**
+ * the handle to the OS resource
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public Container handle;
+ Composite parent;
+// Cursor cursor;
+ Menu menu;
+// String toolTipText;
+ Object layoutData;
+ Accessible accessible;
+// int drawCount, foreground, background;
+// long lastPressed = 0;
+ Image backgroundImage;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Control () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#BORDER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Control (Composite parent, int style) {
+ super (parent, style);
+ this.parent = parent;
+ createWidget ();
+}
+
+/**
+ * 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 ControlListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @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.Resize,typedListener);
+ addListener (SWT.Move,typedListener);
+}
+
+/**
+ * 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 FocusListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @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);
+}
+
+/**
+ * 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
+ * HelpListener interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see HelpListener
+ * @see #removeHelpListener
+ */
+public void addHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Help, typedListener);
+}
+
+/**
+ * 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 KeyListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see KeyListener
+ * @see #removeKeyListener
+ */
+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);
+}
+
+/**
+ * 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 MouseListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see MouseListener
+ * @see #removeMouseListener
+ */
+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);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the mouse passes or hovers over controls, by sending
+ * it one of the messages defined in the MouseTrackListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see MouseTrackListener
+ * @see #removeMouseTrackListener
+ */
+public void addMouseTrackListener (MouseTrackListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.MouseEnter,typedListener);
+ addListener (SWT.MouseExit,typedListener);
+ addListener (SWT.MouseHover,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the mouse moves, by sending it one of the
+ * messages defined in the MouseMoveListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see MouseMoveListener
+ * @see #removeMouseMoveListener
+ */
+public void addMouseMoveListener (MouseMoveListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.MouseMove,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver needs to be painted, by sending it
+ * one of the messages defined in the PaintListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see PaintListener
+ * @see #removePaintListener
+ */
+public void addPaintListener (PaintListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Paint,typedListener);
+}
+
+/**
+ * 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 TraverseListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * The preferred size 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 SWT.DEFAULT is passed for the hint.
+ *
+ *
+ * @param wHint the width hint (can be SWT.DEFAULT)
+ * @param hHint the height hint (can be SWT.DEFAULT)
+ * @return the preferred size of the control
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @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.
+ *
+ * The preferred size 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 SWT.DEFAULT is passed for the hint.
+ *
+ * If the changed flag is true, it indicates that the receiver's
+ * contents 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 false, so layout
+ * manager caches can be retained.
+ *
+ *
+ * @param wHint the width hint (can be SWT.DEFAULT)
+ * @param hHint the height hint (can be SWT.DEFAULT)
+ * @param changed true if the control's contents have changed, and false otherwise
+ * @return the preferred size of the control.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @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 ();
+ //TODO: it seems that for some components we have to take the border into account (Shell), and for others not (Button).
+ // Let's assume for a start that we don't take that into account if the component is the same as the client area.
+ Container clientArea = ((CControl)handle).getClientArea();
+ Dimension size = handle.getPreferredSize();
+ Dimension contentSize = clientArea.getPreferredSize();
+ if(clientArea != handle) {
+ Insets insets = clientArea.getInsets();
+ contentSize.width -= insets.left + insets.right;
+ contentSize.height -= insets.top + insets.bottom;
+ }
+ int width = size.width;
+ int height = size.height;
+ if(wHint != SWT.DEFAULT) {
+ width = wHint + width - contentSize.width;
+ }
+ if(hHint != SWT.DEFAULT) {
+ height = hHint + height - contentSize.height;
+ }
+ return new Point (width, height);
+}
+
+Control computeTabGroup () {
+ if (isTabGroup ()) return this;
+ return parent.computeTabGroup ();
+}
+
+Control computeTabRoot () {
+ Control [] tabList = parent._getTabList ();
+ if (tabList != null) {
+ int index = 0;
+ while (index < tabList.length) {
+ if (tabList [index] == this) break;
+ index++;
+ }
+ if (index == tabList.length) {
+ if (isTabGroup ()) return this;
+ }
+ }
+ return parent.computeTabRoot ();
+}
+
+Control [] computeTabList () {
+ if (isTabGroup ()) {
+ if (getVisible () && getEnabled ()) {
+ return new Control [] {this};
+ }
+ }
+ return new Control [0];
+}
+
+/**
+ * Like create handle, but overriden class should call its supertype declaration
+ */
+void createHandleInit () {
+
+}
+
+Container createHandle () {
+ if(handle != null) return handle;
+ error (SWT.ERROR_NO_HANDLES);
+ return null;
+}
+
+boolean autoAddChildren() {
+ return true;
+}
+
+void createWidget () {
+ checkOrientation (parent);
+ createHandleInit ();
+ handle = createHandle ();
+ if(!(handle instanceof CControl)) throw new IllegalStateException("The widget should implement the CComponent interface!");
+ if(handle instanceof Window) {
+ Dimension size = ((Window)handle).getSize();
+ ((Window)handle).pack();
+ handle.setSize(size);
+ }
+ if(parent != null && !(handle instanceof Window)) {
+ if(parent.autoAddChildren()) {
+ Container clientArea = ((CControl)parent.handle).getClientArea();
+ if(!parent.isLayoutManaged()) {
+ clientArea.setLayout(null);
+ }
+ clientArea.add(handle);
+ updateBackgroundMode();
+ ((JComponent)clientArea).revalidate();
+ clientArea.repaint();
+ }
+// if(parent instanceof Shell && parent.getChildren().length == 0) {
+// handle.requestFocus();
+// }
+ }
+ // TODO: should have a fixInitSize like in old implementation <- Note it seems to be fixed now, but have to check
+// if(handle.getSize().equals(new java.awt.Dimension(0, 0))) {
+// handle.setSize(handle.getPreferredSize());
+// if(handle instanceof JComponent) {
+// JComponent component = (JComponent)handle;
+//// component.setOpaque(true);
+//// component.revalidate();
+//// } else {
+//// handle.validate();
+// }
+// }
+ register ();
+// subclass ();
+// setDefaultFont ();
+// checkMirrored ();
+// checkBorder ();
+}
+
+//int defaultBackground () {
+// if (OS.IsWinCE) return OS.GetSysColor (OS.COLOR_WINDOW);
+// return OS.GetSysColor (OS.COLOR_BTNFACE);
+//}
+//
+//int defaultFont () {
+// return display.systemFont ();
+//}
+//
+//int defaultForeground () {
+// return OS.GetSysColor (OS.COLOR_WINDOWTEXT);
+//}
+
+void deregister () {
+ display.removeControl (handle);
+}
+
+void destroyWidget () {
+// int hwnd = topHandle ();
+ releaseHandle ();
+// if (hwnd != 0) {
+// OS.DestroyWindow (hwnd);
+// }
+}
+
+//void drawBackground (int hDC) {
+// RECT rect = new RECT ();
+// OS.GetClientRect (handle, rect);
+// drawBackground (hDC, getBackgroundPixel (), rect);
+//}
+//
+//void drawBackground (int hDC, int pixel, RECT rect) {
+// Control control = null;
+// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+// control = findThemeControl ();
+// }
+// if (control == null) {
+// int hPalette = display.hPalette;
+// if (hPalette != 0) {
+// OS.SelectPalette (hDC, hPalette, false);
+// OS.RealizePalette (hDC);
+// }
+// int hBrush = findBrush (pixel);
+// OS.FillRect (hDC, rect, hBrush);
+// } else {
+// RECT rect2 = new RECT ();
+// OS.GetWindowRect (control.handle, rect2);
+// OS.MapWindowPoints (0, handle, rect2, 2);
+// control.drawThemeBackground (hDC, rect2);
+// }
+//}
+//
+//void drawBackground (int hDC, RECT rect) {
+// drawBackground (hDC, getBackgroundPixel (), rect);
+//}
+//
+//void drawThemeBackground (int hDC, RECT rect) {
+// /* Do nothing */
+//}
+//
+//void enableWidget (boolean enabled) {
+// handle.setEnabled(enabled);
+//}
+//
+//int findBrush (int pixel) {
+// return parent.findBrush (pixel);
+//}
+//
+//Cursor findCursor () {
+// if (cursor != null) return cursor;
+// return parent.findCursor ();
+//}
+//
+//Control findThemeControl () {
+// return background == - 1 ? parent.findThemeControl () : null;
+//}
+
+Menu [] findMenus (Control control) {
+ if (menu != null && this != control) return new Menu [] {menu};
+ return new Menu [0];
+}
+
+//int findMnemonicIndex (String string) {
+// int index = 0;
+// int length = string.length ();
+// do {
+// while (index < length && string.charAt (index) != '&') index++;
+// if (++index >= length) return -1;
+// if (string.charAt (index) != '&') return index;
+// index++;
+// } while (index < length);
+// return -1;
+//}
+
+char findMnemonic (String string) {
+ int index = 0;
+ int length = string.length ();
+ do {
+ while (index < length && string.charAt (index) != '&') index++;
+ if (++index >= length) return '\0';
+ if (string.charAt (index) != '&') return string.charAt (index);
+ index++;
+ } while (index < length);
+ return '\0';
+}
+
+void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
+ oldShell.fixShell (newShell, this);
+ oldDecorations.fixDecorations (newDecorations, this, menus);
+}
+
+//void fixFocus (Control focusControl) {
+// Shell shell = getShell ();
+// Control control = this;
+// while ((control = control.parent) != null) {
+// if (control.setFocus ()) return;
+// if (control == shell) break;
+// }
+// shell.setSavedFocus (focusControl);
+// OS.SetFocus (0);
+//}
+
+/**
+ * Forces the receiver to have the keyboard focus, causing
+ * all keyboard events to be delivered to it.
+ *
+ * @return true if the control got focus, and false if it was unable to.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setFocus
+ */
+public boolean forceFocus () {
+ checkWidget ();
+// if (display.focusEvent == SWT.FocusOut) return false;
+// Decorations shell = menuShell ();
+// shell.setSavedFocus (this);
+ if (!isEnabled () /*|| !isActive ()*/) return false;
+ if(!handle.isFocusable()) return false;
+ if (!isVisible ()) {
+ Window window = SwingUtilities.getWindowAncestor(handle);
+ if(window != null && !window.isVisible()) {
+ getShell().setInitialFocusedControl(this);
+ return true;
+ }
+ return false;
+ }
+ if (isFocusControl ()) return true;
+// shell.setSavedFocus (null);
+ // return handle.requestFocusInWindow();
+ Window window = SwingUtilities.getWindowAncestor(handle);
+ if(window != null) {
+ window.setFocusableWindowState(true);
+ }
+// if (handle instanceof JComponent) {
+// ((javax.swing.JComponent) handle).grabFocus();
+// } else {
+ handle.requestFocus();
+// }
+ return true;
+
+// return handle.hasFocus();
+// /*
+// * This code is intentionally commented.
+// *
+// * When setting focus to a control, it is
+// * possible that application code can set
+// * the focus to another control inside of
+// * WM_SETFOCUS. In this case, the original
+// * control will no longer have the focus
+// * and the call to setFocus() will return
+// * false indicating failure.
+// *
+// * We are still working on a solution at
+// * this time.
+// */
+//// if (OS.GetFocus () != OS.SetFocus (handle)) return false;
+// OS.SetFocus (handle);
+// if (isDisposed ()) return false;
+// shell.setSavedFocus (this);
+// return isFocusControl ();
+}
+
+//void forceResize () {
+// if (parent == null) return;
+// WINDOWPOS [] lpwp = parent.lpwp;
+// if (lpwp == null) return;
+// for (int i=0; i 1) {
+//// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+//// if ((bits & OS.WS_CLIPSIBLINGS) == 0) wp.flags |= OS.SWP_NOCOPYBITS;
+//// }
+// SetWindowPos (wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+// lpwp [i] = null;
+// return;
+// }
+// }
+//}
+
+/**
+ * Returns the accessible object for the receiver.
+ * If this is the first time this object is requested,
+ * then the object is created and returned.
+ *
+ * @return the accessible object
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getBorderWidth () {
+ checkWidget ();
+ java.awt.Rectangle bounds = handle.getBounds();
+ java.awt.Rectangle cBounds = ((CControl)handle).getClientArea().getBounds();
+ return Math.max((bounds.width - cBounds.width + 1) / 2, (bounds.height - cBounds.height + 1) / 2);
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Rectangle getBounds () {
+ checkWidget ();
+ java.awt.Rectangle rect = handle.getBounds();
+ Point offset = parent == null? new Point(0, 0): parent.getInternalOffset();
+ return new Rectangle (rect.x + offset.x, rect.y + offset.y, rect.width, rect.height);
+//
+// RECT rect = new RECT ();
+// OS.GetWindowRect (topHandle (), rect);
+// int hwndParent = parent == null ? 0 : parent.handle;
+// OS.MapWindowPoints (0, hwndParent, rect, 2);
+// int width = rect.right - rect.left;
+// int height = rect.bottom - rect.top;
+// return new Rectangle (rect.left, rect.top, width, height);
+}
+
+//int getCodePage () {
+// if (OS.IsUnicode) return OS.CP_ACP;
+// int hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+// LOGFONT logFont = OS.IsUnicode ? (LOGFONT) new LOGFONTW () : new LOGFONTA ();
+// OS.GetObject (hFont, LOGFONT.sizeof, logFont);
+// int cs = logFont.lfCharSet & 0xFF;
+// int [] lpCs = new int [8];
+// if (OS.TranslateCharsetInfo (cs, lpCs, OS.TCI_SRCCHARSET)) {
+// return lpCs [1];
+// }
+// return OS.GetACP ();
+//}
+//
+//String getClipboardText () {
+// String string = "";
+// if (OS.OpenClipboard (0)) {
+// int hMem = OS.GetClipboardData (OS.IsUnicode ? OS.CF_UNICODETEXT : OS.CF_TEXT);
+// if (hMem != 0) {
+// /* Ensure byteCount is a multiple of 2 bytes on UNICODE platforms */
+// int byteCount = OS.GlobalSize (hMem) / TCHAR.sizeof * TCHAR.sizeof;
+// int ptr = OS.GlobalLock (hMem);
+// if (ptr != 0) {
+// /* Use the character encoding for the default locale */
+// TCHAR buffer = new TCHAR (0, byteCount / TCHAR.sizeof);
+// OS.MoveMemory (buffer, ptr, byteCount);
+// string = buffer.toString (0, buffer.strlen ());
+// OS.GlobalUnlock (hMem);
+// }
+// }
+// OS.CloseClipboard ();
+// }
+// return string;
+//}
+
+/**
+ * Returns true if the receiver is enabled, and
+ * false 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #isEnabled
+ */
+public boolean getEnabled () {
+ checkWidget ();
+ return handle.isEnabled();
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Font getFont () {
+ checkWidget ();
+ return Font.swing_new (display, ((CControl)handle).getUserAttributeHandler().getFont());
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Color getForeground () {
+ checkWidget ();
+ return Color.swing_new (display, ((CControl)handle).getUserAttributeHandler().getForeground());
+}
+
+//int getForegroundPixel () {
+// if (foreground == -1) return defaultForeground ();
+// return foreground;
+//}
+
+/**
+ * Returns layout data which is associated with the receiver.
+ *
+ * @return the receiver's layout data
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Object getLayoutData () {
+ checkWidget ();
+ return layoutData;
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getLocation () {
+ checkWidget ();
+ java.awt.Point location = handle.getLocation();
+ Point offset = parent == null? new Point(0, 0): parent.getInternalOffset();
+ return new Point (location.x + offset.x, location.y + offset.y);
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Menu getMenu () {
+ checkWidget ();
+ return menu;
+}
+
+/**
+ * Returns the receiver's monitor.
+ *
+ * @return the receiver's monitor
+ *
+ * @since 3.0
+ */
+public Monitor getMonitor () {
+ checkWidget ();
+ GraphicsConfiguration gc = handle.getGraphicsConfiguration();
+ Monitor monitor = new Monitor();
+ monitor.handle = gc;
+ java.awt.Rectangle bounds = gc.getBounds();
+ monitor.x = bounds.x;
+ monitor.y = bounds.y;
+ monitor.width = bounds.width;
+ monitor.height = bounds.height;
+ java.awt.Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
+ monitor.clientX = bounds.x + insets.left;
+ monitor.clientY = bounds.y + insets.top;
+ monitor.clientWidth = bounds.width - insets.left - insets.right;
+ monitor.clientHeight = bounds.height - insets.top - insets.bottom;
+ return monitor;
+}
+
+/**
+ * Returns the receiver's parent, which must be a Composite
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Composite getParent () {
+ checkWidget ();
+ return parent;
+}
+
+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;
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getParent
+ */
+public Shell getShell () {
+ checkWidget ();
+ return parent.getShell ();
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getSize () {
+ checkWidget ();
+ java.awt.Dimension size = handle.getSize();
+ return new Point(size.width, size.height);
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getToolTipText () {
+ checkWidget ();
+ return toolTipText;
+}
+
+/**
+ * Returns true if the receiver is visible, and
+ * false otherwise.
+ *
+ * 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.
+ *
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getVisible () {
+ checkWidget ();
+ return handle.isVisible();
+}
+
+//boolean hasCursor () {
+// RECT rect = new RECT ();
+// if (!OS.GetClientRect (handle, rect)) return false;
+// OS.MapWindowPoints (handle, 0, rect, 2);
+// POINT pt = new POINT ();
+// return OS.GetCursorPos (pt) && OS.PtInRect (rect, pt);
+//}
+//
+//boolean hasFocus () {
+// /*
+// * If a non-SWT child of the control has focus,
+// * then this control is considered to have focus
+// * even though it does not have focus in Windows.
+// */
+// int hwndFocus = OS.GetFocus ();
+// while (hwndFocus != 0) {
+// if (hwndFocus == handle) return true;
+// if (display.getControl (hwndFocus) != null) {
+// return false;
+// }
+// hwndFocus = OS.GetParent (hwndFocus);
+// }
+// return false;
+//}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Control. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Control. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public void internal_dispose_GC (CGC hDC, GCData data) {
+ checkWidget ();
+// Component hwnd = handle;
+// if (data != null && data.hwnd != null) {
+// hwnd = data.hwnd;
+// }
+ hDC.dispose();
+// if (data == null || data.ps == null) {
+// OS.ReleaseDC (hwnd, hDC);
+// } else {
+// OS.EndPaint (hwnd, data.ps);
+// }
+}
+//
+//boolean isActive () {
+// Shell dialogShell = display.getModalDialogShell ();
+// if (dialogShell != null && dialogShell != getShell ()) {
+// return false;
+// }
+// Shell shell = null;
+// Shell [] modalShells = display.modalShells;
+// if (modalShells != null) {
+// int bits = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
+// int index = modalShells.length;
+// while (--index >= 0) {
+// Shell modal = modalShells [index];
+// if (modal != null) {
+// if ((modal.style & bits) != 0) {
+// Control control = this;
+// while (control != null) {
+// if (control == modal) break;
+// control = control.parent;
+// }
+// if (control != modal) return false;
+// break;
+// }
+// if ((modal.style & SWT.PRIMARY_MODAL) != 0) {
+// if (shell == null) shell = getShell ();
+// if (modal.parent == shell) return false;
+// }
+// }
+// }
+// }
+// if (shell == null) shell = getShell ();
+// return shell.getEnabled ();
+//}
+
+/**
+ * Returns true if the receiver is enabled and all
+ * ancestors up to and including the receiver's nearest ancestor
+ * shell are enabled. Otherwise, false 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getEnabled
+ */
+public boolean isEnabled () {
+ checkWidget ();
+ return getEnabled () && parent.isEnabled ();
+}
+
+/**
+ * Returns true if the receiver has the user-interface
+ * focus, and false otherwise.
+ *
+ * @return the receiver's focus state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean isFocusControl () {
+ checkWidget ();
+ return display.findControl(KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner()) == this;
+}
+
+//boolean isFocusAncestor (Control control) {
+// while (control != null && control != this) {
+// control = control.parent;
+// }
+// return control == this;
+//}
+
+/**
+ * Returns true if the underlying operating
+ * system supports this reparenting, otherwise false
+ *
+ * @return true if the widget can be reparented, otherwise false
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean isReparentable () {
+ checkWidget ();
+ return true;
+}
+
+//boolean isShowing () {
+// /*
+// * This is not complete. Need to check if the
+// * widget is obscurred by a parent or sibling.
+// */
+// if (!isVisible ()) return false;
+// Control control = this;
+// while (control != null) {
+// Point size = control.getSize ();
+// if (size.x == 0 || size.y == 0) {
+// return false;
+// }
+// control = control.parent;
+// }
+// return true;
+// /*
+// * Check to see if current damage is included.
+// */
+//// if (!OS.IsWindowVisible (handle)) return false;
+//// int flags = OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS;
+//// int hDC = OS.GetDCEx (handle, 0, flags);
+//// int result = OS.GetClipBox (hDC, new RECT ());
+//// OS.ReleaseDC (handle, hDC);
+//// return result != OS.NULLREGION;
+//}
+
+boolean isTabGroup () {
+ Control [] tabList = parent._getTabList ();
+ if (tabList != null) {
+ for (int i=0; itrue if the receiver is visible and all
+ * ancestors up to and including the receiver's nearest ancestor
+ * shell are visible. Otherwise, false is returned.
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getVisible
+ */
+public boolean isVisible () {
+ checkWidget ();
+ return handle.isShowing();
+}
+
+//void mapEvent (int hwnd, Event event) {
+// if (hwnd != handle) {
+// POINT point = new POINT ();
+// point.x = event.x;
+// point.y = event.y;
+// OS.MapWindowPoints (hwnd, handle, point, 1);
+// event.x = point.x;
+// event.y = point.y;
+// }
+//}
+
+void markLayout (boolean changed, boolean all) {
+ /* Do nothing */
+}
+
+Decorations menuShell () {
+ return parent.menuShell ();
+}
+
+boolean mnemonicHit (char key) {
+ return false;
+}
+
+boolean mnemonicMatch (char key) {
+ return false;
+}
+
+/**
+ * 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
+ *
ERROR_INVALID_ARGUMENT - if the control has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Control#moveBelow
+ * @see Composite#getChildren
+ */
+public void moveAbove (Control control) {
+ checkWidget ();
+ Container cParent = handle.getParent();
+ if (control != null) {
+ if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+ if (handle == control.handle) return;
+ if (parent != control.parent) return;
+ if(!Compatibility.IS_JAVA_5_OR_GREATER) {
+ boolean isFound = false;
+ for(int i=cParent.getComponentCount()-1; i>=0; i--) {
+ isFound = control.handle == handle;
+ if(cParent.getComponent(i) == control.handle) {
+ cParent.remove(handle);
+ cParent.add(handle, isFound? i: i-1);
+ handle.invalidate();
+ cParent.validate();
+ cParent.repaint();
+ break;
+ }
+ }
+ return;
+ }
+ int cOrder = cParent.getComponentZOrder(control.handle);
+ int order = cParent.getComponentZOrder(handle);
+ if(order < cOrder) {
+ cOrder--;
+ }
+ cParent.setComponentZOrder(handle, cOrder);
+ } else {
+ if(!Compatibility.IS_JAVA_5_OR_GREATER) {
+ cParent.remove(handle);
+ cParent.add(handle, 0);
+ handle.invalidate();
+ cParent.validate();
+ cParent.repaint();
+ return;
+ }
+ cParent.setComponentZOrder(handle, 0);
+ }
+// int topHandle = topHandle (), hwndAbove = OS.HWND_TOP;
+// if (control != null) {
+// if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+// if (parent != control.parent) return;
+// int hwnd = control.topHandle ();
+// if (hwnd == 0 || hwnd == topHandle) return;
+// hwndAbove = OS.GetWindow (hwnd, OS.GW_HWNDPREV);
+// /*
+// * Bug in Windows. For some reason, when GetWindow ()
+// * with GW_HWNDPREV is used to query the previous window
+// * in the z-order with the first child, Windows returns
+// * the first child instead of NULL. The fix is to detect
+// * this case and move the control to the top.
+// */
+// if (hwndAbove == 0 || hwndAbove == hwnd) {
+// hwndAbove = OS.HWND_TOP;
+// }
+// }
+// int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+// SetWindowPos (topHandle, hwndAbove, 0, 0, 0, 0, flags);
+}
+
+/**
+ * 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
+ *
ERROR_INVALID_ARGUMENT - if the control has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @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.
+ *
+ * If the changed flag is true, it indicates that the receiver's
+ * contents 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 false, so layout
+ * manager caches can be retained.
+ *
+ *
+ * @param changed whether or not the receiver's contents have changed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #computeSize(int, int, boolean)
+ */
+public void pack (boolean changed) {
+ checkWidget ();
+ setSize (computeSize (SWT.DEFAULT, SWT.DEFAULT, changed));
+}
+
+/**
+ * Causes the entire bounds of the receiver to be marked
+ * as needing to be redrawn. The next time a paint request
+ * is processed, the control will be completely painted,
+ * including the background.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #update
+ * @see PaintListener
+ * @see SWT#Paint
+ * @see SWT#NO_BACKGROUND
+ * @see SWT#NO_REDRAW_RESIZE
+ * @see SWT#NO_MERGE_PAINTS
+ */
+public void redraw () {
+ checkWidget ();
+ handle.repaint();
+// if (!OS.IsWindowVisible (handle)) return;
+// if (OS.IsWinCE) {
+// OS.InvalidateRect (handle, null, true);
+// } else {
+// int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+// OS.RedrawWindow (handle, null, 0, flags);
+// }
+}
+
+/**
+ * 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 all flag is true, any
+ * children of the receiver which intersect with the specified
+ * area will also paint their intersecting areas. If the
+ * all flag is false, 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 true if children should redraw, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #update
+ * @see PaintListener
+ * @see SWT#Paint
+ * @see SWT#NO_BACKGROUND
+ * @see SWT#NO_REDRAW_RESIZE
+ * @see SWT#NO_MERGE_PAINTS
+ */
+public void redraw (int x, int y, int width, int height, boolean all) {
+ checkWidget ();
+ if (width <= 0 || height <= 0) return;
+ // TODO: what about the "all" setting?
+// handle.repaint();
+ // TODO: check using the Paint Example why this repaint needs -1 and +2...
+ ((CControl)handle).getClientArea().repaint(x-1, y-1, width+2, height+2);
+// if (!OS.IsWindowVisible (handle)) return;
+// RECT rect = new RECT ();
+// OS.SetRect (rect, x, y, x + width, y + height);
+// if (OS.IsWinCE) {
+// OS.InvalidateRect (handle, rect, true);
+// } else {
+// int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+// if (all) flags |= OS.RDW_ALLCHILDREN;
+// OS.RedrawWindow (handle, rect, 0, flags);
+// }
+}
+
+void register () {
+ display.addControl (handle, this);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ handle = null;
+ parent = null;
+}
+
+void releaseParent () {
+ Container parent = handle.getParent();
+ if(parent != null) {
+ parent.remove(handle);
+ ((JComponent)parent).revalidate();
+ parent.repaint();
+ }
+ this.parent.removeControl (this);
+}
+
+void releaseWidget () {
+ if(focusLostRunnable != null && getShell().getActiveControl() == this) {
+ focusLostRunnable.run();
+ }
+ super.releaseWidget ();
+// if (OS.IsDBLocale) {
+// OS.ImmAssociateContext (handle, 0);
+// }
+// if (toolTipText != null) {
+// Shell shell = getShell ();
+// shell.setToolTipText (handle, null);
+// }
+// toolTipText = null;
+ if (menu != null && !menu.isDisposed ()) {
+ menu.dispose ();
+ }
+ menu = null;
+// cursor = null;
+ deregister ();
+// unsubclass ();
+ layoutData = null;
+ if (accessible != null) {
+ accessible.internal_dispose_Accessible ();
+ }
+ accessible = null;
+ if(disabledStatePanel != null) {
+ disabledStatePanel.release();
+ disabledStatePanel = null;
+ }
+}
+
+/**
+ * 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
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Move, listener);
+ eventTable.unhook (SWT.Resize, listener);
+}
+
+/**
+ * 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
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see FocusListener
+ * @see #addFocusListener
+ */
+public void removeFocusListener(FocusListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.FocusIn, listener);
+ eventTable.unhook (SWT.FocusOut, listener);
+}
+
+/**
+ * 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
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see HelpListener
+ * @see #addHelpListener
+ */
+public void removeHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Help, listener);
+}
+
+/**
+ * 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
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see KeyListener
+ * @see #addKeyListener
+ */
+public void removeKeyListener(KeyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.KeyUp, listener);
+ eventTable.unhook (SWT.KeyDown, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the mouse passes or hovers over controls.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see MouseTrackListener
+ * @see #addMouseTrackListener
+ */
+public void removeMouseTrackListener(MouseTrackListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.MouseEnter, listener);
+ eventTable.unhook (SWT.MouseExit, listener);
+ eventTable.unhook (SWT.MouseHover, listener);
+}
+
+/**
+ * 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
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see MouseListener
+ * @see #addMouseListener
+ */
+public void removeMouseListener (MouseListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.MouseDown, listener);
+ eventTable.unhook (SWT.MouseUp, listener);
+ eventTable.unhook (SWT.MouseDoubleClick, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the mouse moves.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see MouseMoveListener
+ * @see #addMouseMoveListener
+ */
+public void removeMouseMoveListener(MouseMoveListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.MouseMove, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver needs to be painted.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see PaintListener
+ * @see #addPaintListener
+ */
+public void removePaintListener(PaintListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook(SWT.Paint, listener);
+}
+
+/**
+ * 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
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see TraverseListener
+ * @see #addTraverseListener
+ */
+public void removeTraverseListener(TraverseListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Traverse, listener);
+}
+
+//void showWidget (boolean visible) {
+// OS.ShowWindow (handle, visible ? OS.SW_SHOW : OS.SW_HIDE);
+//}
+//
+//boolean sendFocusEvent (int type) {
+// Shell shell = getShell ();
+//
+// /*
+// * Feature in Windows. During the processing of WM_KILLFOCUS,
+// * when the focus window is queried using GetFocus(), it has
+// * already been assigned to the new window. The fix is to
+// * remember the control that is losing or gaining focus and
+// * answer it during WM_KILLFOCUS. If a WM_SETFOCUS occurs
+// * during WM_KILLFOCUS, the focus control needs to be updated
+// * to the current control. At any other time, the focus
+// * control matches Windows.
+// */
+// Display display = this.display;
+// display.focusEvent = type;
+// display.focusControl = this;
+// sendEvent (type);
+// // widget could be disposed at this point
+// display.focusEvent = SWT.None;
+// display.focusControl = null;
+//
+// /*
+// * It is possible that the shell may be
+// * disposed at this point. If this happens
+// * don't send the activate and deactivate
+// * events.
+// */
+// if (!shell.isDisposed ()) {
+// switch (type) {
+// case SWT.FocusIn:
+// shell.setActiveControl (this);
+// break;
+// case SWT.FocusOut:
+// if (shell != display.getActiveShell ()) {
+// shell.setActiveControl (null);
+// }
+// break;
+// }
+// }
+// return true;
+//}
+
+/**
+ * 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
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setBackground (Color color) {
+ checkWidget ();
+ if (color != null) {
+ if (color.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ ((CControl)handle).getUserAttributeHandler().setBackground (color.handle);
+ } else {
+ ((CControl)handle).getUserAttributeHandler().setBackground (null);
+ }
+ handle.repaint();
+}
+
+/**
+ * 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.
+ *
+ * @param image the new image (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
ERROR_INVALID_ARGUMENT - if the argument is not a bitmap
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setBackgroundImage (Image image) {
+ checkWidget ();
+ if (image != null) {
+ if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (image.type != SWT.BITMAP) error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (backgroundImage == image) return;
+ backgroundImage = image;
+ ((CControl)handle).setBackgroundImage(backgroundImage == null? null: backgroundImage.handle);
+ handle.repaint();
+}
+
+//void setBackgroundPixel (int pixel) {
+// if (background == pixel) return;
+// background = pixel;
+// OS.InvalidateRect (handle, null, true);
+//}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the arguments. The x and
+ * y 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 x
+ * and y arguments are relative to the display.
+ *
+ * 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.
+ *
+ *
+ * @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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setBounds (int x, int y, int width, int height) {
+ checkWidget ();
+ if(width < 0) width = 0;
+ if(height < 0) height = 0;
+ Point offset = parent == null? new Point(0, 0): parent.getInternalOffset();
+ x -= offset.x;
+ y -= offset.y;
+// java.awt.Point location = new java.awt.Point(x, y);
+// Container parent = handle.getParent();
+// if(parent != null) {
+// location = SwingUtilities.convertPoint(this.parent.handle, location, parent);
+// }
+ java.awt.Rectangle bounds = handle.getBounds();
+ if(bounds.x == x && bounds.y == y && bounds.width == width && bounds.height == height) return;
+ handle.setBounds(x, y, width, height);
+ // The notification has to be immediate in SWT, so we force it
+ if(bounds.width != width || bounds.height != height) {
+ ((CControl)handle).getClientArea().invalidate();
+ handle.validate();
+ processEvent(new ComponentEvent(handle, ComponentEvent.COMPONENT_RESIZED));
+ }
+ // The notification has to be immediate in SWT, so we force it
+ if(bounds.x != x || bounds.y != y) {
+ processEvent(new ComponentEvent(handle, ComponentEvent.COMPONENT_MOVED));
+ }
+ handle.repaint();
+}
+
+//void setBounds (int x, int y, int width, int height, int flags) {
+// setBounds (x, y, width, height, flags, true);
+//}
+//
+//void setBounds (int x, int y, int width, int height, int flags, boolean defer) {
+// int topHandle = topHandle ();
+// if (defer && parent != null) {
+// forceResize ();
+// WINDOWPOS [] lpwp = parent.lpwp;
+// if (lpwp == null) {
+// /*
+// * This code is intentionally commented. All widgets that
+// * are created by SWT have WS_CLIPSIBLINGS to ensure that
+// * application code does not draw outside of the control.
+// */
+//// int count = parent.getChildrenCount ();
+//// if (count > 1) {
+//// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+//// if ((bits & OS.WS_CLIPSIBLINGS) == 0) flags |= OS.SWP_NOCOPYBITS;
+//// }
+// SetWindowPos (topHandle, 0, x, y, width, height, flags);
+// } else {
+// int index = 0;
+// while (index < lpwp.length) {
+// if (lpwp [index] == null) break;
+// index ++;
+// }
+// if (index == lpwp.length) {
+// WINDOWPOS [] newLpwp = new WINDOWPOS [lpwp.length + 4];
+// System.arraycopy (lpwp, 0, newLpwp, 0, lpwp.length);
+// parent.lpwp = lpwp = newLpwp;
+// }
+// WINDOWPOS wp = new WINDOWPOS ();
+// wp.hwnd = topHandle;
+// wp.x = x;
+// wp.y = y;
+// wp.cx = width;
+// wp.cy = height;
+// wp.flags = flags;
+// lpwp [index] = wp;
+// }
+// } else {
+// SetWindowPos (topHandle, 0, x, y, width, height, flags);
+// }
+//}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the argument. The x and
+ * y fields of the rectangle are relative to
+ * the receiver's parent (or its display if its parent is null).
+ *
+ * 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.
+ *
+ *
+ * @param rect the new bounds for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setBounds (Rectangle rect) {
+ checkWidget ();
+ if (rect == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setBounds (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * If the argument is true, causes the receiver to have
+ * all mouse events delivered to it until the method is called with
+ * false as the argument.
+ *
+ * @param capture true to capture the mouse, and false to release it
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setCapture (boolean capture) {
+ checkWidget ();
+ if (capture) {
+ Utils.capturedControl = this;
+ } else {
+ if (Utils.capturedControl == this) {
+ Utils.capturedControl = null;
+ }
+ }
+// if (capture) {
+// OS.SetCapture (handle);
+// } else {
+// if (OS.GetCapture () == handle) {
+// OS.ReleaseCapture ();
+// }
+// }
+}
+
+void sendMouseEvent(int eventType, Event event) {
+ if(Utils.capturedControl == null || Utils.capturedControl == this) {
+ sendEvent(eventType, event);
+ return;
+ }
+ Control control = Utils.capturedControl;
+ switch(eventType) {
+ case SWT.MouseDown:
+ case SWT.MouseUp:
+ Utils.capturedControl = null;
+ break;
+ }
+ java.awt.Point point = SwingUtilities.convertPoint(handle, event.x, event.y, control.handle);
+ event.x = point.x;
+ event.y = point.y;
+ control.sendEvent(eventType, event);
+}
+
+//void setCursor () {
+// int lParam = OS.HTCLIENT | (OS.WM_MOUSEMOVE << 16);
+// OS.SendMessage (handle, OS.WM_SETCURSOR, handle, lParam);
+//}
+
+/**
+ * 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.
+ *
+ * When the mouse pointer passes over a control its appearance
+ * is changed to match the control's cursor.
+ *
+ *
+ * @param cursor the new cursor (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setCursor (Cursor cursor) {
+ checkWidget ();
+ if (cursor != null) {
+ if (cursor.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ ((CControl)handle).getUserAttributeHandler().setCursor(cursor.handle);
+ } else {
+ ((CControl)handle).getUserAttributeHandler().setCursor (null);
+ }
+// this.cursor = cursor;
+// if (OS.IsWinCE) {
+// int hCursor = cursor != null ? cursor.handle : 0;
+// OS.SetCursor (hCursor);
+// return;
+// }
+// int hwndCursor = OS.GetCapture ();
+// if (hwndCursor == 0) {
+// POINT pt = new POINT ();
+// if (!OS.GetCursorPos (pt)) return;
+// int hwnd = hwndCursor = OS.WindowFromPoint (pt);
+// while (hwnd != 0 && hwnd != handle) {
+// hwnd = OS.GetParent (hwnd);
+// }
+// if (hwnd == 0) return;
+// }
+// Control control = display.getControl (hwndCursor);
+// if (control == null) control = this;
+// control.setCursor ();
+}
+
+//void setDefaultFont () {
+// int hFont = display.systemFont ();
+// OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+//}
+
+private DisabledStatePanel disabledStatePanel;
+
+/**
+ * Enables the receiver if the argument is true,
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setEnabled (boolean enabled) {
+ checkWidget ();
+ handle.setEnabled(enabled);
+ if(enabled) {
+ if(disabledStatePanel != null) {
+ disabledStatePanel.release();
+ disabledStatePanel = null;
+ }
+ } else {
+ if(disabledStatePanel == null) {
+ disabledStatePanel = new DisabledStatePanel(this);
+ }
+ }
+// /*
+// * 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) {
+// if (display.focusEvent != SWT.FocusOut) {
+// control = display.getFocusControl ();
+// fixFocus = isFocusAncestor (control);
+// }
+// }
+// enableWidget (enabled);
+// if (fixFocus) fixFocus (control);
+}
+
+/**
+ * Causes the receiver to have the keyboard focus,
+ * such that all keyboard events will be delivered to it. Focus
+ * reassignment will respect applicable platform constraints.
+ *
+ * @return true if the control got focus, and false if it was unable to.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #forceFocus
+ */
+public boolean setFocus () {
+ checkWidget ();
+ if ((style & SWT.NO_FOCUS) != 0) return false;
+ return forceFocus ();
+}
+
+/**
+ * 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
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setFont (Font font) {
+ checkWidget ();
+ if (font != null) {
+ if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ ((CControl)handle).getUserAttributeHandler().setFont(font.handle);
+ } else {
+ ((CControl)handle).getUserAttributeHandler().setFont(null);
+ }
+ handle.repaint();
+}
+
+/**
+ * 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
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setForeground (Color color) {
+ checkWidget ();
+ if (color != null) {
+ if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ ((CControl)handle).getUserAttributeHandler().setForeground(color.handle);
+ } else {
+ ((CControl)handle).getUserAttributeHandler().setForeground (null);
+ }
+ handle.repaint();
+}
+
+//void setForegroundPixel (int pixel) {
+// if (foreground == pixel) return;
+// foreground = pixel;
+// OS.InvalidateRect (handle, null, true);
+//}
+
+/**
+ * Sets the layout data associated with the receiver to the argument.
+ *
+ * @param layoutData the new layout data for the receiver.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setLayoutData (Object layoutData) {
+ checkWidget ();
+ this.layoutData = layoutData;
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setLocation (int x, int y) {
+ checkWidget ();
+ Point offset = parent == null? new Point(0, 0): parent.getInternalOffset();
+ x -= offset.x;
+ y -= offset.y;
+ java.awt.Point location = handle.getLocation();
+ if(location.x == x && location.y == y) return;
+ handle.setLocation(x, y);
+// ((CControl)handle).getClientArea().invalidate();
+// handle.validate();
+ // The notification has to be immediate in SWT, so we force it
+ if(location.x != x || location.y != y) {
+ processEvent(new ComponentEvent(handle, ComponentEvent.COMPONENT_MOVED));
+ }
+ handle.repaint();
+// Container parent = handle.getParent();
+// if(parent != null) {
+// if(parent instanceof JComponent) {
+// ((JComponent)parent).revalidate();
+// } else {
+// parent.invalidate();
+// parent.validate();
+// }
+// parent.repaint();
+// }
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setLocation (Point location) {
+ checkWidget ();
+ if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setLocation (location.x, location.y);
+}
+
+/**
+ * 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.
+ *
+ * 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.
+ *
+ *
+ * @param menu the new pop up menu
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu
+ *
ERROR_INVALID_PARENT - if the menu is not in the same widget tree
+ *
ERROR_INVALID_ARGUMENT - if the menu has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMenu (Menu menu) {
+ checkWidget ();
+ if (menu != null) {
+ if (menu.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if ((menu.style & SWT.POP_UP) == 0) {
+ error (SWT.ERROR_MENU_NOT_POP_UP);
+ }
+ if (menu.parent != menuShell ()) {
+ error (SWT.ERROR_INVALID_PARENT);
+ }
+ }
+ this.menu = menu;
+}
+
+boolean setRadioFocus () {
+ return false;
+}
+
+boolean setRadioSelection (boolean value) {
+ return false;
+}
+
+/**
+ * If the argument is false, 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
+ * false are lost. When the flag is set to true,
+ * the entire widget is marked as needing to be redrawn. Nested calls
+ * to this method are stacked.
+ *
+ * Note: This operation is a hint and may not be supported on some
+ * platforms or for some widgets.
+ *
+ *
+ * @param redraw the new redraw state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #redraw(int, int, int, int, boolean)
+ * @see #update
+ */
+public void setRedraw (boolean redraw) {
+ checkWidget ();
+ handle.setIgnoreRepaint(!redraw);
+}
+
+//boolean setSavedFocus () {
+// return forceFocus ();
+//}
+
+/**
+ * Sets the receiver's size to the point specified by the arguments.
+ *
+ * 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.
+ *
+ *
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSize (int width, int height) {
+ checkWidget ();
+ if(width < 0) width = 0;
+ if(height < 0) height = 0;
+ java.awt.Dimension size = handle.getSize();
+ handle.setSize(width, height);
+ // The notification has to be immediate in SWT, so we force it
+ if(size.width != width || size.height != height) {
+ ((CControl)handle).getClientArea().invalidate();
+ handle.validate();
+ processEvent(new ComponentEvent(handle, ComponentEvent.COMPONENT_RESIZED));
+ }
+ handle.repaint();
+}
+
+/**
+ * Sets the receiver's size to the point specified by the argument.
+ *
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause them to be
+ * set to zero instead.
+ *
+ *
+ * @param size the new size for the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSize (Point size) {
+ checkWidget ();
+ if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSize (size.x, size.y);
+}
+
+boolean setTabGroupFocus () {
+ return setTabItemFocus ();
+}
+
+boolean setTabItemFocus () {
+ if (!handle.isShowing ()) return false;
+ return forceFocus ();
+}
+
+String toolTipText;
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setToolTipText (String string) {
+ checkWidget ();
+ toolTipText = string;
+ ((CControl)handle).setToolTipText(Utils.convertStringToHTML(string));
+}
+
+/**
+ * Marks the receiver as visible if the argument is true,
+ * and marks it invisible otherwise.
+ *
+ * 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.
+ *
+ *
+ * @param visible the new visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setVisible (boolean visible) {
+ checkWidget ();
+ handle.setVisible(visible);
+// if (drawCount != 0) {
+// if (((state & HIDDEN) == 0) == visible) return;
+// } else {
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// if (((bits & OS.WS_VISIBLE) != 0) == visible) return;
+// }
+ // TODO: uncomment the next lines, or attach a listener to components?
+// if (visible) {
+// sendEvent (SWT.Show);
+// if (isDisposed ()) return;
+// }
+
+// /*
+// * Feature in Windows. If the receiver has focus, hiding
+// * 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 (!visible) {
+// if (display.focusEvent != SWT.FocusOut) {
+// control = display.getFocusControl ();
+// fixFocus = isFocusAncestor (control);
+// }
+// }
+// if (drawCount != 0) {
+// state = visible ? state & ~HIDDEN : state | HIDDEN;
+// } else {
+// showWidget (visible);
+// if (isDisposed ()) return;
+// }
+// if (!visible) {
+// sendEvent (SWT.Hide);
+// if (isDisposed ()) return;
+// }
+// if (fixFocus) fixFocus (control);
+}
+
+void sort (int [] items) {
+ /* Shell Sort from K&R, pg 108 */
+ int length = items.length;
+ for (int gap=length/2; gap>0; gap/=2) {
+ for (int i=gap; i=0; j-=gap) {
+ if (items [j] <= items [j + gap]) {
+ int swap = items [j];
+ items [j] = items [j + gap];
+ items [j + gap] = swap;
+ }
+ }
+ }
+ }
+}
+
+//void subclass () {
+// int oldProc = windowProc ();
+// int newProc = display.windowProc;
+// if (oldProc == newProc) return;
+// OS.SetWindowLong (handle, OS.GWL_WNDPROC, newProc);
+//}
+
+/**
+ * Returns a point which is the result of converting the
+ * argument, which is specified in display relative coordinates,
+ * to coordinates relative to the receiver.
+ *
+ * @param x the x coordinate to be translated
+ * @param y the y coordinate to be translated
+ * @return the translated coordinates
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.1
+ */
+public Point toControl (int x, int y) {
+ checkWidget ();
+ java.awt.Point point = new java.awt.Point(x, y);
+ Container container = handle;
+ if(container instanceof RootPaneContainer) {
+ container = ((RootPaneContainer)container).getContentPane();
+ }
+ SwingUtilities.convertPointFromScreen(point, container);
+ return new Point(point.x, point.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.
+ *
+ * @param point the point to be translated (must not be null)
+ * @return the translated coordinates
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+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.
+ *
+ * @param x the x coordinate to be translated
+ * @param y the y coordinate to be translated
+ * @return the translated coordinates
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.1
+ */
+public Point toDisplay (int x, int y) {
+ checkWidget ();
+ java.awt.Point point = new java.awt.Point(x, y);
+ Container container = handle;
+ if(container instanceof RootPaneContainer) {
+ container = ((RootPaneContainer)container).getContentPane();
+ }
+ SwingUtilities.convertPointToScreen(point, container);
+ return new Point(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.
+ *
+ * @param point the point to be translated (must not be null)
+ * @return the translated coordinates
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point toDisplay (Point point) {
+ checkWidget ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ return toDisplay (point.x, point.y);
+}
+
+//int topHandle () {
+// return handle;
+//}
+
+//boolean translateAccelerator (MSG msg) {
+// return menuShell ().translateAccelerator (msg);
+//}
+
+boolean translateMnemonic (Event event, Control control) {
+ if (control == this) return false;
+ if (!isVisible () || !isEnabled ()) return false;
+ event.doit = mnemonicMatch (event.character);
+ return traverse (event);
+}
+
+//boolean translateMnemonic (MSG msg) {
+// if (msg.wParam < 0x20) return false;
+// int hwnd = msg.hwnd;
+// if (OS.GetKeyState (OS.VK_MENU) >= 0) {
+// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+// if ((code & OS.DLGC_WANTALLKEYS) != 0) return false;
+// if ((code & OS.DLGC_BUTTON) == 0) return false;
+// }
+// Decorations shell = menuShell ();
+// if (shell.isVisible () && shell.isEnabled ()) {
+// display.lastAscii = msg.wParam;
+// display.lastNull = display.lastDead = false;
+// Event event = new Event ();
+// event.detail = SWT.TRAVERSE_MNEMONIC;
+// if (setKeyState (event, SWT.Traverse, msg.wParam, msg.lParam)) {
+// return translateMnemonic (event, null) || shell.translateMnemonic (event, this);
+// }
+// }
+// return false;
+//}
+//
+//boolean translateTraversal (MSG msg) {
+// int key = msg.wParam;
+// if (key == OS.VK_MENU) {
+// Shell shell = getShell ();
+// int hwndShell = shell.handle;
+// OS.SendMessage (hwndShell, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+// return false;
+// }
+// int hwnd = msg.hwnd;
+// int detail = SWT.TRAVERSE_NONE;
+// boolean doit = true, all = false;
+// boolean lastVirtual = false;
+// int lastKey = key, lastAscii = 0;
+// switch (key) {
+// case OS.VK_ESCAPE: {
+// all = true;
+// lastAscii = 27;
+// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+// if ((code & OS.DLGC_WANTALLKEYS) != 0) {
+// /*
+// * Use DLGC_HASSETSEL to determine that the control
+// * is a text widget. A text widget normally wants
+// * all keys except VK_ESCAPE. If this bit is not
+// * set, then assume the control wants all keys,
+// * including VK_ESCAPE.
+// */
+// if ((code & OS.DLGC_HASSETSEL) == 0) doit = false;
+// }
+// detail = SWT.TRAVERSE_ESCAPE;
+// break;
+// }
+// case OS.VK_RETURN: {
+// all = true;
+// lastAscii = '\r';
+// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+// if ((code & OS.DLGC_WANTALLKEYS) != 0) doit = false;
+// detail = SWT.TRAVERSE_RETURN;
+// break;
+// }
+// case OS.VK_TAB: {
+// lastAscii = '\t';
+// boolean next = OS.GetKeyState (OS.VK_SHIFT) >= 0;
+// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+// if ((code & (OS.DLGC_WANTTAB | OS.DLGC_WANTALLKEYS)) != 0) {
+// /*
+// * Use DLGC_HASSETSEL to determine that the control is a
+// * text widget. If the control is a text widget, then
+// * Ctrl+Tab and Shift+Tab should traverse out of the widget.
+// * If the control is not a text widget, the correct behavior
+// * is to give every character, including Tab, Ctrl+Tab and
+// * Shift+Tab to the control.
+// */
+// if ((code & OS.DLGC_HASSETSEL) != 0) {
+// if (next && OS.GetKeyState (OS.VK_CONTROL) >= 0) {
+// doit = false;
+// }
+// } else {
+// doit = false;
+// }
+// }
+// if (parent != null && (parent.style & SWT.MIRRORED) != 0) {
+// if (key == OS.VK_LEFT || key == OS.VK_RIGHT) next = !next;
+// }
+// detail = next ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS;
+// break;
+// }
+// case OS.VK_UP:
+// case OS.VK_LEFT:
+// case OS.VK_DOWN:
+// case OS.VK_RIGHT: {
+// /*
+// * On WinCE SP there is no tab key. Focus is assigned
+// * using the VK_UP and VK_DOWN keys, not with VK_LEFT
+// * or VK_RIGHT.
+// */
+// if (OS.IsSP) {
+// if (key == OS.VK_LEFT || key == OS.VK_RIGHT) return false;
+// }
+// lastVirtual = true;
+// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+// if ((code & (OS.DLGC_WANTARROWS /*| OS.DLGC_WANTALLKEYS*/)) != 0) doit = false;
+// boolean next = key == OS.VK_DOWN || key == OS.VK_RIGHT;
+// detail = next ? SWT.TRAVERSE_ARROW_NEXT : SWT.TRAVERSE_ARROW_PREVIOUS;
+// break;
+// }
+// case OS.VK_PRIOR:
+// case OS.VK_NEXT: {
+// all = true;
+// lastVirtual = true;
+// if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false;
+// int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+// if ((code & OS.DLGC_WANTALLKEYS) != 0) {
+// /*
+// * Use DLGC_HASSETSEL to determine that the control is a
+// * text widget. If the control is a text widget, then
+// * Ctrl+PgUp and Ctrl+PgDn should traverse out of the widget.
+// */
+// if ((code & OS.DLGC_HASSETSEL) == 0) doit = false;
+// }
+// detail = key == OS.VK_PRIOR ? SWT.TRAVERSE_PAGE_PREVIOUS : SWT.TRAVERSE_PAGE_NEXT;
+// break;
+// }
+// default:
+// return false;
+// }
+// Event event = new Event ();
+// event.doit = doit;
+// event.detail = detail;
+// display.lastKey = lastKey;
+// display.lastAscii = lastAscii;
+// display.lastVirtual = lastVirtual;
+// display.lastNull = display.lastDead = false;
+// if (!setKeyState (event, SWT.Traverse, msg.wParam, msg.lParam)) return false;
+// Shell shell = getShell ();
+// Control control = this;
+// do {
+// if (control.traverse (event)) {
+// int hwndShell = shell.handle;
+// OS.SendMessage (hwndShell, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+// return true;
+// }
+// if (!event.doit && control.hooks (SWT.Traverse)) return false;
+// if (control == shell) return false;
+// control = control.parent;
+// } while (all && control != null);
+// return false;
+//}
+
+boolean traverse (Event event) {
+ /*
+ * It is possible (but unlikely), that application
+ * code could have disposed the widget in the traverse
+ * event. If this happens, return true to stop further
+ * event processing.
+ */
+ sendEvent (SWT.Traverse, event);
+ if (isDisposed ()) return true;
+ if (!event.doit) return false;
+ switch (event.detail) {
+ case SWT.TRAVERSE_NONE: return true;
+ case SWT.TRAVERSE_ESCAPE: return traverseEscape ();
+ case SWT.TRAVERSE_RETURN: return traverseReturn ();
+ case SWT.TRAVERSE_TAB_NEXT: return traverseGroup (true);
+ case SWT.TRAVERSE_TAB_PREVIOUS: return traverseGroup (false);
+ case SWT.TRAVERSE_ARROW_NEXT: return traverseItem (true);
+ case SWT.TRAVERSE_ARROW_PREVIOUS: return traverseItem (false);
+ case SWT.TRAVERSE_MNEMONIC: return traverseMnemonic (event.character);
+ case SWT.TRAVERSE_PAGE_NEXT: return traversePage (true);
+ case SWT.TRAVERSE_PAGE_PREVIOUS: return traversePage (false);
+ }
+ return false;
+}
+
+/**
+ * Based on the argument, perform one of the expected platform
+ * traversal action. The argument should be one of the constants:
+ * SWT.TRAVERSE_ESCAPE, SWT.TRAVERSE_RETURN,
+ * SWT.TRAVERSE_TAB_NEXT, SWT.TRAVERSE_TAB_PREVIOUS,
+ * SWT.TRAVERSE_ARROW_NEXT and SWT.TRAVERSE_ARROW_PREVIOUS.
+ *
+ * @param traversal the type of traversal
+ * @return true if the traversal succeeded
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean traverse (int traversal) {
+ checkWidget ();
+ Event event = new Event ();
+ event.doit = true;
+ event.detail = traversal;
+ return traverse (event);
+}
+
+boolean traverseEscape () {
+ return false;
+}
+
+boolean traverseGroup (boolean next) {
+ Control root = computeTabRoot ();
+ Control group = computeTabGroup ();
+ Control [] list = root.computeTabList ();
+ int length = list.length;
+ int index = 0;
+ while (index < length) {
+ if (list [index] == group) break;
+ index++;
+ }
+ /*
+ * It is possible (but unlikely), that application
+ * code could have disposed the widget in focus in
+ * or out events. Ensure that a disposed widget is
+ * not accessed.
+ */
+ if (index == length) return false;
+ int start = index, offset = (next) ? 1 : -1;
+ while ((index = ((index + offset + length) % length)) != start) {
+ Control control = list [index];
+ if (!control.isDisposed () && control.setTabGroupFocus ()) {
+ return true;
+ }
+ }
+ if (group.isDisposed ()) return false;
+ return group.setTabGroupFocus ();
+}
+
+boolean traverseItem (boolean next) {
+ Control [] children = parent._getChildren ();
+ int length = children.length;
+ int index = 0;
+ while (index < length) {
+ if (children [index] == this) break;
+ index++;
+ }
+ /*
+ * It is possible (but unlikely), that application
+ * code could have disposed the widget in focus in
+ * or out events. Ensure that a disposed widget is
+ * not accessed.
+ */
+ if (index == length) return false;
+ int start = index, offset = (next) ? 1 : -1;
+ while ((index = (index + offset + length) % length) != start) {
+ Control child = children [index];
+ if (!child.isDisposed () && child.isTabItem ()) {
+ if (child.setTabItemFocus ()) return true;
+ }
+ }
+ return false;
+}
+
+boolean traverseMnemonic (char key) {
+ return mnemonicHit (key);
+}
+
+boolean traversePage (boolean next) {
+ return false;
+}
+
+boolean traverseReturn () {
+ return false;
+}
+
+//void unsubclass () {
+// int newProc = windowProc ();
+// int oldProc = display.windowProc;
+// if (oldProc == newProc) return;
+// OS.SetWindowLong (handle, OS.GWL_WNDPROC, newProc);
+//}
+
+/**
+ * Forces all outstanding paint requests for the widget
+ * to be processed before this method returns.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #redraw(int, int, int, int, boolean)
+ * @see PaintListener
+ * @see SWT#Paint
+ */
+public void update () {
+ checkWidget ();
+ Utils.paintComponentImmediately(handle);
+// update (false);
+}
+
+//void update (boolean all) {
+//// checkWidget ();
+// if (OS.IsWinCE) {
+// OS.UpdateWindow (handle);
+// } else {
+// int flags = OS.RDW_UPDATENOW;
+// if (all) flags |= OS.RDW_ALLCHILDREN;
+// OS.RedrawWindow (handle, null, 0, flags);
+// }
+//}
+//
+//boolean updateFont (Font oldFont, Font newFont) {
+// boolean sameFont = getFont ().equals (oldFont);
+// /*
+// * If the font that the control is using is the
+// * same one that was being used from the Control
+// * Panel, then use the new Control Panel font.
+// */
+// if (sameFont) setFont (newFont);
+// return sameFont;
+//}
+
+void updateBackgroundMode() {
+ switch(parent.getBackgroundMode()) {
+ case SWT.INHERIT_NONE: ((CControl)handle).setBackgroundInheritance(CControl.NO_BACKGROUND_INHERITANCE); break;
+ case SWT.INHERIT_DEFAULT: ((CControl)handle).setBackgroundInheritance(CControl.PREFERRED_BACKGROUND_INHERITANCE); break;
+ case SWT.INHERIT_FORCE: ((CControl)handle).setBackgroundInheritance(CControl.BACKGROUND_INHERITANCE); break;
+ }
+ handle.repaint();
+}
+
+void updateLayout (boolean resize, boolean all) {
+ /* Do nothing */
+}
+
+//CREATESTRUCT widgetCreateStruct () {
+// return null;
+//}
+//
+//int widgetExtStyle () {
+// int bits = 0;
+// if (!OS.IsPPC) {
+// if ((style & SWT.BORDER) != 0) bits |= OS.WS_EX_CLIENTEDGE;
+// }
+//// if ((style & SWT.BORDER) != 0) {
+//// if ((style & SWT.FLAT) == 0) bits |= OS.WS_EX_CLIENTEDGE;
+//// }
+// /*
+// * Feature in Windows NT. When CreateWindowEx() is called with
+// * WS_EX_LAYOUTRTL or WS_EX_NOINHERITLAYOUT, CreateWindowEx()
+// * fails to create the HWND. The fix is to not use these bits.
+// */
+// if (OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+// return bits;
+// }
+// bits |= OS.WS_EX_NOINHERITLAYOUT;
+// if ((style & SWT.RIGHT_TO_LEFT) != 0) bits |= OS.WS_EX_LAYOUTRTL;
+// return bits;
+//}
+//
+//int widgetParent () {
+// return parent.handle;
+//}
+//
+//int widgetStyle () {
+// /* Force clipping of siblings by setting WS_CLIPSIBLINGS */
+// int bits = OS.WS_CHILD | OS.WS_VISIBLE | OS.WS_CLIPSIBLINGS;
+//// if ((style & SWT.BORDER) != 0) {
+//// if ((style & SWT.FLAT) != 0) bits |= OS.WS_BORDER;
+//// }
+// if (OS.IsPPC) {
+// if ((style & SWT.BORDER) != 0) bits |= OS.WS_BORDER;
+// }
+// return bits;
+//
+// /*
+// * This code is intentionally commented. When clipping
+// * of both siblings and children is not enforced, it is
+// * possible for application code to draw outside of the
+// * control.
+// */
+//// int bits = OS.WS_CHILD | OS.WS_VISIBLE;
+//// if ((style & SWT.CLIP_SIBLINGS) != 0) bits |= OS.WS_CLIPSIBLINGS;
+//// if ((style & SWT.CLIP_CHILDREN) != 0) bits |= OS.WS_CLIPCHILDREN;
+//// return bits;
+//}
+
+/**
+ * Changes the parent of the widget to be the one provided if
+ * the underlying operating system supports this feature.
+ * Returns true if the parent is successfully changed.
+ *
+ * @param parent the new parent for the control.
+ * @return true if the parent is changed and false otherwise.
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean setParent (Composite parent) {
+ checkWidget ();
+ if (parent == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (parent.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.parent == parent) return true;
+ if (!isReparentable ()) return false;
+ releaseParent ();
+ Shell newShell = parent.getShell (), oldShell = getShell ();
+ Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell ();
+ if (oldShell != newShell || oldDecorations != newDecorations) {
+ Menu [] menus = oldShell.findMenus (this);
+ fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
+ }
+ ((CControl)parent.handle).getClientArea().add(handle);
+ updateBackgroundMode();
+// int topHandle = topHandle ();
+// if (OS.SetParent (topHandle, parent.handle) == 0) return false;
+// this.parent = parent;
+// int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+// SetWindowPos (topHandle, OS.HWND_BOTTOM, 0, 0, 0, 0, flags);
+ return true;
+}
+
+//abstract TCHAR windowClass ();
+//
+//abstract int windowProc ();
+//
+//int windowProc (int hwnd, int msg, int wParam, int lParam) {
+// LRESULT result = null;
+// switch (msg) {
+// case OS.WM_ACTIVATE: result = WM_ACTIVATE (wParam, lParam); break;
+// case OS.WM_CAPTURECHANGED: result = WM_CAPTURECHANGED (wParam, lParam); break;
+// case OS.WM_CHAR: result = WM_CHAR (wParam, lParam); break;
+// case OS.WM_CLEAR: result = WM_CLEAR (wParam, lParam); break;
+// case OS.WM_CLOSE: result = WM_CLOSE (wParam, lParam); break;
+// case OS.WM_COMMAND: result = WM_COMMAND (wParam, lParam); break;
+// case OS.WM_CONTEXTMENU: result = WM_CONTEXTMENU (wParam, lParam); break;
+// case OS.WM_CTLCOLORBTN:
+// case OS.WM_CTLCOLORDLG:
+// case OS.WM_CTLCOLOREDIT:
+// case OS.WM_CTLCOLORLISTBOX:
+// case OS.WM_CTLCOLORMSGBOX:
+// case OS.WM_CTLCOLORSCROLLBAR:
+// case OS.WM_CTLCOLORSTATIC: result = WM_CTLCOLOR (wParam, lParam); break;
+// case OS.WM_CUT: result = WM_CUT (wParam, lParam); break;
+// case OS.WM_DESTROY: result = WM_DESTROY (wParam, lParam); break;
+// case OS.WM_DRAWITEM: result = WM_DRAWITEM (wParam, lParam); break;
+// case OS.WM_ENDSESSION: result = WM_ENDSESSION (wParam, lParam); break;
+// case OS.WM_ENTERIDLE: result = WM_ENTERIDLE (wParam, lParam); break;
+// case OS.WM_ERASEBKGND: result = WM_ERASEBKGND (wParam, lParam); break;
+// case OS.WM_GETDLGCODE: result = WM_GETDLGCODE (wParam, lParam); break;
+// case OS.WM_GETFONT: result = WM_GETFONT (wParam, lParam); break;
+// case OS.WM_GETOBJECT: result = WM_GETOBJECT (wParam, lParam); break;
+// case OS.WM_GETMINMAXINFO: result = WM_GETMINMAXINFO (wParam, lParam); break;
+// case OS.WM_HELP: result = WM_HELP (wParam, lParam); break;
+// case OS.WM_HSCROLL: result = WM_HSCROLL (wParam, lParam); break;
+// case OS.WM_IME_CHAR: result = WM_IME_CHAR (wParam, lParam); break;
+// case OS.WM_IME_COMPOSITION: result = WM_IME_COMPOSITION (wParam, lParam); break;
+// case OS.WM_INITMENUPOPUP: result = WM_INITMENUPOPUP (wParam, lParam); break;
+// case OS.WM_INPUTLANGCHANGE: result = WM_INPUTLANGCHANGE (wParam, lParam); break;
+// case OS.WM_HOTKEY: result = WM_HOTKEY (wParam, lParam); break;
+// case OS.WM_KEYDOWN: result = WM_KEYDOWN (wParam, lParam); break;
+// case OS.WM_KEYUP: result = WM_KEYUP (wParam, lParam); break;
+// case OS.WM_KILLFOCUS: result = WM_KILLFOCUS (wParam, lParam); break;
+// case OS.WM_LBUTTONDBLCLK: result = WM_LBUTTONDBLCLK (wParam, lParam); break;
+// case OS.WM_LBUTTONDOWN: result = WM_LBUTTONDOWN (wParam, lParam); break;
+// case OS.WM_LBUTTONUP: result = WM_LBUTTONUP (wParam, lParam); break;
+// case OS.WM_MBUTTONDBLCLK: result = WM_MBUTTONDBLCLK (wParam, lParam); break;
+// case OS.WM_MBUTTONDOWN: result = WM_MBUTTONDOWN (wParam, lParam); break;
+// case OS.WM_MBUTTONUP: result = WM_MBUTTONUP (wParam, lParam); break;
+// case OS.WM_MEASUREITEM: result = WM_MEASUREITEM (wParam, lParam); break;
+// case OS.WM_MENUCHAR: result = WM_MENUCHAR (wParam, lParam); break;
+// case OS.WM_MENUSELECT: result = WM_MENUSELECT (wParam, lParam); break;
+// case OS.WM_MOUSEACTIVATE: result = WM_MOUSEACTIVATE (wParam, lParam); break;
+// case OS.WM_MOUSEHOVER: result = WM_MOUSEHOVER (wParam, lParam); break;
+// case OS.WM_MOUSELEAVE: result = WM_MOUSELEAVE (wParam, lParam); break;
+// case OS.WM_MOUSEMOVE: result = WM_MOUSEMOVE (wParam, lParam); break;
+// case OS.WM_MOUSEWHEEL: result = WM_MOUSEWHEEL (wParam, lParam); break;
+// case OS.WM_MOVE: result = WM_MOVE (wParam, lParam); break;
+// case OS.WM_NCACTIVATE: result = WM_NCACTIVATE (wParam, lParam); break;
+// case OS.WM_NCCALCSIZE: result = WM_NCCALCSIZE (wParam, lParam); break;
+// case OS.WM_NCHITTEST: result = WM_NCHITTEST (wParam, lParam); break;
+// case OS.WM_NCLBUTTONDOWN: result = WM_NCLBUTTONDOWN (wParam, lParam); break;
+// case OS.WM_NOTIFY: result = WM_NOTIFY (wParam, lParam); break;
+// case OS.WM_PAINT: result = WM_PAINT (wParam, lParam); break;
+// case OS.WM_PALETTECHANGED: result = WM_PALETTECHANGED (wParam, lParam); break;
+// case OS.WM_PARENTNOTIFY: result = WM_PARENTNOTIFY (wParam, lParam); break;
+// case OS.WM_PASTE: result = WM_PASTE (wParam, lParam); break;
+// case OS.WM_PRINTCLIENT: result = WM_PRINTCLIENT (wParam, lParam); break;
+// case OS.WM_QUERYENDSESSION: result = WM_QUERYENDSESSION (wParam, lParam); break;
+// case OS.WM_QUERYNEWPALETTE: result = WM_QUERYNEWPALETTE (wParam, lParam); break;
+// case OS.WM_QUERYOPEN: result = WM_QUERYOPEN (wParam, lParam); break;
+// case OS.WM_RBUTTONDBLCLK: result = WM_RBUTTONDBLCLK (wParam, lParam); break;
+// case OS.WM_RBUTTONDOWN: result = WM_RBUTTONDOWN (wParam, lParam); break;
+// case OS.WM_RBUTTONUP: result = WM_RBUTTONUP (wParam, lParam); break;
+// case OS.WM_SETCURSOR: result = WM_SETCURSOR (wParam, lParam); break;
+// case OS.WM_SETFOCUS: result = WM_SETFOCUS (wParam, lParam); break;
+// case OS.WM_SETFONT: result = WM_SETFONT (wParam, lParam); break;
+// case OS.WM_SETTINGCHANGE: result = WM_SETTINGCHANGE (wParam, lParam); break;
+// case OS.WM_SETREDRAW: result = WM_SETREDRAW (wParam, lParam); break;
+// case OS.WM_SHOWWINDOW: result = WM_SHOWWINDOW (wParam, lParam); break;
+// case OS.WM_SIZE: result = WM_SIZE (wParam, lParam); break;
+// case OS.WM_SYSCHAR: result = WM_SYSCHAR (wParam, lParam); break;
+// case OS.WM_SYSCOLORCHANGE: result = WM_SYSCOLORCHANGE (wParam, lParam); break;
+// case OS.WM_SYSCOMMAND: result = WM_SYSCOMMAND (wParam, lParam); break;
+// case OS.WM_SYSKEYDOWN: result = WM_SYSKEYDOWN (wParam, lParam); break;
+// case OS.WM_SYSKEYUP: result = WM_SYSKEYUP (wParam, lParam); break;
+// case OS.WM_TIMER: result = WM_TIMER (wParam, lParam); break;
+// case OS.WM_UNDO: result = WM_UNDO (wParam, lParam); break;
+// case OS.WM_VSCROLL: result = WM_VSCROLL (wParam, lParam); break;
+// case OS.WM_WINDOWPOSCHANGED: result = WM_WINDOWPOSCHANGED (wParam, lParam); break;
+// case OS.WM_WINDOWPOSCHANGING: result = WM_WINDOWPOSCHANGING (wParam, lParam); break;
+// case OS.WM_XBUTTONDBLCLK: result = WM_XBUTTONDBLCLK (wParam, lParam); break;
+// case OS.WM_XBUTTONDOWN: result = WM_XBUTTONDOWN (wParam, lParam); break;
+// case OS.WM_XBUTTONUP: result = WM_XBUTTONUP (wParam, lParam); break;
+// }
+// if (result != null) return result.value;
+// return callWindowProc (hwnd, msg, wParam, lParam);
+//}
+//
+//LRESULT WM_ACTIVATE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_CAPTURECHANGED (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_CHAR (int wParam, int lParam) {
+// return wmChar (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_CLEAR (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_CLOSE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_COMMAND (int wParam, int lParam) {
+// /*
+// * When the WM_COMMAND message is sent from a
+// * menu, the HWND parameter in LPARAM is zero.
+// */
+// if (lParam == 0) {
+// Decorations shell = menuShell ();
+// if (shell.isEnabled ()) {
+// int id = wParam & 0xFFFF;
+// MenuItem item = display.getMenuItem (id);
+// if (item != null && item.isEnabled ()) {
+// return item.wmCommandChild (wParam, lParam);
+// }
+// }
+// return null;
+// }
+// Control control = display.getControl (lParam);
+// if (control == null) return null;
+// return control.wmCommandChild (wParam, lParam);
+//}
+//
+//LRESULT WM_CONTEXTMENU (int wParam, int lParam) {
+// return wmContextMenu (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_CTLCOLOR (int wParam, int lParam) {
+// int hPalette = display.hPalette;
+// if (hPalette != 0) {
+// OS.SelectPalette (wParam, hPalette, false);
+// OS.RealizePalette (wParam);
+// }
+// Control control = display.getControl (lParam);
+// if (control == null) return null;
+// return control.wmColorChild (wParam, lParam);
+//}
+//
+//LRESULT WM_CUT (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_DESTROY (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_DRAWITEM (int wParam, int lParam) {
+// DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
+// OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
+// if (struct.CtlType == OS.ODT_MENU) {
+// MenuItem item = display.getMenuItem (struct.itemID);
+// if (item == null) return null;
+// return item.wmDrawChild (wParam, lParam);
+// }
+// Control control = display.getControl (struct.hwndItem);
+// if (control == null) return null;
+// return control.wmDrawChild (wParam, lParam);
+//}
+//
+//LRESULT WM_ENDSESSION (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_ENTERIDLE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_GETFONT (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_GETOBJECT (int wParam, int lParam) {
+// if (accessible != null) {
+// int result = accessible.internal_WM_GETOBJECT (wParam, lParam);
+// if (result != 0) return new LRESULT (result);
+// }
+// return null;
+//}
+//
+//LRESULT WM_GETMINMAXINFO (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_HOTKEY (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_HELP (int wParam, int lParam) {
+// if (OS.IsWinCE) return null;
+// HELPINFO lphi = new HELPINFO ();
+// OS.MoveMemory (lphi, lParam, HELPINFO.sizeof);
+// Decorations shell = menuShell ();
+// if (!shell.isEnabled ()) return null;
+// if (lphi.iContextType == OS.HELPINFO_MENUITEM) {
+// MenuItem item = display.getMenuItem (lphi.iCtrlId);
+// if (item != null && item.isEnabled ()) {
+// Widget widget = null;
+// if (item.hooks (SWT.Help)) {
+// widget = item;
+// } else {
+// Menu menu = item.parent;
+// if (menu.hooks (SWT.Help)) widget = menu;
+// }
+// if (widget != null) {
+// int hwndShell = shell.handle;
+// OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0);
+// widget.postEvent (SWT.Help);
+// return LRESULT.ONE;
+// }
+// }
+// return null;
+// }
+// if (hooks (SWT.Help)) {
+// postEvent (SWT.Help);
+// return LRESULT.ONE;
+// }
+// return null;
+//}
+//
+//LRESULT WM_HSCROLL (int wParam, int lParam) {
+// if (lParam == 0) return null;
+// Control control = display.getControl (lParam);
+// if (control == null) return null;
+// return control.wmScrollChild (wParam, lParam);
+//}
+//
+//LRESULT WM_IME_CHAR (int wParam, int lParam) {
+// return wmIMEChar (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_IME_COMPOSITION (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_INITMENUPOPUP (int wParam, int lParam) {
+//
+// /* Ignore WM_INITMENUPOPUP for an accelerator */
+// if (display.accelKeyHit) return null;
+//
+// /*
+// * If the high order word of LPARAM is non-zero,
+// * the menu is the system menu and we can ignore
+// * WPARAM. Otherwise, use WPARAM to find the menu.
+// */
+// Shell shell = getShell ();
+// Menu oldMenu = shell.activeMenu, newMenu = null;
+// if ((lParam >> 16) == 0) {
+// newMenu = menuShell ().findMenu (wParam);
+// }
+// Menu menu = newMenu;
+// while (menu != null && menu != oldMenu) {
+// menu = menu.getParentMenu ();
+// }
+// if (menu == null) {
+// menu = shell.activeMenu;
+// while (menu != null) {
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the hide
+// * event. If this happens, stop searching up the
+// * ancestor list because there is no longer a link
+// * to follow.
+// */
+// menu.sendEvent (SWT.Hide);
+// if (menu.isDisposed ()) break;
+// menu = menu.getParentMenu ();
+// Menu ancestor = newMenu;
+// while (ancestor != null && ancestor != menu) {
+// ancestor = ancestor.getParentMenu ();
+// }
+// if (ancestor != null) break;
+// }
+// }
+//
+// /*
+// * The shell and the new menu may be disposed because of
+// * sending the hide event to the ancestor menus but setting
+// * a field to null in a disposed shell is not harmful.
+// */
+// if (newMenu != null && newMenu.isDisposed ()) newMenu = null;
+// shell.activeMenu = newMenu;
+//
+// /* Send the show event */
+// if (newMenu != null && newMenu != oldMenu) {
+// newMenu.sendEvent (SWT.Show);
+// // widget could be disposed at this point
+// }
+// return null;
+//}
+//
+//LRESULT WM_INPUTLANGCHANGE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_KEYDOWN (int wParam, int lParam) {
+// return wmKeyDown (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_KEYUP (int wParam, int lParam) {
+// return wmKeyUp (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+// return wmKillFocus (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
+// return wmLButtonDblClk (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+// return wmLButtonDown (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_LBUTTONUP (int wParam, int lParam) {
+// return wmLButtonUp (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_MBUTTONDBLCLK (int wParam, int lParam) {
+// return wmMButtonDblClk (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_MBUTTONDOWN (int wParam, int lParam) {
+// return wmMButtonDown (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_MBUTTONUP (int wParam, int lParam) {
+// return wmMButtonUp (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_MEASUREITEM (int wParam, int lParam) {
+// MEASUREITEMSTRUCT struct = new MEASUREITEMSTRUCT ();
+// OS.MoveMemory (struct, lParam, MEASUREITEMSTRUCT.sizeof);
+// if (struct.CtlType == OS.ODT_MENU) {
+// MenuItem item = display.getMenuItem (struct.itemID);
+// if (item == null) return null;
+// return item.wmMeasureChild (wParam, lParam);
+// }
+// int hwnd = OS.GetDlgItem (handle, struct.CtlID);
+// Control control = display.getControl (hwnd);
+// if (control == null) return null;
+// return control.wmMeasureChild (wParam, lParam);
+//}
+//
+//LRESULT WM_MENUCHAR (int wParam, int lParam) {
+// /*
+// * Feature in Windows. When the user types Alt+
+// * and does not match a mnemonic in the System
+// * menu or the menu bar, Windows beeps. This beep is
+// * unexpected and unwanted by applications that look
+// * for Alt+. The fix is to detect the case and
+// * stop Windows from beeping by closing the menu.
+// */
+// int type = wParam >> 16;
+// if (type == 0 || type == OS.MF_SYSMENU) {
+// display.mnemonicKeyHit = false;
+// return new LRESULT (OS.MNC_CLOSE << 16);
+// }
+// return null;
+//}
+//
+//LRESULT WM_MENUSELECT (int wParam, int lParam) {
+// int code = wParam >> 16;
+// Shell shell = getShell ();
+// if (code == -1 && lParam == 0) {
+// Menu menu = shell.activeMenu;
+// while (menu != null) {
+// /*
+// * When the user cancels any menu that is not the
+// * menu bar, assume a mnemonic key was pressed to open
+// * the menu from WM_SYSCHAR. When the menu was invoked
+// * using the mouse, this assumption is wrong but not
+// * harmful. This variable is only used in WM_SYSCHAR
+// * and WM_SYSCHAR is only sent after the user has pressed
+// * a mnemonic.
+// */
+// display.mnemonicKeyHit = true;
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the hide
+// * event. If this happens, stop searching up the
+// * parent list because there is no longer a link
+// * to follow.
+// */
+// menu.sendEvent (SWT.Hide);
+// if (menu.isDisposed ()) break;
+// menu = menu.getParentMenu ();
+// }
+// /*
+// * The shell may be disposed because of sending the hide
+// * event to the last active menu menu but setting a field
+// * to null in a destroyed widget is not harmful.
+// */
+// shell.activeMenu = null;
+// return null;
+// }
+// if ((code & OS.MF_SYSMENU) != 0) return null;
+// if ((code & OS.MF_HILITE) != 0) {
+// MenuItem item = null;
+// Decorations menuShell = menuShell ();
+// if ((code & OS.MF_POPUP) != 0) {
+// int index = wParam & 0xFFFF;
+// MENUITEMINFO info = new MENUITEMINFO ();
+// info.cbSize = MENUITEMINFO.sizeof;
+// info.fMask = OS.MIIM_SUBMENU;
+// if (OS.GetMenuItemInfo (lParam, index, true, info)) {
+// Menu newMenu = menuShell.findMenu (info.hSubMenu);
+// if (newMenu != null) item = newMenu.cascade;
+// }
+// } else {
+// Menu newMenu = menuShell.findMenu (lParam);
+// if (newMenu != null) {
+// int id = wParam & 0xFFFF;
+// item = display.getMenuItem (id);
+// }
+// Menu oldMenu = shell.activeMenu;
+// if (oldMenu != null) {
+// Menu ancestor = oldMenu;
+// while (ancestor != null && ancestor != newMenu) {
+// ancestor = ancestor.getParentMenu ();
+// }
+// if (ancestor == newMenu) {
+// ancestor = oldMenu;
+// while (ancestor != newMenu) {
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the hide
+// * event or the item about to be armed. If this
+// * happens, stop searching up the ancestor list
+// * because there is no longer a link to follow.
+// */
+// ancestor.sendEvent (SWT.Hide);
+// if (ancestor.isDisposed ()) break;
+// ancestor = ancestor.getParentMenu ();
+// }
+// /*
+// * The shell and/or the item could be disposed when
+// * processing hide events from above. If this happens,
+// * ensure that the shell is not accessed and that no
+// * arm event is sent to the item.
+// */
+// if (!shell.isDisposed ()) {
+// if (newMenu != null && newMenu.isDisposed ()) {
+// newMenu = null;
+// }
+// shell.activeMenu = newMenu;
+// }
+// if (item != null && item.isDisposed ()) item = null;
+// }
+// }
+// }
+// if (item != null) item.sendEvent (SWT.Arm);
+// }
+// return null;
+//}
+//
+//LRESULT WM_MOUSEACTIVATE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_MOUSEHOVER (int wParam, int lParam) {
+// return wmMouseHover (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_MOUSELEAVE (int wParam, int lParam) {
+// return wmMouseLeave (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_MOUSEMOVE (int wParam, int lParam) {
+// return wmMouseMove (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_MOUSEWHEEL (int wParam, int lParam) {
+// return wmMouseWheel (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_MOVE (int wParam, int lParam) {
+// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+// if (OS.IsWindowVisible (handle)) {
+// if (findThemeControl () != null) {
+// int flags = OS.RDW_ERASE | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+// OS.RedrawWindow (handle, null, 0, flags);
+// }
+// }
+// }
+// sendEvent (SWT.Move);
+// // widget could be disposed at this point
+// return null;
+//}
+//
+//LRESULT WM_NCACTIVATE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_NCCALCSIZE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_NCHITTEST (int wParam, int lParam) {
+// if (!OS.IsWindowEnabled (handle)) return null;
+// if (!isActive ()) return new LRESULT (OS.HTTRANSPARENT);
+// return null;
+//}
+//
+//LRESULT WM_NCLBUTTONDOWN (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_NOTIFY (int wParam, int lParam) {
+// NMHDR hdr = new NMHDR ();
+// OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+// int hwnd = hdr.hwndFrom;
+// if (hwnd == 0) return null;
+// Control control = display.getControl (hwnd);
+// if (control == null) return null;
+// return control.wmNotifyChild (wParam, lParam);
+//}
+//
+//LRESULT WM_PAINT (int wParam, int lParam) {
+// return super.wmPaint (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_PALETTECHANGED (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_PARENTNOTIFY (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_PASTE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_PRINTCLIENT (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_QUERYENDSESSION (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_QUERYNEWPALETTE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_QUERYOPEN (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_RBUTTONDBLCLK (int wParam, int lParam) {
+// return wmRButtonDblClk (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_RBUTTONDOWN (int wParam, int lParam) {
+// return wmRButtonDown (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_RBUTTONUP (int wParam, int lParam) {
+// return wmRButtonUp (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_SETCURSOR (int wParam, int lParam) {
+// int hitTest = (short) (lParam & 0xFFFF);
+// if (hitTest == OS.HTCLIENT) {
+// Control control = display.getControl (wParam);
+// if (control == null) return null;
+// Cursor cursor = control.findCursor ();
+// if (cursor != null) {
+// OS.SetCursor (cursor.handle);
+// return LRESULT.ONE;
+// }
+// }
+// return null;
+//}
+//
+//LRESULT WM_SETFOCUS (int wParam, int lParam) {
+// return wmSetFocus (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_SETTINGCHANGE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_SETFONT (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_SETREDRAW (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_SHOWWINDOW (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_SIZE (int wParam, int lParam) {
+// sendEvent (SWT.Resize);
+// // widget could be disposed at this point
+// return null;
+//}
+//
+//LRESULT WM_SYSCHAR (int wParam, int lParam) {
+// return wmSysChar (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
+// /*
+// * Check to see if the command is a system command or
+// * a user menu item that was added to the System menu.
+// * When a user item is added to the System menu,
+// * WM_SYSCOMMAND must always return zero.
+// */
+// if ((wParam & 0xF000) == 0) {
+// Decorations shell = menuShell ();
+// if (shell.isEnabled ()) {
+// MenuItem item = display.getMenuItem (wParam & 0xFFFF);
+// if (item != null) item.wmCommandChild (wParam, lParam);
+// }
+// return LRESULT.ZERO;
+// }
+//
+// /* Process the System Command */
+// int cmd = wParam & 0xFFF0;
+// switch (cmd) {
+// case OS.SC_CLOSE:
+// int hwndShell = menuShell ().handle;
+// int bits = OS.GetWindowLong (hwndShell, OS.GWL_STYLE);
+// if ((bits & OS.WS_SYSMENU) == 0) return LRESULT.ZERO;
+// break;
+// case OS.SC_KEYMENU:
+// /*
+// * When lParam is zero, one of F10, Shift+F10, Ctrl+F10 or
+// * Ctrl+Shift+F10 was pressed. If there is no menu bar and
+// * the focus control is interested in keystrokes, give the
+// * key to the focus control. Normally, F10 with no menu bar
+// * moves focus to the System menu but this can be achieved
+// * using Alt+Space. To allow the application to see F10,
+// * avoid running the default window proc.
+// *
+// * NOTE: When F10 is pressed, WM_SYSCOMMAND is sent to the
+// * shell, not the focus control. This is undocumented Windows
+// * behavior.
+// */
+// if (lParam == 0) {
+// Decorations shell = menuShell ();
+// Menu menu = shell.getMenuBar ();
+// if (menu == null) {
+// Control control = display._getFocusControl ();
+// if (control != null) {
+// if (control.hooks (SWT.KeyDown) || control.hooks (SWT.KeyUp)) {
+// display.mnemonicKeyHit = false;
+// return LRESULT.ZERO;
+// }
+// }
+// }
+// } else {
+// /*
+// * When lParam is not zero, Alt+ was pressed. If the
+// * application is interested in keystrokes and there is a
+// * menu bar, check to see whether the key that was pressed
+// * matches a mnemonic on the menu bar. Normally, Windows
+// * matches the first character of a menu item as well as
+// * matching the mnemonic character. To allow the application
+// * to see the keystrokes in this case, avoid running the default
+// * window proc.
+// *
+// * NOTE: When the user types Alt+Space, the System menu is
+// * activated. In this case the application should not see
+// * the keystroke.
+// */
+// if (hooks (SWT.KeyDown) || hooks (SWT.KeyUp)) {
+// if (lParam != ' ') {
+// Decorations shell = menuShell ();
+// Menu menu = shell.getMenuBar ();
+// if (menu != null) {
+// char key = Display.mbcsToWcs (lParam);
+// if (key != 0) {
+// key = Character.toUpperCase (key);
+// MenuItem [] items = menu.getItems ();
+// for (int i=0; i 0 && mnemonic == 0) {
+// char ch = text.charAt (0);
+// if (Character.toUpperCase (ch) == key) {
+// display.mnemonicKeyHit = false;
+// return LRESULT.ZERO;
+// }
+// }
+// }
+// }
+// } else {
+// display.mnemonicKeyHit = false;
+// }
+// }
+// }
+// }
+// // FALL THROUGH
+// case OS.SC_HSCROLL:
+// case OS.SC_VSCROLL:
+// /*
+// * Do not allow keyboard traversal of the menu bar
+// * or scrolling when the shell is not enabled.
+// */
+// Decorations shell = menuShell ();
+// if (!shell.isEnabled () || !shell.isActive ()) {
+// return LRESULT.ZERO;
+// }
+// break;
+// case OS.SC_MINIMIZE:
+// /* Save the focus widget when the shell is minimized */
+// menuShell ().saveFocus ();
+// break;
+// }
+// return null;
+//}
+//
+//LRESULT WM_SYSKEYDOWN (int wParam, int lParam) {
+// return wmSysKeyDown (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_SYSKEYUP (int wParam, int lParam) {
+// return wmSysKeyUp (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_TIMER (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_UNDO (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_VSCROLL (int wParam, int lParam) {
+// if (lParam == 0) return null;
+// Control control = display.getControl (lParam);
+// if (control == null) return null;
+// return control.wmScrollChild (wParam, lParam);
+//}
+//
+//LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_XBUTTONDBLCLK (int wParam, int lParam) {
+// return wmXButtonDblClk (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_XBUTTONDOWN (int wParam, int lParam) {
+// return wmXButtonDown (handle, wParam, lParam);
+//}
+//
+//LRESULT WM_XBUTTONUP (int wParam, int lParam) {
+// return wmXButtonUp (handle, wParam, lParam);
+//}
+//
+//LRESULT wmColorChild (int wParam, int lParam) {
+// if (background == -1 && foreground == -1) return null;
+// int forePixel = foreground, backPixel = background;
+// if (forePixel == -1) forePixel = defaultForeground ();
+// if (backPixel == -1) backPixel = defaultBackground ();
+// OS.SetTextColor (wParam, forePixel);
+// OS.SetBkColor (wParam, backPixel);
+// return new LRESULT (findBrush (backPixel));
+//}
+//
+//LRESULT wmCommandChild (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT wmDrawChild (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT wmMeasureChild (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT wmNotifyChild (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT wmScrollChild (int wParam, int lParam) {
+// return null;
+//}
+
+private volatile long mouseHoverTimeStamp;
+private volatile Thread mouseHoverThread;
+private java.awt.event.MouseEvent mouseHoverEvent;
+
+void adjustMouseHoverState(java.awt.event.MouseEvent me) {
+ mouseHoverTimeStamp = System.currentTimeMillis() + 500;
+ mouseHoverEvent = me;
+ if(mouseHoverThread == null) {
+ mouseHoverThread = new Thread("Mouse Hover Thread") {
+ public void run() {
+ while(mouseHoverThread == this) {
+ try {
+ sleep(Math.max(50, mouseHoverTimeStamp - System.currentTimeMillis()));
+ } catch(Exception e) {}
+ if(mouseHoverThread != this) {
+ return;
+ }
+ if(mouseHoverTimeStamp - System.currentTimeMillis() < 0) {
+ final Thread t = this;
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ if(mouseHoverThread != t) {
+ return;
+ }
+ if(mouseHoverTimeStamp - System.currentTimeMillis() < 0) {
+ mouseHoverThread = null;
+ java.awt.event.MouseEvent me = mouseHoverEvent;
+ mouseHoverEvent = null;
+ // TODO: the point is incorrect when the wheel mouse is used: cf snippet125
+ if(!isDisposed() && me.getComponent().contains(me.getPoint())) {
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ return;
+ }
+ try {
+ sendMouseEvent(SWT.MouseHover, createMouseEvent(me, false));
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+ }
+ }
+ }
+ });
+ }
+ }
+ }
+ };
+ mouseHoverThread.setDaemon(true);
+ mouseHoverThread.start();
+ }
+}
+
+/**
+ * The entry point for callbacks
+ * (Warning: This method is platform dependent)
+ *
+ * IMPORTANT: This method is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+public void processEvent(EventObject e) {
+}
+
+boolean isTraversing;
+int lastPressedKeyCode;
+char lastPressedKeyChar;
+//int lastKeyCode;
+static Runnable focusLostRunnable;
+
+boolean isAdjustingSize;
+static boolean isDragging;
+
+/**
+ * The entry point for callbacks
+ * (Warning: This method is platform dependent)
+ *
+ * IMPORTANT: This method is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ * The item children that may be added to instances of this class
+ * must be of type CoolItem.
+ *
+ * Note that although this class is a subclass of Composite,
+ * it does not make sense to add Control children to it,
+ * or set a layout on it.
+ *
+ *
+ *
Styles:
+ *
FLAT, HORIZONTAL, VERTICAL
+ *
Events:
+ *
(none)
+ *
+ *
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+
+public class CoolBar extends Composite {
+ ArrayList itemList;
+ ArrayList originalItemList;
+// CoolItem [] originalItems;
+// boolean locked;
+// boolean ignoreResize;
+// static final int SEPARATOR_WIDTH = 2;
+// static final int MAX_WIDTH = 0x7FFF;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public CoolBar (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+static int checkStyle (int style) {
+ style |= SWT.NO_FOCUS;
+ /*
+ * Even though it is legal to create this widget
+ * with scroll bars, they serve no useful purpose
+ * because they do not automatically scroll the
+ * widget's client area. The fix is to clear
+ * the SWT style.
+ */
+ return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+//public Point computeSize (int wHint, int hHint, boolean changed) {
+// checkWidget ();
+// int width = 0, height = 0;
+// int border = getBorderWidth ();
+// int newWidth = wHint == SWT.DEFAULT ? 0x3FFF : wHint + (border * 2);
+// int newHeight = hHint == SWT.DEFAULT ? 0x3FFF : hHint + (border * 2);
+// int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+// if (count != 0) {
+// ignoreResize = true;
+// boolean redraw = false;
+// if (OS.IsWindowVisible (handle)) {
+// if (OS.COMCTL32_MAJOR >= 6) {
+// redraw = true;
+// OS.UpdateWindow (handle);
+// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+// } else {
+// redraw = drawCount == 0;
+// if (redraw) {
+// OS.UpdateWindow (handle);
+// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+// }
+// }
+// }
+// RECT oldRect = new RECT ();
+// OS.GetWindowRect (handle, oldRect);
+// int oldWidth = oldRect.right - oldRect.left;
+// int oldHeight = oldRect.bottom - oldRect.top;
+// int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER;
+// SetWindowPos (handle, 0, 0, 0, newWidth, newHeight, flags);
+// RECT rect = new RECT ();
+// OS.SendMessage (handle, OS.RB_GETRECT, count - 1, rect);
+// height = Math.max (height, rect.bottom);
+// SetWindowPos (handle, 0, 0, 0, oldWidth, oldHeight, flags);
+// REBARBANDINFO rbBand = new REBARBANDINFO ();
+// rbBand.cbSize = REBARBANDINFO.sizeof;
+// rbBand.fMask = OS.RBBIM_IDEALSIZE | OS.RBBIM_STYLE;
+// int rowWidth = 0;
+// int separator = (style & SWT.FLAT) == 0 ? SEPARATOR_WIDTH : 0;
+// for (int i = 0; i < count; i++) {
+// OS.SendMessage(handle, OS.RB_GETBANDINFO, i, rbBand);
+// if ((rbBand.fStyle & OS.RBBS_BREAK) != 0) {
+// width = Math.max(width, rowWidth - separator);
+// rowWidth = 0;
+// }
+// rowWidth += rbBand.cxIdeal + getMargin (i) + separator;
+// }
+// width = Math.max(width, rowWidth - separator);
+// if (redraw) {
+// if (OS.COMCTL32_MAJOR >= 6) {
+// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+// } else {
+// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+// }
+// }
+// ignoreResize = false;
+// }
+// if (width == 0) width = DEFAULT_WIDTH;
+// if (height == 0) height = DEFAULT_HEIGHT;
+// if (wHint != SWT.DEFAULT) width = wHint;
+// if (hHint != SWT.DEFAULT) height = hHint;
+// height += border * 2;
+// width += border * 2;
+// return new Point (width, height);
+//}
+
+boolean autoAddChildren() {
+ return false;
+}
+
+void createHandleInit() {
+ super.createHandleInit();
+ state &= ~(CANVAS | THEME_BACKGROUND);
+}
+
+protected Container createHandle () {
+ return (Container)CCoolBar.Factory.newInstance(this, style);
+}
+
+//void createHandle () {
+// super.createHandle ();
+// state &= ~CANVAS;
+//
+// /*
+// * Feature in Windows. When the control is created,
+// * it does not use the default system font. A new HFONT
+// * is created and destroyed when the control is destroyed.
+// * This means that a program that queries the font from
+// * this control, uses the font in another control and then
+// * destroys this control will have the font unexpectedly
+// * destroyed in the other control. The fix is to assign
+// * the font ourselves each time the control is created.
+// * The control will not destroy a font that it did not
+// * create.
+// */
+// int hFont = OS.GetStockObject (OS.SYSTEM_FONT);
+// OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+//}
+
+void createItem (CoolItem item, int index) {
+ int count = getItemCount();
+ if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+ itemList.add(index, item);
+// if (index == 0 && count > 0) {
+// getItem (0).setWrap (false);
+// }
+ handle.add(item.handle, index);
+ originalItemList.add(index, item);
+// /* Insert the item */
+// if (OS.SendMessage (handle, OS.RB_INSERTBAND, index, rbBand) == 0) {
+// error (SWT.ERROR_ITEM_NOT_ADDED);
+// }
+//
+// /* Resize the next to last item to the ideal size */
+// if (fixLast) {
+// resizeToPreferredWidth (lastIndex);
+// }
+//
+// OS.HeapFree (hHeap, 0, lpText);
+// items [item.id = id] = item;
+// int length = originalItems.length;
+// CoolItem [] newOriginals = new CoolItem [length + 1];
+// System.arraycopy (originalItems, 0, newOriginals, 0, index);
+// System.arraycopy (originalItems, index, newOriginals, index + 1, length - index);
+// newOriginals [index] = item;
+// originalItems = newOriginals;
+}
+
+void createWidget () {
+ super.createWidget ();
+ itemList = new ArrayList(4);
+ originalItemList = new ArrayList(4);
+// originalItems = new CoolItem [0];
+}
+
+void destroyItem (CoolItem item) {
+ if(!itemList.remove(item)) {
+ return;
+ }
+ Component[] components = handle.getComponents();
+ for(int i=0; i= 6) {
+// MARGINS margins = new MARGINS ();
+// OS.SendMessage (handle, OS.RB_GETBANDMARGINS, 0, margins);
+// margin += margins.cxLeftWidth + margins.cxRightWidth;
+// }
+// RECT rect = new RECT ();
+// OS.SendMessage (handle, OS.RB_GETBANDBORDERS, index, rect);
+// if ((style & SWT.FLAT) != 0) {
+// /*
+// * Bug in Windows. When the style bit RBS_BANDBORDERS is not set
+// * the rectangle returned by RBS_BANDBORDERS is four pixels too small.
+// * The fix is to add four pixels to the result.
+// */
+// margin += rect.left + 4;
+// } else {
+// margin += rect.left + rect.right;
+// }
+// return margin;
+//}
+
+//Control findThemeControl () {
+// return null;
+//}
+
+/**
+ * Returns the item that is currently displayed at the given,
+ * zero-relative index. Throws an exception if the index is
+ * out of range.
+ *
+ * @param index the visual index of the item to return
+ * @return the item at the given visual index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public CoolItem getItem (int index) {
+ checkWidget ();
+ int count = getItemCount();
+ if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+ Component component = handle.getComponent(index);
+ for(int i=itemList.size()-1; i>=0; i--) {
+ CoolItem coolItem = (CoolItem)itemList.get(i);
+ if(coolItem.handle == component) {
+ return coolItem;
+ }
+ }
+ // Should not happen
+ return null;
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemCount () {
+ checkWidget ();
+ return ((CCoolBar)handle).getItemCount();
+}
+
+/**
+ * Returns an array of zero-relative ints that map
+ * the creation order of the receiver's items to the
+ * order in which they are currently being displayed.
+ *
+ * Specifically, the indices of the returned array represent
+ * the current visual order of the items, and the contents
+ * of the array represent the creation order of the items.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the current visual order of the receiver's items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int [] getItemOrder () {
+ checkWidget ();
+ Utils.notImplemented(); return null;
+// int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+// int [] indices = new int [count];
+// REBARBANDINFO rbBand = new REBARBANDINFO ();
+// rbBand.cbSize = REBARBANDINFO.sizeof;
+// rbBand.fMask = OS.RBBIM_ID;
+// for (int i=0; iCoolItems in the order
+ * in which they are currently being displayed.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the receiver's items in their current visual order
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public CoolItem [] getItems () {
+ checkWidget ();
+ int count = getItemCount();
+ CoolItem[] coolItems = new CoolItem[count];
+ ArrayList itemList = (ArrayList)this.itemList.clone();
+ Component[] components = handle.getComponents();
+ for(int i=0; i=0; j--) {
+ CoolItem coolItem = (CoolItem)itemList.get(j);
+ if(coolItem.handle == component) {
+ itemList.remove(j);
+ coolItems[i] = coolItem;
+ break;
+ }
+ }
+ }
+ return coolItems;
+}
+
+/**
+ * Returns an array of points whose x and y coordinates describe
+ * the widths and heights (respectively) of the items in the receiver
+ * in the order in which they are currently being displayed.
+ *
+ * @return the receiver's item sizes in their current visual order
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point [] getItemSizes () {
+ checkWidget ();
+ Component[] components = handle.getComponents();
+ int count = components.length;
+ Point [] sizes = new Point [count];
+ for(int i=0; i
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ */
+public boolean getLocked () {
+ checkWidget ();
+ return ((CCoolBar)handle).isLocked();
+}
+
+/**
+ * Returns an array of ints that describe the zero-relative
+ * indices of any item(s) in the receiver that will begin on
+ * a new row. The 0th visible item always begins the first row,
+ * therefore it does not count as a wrap index.
+ *
+ * @return an array containing the receiver's wrap indices, or an empty array if all items are in one row
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int [] getWrapIndices () {
+ checkWidget ();
+ Component[] components = handle.getComponents();
+ ArrayList wrapIndiceList = new ArrayList();
+ for(int i=1; i
+ *
ERROR_NULL_ARGUMENT - if the item is null
+ *
ERROR_INVALID_ARGUMENT - if the item is disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int indexOf (CoolItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ Component[] components = handle.getComponents();
+ for(int i=0; i=0; i--) {
+ CoolItem item = (CoolItem)itemList.get(i);
+ if (item != null && !item.isDisposed ()) {
+ item.release (false);
+ }
+ }
+ itemList = null;
+ originalItemList = null;
+ }
+ super.releaseChildren (destroy);
+}
+
+void removeControl (Control control) {
+ if(isDisposed()) return;
+ super.removeControl (control);
+ int count = itemList.size();
+ for (int i=0; i
+ * The item order is the order in which the items in the receiver
+ * should be displayed, given in terms of the zero-relative ordering
+ * of when the items were added.
+ *
+ * The wrap indices are the indices of all item(s) in the receiver
+ * that will begin on a new row. The indices are given in the order
+ * specified by the item order. The 0th item always begins the first
+ * row, therefore it does not count as a wrap index. If wrap indices
+ * is null or empty, the items will be placed on one line.
+ *
+ * The sizes are specified in an array of points whose x and y
+ * coordinates describe the new widths and heights (respectively)
+ * of the receiver's items in the order specified by the item order.
+ *
+ *
+ * @param itemOrder an array of indices that describe the new order to display the items in
+ * @param wrapIndices an array of wrap indices, or null
+ * @param sizes an array containing the new sizes for each of the receiver's items in visual order
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if item order or sizes is null
+ *
ERROR_INVALID_ARGUMENT - if item order or sizes is not the same length as the number of items
+ *
+ */
+public void setItemLayout (int [] itemOrder, int [] wrapIndices, Point [] sizes) {
+ checkWidget ();
+ setRedraw (false);
+ Utils.notImplemented();
+// setItemOrder (itemOrder);
+// setWrapIndices (wrapIndices);
+// setItemSizes (sizes);
+// setRedraw (true);
+}
+
+///*
+// * Sets the order that the items in the receiver should
+// * be displayed in to the given argument which is described
+// * in terms of the zero-relative ordering of when the items
+// * were added.
+// *
+// * @param itemOrder the new order to display the items in
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the item order is null
+// *
ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items
+// *
+// */
+//void setItemOrder (int [] itemOrder) {
+// if (itemOrder == null) error (SWT.ERROR_NULL_ARGUMENT);
+// int itemCount = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+// if (itemOrder.length != itemCount) error (SWT.ERROR_INVALID_ARGUMENT);
+//
+// /* Ensure that itemOrder does not contain any duplicates. */
+// boolean [] set = new boolean [itemCount];
+// for (int i=0; i= itemCount) error (SWT.ERROR_INVALID_RANGE);
+// if (set [index]) error (SWT.ERROR_INVALID_ARGUMENT);
+// set [index] = true;
+// }
+//
+// REBARBANDINFO rbBand = new REBARBANDINFO ();
+// rbBand.cbSize = REBARBANDINFO.sizeof;
+// for (int i=0; i= 0) {
+// resizeToMaximumWidth (index - 1);
+// }
+// if (i == lastItemDstRow) {
+// resizeToMaximumWidth (i);
+// }
+// }
+// }
+//}
+//
+///*
+// * Sets the width and height of the receiver's items to the ones
+// * specified by the argument, which is an array of points whose x
+// * and y coordinates describe the widths and heights (respectively)
+// * in the order in which the items are currently being displayed.
+// *
+// * @param sizes an array containing the new sizes for each of the receiver's items in visual order
+// *
+// * @exception IllegalArgumentException
+// *
ERROR_NULL_ARGUMENT - if the array of sizes is null
+// *
ERROR_INVALID_ARGUMENT - if the array of sizes is not the same length as the number of items
+// *
+// * @exception SWTException
+// *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+// *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+// *
+// */
+//void setItemSizes (Point [] sizes) {
+// if (sizes == null) error (SWT.ERROR_NULL_ARGUMENT);
+// int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+// if (sizes.length != count) error (SWT.ERROR_INVALID_ARGUMENT);
+// REBARBANDINFO rbBand = new REBARBANDINFO ();
+// rbBand.cbSize = REBARBANDINFO.sizeof;
+// rbBand.fMask = OS.RBBIM_ID;
+// for (int i=0; i
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ */
+public void setLocked (boolean locked) {
+ checkWidget ();
+ ((CCoolBar)handle).setLocked(locked);
+}
+
+/**
+ * Sets the indices of all item(s) in the receiver that will
+ * begin on a new row. The indices are given in the order in
+ * which they are currently being displayed. The 0th item
+ * always begins the first row, therefore it does not count
+ * as a wrap index. If indices is null or empty, the items
+ * will be placed on one line.
+ *
+ * @param indices an array of wrap indices, or null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setWrapIndices (int [] indices) {
+ checkWidget ();
+ if (indices == null) indices = new int [0];
+ int count = getItemCount ();
+ for (int i=0; i= count) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ }
+ setRedraw (false);
+ ((CCoolBar)handle).setWrappedIndices(indices);
+ setRedraw (true);
+}
+
+//int widgetStyle () {
+// int bits = super.widgetStyle () | OS.CCS_NODIVIDER | OS.CCS_NORESIZE;
+// bits |= OS.RBS_VARHEIGHT | OS.RBS_DBLCLKTOGGLE;
+// if ((style & SWT.FLAT) == 0) bits |= OS.RBS_BANDBORDERS;
+// return bits;
+//}
+//
+//TCHAR windowClass () {
+// return ReBarClass;
+//}
+//
+//int windowProc () {
+// return ReBarProc;
+//}
+//
+//LRESULT WM_COMMAND (int wParam, int lParam) {
+// /*
+// * Feature in Windows. When the coolbar window
+// * proc processes WM_COMMAND, it forwards this
+// * message to its parent. This is done so that
+// * children of this control that send this message
+// * type to their parent will notify not only
+// * this control but also the parent of this control,
+// * which is typically the application window and
+// * the window that is looking for the message.
+// * If the control did not forward the message,
+// * applications would have to subclass the control
+// * window to see the message. Because the control
+// * window is subclassed by SWT, the message
+// * is delivered twice, once by SWT and once when
+// * the message is forwarded by the window proc.
+// * The fix is to avoid calling the window proc
+// * for this control.
+// */
+// LRESULT result = super.WM_COMMAND (wParam, lParam);
+// if (result != null) return result;
+// return LRESULT.ZERO;
+//}
+//
+//LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+// LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+// if (result != null) return result;
+//
+// /*
+// * Feature in Windows. For some reason, Windows
+// * does not fully erase the area that the cool bar
+// * occupies when the size of the cool bar is larger
+// * than the space occupied by the cool bar items.
+// * The fix is to erase the cool bar background.
+// *
+// * NOTE: On versions of Windows prior to XP, for
+// * some reason, the cool bar draws separators in
+// * WM_ERASEBKGND. Therefore it is essential to run
+// * the cool bar window proc after the background has
+// * been erased.
+// *
+// * On XP, this work around is unnecessary because
+// * the background is drawn using NM_CUSTOMDRAW.
+// */
+// if (OS.COMCTL32_MAJOR < 6) drawBackground (wParam);
+// return null;
+//}
+//
+//LRESULT WM_NOTIFY (int wParam, int lParam) {
+// /*
+// * Feature in Windows. When the cool bar window
+// * proc processes WM_NOTIFY, it forwards this
+// * message to its parent. This is done so that
+// * children of this control that send this message
+// * type to their parent will notify not only
+// * this control but also the parent of this control,
+// * which is typically the application window and
+// * the window that is looking for the message.
+// * If the control did not forward the message,
+// * applications would have to subclass the control
+// * window to see the message. Because the control
+// * window is subclassed by SWT, the message
+// * is delivered twice, once by SWT and once when
+// * the message is forwarded by the window proc.
+// * The fix is to avoid calling the window proc
+// * for this control.
+// */
+// LRESULT result = super.WM_NOTIFY (wParam, lParam);
+// if (result != null) return result;
+// return LRESULT.ZERO;
+//}
+//
+//LRESULT WM_SETREDRAW (int wParam, int lParam) {
+// LRESULT result = super.WM_SETREDRAW (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Feature in Windows. When redraw is turned off, the rebar
+// * control does not call the default window proc. This means
+// * that the rebar will redraw and children of the rebar will
+// * also redraw. The fix is to call both the rebar window proc
+// * and the default window proc.
+// *
+// * NOTE: The rebar control can resize itself in WM_SETREDRAW.
+// * When redraw is turned off by the default window proc, this
+// * can leave pixel corruption in the parent. The fix is to
+// * detect the size change and damage the previous area in the
+// * parent.
+// *
+// * NOTE: In version 6.00 of COMCTL32.DLL, when WM_SETREDRAW
+// * is off, we cannot detect that the size has changed causing
+// * pixel corruption. The fix is to disallow WM_SETREDRAW by
+// * not running the default window proc or the rebar window
+// * proc.
+// */
+// if (OS.COMCTL32_MAJOR >= 6) return LRESULT.ZERO;
+// Rectangle rect = getBounds ();
+// int code = callWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
+// OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
+// if (!rect.equals (getBounds ())) {
+// parent.redraw (rect.x, rect.y, rect.width, rect.height, true);
+// }
+// return new LRESULT (code);
+//}
+//
+//LRESULT WM_SIZE (int wParam, int lParam) {
+// if (ignoreResize) {
+// int code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
+// if (code == 0) return LRESULT.ZERO;
+// return new LRESULT (code);
+// }
+// return super.WM_SIZE (wParam, lParam);
+//}
+//
+//LRESULT wmNotifyChild (int wParam, int lParam) {
+// NMHDR hdr = new NMHDR ();
+// OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+// switch (hdr.code) {
+// case OS.RBN_CHILDSIZE:
+// /*
+// * Bug in Windows. When Windows sets the size of the rebar band
+// * child and the child is a combo box, the size of the drop down
+// * portion of the combo box is resized to zero. The fix is to set
+// * the size of the control to the current size after the rebar has
+// * already resized it. If the control is not a combo, this does
+// * nothing. If the control is a combo, the drop down portion is
+// * recalculated.
+// */
+// NMREBARCHILDSIZE lprbcs = new NMREBARCHILDSIZE ();
+// OS.MoveMemory (lprbcs, lParam, NMREBARCHILDSIZE.sizeof);
+// if (lprbcs.uBand != -1) {
+// CoolItem item = items [lprbcs.wID];
+// Control control = item.control;
+// if (control != null) {
+// int width = lprbcs.rcChild_right - lprbcs.rcChild_left;
+// int height = lprbcs.rcChild_bottom - lprbcs.rcChild_top;
+// control.setBounds (lprbcs.rcChild_left, lprbcs.rcChild_top, width, height);
+// }
+// }
+// break;
+// case OS.RBN_HEIGHTCHANGE:
+// if (!ignoreResize) {
+// Point size = getSize ();
+// int border = getBorderWidth ();
+// int height = OS.SendMessage (handle, OS.RB_GETBARHEIGHT, 0, 0);
+// setSize (size.x, height + (border * 2));
+// }
+// break;
+// case OS.RBN_CHEVRONPUSHED:
+// NMREBARCHEVRON lpnm = new NMREBARCHEVRON ();
+// OS.MoveMemory (lpnm, lParam, NMREBARCHEVRON.sizeof);
+// CoolItem item = items [lpnm.wID];
+// if (item != null) {
+// Event event = new Event();
+// event.detail = SWT.ARROW;
+// event.x = lpnm.left;
+// event.y = lpnm.bottom;
+// item.postEvent (SWT.Selection, event);
+// }
+// break;
+// case OS.NM_CUSTOMDRAW:
+// /*
+// * Bug in Windows. On versions of Windows prior to XP,
+// * drawing the background color in NM_CUSTOMDRAW erases
+// * the separators. The fix is to draw the background
+// * in WM_ERASEBKGND.
+// */
+// if (OS.COMCTL32_MAJOR < 6) break;
+// if (background != -1 || (style & SWT.FLAT) != 0) {
+// NMCUSTOMDRAW nmcd = new NMCUSTOMDRAW ();
+// OS.MoveMemory (nmcd, lParam, NMCUSTOMDRAW.sizeof);
+// switch (nmcd.dwDrawStage) {
+// case OS.CDDS_PREERASE:
+// return new LRESULT (OS.CDRF_NOTIFYPOSTERASE);
+// case OS.CDDS_POSTERASE:
+// drawBackground (nmcd.hdc);
+// break;
+// }
+// }
+// break;
+// }
+// return super.wmNotifyChild (wParam, lParam);
+//}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/CoolItem.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/CoolItem.java
new file mode 100644
index 00000000000..53dd407074f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/CoolItem.java
@@ -0,0 +1,577 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.Container;
+import java.awt.Dimension;
+
+import javax.swing.JComponent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.swing.CCoolItem;
+import org.eclipse.swt.internal.swing.Compatibility;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that represent the dynamically positionable
+ * areas of a CoolBar.
+ *
+ *
Styles:
+ *
DROP_DOWN
+ *
Events:
+ *
Selection
+ *
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+
+public class CoolItem extends Item {
+ CoolBar parent;
+ Control control;
+ Container handle;
+
+// int id;
+// boolean ideal, minimum;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a CoolBar), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ * @param index the zero-relative index at which to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public CoolItem (CoolBar parent, int style) {
+ super (parent, style);
+ this.parent = parent;
+ handle = createHandle();
+ parent.createItem (this, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a CoolBar), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ * @param index the index at which to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public CoolItem (CoolBar parent, int style, int index) {
+ super (parent, style);
+ this.parent = parent;
+ handle = createHandle();
+ parent.createItem (this, index);
+}
+
+/**
+ * Adds the listener to the collection of listeners that will
+ * be notified when the control is selected, by sending it one
+ * of the messages defined in the SelectionListener
+ * interface.
+ *
+ * If widgetSelected is called when the mouse is over
+ * the drop-down arrow (or 'chevron') portion of the cool item,
+ * the event object detail field contains the value SWT.ARROW,
+ * and the x and y fields in the event object represent the point at
+ * the bottom left of the chevron, where the menu should be popped up.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * The preferred size of a CoolItem is the size that
+ * it would best be displayed at. The width hint and height hint arguments
+ * allow the caller to ask the instance questions such as "Given a particular
+ * width, how high does it need to be to show all of the contents?"
+ * To indicate that the caller does not wish to constrain a particular
+ * dimension, the constant SWT.DEFAULT is passed for the hint.
+ *
+ *
+ * @param wHint the width hint (can be SWT.DEFAULT)
+ * @param hHint the height hint (can be SWT.DEFAULT)
+ * @return the preferred size
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Layout
+ * @see #getBounds
+ * @see #getSize
+ * @see Control#getBorderWidth
+ * @see Scrollable#computeTrim
+ * @see Scrollable#getClientArea
+ */
+public Point computeSize (int wHint, int hHint) {
+ checkWidget ();
+ int index = parent.indexOf (this);
+ if (index == -1) return new Point (0, 0);
+ int width = wHint, height = hHint;
+ if (wHint == SWT.DEFAULT) width = handle.getWidth();
+ if (hHint == SWT.DEFAULT) height = handle.getHeight();
+// if ((parent.style & SWT.VERTICAL) != 0) {
+// height += parent.getMargin (index);
+// } else {
+// width += parent.getMargin (index);
+// }
+ return new Point (width, height);
+}
+
+Container createHandle () {
+ return (Container)CCoolItem.Factory.newInstance(this, style);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Rectangle getBounds () {
+ checkWidget ();
+ java.awt.Rectangle bounds = handle.getBounds();
+ return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
+}
+
+///*
+//* Not currently used.
+//*/
+//Rectangle getClientArea () {
+// checkWidget ();
+// int index = parent.indexOf (this);
+// if (index == -1) return new Rectangle (0, 0, 0, 0);
+// int hwnd = parent.handle;
+// RECT insetRect = new RECT ();
+// OS.SendMessage (hwnd, OS.RB_GETBANDBORDERS, index, insetRect);
+// RECT rect = new RECT ();
+// OS.SendMessage (hwnd, OS.RB_GETRECT, index, rect);
+// int x = rect.left + insetRect.left;
+// int y = rect.top;
+// int width = rect.right - rect.left - insetRect.left;
+// int height = rect.bottom - rect.top;
+// if ((parent.style & SWT.FLAT) == 0) {
+// y += insetRect.top;
+// width -= insetRect.right;
+// height -= insetRect.top + insetRect.bottom;
+// }
+// if (index == 0) {
+// REBARBANDINFO rbBand = new REBARBANDINFO ();
+// rbBand.cbSize = REBARBANDINFO.sizeof;
+// rbBand.fMask = OS.RBBIM_HEADERSIZE;
+// OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, rbBand);
+// width = width - rbBand.cxHeader + 1;
+// }
+// return new Rectangle (x, y, width, height);
+//}
+
+/**
+ * Returns the control that is associated with the receiver.
+ *
+ * @return the control that is contained by the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Control getControl () {
+ checkWidget ();
+ return control;
+}
+
+/**
+ * Returns the receiver's parent, which must be a CoolBar.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public CoolBar getParent () {
+ checkWidget ();
+ return parent;
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ parent = null;
+ control = null;
+}
+
+/**
+ * Sets the control that is associated with the receiver
+ * to the argument.
+ *
+ * @param control the new control that will be contained by the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the control has been disposed
+ *
ERROR_INVALID_PARENT - if the control is not in the same widget tree
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setControl (Control control) {
+ checkWidget ();
+ if (control != null) {
+ if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+ }
+ if(this.control != null) {
+ handle.removeAll();
+ }
+ this.control = control;
+ if(control != null) {
+ handle.add(control.handle);
+ }
+ handle.invalidate();
+ handle.validate();
+ handle.repaint();
+}
+
+/**
+ * Returns a point describing the receiver's ideal size.
+ * The x coordinate of the result is the ideal width of the receiver.
+ * The y coordinate of the result is the ideal height of the receiver.
+ *
+ * @return the receiver's ideal size
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getPreferredSize () {
+ checkWidget ();
+ Dimension preferredSize = handle.getPreferredSize();
+ return new Point (preferredSize.width, preferredSize.height);
+}
+
+/**
+ * Sets the receiver's ideal size to the point specified by the arguments.
+ *
+ * @param width the new ideal width for the receiver
+ * @param height the new ideal height for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setPreferredSize (int width, int height) {
+ checkWidget ();
+ if(Compatibility.IS_JAVA_5_OR_GREATER) {
+ handle.setPreferredSize(new Dimension(width, height));
+ } else if(handle instanceof JComponent) {
+ ((JComponent)handle).setPreferredSize(new Dimension(width, height));
+ }
+ handle.invalidate();
+ handle.validate();
+ handle.repaint();
+}
+
+/**
+ * Sets the receiver's ideal size to the point specified by the argument.
+ *
+ * @param size the new ideal size for the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setPreferredSize (Point size) {
+ checkWidget ();
+ if (size == null) error(SWT.ERROR_NULL_ARGUMENT);
+ setPreferredSize (size.x, size.y);
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getSize() {
+ checkWidget ();
+ Dimension size = handle.getSize();
+ return new Point (size.width, size.height);
+}
+
+/**
+ * Sets the receiver's size to the point specified by the arguments.
+ *
+ * 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.
+ *
+ *
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSize (int width, int height) {
+ checkWidget ();
+ handle.setSize(new Dimension(width, height));
+}
+
+/**
+ * Sets the receiver's size to the point specified by the argument.
+ *
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause them to be
+ * set to zero instead.
+ *
+ *
+ * @param size the new size for the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSize (Point size) {
+ if (size == null) error(SWT.ERROR_NULL_ARGUMENT);
+ setSize (size.x, size.y);
+}
+
+/**
+ * Returns the minimum size that the cool item can
+ * be resized to using the cool item's gripper.
+ *
+ * @return a point containing the minimum width and height of the cool item, in pixels
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ */
+public Point getMinimumSize () {
+ checkWidget ();
+ Dimension minimumSize = handle.getMinimumSize();
+ return new Point (minimumSize.width, minimumSize.height);
+}
+
+/**
+ * Sets the minimum size that the cool item can be resized to
+ * using the cool item's gripper, to the point specified by the arguments.
+ *
+ * @param width the minimum width of the cool item, in pixels
+ * @param height the minimum height of the cool item, in pixels
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ */
+public void setMinimumSize (int width, int height) {
+ checkWidget ();
+ if(Compatibility.IS_JAVA_5_OR_GREATER) {
+ handle.setMinimumSize(new Dimension(width, height));
+ } else if(handle instanceof JComponent) {
+ ((JComponent)handle).setMinimumSize(new Dimension(width, height));
+ }
+}
+
+/**
+ * Sets the minimum size that the cool item can be resized to
+ * using the cool item's gripper, to the point specified by the argument.
+ *
+ * @param size a point representing the minimum width and height of the cool item, in pixels
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ */
+public void setMinimumSize (Point size) {
+ checkWidget ();
+ if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setMinimumSize (size.x, size.y);
+}
+
+//boolean getWrap() {
+// int index = parent.indexOf (this);
+// int hwnd = parent.handle;
+// REBARBANDINFO rbBand = new REBARBANDINFO ();
+// rbBand.cbSize = REBARBANDINFO.sizeof;
+// rbBand.fMask = OS.RBBIM_STYLE;
+// OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, rbBand);
+// return (rbBand.fStyle & OS.RBBS_BREAK) != 0;
+//}
+
+//void setWrap(boolean wrap) {
+// int index = parent.indexOf (this);
+// int hwnd = parent.handle;
+// REBARBANDINFO rbBand = new REBARBANDINFO ();
+// rbBand.cbSize = REBARBANDINFO.sizeof;
+// rbBand.fMask = OS.RBBIM_STYLE;
+// OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, rbBand);
+// if (wrap) {
+// rbBand.fStyle |= OS.RBBS_BREAK;
+// } else {
+// rbBand.fStyle &= ~OS.RBBS_BREAK;
+// }
+// OS.SendMessage (hwnd, OS.RB_SETBANDINFO, index, rbBand);
+//}
+
+/**
+ * Removes the listener from the collection of listeners that
+ * will be notified when the control is selected.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ *
+ * @since 2.0
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Decorations.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Decorations.java
new file mode 100644
index 00000000000..4aec1901ada
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Decorations.java
@@ -0,0 +1,1611 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.util.ArrayList;
+
+import javax.swing.JMenuBar;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.internal.swing.CButton;
+import org.eclipse.swt.internal.swing.CShell;
+
+/**
+ * Instances of this class provide the appearance and
+ * behavior of Shells, but are not top
+ * level shells or dialogs. Class Shell
+ * shares a significant amount of code with this class,
+ * and is a subclass.
+ *
+ * IMPORTANT: This class was intended to be abstract and
+ * should never be referenced or instantiated.
+ * Instead, the class Shell should be used.
+ *
+ *
+ * Instances are always displayed in one of the maximized,
+ * minimized or normal states:
+ *
+ *
+ * When an instance is marked as maximized, the
+ * window manager will typically resize it to fill the
+ * entire visible area of the display, and the instance
+ * is usually put in a state where it can not be resized
+ * (even if it has style RESIZE) until it is
+ * no longer maximized.
+ *
+ * When an instance is in the normal state (neither
+ * maximized or minimized), its appearance is controlled by
+ * the style constants which were specified when it was created
+ * and the restrictions of the window manager (see below).
+ *
+ * When an instance has been marked as minimized,
+ * its contents (client area) will usually not be visible,
+ * and depending on the window manager, it may be
+ * "iconified" (that is, replaced on the desktop by a small
+ * simplified representation of itself), relocated to a
+ * distinguished area of the screen, or hidden. Combinations
+ * of these changes are also possible.
+ *
+ *
+ *
+ * Note: The styles supported by this class must be treated
+ * as HINTs, since the window manager for the
+ * desktop on which the instance is visible has ultimate
+ * control over the appearance and behavior of decorations.
+ * For example, some window managers only support resizable
+ * windows and will always assume the RESIZE style, even if
+ * it is not set.
+ *
+ * Class SWT provides two "convenience constants"
+ * for the most commonly required style combinations:
+ *
+ *
SHELL_TRIM
+ *
+ * the result of combining the constants which are required
+ * to produce a typical application top level shell: (that
+ * is, CLOSE | TITLE | MIN | MAX | RESIZE)
+ *
+ *
DIALOG_TRIM
+ *
+ * the result of combining the constants which are required
+ * to produce a typical application dialog shell: (that
+ * is, TITLE | CLOSE | BORDER)
+ *
+ *
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ *
+ * @see #getMinimized
+ * @see #getMaximized
+ * @see Shell
+ * @see SWT
+ */
+
+public class Decorations extends Canvas {
+ Image image, smallImage, largeImage;
+ Image [] images;
+ Menu menuBar;
+ Menu [] menus;
+// Control savedFocus;
+ Button defaultButton, saveDefault;
+// int swFlags, hAccel, nAccel;
+// boolean moved, resized, opened;
+ boolean opened;
+// int oldX = OS.CW_USEDEFAULT, oldY = OS.CW_USEDEFAULT;
+// int oldWidth = OS.CW_USEDEFAULT, oldHeight = OS.CW_USEDEFAULT;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Decorations () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setDefaultButton
+ */
+public Button getDefaultButton () {
+ checkWidget ();
+ return defaultButton;
+}
+
+/**
+ * Returns the receiver's image if it had previously been
+ * set using setImage(). The image is typically
+ * displayed by the window manager when the instance is
+ * marked as iconified, and may also be displayed somewhere
+ * in the trim when the instance is in normal or maximized
+ * states.
+ *
+ * Note: This method will return null if called before
+ * setImage() is called. It does not provide
+ * access to a window manager provided, "default" image
+ * even if one exists.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Image getImage () {
+ checkWidget ();
+ return image;
+}
+
+/**
+ * Returns the receiver's images if they had previously been
+ * set using setImages(). Images are typically
+ * displayed by the window manager when the instance is
+ * marked as iconified, and may also be displayed somewhere
+ * in the trim when the instance is in normal or maximized
+ * states. Depending where the icon is displayed, the platform
+ * chooses the icon with the "best" attributes. It is expected
+ * that the array will contain the same icon rendered at different
+ * sizes, with different depth and transparency attributes.
+ *
+ *
+ * Note: This method will return an empty array if called before
+ * setImages() is called. It does not provide
+ * access to a window manager provided, "default" image
+ * even if one exists.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public Image [] getImages () {
+ checkWidget ();
+ if (images == null) return new Image [0];
+ Image [] result = new Image [images.length];
+ System.arraycopy (images, 0, result, 0, images.length);
+ return result;
+}
+
+//public Point getLocation () {
+// checkWidget ();
+// if (!OS.IsWinCE) {
+// if (OS.IsIconic (handle)) {
+// WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
+// lpwndpl.length = WINDOWPLACEMENT.sizeof;
+// OS.GetWindowPlacement (handle, lpwndpl);
+// return new Point (lpwndpl.left, lpwndpl.top);
+// }
+// }
+// return super.getLocation ();
+//}
+
+/**
+ * Returns true if the receiver is currently
+ * maximized, and false otherwise.
+ *
+ *
+ * @return the maximized state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setMaximized
+ */
+public boolean getMaximized () {
+ checkWidget ();
+ return (((CShell)handle).getExtendedState() & CShell.MAXIMIZED_BOTH) != 0;
+}
+
+/**
+ * Returns the receiver's menu bar if one had previously
+ * been set, otherwise returns null.
+ *
+ * @return the menu bar or null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Menu getMenuBar () {
+ checkWidget ();
+ return menuBar;
+}
+
+/**
+ * Returns true if the receiver is currently
+ * minimized, and false otherwise.
+ *
+ *
+ * @return the minimized state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setMinimized
+ */
+public boolean getMinimized () {
+ checkWidget ();
+ return (((CShell)handle).getExtendedState() & CShell.ICONIFIED) != 0;
+}
+
+String getNameText () {
+ return getText ();
+}
+
+//public Point getSize () {
+// checkWidget ();
+// if (!OS.IsWinCE) {
+// if (OS.IsIconic (handle)) {
+// WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
+// lpwndpl.length = WINDOWPLACEMENT.sizeof;
+// OS.GetWindowPlacement (handle, lpwndpl);
+// int width = lpwndpl.right - lpwndpl.left;
+// int height = lpwndpl.bottom - lpwndpl.top;
+// return new Point (width, height);
+// }
+// }
+// return super.getSize ();
+//}
+
+/**
+ * Returns the receiver's text, which is the string that the
+ * window manager will typically display as the receiver's
+ * title. If the text has not previously been set,
+ * returns an empty string.
+ *
+ * @return the text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getText () {
+ checkWidget ();
+ String title = ((CShell)handle).getTitle();
+ return title == null? "": title;
+}
+
+public boolean isReparentable () {
+ checkWidget ();
+ /*
+ * Feature in Windows. Calling SetParent() for a shell causes
+ * a kind of fake MDI to happen. It doesn't work well on Windows
+ * and is not supported on the other platforms. The fix is to
+ * disallow the SetParent().
+ */
+ return false;
+}
+
+boolean isTabGroup () {
+ /*
+ * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX.
+ */
+ return true;
+}
+
+boolean isTabItem () {
+ /*
+ * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX.
+ */
+ return false;
+}
+
+Decorations menuShell () {
+ return this;
+}
+
+void releaseChildren (boolean destroy) {
+ if (menuBar != null) {
+ menuBar.release (false);
+ menuBar = null;
+ }
+ super.releaseChildren (destroy);
+ if (menus != null) {
+ do {
+ int index = 0;
+ while (index < menus.length) {
+ Menu menu = menus [index];
+ if (menu != null && !menu.isDisposed ()) {
+ while (menu.getParentMenu () != null) {
+ menu = menu.getParentMenu ();
+ }
+ menu.dispose ();
+ break;
+ }
+ index++;
+ }
+ if (index == menus.length) break;
+ } while (true);
+ menus = null;
+ }
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ if (smallImage != null) smallImage.dispose ();
+ if (largeImage != null) largeImage.dispose ();
+ smallImage = largeImage = image = null;
+ images = null;
+// savedFocus = null;
+ defaultButton = saveDefault = null;
+// if (hAccel != 0 && hAccel != -1) OS.DestroyAcceleratorTable (hAccel);
+// hAccel = -1;
+}
+
+void removeMenu (Menu menu) {
+ if (menus == null) return;
+ for (int i=0; isaved default button). If no default button had
+ * previously been set, or the saved default button was
+ * disposed, the receiver's default button will be set to
+ * null.
+ *
+ * The default button is the button that is selected when
+ * the receiver is active and the user presses ENTER.
+ *
+ *
+ * @param button the new default button
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the button has been disposed
+ *
ERROR_INVALID_PARENT - if the control is not in the same widget tree
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setDefaultButton (Button button) {
+ checkWidget ();
+ if (button != null) {
+ if (button.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (button.menuShell () != this) error(SWT.ERROR_INVALID_PARENT);
+ }
+ setDefaultButton (button, true);
+}
+
+void setDefaultButton (Button button, boolean save) {
+ if (button == null) {
+ if (defaultButton == saveDefault) {
+ if (save) saveDefault = null;
+ return;
+ }
+ } else {
+ if ((button.style & SWT.PUSH) == 0) return;
+ if (button == defaultButton) return;
+ }
+ if (defaultButton != null) {
+ if (!defaultButton.isDisposed ()) ((CShell)handle).setDefaultButton(null);
+ }
+ if ((defaultButton = button) == null) defaultButton = saveDefault;
+ if (defaultButton != null) {
+ if (!defaultButton.isDisposed ()) ((CShell)handle).setDefaultButton((CButton)defaultButton.handle);
+ }
+ if (save) saveDefault = defaultButton;
+ if (saveDefault != null && saveDefault.isDisposed ()) saveDefault = null;
+}
+
+/**
+ * Sets the receiver's image to the argument, which may
+ * be null. The image is typically displayed by the window
+ * manager when the instance is marked as iconified, and
+ * may also be displayed somewhere in the trim when the
+ * instance is in normal or maximized states.
+ *
+ * @param image the new image (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setImage (Image image) {
+ checkWidget ();
+ if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ this.image = image;
+ ((CShell)handle).setIconImage(image.handle);
+}
+
+/**
+ * Sets the receiver's images to the argument, which may
+ * be an empty array. Images are typically displayed by the
+ * window manager when the instance is marked as iconified,
+ * and may also be displayed somewhere in the trim when the
+ * instance is in normal or maximized states. Depending where
+ * the icon is displayed, the platform chooses the icon with
+ * the "best" attributes. It is expected that the array will
+ * contain the same icon rendered at different sizes, with
+ * different depth and transparency attributes.
+ *
+ * @param images the new image array
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the array of images is null
+ *
ERROR_INVALID_ARGUMENT - if one of the images is null or has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public void setImages (Image [] images) {
+ checkWidget ();
+ if (images == null) error (SWT.ERROR_INVALID_ARGUMENT);
+ for (int i = 0; i < images.length; i++) {
+ if (images [i] == null || images [i].isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.images = images;
+
+ if(images.length > 0) {
+ java.util.List imageList = new ArrayList(images.length);
+ for(int i=0; itrue causes the receiver
+ * to switch to the maximized state, and if the argument is
+ * false and the receiver was previously maximized,
+ * causes the receiver to switch back to either the minimized
+ * or normal states.
+ *
+ * Note: The result of intermixing calls to setMaximized(true)
+ * and setMinimized(true) will vary by platform. Typically,
+ * the behavior will match the platform user's expectations, but not
+ * always. This should be avoided if possible.
+ *
+ *
+ * @param maximized the new maximized state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setMinimized
+ */
+public void setMaximized (boolean maximized) {
+ checkWidget ();
+ CShell cShell = (CShell)handle;
+ if(maximized) {
+ cShell.setExtendedState(CShell.MAXIMIZED_BOTH);
+ } else {
+ cShell.setExtendedState(cShell.getExtendedState() & ~CShell.MAXIMIZED_BOTH);
+ }
+}
+
+/**
+ * Sets the receiver's menu bar to the argument, which
+ * may be null.
+ *
+ * @param menu the new menu bar
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the menu has been disposed
+ *
ERROR_INVALID_PARENT - if the menu is not in the same widget tree
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMenuBar (Menu menu) {
+ checkWidget ();
+ if (menuBar == menu) return;
+ if (menu != null) {
+ if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ if ((menu.style & SWT.BAR) == 0) error (SWT.ERROR_MENU_NOT_BAR);
+ if (menu.parent != this) error (SWT.ERROR_INVALID_PARENT);
+ }
+ if (menu != null) display.removeBar (menu);
+ menuBar = menu;
+ ((CShell)handle).setJMenuBar((JMenuBar)menuBar.handle);
+// destroyAccelerators ();
+}
+
+/**
+ * Sets the minimized stated of the receiver.
+ * If the argument is true causes the receiver
+ * to switch to the minimized state, and if the argument is
+ * false and the receiver was previously minimized,
+ * causes the receiver to switch back to either the maximized
+ * or normal states.
+ *
+ * Note: The result of intermixing calls to setMaximized(true)
+ * and setMinimized(true) will vary by platform. Typically,
+ * the behavior will match the platform user's expectations, but not
+ * always. This should be avoided if possible.
+ *
+ *
+ * @param minimized the new maximized state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setMaximized
+ */
+public void setMinimized (boolean minimized) {
+ checkWidget ();
+ CShell cShell = (CShell)handle;
+ if(minimized) {
+ cShell.setExtendedState(CShell.ICONIFIED);
+ } else {
+ cShell.setExtendedState(cShell.getExtendedState() & ~CShell.ICONIFIED);
+ }
+}
+
+//void setParent () {
+// /*
+// * In order for an MDI child window to support
+// * a menu bar, setParent () is needed to reset
+// * the parent. Otherwise, the MDI child window
+// * will appear as a separate shell. This is an
+// * undocumented and possibly dangerous Windows
+// * feature.
+// */
+// int hwndParent = parent.handle;
+// display.lockActiveWindow = true;
+// OS.SetParent (handle, hwndParent);
+// if (!OS.IsWindowVisible (hwndParent)) {
+// OS.ShowWindow (handle, OS.SW_SHOWNA);
+// }
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// bits &= ~OS.WS_CHILD;
+// OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.WS_POPUP);
+// OS.SetWindowLong (handle, OS.GWL_ID, 0);
+// int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+// SetWindowPos (handle, OS.HWND_BOTTOM, 0, 0, 0, 0, flags);
+// display.lockActiveWindow = false;
+//}
+//
+//void setPlacement (int x, int y, int width, int height, int flags) {
+// WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
+// lpwndpl.length = WINDOWPLACEMENT.sizeof;
+// OS.GetWindowPlacement (handle, lpwndpl);
+// lpwndpl.showCmd = OS.SW_SHOWNA;
+// if (OS.IsIconic (handle)) {
+// lpwndpl.showCmd = OS.SW_SHOWMINNOACTIVE;
+// } else {
+// if (OS.IsZoomed (handle)) {
+// lpwndpl.showCmd = OS.SW_SHOWMAXIMIZED;
+// }
+// }
+// boolean sameOrigin = true;
+// if ((flags & OS.SWP_NOMOVE) == 0) {
+// sameOrigin = lpwndpl.left != x || lpwndpl.top != y;
+// lpwndpl.right = x + (lpwndpl.right - lpwndpl.left);
+// lpwndpl.bottom = y + (lpwndpl.bottom - lpwndpl.top);
+// lpwndpl.left = x;
+// lpwndpl.top = y;
+// }
+// boolean sameExtent = true;
+// if ((flags & OS.SWP_NOSIZE) == 0) {
+// sameExtent = lpwndpl.right - lpwndpl.left != width || lpwndpl.bottom - lpwndpl.top != height;
+// lpwndpl.right = lpwndpl.left + width;
+// lpwndpl.bottom = lpwndpl.top + height;
+// }
+// OS.SetWindowPlacement (handle, lpwndpl);
+// if (OS.IsIconic (handle)) {
+// if (sameOrigin) {
+// moved = true;
+// Point location = getLocation ();
+// oldX = location.x;
+// oldY = location.y;
+// sendEvent (SWT.Move);
+// if (isDisposed ()) return;
+// }
+// if (sameExtent) {
+// resized = true;
+// Rectangle rect = getClientArea ();
+// oldWidth = rect.width;
+// oldHeight = rect.height;
+// sendEvent (SWT.Resize);
+// if (isDisposed ()) return;
+// if (layout != null) {
+// markLayout (false, false);
+// updateLayout (true, false);
+// }
+// }
+// }
+//}
+//
+//void setSavedFocus (Control control) {
+// savedFocus = control;
+//}
+//
+//void setSystemMenu () {
+// if (OS.IsWinCE) return;
+// int hMenu = OS.GetSystemMenu (handle, false);
+// if (hMenu == 0) return;
+// int oldCount = OS.GetMenuItemCount (hMenu);
+// if ((style & SWT.RESIZE) == 0) {
+// OS.DeleteMenu (hMenu, OS.SC_SIZE, OS.MF_BYCOMMAND);
+// }
+// if ((style & SWT.MIN) == 0) {
+// OS.DeleteMenu (hMenu, OS.SC_MINIMIZE, OS.MF_BYCOMMAND);
+// }
+// if ((style & SWT.MAX) == 0) {
+// OS.DeleteMenu (hMenu, OS.SC_MAXIMIZE, OS.MF_BYCOMMAND);
+// }
+// if ((style & (SWT.MIN | SWT.MAX)) == 0) {
+// OS.DeleteMenu (hMenu, OS.SC_RESTORE, OS.MF_BYCOMMAND);
+// }
+// int newCount = OS.GetMenuItemCount (hMenu);
+// if ((style & SWT.CLOSE) == 0 || newCount != oldCount) {
+// OS.DeleteMenu (hMenu, OS.SC_TASKLIST, OS.MF_BYCOMMAND);
+// MENUITEMINFO info = new MENUITEMINFO ();
+// info.cbSize = MENUITEMINFO.sizeof;
+// info.fMask = OS.MIIM_ID;
+// int index = 0;
+// while (index < newCount) {
+// if (OS.GetMenuItemInfo (hMenu, index, true, info)) {
+// if (info.wID == OS.SC_CLOSE) break;
+// }
+// index++;
+// }
+// if (index != newCount) {
+// OS.DeleteMenu (hMenu, index - 1, OS.MF_BYPOSITION);
+// if ((style & SWT.CLOSE) == 0) {
+// OS.DeleteMenu (hMenu, OS.SC_CLOSE, OS.MF_BYCOMMAND);
+// }
+// }
+// }
+//}
+
+/**
+ * Sets the receiver's text, which is the string that the
+ * window manager will typically display as the receiver's
+ * title, to the argument, which must not be null.
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ ((CShell)handle).setTitle(string);
+}
+
+public void setVisible (boolean visible) {
+ checkWidget ();
+// if (drawCount != 0) {
+// if (((state & HIDDEN) == 0) == visible) return;
+// } else {
+ if (visible == handle.isVisible()) return;
+// }
+ if (visible) {
+ /*
+ * It is possible (but unlikely), that application
+ * code could have disposed the widget in the show
+ * event. If this happens, just return.
+ */
+ sendEvent (SWT.Show);
+ if (isDisposed ()) return;
+ handle.setVisible(true);
+// if (drawCount != 0) {
+// state &= ~HIDDEN;
+// } else {
+// if (menuBar != null) {
+// display.removeBar (menuBar);
+// OS.DrawMenuBar (handle);
+// }
+// OS.ShowWindow (handle, swFlags);
+ if (isDisposed ()) return;
+ opened = true;
+// if (!moved) {
+// moved = true;
+// Point location = getLocation ();
+// oldX = location.x;
+// oldY = location.y;
+// }
+// if (!resized) {
+// resized = true;
+// Rectangle rect = getClientArea ();
+// oldWidth = rect.width;
+// oldHeight = rect.height;
+// }
+// OS.UpdateWindow (handle);
+// }
+ } else {
+ handle.setVisible(false);
+// if (!OS.IsWinCE) {
+// if (OS.IsIconic (handle)) {
+// swFlags = OS.SW_SHOWMINNOACTIVE;
+// } else {
+// if (OS.IsZoomed (handle)) {
+// swFlags = OS.SW_SHOWMAXIMIZED;
+// } else {
+// if (handle == OS.GetActiveWindow ()) {
+// swFlags = OS.SW_RESTORE;
+// } else {
+// swFlags = OS.SW_SHOWNOACTIVATE;
+// }
+// }
+// }
+// }
+// if (drawCount != 0) {
+// state |= HIDDEN;
+// } else {
+// OS.ShowWindow (handle, OS.SW_HIDE);
+// }
+ if (isDisposed ()) return;
+ sendEvent (SWT.Hide);
+ }
+}
+
+//void sort (Image [] images, ImageData [] datas, int width, int height, int depth) {
+// /* Shell Sort from K&R, pg 108 */
+// int length = images.length;
+// if (length <= 1) return;
+// for (int gap=length/2; gap>0; gap/=2) {
+// for (int i=gap; i=0; j-=gap) {
+// if (compare (datas [j], datas [j + gap], width, height, depth) >= 0) {
+// Image swap = images [j];
+// images [j] = images [j + gap];
+// images [j + gap] = swap;
+// ImageData swapData = datas [j];
+// datas [j] = datas [j + gap];
+// datas [j + gap] = swapData;
+// }
+// }
+// }
+// }
+//}
+
+//boolean translateAccelerator (MSG msg) {
+// if (!isEnabled () || !isActive ()) return false;
+// if (menuBar != null && !menuBar.isEnabled ()) return false;
+// if (translateMDIAccelerator (msg) || translateMenuAccelerator (msg)) return true;
+// Decorations decorations = parent.menuShell ();
+// return decorations.translateAccelerator (msg);
+//}
+
+//boolean translateMenuAccelerator (MSG msg) {
+// if (hAccel == -1) createAccelerators ();
+// return hAccel != 0 && OS.TranslateAccelerator (handle, hAccel, msg) != 0;
+//}
+//
+//boolean translateMDIAccelerator (MSG msg) {
+// if (!(this instanceof Shell)) {
+// Shell shell = getShell ();
+// int hwndMDIClient = shell.hwndMDIClient;
+// if (hwndMDIClient != 0 && OS.TranslateMDISysAccel (hwndMDIClient, msg)) {
+// return true;
+// }
+// if (msg.message == OS.WM_KEYDOWN) {
+// if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false;
+// switch (msg.wParam) {
+// case OS.VK_F4:
+// OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
+// return true;
+// case OS.VK_F6:
+// if (traverseDecorations (true)) return true;
+// }
+// return false;
+// }
+// if (msg.message == OS.WM_SYSKEYDOWN) {
+// switch (msg.wParam) {
+// case OS.VK_F4:
+// OS.PostMessage (shell.handle, OS.WM_CLOSE, 0, 0);
+// return true;
+// }
+// return false;
+// }
+// }
+// return false;
+//}
+
+boolean traverseDecorations (boolean next) {
+ Control [] children = parent._getChildren ();
+ int length = children.length;
+ int index = 0;
+ while (index < length) {
+ if (children [index] == this) break;
+ index++;
+ }
+ /*
+ * It is possible (but unlikely), that application
+ * code could have disposed the widget in focus in
+ * or out events. Ensure that a disposed widget is
+ * not accessed.
+ */
+ int start = index, offset = (next) ? 1 : -1;
+ while ((index = (index + offset + length) % length) != start) {
+ Control child = children [index];
+ if (!child.isDisposed () && child instanceof Decorations) {
+ if (child.setFocus ()) return true;
+ }
+ }
+ return false;
+}
+
+boolean traverseItem (boolean next) {
+ return false;
+}
+
+boolean traverseReturn () {
+ if (defaultButton == null || defaultButton.isDisposed ()) return false;
+ if (!defaultButton.isVisible () || !defaultButton.isEnabled ()) return false;
+ defaultButton.click ();
+ return true;
+}
+
+//CREATESTRUCT widgetCreateStruct () {
+// return new CREATESTRUCT ();
+//}
+//
+//int widgetExtStyle () {
+// int bits = super.widgetExtStyle () | OS.WS_EX_MDICHILD;
+// bits &= ~OS.WS_EX_CLIENTEDGE;
+// if ((style & SWT.NO_TRIM) != 0) return bits;
+// if (OS.IsPPC) {
+// if ((style & SWT.CLOSE) != 0) bits |= OS.WS_EX_CAPTIONOKBTN;
+// }
+// if ((style & SWT.RESIZE) != 0) return bits;
+// if ((style & SWT.BORDER) != 0) bits |= OS.WS_EX_DLGMODALFRAME;
+// return bits;
+//}
+//
+//int widgetParent () {
+// Shell shell = getShell ();
+// return shell.hwndMDIClient ();
+//}
+//
+//int widgetStyle () {
+// /*
+// * Clear WS_VISIBLE and WS_TABSTOP. NOTE: In Windows, WS_TABSTOP
+// * has the same value as WS_MAXIMIZEBOX so these bits cannot be
+// * used to control tabbing.
+// */
+// int bits = super.widgetStyle () & ~(OS.WS_TABSTOP | OS.WS_VISIBLE);
+//
+// /* Set the title bits and no-trim bits */
+// bits &= ~OS.WS_BORDER;
+// if ((style & SWT.NO_TRIM) != 0) return bits;
+// if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION;
+//
+// /* Set the min and max button bits */
+// if ((style & SWT.MIN) != 0) bits |= OS.WS_MINIMIZEBOX;
+// if ((style & SWT.MAX) != 0) bits |= OS.WS_MAXIMIZEBOX;
+//
+// /* Set the resize, dialog border or border bits */
+// if ((style & SWT.RESIZE) != 0) {
+// /*
+// * Note on WinCE PPC. SWT.RESIZE is used to resize
+// * the Shell according to the state of the IME.
+// * It does not set the WS_THICKFRAME style.
+// */
+// if (!OS.IsPPC) bits |= OS.WS_THICKFRAME;
+// } else {
+// if ((style & SWT.BORDER) == 0) bits |= OS.WS_BORDER;
+// }
+//
+// /* Set the system menu and close box bits */
+// if (!OS.IsPPC && !OS.IsSP) {
+// if ((style & SWT.CLOSE) != 0) bits |= OS.WS_SYSMENU;
+// }
+//
+// return bits;
+//}
+//
+//int windowProc (int hwnd, int msg, int wParam, int lParam) {
+// switch (msg) {
+// case Display.SWT_GETACCEL:
+// case Display.SWT_GETACCELCOUNT:
+// if (hAccel == -1) createAccelerators ();
+// return msg == Display.SWT_GETACCELCOUNT ? nAccel : hAccel;
+// }
+// return super.windowProc (hwnd, msg, wParam, lParam);
+//}
+//
+//LRESULT WM_ACTIVATE (int wParam, int lParam) {
+// LRESULT result = super.WM_ACTIVATE (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Feature in AWT. When an AWT Window is activated,
+// * for some reason, it seems to forward the WM_ACTIVATE
+// * message to the parent. Normally, the parent is an
+// * AWT Frame. When AWT is embedded in SWT, the SWT
+// * shell gets the WM_ACTIVATE and assumes that it came
+// * from Windows. When an SWT shell is activated it
+// * restores focus to the last control that had focus.
+// * If this control is an embedded composite, it takes
+// * focus from the AWT Window. The fix is to ignore
+// * WM_ACTIVATE messages that come from AWT Windows.
+// */
+// if (OS.GetParent (lParam) == handle) {
+// TCHAR buffer = new TCHAR (0, 128);
+// OS.GetClassName (lParam, buffer, buffer.length ());
+// String className = buffer.toString (0, buffer.strlen ());
+// if (className.equals (Display.AWT_WINDOW_CLASS)) {
+// return LRESULT.ZERO;
+// }
+// }
+// if ((wParam & 0xFFFF) != 0) {
+// /*
+// * When the high word of wParam is non-zero, the activation
+// * state of the window is being changed while the window is
+// * minimized. If this is the case, do not report activation
+// * events or restore the focus.
+// */
+// if ((wParam >> 16) != 0) return result;
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the activate
+// * event. If this happens, end the processing of the
+// * Windows message by returning zero as the result of
+// * the window proc.
+// */
+// Control control = display.findControl (lParam);
+// if (control == null || control instanceof Shell) {
+// if (this instanceof Shell) {
+// sendEvent (SWT.Activate);
+// if (isDisposed ()) return LRESULT.ZERO;
+// }
+// }
+// if (restoreFocus ()) return LRESULT.ZERO;
+// } else {
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the deactivate
+// * event. If this happens, end the processing of the
+// * Windows message by returning zero as the result of
+// * the window proc.
+// */
+// Control control = display.findControl (lParam);
+// if (control == null || control instanceof Shell) {
+// if (this instanceof Shell) {
+// sendEvent (SWT.Deactivate);
+// if (isDisposed ()) return LRESULT.ZERO;
+// Shell shell = getShell ();
+// shell.setActiveControl (null);
+// if (isDisposed ()) return LRESULT.ZERO;
+// }
+// }
+// saveFocus ();
+// }
+// return result;
+//}
+//
+//LRESULT WM_CLOSE (int wParam, int lParam) {
+// LRESULT result = super.WM_CLOSE (wParam, lParam);
+// if (result != null) return result;
+// if (isEnabled () && isActive ()) closeWidget ();
+// return LRESULT.ZERO;
+//}
+//
+//LRESULT WM_HOTKEY (int wParam, int lParam) {
+// LRESULT result = super.WM_HOTKEY (wParam, lParam);
+// if (result != null) return result;
+// if (OS.IsSP) {
+// /*
+// * Feature on WinCE SP. The Back key is either used to close
+// * the foreground Dialog or used as a regular Back key in an EDIT
+// * control. The article 'Back Key' in MSDN for Smartphone
+// * describes how an application should handle it. The
+// * workaround is to override the Back key when creating
+// * the menubar and handle it based on the style of the Shell.
+// * If the Shell has the SWT.CLOSE style, close the Shell.
+// * Otherwise, send the Back key to the window with focus.
+// */
+// if (((lParam >> 16) & 0xFFFF) == OS.VK_ESCAPE) {
+// if ((style & SWT.CLOSE) != 0) {
+// OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
+// } else {
+// OS.SHSendBackToFocusWindow (OS.WM_HOTKEY, wParam, lParam);
+// }
+// return LRESULT.ZERO;
+// }
+// }
+// return result;
+//}
+//
+//LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+// LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+// saveFocus ();
+// return result;
+//}
+//
+//LRESULT WM_MOVE (int wParam, int lParam) {
+// if (moved) {
+// Point location = getLocation ();
+// if (location.x == oldX && location.y == oldY) {
+// return null;
+// }
+// oldX = location.x;
+// oldY = location.y;
+// }
+// return super.WM_MOVE (wParam, lParam);
+//}
+//
+//LRESULT WM_NCACTIVATE (int wParam, int lParam) {
+// LRESULT result = super.WM_NCACTIVATE (wParam, lParam);
+// if (result != null) return result;
+// if (wParam == 0) {
+// if (display.lockActiveWindow) return LRESULT.ZERO;
+// Control control = display.findControl (lParam);
+// if (control != null) {
+// Shell shell = getShell ();
+// Decorations decorations = control.menuShell ();
+// if (decorations.getShell () == shell) {
+// if (this instanceof Shell) return LRESULT.ONE;
+// if (display.ignoreRestoreFocus) {
+// if (display.lastHittest != OS.HTCLIENT) {
+// result = LRESULT.ONE;
+// }
+// }
+// }
+// }
+// }
+// if (!(this instanceof Shell)) {
+// int hwndShell = getShell().handle;
+// OS.SendMessage (hwndShell, OS.WM_NCACTIVATE, wParam, lParam);
+// }
+// return result;
+//}
+//
+//LRESULT WM_QUERYOPEN (int wParam, int lParam) {
+// LRESULT result = super.WM_QUERYOPEN (wParam, lParam);
+// if (result != null) return result;
+// sendEvent (SWT.Deiconify);
+// // widget could be disposed at this point
+// return result;
+//}
+//
+//LRESULT WM_SETFOCUS (int wParam, int lParam) {
+// LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+// if (savedFocus != this) restoreFocus ();
+// return result;
+//}
+//
+//LRESULT WM_SIZE (int wParam, int lParam) {
+// LRESULT result = null;
+// boolean changed = true;
+// if (resized) {
+// int newWidth = 0, newHeight = 0;
+// switch (wParam) {
+// case OS.SIZE_RESTORED:
+// case OS.SIZE_MAXIMIZED:
+// newWidth = lParam & 0xFFFF;
+// newHeight = lParam >> 16;
+// break;
+// case OS.SIZE_MINIMIZED:
+// Rectangle rect = getClientArea ();
+// newWidth = rect.width;
+// newHeight = rect.height;
+// break;
+// }
+// changed = newWidth != oldWidth || newHeight != oldHeight;
+// if (changed) {
+// oldWidth = newWidth;
+// oldHeight = newHeight;
+// }
+// }
+// if (changed) {
+// result = super.WM_SIZE (wParam, lParam);
+// if (isDisposed ()) return result;
+// }
+// if (wParam == OS.SIZE_MINIMIZED) {
+// sendEvent (SWT.Iconify);
+// // widget could be disposed at this point
+// }
+// return result;
+//}
+//
+//LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
+// LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
+// if (result != null) return result;
+// if (!(this instanceof Shell)) {
+// int cmd = wParam & 0xFFF0;
+// switch (cmd) {
+// case OS.SC_CLOSE: {
+// OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
+// return LRESULT.ZERO;
+// }
+// case OS.SC_NEXTWINDOW: {
+// traverseDecorations (true);
+// return LRESULT.ZERO;
+// }
+// }
+// }
+// return result;
+//}
+//
+//LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+// LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+// if (result != null) return result;
+// if (display.lockActiveWindow) {
+// WINDOWPOS lpwp = new WINDOWPOS ();
+// OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+// lpwp.flags |= OS.SWP_NOZORDER;
+// OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof);
+// }
+// return result;
+//}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/DirectoryDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/DirectoryDialog.java
new file mode 100644
index 00000000000..bc4f1cb2880
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/DirectoryDialog.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.io.File;
+
+import javax.swing.JFileChooser;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+
+/**
+ * Instances of this class allow the user to navigate
+ * the file system and select a directory.
+ *
+ *
Styles:
+ *
(none)
+ *
Events:
+ *
(none)
+ *
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+
+public class DirectoryDialog extends Dialog {
+ String message = "", filterPath = ""; //$NON-NLS-1$//$NON-NLS-2$
+ String directoryPath;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+public DirectoryDialog (Shell parent) {
+ this (parent, SWT.PRIMARY_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+public DirectoryDialog (Shell parent, int style) {
+ super (parent, style);
+ checkSubclass ();
+}
+
+/**
+ * Returns the path which the dialog will use to filter
+ * the directories it shows.
+ *
+ * @return the filter path
+ *
+ * @see #setFilterPath
+ */
+public String getFilterPath () {
+ return filterPath;
+}
+
+/**
+ * Returns the dialog's message, which is a description of
+ * the purpose for which it was opened. This message will be
+ * visible on the dialog while it is open.
+ *
+ * @return the message
+ */
+public String getMessage () {
+ return message;
+}
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return a string describing the absolute path of the selected directory,
+ * or null if the dialog was cancelled or an error occurred
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the dialog has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog
+ *
+ */
+public String open () {
+ final JFileChooser fileChooser = new JFileChooser(filterPath);
+ String title = getText();
+ if(title != null && title.length() > 0) {
+ fileChooser.setDialogTitle(title);
+ }
+ String fullPath = null;
+ // TODO: file filters
+ // TODO: custom message
+ fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ int returnValue = 0;
+ if((style & SWT.SAVE) != 0) {
+ returnValue = fileChooser.showSaveDialog(getParent().handle);
+ } else {
+ returnValue = fileChooser.showOpenDialog(getParent().handle);
+ }
+ if(returnValue == JFileChooser.APPROVE_OPTION) {
+ File directory = fileChooser.getSelectedFile();
+ fullPath = directory.getAbsolutePath();
+ filterPath = new String(fullPath);
+ }
+ return fullPath;
+}
+
+/**
+ * Sets the path that the dialog will use to filter
+ * the directories it shows to the argument, which may
+ * be null. If the string is null, then the operating
+ * system's default filter path will be used.
+ *
+ * Note that the path string is platform dependent.
+ * For convenience, either '/' or '\' can be used
+ * as a path separator.
+ *
+ *
+ * @param string the filter path
+ */
+public void setFilterPath (String string) {
+ filterPath = string;
+}
+
+/**
+ * Sets the dialog's message, which is a description of
+ * the purpose for which it was opened. This message will be
+ * visible on the dialog while it is open.
+ *
+ * @param string the message
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ */
+public void setMessage (String string) {
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ message = string;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Display.java
new file mode 100644
index 00000000000..9fdd6282c70
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Display.java
@@ -0,0 +1,2628 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import java.util.*;
+import java.util.function.*;
+
+import javax.swing.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.swing.*;
+import org.eclipse.swt.internal.swing.Compatibility;
+
+/**
+ * Instances of this class are responsible for managing the
+ * connection between SWT and the underlying operating
+ * system. Their most important function is to implement
+ * the SWT event loop in terms of the platform event model.
+ * They also provide various methods for accessing information
+ * about the operating system, and have overall control over
+ * the operating system resources which SWT allocates.
+ *
+ * Applications which are built with SWT will almost always
+ * require only a single display. In particular, some platforms
+ * which SWT supports will not allow more than one active
+ * display. In other words, some platforms do not support
+ * creating a new display if one already exists that has not been
+ * sent the dispose() message.
+ *
+ * In SWT, the thread which creates a Display
+ * instance is distinguished as the user-interface thread
+ * for that display.
+ *
+ * The user-interface thread for a particular display has the
+ * following special attributes:
+ *
+ *
+ * The event loop for that display must be run from the thread.
+ *
+ *
+ * Some SWT API methods (notably, most of the public methods in
+ * Widget and its subclasses), may only be called
+ * from the thread. (To support multi-threaded user-interface
+ * applications, class Display provides inter-thread
+ * communication methods which allow threads other than the
+ * user-interface thread to request that it perform operations
+ * on their behalf.)
+ *
+ *
+ * The thread is not allowed to construct other
+ * Displays until that display has been disposed.
+ * (Note that, this is in addition to the restriction mentioned
+ * above concerning platform support for multiple displays. Thus,
+ * the only way to have multiple simultaneously active displays,
+ * even on platforms which support it, is to have multiple threads.)
+ *
+ *
+ * Enforcing these attributes allows SWT to be implemented directly
+ * on the underlying operating system's event model. This has
+ * numerous benefits including smaller footprint, better use of
+ * resources, safer memory management, clearer program logic,
+ * better performance, and fewer overall operating system threads
+ * required. The down side however, is that care must be taken
+ * (only) when constructing multi-threaded applications to use the
+ * inter-thread communication mechanisms which this class provides
+ * when required.
+ *
+ * All SWT API methods which may only be called from the user-interface
+ * thread are distinguished in their documentation by indicating that
+ * they throw the "ERROR_THREAD_INVALID_ACCESS"
+ * SWT exception.
+ *
+ *
+ *
Styles:
+ *
(none)
+ *
Events:
+ *
Close, Dispose
+ *
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ * Note: The resulting display is marked as the current
+ * display. If this is the first display which has been
+ * constructed since the application started, it is also
+ * marked as the default display.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if called from a thread that already created an existing display
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see #getCurrent
+ * @see #getDefault
+ * @see Widget#checkSubclass
+ * @see Shell
+ */
+public Display () {
+ this (null);
+}
+
+/**
+ * Constructs a new instance of this class using the parameter.
+ *
+ * @param data the device data
+ */
+public Display (DeviceData data) {
+ super (data);
+ boolean lightweightPopups = Utils.isLightweightPopups();
+ ToolTipManager.sharedInstance().setLightWeightPopupEnabled(lightweightPopups);
+ JPopupMenu.setDefaultLightWeightPopupEnabled(lightweightPopups);
+ Utils.installDefaultLookAndFeel();
+}
+
+public static void main(final String[] args) {
+ UIThreadUtils.main(args);
+}
+
+public static void swtExec(Runnable runnable) {
+ UIThreadUtils.swtExec(runnable);
+}
+
+void addBar (Menu menu) {
+ if (bars == null) bars = new Menu [4];
+ int length = bars.length;
+ for (int i=0; iSWT. When the event does occur,
+ * the listener is notified by sending it the handleEvent()
+ * message.
+ *
+ * Setting the type of an event to SWT.None from
+ * within the handleEvent() method can be used to
+ * change the event type and stop subsequent Java listeners
+ * from running. Because event filters run before other listeners,
+ * event filters can both block other listeners and set arbitrary
+ * fields within an event. For this reason, event filters are both
+ * powerful and dangerous. They should generally be avoided for
+ * performance, debugging and code maintenance reasons.
+ *
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should be notified when the event occurs
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Listener
+ * @see SWT
+ * @see #removeFilter
+ * @see #removeListener
+ *
+ * @since 3.0
+ */
+public void addFilter (int eventType, Listener listener) {
+ checkDevice ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (filterTable == null) filterTable = new EventTable ();
+ filterTable.hook (eventType, listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notifed when an event of the given type occurs. The event
+ * type is one of the event constants defined in class SWT.
+ * When the event does occur in the display, the listener is notified by
+ * sending it the handleEvent() message.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should be notified when the event occurs
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Listener
+ * @see SWT
+ * @see #removeListener
+ *
+ * @since 2.0
+ */
+public void addListener (int eventType, Listener listener) {
+ checkDevice ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) eventTable = new EventTable ();
+ eventTable.hook (eventType, listener);
+}
+
+void addMenuItem (MenuItem item) {
+ menuItemsList.add(item);
+}
+
+void addPopup (Menu menu) {
+ if (popups == null) popups = new Menu [4];
+ int length = popups.length;
+ for (int i=0; irun() method of the runnable to
+ * be invoked by the user-interface thread at the next
+ * reasonable opportunity. The caller of this method continues
+ * to run in parallel, and is not notified when the
+ * runnable has completed. Specifying null as the
+ * runnable simply wakes the user-interface thread when run.
+ *
+ * Note that at the time the runnable is invoked, widgets
+ * that have the receiver as their display may have been
+ * disposed. Therefore, it is necessary to check for this
+ * case inside the runnable before accessing the widget.
+ *
+ *
+ * @param runnable code to run on the user-interface thread or null
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #syncExec
+ */
+public void asyncExec (Runnable runnable) {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ synchronizer.asyncExec (runnable);
+}
+
+/**
+ * Causes the system hardware to emit a short sound
+ * (if it supports this capability).
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void beep () {
+ checkDevice ();
+ Toolkit.getDefaultToolkit().beep();
+}
+
+/**
+ * Checks that this class can be subclassed.
+ *
+ * IMPORTANT: See the comment in Widget.checkSubclass().
+ *
+ *
+ * @exception SWTException
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Device#dispose
+ *
+ * @since 2.0
+ */
+public void close () {
+ checkDevice ();
+ Event event = new Event ();
+ sendEvent (SWT.Close, event);
+ if (event.doit) dispose ();
+}
+
+/**
+ * Creates the device in the operating system. If the device
+ * does not have a handle, this method may do nothing depending
+ * on the device.
+ *
+ * This method is called before init.
+ *
+ *
+ * @param data the DeviceData which describes the receiver
+ *
+ * @see #init
+ */
+@Override
+protected void create (DeviceData data) {
+ checkSubclass ();
+ thread = Thread.currentThread ();
+ UIThreadUtils.setMainThread(thread);
+ checkDisplay (thread, true);
+ createDisplay (data);
+ register (this);
+ if (Default == null) Default = this;
+}
+
+void createDisplay (DeviceData data) {
+}
+
+static synchronized void deregister (Display display) {
+ for (int i=0; i
+ * This method is called after release.
+ *
+ * @see Device#dispose
+ * @see #release
+ */
+@Override
+protected void destroy () {
+ if (this == Default) Default = null;
+ deregister (this);
+ destroyDisplay ();
+}
+
+void destroyDisplay () {
+ if(UIThreadUtils.isRealDispatch()) {
+ UIThreadUtils.popQueue();
+// /*
+// * When the session is ending, no SWT program can continue
+// * to run. In order to avoid running code after the display
+// * has been disposed, exit from Java.
+// */
+// System.exit (0);
+ }
+}
+
+/**
+ * Causes the run() method of the runnable to
+ * be invoked by the user-interface thread just before the
+ * receiver is disposed. Specifying a null runnable
+ * is ignored.
+ *
+ * @param runnable code to run at dispose time.
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public void disposeExec (Runnable runnable) {
+ checkDevice ();
+ if (disposeList == null) disposeList = new ArrayList();
+ disposeList.add(runnable);
+}
+
+/**
+ * Does whatever display specific cleanup is required, and then
+ * uses the code in SWTError.error to handle the error.
+ *
+ * @param code the descriptive error code
+ *
+ * @see SWT#error(int)
+ */
+void error (int code) {
+ SWT.error (code);
+}
+
+boolean filterEvent (Event event) {
+ if (filterTable != null) filterTable.sendEvent (event);
+ return false;
+}
+
+boolean filters (int eventType) {
+ if (filterTable == null) return false;
+ return filterTable.hooks (eventType);
+}
+
+HashMap componentToControlMap = new HashMap();
+
+Control findControl (Component handle) {
+ if (handle == null) return null;
+ do {
+ Control control = getControl (handle);
+ if (control != null) return control;
+ } while ((handle = handle.getParent()) != null);
+ return null;
+}
+
+/**
+ * Returns the display which the given thread is the
+ * user-interface thread for, or null if the given thread
+ * is not a user-interface thread for any display. Specifying
+ * null as the thread will return null
+ * for the display.
+ *
+ * @param thread the user-interface thread
+ * @return the display for the given thread
+ */
+public static synchronized Display findDisplay (Thread thread) {
+ if(Displays.length == 0) return null;
+ if(Thread.currentThread() == thread && SwingUtilities.isEventDispatchThread()) {
+ return Displays[0];
+ }
+ for (int i=0; iShell, or null
+ * if no shell belonging to the currently running application
+ * is active.
+ *
+ * @return the active shell or null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getBounds
+ */
+@Override
+public Rectangle getClientArea () {
+ checkDevice ();
+ return getBounds();
+}
+
+Control getControl (Component handle) {
+ return (Control)componentToControlMap.get(handle);
+}
+
+/**
+ * Returns the control which the on-screen pointer is currently
+ * over top of, or null if it is not currently over one of the
+ * controls built by the currently running application.
+ *
+ * @return the control under the cursor
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Control getCursorControl () {
+ checkDevice ();
+ if(!Compatibility.IS_JAVA_5_OR_GREATER) {
+ return Utils.getTrakedMouseControl();
+ }
+ java.awt.Point point = MouseInfo.getPointerInfo().getLocation();
+ // TODO: what about windows?
+ Frame[] frames = Frame.getFrames();
+ for(int i=0; i
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Point getCursorLocation () {
+ checkDevice ();
+ if(!Compatibility.IS_JAVA_5_OR_GREATER) {
+ java.awt.Point point = Utils.getTrakedMouseLocation();
+ return new Point(point.x, point.y);
+ }
+ java.awt.Point point = MouseInfo.getPointerInfo().getLocation();
+ return new Point(point.x, point.y);
+}
+
+/**
+ * Returns an array containing the recommended cursor sizes.
+ *
+ * @return the array of cursor sizes
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public Point [] getCursorSizes () {
+ checkDevice ();
+ HashSet set = new HashSet();
+ Toolkit toolkit = Toolkit.getDefaultToolkit();
+ for(int i=8; i<64; i++) {
+ set.add(toolkit.getBestCursorSize(i, i));
+ }
+ set.remove(new java.awt.Dimension(0, 0));
+ Point[] sizes = new Point[set.size()];
+ int i=0;
+ for(Iterator it=set.iterator(); it.hasNext(); ) {
+ java.awt.Dimension d = ((java.awt.Dimension)it.next());
+ sizes[i++] = new Point(d.width, d.height);
+ }
+ return sizes;
+}
+
+/**
+ * Returns the default display. One is created (making the
+ * thread that invokes this method its user-interface thread)
+ * if it did not already exist.
+ *
+ * @return the default display
+ */
+public static synchronized Display getDefault () {
+ if (Default == null) Default = new Display ();
+ return Default;
+}
+
+static boolean isValidClass (Class clazz) {
+ String name = clazz.getName ();
+ int index = name.lastIndexOf ('.');
+ return name.substring (0, index + 1).equals (PACKAGE_PREFIX);
+}
+
+/**
+ * Returns the application defined property of the receiver
+ * with the specified name, or null if it has not been set.
+ *
+ * Applications may have associated arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the display is disposed
+ * of, it is the application's responsibility to provide a
+ * disposeExec() handler which does so.
+ *
+ *
+ * @param key the name of the property
+ * @return the value of the property or null if it has not been set
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the key is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #setData(String, Object)
+ * @see #disposeExec(Runnable)
+ */
+public Object getData (String key) {
+ checkDevice ();
+ if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+// if (key.equals (RUN_MESSAGES_IN_IDLE_KEY)) {
+// return new Boolean (runMessagesInIdle);
+// }
+ if (keys == null) return null;
+ for (int i=0; idisplay specific data is a single,
+ * unnamed field that is stored with every display.
+ *
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the display specific data needs to
+ * be notified when the display is disposed of, it is the
+ * application's responsibility to provide a
+ * disposeExec() handler which does so.
+ *
+ *
+ * @return the display specific data
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #setData(Object)
+ * @see #disposeExec(Runnable)
+ */
+public Object getData () {
+ checkDevice ();
+ return data;
+}
+
+/**
+ * Returns the button dismissal alignment, one of LEFT or RIGHT.
+ * The button dismissal alignment is the ordering that should be used when positioning the
+ * default dismissal button for a dialog. For example, in a dialog that contains an OK and
+ * CANCEL button, on platforms where the button dismissal alignment is LEFT, the
+ * button ordering should be OK/CANCEL. When button dismissal alignment is RIGHT,
+ * the button ordering should be CANCEL/OK.
+ *
+ * @return the button dismissal order
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 2.1
+ */
+public int getDismissalAlignment () {
+ checkDevice ();
+ return SWT.LEFT;
+}
+
+
+/**
+ * Returns the longest duration, in milliseconds, between
+ * two mouse button clicks that will be considered a
+ * double click by the underlying operating system.
+ *
+ * @return the double click time
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public int getDoubleClickTime () {
+ checkDevice ();
+ // TODO: Method in Swing to do that?
+ return 200;
+}
+
+/**
+ * Returns the control which currently has keyboard focus,
+ * or null if keyboard events are not currently going to
+ * any of the controls built by the currently running
+ * application.
+ *
+ * @return the control under the cursor
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Control getFocusControl () {
+ checkDevice ();
+ Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
+ if(component == null) return null;
+ return findControl(component);
+}
+
+/**
+ * Returns true when the high contrast mode is enabled.
+ * Otherwise, false is returned.
+ *
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ *
+ *
+ * @return the high contrast mode
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public boolean getHighContrast () {
+ checkDevice ();
+ // TODO: What about other platforms
+ Boolean highContrast = (Boolean)Toolkit.getDefaultToolkit().getDesktopProperty("win.highContrast.on");
+ return highContrast != null? highContrast.booleanValue(): false;
+}
+
+/**
+ * Returns the maximum allowed depth of icons on this display, in bits per pixel.
+ * On some platforms, this may be different than the actual depth of the display.
+ *
+ * @return the maximum icon depth
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Device#getDepth
+ */
+public int getIconDepth () {
+ checkDevice ();
+ // TODO: is this correct?
+ return getDepth();
+}
+
+/**
+ * Returns an array containing the recommended icon sizes.
+ *
+ * @return the array of icon sizes
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Decorations#setImages(Image[])
+ *
+ * @since 3.0
+ */
+public Point [] getIconSizes () {
+ checkDevice ();
+ // TODO: method to do so in Swing?
+ return new Point [] {
+ new Point (32, 32),
+ new Point (64, 64),
+ };
+}
+
+MenuItem getMenuItem (JComponent component) {
+ for(int i=0; i
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Shell [] getShells () {
+ checkDevice ();
+ ArrayList controlsList = new ArrayList();
+ for(Iterator it = componentToControlMap.keySet().iterator(); it.hasNext(); ) {
+ Component component = (Component)it.next();
+ // TODO: what about file dialogs and such?
+ if(component instanceof Window) {
+ Control control = findControl(component);
+ if(control instanceof Shell) {
+ controlsList.add(control);
+ }
+ }
+ }
+ return (Shell[])controlsList.toArray(new Shell[0]);
+}
+
+/**
+ * Returns the thread that has invoked syncExec
+ * or null if no such runnable is currently being invoked by
+ * the user-interface thread.
+ *
+ * Note: If a runnable invoked by asyncExec is currently
+ * running, this method will return null.
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Thread getSyncThread () {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ return synchronizer.syncThread;
+}
+
+/**
+ * Returns the matching standard color for the given
+ * constant, which should be one of the color constants
+ * specified in class SWT. Any value other
+ * than one of the SWT color constants which is passed
+ * in will result in the color black. This color should
+ * not be free'd because it was allocated by the system,
+ * not the application.
+ *
+ * @param id the color constant
+ * @return the matching color
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see SWT
+ */
+@Override
+public Color getSystemColor (int id) {
+ checkDevice ();
+ java.awt.Color swingColor = LookAndFeelUtils.getSystemColor(id);
+ if(swingColor == null) {
+ return super.getSystemColor(id);
+ }
+ return Color.swing_new(this, swingColor);
+}
+
+/**
+ * Returns the matching standard platform cursor for the given
+ * constant, which should be one of the cursor constants
+ * specified in class SWT. This cursor should
+ * not be free'd because it was allocated by the system,
+ * not the application. A value of null will
+ * be returned if the supplied constant is not an SWT cursor
+ * constant.
+ *
+ * @param id the SWT cursor constant
+ * @return the corresponding cursor or null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see SWT#CURSOR_ARROW
+ * @see SWT#CURSOR_WAIT
+ * @see SWT#CURSOR_CROSS
+ * @see SWT#CURSOR_APPSTARTING
+ * @see SWT#CURSOR_HELP
+ * @see SWT#CURSOR_SIZEALL
+ * @see SWT#CURSOR_SIZENESW
+ * @see SWT#CURSOR_SIZENS
+ * @see SWT#CURSOR_SIZENWSE
+ * @see SWT#CURSOR_SIZEWE
+ * @see SWT#CURSOR_SIZEN
+ * @see SWT#CURSOR_SIZES
+ * @see SWT#CURSOR_SIZEE
+ * @see SWT#CURSOR_SIZEW
+ * @see SWT#CURSOR_SIZENE
+ * @see SWT#CURSOR_SIZESE
+ * @see SWT#CURSOR_SIZESW
+ * @see SWT#CURSOR_SIZENW
+ * @see SWT#CURSOR_UPARROW
+ * @see SWT#CURSOR_IBEAM
+ * @see SWT#CURSOR_NO
+ * @see SWT#CURSOR_HAND
+ *
+ * @since 3.0
+ */
+public Cursor getSystemCursor (int id) {
+ checkDevice ();
+ if (!(0 <= id && id < cursors.length)) return null;
+ if (cursors [id] == null) {
+ cursors [id] = new Cursor (this, id);
+ }
+ return cursors [id];
+}
+
+/**
+ * Returns the matching standard platform image for the given
+ * constant, which should be one of the icon constants
+ * specified in class SWT. This image should
+ * not be free'd because it was allocated by the system,
+ * not the application. A value of null will
+ * be returned either if the supplied constant is not an
+ * SWT icon constant or if the platform does not define an
+ * image that corresponds to the constant.
+ *
+ * @param id the SWT icon constant
+ * @return the corresponding image or null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see SWT#ICON_ERROR
+ * @see SWT#ICON_INFORMATION
+ * @see SWT#ICON_QUESTION
+ * @see SWT#ICON_WARNING
+ * @see SWT#ICON_WORKING
+ *
+ * @since 3.0
+ */
+public Image getSystemImage (int id) {
+ checkDevice ();
+ java.awt.Image hIcon = null;
+ switch (id) {
+ case SWT.ICON_ERROR:
+ if (errorIcon == null) {
+ errorIcon = getImage(LookAndFeelUtils.getSystemIcon(id));
+ }
+ hIcon = errorIcon;
+ break;
+ case SWT.ICON_INFORMATION:
+ if (infoIcon == null) {
+ infoIcon = getImage(LookAndFeelUtils.getSystemIcon(id));
+ }
+ hIcon = infoIcon;
+ break;
+ case SWT.ICON_WORKING:
+ if (workingIcon == null) {
+ workingIcon = getImage(LookAndFeelUtils.getSystemIcon(id));
+ }
+ hIcon = workingIcon;
+ break;
+ case SWT.ICON_QUESTION:
+ if (questionIcon == null) {
+ questionIcon = getImage(LookAndFeelUtils.getSystemIcon(id));
+ }
+ hIcon = questionIcon;
+ break;
+ case SWT.ICON_WARNING:
+ if (warningIcon == null) {
+ warningIcon = getImage(LookAndFeelUtils.getSystemIcon(id));
+ }
+ hIcon = warningIcon;
+ break;
+ }
+ if (hIcon == null) return null;
+ return Image.swing_new (this, SWT.ICON, hIcon);
+}
+
+static java.awt.Image getImage(Icon icon) {
+ BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
+ Graphics g = image.getGraphics();
+ icon.paintIcon(Utils.getDefaultComponent(), g, 0, 0);
+ g.dispose();
+ return image;
+}
+
+/**
+ * Returns the single instance of the system tray or null
+ * when there is no system tray available for the platform.
+ *
+ * @return the system tray or null
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.0
+ */
+public Tray getSystemTray () {
+ checkDevice ();
+ if (tray != null) return tray;
+ if (!Compatibility.IS_JAVA_6_OR_GREATER || !SystemTray.isSupported()) {
+ return null;
+ }
+ return tray = new Tray (this, SWT.NONE);
+}
+
+/**
+ * Returns the user-interface thread for the receiver.
+ *
+ * @return the receiver's user-interface thread
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Thread getThread () {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ return thread;
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Display. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ * @exception SWTError
+ *
ERROR_NO_HANDLES if a handle could not be obtained for gc creation
+ *
+ */
+@Override
+public CGC internal_new_GC (GCData data) {
+ if (isDisposed()) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
+ if (data != null) {
+ data.device = this;
+ }
+// int hDC = OS.GetDC (0);
+// if (hDC == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+// if (data != null) {
+// int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+// if ((data.style & mask) != 0) {
+// data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.LAYOUT_RTL : 0;
+// } else {
+// data.style |= SWT.LEFT_TO_RIGHT;
+// }
+// data.device = this;
+// data.hFont = systemFont ();
+// }
+// return hDC;
+ Frame[] frames = Frame.getFrames ();
+ Graphics2D g = null;
+ for (int i = 0; i < frames.length; i++) {
+ if (frames[i].isActive ()) {
+ g = (Graphics2D) frames[i].getGraphics ();
+ break;
+ }
+ }
+ if(g == null) {
+ for (int i = 0; i < frames.length; i++) {
+ if (frames[i].isShowing()) {
+ g = (Graphics2D) frames[i].getGraphics ();
+ }
+ }
+ }
+ for (int i = 0; i < frames.length && g == null; i++) {
+ g = (Graphics2D) frames[i].getGraphics ();
+ }
+ if(g == null) {
+ g = new NullGraphics2D();
+ }
+ final Graphics2D g2D = g;
+ return new CGC.CGCGraphics2D() {
+ @Override
+ public Graphics2D getGraphics() {
+ return g2D;
+ }
+ @Override
+ public Dimension getDeviceSize() {
+ Rectangle bounds = getBounds();
+ return new Dimension(bounds.width, bounds.height);
+ }
+ };
+}
+
+/**
+ * Initializes any internal resources needed by the
+ * device.
+ *
+ * IMPORTANT: This method is not part of the public
+ * API for Display. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param handle the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+@Override
+public void internal_dispose_GC (CGC handle, GCData data) {
+ handle.dispose();
+}
+
+boolean isValidThread () {
+ return thread == Thread.currentThread () || SwingUtilities.isEventDispatchThread();
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ *
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle. When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction. Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ *
+ *
+ * @param from the source Control or null
+ * @param to the destination Control or null
+ * @param point to be mapped
+ * @return point with mapped coordinates
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 2.1.2
+ */
+public Point map (Control from, Control to, Point point) {
+ checkDevice ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ return map (from, to, point.x, point.y);
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ *
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle. When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction. Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ *
+ *
+ * @param from the source Control or null
+ * @param to the destination Control or null
+ * @param x coordinates to be mapped
+ * @param y coordinates to be mapped
+ * @return point with mapped coordinates
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 2.1.2
+ */
+public Point map (Control from, Control to, int x, int y) {
+ checkDevice ();
+ if (from != null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (to != null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ Rectangle r = map(from, to, x, y, 0, 0);
+ return new Point(r.x, r.y);
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ *
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle. When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction. Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ *
+ *
+ * @param from the source Control or null
+ * @param to the destination Control or null
+ * @param rectangle to be mapped
+ * @return rectangle with mapped coordinates
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the rectangle is null
+ *
ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 2.1.2
+ */
+public Rectangle map (Control from, Control to, Rectangle rectangle) {
+ checkDevice ();
+ if (rectangle == null) error (SWT.ERROR_NULL_ARGUMENT);
+ return map (from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ *
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle. When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction. Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ *
+ *
+ * @param from the source Control or null
+ * @param to the destination Control or null
+ * @param x coordinates to be mapped
+ * @param y coordinates to be mapped
+ * @param width coordinates to be mapped
+ * @param height coordinates to be mapped
+ * @return rectangle with mapped coordinates
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 2.1.2
+ */
+public Rectangle map (Control from, Control to, int x, int y, int width, int height) {
+ checkDevice ();
+ java.awt.Point point = new java.awt.Point(x, y);
+ if(from == null) {
+ if(to == null) return new Rectangle(x, y, width, height);
+ Point offset = to.getInternalOffset();
+ point.x += offset.x;
+ point.y += offset.y;
+ SwingUtilities.convertPointFromScreen(point, ((CControl)to.handle).getClientArea());
+ } else {
+ Point offset = from.getInternalOffset();
+ point.x -= offset.x;
+ point.y -= offset.y;
+ if(to == null) {
+ SwingUtilities.convertPointToScreen(point, ((CControl)from.handle).getClientArea());
+ } else {
+ offset = to.getInternalOffset();
+ point.x += offset.x;
+ point.y += offset.y;
+ point = SwingUtilities.convertPoint(((CControl)from.handle).getClientArea(), point, ((CControl)to.handle).getClientArea());
+ }
+ }
+ // TODO: check what the "mirror" stuff mentioned in the comments is about.
+ return new Rectangle(point.x, point.y, width, height);
+}
+
+static int getPreviousInputState() {
+ return convertModifiersEx(Utils.previousModifiersEx);
+}
+
+static int getInputState() {
+ return convertModifiersEx(Utils.modifiersEx);
+}
+
+static int convertModifiersEx(int modifiersEx) {
+ int state = 0;
+ if((modifiersEx & java.awt.event.KeyEvent.SHIFT_DOWN_MASK) != 0) {
+ state |= SWT.SHIFT;
+ }
+ if((modifiersEx & java.awt.event.KeyEvent.ALT_DOWN_MASK) != 0) {
+ state |= SWT.ALT;
+ }
+ if((modifiersEx & java.awt.event.KeyEvent.CTRL_DOWN_MASK) != 0) {
+ state |= SWT.CTRL;
+ }
+ if((modifiersEx & java.awt.event.KeyEvent.BUTTON1_DOWN_MASK) != 0) {
+ state |= SWT.BUTTON1;
+ }
+ if((modifiersEx & java.awt.event.KeyEvent.BUTTON2_DOWN_MASK) != 0) {
+ state |= SWT.BUTTON2;
+ }
+ if((modifiersEx & java.awt.event.KeyEvent.BUTTON3_DOWN_MASK) != 0) {
+ state |= SWT.BUTTON3;
+ }
+ return state;
+}
+
+/**
+ * Generate a low level system event.
+ *
+ * post is used to generate low level keyboard
+ * and mouse events. The intent is to enable automated UI
+ * testing by simulating the input from the user. Most
+ * SWT applications should never need to call this method.
+ *
+ * Note that this operation can fail when the operating system
+ * fails to generate the event for any reason. For example,
+ * this can happen when there is no such key or mouse button
+ * or when the system event queue is full.
+ *
+ *
+ * Event Types:
+ *
KeyDown, KeyUp
+ *
The following fields in the Event apply:
+ *
+ *
(in) type KeyDown or KeyUp
+ *
Either one of:
+ *
(in) character a character that corresponds to a keyboard key
+ *
(in) keyCode the key code of the key that was typed,
+ * as defined by the key code constants in class SWT
+ *
+ *
MouseDown, MouseUp
+ *
The following fields in the Event apply:
+ *
+ *
(in) type MouseDown or MouseUp
+ *
(in) button the button that is pressed or released
+ *
+ *
MouseMove
+ *
The following fields in the Event apply:
+ *
+ *
(in) type MouseMove
+ *
(in) x the x coordinate to move the mouse pointer to in screen coordinates
+ *
(in) y the y coordinate to move the mouse pointer to in screen coordinates
+ *
+ *
+ *
+ * @param event the event to be generated
+ *
+ * @return true if the event was generated or false otherwise
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the event is null
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 3.0
+ *
+ */
+public boolean post (Event event) {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
+ try {
+ int type = event.type;
+ switch (type) {
+ case SWT.KeyDown: {
+ int keyCode = event.keyCode == 0? untranslateChar(event.character): untranslateKey(event.keyCode);
+ if(keyCode == 0) {
+ return false;
+ }
+ new Robot().keyPress(keyCode);
+ return true;
+ }
+ case SWT.KeyUp:
+ int keyCode = event.keyCode == 0? untranslateChar(event.character): untranslateKey(event.keyCode);
+ if(keyCode == 0) {
+ return false;
+ }
+ new Robot().keyRelease(keyCode);
+ return true;
+ case SWT.MouseMove:
+ new Robot().mouseMove(event.x, event.y);
+ return true;
+ case SWT.MouseDown:
+ case SWT.MouseUp: {
+ int buttons;
+ switch (event.button) {
+ case 1: buttons = java.awt.event.InputEvent.BUTTON1_MASK; break;
+ case 2: buttons = java.awt.event.InputEvent.BUTTON2_MASK; break;
+ case 3: buttons = java.awt.event.InputEvent.BUTTON3_MASK; break;
+ default: return false;
+ }
+ if(type == SWT.MouseDown) {
+ new Robot().mousePress(buttons);
+ } else {
+ new Robot().mouseRelease(buttons);
+ }
+ return true;
+ }
+ }
+ } catch(Exception e) {
+ return false;
+ }
+ return false;
+}
+
+void postEvent (final Event event) {
+ /*
+ * Place the event at the end of the event queue.
+ * This code is always called in the Display's
+ * thread so it must be re-enterant but does not
+ * need to be synchronized.
+ */
+ if (eventQueue == null) eventQueue = new Event [4];
+ int index = 0;
+ int length = eventQueue.length;
+ while (index < length) {
+ if (eventQueue [index] == null) break;
+ index++;
+ }
+ if (index == length) {
+ Event [] newQueue = new Event [length + 4];
+ System.arraycopy (eventQueue, 0, newQueue, 0, length);
+ eventQueue = newQueue;
+ }
+ eventQueue [index] = event;
+}
+
+AWTEvent event;
+
+/**
+ * Reads an event from the operating system's event queue,
+ * dispatches it appropriately, and returns true
+ * if there is potentially more work to do, or false
+ * if the caller can sleep until another event is placed on
+ * the event queue.
+ *
+ * In addition to checking the system event queue, this method also
+ * checks if any inter-thread messages (created by syncExec()
+ * or asyncExec()) are waiting to be processed, and if
+ * so handles them before returning.
+ *
+ *
+ * @return false if the caller can sleep upon return from this method
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message
+ *
+ *
+ * @see #sleep
+ * @see #wake
+ */
+public boolean readAndDispatch () {
+ checkDevice ();
+ if(UIThreadUtils.isRealDispatch()) {
+ boolean result = UIThreadUtils.swingEventQueue.dispatchEvent();
+ UIThreadUtils.throwStoredException();
+ runDeferredEvents ();
+ return result || isDisposed();
+ }
+ if(event != null) {
+ AWTEvent awtEvent = event;
+ event = null;
+ try {
+ Object source = awtEvent.getSource();
+ if (awtEvent instanceof ActiveEvent) {
+ ((ActiveEvent)awtEvent).dispatch();
+ } else if(source instanceof Component) {
+ ((Component)source).dispatchEvent(awtEvent);
+ } else if(source instanceof MenuComponent) {
+ ((MenuComponent)source).dispatchEvent(awtEvent);
+ }
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ }
+ UIThreadUtils.throwStoredException();
+ return true;
+ }
+ if(SwingUtilities.isEventDispatchThread()) {
+ return isDisposed();
+ }
+ synchronized(UIThreadUtils.UI_LOCK) {
+ if(UIThreadUtils.exclusiveSectionCount == 0) {
+ return isDisposed();
+ }
+ try {
+ UIThreadUtils.UI_LOCK.notify();
+ UIThreadUtils.UI_LOCK.wait();
+ } catch(Exception e) {
+ }
+ UIThreadUtils.throwStoredException();
+ }
+ runDeferredEvents ();
+// return true;
+// }
+// /*boolean result =*/ runAsyncMessages (false);
+// System.err.println(synchronizer.getMessageCount());
+ return true;
+}
+
+static synchronized void register (Display display) {
+ for (int i=0; i
+ * Disposes all shells which are currently open on the display.
+ * After this method has been invoked, all related related shells
+ * will answer true when sent the message
+ * isDisposed().
+ *
+ * When a device is destroyed, resources that were acquired
+ * on behalf of the programmer need to be returned to the
+ * operating system. For example, if the device allocated a
+ * font to be used as the system font, this font would be
+ * freed in release. Also,to assist the garbage
+ * collector and minimize the amount of memory that is not
+ * reclaimed when the programmer keeps a reference to a
+ * disposed device, all fields except the handle are zero'd.
+ * The handle is needed by destroy.
+ *
+ * This method is called before destroy.
+ *
+ * @see Device#dispose
+ * @see #destroy
+ */
+@Override
+protected void release () {
+ sendEvent (SWT.Dispose, new Event ());
+ Shell [] shells = getShells ();
+ for (int i=0; iSWT.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified when the event occurs
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Listener
+ * @see SWT
+ * @see #addFilter
+ * @see #addListener
+ *
+ * @since 3.0
+ */
+public void removeFilter (int eventType, Listener listener) {
+ checkDevice ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (filterTable == null) return;
+ filterTable.unhook (eventType, listener);
+ if (filterTable.size () == 0) filterTable = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notifed when an event of the given type occurs. The event type
+ * is one of the event constants defined in class SWT.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified when the event occurs
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Listener
+ * @see SWT
+ * @see #addListener
+ *
+ * @since 2.0
+ */
+public void removeListener (int eventType, Listener listener) {
+ checkDevice ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (eventType, listener);
+}
+
+void removeBar (Menu menu) {
+ if (bars == null) return;
+ for (int i=0; iNote: It is typically considered bad practice for a
+ * program to move the on-screen pointer location.
+ *
+ * @param x the new x coordinate for the cursor
+ * @param y the new y coordinate for the cursor
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 2.1
+ */
+public void setCursorLocation (int x, int y) {
+ checkDevice ();
+ try {
+ new Robot().mouseMove(x, y);
+ } catch(Exception e) {}
+}
+
+/**
+ * Sets the location of the on-screen pointer relative to the top left corner
+ * of the screen. Note: It is typically considered bad practice for a
+ * program to move the on-screen pointer location.
+ *
+ * @param point new position
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @since 2.0
+ */
+public void setCursorLocation (Point point) {
+ checkDevice ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setCursorLocation (point.x, point.y);
+}
+
+/**
+ * Sets the application defined property of the receiver
+ * with the specified name to the given argument.
+ *
+ * Applications may have associated arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the display is disposed
+ * of, it is the application's responsibility provide a
+ * disposeExec() handler which does so.
+ *
+ *
+ * @param key the name of the property
+ * @param value the new value for the property
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the key is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getData(String)
+ * @see #disposeExec(Runnable)
+ */
+public void setData (String key, Object value) {
+ checkDevice ();
+ if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+// if (key.equals (RUN_MESSAGES_IN_IDLE_KEY)) {
+// Boolean data = (Boolean) value;
+// runMessagesInIdle = data != null && data.booleanValue ();
+// return;
+// }
+
+ /* Remove the key/value pair */
+ if (value == null) {
+ if (keys == null) return;
+ int index = 0;
+ while (index < keys.length && !keys [index].equals (key)) index++;
+ if (index == keys.length) return;
+ if (keys.length == 1) {
+ keys = null;
+ values = null;
+ } else {
+ String [] newKeys = new String [keys.length - 1];
+ Object [] newValues = new Object [values.length - 1];
+ System.arraycopy (keys, 0, newKeys, 0, index);
+ System.arraycopy (keys, index + 1, newKeys, index, newKeys.length - index);
+ System.arraycopy (values, 0, newValues, 0, index);
+ System.arraycopy (values, index + 1, newValues, index, newValues.length - index);
+ keys = newKeys;
+ values = newValues;
+ }
+ return;
+ }
+
+ /* Add the key/value pair */
+ if (keys == null) {
+ keys = new String [] {key};
+ values = new Object [] {value};
+ return;
+ }
+ for (int i=0; idisplay specific data is a single,
+ * unnamed field that is stored with every display.
+ *
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the display specific data needs to
+ * be notified when the display is disposed of, it is the
+ * application's responsibility provide a
+ * disposeExec() handler which does so.
+ *
+ *
+ * @param data the new display specific data
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #getData()
+ * @see #disposeExec(Runnable)
+ */
+public void setData (Object data) {
+ checkDevice ();
+ this.data = data;
+}
+
+/**
+ * On platforms which support it, sets the application name
+ * to be the argument. On Motif, for example, this can be used
+ * to set the name used for resource lookup. Specifying
+ * null for the name clears it.
+ *
+ * @param name the new app name or null
+ */
+public static void setAppName (String name) {
+ /* Do nothing */
+}
+
+/**
+ * Sets the synchronizer used by the display to be
+ * the argument, which can not be null.
+ *
+ * @param synchronizer the new synchronizer for the display (must not be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the synchronizer is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message
+ *
+ */
+public void setSynchronizer (Synchronizer synchronizer) {
+ checkDevice ();
+ if (synchronizer == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (this.synchronizer != null) {
+ this.synchronizer.runAsyncMessages(true);
+ }
+ this.synchronizer = synchronizer;
+}
+
+/**
+ * Causes the user-interface thread to sleep (that is,
+ * to be put in a state where it does not consume CPU cycles)
+ * until an event is received or it is otherwise awakened.
+ *
+ * @return true if an event requiring dispatching was placed on the queue.
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #wake
+ */
+public boolean sleep () {
+ checkDevice ();
+ if(UIThreadUtils.isRealDispatch()) {
+ return UIThreadUtils.swingEventQueue.sleep();
+ }
+ if(SwingUtilities.isEventDispatchThread()) {
+ boolean result = true;
+ UIThreadUtils.fakeDispatchingEDT = Thread.currentThread();
+ try {
+ event = Toolkit.getDefaultToolkit().getSystemEventQueue().getNextEvent();
+ } catch(InterruptedException e) {
+ result = false;
+ }
+ UIThreadUtils.fakeDispatchingEDT = null;
+ return result;
+ }
+ synchronized(UIThreadUtils.UI_LOCK) {
+ if(UIThreadUtils.exclusiveSectionCount == 0) {
+ try {
+ UIThreadUtils.UI_LOCK.wait();
+ } catch(Exception e) {
+ }
+ }
+ return UIThreadUtils.exclusiveSectionCount > 0;
+ }
+}
+
+/**
+ * Causes the run() method of the runnable to
+ * be invoked by the user-interface thread at the next
+ * reasonable opportunity. The thread which calls this method
+ * is suspended until the runnable completes. Specifying null
+ * as the runnable simply wakes the user-interface thread.
+ *
+ * Note that at the time the runnable is invoked, widgets
+ * that have the receiver as their display may have been
+ * disposed. Therefore, it is necessary to check for this
+ * case inside the runnable before accessing the widget.
+ *
+ *
+ * @param runnable code to run on the user-interface thread or null
+ *
+ * @exception SWTException
+ *
ERROR_FAILED_EXEC - if an exception occured when executing the runnable
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #asyncExec
+ */
+public void syncExec (Runnable runnable) {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ synchronizer.syncExec (runnable);
+}
+
+/**
+ * Causes the run() method of the runnable to
+ * be invoked by the user-interface thread after the specified
+ * number of milliseconds have elapsed. If milliseconds is less
+ * than zero, the runnable is not executed.
+ *
+ * Note that at the time the runnable is invoked, widgets
+ * that have the receiver as their display may have been
+ * disposed. Therefore, it is necessary to check for this
+ * case inside the runnable before accessing the widget.
+ *
+ *
+ * @param milliseconds the delay before running the runnable
+ * @param runnable code to run on the user-interface thread
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the runnable is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #asyncExec
+ */
+public void timerExec (final int milliseconds, final Runnable runnable) {
+ checkDevice ();
+ if (runnable == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (milliseconds < 0) {
+ timerList.remove(runnable);
+ return;
+ }
+ timerList.add(runnable);
+ new Thread("Display.timerExecThread") {
+ @Override
+ public void run() {
+ try {
+ sleep(milliseconds);
+ boolean isRemoved = timerList.remove(runnable);
+ if(isRemoved) {
+ SwingUtilities.invokeLater(runnable);
+ }
+ } catch(Exception e) {}
+ }
+ }.start();
+}
+
+static int translateKey (int key) {
+ for (int i=0; i= '0' && c <='9') {
+ return c;
+ }
+ char uc = Character.toUpperCase(c);
+ if(uc >= 'A' && uc <= 'Z') {
+ return uc;
+ }
+ switch(c) {
+ case '\n': return java.awt.event.KeyEvent.VK_ENTER;
+ case '\b': return java.awt.event.KeyEvent.VK_BACK_SPACE;
+ case '\t': return java.awt.event.KeyEvent.VK_TAB;
+ case ' ': return java.awt.event.KeyEvent.VK_SPACE;
+ case ',': return java.awt.event.KeyEvent.VK_COMMA;
+ case '-': return java.awt.event.KeyEvent.VK_MINUS;
+ case '.': return java.awt.event.KeyEvent.VK_PERIOD;
+ case ';': return java.awt.event.KeyEvent.VK_SEMICOLON;
+ case '=': return java.awt.event.KeyEvent.VK_EQUALS;
+ case '[': return java.awt.event.KeyEvent.VK_OPEN_BRACKET;
+ case '\\': return java.awt.event.KeyEvent.VK_BACK_SLASH;
+ case ']': return java.awt.event.KeyEvent.VK_CLOSE_BRACKET;
+ case '`': return java.awt.event.KeyEvent.VK_BACK_QUOTE;
+ case '\u00B4': return java.awt.event.KeyEvent.VK_QUOTE;
+ case '&': return java.awt.event.KeyEvent.VK_AMPERSAND;
+ case '*': return java.awt.event.KeyEvent.VK_ASTERISK;
+ case '"': return java.awt.event.KeyEvent.VK_QUOTEDBL;
+ case '<': return java.awt.event.KeyEvent.VK_LESS;
+ case '>': return java.awt.event.KeyEvent.VK_GREATER;
+ case '{': return java.awt.event.KeyEvent.VK_BRACELEFT;
+ case '}': return java.awt.event.KeyEvent.VK_BRACERIGHT;
+ case '@': return java.awt.event.KeyEvent.VK_AT;
+ case ':': return java.awt.event.KeyEvent.VK_COLON;
+ case '^': return java.awt.event.KeyEvent.VK_CIRCUMFLEX;
+ case '$': return java.awt.event.KeyEvent.VK_DOLLAR;
+ case '\u20AC': return java.awt.event.KeyEvent.VK_EURO_SIGN;
+ case '!': return java.awt.event.KeyEvent.VK_EXCLAMATION_MARK;
+ case '\u00A1': return java.awt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK;
+ case '(': return java.awt.event.KeyEvent.VK_LEFT_PARENTHESIS;
+ case '#': return java.awt.event.KeyEvent.VK_NUMBER_SIGN;
+ case '+': return java.awt.event.KeyEvent.VK_PLUS;
+ case ')': return java.awt.event.KeyEvent.VK_RIGHT_PARENTHESIS;
+ case '_': return java.awt.event.KeyEvent.VK_UNDERSCORE;
+ }
+ return 0;
+}
+
+/**
+ * Forces all outstanding paint requests for the display
+ * to be processed before this method returns.
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see Control#update()
+ */
+public void update() {
+ checkDevice ();
+ Shell[] shells = getShells ();
+ for (int i=0; isleeping,
+ * causes it to be awakened and start running again. Note that this
+ * method may be called from any thread.
+ *
+ * @exception SWTException
+ *
ERROR_DEVICE_DISPOSED - if the receiver has been disposed
+ *
+ *
+ * @see #sleep
+ */
+public void wake () {
+ if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+ if (thread == Thread.currentThread ()) return;
+ UIThreadUtils.wakeUIThread();
+}
+
+void wakeThread () {
+ SwingUtilities.invokeLater(() -> {
+ UIThreadUtils.startExclusiveSection(Display.this);
+ try {
+ runAsyncMessages (true);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ }
+ UIThreadUtils.stopExclusiveSection();
+ UIThreadUtils.throwStoredException();
+});
+}
+
+/**
+ * Sets a callback that will be invoked whenever an exception is thrown by a listener or external
+ * callback function. The application may use this to set a global exception handling policy:
+ * the most common policies are either to log and discard the exception or to re-throw the
+ * exception.
+ *
+ * The default SWT error handling policy is to rethrow exceptions.
+ *
+ * @param runtimeExceptionHandler new exception handler to be registered.
+ * @since 3.106
+ */
+public final void setRuntimeExceptionHandler (Consumer runtimeExceptionHandler) {
+ checkDevice();
+ this.runtimeExceptionHandler = Objects.requireNonNull (runtimeExceptionHandler);
+}
+
+/**
+ * Returns the current exception handler. It will receive all exceptions thrown by listeners
+ * and external callbacks in this display. If code wishes to temporarily replace the exception
+ * handler (for example, during a unit test), it is common practice to invoke this method prior
+ * to replacing the exception handler so that the old handler may be restored afterward.
+ *
+ * @return the current exception handler. Never null.
+ * @since 3.106
+ */
+public final Consumer getRuntimeExceptionHandler () {
+ return runtimeExceptionHandler;
+}
+
+/**
+ * Sets a callback that will be invoked whenever an error is thrown by a listener or external
+ * callback function. The application may use this to set a global exception handling policy:
+ * the most common policies are either to log and discard the exception or to re-throw the
+ * exception.
+ *
+ * The default SWT error handling policy is to rethrow exceptions.
+ *
+ * @param errorHandler new error handler to be registered.
+ * @since 3.106
+ */
+public final void setErrorHandler (Consumer errorHandler) {
+ checkDevice();
+ this.errorHandler = Objects.requireNonNull (errorHandler);
+}
+
+/**
+ * Returns the current exception handler. It will receive all errors thrown by listeners
+ * and external callbacks in this display. If code wishes to temporarily replace the error
+ * handler (for example, during a unit test), it is common practice to invoke this method prior
+ * to replacing the error handler so that the old handler may be restored afterward.
+ *
+ * @return the current error handler. Never null.
+ * @since 3.106
+ */
+public final Consumer getErrorHandler () {
+ return errorHandler;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandBar.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandBar.java
new file mode 100644
index 00000000000..056a344a74c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandBar.java
@@ -0,0 +1,342 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.util.ArrayList;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ExpandAdapter;
+import org.eclipse.swt.events.ExpandEvent;
+import org.eclipse.swt.events.ExpandListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.swing.CControl;
+import org.eclipse.swt.internal.swing.CExpandBar;
+import org.eclipse.swt.internal.swing.CExpandItem;
+import org.eclipse.swt.internal.swing.JExpandPane.JExpandPaneItem;
+
+/**
+ * Instances of this class support the layout of selectable
+ * expand bar items.
+ *
+ * The item children that may be added to instances of this class
+ * must be of type ExpandItem.
+ *
+ *
+ *
Styles:
+ *
V_SCROLL
+ *
Events:
+ *
Expand, Collapse
+ *
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @see ExpandItem
+ * @see ExpandEvent
+ * @see ExpandListener
+ * @see ExpandAdapter
+ *
+ * @since 3.2
+ */
+public class ExpandBar extends Composite {
+
+ ArrayList itemList;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ExpandBar (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+Control [] _getChildren () {
+ Component[] children = ((CControl)handle).getClientArea().getComponents();
+ if(children.length == 0) {
+ return new Control[0];
+ }
+ ArrayList controlsList = new ArrayList(children.length);
+ for(int i=0; iExpandListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ExpandListener
+ * @see #removeExpandListener
+ */
+public void addExpandListener (ExpandListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Expand, typedListener);
+ addListener (SWT.Collapse, typedListener);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+static int checkStyle (int style) {
+ style &= ~SWT.H_SCROLL;
+ return style | SWT.NO_BACKGROUND;
+}
+
+boolean autoAddChildren() {
+ return false;
+}
+
+void createHandleInit() {
+ super.createHandleInit();
+ state &= ~CANVAS;
+}
+
+protected Container createHandle () {
+ return (Container)CExpandBar.Factory.newInstance(this, style);
+}
+
+void createItem (ExpandItem item, int style, int index) {
+ int count = getItemCount();
+ if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+ itemList.add(index, item);
+ ((CExpandBar)handle).insertExpandPaneItem(null, null, item.handle, index);
+ handle.invalidate();
+ handle.validate();
+}
+
+void createWidget () {
+ super.createWidget ();
+ itemList = new ArrayList();
+}
+
+void destroyItem (ExpandItem item) {
+ int index = indexOf(item);
+ if(index != -1) {
+ ((CExpandBar)handle).removeExpandPaneItem(item.handle);
+ handle.invalidate();
+ handle.validate();
+ handle.repaint();
+ }
+ itemList = null;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public ExpandItem getItem (int index) {
+ checkWidget ();
+ int count = getItemCount();
+ if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+ return (ExpandItem)itemList.get(index);
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemCount () {
+ checkWidget ();
+ return itemList.size();
+}
+
+/**
+ * Returns an array of ExpandItems which are the items
+ * in the receiver.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSpacing () {
+ checkWidget ();
+ return ((CExpandBar)handle).getSpacing();
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the item is null
+ *
ERROR_INVALID_ARGUMENT - if the item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int indexOf (ExpandItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int count = getItemCount();
+ for (int i=0; i
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ExpandListener
+ * @see #addExpandListener
+ */
+public void removeExpandListener (ExpandListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Expand, listener);
+ eventTable.unhook (SWT.Collapse, listener);
+}
+
+/**
+ * Sets the receiver's spacing. Spacing specifies the number of pixels allocated around
+ * each item.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSpacing (int spacing) {
+ checkWidget ();
+ if (spacing < 0) return;
+ ((CExpandBar)handle).setSpacing(spacing);
+}
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandItem.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandItem.java
new file mode 100644
index 00000000000..457a8cb0309
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ExpandItem.java
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.internal.swing.CExpandBar;
+import org.eclipse.swt.internal.swing.CExpandItem;
+import org.eclipse.swt.internal.swing.Compatibility;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that represents a expandable item in a expand bar.
+ *
+ *
+ *
Styles:
+ *
(none)
+ *
Events:
+ *
(none)
+ *
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @see ExpandBar
+ *
+ * @since 3.2
+ */
+public class ExpandItem extends Item {
+ ExpandBar parent;
+ Control control;
+ Container handle;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ExpandItem (ExpandBar parent, int style) {
+ this (parent, style, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent, a
+ * style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ExpandItem (ExpandBar parent, int style, int index) {
+ super (parent, style);
+ this.parent = parent;
+ handle = createHandle();
+ parent.createItem (this, style, index);
+}
+
+Container createHandle () {
+ return (Container)CExpandItem.Factory.newInstance(this, style);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+/**
+ * Returns the control that is shown when the item is expanded.
+ * If no control has been set, return null.
+ *
+ * @return the control
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Control getControl () {
+ checkWidget ();
+ return control;
+}
+
+/**
+ * Returns true if the receiver is expanded,
+ * and false otherwise.
+ *
+ * @return the expanded state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getExpanded () {
+ checkWidget ();
+ return ((CExpandBar)parent.handle).isExpanded(handle);
+}
+
+/**
+ * Returns the height of the receiver's header
+ *
+ * @return the height of the header
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getHeaderHeight () {
+ checkWidget ();
+ return ((CExpandBar)parent.handle).getTitleBarSize(handle).height;
+}
+
+/**
+ * Gets the height of the receiver.
+ *
+ * @return the height
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getHeight () {
+ checkWidget ();
+ return ((CExpandBar)parent.handle).getSize().height;
+}
+
+/**
+ * Returns the receiver's parent, which must be a ExpandBar.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public ExpandBar getParent () {
+ checkWidget ();
+ return parent;
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ parent = null;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ control = null;
+}
+
+
+/**
+ * Sets the control that is shown when the item is expanded.
+ *
+ * @param control the new control (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the control has been disposed
+ *
ERROR_INVALID_PARENT - if the control is not in the same widget tree
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setControl (Control control) {
+ checkWidget();
+ if (control != null) {
+ if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+ }
+ if (this.control != null && this.control.isDisposed ()) {
+ this.control = null;
+ }
+ handle.remove(control.handle);
+ this.control = control;
+ if(control != null) {
+ handle.add(control.handle, BorderLayout.CENTER);
+ }
+ handle.invalidate();
+ handle.validate();
+ handle.repaint();
+}
+
+/**
+ * Sets the expanded state of the receiver.
+ *
+ * @param expanded the new expanded state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setExpanded (boolean expanded) {
+ checkWidget ();
+ ((CExpandBar)parent.handle).setExpanded(handle, expanded);
+}
+
+/**
+ * Sets the height of the receiver. This is height of the item when it is expanded,
+ * excluding the height of the header.
+ *
+ * @param height the new height
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setHeight (int height) {
+ checkWidget ();
+ if (height < 0) return;
+ if(Compatibility.IS_JAVA_5_OR_GREATER) {
+ handle.setPreferredSize(new Dimension(handle.getPreferredSize().width, height));
+ } else if(handle instanceof JComponent) {
+ ((JComponent)handle).setPreferredSize(new Dimension(handle.getPreferredSize().width, height));
+ }
+ ((JComponent)handle).revalidate();
+ handle.repaint();
+}
+
+public void setImage (Image image) {
+ super.setImage (image);
+ ((CExpandBar)parent.handle).setIcon(handle, new ImageIcon(image.handle));
+}
+
+public void setText (String string) {
+ super.setText (string);
+ ((CExpandBar)parent.handle).setText(handle, text);
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FileDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FileDialog.java
new file mode 100644
index 00000000000..37fa4884934
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FileDialog.java
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.io.File;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.swing.JFileChooser;
+import javax.swing.filechooser.FileFilter;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.swing.Compatibility;
+
+/**
+ * Instances of this class allow the user to navigate
+ * the file system and select or enter a file name.
+ *
+ *
Styles:
+ *
SAVE, OPEN, MULTI
+ *
Events:
+ *
(none)
+ *
+ *
+ * Note: Only one of the styles SAVE and OPEN may be specified.
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+public class FileDialog extends Dialog {
+ String [] filterNames = new String [0];
+ String [] filterExtensions = new String [0];
+ String [] fileNames = new String [0];
+ String filterPath = "", fileName = "";
+ static final String FILTER = "*.*";
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+public FileDialog (Shell parent) {
+ this (parent, SWT.PRIMARY_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+public FileDialog (Shell parent, int style) {
+ super (parent, style);
+ checkSubclass ();
+}
+
+/**
+ * Returns the path of the first file that was
+ * selected in the dialog relative to the filter path, or an
+ * empty string if no such file has been selected.
+ *
+ * @return the relative path of the file
+ */
+public String getFileName () {
+ return fileName;
+}
+
+/**
+ * Returns a (possibly empty) array with the paths of all files
+ * that were selected in the dialog relative to the filter path.
+ *
+ * @return the relative paths of the files
+ */
+public String [] getFileNames () {
+ return fileNames;
+}
+
+/**
+ * Returns the file extensions which the dialog will
+ * use to filter the files it shows.
+ *
+ * @return the file extensions filter
+ */
+public String [] getFilterExtensions () {
+ return filterExtensions;
+}
+
+/**
+ * Returns the names that describe the filter extensions
+ * which the dialog will use to filter the files it shows.
+ *
+ * @return the list of filter names
+ */
+public String [] getFilterNames () {
+ return filterNames;
+}
+
+/**
+ * Returns the directory path that the dialog will use, or an empty
+ * string if this is not set. File names in this path will appear
+ * in the dialog, filtered according to the filter extensions.
+ *
+ * @return the directory path string
+ *
+ * @see #setFilterExtensions
+ */
+public String getFilterPath () {
+ return filterPath;
+}
+
+protected static String currentDirectoryPath;
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return a string describing the absolute path of the first selected file,
+ * or null if the dialog was cancelled or an error occurred
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the dialog has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog
+ *
+ */
+public String open () {
+ final JFileChooser fileChooser = new JFileChooser(currentDirectoryPath);
+ String title = getText();
+ if(title != null && title.length() > 0) {
+ fileChooser.setDialogTitle(title);
+ }
+ if(filterPath != null && filterPath.length() > 0) {
+ fileChooser.setCurrentDirectory(new File(filterPath));
+ }
+ if(fileName != null && fileName.length() > 0) {
+ fileChooser.setSelectedFile(new File(fileChooser.getCurrentDirectory().getAbsolutePath() + "/" + fileName));
+ }
+ fileName = "";
+ fileNames = null;
+ String fullPath = null;
+ fileChooser.setMultiSelectionEnabled((style & SWT.MULTI) != 0);
+ if(filterExtensions != null && filterExtensions.length > 0) {
+ fileChooser.setAcceptAllFileFilterUsed(false);
+ for(int i=0; i= filterNames.length)? filterExtension: filterNames[i];
+ fileChooser.addChoosableFileFilter(new FileFilter() {
+ public boolean accept(File f) {
+ if(f.isDirectory()) {
+ return true;
+ }
+ for(int i=0; i 0) {
+ fullPath = selectedFiles[0].getParentFile().getAbsolutePath();
+ }
+ } else {
+ File selectedFile = fileChooser.getSelectedFile();
+ fileName = selectedFile.getName();
+ fullPath = selectedFile.getAbsolutePath();
+ }
+ filterPath = new String(fullPath);
+ }
+ return fullPath;
+}
+
+/**
+ * Set the initial filename which the dialog will
+ * select by default when opened to the argument,
+ * which may be null. The name will be prefixed with
+ * the filter path when one is supplied.
+ *
+ * @param string the file name
+ */
+public void setFileName (String string) {
+ fileName = string;
+}
+
+/**
+ * Set the file extensions which the dialog will
+ * use to filter the files it shows to the argument,
+ * which may be null.
+ *
+ * The strings are platform specific. For example, on
+ * Windows, an extension filter string is typically of
+ * the form "*.extension", where "*.*" matches all files.
+ *
+ *
+ * @param extensions the file extension filter
+ *
+ * @see #setFilterNames to specify the user-friendly
+ * names corresponding to the extensions
+ */
+public void setFilterExtensions (String [] extensions) {
+ filterExtensions = extensions;
+}
+
+/**
+ * Sets the the names that describe the filter extensions
+ * which the dialog will use to filter the files it shows
+ * to the argument, which may be null.
+ *
+ * Each name is a user-friendly short description shown for
+ * its corresponding filter. The names array must
+ * be the same length as the extensions array.
+ *
+ *
+ * @param names the list of filter names, or null for no filter names
+ *
+ * @see #setFilterExtensions
+ */
+public void setFilterNames (String [] names) {
+ filterNames = names;
+}
+
+/**
+ * Sets the directory path that the dialog will use
+ * to the argument, which may be null. File names in this
+ * path will appear in the dialog, filtered according
+ * to the filter extensions. If the string is null,
+ * then the operating system's default filter path
+ * will be used.
+ *
+ * Note that the path string is platform dependent.
+ * For convenience, either '/' or '\' can be used
+ * as a path separator.
+ *
+ *
+ * @param string the directory path
+ *
+ * @see #setFilterExtensions
+ */
+public void setFilterPath (String string) {
+ filterPath = string;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FontDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FontDialog.java
new file mode 100644
index 00000000000..6285166bdb7
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/FontDialog.java
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.Color;
+import java.awt.Frame;
+import java.awt.Window;
+import java.awt.font.TextAttribute;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.internal.swing.JFontChooser;
+
+/**
+ * Instances of this class allow the user to select a font
+ * from all available fonts in the system.
+ *
+ *
Styles:
+ *
(none)
+ *
Events:
+ *
(none)
+ *
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+public class FontDialog extends Dialog {
+ FontData fontData;
+ RGB rgb;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+public FontDialog (Shell parent) {
+ this (parent, SWT.PRIMARY_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+public FontDialog (Shell parent, int style) {
+ super (parent, style);
+ checkSubclass ();
+}
+
+/**
+ * Returns a FontData object describing the font that was
+ * selected in the dialog, or null if none is available.
+ *
+ * @return the FontData for the selected font, or null
+ * @deprecated use #getFontList ()
+ */
+public FontData getFontData () {
+ return fontData;
+}
+
+/**
+ * Returns a FontData set describing the font that was
+ * selected in the dialog, or null if none is available.
+ *
+ * @return the FontData for the selected font, or null
+ * @since 2.1.1
+ */
+public FontData [] getFontList () {
+ if (fontData == null) return null;
+ FontData [] result = new FontData [1];
+ result [0] = fontData;
+ return result;
+}
+
+/**
+ * Returns an RGB describing the color that was selected
+ * in the dialog, or null if none is available.
+ *
+ * @return the RGB value for the selected color, or null
+ *
+ * @see PaletteData#getRGBs
+ *
+ * @since 2.1
+ */
+public RGB getRGB () {
+ return rgb;
+}
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return a FontData object describing the font that was selected,
+ * or null if the dialog was cancelled or an error occurred
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the dialog has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog
+ *
+ */
+public FontData open () {
+ Window window = (Window)getParent().handle;
+ JFontChooser fontChooser;
+ if(window instanceof Frame) {
+ fontChooser = new JFontChooser((Frame)window);
+ } else {
+ fontChooser = new JFontChooser((java.awt.Dialog)window);
+ }
+ if(rgb != null) {
+ fontChooser.setDefaultColor(new Color(rgb.red, rgb.green, rgb.blue));
+ }
+ int dpi = getParent().getDisplay().getDPI().x;
+ if(fontData != null) {
+ int height = Math.round(fontData.getHeight() * dpi / 72.0f);
+ int style = fontData.getStyle();
+ style = (((style & SWT.ITALIC) != 0? java.awt.Font.ITALIC: 0)) | (((style & SWT.BOLD) != 0? java.awt.Font.BOLD: 0));
+
+ java.awt.Font defaultFont;
+ if(fontData.data != null) {
+ Map attributeMap = new HashMap(fontData.data);
+ attributeMap.put(TextAttribute.FAMILY, fontData.getName());
+ attributeMap.put(TextAttribute.POSTURE, (style & SWT.ITALIC) != 0? TextAttribute.POSTURE_OBLIQUE: TextAttribute.POSTURE_REGULAR);
+ attributeMap.put(TextAttribute.WEIGHT, (style & SWT.BOLD) != 0? TextAttribute.WEIGHT_BOLD: TextAttribute.WEIGHT_REGULAR);
+ defaultFont = new java.awt.Font(attributeMap);
+ } else {
+ defaultFont = new java.awt.Font(fontData.getName(), style, height);
+ }
+ fontChooser.setDefaultFont(defaultFont);
+ }
+ fontChooser.setModal(true);
+ fontChooser.setVisible(true);
+ java.awt.Font font = fontChooser.getNewFont();
+ if(font == null) {
+ return null;
+ }
+ Color color = fontChooser.getNewColor();
+ int height = Math.round(font.getSize() * 72.0f / dpi);
+ int style = font.getStyle();
+ fontData = new FontData(font.getName(), height, 0 | (((style & java.awt.Font.ITALIC) != 0? SWT.ITALIC: 0)) | (((style & java.awt.Font.BOLD) != 0? SWT.BOLD: 0)));
+ fontData.data = font.getAttributes();
+ rgb = new RGB(color.getRed(), color.getGreen(), color.getBlue());
+ return fontData;
+}
+
+/**
+ * Sets a FontData object describing the font to be
+ * selected by default in the dialog, or null to let
+ * the platform choose one.
+ *
+ * @param fontData the FontData to use initially, or null
+ * @deprecated use #setFontList (FontData [])
+ */
+public void setFontData (FontData fontData) {
+ this.fontData = fontData;
+}
+
+/**
+ * Sets the set of FontData objects describing the font to
+ * be selected by default in the dialog, or null to let
+ * the platform choose one.
+ *
+ * @param fontData the set of FontData objects to use initially, or null
+ * to let the platform select a default when open() is called
+ *
+ * @see Font#getFontData
+ *
+ * @since 2.1.1
+ */
+public void setFontList (FontData [] fontData) {
+ if (fontData != null && fontData.length > 0) {
+ this.fontData = fontData [0];
+ } else {
+ this.fontData = null;
+ }
+}
+
+/**
+ * Sets the RGB describing the color to be selected by default
+ * in the dialog, or null to let the platform choose one.
+ *
+ * @param rgb the RGB value to use initially, or null to let
+ * the platform select a default when open() is called
+ *
+ * @see PaletteData#getRGBs
+ *
+ * @since 2.1
+ */
+public void setRGB (RGB rgb) {
+ this.rgb = rgb;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Group.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Group.java
new file mode 100644
index 00000000000..9ccd58d57ff
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Group.java
@@ -0,0 +1,412 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.Container;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.swing.CGroup;
+
+/**
+ * Instances of this class provide an etched border
+ * with an optional title.
+ *
+ * Shadow styles are hints and may not be honoured
+ * by the platform. To create a group with the
+ * default shadow style for the platform, do not
+ * specify a shadow style.
+ *
+ * Note: Only one of the above styles may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+
+public class Group extends Composite {
+
+ String text;
+
+// static final int CLIENT_INSET = 3;
+// static final int GroupProc;
+// static final TCHAR GroupClass = new TCHAR (0, OS.IsWinCE ? "BUTTON" : "SWT_GROUP", true);
+// static {
+// /*
+// * Feature in Windows. The group box window class
+// * uses the CS_HREDRAW and CS_VREDRAW style bits to
+// * force a full redraw of the control and all children
+// * when resized. This causes flashing. The fix is to
+// * register a new window class without these bits and
+// * implement special code that damages only the exposed
+// * area.
+// *
+// * Feature in WinCE. On certain devices, defining
+// * a new window class which looks like BUTTON causes
+// * CreateWindowEx() to crash. The workaround is to use
+// * the class Button directly.
+// */
+// WNDCLASS lpWndClass = new WNDCLASS ();
+// if (OS.IsWinCE) {
+// OS.GetClassInfo (0, GroupClass, lpWndClass);
+// GroupProc = lpWndClass.lpfnWndProc;
+// } else {
+// TCHAR WC_BUTTON = new TCHAR (0, "BUTTON", true);
+// OS.GetClassInfo (0, WC_BUTTON, lpWndClass);
+// GroupProc = lpWndClass.lpfnWndProc;
+// int hInstance = OS.GetModuleHandle (null);
+// if (!OS.GetClassInfo (hInstance, GroupClass, lpWndClass)) {
+// int hHeap = OS.GetProcessHeap ();
+// lpWndClass.hInstance = hInstance;
+// lpWndClass.style &= ~(OS.CS_HREDRAW | OS.CS_VREDRAW);
+// int byteCount = GroupClass.length () * TCHAR.sizeof;
+// int lpszClassName = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+// OS.MoveMemory (lpszClassName, GroupClass, byteCount);
+// lpWndClass.lpszClassName = lpszClassName;
+// OS.RegisterClass (lpWndClass);
+//// OS.HeapFree (hHeap, 0, lpszClassName);
+// }
+// }
+// }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#SHADOW_ETCHED_IN
+ * @see SWT#SHADOW_ETCHED_OUT
+ * @see SWT#SHADOW_IN
+ * @see SWT#SHADOW_OUT
+ * @see SWT#SHADOW_NONE
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Group (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+//int callWindowProc (int hwnd, int msg, int wParam, int lParam) {
+// if (handle == 0) return 0;
+// /*
+// * Feature in Windows. When the user clicks on the group
+// * box label, the group box takes focus. This is unwanted.
+// * The fix is to avoid calling the group box window proc.
+// */
+// switch (msg) {
+// case OS.WM_LBUTTONDOWN:
+// case OS.WM_LBUTTONDBLCLK:
+// return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+// }
+// return OS.CallWindowProc (GroupProc, hwnd, msg, wParam, lParam);
+//}
+
+static int checkStyle (int style) {
+ style |= SWT.NO_FOCUS;
+ /*
+ * Even though it is legal to create this widget
+ * with scroll bars, they serve no useful purpose
+ * because they do not automatically scroll the
+ * widget's client area. The fix is to clear
+ * the SWT style.
+ */
+ return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+//public Point computeSize (int wHint, int hHint, boolean changed) {
+// checkWidget ();
+// Point size = super.computeSize (wHint, hHint, changed);
+// int length = OS.GetWindowTextLength (handle);
+// if (length != 0) {
+// /*
+// * If the group has text, and the text is wider than the
+// * client area, pad the width so the text is not clipped.
+// */
+// TCHAR buffer1 = new TCHAR (getCodePage (), length + 1);
+// OS.GetWindowText (handle, buffer1, length + 1);
+// int newFont, oldFont = 0;
+// int hDC = OS.GetDC (handle);
+// newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+// RECT rect = new RECT ();
+// int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE;
+// OS.DrawText (hDC, buffer1, length, rect, flags);
+// if (newFont != 0) OS.SelectObject (hDC, oldFont);
+// OS.ReleaseDC (handle, hDC);
+// size.x = Math.max (size.x, rect.right - rect.left + CLIENT_INSET * 6);
+// }
+// return size;
+//}
+//
+//public Rectangle computeTrim (int x, int y, int width, int height) {
+// checkWidget ();
+// Rectangle trim = super.computeTrim (x, y, width, height);
+// int newFont, oldFont = 0;
+// int hDC = OS.GetDC (handle);
+// newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+// TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA ();
+// OS.GetTextMetrics (hDC, tm);
+// if (newFont != 0) OS.SelectObject (hDC, oldFont);
+// OS.ReleaseDC (handle, hDC);
+// trim.x -= CLIENT_INSET;
+// trim.y -= tm.tmHeight;
+// trim.width += CLIENT_INSET * 2;
+// trim.height += tm.tmHeight + CLIENT_INSET;
+// return trim;
+//}
+
+void createHandleInit() {
+ super.createHandleInit();
+ state |= DRAW_BACKGROUND;
+ state &= ~CANVAS;
+}
+
+protected Container createHandle () {
+ return (Container)CGroup.Factory.newInstance(this, style);
+// super.createHandle ();
+}
+
+//public Rectangle getClientArea () {
+// checkWidget ();
+// forceResize ();
+// RECT rect = new RECT ();
+// OS.GetClientRect (handle, rect);
+// int newFont, oldFont = 0;
+// int hDC = OS.GetDC (handle);
+// newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+// TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA ();
+// OS.GetTextMetrics (hDC, tm);
+// if (newFont != 0) OS.SelectObject (hDC, oldFont);
+// OS.ReleaseDC (handle, hDC);
+// int x = CLIENT_INSET, y = tm.tmHeight;
+// int width = rect.right - CLIENT_INSET * 2;
+// int height = rect.bottom - y - CLIENT_INSET;
+// return new Rectangle (x, y, width, height);
+//}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns the receiver's text, which is the string that the
+ * is used as the title. If the text has not previously
+ * been set, returns an empty string.
+ *
+ * @return the text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getText () {
+ checkWidget ();
+ return text == null? "": text;
+}
+
+boolean mnemonicHit (char key) {
+ return setFocus ();
+}
+
+boolean mnemonicMatch (char key) {
+ char mnemonic = findMnemonic (getText ());
+ if (mnemonic == '\0') return false;
+ return Character.toUpperCase (key) == Character.toUpperCase (mnemonic);
+}
+
+/**
+ * Sets the receiver's text, which is the string that will
+ * be displayed as the receiver's title, to the argument,
+ * which may not be null. The string may include the mnemonic character.
+ *
+ * Mnemonics are indicated by an '&' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, focus is assigned
+ * to the first child of the group. On most platforms, the
+ * mnemonic appears underlined but may be emphasised in a
+ * platform specific manner. The mnemonic indicator character
+ * '&' can be escaped by doubling it in the string, causing
+ * a single '&' to be displayed.
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ this.text = string;
+ int mnemonicIndex = findMnemonicIndex(string);
+ if(mnemonicIndex > 0) {
+ String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&");
+ string = s + string.substring(mnemonicIndex).replaceAll("&&", "&");
+ mnemonicIndex -= mnemonicIndex - 1 - s.length();
+ mnemonicIndex--;
+ } else {
+ string = string.replaceAll("&&", "&");
+ }
+ ((CGroup)handle).setText(string);
+}
+
+//int widgetStyle () {
+// /*
+// * Bug in Windows. When GetDCEx () is called with DCX_INTERSECTUPDATE,
+// * the HDC that is returned does not include the current update region.
+// * This was confirmed under DEBUG Windows when GetDCEx () complained about
+// * invalid flags. Therefore, it is not easily possible to get an HDC from
+// * outside of WM_PAINT that includes the current damage and clips children.
+// * Because the receiver has children and draws a frame and label, it is
+// * necessary that the receiver always draw clipped, in the current damaged
+// * area. The fix is to force the receiver to be fully clipped by including
+// * WS_CLIPCHILDREN and WS_CLIPSIBLINGS in the default style bits.
+// */
+// return super.widgetStyle () | OS.BS_GROUPBOX | OS.WS_CLIPCHILDREN | OS.WS_CLIPSIBLINGS;
+//}
+//
+//TCHAR windowClass () {
+// return GroupClass;
+//}
+//
+//int windowProc () {
+// return GroupProc;
+//}
+//
+//LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+// LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Feaure in Windows. Group boxes do not erase
+// * the background before drawing. The fix is to
+// * fill the background.
+// *
+// * NOTE: This work around causes flashing on XP
+// * and is not necessary when a parent has a theme.
+// */
+// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+// if (findThemeControl () != null) return result;
+// }
+// drawBackground (wParam);
+// return LRESULT.ONE;
+//}
+//
+//LRESULT WM_NCHITTEST (int wParam, int lParam) {
+// LRESULT result = super.WM_NCHITTEST (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Feature in Windows. The window proc for the group box
+// * returns HTTRANSPARENT indicating that mouse messages
+// * should not be delivered to the receiver and any children.
+// * Normally, group boxes in Windows do not have children and
+// * this is the correct behavior for this case. Because we
+// * allow children, answer HTCLIENT to allow mouse messages
+// * to be delivered to the children.
+// */
+// int code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+// if (code == OS.HTTRANSPARENT) code = OS.HTCLIENT;
+// return new LRESULT (code);
+//}
+//
+//LRESULT WM_MOUSEMOVE (int wParam, int lParam) {
+// LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Feature in Windows. In version 6.00 of COMCTL32.DLL,
+// * every time the mouse moves, the group title redraws.
+// * This only happens when WM_NCHITTEST returns HTCLIENT.
+// * The fix is to avoid calling the group window proc.
+// */
+// return LRESULT.ZERO;
+//}
+//
+//LRESULT WM_PRINTCLIENT (int wParam, int lParam) {
+// LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Feature in Windows. In version 6.00 of COMCTL32.DLL,
+// * when WM_PRINTCLIENT is sent from a child BS_GROUP
+// * control to a parent BS_GROUP, the parent BS_GROUP
+// * clears the font from the HDC. Normally, group boxes
+// * in Windows do not have children so this behavior is
+// * undefined. When the parent of a BS_GROUP is not a
+// * BS_GROUP, there is no problem. The fix is to save
+// * and restore the current font.
+// */
+// if (OS.COMCTL32_MAJOR >= 6) {
+// int nSavedDC = OS.SaveDC (wParam);
+// int code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
+// OS.RestoreDC (wParam, nSavedDC);
+// return new LRESULT (code);
+// }
+// return result;
+//}
+//
+//LRESULT WM_SIZE (int wParam, int lParam) {
+// LRESULT result = super.WM_SIZE (wParam, lParam);
+// if (OS.IsWinCE) return result;
+// OS.InvalidateRect (handle, null, true);
+// return result;
+//}
+//
+//LRESULT wmColorChild (int wParam, int lParam) {
+// LRESULT result = super.wmColorChild (wParam, lParam);
+// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+// Control control = findThemeControl ();
+// if (control != null) {
+// OS.SetBkMode (wParam, OS.TRANSPARENT);
+// RECT rect = new RECT ();
+// OS.GetClientRect (control.handle, rect);
+// OS.MapWindowPoints (control.handle, handle, rect, 2);
+// control.drawThemeBackground (wParam, rect);
+// return new LRESULT (OS.GetStockObject (OS.NULL_BRUSH));
+// }
+// }
+// return result;
+//}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Label.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Label.java
new file mode 100644
index 00000000000..c6c86443f4f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Label.java
@@ -0,0 +1,564 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.Container;
+import java.awt.Dimension;
+
+import javax.swing.ImageIcon;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.swing.CLabel;
+
+/**
+ * Instances of this class represent a non-selectable
+ * user interface object that displays a string or image.
+ * When SEPARATOR is specified, displays a single
+ * vertical or horizontal line.
+ *
+ *
Styles:
+ *
SEPARATOR, HORIZONTAL, VERTICAL
+ *
SHADOW_IN, SHADOW_OUT, SHADOW_NONE
+ *
CENTER, LEFT, RIGHT, WRAP
+ *
Events:
+ *
(none)
+ *
+ *
+ * Note: Only one of SHADOW_IN, SHADOW_OUT and SHADOW_NONE may be specified.
+ * SHADOW_NONE is a HINT. Only one of HORIZONTAL and VERTICAL may be specified.
+ * Only one of CENTER, LEFT and RIGHT may be specified.
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+public class Label extends Control {
+// String text = "";
+ Image image;
+ String text;
+// int font;
+// static final int LabelProc;
+// static final TCHAR LabelClass = new TCHAR (0, "STATIC", true);
+// static {
+// WNDCLASS lpWndClass = new WNDCLASS ();
+// OS.GetClassInfo (0, LabelClass, lpWndClass);
+// LabelProc = lpWndClass.lpfnWndProc;
+// }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#SEPARATOR
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see SWT#SHADOW_IN
+ * @see SWT#SHADOW_OUT
+ * @see SWT#SHADOW_NONE
+ * @see SWT#CENTER
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#WRAP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Label (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+//int callWindowProc (int hwnd, int msg, int wParam, int lParam) {
+// if (handle == 0) return 0;
+// return OS.CallWindowProc (LabelProc, hwnd, msg, wParam, lParam);
+//}
+
+static int checkStyle (int style) {
+ style |= SWT.NO_FOCUS;
+ if ((style & SWT.SEPARATOR) != 0) {
+ style = checkBits (style, SWT.VERTICAL, SWT.HORIZONTAL, 0, 0, 0, 0);
+ return checkBits (style, SWT.SHADOW_OUT, SWT.SHADOW_IN, SWT.SHADOW_NONE, 0, 0, 0);
+ }
+ return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+}
+
+//public Point computeSize (int wHint, int hHint, boolean changed) {
+// checkWidget ();
+// int width = 0, height = 0;
+// int border = getBorderWidth ();
+// if ((style & SWT.SEPARATOR) != 0) {
+// int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER);
+// if ((style & SWT.HORIZONTAL) != 0) {
+// width = DEFAULT_WIDTH; height = lineWidth * 2;
+// } else {
+// width = lineWidth * 2; height = DEFAULT_HEIGHT;
+// }
+// if (wHint != SWT.DEFAULT) width = wHint;
+// if (hHint != SWT.DEFAULT) height = hHint;
+// width += border * 2; height += border * 2;
+// return new Point (width, height);
+// }
+// /*
+// * NOTE: SS_BITMAP and SS_ICON are not single bit
+// * masks so it is necessary to test for all of the
+// * bits in these masks.
+// */
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// boolean isBitmap = (bits & OS.SS_BITMAP) == OS.SS_BITMAP;
+// boolean isIcon = (bits & OS.SS_ICON) == OS.SS_ICON;
+// if (isBitmap || isIcon) {
+// if (image != null) {
+// Rectangle rect = image.getBounds();
+// width = rect.width;
+// height = rect.height;
+// }
+// } else {
+// int hDC = OS.GetDC (handle);
+// int newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+// int oldFont = OS.SelectObject (hDC, newFont);
+// RECT rect = new RECT ();
+// int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_EXPANDTABS;
+// if ((style & SWT.WRAP) != 0 && wHint != SWT.DEFAULT) {
+// flags |= OS.DT_WORDBREAK;
+// rect.right = wHint;
+// }
+// int length = OS.GetWindowTextLength (handle);
+// TCHAR buffer = new TCHAR (getCodePage (), length + 1);
+// OS.GetWindowText (handle, buffer, length + 1);
+// OS.DrawText (hDC, buffer, length, rect, flags);
+// width = rect.right - rect.left;
+// height = rect.bottom - rect.top;
+// if (height == 0) {
+// TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA ();
+// OS.GetTextMetrics (hDC, tm);
+// height = tm.tmHeight;
+// }
+// if (newFont != 0) OS.SelectObject (hDC, oldFont);
+// OS.ReleaseDC (handle, hDC);
+// }
+// if (wHint != SWT.DEFAULT) width = wHint;
+// if (hHint != SWT.DEFAULT) height = hHint;
+// width += border * 2; height += border * 2;
+// /*
+// * Feature in WinCE PPC. Text labels have a trim
+// * of one pixel wide on the right and left side.
+// * The fix is to increase the size.
+// */
+// if (OS.IsWinCE) {
+// if (!isBitmap && !isIcon) width += 2;
+// }
+// return new Point (width, height);
+//}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * LEFT, RIGHT or CENTER
+ * unless the receiver is a SEPARATOR label, in
+ * which case, NONE is returned.
+ *
+ * @return the alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getAlignment () {
+ checkWidget ();
+ if ((style & SWT.SEPARATOR) != 0) return 0;
+ if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+ if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+ if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+ return SWT.LEFT;
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ if((style & SWT.WRAP) != 0) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ isAdjustingSize = true;
+ }
+ });
+ Dimension size = handle.getSize();
+ if(wHint == SWT.DEFAULT) {
+ handle.setSize(((CLabel)handle).getPreferredWidth(), 0);
+ } else {
+ handle.setSize(wHint, 0);
+ }
+ Point point = super.computeSize (wHint, hHint, changed);
+ handle.setSize(size);
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ isAdjustingSize = false;
+ }
+ });
+ return point;
+ }
+ return super.computeSize (wHint, hHint, changed);
+}
+
+void createHandleInit() {
+ super.createHandleInit();
+ state |= THEME_BACKGROUND;
+}
+
+Container createHandle () {
+ return (Container)CLabel.Factory.newInstance(this, style);
+}
+
+/**
+ * Returns the receiver's image if it has one, or null
+ * if it does not.
+ *
+ * @return the receiver's image
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Image getImage () {
+ checkWidget ();
+ return image;
+}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set or if the receiver is
+ * a SEPARATOR label.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getText () {
+ checkWidget ();
+ if ((style & SWT.SEPARATOR) != 0) return "";
+ return text == null? "": text;
+}
+
+//boolean mnemonicHit (char key) {
+// Composite control = this.parent;
+// while (control != null) {
+// Control [] children = control._getChildren ();
+// int index = 0;
+// while (index < children.length) {
+// if (children [index] == this) break;
+// index++;
+// }
+// index++;
+// if (index < children.length) {
+// if (children [index].setFocus ()) return true;
+// }
+// control = control.parent;
+// }
+// return false;
+//}
+//
+//boolean mnemonicMatch (char key) {
+// char mnemonic = findMnemonic (getText ());
+// if (mnemonic == '\0') return false;
+// return Character.toUpperCase (key) == Character.toUpperCase (mnemonic);
+//}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ image = null;
+}
+
+/**
+ * Controls how text and images will be displayed in the receiver.
+ * The argument should be one of LEFT, RIGHT
+ * or CENTER. If the receiver is a SEPARATOR
+ * label, the argument is ignored and the alignment is not changed.
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setAlignment (int alignment) {
+ checkWidget ();
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return;
+ style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ if((alignment & SWT.LEFT) != 0) {
+ ((CLabel)handle).setAlignment(SwingConstants.LEFT);
+ } else if((alignment & SWT.RIGHT) != 0) {
+ ((CLabel)handle).setAlignment(SwingConstants.RIGHT);
+ } else if((alignment & SWT.CENTER) != 0) {
+ ((CLabel)handle).setAlignment(SwingConstants.CENTER);
+ }
+}
+
+/**
+ * Sets the receiver's image to the argument, which may be
+ * null indicating that no image should be displayed.
+ *
+ * @param image the image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * This method sets the widget label. The label may include
+ * the mnemonic character and line delimiters.
+ *
+ *
+ * Mnemonics are indicated by an '&' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, focus is assigned
+ * to the control that follows the label. On most platforms,
+ * the mnemonic appears underlined but may be emphasised in a
+ * platform specific manner. The mnemonic indicator character
+ * '&' can be escaped by doubling it in the string, causing
+ * a single '&' to be displayed.
+ *
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if ((style & SWT.SEPARATOR) != 0) return;
+ this.text = string;
+ int mnemonicIndex = findMnemonicIndex(string);
+ if(mnemonicIndex > 0) {
+ String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&");
+ string = s + string.substring(mnemonicIndex).replaceAll("&&", "&");
+ mnemonicIndex -= mnemonicIndex - 1 - s.length();
+ mnemonicIndex--;
+ } else {
+ string = string.replaceAll("&&", "&");
+ }
+ ((CLabel)handle).setText(string, mnemonicIndex);
+}
+
+//int widgetExtStyle () {
+// int bits = super.widgetExtStyle () & ~OS.WS_EX_CLIENTEDGE;
+// if ((style & SWT.BORDER) != 0) return bits | OS.WS_EX_STATICEDGE;
+// return bits;
+//}
+//
+//int widgetStyle () {
+// int bits = super.widgetStyle () | OS.SS_NOTIFY;
+// if ((style & SWT.SEPARATOR) != 0) return bits | OS.SS_OWNERDRAW;
+// if ((style & SWT.CENTER) != 0) return bits | OS.SS_CENTER;
+// if ((style & SWT.RIGHT) != 0) return bits | OS.SS_RIGHT;
+// if ((style & SWT.WRAP) != 0) return bits | OS.SS_LEFT;
+// return bits | OS.SS_LEFTNOWORDWRAP;
+//}
+//
+//TCHAR windowClass () {
+// return LabelClass;
+//}
+//
+//int windowProc () {
+// return LabelProc;
+//}
+//
+//LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+// LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+// if (result != null) return result;
+// if ((style & SWT.SEPARATOR) != 0) return LRESULT.ONE;
+// /*
+// * Bug in Windows. When a label has the SS_BITMAP
+// * or SS_ICON style, the label does not draw the
+// * background. The fix is to draw the background
+// * when the label is showing a bitmap or icon.
+// *
+// * NOTE: SS_BITMAP and SS_ICON are not single bit
+// * masks so it is necessary to test for all of the
+// * bits in these masks.
+// */
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// boolean isBitmap = (bits & OS.SS_BITMAP) == OS.SS_BITMAP;
+// boolean isIcon = (bits & OS.SS_ICON) == OS.SS_ICON;
+// if (isBitmap || isIcon) {
+// drawBackground (wParam);
+// return LRESULT.ONE;
+// }
+// return result;
+//}
+//
+//LRESULT WM_GETFONT (int wParam, int lParam) {
+// LRESULT result = super.WM_GETFONT (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Bug in Windows. When the style of a label is SS_BITMAP
+// * or SS_ICON, the label does not remember the font that is
+// * set in WM_SETFONT. The fix is to remember the font and
+// * return the font in WM_GETFONT.
+// */
+// if (font == 0) font = defaultFont ();
+// return new LRESULT (font);
+//}
+//
+//LRESULT WM_SETFONT (int wParam, int lParam) {
+// /*
+// * Bug in Windows. When the style of a label is SS_BITMAP
+// * or SS_ICON, the label does not remember the font that is
+// * set in WM_SETFONT. The fix is to remember the font and
+// * return the font in WM_GETFONT.
+// */
+// return super.WM_SETFONT (font = wParam, lParam);
+//}
+//
+//LRESULT WM_SIZE (int wParam, int lParam) {
+// LRESULT result = super.WM_SIZE (wParam, lParam);
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the resize
+// * event. If this happens, end the processing of the
+// * Windows message by returning the result of the
+// * WM_SIZE message.
+// */
+// if (isDisposed ()) return result;
+// if ((style & SWT.SEPARATOR) != 0) {
+// OS.InvalidateRect (handle, null, true);
+// return result;
+// }
+//
+// /*
+// * Bug in Windows. For some reason, a label with
+// * SS_BITMAP or SS_ICON and SS_CENTER does not redraw
+// * properly when resized. Only the new area is drawn
+// * and the old area is not cleared. The fix is to
+// * force the redraw.
+// *
+// * NOTE: SS_BITMAP and SS_ICON are not single bit
+// * masks so it is necessary to test for all of the
+// * bits in these masks.
+// */
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// boolean isBitmap = (bits & OS.SS_BITMAP) == OS.SS_BITMAP;
+// boolean isIcon = (bits & OS.SS_ICON) == OS.SS_ICON;
+// if (isBitmap || isIcon) {
+// OS.InvalidateRect (handle, null, true);
+// return result;
+// }
+//
+// /*
+// * Bug in Windows. For some reason, a label with
+// * style SS_LEFT, SS_CENTER or SS_RIGHT does not
+// * redraw the text in the new position when resized.
+// * Note that SS_LEFTNOWORDWRAP does not have the
+// * problem. The fix is to force the redraw.
+// */
+// if ((style & (SWT.WRAP | SWT.CENTER | SWT.RIGHT)) != 0) {
+// OS.InvalidateRect (handle, null, true);
+// return result;
+// }
+//
+// return result;
+//}
+//
+//LRESULT wmColorChild (int wParam, int lParam) {
+// LRESULT result = super.wmColorChild (wParam, lParam);
+// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+// Control control = findThemeControl ();
+// if (control != null) {
+// OS.SetBkMode (wParam, OS.TRANSPARENT);
+// RECT rect = new RECT ();
+// OS.GetClientRect (control.handle, rect);
+// OS.MapWindowPoints (control.handle, handle, rect, 2);
+// control.drawThemeBackground (wParam, rect);
+// return new LRESULT (OS.GetStockObject (OS.NULL_BRUSH));
+// }
+// }
+// return result;
+//}
+//
+//LRESULT wmDrawChild (int wParam, int lParam) {
+// DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
+// OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
+// drawBackground (struct.hDC);
+// if ((style & SWT.SHADOW_NONE) != 0) return null;
+// RECT rect = new RECT ();
+// int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER);
+// int flags = OS.EDGE_ETCHED;
+// if ((style & SWT.SHADOW_IN) != 0) flags = OS.EDGE_SUNKEN;
+// if ((style & SWT.HORIZONTAL) != 0) {
+// int bottom = struct.top + Math.max (lineWidth * 2, (struct.bottom - struct.top) / 2);
+// OS.SetRect (rect, struct.left, struct.top, struct.right, bottom);
+// OS.DrawEdge (struct.hDC, rect, flags, OS.BF_BOTTOM);
+// } else {
+// int right = struct.left + Math.max (lineWidth * 2, (struct.right - struct.left) / 2);
+// OS.SetRect (rect, struct.left, struct.top, right, struct.bottom);
+// OS.DrawEdge (struct.hDC, rect, flags, OS.BF_RIGHT);
+// }
+// return null;
+//}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Link.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Link.java
new file mode 100644
index 00000000000..faa60cd0c9c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Link.java
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.util.EventObject;
+
+import javax.swing.SwingUtilities;
+import javax.swing.event.HyperlinkEvent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.swing.CLink;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+
+/**
+ * Instances of this class represent a selectable
+ * user interface object that displays a text with
+ * links.
+ *
+ *
+ *
Styles:
+ *
(none)
+ *
Events:
+ *
Selection
+ *
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @since 3.1
+ */
+public class Link extends Control {
+
+ String text;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Link (Composite parent, int style) {
+ super (parent, style);
+}
+
+/**
+ * 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 SelectionListener
+ * interface.
+ *
+ * widgetSelected is called when the control is selected.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection, typedListener);
+ addListener (SWT.DefaultSelection, typedListener);
+}
+
+void createHandleInit() {
+ super.createHandleInit();
+ state |= THEME_BACKGROUND;
+}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ checkWidget ();
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ isAdjustingSize = true;
+ }
+ });
+ Dimension size = handle.getSize();
+ if(wHint == SWT.DEFAULT) {
+ handle.setSize(((CLink)handle).getPreferredWidth(), 0);
+ } else {
+ handle.setSize(wHint, 0);
+ }
+ Point point = super.computeSize (wHint, hHint, changed);
+ handle.setSize(size);
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ isAdjustingSize = false;
+ }
+ });
+ return point;
+}
+
+Container createHandle () {
+ return (Container)CLink.Factory.newInstance(this, style);
+}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getText () {
+ checkWidget ();
+ return text == null? "": text;
+}
+
+boolean mnemonicHit (char key) {
+ Composite control = this.parent;
+ while (control != null) {
+ Control [] children = control._getChildren ();
+ int index = 0;
+ while (index < children.length) {
+ if (children [index] == this) break;
+ index++;
+ }
+ index++;
+ if (index < children.length) {
+ if (children [index].setFocus ()) return true;
+ }
+ control = control.parent;
+ }
+ return false;
+}
+
+boolean mnemonicMatch (char key) {
+ char mnemonic = findMnemonic (getText ());
+ if (mnemonic == '\0') return false;
+ return Character.toUpperCase (key) == Character.toUpperCase (mnemonic);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * The string can contain both regular text and hyperlinks. A hyperlink
+ * is delimited by an anchor tag, <A> and </A>. Within an
+ * anchor, a single HREF attribute is supported. When a hyperlink is
+ * selected, the text field of the selection event contains either the
+ * text of the hyperlink or the value of its HREF, if one was specified.
+ * In the rare case of identical hyperlinks within the same string, the
+ * HREF tag can be used to distinguish between them. The string may
+ * include the mnemonic character and line delimiters.
+ *
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ checkWidget ();
+ this.text = string;
+ int mnemonicIndex = findMnemonicIndex(string);
+ if(mnemonicIndex > 0) {
+ String s = string.substring(0, mnemonicIndex - 1).replaceAll("&&", "&");
+ string = s + string.substring(mnemonicIndex).replaceAll("&&", "&");
+// mnemonicIndex -= mnemonicIndex - 1 - s.length();
+// mnemonicIndex--;
+ } else {
+ string = string.replaceAll("&&", "&");
+ }
+ ((CLink)handle).setLinkText(string);
+}
+
+public void processEvent(EventObject e) {
+ if(e instanceof HyperlinkEvent) {
+ if(!hooks(SWT.Selection)) { super.processEvent(e); return; }
+ } else {
+ super.processEvent(e);
+ return;
+ }
+ if(isDisposed()) {
+ super.processEvent(e);
+ return;
+ }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ if(e instanceof HyperlinkEvent) {
+ Event event = new Event();
+ event.text = ((HyperlinkEvent)e).getDescription();
+ sendEvent(SWT.Selection, event);
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/List.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/List.java
new file mode 100644
index 00000000000..f19861321fe
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/List.java
@@ -0,0 +1,1031 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.AWTEvent;
+import java.awt.Container;
+import java.awt.event.ActionEvent;
+import java.util.EventObject;
+
+import javax.swing.event.ListSelectionEvent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.internal.swing.CList;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+
+/**
+ * Instances of this class represent a selectable user interface
+ * object that displays a list of strings and issues notificiation
+ * when a string selected. A list may be single or multi select.
+ *
+ *
+ *
Styles:
+ *
SINGLE, MULTI
+ *
Events:
+ *
Selection, DefaultSelection
+ *
+ *
+ * Note: Only one of SINGLE and MULTI may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+
+public class List extends Scrollable {
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public List (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+/**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param string the new item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #add(String,int)
+ */
+public void add (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ ((CList)handle).addElement(string);
+}
+/**
+ * Adds the argument to the receiver's list at the given
+ * zero-relative index.
+ *
+ * Note: To add an item at the end of the list, use the
+ * result of calling getItemCount() as the
+ * index or use add(String).
+ *
+ *
+ * @param string the new item
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #add(String)
+ */
+public void add (String string, int index) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (index == -1) error (SWT.ERROR_INVALID_RANGE);
+ int count = getItemCount();
+ if (index < 0 || count < index) error (SWT.ERROR_INVALID_RANGE);
+ ((CList)handle).addElement(string);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's selection changes, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * widgetSelected is called when the selection changes.
+ * widgetDefaultSelected is typically called when an item is double-clicked.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected. If the item at the index
+ * was not selected, it remains deselected. Indices that are out
+ * of range and duplicate indices are ignored.
+ *
+ * @param indices the array of indices for the items to deselect
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the set of indices is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void deselect (int index) {
+ checkWidget ();
+ ((CList)handle).removeSelectionInterval(index, index);
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected. If the item at the index
+ * was not selected, it remains deselected. The range of the
+ * indices is inclusive. Indices that are out of range are ignored.
+ *
+ * @param start the start index of the items to deselect
+ * @param end the end index of the items to deselect
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void deselect (int start, int end) {
+ checkWidget ();
+ ((CList)handle).removeSelectionInterval(start, end);
+}
+
+/**
+ * Deselects all selected items in the receiver.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void deselectAll () {
+ checkWidget ();
+ int count = getItemCount();
+ if(count == 0) return;
+ ((CList)handle).removeSelectionInterval(0, count - 1);
+}
+
+/**
+ * Returns the zero-relative index of the item which currently
+ * has the focus in the receiver, or -1 if no item has focus.
+ *
+ * @return the index of the selected item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getFocusIndex () {
+ checkWidget ();
+ return ((CList)handle).getFocusIndex();
+// int result = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+// if (result == 0) {
+// int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+// if (count == 0) return -1;
+// }
+// return result;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getItem (int index) {
+ checkWidget ();
+ if(index < 0) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ int count = getItemCount();
+ if (index < 0 || count <= index) error (SWT.ERROR_INVALID_RANGE);
+ return (String)((CList)handle).getElementAt(index);
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemCount () {
+ checkWidget ();
+ return ((CList)handle).getItemCount();
+}
+
+/**
+ * Returns the height of the area which would be used to
+ * display one of the items in the list.
+ *
+ * @return the height of one item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemHeight () {
+ checkWidget ();
+ java.awt.Rectangle bounds = ((CList)handle).getCellBounds(0);
+ // TODO: find another way to get a default value.
+ if(bounds == null) return 16;
+ return bounds.height;
+// int result = OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0);
+// if (result == OS.LB_ERR) error (SWT.ERROR_CANNOT_GET_ITEM_HEIGHT);
+// return result;
+}
+
+/**
+ * Returns a (possibly empty) array of Strings which
+ * are the items in the receiver.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the items in the receiver's list
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String [] getItems () {
+ checkWidget ();
+ int count = getItemCount ();
+ String [] result = new String [count];
+ for (int i=0; iStrings that are currently
+ * selected in the receiver. The order of the items is unspecified.
+ * An empty array indicates that no items are selected.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ *
+ * @return an array representing the selection
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String [] getSelection () {
+ checkWidget ();
+ int [] indices = getSelectionIndices ();
+ String [] result = new String [indices.length];
+ for (int i=0; i
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelectionCount () {
+ checkWidget ();
+ int min = ((CList)handle).getMinSelectionIndex();
+ if(min == -1) {
+ return 0;
+ }
+ return ((CList)handle).getMaxSelectionIndex() - min + 1;
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver, or -1 if no item is selected.
+ *
+ * @return the index of the selected item or -1
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelectionIndex () {
+ checkWidget ();
+ return ((CList)handle).getMinSelectionIndex();
+}
+
+/**
+ * Returns the zero-relative indices of the items which are currently
+ * selected in the receiver. The order of the indices is unspecified.
+ * The array is empty if no items are selected.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ *
+ * @return the array of indices of the selected items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int [] getSelectionIndices () {
+ checkWidget ();
+ return ((CList)handle).getSelectionIndices();
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items are
+ * scrolled or new items are added or removed.
+ *
+ * @return the index of the top item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getTopIndex () {
+ checkWidget ();
+ return ((CList)handle).getFirstVisibleIndex();
+}
+
+/**
+ * Gets the index of an item.
+ *
+ * The list is searched starting at 0 until an
+ * item is found that is equal to the search item.
+ * If no item is found, -1 is returned. Indexing
+ * is zero based.
+ *
+ * @param string the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int indexOf (String string) {
+ return indexOf (string, 0);
+}
+
+/**
+ * Searches the receiver's list starting at the given,
+ * zero-relative index until an item is found that is equal
+ * to the argument, and returns the index of that item. If
+ * no item is found or the starting index is out of range,
+ * returns -1.
+ *
+ * @param string the search item
+ * @param start the zero-relative index at which to start the search
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int indexOf (String string, int start) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ return ((CList)handle).indexOf(string, start);
+}
+
+/**
+ * Returns true if the item is selected,
+ * and false otherwise. Indices out of
+ * range are ignored.
+ *
+ * @param index the index of the item
+ * @return the visibility state of the item at the index
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean isSelected (int index) {
+ checkWidget ();
+ return ((CList)handle).isSelectedIndex(index);
+}
+
+/**
+ * Removes the items from the receiver at the given
+ * zero-relative indices.
+ *
+ * @param indices the array of indices of the items
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
ERROR_NULL_ARGUMENT - if the indices array is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void remove (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (indices.length == 0) return;
+ int [] newIndices = new int [indices.length];
+ System.arraycopy (indices, 0, newIndices, 0, indices.length);
+ sort (newIndices);
+ int start = newIndices [newIndices.length - 1], end = newIndices [0];
+ int count = getItemCount();
+ if (start < 0 || start > end || end >= count) error (SWT.ERROR_INVALID_RANGE);
+ CList cList = (CList)handle;
+ for(int i=newIndices.length-1; i>=0; i--) {
+ cList.removeElementAt(newIndices[i]);
+ }
+}
+
+/**
+ * Removes the item from the receiver at the given
+ * zero-relative index.
+ *
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void remove (int index) {
+ checkWidget ();
+ int count = getItemCount();
+ if (index < 0 || count <= index) error (SWT.ERROR_INVALID_RANGE);
+ ((CList)handle).removeElementAt(index);
+}
+
+/**
+ * Removes the items from the receiver which are
+ * between the given zero-relative start and end
+ * indices (inclusive).
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void remove (int start, int end) {
+ checkWidget ();
+ if (start > end) return;
+ int count = getItemCount();
+ if (start < 0 || start > end || end >= count) error (SWT.ERROR_INVALID_RANGE);
+ ((CList)handle).removeRange(start, end);
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * until an item is found that is equal to the argument,
+ * and removes that item from the list.
+ *
+ * @param string the item to remove
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
ERROR_INVALID_ARGUMENT - if the string is not found in the list
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void remove (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int index = indexOf (string, 0);
+ if (index == -1) error (SWT.ERROR_INVALID_ARGUMENT);
+ remove (index);
+}
+
+/**
+ * Removes all of the items from the receiver.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void removeAll () {
+ checkWidget ();
+ ((CList)handle).removeAllElements();
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's selection changes.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+boolean isAdjustingSelection;
+
+/**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is not cleared before the new items are selected.
+ *
+ * If the item at a given index is not selected, it is selected.
+ * If the item at a given index was already selected, it remains selected.
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ *
+ * @param indices the array of indices for the items to select
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the array of indices is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void select (int index) {
+ checkWidget ();
+ isAdjustingSelection = true;
+ ((CList)handle).addSelectionInterval(index, index);
+ isAdjustingSelection = false;
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is not cleared before the new items are selected.
+ *
+ * If an item in the given range is not selected, it is selected.
+ * If an item in the given range was already selected, it remains selected.
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see List#setSelection(int,int)
+ */
+public void select (int start, int end) {
+ checkWidget ();
+ if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return;
+ int count = getItemCount();
+ if (count == 0 || start >= count) return;
+ isAdjustingSelection = true;
+ start = Math.max (0, start);
+ end = Math.min (end, count - 1);
+ ((CList)handle).addSelectionInterval(start, end);
+ isAdjustingSelection = false;
+}
+
+/**
+ * Selects all of the items in the receiver.
+ *
+ * If the receiver is single-select, do nothing.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void selectAll () {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) return;
+ int count = getItemCount();
+ if(count == 0) return;
+ isAdjustingSelection = true;
+ ((CList)handle).setSelectionInterval(0, count - 1);
+ isAdjustingSelection = false;
+}
+
+/**
+ * Sets the text of the item in the receiver's list at the given
+ * zero-relative index to the string argument. This is equivalent
+ * to remove'ing the old item at the index, and then
+ * add'ing the new item at that index.
+ *
+ * @param index the index for the item
+ * @param string the new text for the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setItem (int index, String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ ((CList)handle).setElementAt(string, index);
+}
+
+/**
+ * Sets the receiver's items to be the given array of items.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the items array is null
+ *
ERROR_INVALID_ARGUMENT - if an item in the items array is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setItems (String [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ for (int i=0; i
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ *
+ * @param indices the indices of the items to select
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the array of indices is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see List#deselectAll()
+ * @see List#select(int[])
+ */
+public void setSelection(int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ deselectAll ();
+ int length = indices.length;
+ if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+ isAdjustingSelection = true;
+ for(int i=0; i
+ * Items that are not in the receiver are ignored.
+ * If the receiver is single-select and multiple items are specified,
+ * then all items are ignored.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the array of items is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see List#deselectAll()
+ * @see List#select(int[])
+ * @see List#setSelection(int[])
+ */
+public void setSelection (String [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ isAdjustingSelection = true;
+ deselectAll ();
+ int length = items.length;
+ if (length != 0 && ((style & SWT.SINGLE) == 0 || length <= 1)) {
+ ((CList)handle).setSelectedElements(items);
+ }
+ isAdjustingSelection = false;
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already selected, it remains selected.
+ * The current selection is first cleared, then the new item is selected.
+ * Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @see List#deselectAll()
+ * @see List#select(int)
+ */
+public void setSelection (int index) {
+ checkWidget ();
+ isAdjustingSelection = true;
+ ((CList)handle).setSelectionInterval(index, index);
+ isAdjustingSelection = false;
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is cleared before the new items are selected.
+ *
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ *
+ * @param start the start index of the items to select
+ * @param end the end index of the items to select
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see List#deselectAll()
+ * @see List#select(int,int)
+ */
+public void setSelection (int start, int end) {
+ checkWidget ();
+ deselectAll ();
+ if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return;
+ int count = getItemCount();
+ if (count == 0 || start >= count) return;
+ isAdjustingSelection = true;
+ start = Math.max (0, start);
+ end = Math.min (end, count - 1);
+ ((CList)handle).setSelectionInterval(start, end);
+ isAdjustingSelection = false;
+}
+
+/**
+ * Sets the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items
+ * are scrolled or new items are added and removed.
+ *
+ * @param index the index of the top item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setTopIndex (int index) {
+ checkWidget ();
+ ((CList)handle).setFirstVisibleIndex(index);
+}
+
+/**
+ * Shows the selection. If the selection is already showing in the receiver,
+ * this method simply returns. Otherwise, the items are scrolled until
+ * the selection is visible.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void showSelection () {
+ checkWidget ();
+ ((CList)handle).showSelection();
+}
+
+public void processEvent(EventObject e) {
+ if(e instanceof ListSelectionEvent) {
+ if(!hooks(SWT.Selection) || isAdjustingSelection) { super.processEvent(e); return; }
+ } else { super.processEvent(e); return; }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ if(e instanceof ListSelectionEvent) {
+ if(!((ListSelectionEvent)e).getValueIsAdjusting()) {
+ sendEvent(SWT.Selection);
+ }
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+public void processEvent(AWTEvent e) {
+ int id = e.getID();
+ switch(id) {
+ case ActionEvent.ACTION_PERFORMED: if(!hooks(SWT.Selection)) { super.processEvent(e); return; } break;
+ default: { super.processEvent(e); return; }
+ }
+ if(isDisposed()) {
+ super.processEvent(e);
+ return;
+ }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ switch(id) {
+ case ActionEvent.ACTION_PERFORMED:
+ sendEvent(SWT.DefaultSelection);
+ break;
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Menu.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Menu.java
new file mode 100644
index 00000000000..1764119a8ad
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Menu.java
@@ -0,0 +1,1179 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.Component;
+import java.awt.MouseInfo;
+import java.util.ArrayList;
+
+import javax.swing.JComponent;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JPopupMenu;
+import javax.swing.SwingUtilities;
+import javax.swing.event.PopupMenuEvent;
+import javax.swing.event.PopupMenuListener;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.HelpListener;
+import org.eclipse.swt.events.MenuListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.swing.Compatibility;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+
+/**
+ * Instances of this class are user interface objects that contain
+ * menu items.
+ *
+ *
Styles:
+ *
BAR, DROP_DOWN, POP_UP, NO_RADIO_GROUP
+ *
LEFT_TO_RIGHT, RIGHT_TO_LEFT
+ *
Events:
+ *
Help, Hide, Show
+ *
+ *
+ * Note: Only one of BAR, DROP_DOWN and POP_UP may be specified.
+ * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+
+public class Menu extends Widget {
+ /**
+ * the handle to the OS resource
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public JComponent handle;
+
+// int x, y, hwndCB, id0, id1;
+ int x, y;
+ boolean hasLocation;
+ MenuItem cascade;
+ Decorations parent;
+// ImageList imageList;
+
+// /* Resource ID for SHMENUBARINFO */
+// static final int ID_PPC = 100;
+//
+// /* SmartPhone SoftKeyBar resource ids */
+// static final int ID_SPMM = 102;
+// static final int ID_SPBM = 103;
+// static final int ID_SPMB = 104;
+// static final int ID_SPBB = 105;
+// static final int ID_SPSOFTKEY0 = 106;
+// static final int ID_SPSOFTKEY1 = 107;
+
+/**
+ * Constructs a new instance of this class given its parent,
+ * and sets the style for the instance so that the instance
+ * will be a popup menu on the given parent's shell.
+ *
+ * @param parent a control which will be the parent of the new instance (cannot be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#POP_UP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Menu (Control parent) {
+ this (checkNull (parent).menuShell (), SWT.POP_UP);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Decorations) and a style value
+ * describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a decorations control which will be the parent of the new instance (cannot be null)
+ * @param style the style of menu to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#BAR
+ * @see SWT#DROP_DOWN
+ * @see SWT#POP_UP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Menu (Decorations parent, int style) {
+ this (parent, checkStyle (style), null);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Menu) and sets the style
+ * for the instance so that the instance will be a drop-down
+ * menu on the given parent's parent.
+ *
+ * @param parentMenu a menu which will be the parent of the new instance (cannot be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Menu (Menu parentMenu) {
+ this (checkNull (parentMenu).parent, SWT.DROP_DOWN);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a MenuItem) and sets the style
+ * for the instance so that the instance will be a drop-down
+ * menu on the given parent's parent menu.
+ *
+ * @param parentItem a menu item which will be the parent of the new instance (cannot be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Menu (MenuItem parentItem) {
+ this (checkNull (parentItem).parent);
+}
+
+Menu (Decorations parent, int style, JMenuBar handle) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ this.handle = handle;
+ createWidget ();
+}
+
+//void _setVisible (boolean visible) {
+// if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
+// int hwndParent = parent.handle;
+// if (visible) {
+// int flags = OS.TPM_LEFTBUTTON;
+// if (OS.GetKeyState (OS.VK_LBUTTON) >= 0) flags |= OS.TPM_RIGHTBUTTON;
+// if ((style & SWT.RIGHT_TO_LEFT) != 0) flags |= OS.TPM_RIGHTALIGN;
+// if ((parent.style & SWT.MIRRORED) != 0) {
+// flags &= ~OS.TPM_RIGHTALIGN;
+// if ((style & SWT.LEFT_TO_RIGHT) != 0) flags |= OS.TPM_RIGHTALIGN;
+// }
+// int nX = x, nY = y;
+// if (!hasLocation) {
+// int pos = OS.GetMessagePos ();
+// nX = (short) (pos & 0xFFFF);
+// nY = (short) (pos >> 16);
+// }
+// /*
+// * Feature in Windows. It is legal use TrackPopupMenu()
+// * to display an empty menu as long as menu items are added
+// * inside of WM_INITPOPUPMENU. If no items are added, then
+// * TrackPopupMenu() fails and does not send an indication
+// * that the menu has been closed. This is not strictly a
+// * bug but leads to unwanted behavior when application code
+// * assumes that every WM_INITPOPUPMENU will eventually result
+// * in a WM_MENUSELECT, wParam=0xFFFF0000, lParam=0 to indicate
+// * that the menu has been closed. The fix is to detect the
+// * case when TrackPopupMenu() fails and the number of items in
+// * the menu is zero and issue a fake WM_MENUSELECT.
+// */
+// boolean success = OS.TrackPopupMenu (handle, flags, nX, nY, 0, hwndParent, null);
+// if (!success && GetMenuItemCount (handle) == 0) {
+// OS.SendMessage (hwndParent, OS.WM_MENUSELECT, 0xFFFF0000, 0);
+// }
+// } else {
+// OS.SendMessage (hwndParent, OS.WM_CANCELMODE, 0, 0);
+// }
+//}
+
+/**
+ * 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
+ * HelpListener interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see HelpListener
+ * @see #removeHelpListener
+ */
+public void addHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Help, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when menus are hidden or shown, by sending it
+ * one of the messages defined in the MenuListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see MenuListener
+ * @see #removeMenuListener
+ */
+public void addMenuListener (MenuListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Hide,typedListener);
+ addListener (SWT.Show,typedListener);
+}
+
+static Control checkNull (Control control) {
+ if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return control;
+}
+
+static Menu checkNull (Menu menu) {
+ if (menu == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return menu;
+}
+
+static MenuItem checkNull (MenuItem item) {
+ if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return item;
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.POP_UP, SWT.BAR, SWT.DROP_DOWN, 0, 0, 0);
+}
+
+void createHandle () {
+ if (handle != null) return;
+ if ((style & SWT.BAR) != 0) {
+ JMenuBar menuBar = new JMenuBar();
+ handle = menuBar;
+ } else if((style & SWT.POP_UP) != 0) {
+ JPopupMenu popup = new JPopupMenu();
+ // TODO: check if a component listener for visibility is needed
+ popup.addPopupMenuListener(new PopupMenuListener() {
+ public void popupMenuCanceled(PopupMenuEvent e) {
+ }
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+ if(!hooks(SWT.Hide)) return;
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ return;
+ }
+ try {
+ Event event = new Event();
+ event.widget = Menu.this;
+ sendEvent(SWT.Hide, event);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+ }
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+ if(!hooks(SWT.Show)) return;
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ return;
+ }
+ try {
+ Event event = new Event();
+ event.widget = Menu.this;
+ sendEvent(SWT.Show, event);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+ }
+ });
+ handle = popup;
+ } else if((style & SWT.DROP_DOWN) != 0) {
+ handle = new JMenu();
+ }
+}
+
+void createItem (MenuItem item, int index) {
+ int count = handle.getComponentCount();
+ if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+ display.addMenuItem (item);
+ handle.add(item.handle, index);
+// handle.invalidate();
+// handle.validate();
+// handle.repaint();
+
+// if (!success) {
+// display.removeMenuItem (item);
+// error (SWT.ERROR_ITEM_NOT_ADDED);
+// }
+// redraw ();
+}
+
+void createWidget () {
+ checkOrientation (parent);
+ createHandle ();
+ parent.addMenu (this);
+}
+
+///*
+//* Currently not used.
+//*/
+//int defaultBackground () {
+// return OS.GetSysColor (OS.COLOR_MENU);
+//}
+//
+///*
+//* Currently not used.
+//*/
+//int defaultForeground () {
+// return OS.GetSysColor (OS.COLOR_MENUTEXT);
+//}
+//
+//void destroyAccelerators () {
+// parent.destroyAccelerators ();
+//}
+
+void destroyItem (MenuItem item) {
+ java.awt.Component comp = item.handle.getParent();
+ handle.remove(item.handle);
+ if(comp instanceof JPopupMenu) {
+ ((JPopupMenu)comp).pack();
+ }
+// redraw ();
+}
+
+void destroyWidget () {
+// int hMenu = handle, hCB = hwndCB;
+ releaseHandle ();
+// if (OS.IsWinCE && hCB != 0) {
+// OS.CommandBar_Destroy (hCB);
+// } else {
+// if (hMenu != 0) OS.DestroyMenu (hMenu);
+// }
+}
+
+void fixMenus (Decorations newParent) {
+ MenuItem [] items = getItems ();
+ for (int i=0; i
+ * Note that the bounds of a menu or menu item are undefined when
+ * the menu is not visible. This is because most platforms compute
+ * the bounds of a menu dynamically just before it is displayed.
+ *
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+/*public*/ Rectangle getBounds () {
+ checkWidget ();
+ java.awt.Rectangle bounds = handle.getBounds();
+ return new Rectangle (bounds.x, bounds.y, bounds.width, bounds.height);
+// if (OS.IsWinCE) return new Rectangle (0, 0, 0, 0);
+// if ((style & SWT.BAR) != 0) {
+// if (parent.menuBar != this) {
+// return new Rectangle (0, 0, 0, 0);
+// }
+// int hwndShell = parent.handle;
+// MENUBARINFO info = new MENUBARINFO ();
+// info.cbSize = MENUBARINFO.sizeof;
+// if (OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, 0, info)) {
+// int width = info.right - info.left;
+// int height = info.bottom - info.top;
+// return new Rectangle (info.left, info.top, width, height);
+// }
+// } else {
+// int count = GetMenuItemCount (handle);
+// if (count != 0) {
+// RECT rect1 = new RECT ();
+// if (OS.GetMenuItemRect (0, handle, 0, rect1)) {
+// RECT rect2 = new RECT ();
+// if (OS.GetMenuItemRect (0, handle, count - 1, rect2)) {
+// int x = rect1.left - 2, y = rect1.top - 2;
+// int width = (rect2.right - rect2.left) + 4;
+// int height = (rect2.bottom - rect1.top) + 4;
+// return new Rectangle (x, y, width, height);
+// }
+// }
+// }
+// }
+// return new Rectangle (0, 0, 0, 0);
+}
+
+/**
+ * Returns the default menu item or null if none has
+ * been previously set.
+ *
+ * @return the default menu item.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public MenuItem getDefaultItem () {
+ checkWidget ();
+ // TODO: implement that?
+// if (OS.IsWinCE) return null;
+// int id = OS.GetMenuDefaultItem (handle, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED);
+// if (id == -1) return null;
+// MENUITEMINFO info = new MENUITEMINFO ();
+// info.cbSize = MENUITEMINFO.sizeof;
+// info.fMask = OS.MIIM_ID;
+// if (OS.GetMenuItemInfo (handle, id, false, info)) {
+// return display.getMenuItem (info.wID);
+// }
+ return null;
+}
+
+/**
+ * Returns true if the receiver is enabled, and
+ * false otherwise. A disabled menu is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #isEnabled
+ */
+public boolean getEnabled () {
+ checkWidget ();
+ return handle.isEnabled();
+// return (state & DISABLED) == 0;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public MenuItem getItem (int index) {
+ checkWidget ();
+ if(index < 0) error (SWT.ERROR_INVALID_RANGE);
+ int result = 0;
+ int count = handle.getComponentCount();
+ if(index > count) error (SWT.ERROR_INVALID_RANGE);
+ for(int i=0; i
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemCount () {
+ checkWidget ();
+ int count = handle.getComponentCount();
+ int result = 0;
+ for(int i=0; iMenuItems which
+ * are the items in the receiver.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public MenuItem [] getItems () {
+ checkWidget ();
+ int count = handle.getComponentCount();
+ java.util.List arrayList = new ArrayList(count);
+ for(int i=0; i 0) {
+ for (int i=0; iDecorations.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Decorations getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * MenuItem or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public MenuItem getParentItem () {
+ checkWidget ();
+ return cascade;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * Menu or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Menu getParentMenu () {
+ checkWidget ();
+ if (cascade != null) return cascade.parent;
+ return null;
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getParent
+ */
+public Shell getShell () {
+ checkWidget ();
+ return parent.getShell ();
+}
+
+/**
+ * Returns true if the receiver is visible, and
+ * false otherwise.
+ *
+ * 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.
+ *
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getVisible () {
+ checkWidget ();
+ if(!handle.isVisible()) {
+ return false;
+ }
+ if ((style & SWT.BAR) != 0) {
+ return this == parent.menuShell ().menuBar;
+ }
+ if ((style & SWT.POP_UP) != 0) {
+ Menu [] popups = display.popups;
+ if (popups == null) return false;
+ for (int i=0; i
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int indexOf (MenuItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ if (item.parent != this) return -1;
+ int componentCount = handle.getComponentCount();
+ for(int i=0; itrue if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and false
+ * otherwise. A disabled menu is typically not selectable from the
+ * user interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getEnabled
+ */
+public boolean isEnabled () {
+ checkWidget ();
+ Menu parentMenu = getParentMenu ();
+ if (parentMenu == null) return getEnabled ();
+ return getEnabled () && parentMenu.isEnabled ();
+}
+
+/**
+ * Returns true if the receiver is visible and all
+ * of the receiver's ancestors are visible and false
+ * otherwise.
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see HelpListener
+ * @see #addHelpListener
+ */
+public void removeHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Help, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the menu events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see MenuListener
+ * @see #addMenuListener
+ */
+public void removeMenuListener (MenuListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Hide, listener);
+ eventTable.unhook (SWT.Show, listener);
+}
+
+/**
+ * Sets the default menu item to the argument or removes
+ * the default emphasis when the argument is null.
+ *
+ * @param item the default menu item or null
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the menu item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setDefaultItem (MenuItem item) {
+ // TODO: implement that?
+// checkWidget ();
+// int newID = -1;
+// if (item != null) {
+// if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+// if (item.parent != this) return;
+// newID = item.id;
+// }
+// if (OS.IsWinCE) return;
+// int oldID = OS.GetMenuDefaultItem (handle, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED);
+// if (newID == oldID) return;
+// OS.SetMenuDefaultItem (handle, newID, OS.MF_BYCOMMAND);
+// redraw ();
+}
+
+/**
+ * Enables the receiver if the argument is true,
+ * and disables it otherwise. A disabled menu is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @param enabled the new enabled state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setEnabled (boolean enabled) {
+ checkWidget ();
+ handle.setEnabled(enabled);
+}
+
+/**
+ * Sets the location of the receiver, which must be a popup,
+ * to the point specified by the arguments which are relative
+ * to the display.
+ *
+ * Note that this is different from most widgets where the
+ * location of the widget is relative to the parent.
+ *
+ * Note that the platform window manager ultimately has control
+ * over the location of popup menus.
+ *
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setLocation (int x, int y) {
+ checkWidget ();
+ if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
+ this.x = x;
+ this.y = y;
+ hasLocation = true;
+}
+
+/**
+ * Sets the location of the receiver, which must be a popup,
+ * to the point specified by the argument which is relative
+ * to the display.
+ *
+ * Note that this is different from most widgets where the
+ * location of the widget is relative to the parent.
+ *
+ * Note that the platform window manager ultimately has control
+ * over the location of popup menus.
+ *
+ *
+ * @param location the new location for the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.1
+ */
+public void setLocation (Point location) {
+ checkWidget ();
+ if (location == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ setLocation (location.x, location.y);
+}
+
+/**
+ * Marks the receiver as visible if the argument is true,
+ * and marks it invisible otherwise.
+ *
+ * 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.
+ *
+ *
+ * @param visible the new visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setVisible (boolean visible) {
+ checkWidget ();
+ if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
+ JPopupMenu popup = (JPopupMenu)handle;
+ if (visible) {
+ display.addPopup (this);
+ java.awt.Point location;
+ if(hasLocation) {
+ location = new java.awt.Point(x, y);
+ } else {
+ if(Compatibility.IS_JAVA_5_OR_GREATER) {
+ location = MouseInfo.getPointerInfo().getLocation();
+ } else {
+ location = new java.awt.Point(0, 0);
+ }
+ }
+ Shell shell = getShell();
+ if(shell != null) {
+ Component shellHandle = shell.handle;
+ if(shellHandle.isShowing()) {
+ SwingUtilities.convertPointFromScreen(location, shellHandle);
+ popup.show(shellHandle, location.x, location.y);
+ return;
+ }
+ }
+ popup.show(null, location.x, location.y);
+ } else {
+ display.removePopup (this);
+ popup.setVisible(false);
+// _setVisible (false);
+ }
+}
+
+//void update () {
+// if (OS.IsPPC || OS.IsSP) return;
+// if (OS.IsHPC) {
+// /*
+// * Each time a menu has been modified, the command menu bar
+// * must be redrawn or it won't update properly. For example,
+// * a submenu will not drop down.
+// */
+// Menu menuBar = parent.menuBar;
+// if (menuBar != null) {
+// Menu menu = this;
+// while (menu != null && menu != menuBar) {
+// menu = menu.getParentMenu ();
+// }
+// if (menu == menuBar) {
+// OS.CommandBar_DrawMenuBar (menuBar.hwndCB, 0);
+// OS.CommandBar_Show (menuBar.hwndCB, true);
+// }
+// }
+// return;
+// }
+// if (OS.IsWinCE) return;
+// if ((style & SWT.BAR) != 0) {
+// if (this == parent.menuBar) OS.DrawMenuBar (parent.handle);
+// return;
+// }
+// if (OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+// return;
+// }
+// boolean hasCheck = false, hasImage = false;
+// MenuItem [] items = getItems ();
+// for (int i=0; i
+ *
Styles:
+ *
CHECK, CASCADE, PUSH, RADIO, SEPARATOR
+ *
Events:
+ *
Arm, Help, Selection
+ *
+ *
+ * Note: Only one of the styles CHECK, CASCADE, PUSH, RADIO and SEPARATOR
+ * may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+
+public class MenuItem extends Item {
+ Menu parent, menu;
+// int id, accelerator;
+ int accelerator;
+ JComponent handle;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Menu) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a menu control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#CHECK
+ * @see SWT#CASCADE
+ * @see SWT#PUSH
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public MenuItem (Menu parent, int style) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ createHandle();
+ parent.createItem (this, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Menu), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a menu control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#CHECK
+ * @see SWT#CASCADE
+ * @see SWT#PUSH
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public MenuItem (Menu parent, int style, int index) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ createHandle();
+ parent.createItem (this, index);
+}
+
+MenuItem (Menu parent, Menu menu, int style, int index) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ this.menu = menu;
+ if (menu != null) menu.cascade = this;
+ display.addMenuItem (this);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the arm events are generated for the control, by sending
+ * it one of the messages defined in the ArmListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ArmListener
+ * @see #removeArmListener
+ */
+public void addArmListener (ArmListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Arm, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the help events are generated for the control, by sending
+ * it one of the messages defined in the HelpListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see HelpListener
+ * @see #removeHelpListener
+ */
+public void addHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Help, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the menu item is selected, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * When widgetSelected is called, the stateMask field of the event object is valid.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener(listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.CASCADE, 0);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+//void fillAccel (ACCEL accel) {
+// accel.fVirt = 0;
+// accel.cmd = accel.key = 0;
+// if (accelerator == 0 || !getEnabled ()) return;
+// int fVirt = OS.FVIRTKEY;
+// int key = accelerator & SWT.KEY_MASK;
+// int vKey = Display.untranslateKey (key);
+// if (vKey != 0) {
+// key = vKey;
+// } else {
+// switch (key) {
+// /*
+// * Bug in Windows. For some reason, VkKeyScan
+// * fails to map ESC to VK_ESCAPE and DEL to
+// * VK_DELETE. The fix is to map these keys
+// * as a special case.
+// */
+// case 27: key = OS.VK_ESCAPE; break;
+// case 127: key = OS.VK_DELETE; break;
+// default: {
+// key = Display.wcsToMbcs ((char) key);
+// if (key == 0) return;
+// if (OS.IsWinCE) {
+// key = OS.CharUpper ((short) key);
+// } else {
+// vKey = OS.VkKeyScan ((short) key) & 0xFF;
+// if (vKey == -1) {
+// fVirt = 0;
+// } else {
+// key = vKey;
+// }
+// }
+// }
+// }
+// }
+// accel.key = (short) key;
+// accel.cmd = (short) id;
+// accel.fVirt = (byte) fVirt;
+// if ((accelerator & SWT.ALT) != 0) accel.fVirt |= OS.FALT;
+// if ((accelerator & SWT.SHIFT) != 0) accel.fVirt |= OS.FSHIFT;
+// if ((accelerator & SWT.CONTROL) != 0) accel.fVirt |= OS.FCONTROL;
+//}
+
+void fixMenus (Decorations newParent) {
+ if (menu != null) menu.fixMenus (newParent);
+}
+
+/**
+ * Returns the widget accelerator. An accelerator is the bit-wise
+ * OR of zero or more modifier masks and a key. Examples:
+ * SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2.
+ * The default value is zero, indicating that the menu item does
+ * not have an accelerator.
+ *
+ * @return the accelerator or 0
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getAccelerator () {
+ checkWidget ();
+ return accelerator;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent (or its display if its parent is null).
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+/*public*/ Rectangle getBounds () {
+ checkWidget ();
+ java.awt.Rectangle bounds = handle.getBounds();
+ return new Rectangle (bounds.x, bounds.y, bounds.width, bounds.height);
+// if (OS.IsWinCE) return new Rectangle (0, 0, 0, 0);
+// int index = parent.indexOf (this);
+// if (index == -1) return new Rectangle (0, 0, 0, 0);
+// if ((parent.style & SWT.BAR) != 0) {
+// Decorations shell = parent.parent;
+// if (shell.menuBar != parent) {
+// return new Rectangle (0, 0, 0, 0);
+// }
+// int hwndShell = shell.handle;
+// MENUBARINFO info1 = new MENUBARINFO ();
+// info1.cbSize = MENUBARINFO.sizeof;
+// if (!OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, 1, info1)) {
+// return new Rectangle (0, 0, 0, 0);
+// }
+// MENUBARINFO info2 = new MENUBARINFO ();
+// info2.cbSize = MENUBARINFO.sizeof;
+// if (!OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, index + 1, info2)) {
+// return new Rectangle (0, 0, 0, 0);
+// }
+// int x = info2.left - info1.left;
+// int y = info2.top - info1.top;
+// int width = info1.right - info1.left;
+// int height = info1.bottom - info1.top;
+// return new Rectangle (x, y, width, height);
+// } else {
+// int hMenu = parent.handle;
+// RECT rect1 = new RECT ();
+// if (!OS.GetMenuItemRect (0, hMenu, 0, rect1)) {
+// return new Rectangle (0, 0, 0, 0);
+// }
+// RECT rect2 = new RECT ();
+// if (!OS.GetMenuItemRect (0, hMenu, index, rect2)) {
+// return new Rectangle (0, 0, 0, 0);
+// }
+// int x = rect2.left - rect1.left + 2;
+// int y = rect2.top - rect1.top + 2;
+// int width = rect2.right - rect2.left;
+// int height = rect2.bottom - rect2.top;
+// return new Rectangle (x, y, width, height);
+// }
+}
+
+/**
+ * Returns true if the receiver is enabled, and
+ * false otherwise. A disabled menu item is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #isEnabled
+ */
+public boolean getEnabled () {
+ checkWidget ();
+ return handle.isEnabled();
+}
+
+/**
+ * Returns the receiver's cascade menu if it has one or null
+ * if it does not. Only CASCADE menu items can have
+ * a pull down menu. The sequence of key strokes, button presses
+ * and/or button releases that are used to request a pull down
+ * menu is platform specific.
+ *
+ * @return the receiver's menu
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Menu getMenu () {
+ checkWidget ();
+ return menu;
+}
+
+String getNameText () {
+ if ((style & SWT.SEPARATOR) != 0) return "|";
+ return super.getNameText ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a Menu.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Menu getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns true if the receiver is selected,
+ * and false otherwise.
+ *
+ * When the receiver is of type CHECK or RADIO,
+ * it is selected when it is checked.
+ *
+ * @return the selection state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getSelection () {
+ checkWidget ();
+ if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false;
+ return ((AbstractButton)handle).isSelected();
+}
+
+/**
+ * Returns true if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and false
+ * otherwise. A disabled menu item is typically not selectable from the
+ * user interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getEnabled
+ */
+public boolean isEnabled () {
+ return getEnabled () && parent.isEnabled ();
+}
+
+void releaseChildren (boolean destroy) {
+ if (menu != null) {
+ menu.release (false);
+ menu = null;
+ }
+ super.releaseChildren (destroy);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ parent = null;
+}
+
+void releaseMenu () {
+ setMenu (null);
+ menu = null;
+}
+
+void releaseParent () {
+ super.releaseParent ();
+ if (menu != null) menu.dispose ();
+ menu = null;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+// if (accelerator != 0) {
+// parent.destroyAccelerators ();
+// }
+ accelerator = 0;
+ display.removeMenuItem (this);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the arm events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ArmListener
+ * @see #addArmListener
+ */
+public void removeArmListener (ArmListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Arm, listener);
+}
+/**
+ * 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
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see HelpListener
+ * @see #addHelpListener
+ */
+public void removeHelpListener (HelpListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Help, listener);
+}
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+void selectRadio () {
+ int index = 0;
+ MenuItem [] items = parent.getItems ();
+ while (index < items.length && items [index] != this) index++;
+ int i = index - 1;
+ while (i >= 0 && items [i].setRadioSelection (false)) --i;
+ int j = index + 1;
+ while (j < items.length && items [j].setRadioSelection (false)) j++;
+ setSelection (true);
+}
+
+/**
+ * Sets the widget accelerator. An accelerator is the bit-wise
+ * OR of zero or more modifier masks and a key. Examples:
+ * SWT.MOD1 | SWT.MOD2 | 'T', SWT.MOD3 | SWT.F2.
+ * SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2.
+ * The default value is zero, indicating that the menu item does
+ * not have an accelerator.
+ *
+ * @param accelerator an integer that is the bit-wise OR of masks and a key
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setAccelerator (int accelerator) {
+ checkWidget ();
+ if (this.accelerator == accelerator) return;
+ this.accelerator = accelerator;
+ int key = accelerator & SWT.KEY_MASK;
+ int vKey = Display.untranslateKey(key);
+ if(vKey != 0) {
+ key = vKey;
+ }
+ if(handle instanceof JMenu) {
+ ((JMenu)handle).setMnemonic(key);
+ } else {
+ int modifiers = 0;
+ if((accelerator & SWT.ALT) != 0) {
+ modifiers |= java.awt.event.KeyEvent.ALT_DOWN_MASK;
+ }
+ if((accelerator & SWT.SHIFT) != 0) {
+ modifiers |= java.awt.event.KeyEvent.SHIFT_DOWN_MASK;
+ }
+ if((accelerator & SWT.CONTROL) != 0) {
+ modifiers |= java.awt.event.KeyEvent.CTRL_DOWN_MASK;
+ }
+ ((JMenuItem)handle).setAccelerator(KeyStroke.getKeyStroke(key, modifiers));
+ }
+// parent.destroyAccelerators ();
+}
+
+/**
+ * Enables the receiver if the argument is true,
+ * and disables it otherwise. A disabled menu item is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @param enabled the new enabled state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setEnabled (boolean enabled) {
+ checkWidget ();
+ handle.setEnabled(enabled);
+// parent.destroyAccelerators ();
+// parent.redraw ();
+}
+
+/**
+ * Sets the image the receiver will display to the argument.
+ *
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept (for example, Windows NT).
+ *
+ *
+ * @param image the image to display
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setImage (Image image) {
+ checkWidget ();
+ if ((style & SWT.SEPARATOR) != 0) return;
+ super.setImage (image);
+ ImageIcon icon = null;
+ if (image != null && image.handle != null) {
+ icon = new ImageIcon (image.handle);
+ }
+ ((AbstractButton) handle).setIcon (icon);
+// parent.redraw ();
+}
+
+/**
+ * Sets the receiver's pull down menu to the argument.
+ * Only CASCADE menu items can have a
+ * pull down menu. The sequence of key strokes, button presses
+ * and/or button releases that are used to request a pull down
+ * menu is platform specific.
+ *
+ * Note: Disposing of a menu item that has a pull down menu
+ * will dispose of the menu. To avoid this behavior, set the
+ * menu to null before the menu item is disposed.
+ *
+ *
+ * @param menu the new pull down menu
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_MENU_NOT_DROP_DOWN - if the menu is not a drop down menu
+ *
ERROR_MENUITEM_NOT_CASCADE - if the menu item is not a CASCADE
+ *
ERROR_INVALID_ARGUMENT - if the menu has been disposed
+ *
ERROR_INVALID_PARENT - if the menu is not in the same widget tree
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (boolean selected) {
+ checkWidget ();
+ if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return;
+ adjustSelection = true;
+ ((AbstractButton)handle).setSelected(selected);
+ adjustSelection = false;
+// parent.redraw ();
+}
+
+/**
+ * Sets the receiver's text. The string may include
+ * the mnemonic character and accelerator text.
+ *
+ * Mnemonics are indicated by an '&' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasised in a platform specific
+ * manner. The mnemonic indicator character '&' can be
+ * escaped by doubling it in the string, causing a single
+ * '&' to be displayed.
+ *
+ *
+ * Accelerator text is indicated by the '\t' character.
+ * On platforms that support accelerator text, the text
+ * that follows the '\t' character is displayed to the user,
+ * typically indicating the key stroke that will cause
+ * the item to become selected. On most platforms, the
+ * accelerator text appears right aligned in the menu.
+ * Setting the accelerator text does not install the
+ * accelerator key sequence. The accelerator key sequence
+ * is installed using #setAccelerator.
+ *
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setAccelerator
+ */
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if (text.equals (string)) return;
+ super.setText (string);
+ AbstractButton button = (AbstractButton)handle;
+ int index = findMnemonicIndex(string);
+ if(index != -1) {
+ button.setMnemonic(string.charAt(index));
+ string = string.substring(0, index - 1) + string.substring(index);
+ } else {
+ button.setMnemonic('\0');
+ }
+// string = fixMnemonic (string);
+ // TODO: check what to do for cascade (CHECK, CASCADE, PUSH, RADIO and SEPARATOR)
+ index = string.lastIndexOf('\t');
+ if(index != -1) {
+ string = string.substring(0, index);
+ }
+ button.setText(string);
+ java.awt.Component comp = button.getParent();
+ if(comp instanceof javax.swing.JPopupMenu) {
+ ((javax.swing.JPopupMenu)comp).pack();
+ }
+// parent.redraw ();
+}
+
+//int widgetStyle () {
+// int bits = 0;
+// Decorations shell = parent.parent;
+// if ((shell.style & SWT.MIRRORED) != 0) {
+// if ((parent.style & SWT.LEFT_TO_RIGHT) != 0) {
+// bits |= OS.MFT_RIGHTJUSTIFY | OS.MFT_RIGHTORDER;
+// }
+// } else {
+// if ((parent.style & SWT.RIGHT_TO_LEFT) != 0) {
+// bits |= OS.MFT_RIGHTJUSTIFY | OS.MFT_RIGHTORDER;
+// }
+// }
+// if ((style & SWT.SEPARATOR) != 0) return bits | OS.MFT_SEPARATOR;
+// if ((style & SWT.RADIO) != 0) return bits | OS.MFT_RADIOCHECK;
+// return bits | OS.MFT_STRING;
+//}
+//
+//LRESULT wmCommandChild (int wParam, int lParam) {
+// if ((style & SWT.CHECK) != 0) {
+// setSelection (!getSelection ());
+// } else {
+// if ((style & SWT.RADIO) != 0) {
+// if ((parent.getStyle () & SWT.NO_RADIO_GROUP) != 0) {
+// setSelection (!getSelection ());
+// } else {
+// selectRadio ();
+// }
+// }
+// }
+// Event event = new Event ();
+// setInputState (event, SWT.Selection);
+// postEvent (SWT.Selection, event);
+// return null;
+//}
+//
+//LRESULT wmDrawChild (int wParam, int lParam) {
+// DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
+// OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
+// if (image != null) {
+// GCData data = new GCData();
+// data.device = display;
+// GC gc = GC.win32_new (struct.hDC, data);
+// /*
+// * Bug in Windows. When a bitmap is included in the
+// * menu bar, the HDC seems to already include the left
+// * coordinate. The fix is to ignore this value when
+// * the item is in a menu bar.
+// */
+// int x = (parent.style & SWT.BAR) != 0 ? (OS.IsWin95 ? 4 : 2) : struct.left;
+// gc.drawImage (image, x, struct.top + 2);
+// gc.dispose ();
+// }
+// return null;
+//}
+//
+//LRESULT wmMeasureChild (int wParam, int lParam) {
+// MEASUREITEMSTRUCT struct = new MEASUREITEMSTRUCT ();
+// OS.MoveMemory (struct, lParam, MEASUREITEMSTRUCT.sizeof);
+// int width = 0, height = 0;
+// if (image != null) {
+// Rectangle rect = image.getBounds ();
+// width = rect.width;
+// height = rect.height;
+// } else {
+// /*
+// * Bug in Windows. If a menu contains items that have
+// * images and can be checked, Windows does not include
+// * the width of the image and the width of the check when
+// * computing the width of the menu. When the longest item
+// * does not have an image, the label and the accelerator
+// * text can overlap. The fix is to use SetMenuItemInfo()
+// * to indicate that all items have a bitmap and then include
+// * the width of the widest bitmap in WM_MEASURECHILD.
+// */
+// MENUINFO lpcmi = new MENUINFO ();
+// lpcmi.cbSize = MENUINFO.sizeof;
+// lpcmi.fMask = OS.MIM_STYLE;
+// int hMenu = parent.handle;
+// OS.GetMenuInfo (hMenu, lpcmi);
+// if ((lpcmi.dwStyle & OS.MNS_CHECKORBMP) == 0) {
+// MenuItem [] items = parent.getItems ();
+// for (int i=0; i
+ *
+ * Note: Only one of the styles ICON_ERROR, ICON_INFORMATION, ICON_QUESTION,
+ * ICON_WARNING and ICON_WORKING may be specified.
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+public class MessageBox extends Dialog {
+ String message = "";
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+public MessageBox (Shell parent) {
+ this (parent, SWT.OK | SWT.ICON_INFORMATION | SWT.APPLICATION_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+public MessageBox (Shell parent, int style) {
+ super (parent, checkStyle (style));
+ checkSubclass ();
+}
+
+static int checkStyle (int style) {
+ if ((style & (SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) == 0) style |= SWT.APPLICATION_MODAL;
+ int mask = (SWT.YES | SWT.NO | SWT.OK | SWT.CANCEL | SWT.ABORT | SWT.RETRY | SWT.IGNORE);
+ int bits = style & mask;
+ if (bits == SWT.OK || bits == SWT.CANCEL || bits == (SWT.OK | SWT.CANCEL)) return style;
+ if (bits == SWT.YES || bits == SWT.NO || bits == (SWT.YES | SWT.NO) || bits == (SWT.YES | SWT.NO | SWT.CANCEL)) return style;
+ if (bits == (SWT.RETRY | SWT.CANCEL) || bits == (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) return style;
+ style = (style & ~mask) | SWT.OK;
+ return style;
+}
+
+/**
+ * Returns the dialog's message, or an empty string if it does not have one.
+ * The message is a description of the purpose for which the dialog was opened.
+ * This message will be visible in the dialog while it is open.
+ *
+ * @return the message
+ */
+public String getMessage () {
+ return message;
+}
+
+static final int MAX_WIDTH = 120;
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return the ID of the button that was selected to dismiss the
+ * message box (e.g. SWT.OK, SWT.CANCEL, etc...)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the dialog has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog
+ *
+ */
+public void setMessage (String string) {
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ message = string;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ProgressBar.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ProgressBar.java
new file mode 100644
index 00000000000..62c517b47ee
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ProgressBar.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.Container;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.swing.CProgressBar;
+
+/**
+ * Instances of the receiver represent is an unselectable
+ * user interface object that is used to display progress,
+ * typically in the form of a bar.
+ *
+ *
Styles:
+ *
SMOOTH, HORIZONTAL, VERTICAL, INDETERMINATE
+ *
Events:
+ *
(none)
+ *
+ *
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+public class ProgressBar extends Control {
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#SMOOTH
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ProgressBar (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+static int checkStyle (int style) {
+ style |= SWT.NO_FOCUS;
+ return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+Container createHandle () {
+ return (Container)CProgressBar.Factory.newInstance(this, style);
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getMaximum () {
+ checkWidget ();
+ return ((CProgressBar)handle).getMaximum();
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getMinimum () {
+ checkWidget ();
+ return ((CProgressBar)handle).getMinimum();
+}
+
+/**
+ * Returns the single 'selection' that is the receiver's position.
+ *
+ * @return the selection
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelection () {
+ checkWidget ();
+ return ((CProgressBar)handle).getValue();
+}
+
+/**
+ * Sets the maximum value that the receiver will allow. This new
+ * value will be ignored if it is not greater than the receiver's current
+ * minimum value. If the new maximum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMaximum (int value) {
+ checkWidget ();
+ int minimum = getMinimum();
+ if (0 <= minimum && minimum < value) {
+ ((CProgressBar)handle).setMaximum(value);
+ }
+}
+
+/**
+ * Sets the minimum value that the receiver will allow. This new
+ * value will be ignored if it is negative or is not less than the receiver's
+ * current maximum value. If the new minimum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new minimum, which must be nonnegative and less than the current maximum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMinimum (int value) {
+ checkWidget ();
+ int maximum = getMaximum();
+ if (0 <= value && value < maximum) {
+ ((CProgressBar)handle).setMinimum(value);
+ }
+}
+
+/**
+ * Sets the single 'selection' that is the receiver's
+ * position to the argument which must be greater than or equal
+ * to zero.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (int value) {
+ checkWidget ();
+ ((CProgressBar)handle).setValue(value);
+ update();
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Sash.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Sash.java
new file mode 100644
index 00000000000..502d6b61e95
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Sash.java
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.AWTEvent;
+import java.awt.Container;
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.swing.CSash;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+
+/**
+ * Instances of the receiver represent a selectable user interface object
+ * that allows the user to drag a rubber banded outline of the sash within
+ * the parent control.
+ *
+ *
Styles:
+ *
HORIZONTAL, VERTICAL, SMOOTH
+ *
Events:
+ *
Selection
+ *
+ *
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+public class Sash extends Control {
+// final static int INCREMENT = 1;
+// final static int PAGE_INCREMENT = 9;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Sash (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * 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 SelectionListener
+ * interface.
+ *
+ * When widgetSelected is called, the x, y, width, and height fields of the event object are valid.
+ * If the receiver is being dragged, the event object detail field contains the value SWT.DRAG.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+void createHandleInit() {
+ super.createHandleInit();
+ state |= THEME_BACKGROUND;
+}
+
+Container createHandle () {
+ return (Container)CSash.Factory.newInstance(this, style);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ *
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+
+public class Scale extends Control {
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Scale (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's value changes, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * widgetSelected is called when the control's value changes.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+void createHandleInit() {
+ super.createHandleInit();
+ state |= THEME_BACKGROUND | DRAW_BACKGROUND;
+}
+
+Container createHandle () {
+ return (Container)CScale.Factory.newInstance(this, style);
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed.
+ *
+ * @return the increment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getIncrement () {
+ checkWidget ();
+ return ((CScale)handle).getMinorTickSpacing();
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getMaximum () {
+ checkWidget ();
+ return ((CScale)handle).getMaximum();
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getMinimum () {
+ checkWidget ();
+ return ((CScale)handle).getMinimum();
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected.
+ *
+ * @return the page increment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getPageIncrement () {
+ checkWidget ();
+ return ((CScale)handle).getMajorTickSpacing();
+}
+
+/**
+ * Returns the 'selection', which is the receiver's position.
+ *
+ * @return the selection
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelection () {
+ checkWidget ();
+ return ((CScale)handle).getValue();
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's value changes.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed to the argument, which must be at least
+ * one.
+ *
+ * @param increment the new increment (must be greater than zero)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setIncrement (int increment) {
+ checkWidget ();
+ if (increment < 1) return;
+ int minimum = getMinimum();
+ int maximum = getMaximum();
+ if (increment > maximum - minimum) return;
+ ((CScale)handle).setMinorTickSpacing(increment);
+}
+
+/**
+ * Sets the maximum value that the receiver will allow. This new
+ * value will be ignored if it is not greater than the receiver's current
+ * minimum value. If the new maximum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMaximum (int value) {
+ checkWidget ();
+ int minimum = getMinimum();
+ if (0 <= minimum && minimum < value) {
+ ((CScale)handle).setMaximum(value);
+ }
+}
+
+/**
+ * Sets the minimum value that the receiver will allow. This new
+ * value will be ignored if it is negative or is not less than the receiver's
+ * current maximum value. If the new minimum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new minimum, which must be nonnegative and less than the current maximum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMinimum (int value) {
+ checkWidget ();
+ int maximum = getMaximum();
+ if (0 <= value && value < maximum) {
+ ((CScale)handle).setMinimum(value);
+ }
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected to the argument, which must be at least
+ * one.
+ *
+ * @param pageIncrement the page increment (must be greater than zero)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setPageIncrement (int pageIncrement) {
+ checkWidget ();
+ if (pageIncrement < 1) return;
+ int minimum = getMinimum();
+ int maximum = getMaximum();
+ if (pageIncrement > maximum - minimum) return;
+ ((CScale)handle).setMajorTickSpacing(pageIncrement);
+}
+
+/**
+ * Sets the 'selection', which is the receiver's value,
+ * to the argument which must be greater than or equal to zero.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (int value) {
+ checkWidget ();
+ ((CScale)handle).setValue(value);
+}
+
+public void processEvent(EventObject e) {
+ if(e instanceof ChangeEvent) {
+ if(!hooks(SWT.Selection)) { super.processEvent(e); return; }
+ } else { super.processEvent(e); return; }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ if(e instanceof ChangeEvent) {
+// if(!((ChangeEvent)e).getValueIsAdjusting()) {
+ sendEvent(SWT.Selection);
+// }
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ScrollBar.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ScrollBar.java
new file mode 100644
index 00000000000..3ca8991dd66
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ScrollBar.java
@@ -0,0 +1,940 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.AdjustmentListener;
+
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.ScrollPaneConstants;
+
+import org.eclipse.swt.internal.swing.CScrollable;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that represent a range of positive, numeric values.
+ *
+ * At any given moment, a given scroll bar will have a
+ * single 'selection' that is considered to be its
+ * value, which is constrained to be within the range of
+ * values the scroll bar represents (that is, between its
+ * minimum and maximum values).
+ *
+ * Typically, scroll bars will be made up of five areas:
+ *
+ *
an arrow button for decrementing the value
+ *
a page decrement area for decrementing the value by a larger amount
+ *
a thumb for modifying the value by mouse dragging
+ *
a page increment area for incrementing the value by a larger amount
+ *
an arrow button for incrementing the value
+ *
+ * Based on their style, scroll bars are either HORIZONTAL
+ * (which have a left facing button for decrementing the value and a
+ * right facing button for incrementing it) or VERTICAL
+ * (which have an upward facing button for decrementing the value
+ * and a downward facing buttons for incrementing it).
+ *
+ * On some platforms, the size of the scroll bar's thumb can be
+ * varied relative to the magnitude of the range of values it
+ * represents (that is, relative to the difference between its
+ * maximum and minimum values). Typically, this is used to
+ * indicate some proportional value such as the ratio of the
+ * visible area of a document to the total amount of space that
+ * it would take to display it. SWT supports setting the thumb
+ * size even if the underlying platform does not, but in this
+ * case the appearance of the scroll bar will not change.
+ *
+ * Scroll bars are created by specifying either H_SCROLL,
+ * V_SCROLL or both when creating a Scrollable.
+ * They are accessed from the Scrollable using
+ * getHorizontalBar and getVerticalBar.
+ *
+ * Note: Scroll bars are not Controls. On some platforms, scroll bars
+ * that appear as part of some standard controls such as a text or list
+ * have no operating system resources and are not children of the control.
+ * For this reason, scroll bars are treated specially. To create a control
+ * that looks like a scroll bar but has operating system resources, use
+ * Slider.
+ *
+ *
+ *
Styles:
+ *
HORIZONTAL, VERTICAL
+ *
Events:
+ *
Selection
+ *
+ *
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @see Slider
+ * @see Scrollable
+ * @see Scrollable#getHorizontalBar
+ * @see Scrollable#getVerticalBar
+ */
+
+public class ScrollBar extends Widget {
+ Scrollable parent;
+ JScrollBar handle;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+ScrollBar (Scrollable parent, int style) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ createWidget ();
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's value changes, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * When widgetSelected is called, the event object detail field contains one of the following values:
+ * SWT.NONE - for the end of a drag.
+ * SWT.DRAG.
+ * SWT.HOME.
+ * SWT.END.
+ * SWT.ARROW_DOWN.
+ * SWT.ARROW_UP.
+ * SWT.PAGE_DOWN.
+ * SWT.PAGE_UP.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener(listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+void createWidget () {
+ handle = (style & SWT.HORIZONTAL) != 0? ((CScrollable)parent.handle).getHorizontalScrollBar(): ((CScrollable)parent.handle).getVerticalScrollBar();
+ /*
+ * Do not set the intial values of the maximum
+ * or the thumb. These values normally default
+ * to 100 and 10 but may have been set already
+ * by the widget that owns the scroll bar. For
+ * example, a scroll bar that is created for a
+ * list widget, setting these defaults would
+ * override the initial values provided by the
+ * list widget.
+ */
+ handle.addAdjustmentListener(new AdjustmentListener() {
+ public void adjustmentValueChanged(AdjustmentEvent e) {
+ if(blockListener || isDisposed()) return;
+ Event event = new Event ();
+ event.detail = SWT.DRAG;
+ switch(e.getAdjustmentType()) {
+ case AdjustmentEvent.BLOCK_DECREMENT:
+ event.detail = SWT.PAGE_DOWN;
+ break;
+ case AdjustmentEvent.BLOCK_INCREMENT:
+ event.detail = SWT.PAGE_UP;
+ break;
+ case AdjustmentEvent.UNIT_DECREMENT:
+ event.detail = SWT.ARROW_DOWN;
+ break;
+ case AdjustmentEvent.UNIT_INCREMENT:
+ event.detail = SWT.ARROW_UP;
+ break;
+ }
+ sendEvent (SWT.Selection, event);
+ }
+ });
+}
+
+void destroyWidget () {
+ if (isDisposed()) return;
+ if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+// int hwnd = hwndScrollBar (), type = scrollBarType ();
+// if (OS.IsWinCE) {
+// SCROLLINFO info = new SCROLLINFO ();
+// info.cbSize = SCROLLINFO.sizeof;
+// info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
+// info.nPage = 101;
+// info.nMax = 100;
+// info.nMin = 0;
+// OS.SetScrollInfo (hwnd, type, info, true);
+// } else {
+// OS.ShowScrollBar (hwnd, type, false);
+// }
+ releaseHandle ();
+}
+
+///*
+//* Not currently used.
+//*/
+//Rectangle getBounds () {
+//// checkWidget ();
+// parent.forceResize ();
+// RECT rect = new RECT ();
+// OS.GetClientRect (parent.scrolledHandle (), rect);
+// int x = 0, y = 0, width, height;
+// if ((style & SWT.HORIZONTAL) != 0) {
+// y = rect.bottom - rect.top;
+// width = rect.right - rect.left;
+// height = OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+// } else {
+// x = rect.right - rect.left;
+// width = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+// height = rect.bottom - rect.top;
+// }
+// return new Rectangle (x, y, width, height);
+//}
+
+/**
+ * Returns true if the receiver is enabled, and
+ * false 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #isEnabled
+ */
+public boolean getEnabled () {
+ checkWidget();
+ return handle.isEnabled();
+// return (state & DISABLED) == 0;
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed.
+ *
+ * @return the increment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getIncrement () {
+ checkWidget();
+ return handle.getUnitIncrement();
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getMaximum () {
+ checkWidget();
+ return handle.getMaximum();
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getMinimum () {
+ checkWidget();
+ return handle.getMinimum();
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected.
+ *
+ * @return the page increment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getPageIncrement () {
+ checkWidget();
+ return handle.getBlockIncrement();
+}
+
+/**
+ * Returns the receiver's parent, which must be a Scrollable.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Scrollable getParent () {
+ checkWidget();
+ return parent;
+}
+
+/**
+ * Returns the single 'selection' that is the receiver's value.
+ *
+ * @return the selection
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelection () {
+ checkWidget();
+ return handle.getValue();
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getSize () {
+ checkWidget();
+ java.awt.Dimension size;
+ if ((style & SWT.HORIZONTAL) != 0) {
+ size = ((CScrollable)parent.handle).getHorizontalScrollBar().getSize();
+ } else {
+ size = ((CScrollable)parent.handle).getVerticalScrollBar().getSize();
+ }
+ return new Point(size.width, size.height);
+// parent.forceResize ();
+// RECT rect = new RECT ();
+// OS.GetClientRect (parent.scrolledHandle (), rect);
+// int width, height;
+// if ((style & SWT.HORIZONTAL) != 0) {
+// width = rect.right - rect.left;
+// height = OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+// } else {
+// width = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+// height = rect.bottom - rect.top;
+// }
+// return new Point (width, height);
+}
+
+/**
+ * Returns the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values.
+ *
+ * @return the thumb value
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ScrollBar
+ */
+public int getThumb () {
+ checkWidget();
+ return handle.getVisibleAmount();
+}
+
+/**
+ * Returns true if the receiver is visible, and
+ * false otherwise.
+ *
+ * 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.
+ *
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getVisible () {
+ checkWidget();
+ return handle.isVisible();
+// return (state & HIDDEN) == 0;
+}
+
+//int hwndScrollBar () {
+// return parent.scrolledHandle ();
+//}
+
+/**
+ * Returns true if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and false
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getEnabled
+ */
+public boolean isEnabled () {
+ checkWidget();
+ return getEnabled () && parent.isEnabled ();
+}
+
+/**
+ * Returns true if the receiver is visible and all
+ * of the receiver's ancestors are visible and false
+ * otherwise.
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getVisible
+ */
+public boolean isVisible () {
+ checkWidget();
+ return getVisible () && parent.isVisible ();
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ parent = null;
+}
+
+void releaseParent () {
+ super.releaseParent ();
+ if (parent.horizontalBar == this) parent.horizontalBar = null;
+ if (parent.verticalBar == this) parent.verticalBar = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's value changes.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+//int scrollBarType () {
+// if ((style & SWT.VERTICAL) != 0) return OS.SB_VERT;
+// /*
+// * This line is intentionally commented. There should
+// * only ever be HORIZONTAL and VERTICAL scroll bars.
+// * The commented code reminds us that this is the case
+// * and that the default style is HORIZONTAL.
+// */
+//// if ((style & SWT.HORIZONTAL) != 0) return OS.SB_HORZ;
+// return OS.SB_HORZ;
+//}
+
+/**
+ * Enables the receiver if the argument is true,
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setEnabled (boolean enabled) {
+ checkWidget();
+ handle.setEnabled(enabled);
+// /*
+// * This line is intentionally commented. Currently
+// * always show scrollbar as being enabled and visible.
+// */
+//// if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED);
+// if (!OS.IsWinCE) {
+// int hwnd = hwndScrollBar (), type = scrollBarType ();
+// int flags = enabled ? OS.ESB_ENABLE_BOTH : OS.ESB_DISABLE_BOTH;
+// OS.EnableScrollBar (hwnd, type, flags);
+// if (enabled) {
+// state &= ~DISABLED;
+// } else {
+// state |= DISABLED;
+// }
+// }
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed to the argument, which must be at least
+ * one.
+ *
+ * @param value the new increment (must be greater than zero)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setIncrement (int value) {
+ checkWidget();
+ if (value < 1) return;
+ handle.setUnitIncrement(value);
+}
+
+/**
+ * Sets the maximum. If this value is negative or less than or
+ * equal to the minimum, the value is ignored. If necessary, first
+ * the thumb and then the selection are adjusted to fit within the
+ * new range.
+ *
+ * @param value the new maximum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMaximum (int value) {
+ checkWidget();
+ if (value < 0) return;
+ int minimum = handle.getMinimum();
+ if (value <= minimum) return;
+ blockListener = true;
+ handle.setMaximum(value);
+ blockListener = false;
+}
+
+/**
+ * Sets the minimum value. If this value is negative or greater
+ * than or equal to the maximum, the value is ignored. If necessary,
+ * first the thumb and then the selection are adjusted to fit within
+ * the new range.
+ *
+ * @param value the new minimum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMinimum (int value) {
+ checkWidget();
+ if (value < 0) return;
+ int maximum = handle.getMaximum();
+ if (value >= maximum) return;
+ blockListener = true;
+ handle.setMinimum(value);
+ blockListener = false;
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected to the argument, which must be at least
+ * one.
+ *
+ * @param value the page increment (must be greater than zero)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setPageIncrement (int value) {
+ checkWidget();
+ if (value < 1) return;
+ handle.setBlockIncrement(value);
+}
+
+//boolean SetScrollInfo (int hwnd, int flags, SCROLLINFO info, boolean fRedraw) {
+// /*
+// * Bug in Windows. For some reason, when SetScrollInfo()
+// * is used with SIF_POS and the scroll bar is hidden,
+// * the opposite scroll bar is incorrectly made visible
+// * so that the next time the parent is resized (or another
+// * scroll bar operation is performed), the opposite scroll
+// * bar draws. The fix is to hide both scroll bars.
+// */
+// if ((state & (DISABLED | HIDDEN)) != 0) fRedraw = false;
+// boolean result = OS.SetScrollInfo (hwnd, flags, info, fRedraw);
+//
+// /*
+// * Bug in Windows. For some reason, when the widget
+// * is a standard scroll bar, and SetScrollInfo() is
+// * called with SIF_RANGE or SIF_PAGE, the widget is
+// * incorrectly made visible so that the next time the
+// * parent is resized (or another scroll bar operation
+// * is performed), the scroll bar draws. The fix is
+// * to hide the scroll bar (again) when already hidden.
+// */
+// if ((state & HIDDEN) != 0) {
+// /*
+// * This line is intentionally commented. Currently
+// * always show scrollbar as being enabled and visible.
+// */
+//// if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED);
+// if (!OS.IsWinCE) {
+// ScrollBar bar = null;
+// switch (flags) {
+// case OS.SB_HORZ:
+// bar = parent.getVerticalBar ();
+// break;
+// case OS.SB_VERT:
+// bar = parent.getHorizontalBar ();
+// break;
+// }
+// boolean both = bar != null && !bar.getVisible ();
+// OS.ShowScrollBar (hwnd, both ? OS.SB_BOTH : flags, false);
+// }
+// }
+//
+// /*
+// * Feature in Windows. Using SIF_DISABLENOSCROLL,
+// * SetScrollInfo () can change enabled and disabled
+// * state of the scroll bar causing a scroll bar that
+// * was disabled by the application to become enabled.
+// * The fix is to disable the scroll bar (again) when
+// * the application has disabled the scroll bar.
+// */
+// if ((state & DISABLED) != 0) {
+// /*
+// * This line is intentionally commented. Currently
+// * always show scrollbar as being enabled and visible.
+// */
+//// if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED);
+// if (!OS.IsWinCE) {
+// OS.EnableScrollBar (hwnd, flags, OS.ESB_DISABLE_BOTH);
+// }
+// }
+// return result;
+//}
+
+/**
+ * Sets the single selection that is the receiver's
+ * value to the argument which must be greater than or equal
+ * to zero.
+ *
+ * @param selection the new selection (must be zero or greater)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (int selection) {
+ checkWidget();
+ blockListener = true;
+ handle.setValue(selection);
+ blockListener = false;
+}
+
+boolean blockListener;
+
+/**
+ * Sets the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values. This new
+ * value will be ignored if it is less than one, and will be
+ * clamped if it exceeds the receiver's current range.
+ *
+ * @param value the new thumb value, which must be at least one and not
+ * larger than the size of the current range
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setThumb (int value) {
+ checkWidget();
+ if (value < 1) return;
+ int minimum = handle.getMinimum();
+ int maximum = handle.getMaximum();
+ int range = maximum - minimum;
+ if (value > range) {
+ value = range;
+ }
+ int maxSelection = maximum - value;
+ int selection = handle.getValue();
+ if (selection > maxSelection) {
+ selection = maxSelection;
+ }
+ blockListener = true;
+ handle.setValues(selection, value, minimum, maximum);
+ blockListener = false;
+}
+
+/**
+ * Sets the receiver's selection, minimum value, maximum
+ * value, thumb, increment and page increment all at once.
+ *
+ * Note: This is similar to setting the values individually
+ * using the appropriate methods, but may be implemented in a
+ * more efficient fashion on some platforms.
+ *
+ *
+ * @param selection the new selection value
+ * @param minimum the new minimum value
+ * @param maximum the new maximum value
+ * @param thumb the new thumb value
+ * @param increment the new increment value
+ * @param pageIncrement the new pageIncrement value
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) {
+ checkWidget();
+ if (minimum < 0) return;
+ if (maximum < 0) return;
+ if (thumb < 1) return;
+ if (increment < 1) return;
+ if (pageIncrement < 1) return;
+ blockListener = true;
+ handle.setValues(selection, thumb, minimum, maximum);
+ blockListener = false;
+}
+
+/**
+ * Marks the receiver as visible if the argument is true,
+ * and marks it invisible otherwise.
+ *
+ * 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.
+ *
+ *
+ * @param visible the new visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setVisible (boolean visible) {
+ checkWidget();
+// boolean isVisible = (state & HIDDEN) == 0;
+// if (isVisible == visible) return;
+ if(handle.getParent() instanceof JScrollPane) {
+ JScrollPane scrollPane = ((JScrollPane)handle.getParent());
+ if((style & SWT.HORIZONTAL) != 0) {
+ if(visible) {
+ scrollPane.setHorizontalScrollBarPolicy((parent.getStyle() & SWT.H_SCROLL) != 0? ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS: ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ } else {
+ scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
+ }
+ } else {
+ if(visible) {
+ scrollPane.setVerticalScrollBarPolicy((parent.getStyle() & SWT.V_SCROLL) != 0? ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS: ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
+ } else {
+ scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
+ }
+ }
+ } else {
+ handle.setVisible(visible);
+ }
+// /*
+// * On Windows CE, use SIF_DISABLENOSCROLL to show and
+// * hide the scroll bar when the page size is equal to
+// * the range.
+// */
+// if (OS.IsWinCE) {
+// SCROLLINFO info = new SCROLLINFO ();
+// info.cbSize = SCROLLINFO.sizeof;
+// int hwnd = hwndScrollBar (), type = scrollBarType ();
+// info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
+// if (visible) info.fMask |= OS.SIF_DISABLENOSCROLL;
+// OS.GetScrollInfo (hwnd, type, info);
+// if (info.nPage == info.nMax - info.nMin + 1) {
+// /*
+// * Bug in Windows. When the only changed flag to
+// * SetScrollInfo () is OS.SIF_DISABLENOSCROLL,
+// * Windows does not update the scroll bar state.
+// * The fix is to increase and then decrease the
+// * maximum, causing Windows to honour the flag.
+// */
+// int max = info.nMax;
+// info.nMax++;
+// OS.SetScrollInfo (hwnd, type, info, false);
+// info.nMax = max;
+// OS.SetScrollInfo (hwnd, type, info, true);
+// } else {
+// /*
+// * This line is intentionally commented. Currently
+// * always show scrollbar as being enabled and visible.
+// */
+//// if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED);
+// }
+// return;
+// }
+//
+// /*
+// * Set the state bits before calling ShowScrollBar ()
+// * because hiding and showing the scroll bar can cause
+// * WM_SIZE messages when the client area is resized.
+// * Setting the state before the call means that code
+// * that runs during WM_SIZE that queries the visibility
+// * of the scroll bar will get the correct value.
+// */
+// state = visible ? state & ~HIDDEN : state | HIDDEN;
+// int hwnd = hwndScrollBar (), type = scrollBarType ();
+// if (OS.ShowScrollBar (hwnd, type, visible)) {
+// /*
+// * Bug in Windows. For some reason, when the widget
+// * is a standard scroll bar, and SetScrollInfo () is
+// * called with SIF_RANGE or SIF_PAGE while the widget
+// * is not visible, the widget is incorrectly disabled
+// * even though the values for SIF_RANGE and SIF_PAGE,
+// * when set for a visible scroll bar would not disable
+// * the scroll bar. The fix is to enable the scroll bar
+// * when not disabled by the application and the current
+// * scroll bar ranges would cause the scroll bar to be
+// * enabled had they been set when the scroll bar was
+// * visible.
+// */
+// if ((state & DISABLED) == 0) {
+// SCROLLINFO info = new SCROLLINFO ();
+// info.cbSize = SCROLLINFO.sizeof;
+// info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
+// OS.GetScrollInfo (hwnd, type, info);
+// if (info.nMax - info.nMin - info.nPage >= 0) {
+// OS.EnableScrollBar (hwnd, type, OS.ESB_ENABLE_BOTH);
+// }
+// }
+// sendEvent (visible ? SWT.Show : SWT.Hide);
+// // widget could be disposed at this point
+// }
+}
+
+//LRESULT wmScrollChild (int wParam, int lParam) {
+//
+// /* Do nothing when scrolling is ending */
+// int code = wParam & 0xFFFF;
+// switch (code) {
+// case OS.SB_THUMBPOSITION:
+// case OS.SB_ENDSCROLL:
+// return null;
+// }
+//
+// /*
+// * Send the event because WM_HSCROLL and
+// * WM_VSCROLL are sent from a modal message
+// * loop in Windows that is active when the
+// * user is scrolling.
+// */
+// Event event = new Event ();
+// switch (code) {
+// case OS.SB_THUMBTRACK: event.detail = SWT.DRAG; break;
+// case OS.SB_TOP: event.detail = SWT.HOME; break;
+// case OS.SB_BOTTOM: event.detail = SWT.END; break;
+// case OS.SB_LINEDOWN: event.detail = SWT.ARROW_DOWN; break;
+// case OS.SB_LINEUP: event.detail = SWT.ARROW_UP; break;
+// case OS.SB_PAGEDOWN: event.detail = SWT.PAGE_DOWN; break;
+// case OS.SB_PAGEUP: event.detail = SWT.PAGE_UP; break;
+// }
+// sendEvent (SWT.Selection, event);
+// // the widget could be destroyed at this point
+// return null;
+//}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Scrollable.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Scrollable.java
new file mode 100644
index 00000000000..7c54ec1a869
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Scrollable.java
@@ -0,0 +1,422 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.Container;
+import java.awt.Insets;
+import java.awt.Window;
+
+import javax.swing.SwingUtilities;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.swing.CControl;
+
+/**
+ * This class is the abstract superclass of all classes which
+ * represent controls that have standard scroll bars.
+ *
+ *
Styles:
+ *
H_SCROLL, V_SCROLL
+ *
Events:
+ *
(none)
+ *
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ */
+
+public abstract class Scrollable extends Control {
+ ScrollBar horizontalBar, verticalBar;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Scrollable () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#H_SCROLL
+ * @see SWT#V_SCROLL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Scrollable (Composite parent, int style) {
+ super (parent, style);
+}
+
+//int callWindowProc (int hwnd, int msg, int wParam, int lParam) {
+// if (handle == 0) return 0;
+// return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+//}
+
+/**
+ * Given a desired client area for the receiver
+ * (as described by the arguments), returns the bounding
+ * rectangle which would be required to produce that client
+ * area.
+ *
+ * In other words, it returns a rectangle such that, if the
+ * receiver's bounds were set to that rectangle, the area
+ * of the receiver which is capable of displaying data
+ * (that is, not covered by the "trimmings") would be the
+ * rectangle described by the arguments (relative to the
+ * receiver's parent).
+ *
+ *
+ * @param x the desired x coordinate of the client area
+ * @param y the desired y coordinate of the client area
+ * @param width the desired width of the client area
+ * @param height the desired height of the client area
+ * @return the required bounds to produce the given client area
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getClientArea
+ */
+public Rectangle computeTrim (int x, int y, int width, int height) {
+ checkWidget ();
+ java.awt.Dimension hSize = handle.getPreferredSize();
+ java.awt.Container clientArea = ((CControl)handle).getClientArea();
+ java.awt.Dimension cSize = clientArea.getPreferredSize();
+ java.awt.Point location = new java.awt.Point(0, 0);
+ SwingUtilities.convertPoint(clientArea, location, handle);
+ int top = location.y;
+ int left = location.x;
+ int bottom = hSize.height - cSize.height - top;
+ int right = hSize.width - cSize.width - left;
+ return new Rectangle(x - left, y - top, left + width + right, top + height + bottom);
+}
+
+ScrollBar createScrollBar (int type) {
+ ScrollBar bar = new ScrollBar (this, type);
+// if ((state & CANVAS) != 0) {
+// bar.setMaximum (100);
+// bar.setThumb (10);
+// }
+ return bar;
+}
+
+void createWidget () {
+ super.createWidget ();
+ if ((style & SWT.H_SCROLL) != 0) horizontalBar = createScrollBar (SWT.H_SCROLL);
+ if ((style & SWT.V_SCROLL) != 0) verticalBar = createScrollBar (SWT.V_SCROLL);
+}
+
+/**
+ * Returns a rectangle which describes the area of the
+ * receiver which is capable of displaying data (that is,
+ * not covered by the "trimmings").
+ *
+ * @return the client area
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #computeTrim
+ */
+public Rectangle getClientArea () {
+ checkWidget ();
+ Container clientArea = ((CControl)handle).getClientArea();
+ java.awt.Rectangle bounds = clientArea.getBounds();
+ if(handle instanceof Window) {
+ return new Rectangle(0, 0, bounds.width, bounds.height);
+ }
+ Container parent = clientArea.getParent();
+ bounds = SwingUtilities.convertRectangle(parent, bounds, handle);
+ Container handleParent = handle.getParent();
+ while(parent != handleParent) {
+ Insets insets = parent.getInsets();
+ bounds.x -= insets.left;
+ bounds.y -= insets.top;
+ parent = parent.getParent();
+ }
+ Point internalOffset = getInternalOffset();
+ return new Rectangle(bounds.x - internalOffset.x, bounds.y - internalOffset.y, bounds.width + internalOffset.x, bounds.height + internalOffset.y);
+// forceResize ();
+// RECT rect = new RECT ();
+// int scrolledHandle = scrolledHandle ();
+// OS.GetClientRect (scrolledHandle, rect);
+// return new Rectangle (0, 0, rect.right, rect.bottom);
+}
+
+/**
+ * Returns the receiver's horizontal scroll bar if it has
+ * one, and null if it does not.
+ *
+ * @return the horizontal scroll bar (or null)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public ScrollBar getHorizontalBar () {
+ checkWidget ();
+ return horizontalBar;
+}
+
+/**
+ * Returns the receiver's vertical scroll bar if it has
+ * one, and null if it does not.
+ *
+ * @return the vertical scroll bar (or null)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public ScrollBar getVerticalBar () {
+ checkWidget ();
+ return verticalBar;
+}
+
+void releaseChildren (boolean destroy) {
+ if (horizontalBar != null) {
+ horizontalBar.release (false);
+ horizontalBar = null;
+ }
+ if (verticalBar != null) {
+ verticalBar.release (false);
+ verticalBar = null;
+ }
+ super.releaseChildren (destroy);
+}
+
+//int scrolledHandle () {
+// return handle;
+//}
+//
+//int widgetExtStyle () {
+// return super.widgetExtStyle ();
+// /*
+// * This code is intentionally commented. In future,
+// * we may wish to support different standard Windows
+// * edge styles. The issue here is that not all of
+// * these styles are available on the other platforms
+// * this would need to be a hint.
+// */
+//// if ((style & SWT.BORDER) != 0) return OS.WS_EX_CLIENTEDGE;
+//// if ((style & SWT.SHADOW_IN) != 0) return OS.WS_EX_STATICEDGE;
+//// return super.widgetExtStyle ();
+//}
+//
+//int widgetStyle () {
+// int bits = super.widgetStyle () | OS.WS_TABSTOP;
+// if ((style & SWT.H_SCROLL) != 0) bits |= OS.WS_HSCROLL;
+// if ((style & SWT.V_SCROLL) != 0) bits |= OS.WS_VSCROLL;
+// return bits;
+//}
+//
+//TCHAR windowClass () {
+// return display.windowClass;
+//}
+//
+//int windowProc () {
+// return display.windowProc;
+//}
+//
+//LRESULT WM_HSCROLL (int wParam, int lParam) {
+// LRESULT result = super.WM_HSCROLL (wParam, lParam);
+// if (result != null) return result;
+//
+// /*
+// * Bug on WinCE. lParam should be NULL when the message is not sent
+// * by a scroll bar control, but it contains the handle to the window.
+// * When the message is sent by a scroll bar control, it correctly
+// * contains the handle to the scroll bar. The fix is to check for
+// * both.
+// */
+// if (horizontalBar != null && (lParam == 0 || lParam == handle)) {
+// return wmScroll (horizontalBar, (state & CANVAS) != 0, handle, OS.WM_HSCROLL, wParam, lParam);
+// }
+// return result;
+//}
+//
+//LRESULT WM_MOUSEWHEEL (int wParam, int lParam) {
+// LRESULT result = super.WM_MOUSEWHEEL (wParam, lParam);
+// if (result != null) return result;
+//
+// /*
+// * Translate WM_MOUSEWHEEL to WM_VSCROLL or WM_HSCROLL.
+// */
+// if ((state & CANVAS) != 0) {
+// if ((wParam & (OS.MK_SHIFT | OS.MK_CONTROL)) != 0) return result;
+// boolean vertical = verticalBar != null && verticalBar.getEnabled ();
+// boolean horizontal = horizontalBar != null && horizontalBar.getEnabled ();
+// int msg = (vertical) ? OS.WM_VSCROLL : (horizontal) ? OS.WM_HSCROLL : 0;
+// if (msg == 0) return result;
+// int [] value = new int [1];
+// OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, value, 0);
+// int delta = (short) (wParam >> 16);
+// int code = 0, count = 0;
+// if (value [0] == OS.WHEEL_PAGESCROLL) {
+// code = delta < 0 ? OS.SB_PAGEDOWN : OS.SB_PAGEUP;
+// count = Math.abs (delta / OS.WHEEL_DELTA);
+// } else {
+// code = delta < 0 ? OS.SB_LINEDOWN : OS.SB_LINEUP;
+// delta = Math.abs (delta);
+// if (delta < OS.WHEEL_DELTA) return result;
+// if (msg == OS.WM_VSCROLL) {
+// count = value [0] * delta / OS.WHEEL_DELTA;
+// } else {
+// count = delta / OS.WHEEL_DELTA;
+// }
+// }
+// for (int i=0; iDisplay as the argument) are described
+ * as top level shells. Instances that do have
+ * a parent are described as secondary or
+ * dialog shells.
+ *
+ * Instances are always displayed in one of the maximized,
+ * minimized or normal states:
+ *
+ *
+ * When an instance is marked as maximized, the
+ * window manager will typically resize it to fill the
+ * entire visible area of the display, and the instance
+ * is usually put in a state where it can not be resized
+ * (even if it has style RESIZE) until it is
+ * no longer maximized.
+ *
+ * When an instance is in the normal state (neither
+ * maximized or minimized), its appearance is controlled by
+ * the style constants which were specified when it was created
+ * and the restrictions of the window manager (see below).
+ *
+ * When an instance has been marked as minimized,
+ * its contents (client area) will usually not be visible,
+ * and depending on the window manager, it may be
+ * "iconified" (that is, replaced on the desktop by a small
+ * simplified representation of itself), relocated to a
+ * distinguished area of the screen, or hidden. Combinations
+ * of these changes are also possible.
+ *
+ *
+ *
+ * The modality of an instance may be specified using
+ * style bits. The modality style bits are used to determine
+ * whether input is blocked for other shells on the display.
+ * The PRIMARY_MODAL style allows an instance to block
+ * input to its parent. The APPLICATION_MODAL style
+ * allows an instance to block input to every other shell in the
+ * display. The SYSTEM_MODAL style allows an instance
+ * to block input to all shells, including shells belonging to
+ * different applications.
+ *
+ * Note: The styles supported by this class are treated
+ * as HINTs, since the window manager for the
+ * desktop on which the instance is visible has ultimate
+ * control over the appearance and behavior of decorations
+ * and modality. For example, some window managers only
+ * support resizable windows and will always assume the
+ * RESIZE style, even if it is not set. In addition, if a
+ * modality style is not supported, it is "upgraded" to a
+ * more restrictive modality style that is supported. For
+ * example, if PRIMARY_MODAL is not supported,
+ * it would be upgraded to APPLICATION_MODAL.
+ * A modality style may also be "downgraded" to a less
+ * restrictive style. For example, most operating systems
+ * no longer support SYSTEM_MODAL because
+ * it can freeze up the desktop, so this is typically
+ * downgraded to APPLICATION_MODAL.
+ *
+ * Class SWT provides two "convenience constants"
+ * for the most commonly required style combinations:
+ *
+ *
SHELL_TRIM
+ *
+ * the result of combining the constants which are required
+ * to produce a typical application top level shell: (that
+ * is, CLOSE | TITLE | MIN | MAX | RESIZE)
+ *
+ *
DIALOG_TRIM
+ *
+ * the result of combining the constants which are required
+ * to produce a typical application dialog shell: (that
+ * is, TITLE | CLOSE | BORDER)
+ *
+ *
+ *
+ *
+ * Note: Only one of the styles APPLICATION_MODAL, MODELESS,
+ * PRIMARY_MODAL and SYSTEM_MODAL may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @see Decorations
+ * @see SWT
+ */
+public class Shell extends Decorations {
+ Menu activeMenu;
+// int hIMC, hwndMDIClient, toolTipHandle, lpstrTip;
+ int minWidth = SWT.DEFAULT, minHeight = SWT.DEFAULT;
+// int [] brushes;
+// boolean showWithParent;
+ Control lastActive;
+// SHACTIVATEINFO psai;
+ Region region;
+// static final int DialogProc;
+// static final TCHAR DialogClass = new TCHAR (0, OS.IsWinCE ? "Dialog" : "#32770", true);
+// static {
+// WNDCLASS lpWndClass = new WNDCLASS ();
+// OS.GetClassInfo (0, DialogClass, lpWndClass);
+// DialogProc = lpWndClass.lpfnWndProc;
+// }
+
+/**
+ * Constructs a new instance of this class. This is equivalent
+ * to calling Shell((Display) null).
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+public Shell () {
+ this ((Display) null);
+}
+
+/**
+ * Constructs a new instance of this class given only the style
+ * value describing its behavior and appearance. This is equivalent
+ * to calling Shell((Display) null, style).
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param style the style of control to construct
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#BORDER
+ * @see SWT#CLOSE
+ * @see SWT#MIN
+ * @see SWT#MAX
+ * @see SWT#RESIZE
+ * @see SWT#TITLE
+ * @see SWT#NO_TRIM
+ * @see SWT#SHELL_TRIM
+ * @see SWT#DIALOG_TRIM
+ * @see SWT#MODELESS
+ * @see SWT#PRIMARY_MODAL
+ * @see SWT#APPLICATION_MODAL
+ * @see SWT#SYSTEM_MODAL
+ */
+public Shell (int style) {
+ this ((Display) null, style);
+}
+
+/**
+ * Constructs a new instance of this class given only the display
+ * to create it on. It is created with style SWT.SHELL_TRIM.
+ *
+ * Note: Currently, null can be passed in for the display argument.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. Passing in null as
+ * the display argument is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.
+ *
+ *
+ * @param display the display to create the shell on
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+public Shell (Display display) {
+ this (display, SWT.SHELL_TRIM);
+}
+
+/**
+ * Constructs a new instance of this class given the display
+ * to create it on and a style value describing its behavior
+ * and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ * Note: Currently, null can be passed in for the display argument.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. Passing in null as
+ * the display argument is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.
+ *
+ *
+ * @param display the display to create the shell on
+ * @param style the style of control to construct
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#BORDER
+ * @see SWT#CLOSE
+ * @see SWT#MIN
+ * @see SWT#MAX
+ * @see SWT#RESIZE
+ * @see SWT#TITLE
+ * @see SWT#NO_TRIM
+ * @see SWT#SHELL_TRIM
+ * @see SWT#DIALOG_TRIM
+ * @see SWT#MODELESS
+ * @see SWT#PRIMARY_MODAL
+ * @see SWT#APPLICATION_MODAL
+ * @see SWT#SYSTEM_MODAL
+ */
+public Shell (Display display, int style) {
+ this (display, null, style, null);
+}
+
+Shell (Display display, Shell parent, int style, Container handle) {
+ super ();
+ checkSubclass ();
+ if (display == null) display = Display.getCurrent ();
+ if (display == null) display = Display.getDefault ();
+ if (!display.isValidThread ()) {
+ error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ }
+ if (parent != null && parent.isDisposed ()) {
+ error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.style = checkStyle (style);
+ this.parent = parent;
+ this.display = display;
+ this.handle = handle;
+ createWidget ();
+}
+
+/**
+ * Constructs a new instance of this class given only its
+ * parent. It is created with style SWT.DIALOG_TRIM.
+ *
+ * Note: Currently, null can be passed in for the parent.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. Passing in null as
+ * the parent is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.
+ *
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the parent is disposed
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+public Shell (Shell parent) {
+ this (parent, SWT.DIALOG_TRIM);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ * Note: Currently, null can be passed in for the parent.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. Passing in null as
+ * the parent is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.
+ *
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the parent is disposed
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ * IMPORTANT: This method is not part of the public
+ * API for Shell. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ *
+ *
+ * @param display the display for the shell
+ * @param handle the handle for the shell
+ * @return a new shell object containing the specified display and handle
+ */
+public static Shell swing_new (Display display, Container handle) {
+ return new Shell (display, null, SWT.NO_TRIM, handle);
+}
+
+static int checkStyle (int style) {
+ style = Decorations.checkStyle (style);
+ int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL;
+ int bits = style & ~mask;
+ if ((style & SWT.SYSTEM_MODAL) != 0) return bits | SWT.SYSTEM_MODAL;
+ if ((style & SWT.APPLICATION_MODAL) != 0) return bits | SWT.APPLICATION_MODAL;
+ if ((style & SWT.PRIMARY_MODAL) != 0) return bits | SWT.PRIMARY_MODAL;
+ return bits;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when operations are performed on the receiver,
+ * by sending the listener one of the messages defined in the
+ * ShellListener interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ShellListener
+ * @see #removeShellListener
+ */
+public void addShellListener (ShellListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Close,typedListener);
+ addListener (SWT.Iconify,typedListener);
+ addListener (SWT.Deiconify,typedListener);
+ addListener (SWT.Activate, typedListener);
+ addListener (SWT.Deactivate, typedListener);
+}
+
+//int callWindowProc (int hwnd, int msg, int wParam, int lParam) {
+// if ((style & SWT.TOOL) != 0) {
+// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
+// if ((style & trim) == 0) return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+// }
+// if (parent != null) {
+// if (handle == 0) return 0;
+// switch (msg) {
+// case OS.WM_KILLFOCUS:
+// case OS.WM_SETFOCUS:
+// return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+// }
+// return OS.CallWindowProc (DialogProc, hwnd, msg, wParam, lParam);
+// }
+// if (handle == 0) return 0;
+// if (hwndMDIClient != 0) {
+// return OS.DefFrameProc (hwnd, hwndMDIClient, msg, wParam, lParam);
+// }
+// return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+//}
+
+/**
+ * Requests that the window manager close the receiver in
+ * the same way it would be closed when the user clicks on
+ * the "close box" or performs some other platform specific
+ * key or mouse combination that indicates the window
+ * should be removed.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT#Close
+ * @see #dispose
+ */
+public void close () {
+ checkWidget ();
+ closeWidget ();
+}
+
+protected Container createHandle () {
+ CShell parentShell = parent != null? (CShell)parent.handle: null;
+ return (Container)CShell.Factory.newInstance(this, parentShell, style);
+// boolean embedded = handle != 0;
+//
+// /*
+// * On Windows 98 and NT, setting a window to be the
+// * top most window using HWND_TOPMOST can result in a
+// * parent dialog shell being moved behind its parent
+// * if the dialog has a sibling that is currently on top
+// * This only occurs using SetWindowPos (), not when the
+// * handle is created.
+// */
+// /*
+// * The following code is intentionally commented.
+// */
+//// if ((style & SWT.ON_TOP) != 0) display.lockActiveWindow = true;
+// super.createHandle ();
+//
+// /*
+// * The following code is intentionally commented.
+// */
+//// if ((style & SWT.ON_TOP) != 0) display.lockActiveWindow = false;
+//
+// if (!embedded) {
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// bits &= ~(OS.WS_OVERLAPPED | OS.WS_CAPTION);
+// if (!OS.IsWinCE) bits |= OS.WS_POPUP;
+// if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION;
+// if ((style & SWT.NO_TRIM) == 0) {
+// if ((style & (SWT.BORDER | SWT.RESIZE)) == 0) bits |= OS.WS_BORDER;
+// }
+// /*
+// * Bug in Windows. When the WS_CAPTION bits are cleared using
+// * SetWindowLong(), Windows does not resize the client area of
+// * the window to get rid of the caption until the first resize.
+// * The fix is to use SetWindowPos() with SWP_DRAWFRAME to force
+// * the frame to be redrawn and resized.
+// */
+// OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+// int flags = OS.SWP_DRAWFRAME | OS.SWP_NOMOVE | OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE;
+// SetWindowPos (handle, 0, 0, 0, 0, 0, flags);
+// if (OS.IsWinCE) setMaximized (true);
+// if (OS.IsPPC) {
+// psai = new SHACTIVATEINFO ();
+// psai.cbSize = SHACTIVATEINFO.sizeof;
+// }
+// }
+// if (OS.IsDBLocale) {
+// hIMC = OS.ImmCreateContext ();
+// if (hIMC != 0) OS.ImmAssociateContext (handle, hIMC);
+// }
+}
+
+public void dispose () {
+ /*
+ * This code is intentionally commented. On some
+ * platforms, the owner window is repainted right
+ * away when a dialog window exits. This behavior
+ * is currently unspecified.
+ */
+// /*
+// * Note: It is valid to attempt to dispose a widget
+// * more than once. If this happens, fail silently.
+// */
+// if (!isValidWidget ()) return;
+// if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ Display oldDisplay = display;
+ super.dispose ();
+ if (oldDisplay != null) oldDisplay.wake();
+ // widget is disposed at this point
+// if (oldDisplay != null) oldDisplay.update ();
+}
+
+//void enableWidget (boolean enabled) {
+// if (enabled) {
+// state &= ~DISABLED;
+// } else {
+// state |= DISABLED;
+// }
+// if (Display.TrimEnabled) {
+// if (isActive ()) setItemEnabled (OS.SC_CLOSE, enabled);
+// } else {
+// OS.EnableWindow (handle, enabled);
+// }
+//}
+//
+//int findBrush (int pixel) {
+// if (pixel == OS.GetSysColor (OS.COLOR_BTNFACE)) {
+// return OS.GetSysColorBrush (OS.COLOR_BTNFACE);
+// }
+// if (pixel == OS.GetSysColor (OS.COLOR_WINDOW)) {
+// return OS.GetSysColorBrush (OS.COLOR_WINDOW);
+// }
+// if (brushes == null) brushes = new int [4];
+// LOGBRUSH logBrush = new LOGBRUSH ();
+// for (int i=0; i
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ * @see Control#moveAbove
+ * @see Control#setFocus
+ * @see Control#setVisible
+ * @see Display#getActiveShell
+ * @see Decorations#setDefaultButton
+ * @see Shell#open
+ * @see Shell#setActive
+ */
+public void forceActive () {
+ checkWidget ();
+ if(!isVisible()) return;
+ ((CShell)handle).toFront();
+}
+
+//void forceResize () {
+// /* Do nothing */
+//}
+//
+//public Rectangle getBounds () {
+// checkWidget ();
+// if (!OS.IsWinCE) {
+// if (OS.IsIconic (handle)) return super.getBounds ();
+// }
+// RECT rect = new RECT ();
+// OS.GetWindowRect (handle, rect);
+// int width = rect.right - rect.left;
+// int height = rect.bottom - rect.top;
+// return new Rectangle (rect.left, rect.top, width, height);
+//}
+//
+//public boolean getEnabled () {
+// checkWidget ();
+// return (state & DISABLED) == 0;
+//}
+
+/**
+ * Returns the receiver's input method editor mode. This
+ * will be the result of bitwise OR'ing together one or
+ * more of the following constants defined in class
+ * SWT:
+ * NONE, ROMAN, DBCS,
+ * PHONETIC, NATIVE, ALPHA.
+ *
+ * @return the IME mode
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT
+ */
+public int getImeInputMode () {
+ checkWidget ();
+ // TODO: have a look at setImeInputMethod...
+ return SWT.NONE;
+// if (!OS.IsDBLocale) return 0;
+// int hIMC = OS.ImmGetContext (handle);
+// int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1];
+// boolean open = OS.ImmGetOpenStatus (hIMC);
+// if (open) open = OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence);
+// OS.ImmReleaseContext (handle, hIMC);
+// if (!open) return SWT.NONE;
+// int result = 0;
+// if ((lpfdwConversion [0] & OS.IME_CMODE_ROMAN) != 0) result |= SWT.ROMAN;
+// if ((lpfdwConversion [0] & OS.IME_CMODE_FULLSHAPE) != 0) result |= SWT.DBCS;
+// if ((lpfdwConversion [0] & OS.IME_CMODE_KATAKANA) != 0) return result | SWT.PHONETIC;
+// if ((lpfdwConversion [0] & OS.IME_CMODE_NATIVE) != 0) return result | SWT.NATIVE;
+// return result | SWT.ALPHA;
+}
+
+//public Point getLocation () {
+// checkWidget ();
+// if (!OS.IsWinCE) {
+// if (OS.IsIconic (handle)) {
+// return super.getLocation ();
+// }
+// }
+// RECT rect = new RECT ();
+// OS.GetWindowRect (handle, rect);
+// return new Point (rect.left, rect.top);
+//}
+
+/**
+ * Returns a point describing the minimum receiver's size. The
+ * x coordinate of the result is the minimum width of the receiver.
+ * The y coordinate of the result is the minimum height of the
+ * receiver.
+ *
+ * @return the receiver's size
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public Point getMinimumSize () {
+ checkWidget ();
+ java.awt.Dimension size = handle.getMinimumSize();
+ return new Point(size.width, size.height);
+// int width = Math.max (0, minWidth);
+// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+// width = Math.max (width, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
+// }
+// int height = Math.max (0, minHeight);
+// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+// if ((style & SWT.RESIZE) != 0) {
+// height = Math.max (height, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
+// } else {
+// RECT rect = new RECT ();
+// int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+// OS.AdjustWindowRectEx (rect, bits1, false, bits2);
+// height = Math.max (height, rect.bottom - rect.top);
+// }
+// }
+// return new Point (width, height);
+}
+
+/**
+ * Returns the region that defines the shape of the shell,
+ * or null if the shell has the default shape.
+ *
+ * @return the region that defines the shape of the shell (or null)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ *
+ */
+public Region getRegion () {
+ checkWidget ();
+ return region;
+}
+
+public Shell getShell () {
+ checkWidget ();
+ return this;
+}
+
+//public Point getSize () {
+// checkWidget ();
+// if (!OS.IsWinCE) {
+// if (OS.IsIconic (handle)) return super.getSize ();
+// }
+// RECT rect = new RECT ();
+// OS.GetWindowRect (handle, rect);
+// int width = rect.right - rect.left;
+// int height = rect.bottom - rect.top;
+// return new Point (width, height);
+//}
+
+/**
+ * Returns an array containing all shells which are
+ * descendents of the receiver.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Shell [] getShells () {
+ checkWidget ();
+ int count = 0;
+ Shell [] shells = display.getShells ();
+ for (int i=0; i 0 ? this : null;
+}
+
+protected boolean getTraversalKeyDefault(java.awt.event.KeyEvent ke) {
+ return false;
+}
+
+public boolean isEnabled () {
+ checkWidget ();
+ return getEnabled ();
+}
+
+public boolean isFocusControl () {
+ checkWidget ();
+ if(super.isFocusControl()) return true;
+ KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ return keyboardFocusManager.getFocusOwner() == null && keyboardFocusManager.getFocusedWindow() == handle;
+}
+
+//public boolean isVisible () {
+// checkWidget ();
+// return getVisible ();
+//}
+//
+//int hwndMDIClient () {
+// if (hwndMDIClient == 0) {
+// int widgetStyle = OS.MDIS_ALLCHILDSTYLES | OS.WS_CHILD | OS.WS_CLIPCHILDREN | OS.WS_CLIPSIBLINGS;
+// hwndMDIClient = OS.CreateWindowEx (
+// 0,
+// new TCHAR (0, "MDICLIENT", true),
+// null,
+// widgetStyle,
+// 0, 0, 0, 0,
+// handle,
+// 0,
+// OS.GetModuleHandle (null),
+// new CREATESTRUCT ());
+//// OS.ShowWindow (hwndMDIClient, OS.SW_SHOW);
+// }
+// return hwndMDIClient;
+//}
+
+/**
+ * Moves the receiver to the top of the drawing order for
+ * the display on which it was created (so that all other
+ * shells on that display, which are not the receiver's
+ * children will be drawn behind it), marks it visible,
+ * sets the focus and asks the window manager to make the
+ * shell active.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Control#moveAbove
+ * @see Control#setFocus
+ * @see Control#setVisible
+ * @see Display#getActiveShell
+ * @see Decorations#setDefaultButton
+ * @see Shell#setActive
+ * @see Shell#forceActive
+ */
+public void open () {
+ checkWidget ();
+ bringToTop ();
+ if (isDisposed ()) return;
+ layout(); // Added because the default size is not taken into account be layout managers. cf snippet 109
+// /*
+// * Feature on WinCE PPC. A new application becomes
+// * the foreground application only if it has at least
+// * one visible window before the event loop is started.
+// * The workaround is to explicitely force the shell to
+// * be the foreground window.
+// */
+// if (OS.IsWinCE) OS.SetForegroundWindow (handle);
+// OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+ setVisible (true);
+ // This is to ensure that splashscreens that do not dispatch the events from the queue have some display.
+// handle.paint(handle.getGraphics());
+ if (isDisposed ()) return;
+// /*
+// * Bug in Windows XP. Despite the fact that an icon has been
+// * set for a window, the task bar displays the wrong icon the
+// * first time the window is made visible with ShowWindow() after
+// * a call to BringToTop(), when a long time elapses between the
+// * ShowWindow() and the time the event queue is read. The icon
+// * in the window trimming is correct but the one in the task
+// * bar does not get updated. The fix is to call PeekMessage()
+// * with the flag PM_NOREMOVE and PM_QS_SENDMESSAGE to respond
+// * to a cross thread WM_GETICON.
+// *
+// * NOTE: This allows other cross thread messages to be delivered,
+// * most notably WM_ACTIVATE.
+// */
+// MSG msg = new MSG ();
+// int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_SENDMESSAGE;
+// OS.PeekMessage (msg, 0, 0, 0, flags);
+// if (!restoreFocus () && !traverseGroup (true)) setFocus ();
+}
+
+//void releaseHandle () {
+// super.releaseHandle ();
+// hwndMDIClient = 0;
+//}
+
+void releaseChildren (boolean destroy) {
+ Shell [] shells = getShells ();
+ for (int i=0; i
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ShellListener
+ * @see #addShellListener
+ */
+public void removeShellListener (ShellListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Close, listener);
+ eventTable.unhook (SWT.Iconify,listener);
+ eventTable.unhook (SWT.Deiconify,listener);
+ eventTable.unhook (SWT.Activate, listener);
+ eventTable.unhook (SWT.Deactivate, listener);
+}
+
+//LRESULT selectPalette (int hPalette) {
+// int hDC = OS.GetDC (handle);
+// int hOld = OS.SelectPalette (hDC, hPalette, false);
+// int result = OS.RealizePalette (hDC);
+// if (result > 0) {
+// OS.InvalidateRect (handle, null, true);
+// } else {
+// OS.SelectPalette (hDC, hOld, true);
+// OS.RealizePalette (hDC);
+// }
+// OS.ReleaseDC (handle, hDC);
+// return (result > 0) ? LRESULT.ONE : LRESULT.ZERO;
+//}
+
+/**
+ * If the receiver is visible, moves it to the top of the
+ * drawing order for the display on which it was created
+ * (so that all other shells on that display, which are not
+ * the receiver's children will be drawn behind it) and asks
+ * the window manager to make the shell active
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ * @see Control#moveAbove
+ * @see Control#setFocus
+ * @see Control#setVisible
+ * @see Display#getActiveShell
+ * @see Decorations#setDefaultButton
+ * @see Shell#open
+ * @see Shell#setActive
+ */
+public void setActive () {
+ checkWidget ();
+ if(!isVisible()) return;
+// bringToTop ();
+ ((CShell)handle).forceActive();
+ // widget could be disposed at this point
+}
+
+Control getActiveControl() {
+ return lastActive;
+}
+
+void setActiveControl (Control control) {
+ if (control != null && control.isDisposed ()) control = null;
+ if (lastActive != null && lastActive.isDisposed ()) lastActive = null;
+ if (lastActive == control) return;
+
+ /*
+ * Compute the list of controls to be activated and
+ * deactivated by finding the first common parent
+ * control.
+ */
+ Control [] activate = (control == null) ? new Control [0] : control.getPath ();
+ Control [] deactivate = (lastActive == null) ? new Control [0] : lastActive.getPath ();
+ lastActive = control;
+ int index = 0, length = Math.min (activate.length, deactivate.length);
+ while (index < length) {
+ if (activate [index] != deactivate [index]) break;
+ index++;
+ }
+
+ /*
+ * It is possible (but unlikely), that application
+ * code could have destroyed some of the widgets. If
+ * this happens, keep processing those widgets that
+ * are not disposed.
+ */
+ for (int i=deactivate.length-1; i>=index; --i) {
+ if (!deactivate [i].isDisposed ()) {
+ deactivate [i].sendEvent (SWT.Deactivate);
+ }
+ }
+ for (int i=activate.length-1; i>=index; --i) {
+ if (!activate [i].isDisposed ()) {
+ activate [i].sendEvent (SWT.Activate);
+ }
+ }
+}
+
+//void setBounds (int x, int y, int width, int height, int flags, boolean defer) {
+// super.setBounds (x, y, width, height, flags, false);
+//}
+//
+//public void setEnabled (boolean enabled) {
+// checkWidget ();
+// if (((state & DISABLED) == 0) == enabled) return;
+// super.setEnabled (enabled);
+// if (enabled && handle == OS.GetActiveWindow ()) {
+// if (!restoreFocus ()) traverseGroup (true);
+// }
+//}
+
+/**
+ * Sets the input method editor mode to the argument which
+ * should be the result of bitwise OR'ing together one or more
+ * of the following constants defined in class SWT:
+ * NONE, ROMAN, DBCS,
+ * PHONETIC, NATIVE, ALPHA.
+ *
+ * @param mode the new IME mode
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT
+ */
+public void setImeInputMode (int mode) {
+ checkWidget ();
+ // TODO: implement probably with something like the following...
+ InputContext ic = handle.getInputContext();
+ boolean imeOn = mode != SWT.NONE && mode != SWT.ROMAN;
+//handle.enableInputMethods(imeOn);
+ ic.setCompositionEnabled (imeOn);
+ if(imeOn) {
+ boolean phonetic = (mode & SWT.PHONETIC) != 0;
+ boolean nativecs = (mode & SWT.NATIVE) != 0;
+ // PHONETIC > NATIVE > ROMAN = ALPHA ; The former is stronger.
+ Character.Subset subset;
+ if ((mode & SWT.DBCS) != 0) {
+ // double byte characters
+ subset = InputSubset.FULLWIDTH_LATIN;
+ if (nativecs) {
+ subset = UnicodeBlock.HIRAGANA;
+ }
+ if (phonetic) {
+ subset = UnicodeBlock.KATAKANA;
+ }
+ } else {
+ // not double byte characters
+ subset = InputSubset.LATIN;
+ if (phonetic || nativecs) {
+ subset = InputSubset.HALFWIDTH_KATAKANA;
+ }
+ }
+ ic.setCharacterSubsets (new Character.Subset[] { subset });
+ }
+// if (!OS.IsDBLocale) return;
+// boolean imeOn = mode != SWT.NONE && mode != SWT.ROMAN;
+// int hIMC = OS.ImmGetContext (handle);
+// OS.ImmSetOpenStatus (hIMC, imeOn);
+// if (imeOn) {
+// int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1];
+// if (OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence)) {
+// int newBits = 0;
+// int oldBits = OS.IME_CMODE_NATIVE | OS.IME_CMODE_KATAKANA;
+// if ((mode & SWT.PHONETIC) != 0) {
+// newBits = OS.IME_CMODE_KATAKANA | OS.IME_CMODE_NATIVE;
+// oldBits = 0;
+// } else {
+// if ((mode & SWT.NATIVE) != 0) {
+// newBits = OS.IME_CMODE_NATIVE;
+// oldBits = OS.IME_CMODE_KATAKANA;
+// }
+// }
+// if ((mode & SWT.DBCS) != 0) {
+// newBits |= OS.IME_CMODE_FULLSHAPE;
+// } else {
+// oldBits |= OS.IME_CMODE_FULLSHAPE;
+// }
+// if ((mode & SWT.ROMAN) != 0) {
+// newBits |= OS.IME_CMODE_ROMAN;
+// } else {
+// oldBits |= OS.IME_CMODE_ROMAN;
+// }
+// lpfdwConversion [0] |= newBits; lpfdwConversion [0] &= ~oldBits;
+// OS.ImmSetConversionStatus (hIMC, lpfdwConversion [0], lpfdwSentence [0]);
+// }
+// }
+// OS.ImmReleaseContext (handle, hIMC);
+}
+
+/**
+ * Sets the receiver's minimum size to the size specified by the arguments.
+ * If the new minimum size is larger than the current size of the receiver,
+ * the receiver is resized to the new minimum size.
+ *
+ * @param width the new minimum width for the receiver
+ * @param height the new minimum height for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void setMinimumSize (int width, int height) {
+ checkWidget ();
+ if(Compatibility.IS_JAVA_5_OR_GREATER) {
+ handle.setMinimumSize(new java.awt.Dimension(width, height));
+ }
+// int widthLimit = 0, heightLimit = 0;
+// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+// widthLimit = OS.GetSystemMetrics (OS.SM_CXMINTRACK);
+// if ((style & SWT.RESIZE) != 0) {
+// heightLimit = OS.GetSystemMetrics (OS.SM_CYMINTRACK);
+// } else {
+// RECT rect = new RECT ();
+// int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+// OS.AdjustWindowRectEx (rect, bits1, false, bits2);
+// heightLimit = rect.bottom - rect.top;
+// }
+// }
+// minWidth = Math.max (widthLimit, width);
+// minHeight = Math.max (heightLimit, height);
+// Point size = getSize ();
+// int newWidth = Math.max (size.x, minWidth);
+// int newHeight = Math.max (size.y, minHeight);
+// if (minWidth <= widthLimit) minWidth = SWT.DEFAULT;
+// if (minHeight <= heightLimit) minHeight = SWT.DEFAULT;
+// if (newWidth != size.x || newHeight != size.y) setSize (newWidth, newHeight);
+}
+
+/**
+ * Sets the receiver's minimum size to the size specified by the argument.
+ * If the new minimum size is larger than the current size of the receiver,
+ * the receiver is resized to the new minimum size.
+ *
+ * @param size the new minimum size for the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void setMinimumSize (Point size) {
+ checkWidget ();
+ if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setMinimumSize (size.x, size.y);
+}
+
+//void setItemEnabled (int cmd, boolean enabled) {
+// int hMenu = OS.GetSystemMenu (handle, false);
+// if (hMenu == 0) return;
+// int flags = OS.MF_ENABLED;
+// if (!enabled) flags = OS.MF_DISABLED | OS.MF_GRAYED;
+// OS.EnableMenuItem (hMenu, cmd, OS.MF_BYCOMMAND | flags);
+//}
+
+void setParent () {
+ /* Do nothing. Not necessary for Shells */
+}
+
+/**
+ * Sets the shape of the shell to the region specified
+ * by the argument. When the argument is null, the
+ * default shape of the shell is restored. The shell
+ * must be created with the style SWT.NO_TRIM in order
+ * to specify a region.
+ *
+ * @param region the region that defines the shape of the shell (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the region has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ *
+ */
+public void setRegion (Region region) {
+ checkWidget ();
+ if ((style & SWT.NO_TRIM) == 0) return;
+ if (region != null && region.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ // TODO: how to implement that?
+// int hRegion = 0;
+// if (region != null) {
+// hRegion = OS.CreateRectRgn (0, 0, 0, 0);
+// OS.CombineRgn (hRegion, region.handle, hRegion, OS.RGN_OR);
+// }
+// OS.SetWindowRgn (handle, hRegion, true);
+ this.region = region;
+}
+
+//void setToolTipText (int hwnd, String text) {
+// if (OS.IsWinCE) return;
+// if (toolTipHandle == 0) {
+// toolTipHandle = OS.CreateWindowEx (
+// 0,
+// new TCHAR (0, OS.TOOLTIPS_CLASS, true),
+// null,
+// OS.TTS_ALWAYSTIP,
+// OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+// handle,
+// 0,
+// OS.GetModuleHandle (null),
+// null);
+// if (toolTipHandle == 0) error (SWT.ERROR_NO_HANDLES);
+// /*
+// * Feature in Windows. Despite the fact that the
+// * tool tip text contains \r\n, the tooltip will
+// * not honour the new line unless TTM_SETMAXTIPWIDTH
+// * is set. The fix is to set TTM_SETMAXTIPWIDTH to
+// * a large value.
+// */
+// OS.SendMessage (toolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+// }
+// TOOLINFO lpti = new TOOLINFO ();
+// lpti.cbSize = TOOLINFO.sizeof;
+// lpti.uId = hwnd;
+// lpti.hwnd = handle;
+// if (text == null) {
+// OS.SendMessage (toolTipHandle, OS.TTM_DELTOOL, 0, lpti);
+// } else {
+// if (OS.SendMessage (toolTipHandle, OS.TTM_GETTOOLINFO, 0, lpti) != 0) {
+// OS.SendMessage (toolTipHandle, OS.TTM_UPDATE, 0, 0);
+// } else {
+// lpti.uFlags = OS.TTF_IDISHWND | OS.TTF_SUBCLASS;
+// lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
+// OS.SendMessage (toolTipHandle, OS.TTM_ADDTOOL, 0, lpti);
+// }
+// }
+//}
+//
+//void setToolTipText (NMTTDISPINFO lpnmtdi, byte [] buffer) {
+// /*
+// * Ensure that the current position of the mouse
+// * is inside the client area of the shell. This
+// * prevents tool tips from popping up over the
+// * shell trimmings.
+// */
+// if (!hasCursor ()) return;
+// int hHeap = OS.GetProcessHeap ();
+// if (lpstrTip != 0) OS.HeapFree (hHeap, 0, lpstrTip);
+// int byteCount = buffer.length;
+// lpstrTip = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+// OS.MoveMemory (lpstrTip, buffer, byteCount);
+// lpnmtdi.lpszText = lpstrTip;
+//}
+//
+//void setToolTipText (NMTTDISPINFO lpnmtdi, char [] buffer) {
+// /*
+// * Ensure that the current position of the mouse
+// * is inside the client area of the shell. This
+// * prevents tool tips from popping up over the
+// * shell trimmings.
+// */
+// if (!hasCursor ()) return;
+// int hHeap = OS.GetProcessHeap ();
+// if (lpstrTip != 0) OS.HeapFree (hHeap, 0, lpstrTip);
+// int byteCount = buffer.length * 2;
+// lpstrTip = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+// OS.MoveMemory (lpstrTip, buffer, byteCount);
+// lpnmtdi.lpszText = lpstrTip;
+//}
+
+Control initialFocusedControl;
+
+void setInitialFocusedControl(Control initialFocusedControl) {
+ this.initialFocusedControl = initialFocusedControl;
+}
+
+public void setVisible (boolean visible) {
+ checkWidget ();
+ if(handle.isVisible() == visible) {
+ return;
+ }
+ boolean isFocusable = handle instanceof Window? ((Window)handle).getFocusableWindowState(): true;
+ handle.setVisible(visible);
+ if(visible) {
+ if(initialFocusedControl != null) {
+ initialFocusedControl.setFocus();
+ initialFocusedControl = null;
+ } else {
+ if(isFocusable) {
+ if (!traverseGroup (true)) setFocus ();
+ }
+ }
+ layout();
+ }
+// if (drawCount != 0) {
+// if (((state & HIDDEN) == 0) == visible) return;
+// } else {
+// if (visible == OS.IsWindowVisible (handle)) return;
+// }
+//
+// /*
+// * Feature in Windows. When ShowWindow() is called used to hide
+// * a window, Windows attempts to give focus to the parent. If the
+// * parent is disabled by EnableWindow(), focus is assigned to
+// * another windows on the desktop. This means that if you hide
+// * a modal window before the parent is enabled, the parent will
+// * not come to the front. The fix is to change the modal state
+// * before hiding or showing a window so that this does not occur.
+// */
+// int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
+// if ((style & mask) != 0) {
+// if (visible) {
+// display.setModalShell (this);
+// Control control = display._getFocusControl ();
+// if (control != null && !control.isActive ()) bringToTop ();
+// int hwndShell = OS.GetActiveWindow ();
+// if (hwndShell == 0) {
+// if (parent != null) hwndShell = parent.handle;
+// }
+// if (hwndShell != 0) {
+// OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0);
+// }
+// OS.ReleaseCapture ();
+// } else {
+// display.clearModal (this);
+// }
+// } else {
+// updateModal ();
+// }
+//
+// /*
+// * Bug in Windows. Calling ShowOwnedPopups() to hide the
+// * child windows of a hidden window causes the application
+// * to be deactivated. The fix is to call ShowOwnedPopups()
+// * to hide children before hiding the parent.
+// */
+// if (showWithParent && !visible) {
+// if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, false);
+// }
+// super.setVisible (visible);
+// if (isDisposed ()) return;
+// if (showWithParent == visible) return;
+// showWithParent = visible;
+// if (visible) {
+// if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, true);
+// }
+}
+
+//boolean translateAccelerator (MSG msg) {
+// if (!isEnabled () || !isActive ()) return false;
+// if (menuBar != null && !menuBar.isEnabled ()) return false;
+// return translateMDIAccelerator (msg) || translateMenuAccelerator (msg);
+//}
+
+boolean traverseEscape () {
+ if (parent == null) return false;
+ if (!isVisible () || !isEnabled ()) return false;
+ close ();
+ return true;
+}
+
+//void updateModal () {
+// if (Display.TrimEnabled) {
+// setItemEnabled (OS.SC_CLOSE, isActive ());
+// } else {
+// OS.EnableWindow (handle, isActive ());
+// }
+//}
+//
+//CREATESTRUCT widgetCreateStruct () {
+// return null;
+//}
+//
+//int widgetParent () {
+// if (handle != 0) return handle;
+// return parent != null ? parent.handle : 0;
+//}
+//
+//int widgetExtStyle () {
+// int bits = super.widgetExtStyle () & ~OS.WS_EX_MDICHILD;
+// if ((style & SWT.TOOL) != 0) bits |= OS.WS_EX_TOOLWINDOW;
+//
+// /*
+// * Feature in Windows. When a window that does not have a parent
+// * is created, it is automatically added to the Windows Task Bar,
+// * even when it has no title. The fix is to use WS_EX_TOOLWINDOW
+// * which does not cause the window to appear in the Task Bar.
+// */
+// if (!OS.IsWinCE) {
+// if (parent == null) {
+// if ((style & SWT.ON_TOP) != 0) {
+// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+// if ((style & SWT.NO_TRIM) != 0 || (style & trim) == 0) {
+// bits |= OS.WS_EX_TOOLWINDOW;
+// }
+// }
+// }
+// }
+//
+// /*
+// * Bug in Windows 98 and NT. Creating a window with the
+// * WS_EX_TOPMOST extended style can result in a dialog shell
+// * being moved behind its parent. The exact case where this
+// * happens is a shell with two dialog shell children where
+// * each dialog child has another hidden dialog child with
+// * the WS_EX_TOPMOST extended style. Clicking on either of
+// * the visible dialogs causes them to become active but move
+// * to the back, behind the parent shell. The fix is to
+// * disallow the WS_EX_TOPMOST extended style on Windows 98
+// * and NT.
+// */
+// if (parent != null) {
+// if (OS.IsWin95) return bits;
+// if (OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+// return bits;
+// }
+// }
+// if ((style & SWT.ON_TOP) != 0) bits |= OS.WS_EX_TOPMOST;
+// return bits;
+//}
+//
+//TCHAR windowClass () {
+// if (OS.IsSP) return DialogClass;
+// if ((style & SWT.TOOL) != 0) {
+// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
+// if ((style & trim) == 0) return display.windowShadowClass;
+// }
+// return parent != null ? DialogClass : super.windowClass ();
+//}
+//
+//int windowProc () {
+// if (OS.IsSP) return DialogProc;
+// if ((style & SWT.TOOL) != 0) {
+// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
+// if ((style & trim) == 0) super.windowProc ();
+// }
+// return parent != null ? DialogProc : super.windowProc ();
+//}
+//
+//int widgetStyle () {
+// int bits = super.widgetStyle ();
+// if (handle != 0) return bits | OS.WS_CHILD;
+// bits &= ~OS.WS_CHILD;
+// /*
+// * Feature in WinCE. Calling CreateWindowEx () with WS_OVERLAPPED
+// * and a parent window causes the new window to become a WS_CHILD of
+// * the parent instead of a dialog child. The fix is to use WS_POPUP
+// * for a window with a parent.
+// *
+// * Feature in WinCE PPC. A window without a parent with WS_POPUP
+// * always shows on top of the Pocket PC 'Today Screen'. The fix
+// * is to not set WS_POPUP for a window without a parent on WinCE
+// * devices.
+// *
+// * NOTE: WS_POPUP causes CreateWindowEx () to ignore CW_USEDEFAULT
+// * and causes the default window location and size to be zero.
+// */
+// if (OS.IsWinCE) {
+// if (OS.IsSP) return bits | OS.WS_POPUP;
+// return parent == null ? bits : bits | OS.WS_POPUP;
+// }
+//
+// /*
+// * Use WS_OVERLAPPED for all windows, either dialog or top level
+// * so that CreateWindowEx () will respect CW_USEDEFAULT and set
+// * the default window location and size.
+// *
+// * NOTE: When a WS_OVERLAPPED window is created, Windows gives
+// * the new window WS_CAPTION style bits. These two constants are
+// * as follows:
+// *
+// * WS_OVERLAPPED = 0
+// * WS_CAPTION = WS_BORDER | WS_DLGFRAME
+// *
+// */
+// return bits | OS.WS_OVERLAPPED | OS.WS_CAPTION;
+//}
+//
+//LRESULT WM_ACTIVATE (int wParam, int lParam) {
+// if (OS.IsPPC) {
+// /*
+// * Note: this does not work when we get WM_ACTIVATE prior
+// * to adding a listener.
+// */
+// if (hooks (SWT.HardKeyDown) || hooks (SWT.HardKeyUp)) {
+// int fActive = wParam & 0xFFFF;
+// int hwnd = fActive != 0 ? handle : 0;
+// for (int bVk=OS.VK_APP1; bVk<=OS.VK_APP6; bVk++) {
+// OS.SHSetAppKeyWndAssoc ((byte) bVk, hwnd);
+// }
+// }
+// /* Restore SIP state when window is activated */
+// if ((wParam & 0xFFFF) != 0) {
+// OS.SHSipPreference (handle, psai.fSipUp == 0 ? OS.SIP_DOWN : OS.SIP_UP);
+// }
+// }
+//
+// /*
+// * Bug in Windows XP. When a Shell is deactivated, the
+// * IME composition window does not go away. This causes
+// * repaint issues. The fix is to close the IME ourselves
+// * when the Shell is deactivated.
+// *
+// * Note. When the Shell is reactivated, the text in the
+// * composition window has been lost.
+// */
+// if (OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+// if ((wParam & 0xFFFF) == 0 && OS.IsDBLocale && hIMC != 0) {
+// OS.ImmSetOpenStatus (hIMC, false);
+// }
+// }
+//
+// LRESULT result = super.WM_ACTIVATE (wParam, lParam);
+// if (parent != null) return LRESULT.ZERO;
+// return result;
+//}
+//
+//LRESULT WM_COMMAND (int wParam, int lParam) {
+// if (OS.IsPPC) {
+// /*
+// * Note in WinCE PPC: Close the Shell when the "Done Button" has
+// * been pressed. lParam is either 0 (PocketPC 2002) or the handle
+// * to the Shell (PocketPC).
+// */
+// int loWord = wParam & 0xFFFF;
+// if (loWord == OS.IDOK && (lParam == 0 || lParam == handle)) {
+// OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
+// return LRESULT.ZERO;
+// }
+// }
+// /*
+// * Feature in Windows. On PPC, the menu is not actually an HMENU.
+// * By observation, it is a tool bar that is configured to look like
+// * a menu. Therefore, when the PPC menu sends WM_COMMAND messages,
+// * lParam is not zero because the WM_COMMAND was not sent from a menu.
+// * Sub menu item events originate from the menu bar. Top menu items
+// * events originate from a tool bar. The fix is to detect the source
+// * of the WM_COMMAND and set lParam to zero to pretend that the message
+// * came from a real Windows menu, not a tool bar.
+// */
+// if (OS.IsPPC || OS.IsSP) {
+// if (menuBar != null) {
+// int hwndCB = menuBar.hwndCB;
+// if (lParam != 0 && hwndCB != 0) {
+// if (lParam == hwndCB) {
+// return super.WM_COMMAND (wParam, 0);
+// } else {
+// int hwndChild = OS.GetWindow (hwndCB, OS.GW_CHILD);
+// if (lParam == hwndChild) return super.WM_COMMAND (wParam, 0);
+// }
+// }
+// }
+// }
+// return super.WM_COMMAND (wParam, lParam);
+//}
+//
+//LRESULT WM_DESTROY (int wParam, int lParam) {
+// LRESULT result = super.WM_DESTROY (wParam, lParam);
+// /*
+// * When the shell is a WS_CHILD window of a non-SWT
+// * window, the destroy code does not get called because
+// * the non-SWT window does not call dispose (). Instead,
+// * the destroy code is called here in WM_DESTROY.
+// */
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// if ((bits & OS.WS_CHILD) != 0) {
+// releaseChild ();
+// releaseResources ();
+// }
+// return result;
+//}
+//
+//LRESULT WM_ENTERIDLE (int wParam, int lParam) {
+// LRESULT result = super.WM_ENTERIDLE (wParam, lParam);
+// if (result != null) return result;
+// if (OS.IsWinCE) {
+// if (display.runAsyncMessages (true)) display.wakeThread ();
+// }
+// return result;
+//}
+//
+//LRESULT WM_GETMINMAXINFO (int wParam, int lParam) {
+// LRESULT result = super.WM_GETMINMAXINFO (wParam, lParam);
+// if (result != null) return result;
+// if (minWidth != SWT.DEFAULT || minHeight != SWT.DEFAULT) {
+// MINMAXINFO info = new MINMAXINFO ();
+// OS.MoveMemory (info, lParam, MINMAXINFO.sizeof);
+// if (minWidth != SWT.DEFAULT) info.ptMinTrackSize_x = minWidth;
+// if (minHeight != SWT.DEFAULT) info.ptMinTrackSize_y = minHeight;
+// OS.MoveMemory (lParam, info, MINMAXINFO.sizeof);
+// return LRESULT.ZERO;
+// }
+// return result;
+//}
+//
+//LRESULT WM_MOUSEACTIVATE (int wParam, int lParam) {
+// LRESULT result = super.WM_MOUSEACTIVATE (wParam, lParam);
+// if (result != null) return result;
+//
+// /*
+// * Check for WM_MOUSEACTIVATE when an MDI shell is active
+// * and stop the normal shell activation but allow the mouse
+// * down to be delivered.
+// */
+// int hittest = (short) (lParam & 0xFFFF);
+// switch (hittest) {
+// case OS.HTERROR:
+// case OS.HTTRANSPARENT:
+// case OS.HTNOWHERE:
+// break;
+// default: {
+// Control control = display._getFocusControl ();
+// if (control != null) {
+// Decorations decorations = control.menuShell ();
+// if (decorations.getShell () == this && decorations != this) {
+// display.ignoreRestoreFocus = true;
+// display.lastHittest = hittest;
+// display.lastHittestControl = null;
+// if (hittest == OS.HTMENU || hittest == OS.HTSYSMENU) {
+// display.lastHittestControl = control;
+// return null;
+// }
+// if (OS.IsWin95 && hittest == OS.HTCAPTION) {
+// display.lastHittestControl = control;
+// }
+// return new LRESULT (OS.MA_NOACTIVATE);
+// }
+// }
+// }
+// }
+// if (hittest == OS.HTMENU) return null;
+//
+// /*
+// * Get the current location of the cursor,
+// * not the location of the cursor when the
+// * WM_MOUSEACTIVATE was generated. This is
+// * strictly incorrect but is necessary in
+// * order to support Activate and Deactivate
+// * events for embedded widgets that have
+// * their own event loop. In that case, the
+// * cursor location reported by GetMessagePos
+// * is the one for our event loop, not the
+// * embedded widget's event loop.
+// */
+// POINT pt = new POINT ();
+// if (!OS.GetCursorPos (pt)) {
+// int pos = OS.GetMessagePos ();
+// pt.x = (short) (pos & 0xFFFF);
+// pt.y = (short) (pos >> 16);
+// }
+// int hwnd = OS.WindowFromPoint (pt);
+// if (hwnd == 0) return null;
+// Control control = display.findControl (hwnd);
+// setActiveControl (control);
+//
+// /*
+// * This code is intentionally commented. On some platforms,
+// * shells that are created with SWT.NO_TRIM won't take focus
+// * when the user clicks in the client area or on the border.
+// * This behavior is usedful when emulating tool tip shells
+// * Until this behavior is specified, this code will remain
+// * commented.
+// */
+//// if ((style & SWT.NO_TRIM) != 0) {
+//// if (hittest == OS.HTBORDER || hittest == OS.HTCLIENT) {
+//// return new LRESULT (OS.MA_NOACTIVATE);
+//// }
+//// }
+// return null;
+//}
+//
+//LRESULT WM_NCHITTEST (int wParam, int lParam) {
+// if (!OS.IsWindowEnabled (handle)) return null;
+// if (!isEnabled () || !isActive ()) {
+// if (!Display.TrimEnabled) return new LRESULT (OS.HTNOWHERE);
+// int hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+// if (hittest == OS.HTCLIENT || hittest == OS.HTMENU) hittest = OS.HTBORDER;
+// return new LRESULT (hittest);
+// }
+// if (menuBar != null && !menuBar.getEnabled ()) {
+// int hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+// if (hittest == OS.HTMENU) hittest = OS.HTBORDER;
+// return new LRESULT (hittest);
+// }
+// return null;
+//}
+//
+//LRESULT WM_NCLBUTTONDOWN (int wParam, int lParam) {
+// LRESULT result = super.WM_NCLBUTTONDOWN (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * When the normal activation was interruped in WM_MOUSEACTIVATE
+// * because the active shell was an MDI shell, set the active window
+// * to the top level shell but lock the active window and stop focus
+// * changes. This allows the user to interact the top level shell
+// * in the normal manner.
+// */
+// if (!display.ignoreRestoreFocus) return result;
+// Display display = this.display;
+// int hwndActive = 0;
+// boolean fixActive = OS.IsWin95 && display.lastHittest == OS.HTCAPTION;
+// if (fixActive) hwndActive = OS.SetActiveWindow (handle);
+// display.lockActiveWindow = true;
+// int code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam);
+// display.lockActiveWindow = false;
+// if (fixActive) OS.SetActiveWindow (hwndActive);
+// Control focusControl = display.lastHittestControl;
+// if (focusControl != null && !focusControl.isDisposed ()) {
+// focusControl.setFocus ();
+// }
+// display.lastHittestControl = null;
+// display.ignoreRestoreFocus = false;
+// return new LRESULT (code);
+//}
+//
+//LRESULT WM_PALETTECHANGED (int wParam, int lParam) {
+// if (wParam != handle) {
+// int hPalette = display.hPalette;
+// if (hPalette != 0) return selectPalette (hPalette);
+// }
+// return super.WM_PALETTECHANGED (wParam, lParam);
+//}
+//
+//LRESULT WM_QUERYNEWPALETTE (int wParam, int lParam) {
+// int hPalette = display.hPalette;
+// if (hPalette != 0) return selectPalette (hPalette);
+// return super.WM_QUERYNEWPALETTE (wParam, lParam);
+//}
+//
+//LRESULT WM_SETCURSOR (int wParam, int lParam) {
+// /*
+// * Feature in Windows. When the shell is disabled
+// * by a Windows standard dialog (like a MessageBox
+// * or FileDialog), clicking in the shell does not
+// * bring the shell or the dialog to the front. The
+// * fix is to detect this case and bring the shell
+// * forward.
+// */
+// int msg = (short) (lParam >> 16);
+// if (msg == OS.WM_LBUTTONDOWN) {
+// if (!Display.TrimEnabled) {
+// Shell modalShell = display.getModalShell ();
+// if (modalShell != null && !isActive ()) {
+// int hwndModal = modalShell.handle;
+// if (OS.IsWindowEnabled (hwndModal)) {
+// OS.SetActiveWindow (hwndModal);
+// }
+// }
+// }
+// if (!OS.IsWindowEnabled (handle)) {
+// if (!OS.IsWinCE) {
+// int hwndPopup = OS.GetLastActivePopup (handle);
+// if (hwndPopup != 0 && hwndPopup != handle) {
+// if (display.getControl (hwndPopup) == null) {
+// if (OS.IsWindowEnabled (hwndPopup)) {
+// OS.SetActiveWindow (hwndPopup);
+// }
+// }
+// }
+// }
+// }
+// }
+// /*
+// * When the shell that contains a cursor is disabled,
+// * WM_SETCURSOR is called with HTERROR. Normally,
+// * when a control is disabled, the parent will get
+// * mouse and cursor events. In the case of a disabled
+// * shell, there is no enabled parent. In order to
+// * show the cursor when a shell is disabled, it is
+// * necessary to override WM_SETCURSOR when called
+// * with HTERROR to set the cursor but only when the
+// * mouse is in the client area of the shell.
+// */
+// int hitTest = (short) (lParam & 0xFFFF);
+// if (hitTest == OS.HTERROR) {
+// if (!getEnabled ()) {
+// Control control = display.getControl (wParam);
+// if (control == this && cursor != null) {
+// POINT pt = new POINT ();
+// if (OS.GetCursorPos (pt)) {
+// OS.ScreenToClient (handle, pt);
+// RECT rect = new RECT ();
+// OS.GetClientRect (handle, rect);
+// if (OS.PtInRect (rect, pt)) {
+// OS.SetCursor (cursor.handle);
+// switch (msg) {
+// case OS.WM_LBUTTONDOWN:
+// case OS.WM_RBUTTONDOWN:
+// case OS.WM_MBUTTONDOWN:
+// case OS.WM_XBUTTONDOWN:
+// OS.MessageBeep (OS.MB_OK);
+// }
+// return LRESULT.ONE;
+// }
+// }
+// }
+// }
+// }
+// return super.WM_SETCURSOR (wParam, lParam);
+//}
+//
+//LRESULT WM_SETTINGCHANGE (int wParam, int lParam) {
+// LRESULT result = super.WM_SETTINGCHANGE (wParam, lParam);
+// if (result != null) return result;
+// if (OS.IsPPC) {
+// if (wParam == OS.SPI_SETSIPINFO) {
+// /*
+// * The SIP is in a new state. Cache its new value.
+// * Resize the Shell if it has the style SWT.RESIZE.
+// * Note that SHHandleWMSettingChange resizes the
+// * Shell and also updates the cached state.
+// */
+// if ((style & SWT.RESIZE) != 0) {
+// OS.SHHandleWMSettingChange (handle, wParam, lParam, psai);
+// return LRESULT.ZERO;
+// } else {
+// SIPINFO pSipInfo = new SIPINFO ();
+// pSipInfo.cbSize = SIPINFO.sizeof;
+// OS.SipGetInfo (pSipInfo);
+// psai.fSipUp = pSipInfo.fdwFlags & OS.SIPF_ON;
+// }
+// }
+// }
+// return result;
+//}
+//
+//LRESULT WM_SHOWWINDOW (int wParam, int lParam) {
+// LRESULT result = super.WM_SHOWWINDOW (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Bug in Windows. If the shell is hidden while the parent
+// * is iconic, Windows shows the shell when the parent is
+// * deiconified. This does not happen if the shell is hidden
+// * while the parent is not an icon. The fix is to track
+// * visible state for the shell and refuse to show the shell
+// * when the parent is shown.
+// */
+// if (lParam == OS.SW_PARENTOPENING) {
+// Control control = this;
+// while (control != null) {
+// Shell shell = control.getShell ();
+// if (!shell.showWithParent) return LRESULT.ZERO;
+// control = control.parent;
+// }
+// }
+// return result;
+//}
+//
+//LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
+// LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
+// //This code is intentionally commented
+//// if (result != null) return result;
+//// /*
+//// * Feature in Windows. When a window is minimized, the memory
+//// * for the working set of the process. For applications that
+//// * use a lot of memory, when the window is restored, it can take
+//// * a long time (sometimes minutes) before the application becomes
+//// * responsive. The fix is to intercept WM_SYSCOMMAND looking
+//// * for SC_MINIMIZE and use ShowWindow() with SW_SHOWMINIMIZED to
+//// * minimize the window rather than allowing the default window
+//// * proc to do it when more that 64Meg of memory is being used.
+//// *
+//// * NOTE: The default window proc activates the next top-level
+//// * window in the Z order while ShowWindow () with SW_SHOWMINIMIZED
+//// * does not. There is no fix for this at this time.
+//// */
+//// int cmd = wParam & 0xFFF0;
+//// switch (cmd) {
+//// case OS.SC_MINIMIZE:
+//// long memory = Runtime.getRuntime ().totalMemory ();
+//// if (memory > 64000000) {
+//// OS.ShowWindow (handle, OS.SW_SHOWMINIMIZED);
+//// return LRESULT.ZERO;
+//// }
+//// }
+// return result;
+//}
+//
+//LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+// LRESULT result = super.WM_WINDOWPOSCHANGING (wParam,lParam);
+// if (result != null) return result;
+// WINDOWPOS lpwp = new WINDOWPOS ();
+// OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+// if ((lpwp.flags & OS.SWP_NOSIZE) == 0) {
+// lpwp.cx = Math.max (lpwp.cx, minWidth);
+// int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+// lpwp.cx = Math.max (lpwp.cx, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
+// }
+// lpwp.cy = Math.max (lpwp.cy, minHeight);
+// if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
+// if ((style & SWT.RESIZE) != 0) {
+// lpwp.cy = Math.max (lpwp.cy, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
+// } else {
+// RECT rect = new RECT ();
+// int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+// OS.AdjustWindowRectEx (rect, bits1, false, bits2);
+// lpwp.cy = Math.max (lpwp.cy, rect.bottom - rect.top);
+// }
+// }
+// OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof);
+// }
+// return result;
+//}
+
+public void processEvent(AWTEvent e) {
+ int id = e.getID();
+ switch(id) {
+ case ActionEvent.ACTION_PERFORMED: if(!hooks(SWT.Traverse)) { super.processEvent(e); return; } break;
+ case WindowEvent.WINDOW_ACTIVATED: if(!hooks(SWT.Activate)) { super.processEvent(e); return; } break;
+ case WindowEvent.WINDOW_DEACTIVATED: if(!hooks(SWT.Deactivate)) { super.processEvent(e); return; } break;
+ case WindowEvent.WINDOW_CLOSED: if(!hooks(SWT.Close)) { super.processEvent(e); return; } break;
+ case WindowEvent.WINDOW_ICONIFIED: if(!hooks(SWT.Iconify)) { super.processEvent(e); return; } break;
+ case WindowEvent.WINDOW_DEICONIFIED: if(!hooks(SWT.Deiconify)) { super.processEvent(e); return; } break;
+ case WindowEvent.WINDOW_CLOSING: if(!isEnabled()) { super.processEvent(e); return; } break;
+ default: { super.processEvent(e); return; }
+ }
+ if(isDisposed()) {
+ super.processEvent(e);
+ return;
+ }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ switch(id) {
+ case WindowEvent.WINDOW_ACTIVATED: sendEvent(SWT.Activate); break;
+ case WindowEvent.WINDOW_DEACTIVATED: sendEvent(SWT.Deactivate); break;
+ case WindowEvent.WINDOW_CLOSED: sendEvent(SWT.Close); break;
+ case WindowEvent.WINDOW_ICONIFIED: sendEvent(SWT.Iconify); break;
+ case WindowEvent.WINDOW_DEICONIFIED: sendEvent(SWT.Deiconify); break;
+ case WindowEvent.WINDOW_CLOSING:
+ if(isEnabled()) {
+ closeWidget();
+ }
+ break;
+ case ActionEvent.ACTION_PERFORMED:
+ Event event = new Event();
+ event.detail = SWT.TRAVERSE_ESCAPE;
+ sendEvent(SWT.Traverse, event);
+ if(event.doit) {
+ close();
+ }
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Slider.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Slider.java
new file mode 100644
index 00000000000..c488a80a4e5
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Slider.java
@@ -0,0 +1,470 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.AWTEvent;
+import java.awt.Container;
+import java.awt.event.AdjustmentEvent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.internal.swing.CSlider;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that represent a range of positive, numeric values.
+ *
+ * At any given moment, a given slider will have a
+ * single 'selection' that is considered to be its
+ * value, which is constrained to be within the range of
+ * values the slider represents (that is, between its
+ * minimum and maximum values).
+ *
+ * Typically, sliders will be made up of five areas:
+ *
+ *
an arrow button for decrementing the value
+ *
a page decrement area for decrementing the value by a larger amount
+ *
a thumb for modifying the value by mouse dragging
+ *
a page increment area for incrementing the value by a larger amount
+ *
an arrow button for incrementing the value
+ *
+ * Based on their style, sliders are either HORIZONTAL
+ * (which have a left facing button for decrementing the value and a
+ * right facing button for incrementing it) or VERTICAL
+ * (which have an upward facing button for decrementing the value
+ * and a downward facing buttons for incrementing it).
+ *
+ * On some platforms, the size of the slider's thumb can be
+ * varied relative to the magnitude of the range of values it
+ * represents (that is, relative to the difference between its
+ * maximum and minimum values). Typically, this is used to
+ * indicate some proportional value such as the ratio of the
+ * visible area of a document to the total amount of space that
+ * it would take to display it. SWT supports setting the thumb
+ * size even if the underlying platform does not, but in this
+ * case the appearance of the slider will not change.
+ *
+ *
+ *
Styles:
+ *
HORIZONTAL, VERTICAL
+ *
Events:
+ *
Selection
+ *
+ *
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @see ScrollBar
+ */
+public class Slider extends Control {
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Slider (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's value changes, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * When widgetSelected is called, the event object detail field contains one of the following values:
+ * 0 - for the end of a drag.
+ * SWT.NONE - for the end of a drag.
+ * SWT.DRAG.
+ * SWT.HOME.
+ * SWT.END.
+ * SWT.ARROW_DOWN.
+ * SWT.ARROW_UP.
+ * SWT.PAGE_DOWN.
+ * SWT.PAGE_UP.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener(listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+Container createHandle () {
+ return (Container)CSlider.Factory.newInstance(this, style);
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed.
+ *
+ * @return the increment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getIncrement () {
+ checkWidget ();
+ return ((CSlider)handle).getUnitIncrement();
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getMaximum () {
+ checkWidget ();
+ return ((CSlider)handle).getMaximum();
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getMinimum () {
+ checkWidget ();
+ return ((CSlider)handle).getMinimum();
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected.
+ *
+ * @return the page increment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getPageIncrement () {
+ checkWidget ();
+ return ((CSlider)handle).getBlockIncrement();
+}
+
+/**
+ * Returns the 'selection', which is the receiver's value.
+ *
+ * @return the selection
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelection () {
+ checkWidget ();
+ return ((CSlider)handle).getValue();
+}
+
+/**
+ * Returns the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values.
+ *
+ * @return the thumb value
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getThumb () {
+ checkWidget ();
+ return ((CSlider)handle).getVisibleAmount();
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's value changes.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed to the argument, which must be at least
+ * one.
+ *
+ * @param value the new increment (must be greater than zero)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setIncrement (int value) {
+ checkWidget ();
+ if (value < 1) return;
+ ((CSlider)handle).setUnitIncrement(value);
+}
+
+/**
+ * Sets the maximum. If this value is negative or less than or
+ * equal to the minimum, the value is ignored. If necessary, first
+ * the thumb and then the selection are adjusted to fit within the
+ * new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMaximum (int value) {
+ checkWidget ();
+ if (value < 0) return;
+ ((CSlider)handle).setMaximum(value);
+}
+
+/**
+ * Sets the minimum value. If this value is negative or greater
+ * than or equal to the maximum, the value is ignored. If necessary,
+ * first the thumb and then the selection are adjusted to fit within
+ * the new range.
+ *
+ * @param value the new minimum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMinimum (int value) {
+ checkWidget ();
+ if (value < 0) return;
+ ((CSlider)handle).setMinimum(value);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected to the argument, which must be at least
+ * one.
+ *
+ * @param value the page increment (must be greater than zero)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setPageIncrement (int value) {
+ checkWidget ();
+ if (value < 1) return;
+ ((CSlider)handle).setBlockIncrement(value);
+}
+
+/**
+ * Sets the 'selection', which is the receiver's
+ * value, to the argument which must be greater than or equal
+ * to zero.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (int value) {
+ checkWidget ();
+ ((CSlider)handle).setValue(value);
+}
+
+/**
+ * Sets the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values. This new
+ * value will be ignored if it is less than one, and will be
+ * clamped if it exceeds the receiver's current range.
+ *
+ * @param value the new thumb value, which must be at least one and not
+ * larger than the size of the current range
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setThumb (int value) {
+ checkWidget ();
+ if (value < 1) return;
+ ((CSlider)handle).setVisibleAmount(value);
+}
+
+/**
+ * Sets the receiver's selection, minimum value, maximum
+ * value, thumb, increment and page increment all at once.
+ *
+ * Note: This is similar to setting the values individually
+ * using the appropriate methods, but may be implemented in a
+ * more efficient fashion on some platforms.
+ *
+ *
+ * @param selection the new selection value
+ * @param minimum the new minimum value
+ * @param maximum the new maximum value
+ * @param thumb the new thumb value
+ * @param increment the new increment value
+ * @param pageIncrement the new pageIncrement value
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) {
+ checkWidget ();
+ if (minimum < 0) return;
+ if (maximum < 0) return;
+ if (thumb < 1) return;
+ if (increment < 1) return;
+ if (pageIncrement < 1) return;
+ CSlider cSlider = (CSlider)handle;
+ cSlider.setValues(selection, thumb, minimum, maximum);
+ cSlider.setUnitIncrement(increment);
+ cSlider.setBlockIncrement(increment);
+}
+
+public void processEvent(AWTEvent e) {
+ int id = e.getID();
+ switch(id) {
+ case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED: if(!hooks(SWT.Selection)) { super.processEvent(e); return; } break;
+ default: { super.processEvent(e); return; }
+ }
+ if(isDisposed()) {
+ super.processEvent(e);
+ return;
+ }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ switch(id) {
+ case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED:
+ Event event = new Event ();
+ event.detail = SWT.DRAG;
+ switch(((AdjustmentEvent)e).getAdjustmentType()) {
+ case AdjustmentEvent.BLOCK_DECREMENT:
+ event.detail = SWT.PAGE_DOWN;
+ break;
+ case AdjustmentEvent.BLOCK_INCREMENT:
+ event.detail = SWT.PAGE_UP;
+ break;
+ case AdjustmentEvent.UNIT_DECREMENT:
+ event.detail = SWT.ARROW_DOWN;
+ break;
+ case AdjustmentEvent.UNIT_INCREMENT:
+ event.detail = SWT.ARROW_UP;
+ break;
+ }
+ sendEvent (SWT.Selection, event);
+ break;
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Spinner.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Spinner.java
new file mode 100644
index 00000000000..7f79f2d1c4f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Spinner.java
@@ -0,0 +1,1051 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.Container;
+import java.util.EventObject;
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.DocumentEvent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.swing.CSpinner;
+import org.eclipse.swt.internal.swing.TextFilterEvent;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that allow the user to enter and modify numeric
+ * values.
+ *
+ *
+ *
Styles:
+ *
READ_ONLY, WRAP
+ *
Events:
+ *
Selection, Modify
+ *
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @since 3.1
+ */
+public class Spinner extends Composite {
+// boolean ignoreModify;
+ int pageIncrement;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#READ_ONLY
+ * @see SWT#WRAP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Spinner (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+static int checkStyle (int style) {
+ /*
+ * Even though it is legal to create this widget
+ * with scroll bars, they serve no useful purpose
+ * because they do not automatically scroll the
+ * widget's client area. The fix is to clear
+ * the SWT style.
+ */
+ return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void createHandleInit() {
+ super.createHandleInit();
+ state &= ~(CANVAS | THEME_BACKGROUND);
+}
+
+protected Container createHandle () {
+ return (Container)CSpinner.Factory.newInstance(this, style);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is modified, by sending
+ * it one of the messages defined in the ModifyListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ModifyListener
+ * @see #removeModifyListener
+ */
+public void addModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Modify, typedListener);
+}
+
+/**
+ * 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 SelectionListener
+ * interface.
+ *
+ * widgetSelected is not called for texts.
+ * widgetDefaultSelected is typically called when ENTER is pressed in a single-line text.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is verified, by sending
+ * it one of the messages defined in the VerifyListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see VerifyListener
+ * @see #removeVerifyListener
+ */
+void addVerifyListener (VerifyListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Verify, typedListener);
+}
+
+//public Point computeSize (int wHint, int hHint, boolean changed) {
+// checkWidget ();
+// int width = 0, height = 0;
+// if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
+// int newFont, oldFont = 0;
+// int hDC = OS.GetDC (hwndText);
+// newFont = OS.SendMessage (hwndText, OS.WM_GETFONT, 0, 0);
+// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+// TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA ();
+// OS.GetTextMetrics (hDC, tm);
+// height = tm.tmHeight;
+// RECT rect = new RECT ();
+// int [] max = new int [1];
+// OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, max);
+// TCHAR buffer = new TCHAR (getCodePage (), String.valueOf (max [0]), false);
+// int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX;
+// OS.DrawText (hDC, buffer, buffer.length (), rect, flags);
+// width = rect.right - rect.left;
+// if (newFont != 0) OS.SelectObject (hDC, oldFont);
+// OS.ReleaseDC (hwndText, hDC);
+// }
+// if (width == 0) width = DEFAULT_WIDTH;
+// if (height == 0) height = DEFAULT_HEIGHT;
+// if (wHint != SWT.DEFAULT) width = wHint;
+// if (hHint != SWT.DEFAULT) height = hHint;
+// Rectangle trim = computeTrim (0, 0, width, height);
+// if (hHint == SWT.DEFAULT) {
+// trim.height = Math.max (trim.height, OS.GetSystemMetrics (OS.SM_CYVSCROLL));
+// }
+// return new Point (trim.width, trim.height);
+//}
+//
+//public Rectangle computeTrim (int x, int y, int width, int height) {
+// checkWidget ();
+//
+// /* Get the trim of the text control */
+// RECT rect = new RECT ();
+// OS.SetRect (rect, x, y, x + width, y + height);
+// int bits0 = OS.GetWindowLong (hwndText, OS.GWL_STYLE);
+// int bits1 = OS.GetWindowLong (hwndText, OS.GWL_EXSTYLE);
+// OS.AdjustWindowRectEx (rect, bits0, false, bits1);
+// width = rect.right - rect.left;
+// height = rect.bottom - rect.top;
+//
+// /*
+// * The preferred height of a single-line text widget
+// * has been hand-crafted to be the same height as
+// * the single-line text widget in an editable combo
+// * box.
+// */
+// int margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
+// x -= margins & 0xFFFF;
+// width += (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF);
+// if ((style & SWT.BORDER) != 0) {
+// x -= 1;
+// y -= 1;
+// width += 2;
+// height += 2;
+// }
+// width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+// return new Rectangle (x, y, width, height);
+//}
+
+public Point computeSize (int wHint, int hHint, boolean changed) {
+ Point p = super.computeSize(wHint, hHint, changed);
+ return new Point(p.x, handle.getPreferredSize().height);
+}
+
+/**
+ * Copies the selected text.
+ *
+ * The current selection is copied to the clipboard.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * The current selection is first copied to the
+ * clipboard and then deleted from the widget.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void cut () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return;
+ ((CSpinner)handle).cut();
+}
+
+/**
+ * Returns the number of decimal places used by the receiver.
+ *
+ * @return the digits
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getDigits () {
+ checkWidget ();
+ return ((CSpinner)handle).getDigitCount();
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down arrows are pressed.
+ *
+ * @return the increment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getIncrement () {
+ checkWidget ();
+ return ((CSpinner)handle).getStepSize();
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getMaximum () {
+ checkWidget ();
+ return ((CSpinner)handle).getMaximum();
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getMinimum () {
+ checkWidget ();
+ return ((CSpinner)handle).getMinimum();
+}
+
+/**
+ * Returns the amount that the receiver's position will be
+ * modified by when the page up/down keys are pressed.
+ *
+ * @return the page increment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getPageIncrement () {
+ checkWidget ();
+ return pageIncrement;
+}
+
+/**
+ * Returns the selection, which is the receiver's position.
+ *
+ * @return the selection
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelection () {
+ checkWidget ();
+ return ((CSpinner)handle).getSelectedValue();
+}
+
+/**
+ * Pastes text from clipboard.
+ *
+ * The selected text is deleted from the widget
+ * and new text inserted from the clipboard.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void paste () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return;
+ ((CSpinner)handle).paste();
+}
+
+//void releaseHandle () {
+// super.releaseHandle ();
+// hwndText = hwndUpDown = 0;
+//}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's text is modified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ModifyListener
+ * @see #addModifyListener
+ */
+public void removeModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Modify, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is verified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see VerifyListener
+ * @see #addVerifyListener
+ */
+void removeVerifyListener (VerifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Verify, listener);
+}
+
+//boolean sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) {
+// if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
+// return false;
+// }
+// if ((style & SWT.READ_ONLY) != 0) return true;
+// if (type != SWT.KeyDown) return true;
+// if (msg != OS.WM_CHAR && msg != OS.WM_KEYDOWN && msg != OS.WM_IME_CHAR) {
+// return true;
+// }
+// if (event.character == 0) return true;
+//// if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return true;
+// char key = event.character;
+// int stateMask = event.stateMask;
+//
+// /*
+// * Disable all magic keys that could modify the text
+// * and don't send events when Alt, Shift or Ctrl is
+// * pressed.
+// */
+// switch (msg) {
+// case OS.WM_CHAR:
+// if (key != 0x08 && key != 0x7F && key != '\r' && key != '\t' && key != '\n') break;
+// // FALL THROUGH
+// case OS.WM_KEYDOWN:
+// if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) != 0) return false;
+// break;
+// }
+//
+// /*
+// * If the left button is down, the text widget refuses the character.
+// */
+// if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
+// return true;
+// }
+//
+// /* Verify the character */
+// String oldText = "";
+// int [] start = new int [1], end = new int [1];
+// OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+// switch (key) {
+// case 0x08: /* Bs */
+// if (start [0] == end [0]) {
+// if (start [0] == 0) return true;
+// start [0] = start [0] - 1;
+// if (OS.IsDBLocale) {
+// int [] newStart = new int [1], newEnd = new int [1];
+// OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
+// OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd);
+// if (start [0] != newStart [0]) start [0] = start [0] - 1;
+// }
+// start [0] = Math.max (start [0], 0);
+// }
+// break;
+// case 0x7F: /* Del */
+// if (start [0] == end [0]) {
+// int length = OS.GetWindowTextLength (hwndText);
+// if (start [0] == length) return true;
+// end [0] = end [0] + 1;
+// if (OS.IsDBLocale) {
+// int [] newStart = new int [1], newEnd = new int [1];
+// OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
+// OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd);
+// if (end [0] != newEnd [0]) end [0] = end [0] + 1;
+// }
+// end [0] = Math.min (end [0], length);
+// }
+// break;
+// case '\r': /* Return */
+// return true;
+// default: /* Tab and other characters */
+// if (key != '\t' && key < 0x20) return true;
+// oldText = new String (new char [] {key});
+// break;
+// }
+// String newText = verifyText (oldText, start [0], end [0], event);
+// if (newText == null) return false;
+// if (newText == oldText) return true;
+// TCHAR buffer = new TCHAR (getCodePage (), newText, true);
+// OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
+// OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
+// return false;
+//}
+
+
+/**
+ * Sets the number of decimal places used by the receiver.
+ *
+ * The digit setting is used to allow for floating point values in the receiver.
+ * For example, to set the selection to a floating point value of 1.37 call setDigits() with
+ * a value of 2 and setSelection() with a value of 137. Similarly, if getDigits() has a value
+ * of 2 and getSelection() returns 137 this should be interpreted as 1.37. This applies to all
+ * numeric APIs.
+ *
+ *
+ * @param value the new digits (must be greater than or equal to zero)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the value is less than zero
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setDigits (int value) {
+ checkWidget ();
+ if (value < 0) error (SWT.ERROR_INVALID_ARGUMENT);
+ ((CSpinner)handle).setDigitCount(value);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the up/down arrows are pressed to
+ * the argument, which must be at least one.
+ *
+ * @param value the new increment (must be greater than zero)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setIncrement (int value) {
+ checkWidget ();
+ if (value < 1) return;
+ ((CSpinner)handle).setStepSize(value);
+}
+
+/**
+ * Sets the maximum value that the receiver will allow. This new
+ * value will be ignored if it is not greater than the receiver's current
+ * minimum value. If the new maximum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMaximum (int value) {
+ checkWidget ();
+ if (value < 0) return;
+ ((CSpinner)handle).setMaximum(value);
+}
+
+/**
+ * Sets the minimum value that the receiver will allow. This new
+ * value will be ignored if it is negative or is not less than the receiver's
+ * current maximum value. If the new minimum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new minimum, which must be nonnegative and less than the current maximum
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMinimum (int value) {
+ checkWidget ();
+ if (value < 0) return;
+ ((CSpinner)handle).setMinimum(value);
+}
+
+/**
+ * Sets the amount that the receiver's position will be
+ * modified by when the page up/down keys are pressed
+ * to the argument, which must be at least one.
+ *
+ * @param value the page increment (must be greater than zero)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setPageIncrement (int value) {
+ checkWidget ();
+ if (value < 1) return;
+ pageIncrement = value;
+}
+
+/**
+ * Sets the selection, which is the receiver's
+ * position, to the argument. If the argument is not within
+ * the range specified by minimum and maximum, it will be
+ * adjusted to fall within this range.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (int value) {
+ checkWidget ();
+ ((CSpinner)handle).setSelectedValue(value);
+}
+
+/**
+ * Sets the receiver's selection, minimum value, maximum
+ * value, digits, increment and page increment all at once.
+ *
+ * Note: This is similar to setting the values individually
+ * using the appropriate methods, but may be implemented in a
+ * more efficient fashion on some platforms.
+ *
+ *
+ * @param selection the new selection value
+ * @param minimum the new minimum value
+ * @param maximum the new maximum value
+ * @param digits the new digits value
+ * @param increment the new increment value
+ * @param pageIncrement the new pageIncrement value
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setValues (int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) {
+ checkWidget ();
+ if (minimum < 0) return;
+ if (maximum <= minimum) return;
+ if (digits < 0) return;
+ if (increment < 1) return;
+ if (pageIncrement < 1) return;
+ selection = Math.min (Math.max (minimum, selection), maximum);
+ setIncrement (increment);
+ setPageIncrement(pageIncrement);
+ setDigits(digits);
+ setSelection (selection);
+}
+
+//String verifyText (String string, int start, int end, Event keyEvent) {
+// Event event = new Event ();
+// event.text = string;
+// event.start = start;
+// event.end = end;
+// if (keyEvent != null) {
+// event.character = keyEvent.character;
+// event.keyCode = keyEvent.keyCode;
+// event.stateMask = keyEvent.stateMask;
+// }
+// int index = 0;
+// while (index < string.length ()) {
+// if (!Character.isDigit (string.charAt (index))) break;
+// index++;
+// }
+// event.doit = index == string.length ();
+// if (OS.IsDBLocale) {
+// event.start = mbcsToWcsPos (start);
+// event.end = mbcsToWcsPos (end);
+// }
+// sendEvent (SWT.Verify, event);
+// if (!event.doit || isDisposed ()) return null;
+// return event.text;
+//}
+
+//int windowProc (int hwnd, int msg, int wParam, int lParam) {
+// if (hwnd == hwndText || hwnd == hwndUpDown) {
+// LRESULT result = null;
+// switch (msg) {
+// /* Keyboard messages */
+// case OS.WM_CHAR: result = wmChar (hwnd, wParam, lParam); break;
+// case OS.WM_IME_CHAR: result = wmIMEChar (hwnd, wParam, lParam); break;
+// case OS.WM_KEYDOWN: result = wmKeyDown (hwnd, wParam, lParam); break;
+// case OS.WM_KEYUP: result = wmKeyUp (hwnd, wParam, lParam); break;
+// case OS.WM_SYSCHAR: result = wmSysChar (hwnd, wParam, lParam); break;
+// case OS.WM_SYSKEYDOWN: result = wmSysKeyDown (hwnd, wParam, lParam); break;
+// case OS.WM_SYSKEYUP: result = wmSysKeyUp (hwnd, wParam, lParam); break;
+//
+// /* Mouse Messages */
+// case OS.WM_LBUTTONDBLCLK: result = wmLButtonDblClk (hwnd, wParam, lParam); break;
+// case OS.WM_LBUTTONDOWN: result = wmLButtonDown (hwnd, wParam, lParam); break;
+// case OS.WM_LBUTTONUP: result = wmLButtonUp (hwnd, wParam, lParam); break;
+// case OS.WM_MBUTTONDBLCLK: result = wmMButtonDblClk (hwnd, wParam, lParam); break;
+// case OS.WM_MBUTTONDOWN: result = wmMButtonDown (hwnd, wParam, lParam); break;
+// case OS.WM_MBUTTONUP: result = wmMButtonUp (hwnd, wParam, lParam); break;
+// case OS.WM_MOUSEHOVER: result = wmMouseHover (hwnd, wParam, lParam); break;
+// case OS.WM_MOUSELEAVE: result = wmMouseLeave (hwnd, wParam, lParam); break;
+// case OS.WM_MOUSEMOVE: result = wmMouseMove (hwnd, wParam, lParam); break;
+//// case OS.WM_MOUSEWHEEL: result = wmMouseWheel (hwnd, wParam, lParam); break;
+// case OS.WM_RBUTTONDBLCLK: result = wmRButtonDblClk (hwnd, wParam, lParam); break;
+// case OS.WM_RBUTTONDOWN: result = wmRButtonDown (hwnd, wParam, lParam); break;
+// case OS.WM_RBUTTONUP: result = wmRButtonUp (hwnd, wParam, lParam); break;
+// case OS.WM_XBUTTONDBLCLK: result = wmXButtonDblClk (hwnd, wParam, lParam); break;
+// case OS.WM_XBUTTONDOWN: result = wmXButtonDown (hwnd, wParam, lParam); break;
+// case OS.WM_XBUTTONUP: result = wmXButtonUp (hwnd, wParam, lParam); break;
+//
+// /* Focus Messages */
+// case OS.WM_SETFOCUS: result = wmSetFocus (hwnd, wParam, lParam); break;
+// case OS.WM_KILLFOCUS: result = wmKillFocus (hwnd, wParam, lParam); break;
+//
+// /* Paint messages */
+// case OS.WM_PAINT: result = wmPaint (hwnd, wParam, lParam); break;
+//
+// /* Menu messages */
+// case OS.WM_CONTEXTMENU: result = wmContextMenu (hwnd, wParam, lParam);
+//
+// /* Clipboard messages */
+// case OS.WM_CLEAR:
+// case OS.WM_CUT:
+// case OS.WM_PASTE:
+// case OS.WM_UNDO:
+// case OS.EM_UNDO:
+// if (hwnd == hwndText) {
+// result = wmClipboard (hwnd, msg, wParam, lParam);
+// }
+// break;
+// }
+// if (result != null) return result.value;
+// return callWindowProc (hwnd, msg, wParam, lParam);
+// }
+// return super.windowProc (hwnd, msg, wParam, lParam);
+//}
+
+//LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+// LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+// if (result != null) return result;
+// drawBackground (wParam);
+// return LRESULT.ONE;
+//}
+//
+//LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+// return null;
+//}
+//
+//LRESULT WM_SETFOCUS (int wParam, int lParam) {
+// OS.SetFocus (hwndText);
+// return null;
+//}
+//
+//LRESULT WM_SETFONT (int wParam, int lParam) {
+// LRESULT result = super.WM_SETFONT (wParam, lParam);
+// if (result != null) return result;
+// OS.SendMessage (hwndText, OS.WM_SETFONT, wParam, lParam);
+// return result;
+//}
+//
+//LRESULT WM_SIZE (int wParam, int lParam) {
+// LRESULT result = super.WM_SIZE (wParam, lParam);
+// if (isDisposed ()) return result;
+// int width = lParam & 0xFFFF, height = lParam >> 16;
+// int upDownWidth = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+// int textWidth = width - upDownWidth;
+// int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+// SetWindowPos (hwndText, 0, 0, 0, textWidth, height, flags);
+// SetWindowPos (hwndUpDown, 0, textWidth, 0, upDownWidth, height, flags);
+// return result;
+//}
+//
+//LRESULT wmChar (int hwnd, int wParam, int lParam) {
+// LRESULT result = super.wmChar (hwnd, wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Feature in Windows. For some reason, when the
+// * widget is a single line text widget, when the
+// * user presses tab, return or escape, Windows beeps.
+// * The fix is to look for these keys and not call
+// * the window proc.
+// */
+// switch (wParam) {
+// case SWT.CR:
+// int value = getSelectionText ();
+// setSelection (value, true);
+// postEvent (SWT.DefaultSelection);
+// // FALL THROUGH
+// case SWT.TAB:
+// case SWT.ESC: return LRESULT.ZERO;
+// }
+// return result;
+//}
+//
+//LRESULT wmClipboard (int hwndText, int msg, int wParam, int lParam) {
+// if ((style & SWT.READ_ONLY) != 0) return null;
+//// if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
+// boolean call = false;
+// int [] start = new int [1], end = new int [1];
+// String oldText = null, newText = null;
+// switch (msg) {
+// case OS.WM_CLEAR:
+// case OS.WM_CUT:
+// OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+// if (start [0] != end [0]) {
+// newText = "";
+// call = true;
+// }
+// break;
+// case OS.WM_PASTE:
+// OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+// newText = getClipboardText ();
+// break;
+// case OS.EM_UNDO:
+// case OS.WM_UNDO:
+// if (OS.SendMessage (hwndText, OS.EM_CANUNDO, 0, 0) != 0) {
+// ignoreModify = true;
+// OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+// if (OS.IsDBLocale) {
+// start [0] = mbcsToWcsPos (start [0]);
+// end [0] = mbcsToWcsPos (end [0]);
+// }
+// OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+// int length = OS.GetWindowTextLength (hwndText);
+// if (length != 0 && start [0] != end [0]) {
+// TCHAR buffer = new TCHAR (getCodePage (), length + 1);
+// OS.GetWindowText (hwndText, buffer, length + 1);
+// newText = buffer.toString (start [0], end [0] - start [0]);
+// } else {
+// newText = "";
+// }
+// OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+// ignoreModify = false;
+// }
+// break;
+// }
+// if (newText != null && !newText.equals (oldText)) {
+// oldText = newText;
+// newText = verifyText (newText, start [0], end [0], null);
+// if (newText == null) return LRESULT.ZERO;
+// if (!newText.equals (oldText)) {
+// if (call) {
+// OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+// }
+// TCHAR buffer = new TCHAR (getCodePage (), newText, true);
+// if (msg == OS.WM_SETTEXT) {
+// int hHeap = OS.GetProcessHeap ();
+// int byteCount = buffer.length () * TCHAR.sizeof;
+// int pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+// OS.MoveMemory (pszText, buffer, byteCount);
+// int code = OS.CallWindowProc (EditProc, hwndText, msg, wParam, pszText);
+// OS.HeapFree (hHeap, 0, pszText);
+// return new LRESULT (code);
+// } else {
+// OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
+// return LRESULT.ZERO;
+// }
+// }
+// }
+// return null;
+//}
+//
+//LRESULT wmCommandChild (int wParam, int lParam) {
+// int code = wParam >> 16;
+// switch (code) {
+// case OS.EN_CHANGE:
+// if (ignoreModify) break;
+// sendEvent (SWT.Modify);
+// if (isDisposed ()) return LRESULT.ZERO;
+// break;
+// }
+// return super.wmCommandChild (wParam, lParam);
+//}
+//
+//LRESULT wmKeyDown (int hwnd, int wParam, int lParam) {
+// LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
+// if (result != null) return result;
+//
+// /* Increment the value */
+// UDACCEL udaccel = new UDACCEL ();
+// OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 1, udaccel);
+// int delta = 0;
+// switch (wParam) {
+// case OS.VK_UP: delta = udaccel.nInc; break;
+// case OS.VK_DOWN: delta = -udaccel.nInc; break;
+// case OS.VK_PRIOR: delta = pageIncrement; break;
+// case OS.VK_NEXT: delta = -pageIncrement; break;
+// }
+// if (delta != 0) {
+// int value = getSelectionText ();
+// int newValue = value + delta;
+// int [] max = new int [1], min = new int [1];
+// OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
+// if ((style & SWT.WRAP) != 0) {
+// if (newValue < min [0]) newValue = max [0];
+// if (newValue > max [0]) newValue = min [0];
+// }
+// newValue = Math.min (Math.max (min [0], newValue), max [0]);
+// if (value != newValue) setSelection (newValue, true);
+// }
+//
+// /* Stop the edit control from moving the caret */
+// switch (wParam) {
+// case OS.VK_UP:
+// case OS.VK_DOWN:
+// return LRESULT.ZERO;
+// }
+// return result;
+//}
+//
+//LRESULT wmKillFocus (int hwnd, int wParam, int lParam) {
+// int value = getSelectionText ();
+// setSelection (value, true);
+// return super.wmKillFocus (hwnd, wParam, lParam);
+//}
+//
+//LRESULT wmScrollChild (int wParam, int lParam) {
+// int code = wParam & 0xFFFF;
+// switch (code) {
+// case OS.SB_THUMBPOSITION:
+// postEvent (SWT.Selection);
+// break;
+// }
+// return super.wmScrollChild (wParam, lParam);
+//}
+
+String verifyText (String string, int start, int end, Event keyEvent) {
+ Event event = new Event ();
+ event.text = string;
+ event.start = start;
+ event.end = end;
+ if (keyEvent != null) {
+ event.character = keyEvent.character;
+ event.keyCode = keyEvent.keyCode;
+ event.stateMask = keyEvent.stateMask;
+ }
+ sendEvent (SWT.Verify, event);
+ if (!event.doit || isDisposed ()) return null;
+ return event.text;
+}
+
+public void processEvent(EventObject e) {
+ if(e instanceof ChangeEvent) {
+ if(!hooks(SWT.Selection)) { super.processEvent(e); return; }
+ } else if(e instanceof TextFilterEvent) {
+ if(!hooks(SWT.Verify)) { super.processEvent(e); return; }
+ } else { super.processEvent(e); return; }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ if(e instanceof ChangeEvent) {
+ sendEvent (SWT.Selection);
+ } else if(e instanceof TextFilterEvent) {
+ TextFilterEvent filterEvent = (TextFilterEvent)e;
+ filterEvent.setText(verifyText(filterEvent.getText(), filterEvent.getStart(), filterEvent.getStart() + filterEvent.getEnd(), createKeyEvent(filterEvent.getKeyEvent())));
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+public void processEvent(DocumentEvent e) {
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ return;
+ }
+ try {
+ sendEvent(SWT.Modify, new Event());
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabFolder.java
new file mode 100644
index 00000000000..d185119b84b
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabFolder.java
@@ -0,0 +1,504 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.Component;
+import java.awt.Container;
+import java.util.ArrayList;
+import java.util.EventObject;
+
+import javax.swing.event.ChangeEvent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.swing.CControl;
+import org.eclipse.swt.internal.swing.CTabFolder;
+import org.eclipse.swt.internal.swing.CTabItem;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+
+/**
+ * Instances of this class implement the notebook user interface
+ * metaphor. It allows the user to select a notebook page from
+ * set of pages.
+ *
+ * The item children that may be added to instances of this class
+ * must be of type TabItem.
+ * Control children are created and then set into a
+ * tab item using TabItem#setControl.
+ *
+ * Note that although this class is a subclass of Composite,
+ * it does not make sense to set a layout on it.
+ *
+ *
+ *
Styles:
+ *
TOP, BOTTOM
+ *
Events:
+ *
Selection
+ *
+ *
+ * Note: Only one of the styles TOP and BOTTOM may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+public class TabFolder extends Composite {
+
+ ArrayList itemList;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ * When widgetSelected is called, the item field of the event object is valid.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener(listener);
+ addListener(SWT.Selection,typedListener);
+ addListener(SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ style = checkBits (style, SWT.TOP, SWT.BOTTOM, 0, 0, 0, 0);
+ return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+boolean autoAddChildren() {
+ return false;
+}
+
+void createHandleInit() {
+ super.createHandleInit();
+ state &= ~(CANVAS | THEME_BACKGROUND);
+}
+
+protected Container createHandle () {
+ return (Container)CTabFolder.Factory.newInstance(this, style);
+}
+
+void createItem (TabItem item, int index) {
+ int count = getItemCount();
+ if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+ itemList.add(index, item);
+ handle.add(item.handle, index);
+ handle.invalidate();
+ handle.validate();
+ /*
+ * Send a selection event when the item that is added becomes
+ * the new selection. This only happens when the first item
+ * is added.
+ */
+// if (getItemCount() == 1) {
+// Event event = new Event ();
+// event.item = item;
+// sendEvent (SWT.Selection, event);
+// // the widget could be destroyed at this point
+// }
+}
+
+void createWidget () {
+ super.createWidget ();
+ itemList = new ArrayList();
+}
+
+void destroyItem (TabItem item) {
+ int index = indexOf(item);
+ if(index != -1) {
+ handle.remove(item.handle);
+ handle.invalidate();
+ handle.validate();
+ handle.repaint();
+ }
+ itemList = null;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TabItem getItem (int index) {
+ checkWidget ();
+ int count = getItemCount();
+ if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+ return (TabItem)itemList.get(index);
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemCount () {
+ checkWidget ();
+ return itemList.size();
+}
+
+/**
+ * Returns an array of TabItems which are the items
+ * in the receiver.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TabItem [] getItems () {
+ checkWidget ();
+ return (TabItem[])itemList.toArray(new TabItem [0]);
+}
+
+/**
+ * Returns an array of TabItems that are currently
+ * selected in the receiver. An empty array indicates that no
+ * items are selected.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ *
+ * @return an array representing the selection
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TabItem [] getSelection () {
+ checkWidget ();
+ int index = ((CTabFolder)handle).getSelectedIndex();
+ if (index == -1) return new TabItem [0];
+ return new TabItem [] {(TabItem)itemList.get(index)};
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver, or -1 if no item is selected.
+ *
+ * @return the index of the selected item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelectionIndex () {
+ checkWidget ();
+ return ((CTabFolder)handle).getSelectedIndex();
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int indexOf (TabItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int count = getItemCount();
+ for (int i=0; i
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Sets the receiver's selection to the given item.
+ * The current selected is first cleared, then the new item is
+ * selected.
+ *
+ * @param item the item to select
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the item is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setSelection (TabItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSelection (new TabItem [] {item});
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selected is first cleared, then the new items are
+ * selected.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the items array is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (TabItem [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (items.length == 0) {
+ ((CTabFolder)handle).setSelectedIndex(-1);
+ } else {
+ ((CTabFolder)handle).setSelectedIndex(indexOf (items [items.length-1]));
+ }
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already selected, it remains selected.
+ * The current selection is first cleared, then the new items are
+ * selected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (int index) {
+ checkWidget ();
+ int count = getItemCount();
+ if (!(0 <= index && index < count)) return;
+ ((CTabFolder)handle).setSelectedIndex(index);
+}
+
+Point minimumSize (int wHint, int hHint, boolean changed) {
+ java.awt.Dimension size = handle.getPreferredSize();
+ return new Point(size.width, size.height);
+}
+
+public void processEvent(EventObject e) {
+ if(e instanceof ChangeEvent) {
+ if(!hooks(SWT.Selection)) { super.processEvent(e); return; }
+ } else { super.processEvent(e); return; }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ if(e instanceof ChangeEvent) {
+// ChangeEvent ce = (ChangeEvent)e;
+ int index = ((CTabFolder)handle).getSelectedIndex();
+ Event event = new Event();
+ if(index >= 0) {
+ event.item = (Widget)itemList.get(index);
+ }
+ sendEvent(SWT.Selection, event);
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabItem.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabItem.java
new file mode 100644
index 00000000000..af5326388dd
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TabItem.java
@@ -0,0 +1,306 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+
+import javax.swing.ImageIcon;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.internal.swing.CTabFolder;
+import org.eclipse.swt.internal.swing.CTabItem;
+import org.eclipse.swt.internal.swing.Utils;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * corresponding to a tab for a page in a tab folder.
+ *
+ *
Styles:
+ *
(none)
+ *
Events:
+ *
(none)
+ *
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+
+public class TabItem extends Item {
+ TabFolder parent;
+ Control control;
+ String toolTipText;
+ Container handle;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a TabFolder) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TabItem (TabFolder parent, int style) {
+ super (parent, style);
+ this.parent = parent;
+ handle = createHandle();
+ parent.createItem (this, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a TabFolder), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TabItem (TabFolder parent, int style, int index) {
+ super (parent, style);
+ this.parent = parent;
+ handle = createHandle();
+ parent.createItem (this, index);
+}
+
+Container createHandle () {
+ return (Container)CTabItem.Factory.newInstance(this, style);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+/**
+ * Returns the control that is used to fill the client area of
+ * the tab folder when the user selects the tab item. If no
+ * control has been set, return null.
+ *
+ * @return the control
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Control getControl () {
+ checkWidget();
+ return control;
+}
+
+/**
+ * Returns the receiver's parent, which must be a TabFolder.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TabFolder getParent () {
+ checkWidget();
+ return parent;
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getToolTipText () {
+ checkWidget();
+ return toolTipText;
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ parent = null;
+}
+
+void releaseParent () {
+ super.releaseParent ();
+ int index = parent.indexOf (this);
+ if (index == parent.getSelectionIndex ()) {
+ if (control != null) control.setVisible (false);
+ }
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ control = null;
+}
+
+/**
+ * Sets the control that is used to fill the client area of
+ * the tab folder when the user selects the tab item.
+ *
+ * @param control the new control (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the control has been disposed
+ *
ERROR_INVALID_PARENT - if the control is not in the same widget tree
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setControl (Control control) {
+ checkWidget();
+ if (control != null) {
+ if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+ }
+ if (this.control != null && this.control.isDisposed ()) {
+ this.control = null;
+ handle.remove(this.control.handle);
+ }
+ this.control = control;
+ if(control != null) {
+ handle.add(control.handle, BorderLayout.CENTER);
+ }
+ handle.invalidate();
+ handle.validate();
+ handle.repaint();
+}
+
+public void setImage (Image image) {
+ checkWidget();
+ int index = parent.indexOf (this);
+ if (index == -1) return;
+ super.setImage (image);
+ ((CTabFolder)parent.handle).setIconAt(index, new ImageIcon(image.handle));
+}
+
+/**
+ * Sets the receiver's text. The string may include
+ * the mnemonic character.
+ *
+ *
+ * Mnemonics are indicated by an '&' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasised in a platform specific
+ * manner. The mnemonic indicator character '&' can be
+ * escaped by doubling it in the string, causing a single
+ * '&' to be displayed.
+ *
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ */
+public void setText (String string) {
+ checkWidget();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (string.equals (text)) return;
+ int index = parent.indexOf (this);
+ if (index == -1) return;
+ super.setText (string);
+ int mnemonicIndex = findMnemonicIndex(string);
+ char mnemonic;
+ CTabFolder cTabFolder = (CTabFolder)parent.handle;
+ if(mnemonicIndex < 0) {
+ mnemonic = '\0';
+ cTabFolder.setTitleAt(index, string);
+ } else {
+ mnemonic = string.charAt(mnemonicIndex);
+ cTabFolder.setTitleAt(index, string.substring(0, mnemonicIndex - 1) + string.substring(mnemonicIndex));
+ }
+ cTabFolder.setMnemonicAt(index, mnemonic);
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setToolTipText (String string) {
+ checkWidget();
+ toolTipText = string;
+ ((CTabFolder)parent.handle).setToolTipTextAt(parent.indexOf(this), Utils.convertStringToHTML(toolTipText));
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Table.java
new file mode 100644
index 00000000000..14fb2cb76c4
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Table.java
@@ -0,0 +1,3479 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.AWTEvent;
+import java.awt.Container;
+import java.awt.event.ItemEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.EventObject;
+
+import javax.swing.DefaultListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableColumnModel;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.swing.CTable;
+import org.eclipse.swt.internal.swing.CTableItem;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+import org.eclipse.swt.internal.swing.CTable.CellPaintEvent;
+
+/**
+ * Instances of this class implement a selectable user interface
+ * object that displays a list of images and strings and issues
+ * notification when selected.
+ *
+ * The item children that may be added to instances of this class
+ * must be of type TableItem.
+ *
+ * Style VIRTUAL is used to create a Table whose
+ * TableItems are to be populated by the client on an on-demand basis
+ * instead of up-front. This can provide significant performance improvements for
+ * tables that are very large or for which TableItem population is
+ * expensive (for example, retrieving values from an external source).
+ *
+ * Here is an example of using a Table with style VIRTUAL:
+ *
+ * Note: Only one of the styles SINGLE, and MULTI may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+
+public class Table extends Composite {
+ ArrayList itemList;
+ ArrayList columnList;
+// ImageList imageList;
+ TableItem currentItem;
+ int lastIndexOf;
+// int lastWidth;
+// boolean customDraw, dragStarted, fixScrollWidth, mouseDown, tipRequested;
+// boolean ignoreActivate, ignoreSelect, ignoreShrink, ignoreResize;
+ static final int INSET = 4;
+ static final int GRID_WIDTH = 1;
+ static final int HEADER_MARGIN = 10;
+
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#CHECK
+ * @see SWT#FULL_SELECTION
+ * @see SWT#HIDE_SELECTION
+ * @see SWT#VIRTUAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Table (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+void adjustColumnWidth() {
+ // Could be more efficient. Should post, with coalescing?
+ if(getColumnCount() == 0) {
+ CTable cTable = (CTable)handle;
+ cTable.getColumnModel().getColumn(0).setPreferredWidth(cTable.getPreferredColumnWidth(0));
+ }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's selection changes, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * When widgetSelected is called, the item field of the event object is valid.
+ * If the receiver has SWT.CHECK style set and the check selection changes,
+ * the event object detail field contains the value SWT.CHECK.
+ * widgetDefaultSelected is typically called when an item is double-clicked.
+ * The item field of the event object is valid for default selection, but the detail field is not used.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+boolean checkData (TableItem item, boolean redraw) {
+ if ((style & SWT.VIRTUAL) == 0) return true;
+ return checkData (item, indexOf (item), redraw);
+}
+
+boolean checkData (TableItem item, int index, boolean redraw) {
+ if ((style & SWT.VIRTUAL) == 0) return true;
+ if (!item.cached) {
+ item.cached = true;
+ Event event = new Event ();
+ event.item = item;
+ event.index = index;
+ currentItem = item;
+ sendEvent (SWT.SetData, event);
+ //widget could be disposed at this point
+ currentItem = null;
+ if (isDisposed () || item.isDisposed ()) return false;
+// if (redraw) {
+// if (!setScrollWidth (item, false)) {
+// item.redraw ();
+// }
+// }
+ }
+ return true;
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+/**
+ * Clears the item at the given zero-relative index in the receiver.
+ * The text, icon and other attributes of the item are set to the default
+ * value. If the table was created with the SWT.VIRTUAL style,
+ * these attributes are requested again as needed.
+ *
+ * @param index the index of the item to clear
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clear (int index) {
+ checkWidget ();
+ TableItem item = (TableItem)itemList.get(index);
+ if(item != null) {
+ item.clear();
+ }
+ handle.repaint();
+// int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+// if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+// TableItem item = items [index];
+// if (item != null) {
+// if (item != currentItem) item.clear ();
+// /*
+// * Bug in Windows. Despite the fact that every item in the
+// * table always has LPSTR_TEXTCALLBACK, Windows caches the
+// * bounds for the selected items. This means that
+// * when you change the string to be something else, Windows
+// * correctly asks you for the new string but when the item
+// * is selected, the selection draws using the bounds of the
+// * previous item. The fix is to reset LPSTR_TEXTCALLBACK
+// * even though it has not changed, causing Windows to flush
+// * cached bounds.
+// */
+// if ((style & SWT.VIRTUAL) == 0 && item.cached) {
+// LVITEM lvItem = new LVITEM ();
+// lvItem.mask = OS.LVIF_TEXT | OS.LVIF_INDENT;
+// lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+// lvItem.iItem = index;
+// OS.SendMessage (handle, OS.LVM_SETITEM, 0, lvItem);
+// item.cached = false;
+// }
+// if (currentItem == null && drawCount == 0 && OS.IsWindowVisible (handle)) {
+// OS.SendMessage (handle, OS.LVM_REDRAWITEMS, index, index);
+// }
+// setScrollWidth (item, false);
+// }
+}
+
+/**
+ * Removes the items from the receiver which are between the given
+ * zero-relative start and end indices (inclusive). The text, icon
+ * and other attributes of the items are set to their default values.
+ * If the table was created with the SWT.VIRTUAL style,
+ * these attributes are requested again as needed.
+ *
+ * @param start the start index of the item to clear
+ * @param end the end index of the item to clear
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clear (int start, int end) {
+ checkWidget ();
+ if (start > end) return;
+ for(int i=start; i<=end; i++) {
+ TableItem item = (TableItem)itemList.get(i);
+ if(item != null) {
+ item.clear();
+ }
+ }
+ handle.repaint();
+// int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+// if (!(0 <= start && start <= end && end < count)) {
+// error (SWT.ERROR_INVALID_RANGE);
+// }
+// if (start == 0 && end == count - 1) {
+// clearAll ();
+// } else {
+// LVITEM lvItem = null;
+// boolean cleared = false;
+// for (int i=start; i<=end; i++) {
+// TableItem item = items [i];
+// if (item != null) {
+// if (item != currentItem) {
+// cleared = true;
+// item.clear ();
+// }
+// /*
+// * Bug in Windows. Despite the fact that every item in the
+// * table always has LPSTR_TEXTCALLBACK, Windows caches the
+// * bounds for the selected items. This means that
+// * when you change the string to be something else, Windows
+// * correctly asks you for the new string but when the item
+// * is selected, the selection draws using the bounds of the
+// * previous item. The fix is to reset LPSTR_TEXTCALLBACK
+// * even though it has not changed, causing Windows to flush
+// * cached bounds.
+// */
+// if ((style & SWT.VIRTUAL) == 0 && item.cached) {
+// if (lvItem == null) {
+// lvItem = new LVITEM ();
+// lvItem.mask = OS.LVIF_TEXT | OS.LVIF_INDENT;
+// lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+// }
+// lvItem.iItem = i;
+// OS.SendMessage (handle, OS.LVM_SETITEM, 0, lvItem);
+// item.cached = false;
+// }
+// }
+// }
+// if (cleared) {
+// if (currentItem == null && drawCount == 0 && OS.IsWindowVisible (handle)) {
+// OS.SendMessage (handle, OS.LVM_REDRAWITEMS, start, end);
+// }
+// TableItem item = start == end ? items [start] : null;
+// setScrollWidth (item, false);
+// }
+// }
+}
+
+/**
+ * Clears the items at the given zero-relative indices in the receiver.
+ * The text, icon and other attributes of the items are set to their default
+ * values. If the table was created with the SWT.VIRTUAL style,
+ * these attributes are requested again as needed.
+ *
+ * @param indices the array of indices of the items
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
ERROR_NULL_ARGUMENT - if the indices array is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clearAll () {
+ checkWidget ();
+ for (int i=itemList.size()-1; i>=0; i--) {
+ TableItem item = (TableItem)itemList.get(i);
+ if(item != null) {
+ item.clear();
+ }
+ }
+ handle.repaint();
+// LVITEM lvItem = null;
+// boolean cleared = false;
+// int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+// for (int i=0; i> 16;
+//
+// /*
+// * Feature in Windows. The height returned by LVM_APPROXIMATEVIEWRECT
+// * includes the trim plus the height of the items plus one extra row.
+// * The fix is to subtract the height of one row from the result height.
+// */
+// int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+// int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
+// height -= (oneItem >> 16) - (empty >> 16);
+//
+// if (width == 0) width = DEFAULT_WIDTH;
+// if (height == 0) height = DEFAULT_HEIGHT;
+// if (wHint != SWT.DEFAULT) width = wHint;
+// if (hHint != SWT.DEFAULT) height = hHint;
+// int border = getBorderWidth ();
+// width += border * 2; height += border * 2;
+// if ((style & SWT.V_SCROLL) != 0) {
+// width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+// }
+// if ((style & SWT.H_SCROLL) != 0) {
+// height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+// }
+// return new Point (width, height);
+//}
+
+public Rectangle computeTrim(int x, int y, int width, int height) {
+ CTable cTable = (CTable)handle;
+ width += cTable.getVerticalScrollBar().getPreferredSize().width;
+ height += cTable.getHorizontalScrollBar().getPreferredSize().height;
+ return super.computeTrim(x, y, width, height);
+}
+
+void createHandleInit() {
+ super.createHandleInit();
+ state &= ~(CANVAS | THEME_BACKGROUND);
+}
+
+protected Container createHandle () {
+ return (Container)CTable.Factory.newInstance(this, style);
+}
+
+void createItem (TableColumn column, int index) {
+ for (int i=0; i=0; i--) {
+ javax.swing.table.TableColumn tColumn = columnModel.getColumn(i);
+ int modelIndex = tColumn.getModelIndex();
+ if(modelIndex >= index) {
+ tColumn.setModelIndex(modelIndex + 1);
+ }
+ }
+ columnModel.addColumn(tableColumn);
+ tableColumn.setModelIndex(index);
+ ((CTable)handle).moveColumn(getColumnCount()-1, index);
+ // TODO: check it is enough
+ handle.repaint();
+}
+
+void createItem (TableItem item, int index) {
+ int count = getItemCount();
+ if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+ itemList.add(index, item);
+ ((CTable)handle).addItem(index);
+}
+
+void createWidget () {
+ itemList = new ArrayList();
+ columnList = new ArrayList();
+ super.createWidget ();
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected. If the item at the index
+ * was not selected, it remains deselected. Indices that are out
+ * of range and duplicate indices are ignored.
+ *
+ * @param indices the array of indices for the items to deselect
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the set of indices is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void deselect (int index) {
+ checkWidget ();
+ if (index < 0) return;
+ isAdjustingSelection = true;
+ ((CTable)handle).getSelectionModel().removeSelectionInterval(index, index);
+ isAdjustingSelection = false;
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected. If the item at the index
+ * was not selected, it remains deselected. The range of the
+ * indices is inclusive. Indices that are out of range are ignored.
+ *
+ * @param start the start index of the items to deselect
+ * @param end the end index of the items to deselect
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void deselectAll () {
+ checkWidget ();
+ isAdjustingSelection = true;
+ ((CTable)handle).getSelectionModel().clearSelection();
+ isAdjustingSelection = false;
+}
+
+void destroyItem (TableColumn column) {
+ int index = columnList.indexOf(column);
+ for (int i=0; iTableColumns were created by the programmer,
+ * this method will throw ERROR_INVALID_RANGE despite
+ * the fact that a single column of data may be visible in the table.
+ * This occurs when the programmer uses the table like a list, adding
+ * items but never creating a column.
+ *
+ * @param index the index of the column to return
+ * @return the column at the given index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#getColumnOrder()
+ * @see Table#setColumnOrder(int[])
+ * @see TableColumn#getMoveable()
+ * @see TableColumn#setMoveable(boolean)
+ * @see SWT#Move
+ */
+public TableColumn getColumn (int index) {
+ checkWidget ();
+ if (columnList == null) error (SWT.ERROR_INVALID_RANGE);
+ int count = getColumnCount();
+ if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+ return (TableColumn)columnList.get(index);
+}
+
+/**
+ * Returns the number of columns contained in the receiver.
+ * If no TableColumns were created by the programmer,
+ * this value is zero, despite the fact that visually, one column
+ * of items may be visible. This occurs when the programmer uses
+ * the table like a list, adding items but never creating a column.
+ *
+ * @return the number of columns
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getColumnCount () {
+ checkWidget ();
+ return columnList == null? 0: columnList.size();
+}
+
+/**
+ * Returns an array of zero-relative integers that map
+ * the creation order of the receiver's items to the
+ * order in which they are currently being displayed.
+ *
+ * Specifically, the indices of the returned array represent
+ * the current visual order of the items, and the contents
+ * of the array represent the creation order of the items.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the current visual order of the receiver's items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#setColumnOrder(int[])
+ * @see TableColumn#getMoveable()
+ * @see TableColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public int[] getColumnOrder () {
+ checkWidget ();
+ return ((CTable)handle).getColumnOrder();
+}
+
+/**
+ * Returns an array of TableColumns which are the
+ * columns in the receiver. Columns are returned in the order
+ * that they were created. If no TableColumns were
+ * created by the programmer, the array is empty, despite the fact
+ * that visually, one column of items may be visible. This occurs
+ * when the programmer uses the table like a list, adding items but
+ * never creating a column.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#getColumnOrder()
+ * @see Table#setColumnOrder(int[])
+ * @see TableColumn#getMoveable()
+ * @see TableColumn#setMoveable(boolean)
+ * @see SWT#Move
+ */
+public TableColumn [] getColumns () {
+ checkWidget ();
+ if (columnList == null) return new TableColumn [0];
+ return (TableColumn[])columnList.toArray(new TableColumn[0]);
+}
+
+///*
+//* Not currently used.
+//*/
+//int getFocusIndex () {
+//// checkWidget ();
+// return OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+//}
+
+/**
+ * Returns the width in pixels of a grid line.
+ *
+ * @return the width of a grid line in pixels
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getGridLineWidth () {
+ checkWidget ();
+ return GRID_WIDTH;
+}
+
+/**
+ * Returns the height of the receiver's header
+ *
+ * @return the height of the header or zero if the header is not visible
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ */
+public int getHeaderHeight () {
+ checkWidget ();
+ JTableHeader tableHeader = ((CTable)handle).getTableHeader();
+ return tableHeader.isVisible()? tableHeader.getHeight(): 0;
+}
+
+/**
+ * Returns true if the receiver's header is visible,
+ * and false otherwise.
+ *
+ * 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.
+ *
+ *
+ * @return the receiver's header's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getHeaderVisible () {
+ checkWidget ();
+ return ((CTable)handle).getTableHeader().isVisible();
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TableItem getItem (int index) {
+ checkWidget ();
+ int count = getItemCount();
+ if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+ return _getItem(index);
+}
+
+/**
+ * Returns the item at the given point in the receiver
+ * or null if no such item exists. The point is in the
+ * coordinate system of the receiver.
+ *
+ * The item that is returned represents an item that could be selected by the user.
+ * For example, if selection only occurs in items in the first column, then null is
+ * returned if the point is outside of the item.
+ * Note that the SWT.FULL_SELECTION style hint, which specifies the selection policy,
+ * determines the extent of the selection.
+ *
+ *
+ * @param point the point used to locate the item
+ * @return the item at the given point, or null if the point is not in a selectable item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TableItem getItem (Point point) {
+ checkWidget ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int row = ((CTable)handle).rowAtPoint(new java.awt.Point(point.x, point.y));
+ if(row < 0) return null;
+ return _getItem(row);
+}
+
+TableItem _getItem (int index) {
+ TableItem tableItem = (TableItem)itemList.get(index);
+ if ((style & SWT.VIRTUAL) == 0) return tableItem;
+ if (tableItem != null) return tableItem;
+ tableItem = new TableItem (this, SWT.NONE, -1, false);
+ itemList.set(index, tableItem);
+ return tableItem;
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemCount () {
+ checkWidget ();
+ return itemList == null? 0: itemList.size();
+}
+
+/**
+ * Returns the height of the area which would be used to
+ * display one of the items in the receiver's.
+ *
+ * @return the height of one item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemHeight () {
+ checkWidget ();
+ return ((CTable)handle).getRowHeight();
+}
+
+/**
+ * Returns a (possibly empty) array of TableItems which
+ * are the items in the receiver.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TableItem [] getItems () {
+ checkWidget ();
+ if ((style & SWT.VIRTUAL) != 0) {
+ TableItem[] items = new TableItem[getItemCount()];
+ for(int i=0; itrue if the receiver's lines are visible,
+ * and false otherwise.
+ *
+ * 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.
+ *
+ *
+ * @return the visibility state of the lines
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getLinesVisible () {
+ checkWidget ();
+ return ((CTable)handle).isGridVisible();
+}
+
+/**
+ * Returns an array of TableItems that are currently
+ * selected in the receiver. The order of the items is unspecified.
+ * An empty array indicates that no items are selected.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ *
+ * @return an array representing the selection
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TableItem [] getSelection () {
+ checkWidget ();
+ DefaultListSelectionModel selectionModel = ((CTable)handle).getSelectionModel();
+ int minSelectionIndex = selectionModel.getMinSelectionIndex();
+ int maxSelectionIndex = selectionModel.getMaxSelectionIndex();
+ if(minSelectionIndex == -1 || maxSelectionIndex == -1) {
+ return new TableItem[0];
+ }
+ TableItem[] selectedIndices_ = new TableItem[1 + maxSelectionIndex - minSelectionIndex];
+ int count = 0;
+ for(int i=minSelectionIndex; i<=maxSelectionIndex; i++) {
+ if(selectionModel.isSelectedIndex(i)) {
+ selectedIndices_[count++] = _getItem(i);
+ }
+ }
+ TableItem[] selectedIndices = new TableItem[count];
+ System.arraycopy(selectedIndices_, 0, selectedIndices, 0, count);
+ return selectedIndices;
+}
+
+/**
+ * Returns the number of selected items contained in the receiver.
+ *
+ * @return the number of selected items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelectionCount () {
+ checkWidget ();
+ DefaultListSelectionModel selectionModel = ((CTable)handle).getSelectionModel();
+ int minSelectionIndex = selectionModel.getMinSelectionIndex();
+ int maxSelectionIndex = selectionModel.getMaxSelectionIndex();
+ int count = 0;
+ for(int i=minSelectionIndex; i<=maxSelectionIndex; i++) {
+ if(selectionModel.isSelectedIndex(i)) {
+ count++;
+ }
+ }
+ return count;
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver, or -1 if no item is selected.
+ *
+ * @return the index of the selected item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelectionIndex () {
+ checkWidget ();
+ DefaultListSelectionModel selectionModel = ((CTable)handle).getSelectionModel();
+ return selectionModel.getMinSelectionIndex();
+}
+
+/**
+ * Returns the zero-relative indices of the items which are currently
+ * selected in the receiver. The order of the indices is unspecified.
+ * The array is empty if no items are selected.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ *
+ * @return the array of indices of the selected items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int [] getSelectionIndices () {
+ checkWidget ();
+ DefaultListSelectionModel selectionModel = ((CTable)handle).getSelectionModel();
+ int minSelectionIndex = selectionModel.getMinSelectionIndex();
+ int maxSelectionIndex = selectionModel.getMaxSelectionIndex();
+ if(minSelectionIndex == -1 || maxSelectionIndex == -1) {
+ return new int[0];
+ }
+ int[] selectedIndices_ = new int[1 + maxSelectionIndex - minSelectionIndex];
+ int count = 0;
+ for(int i=minSelectionIndex; i<=maxSelectionIndex; i++) {
+ if(selectionModel.isSelectedIndex(i)) {
+ selectedIndices_[count++] = i;
+ }
+ }
+ int[] selectedIndices = new int[count];
+ System.arraycopy(selectedIndices_, 0, selectedIndices, 0, count);
+ return selectedIndices;
+}
+
+TableColumn sortColumn;
+int sortDirection;
+
+/**
+ * Returns the column which shows the sort indicator for
+ * the receiver. The value may be null if no column shows
+ * the sort indicator.
+ *
+ * @return the sort indicator
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setSortColumn(TableColumn)
+ *
+ * @since 3.2
+ */
+public TableColumn getSortColumn () {
+ checkWidget ();
+ return sortColumn;
+}
+
+/**
+ * Returns the direction of the sort indicator for the receiver.
+ * The value will be one of UP, DOWN
+ * or NONE.
+ *
+ * @return the sort direction
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setSortDirection(int)
+ *
+ * @since 3.2
+ */
+public int getSortDirection () {
+ checkWidget ();
+ return sortDirection;
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items are
+ * scrolled or new items are added or removed.
+ *
+ * @return the index of the top item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getTopIndex () {
+ checkWidget ();
+ // Should we return -1 or 0 when there are no items?
+ return Math.max(0, ((CTable)handle).getTopIndex());
+}
+
+//int imageIndex (Image image) {
+// if (image == null) return OS.I_IMAGENONE;
+// if (imageList == null) {
+// Rectangle bounds = image.getBounds ();
+// imageList = display.getImageList (new Point (bounds.width, bounds.height));
+// int index = imageList.indexOf (image);
+// if (index == -1) index = imageList.add (image);
+// int hImageList = imageList.getHandle ();
+// /*
+// * Bug in Windows. Making any change to an item that
+// * changes the item height of a table while the table
+// * is scrolled can cause the lines to draw incorrectly.
+// * This happens even when the lines are not currently
+// * visible and are shown afterwards. The fix is to
+// * save the top index, scroll to the top of the table
+// * and then restore the original top index.
+// */
+// int topIndex = getTopIndex ();
+// setRedraw (false);
+// setTopIndex (0);
+// OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, hImageList);
+// setTopIndex (topIndex);
+// fixCheckboxImageList ();
+// setRedraw (true);
+// return index;
+// }
+// int index = imageList.indexOf (image);
+// if (index != -1) return index;
+// return imageList.add (image);
+//}
+
+/**
+ * Searches the receiver's list starting at the first column
+ * (index 0) until a column is found that is equal to the
+ * argument, and returns the index of that column. If no column
+ * is found, returns -1.
+ *
+ * @param column the search column
+ * @return the index of the column
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int indexOf (TableColumn column) {
+ checkWidget ();
+ if (column == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (column.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ return columnList.indexOf(column);
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int indexOf (TableItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int count = getItemCount();
+ if (1 <= lastIndexOf && lastIndexOf < count - 1) {
+ if (itemList.get(lastIndexOf) == item) return lastIndexOf;
+ if (itemList.get(lastIndexOf + 1) == item) return ++lastIndexOf;
+ if (itemList.get(lastIndexOf - 1) == item) return --lastIndexOf;
+ }
+ if (lastIndexOf < count / 2) {
+ for (int i=0; i=0; --i) {
+ if (itemList.get(i) == item) return lastIndexOf = i;
+ }
+ }
+ return -1;
+}
+
+/**
+ * Returns true if the item is selected,
+ * and false otherwise. Indices out of
+ * range are ignored.
+ *
+ * @param index the index of the item
+ * @return the visibility state of the item at the index
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean isSelected (int index) {
+ checkWidget ();
+ return ((CTable)handle).getSelectionModel().isSelectedIndex(index);
+}
+
+Point minimumSize (int wHint, int hHint, boolean changed) {
+ java.awt.Dimension size = handle.getPreferredSize();
+ return new Point(size.width, size.height);
+}
+
+void releaseChildren (boolean destroy) {
+ if(itemList != null) {
+ for (int i=itemList.size()-1; i>=0; i--) {
+ TableItem item = (TableItem)itemList.get(i);
+ if (item != null && !item.isDisposed ()) item.release (false);
+ }
+ itemList = null;
+ }
+ if(columnList != null) {
+ for(int i=0; i1000) where each
+// * of the subitems in the table has a string, it is much
+// * faster to delete each item with LVM_DELETEITEM rather
+// * than using LVM_DELETEALLITEMS. The fix is to detect
+// * this case and delete the items, one by one. The fact
+// * that the fix is only necessary on Windows 98 was
+// * confirmed using version 5.81 of COMCTL32.DLL on both
+// * Windows 98 and NT.
+// *
+// * NOTE: LVM_DELETEALLITEMS is also sent by the table
+// * when the table is destroyed.
+// */
+// if (OS.IsWin95 && columnCount > 1) {
+// /* Turn off redraw and leave it off */
+// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+// for (int i=itemCount-1; i>=0; --i) {
+// TableItem item = items [i];
+// ignoreSelect = ignoreShrink = true;
+// OS.SendMessage (handle, OS.LVM_DELETEITEM, i, 0);
+// ignoreSelect = ignoreShrink = false;
+// if (item != null && !item.isDisposed ()) item.releaseResources ();
+// }
+// } else {
+// for (int i=0; i
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
ERROR_NULL_ARGUMENT - if the indices array is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void remove (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (indices.length == 0) return;
+ int [] newIndices = new int [indices.length];
+ System.arraycopy (indices, 0, newIndices, 0, indices.length);
+ // Sort puts the biggest indices first
+ sort (newIndices);
+ int start = newIndices [newIndices.length - 1], end = newIndices [0];
+ int count = getItemCount();
+ if (!(0 <= start && start <= end && end < count)) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ for(int i=0; i
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void remove (int index) {
+ checkWidget ();
+ int count = getItemCount();
+ if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+ TableItem tableItem = (TableItem)itemList.get(index);
+ if(tableItem != null) {
+ tableItem.dispose();
+ } else {
+ itemList.remove(index);
+ ((CTable)handle).removeItem(index);
+ }
+}
+
+/**
+ * Removes the items from the receiver which are
+ * between the given zero-relative start and end
+ * indices (inclusive).
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void remove (int start, int end) {
+ checkWidget ();
+ if (start > end) return;
+ int count = getItemCount();
+ if (!(0 <= start && start <= end && end < count)) {
+ error (SWT.ERROR_INVALID_RANGE);
+ }
+ for(int i=end; i>=start; i--) {
+ TableItem tableItem = (TableItem)itemList.get(i);
+ if(tableItem != null) {
+ tableItem.dispose();
+ } else {
+ itemList.remove(i);
+ ((CTable)handle).removeItem(i);
+ }
+ }
+}
+
+/**
+ * Removes all of the items from the receiver.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void removeAll () {
+ checkWidget ();
+ for(int i=itemList.size()-1; i>=0; i--) {
+ TableItem tableItem = (TableItem)itemList.get(i);
+ if(tableItem != null) {
+ tableItem.dispose();
+ } else {
+ itemList.remove(i);
+ ((CTable)handle).removeItem(i);
+ }
+ }
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's selection changes.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener(SelectionListener)
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+boolean isAdjustingSelection;
+
+/**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is not cleared before the new items are selected.
+ *
+ * If the item at a given index is not selected, it is selected.
+ * If the item at a given index was already selected, it remains selected.
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ *
+ *
+ * @param indices the array of indices for the items to select
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the array of indices is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void select (int index) {
+ checkWidget ();
+ isAdjustingSelection = true;
+ ((CTable)handle).getSelectionModel().addSelectionInterval(index, index);
+ isAdjustingSelection = false;
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is not cleared before the new items are selected.
+ *
+ * If an item in the given range is not selected, it is selected.
+ * If an item in the given range was already selected, it remains selected.
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ *
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#setSelection(int,int)
+ */
+public void select (int start, int end) {
+ checkWidget ();
+ if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return;
+ isAdjustingSelection = true;
+ ((CTable)handle).getSelectionModel().addSelectionInterval(start, end);
+ isAdjustingSelection = false;
+}
+
+/**
+ * Selects all of the items in the receiver.
+ *
+ * If the receiver is single-select, do nothing.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void selectAll () {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) return;
+ if(!itemList.isEmpty()) {
+ isAdjustingSelection = true;
+ ((CTable)handle).getSelectionModel().addSelectionInterval(0, itemList.size() - 1);
+ isAdjustingSelection = false;
+ }
+}
+
+//LRESULT sendMouseDownEvent (int type, int button, int msg, int wParam, int lParam) {
+// /*
+// * Feature in Windows. Inside WM_LBUTTONDOWN and WM_RBUTTONDOWN,
+// * the widget starts a modal loop to determine if the user wants
+// * to begin a drag/drop operation or marque select. Unfortunately,
+// * this modal loop eats the corresponding mouse up. The fix is to
+// * detect the cases when the modal loop has eaten the mouse up and
+// * issue a fake mouse up.
+// *
+// * By observation, when the mouse is clicked anywhere but the check
+// * box, the widget eats the mouse up. When the mouse is dragged,
+// * the widget does not eat the mouse up.
+// */
+// LVHITTESTINFO pinfo = new LVHITTESTINFO ();
+// pinfo.x = (short) (lParam & 0xFFFF);
+// pinfo.y = (short) (lParam >> 16);
+// OS.SendMessage (handle, OS.LVM_HITTEST, 0, pinfo);
+// sendMouseEvent (type, button, handle, msg, wParam, lParam);
+//
+// /*
+// * Force the table to have focus so that when the user
+// * reselects the focus item, the LVIS_FOCUSED state bits
+// * for the item will be set. These bits are used when
+// * the table is multi-select to issue the selection
+// * event. If the user did not click on an item, then
+// * set focus to the table so that it will come to the
+// * front and take focus in the work around below.
+// */
+// OS.SetFocus (handle);
+//
+// /*
+// * Feature in Windows. When the user selects outside of
+// * a table item, Windows deselects all the items, even
+// * when the table is multi-select. While not strictly
+// * wrong, this is unexpected. The fix is to detect the
+// * case and avoid calling the window proc.
+// */
+// if (pinfo.iItem == -1) {
+// if (OS.GetCapture () != handle) OS.SetCapture (handle);
+// return LRESULT.ZERO;
+// }
+//
+// /*
+// * Feature in Windows. When a table item is reselected
+// * in a single-select table, Windows does not issue a
+// * WM_NOTIFY because the item state has not changed.
+// * This is strictly correct but is inconsistent with the
+// * list widget and other widgets in Windows. The fix is
+// * to detect the case when an item is reselected and issue
+// * the notification.
+// *
+// * NOTE: This code runs for multi-select as well, ignoring
+// * the selection that is issed from WM_NOTIFY.
+// */
+// boolean wasSelected = false;
+// int count = OS.SendMessage (handle, OS.LVM_GETSELECTEDCOUNT, 0, 0);
+// if (count == 1 && pinfo.iItem != -1) {
+// LVITEM lvItem = new LVITEM ();
+// lvItem.mask = OS.LVIF_STATE;
+// lvItem.stateMask = OS.LVIS_SELECTED;
+// lvItem.iItem = pinfo.iItem;
+// OS.SendMessage (handle, OS.LVM_GETITEM, 0, lvItem);
+// wasSelected = (lvItem.state & OS.LVIS_SELECTED) != 0;
+// if (wasSelected) ignoreSelect = true;
+// }
+// dragStarted = false;
+// int code = callWindowProc (handle, msg, wParam, lParam);
+// if (wasSelected) {
+// ignoreSelect = false;
+// Event event = new Event ();
+// event.item = _getItem (pinfo.iItem);
+// postEvent (SWT.Selection, event);
+// }
+// if (dragStarted) {
+// if (OS.GetCapture () != handle) OS.SetCapture (handle);
+// } else {
+// int flags = OS.LVHT_ONITEMLABEL | OS.LVHT_ONITEMICON;
+// boolean fakeMouseUp = (pinfo.flags & flags) != 0;
+// if (!fakeMouseUp && (style & SWT.MULTI) != 0) {
+// fakeMouseUp = (pinfo.flags & OS.LVHT_ONITEMSTATEICON) == 0;
+// }
+// if (fakeMouseUp) {
+// mouseDown = false;
+// sendMouseEvent (SWT.MouseUp, button, handle, msg, wParam, lParam);
+// }
+// }
+// dragStarted = false;
+// return new LRESULT (code);
+//}
+
+/**
+ * Sets the order that the items in the receiver should
+ * be displayed in to the given argument which is described
+ * in terms of the zero-relative ordering of when the items
+ * were added.
+ *
+ * @param order the new order to display the items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the item order is null
+ *
ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items
+ * 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.
+ *
+ *
+ * @param show the new visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setHeaderVisible (boolean show) {
+ checkWidget ();
+ ((CTable)handle).setHeaderVisible(show);
+}
+
+/**
+ * Sets the number of items contained in the receiver.
+ *
+ * @param count the number of items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public void setItemCount (int count) {
+ checkWidget ();
+ count = Math.max (0, count);
+ int itemCount = getItemCount();
+ if (count == itemCount) return;
+ boolean isVirtual = (style & SWT.VIRTUAL) != 0;
+// if (!isVirtual) setRedraw (false);
+ int index = count;
+ int tmpItemCount = itemCount;
+ while (index < tmpItemCount) {
+ TableItem item = (TableItem)itemList.get(tmpItemCount - 1);
+// if (!isVirtual) {
+// ((CTable)handle).removeItem(index);
+// }
+ if (item != null && !item.isDisposed ()) {
+ item.release (true);
+ } else {
+ itemList.remove(index);
+ ((CTable)handle).removeItem(index);
+ }
+ tmpItemCount--;
+ }
+// if (index < itemCount) error (SWT.ERROR_ITEM_NOT_REMOVED);
+ itemList.ensureCapacity(count);
+ for(int i=itemCount; ione of the items in the table.
+ *
+ * @return the height of one item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+/*public*/ void setItemHeight (int itemHeight) {
+ checkWidget ();
+ if (itemHeight < 0) error (SWT.ERROR_INVALID_ARGUMENT);
+ ((CTable)handle).setRowHeight(itemHeight);
+}
+
+/**
+ * Marks the receiver's lines as visible if the argument is true,
+ * and marks it invisible otherwise.
+ *
+ * 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.
+ *
+ *
+ * @param show the new visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setLinesVisible (boolean show) {
+ checkWidget ();
+ ((CTable)handle).setGridVisible(show);
+}
+
+//public void setRedraw (boolean redraw) {
+// checkWidget ();
+// /*
+// * Feature in Windows. When WM_SETREDRAW is used to turn
+// * off drawing in a widget, it clears the WS_VISIBLE bits
+// * and then sets them when redraw is turned back on. This
+// * means that WM_SETREDRAW will make a widget unexpectedly
+// * visible. The fix is to track the visibility state while
+// * drawing is turned off and restore it when drawing is turned
+// * back on.
+// */
+// if (drawCount == 0) {
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// if ((bits & OS.WS_VISIBLE) == 0) state |= HIDDEN;
+// }
+// if (redraw) {
+// if (--drawCount == 0) {
+// /*
+// * When many items are added to a table, it is faster to
+// * temporarily unsubclass the window proc so that messages
+// * are dispatched directly to the table.
+// *
+// * NOTE: This is optimization somewhat dangerous because any
+// * operation can occur when redraw is turned off, even operations
+// * where the table must be subclassed in order to have the correct
+// * behavior or work around a Windows bug.
+// *
+// * This code is intentionally commented.
+// */
+//// subclass ();
+//
+// /* Set the width of the horizontal scroll bar */
+// setScrollWidth (null, true);
+//
+// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+// if (hwndHeader != 0) OS.SendMessage (hwndHeader, OS.WM_SETREDRAW, 1, 0);
+// if ((state & HIDDEN) != 0) {
+// state &= ~HIDDEN;
+// OS.ShowWindow (handle, OS.SW_HIDE);
+// } else {
+// if (OS.IsWinCE) {
+// OS.InvalidateRect (handle, null, false);
+// if (hwndHeader != 0) {
+// OS.InvalidateRect (hwndHeader, null, false);
+// }
+// } else {
+// int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+// OS.RedrawWindow (handle, null, 0, flags);
+// }
+// }
+// }
+// } else {
+// if (drawCount++ == 0) {
+// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+// if (hwndHeader != 0) OS.SendMessage (hwndHeader, OS.WM_SETREDRAW, 0, 0);
+//
+// /*
+// * When many items are added to a table, it is faster to
+// * temporarily unsubclass the window proc so that messages
+// * are dispatched directly to the table.
+// *
+// * NOTE: This is optimization somewhat dangerous because any
+// * operation can occur when redraw is turned off, even operations
+// * where the table must be subclassed in order to have the correct
+// * behavior or work around a Windows bug.
+// *
+// * This code is intentionally commented.
+// */
+//// unsubclass ();
+// }
+// }
+//}
+
+//boolean setScrollWidth (TableItem item, boolean force) {
+// if (currentItem != null) {
+// if (currentItem != item) fixScrollWidth = true;
+// return false;
+// }
+// if (!force && (drawCount != 0 || !OS.IsWindowVisible (handle))) {
+// fixScrollWidth = true;
+// return false;
+// }
+// fixScrollWidth = false;
+// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// /*
+// * NOTE: It is much faster to measure the strings and compute the
+// * width of the scroll bar in non-virtual table rather than using
+// * LVM_SETCOLUMNWIDTH with LVSCW_AUTOSIZE.
+// */
+// if (count == 1 && columns [0] == null) {
+// int newWidth = 0;
+// count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+// int index = 0;
+// int imageIndent = 0;
+// while (index < count) {
+// String string = null;
+// int font = -1;
+// if (item != null) {
+// string = item.text;
+// imageIndent = Math.max (imageIndent, item.imageIndent);
+// if (item.cellFont != null) font = item.cellFont [0];
+// if (font == -1) font = item.font;
+// } else {
+// if (items [index] != null) {
+// TableItem tableItem = items [index];
+// string = tableItem.text;
+// imageIndent = Math.max (imageIndent, tableItem.imageIndent);
+// if (tableItem.cellFont != null) font = tableItem.cellFont [0];
+// if (font == -1) font = tableItem.font;
+// }
+// }
+// if (string != null && string.length () != 0) {
+// if (font != -1) {
+// int hDC = OS.GetDC (handle);
+// int oldFont = OS.SelectObject (hDC, font);
+// int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+// TCHAR buffer = new TCHAR (getCodePage (), string, false);
+// RECT rect = new RECT ();
+// OS.DrawText (hDC, buffer, buffer.length (), rect, flags);
+// OS.SelectObject (hDC, oldFont);
+// OS.ReleaseDC (handle, hDC);
+// newWidth = Math.max (newWidth, rect.right - rect.left);
+// } else {
+// TCHAR buffer = new TCHAR (getCodePage (), string, true);
+// newWidth = Math.max (newWidth, OS.SendMessage (handle, OS.LVM_GETSTRINGWIDTH, 0, buffer));
+// }
+// }
+// if (item != null) break;
+// index++;
+// }
+// int hStateList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+// if (hStateList != 0) {
+// int [] cx = new int [1], cy = new int [1];
+// OS.ImageList_GetIconSize (hStateList, cx, cy);
+// newWidth += cx [0] + INSET;
+// }
+// int hImageList = OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
+// if (hImageList != 0) {
+// int [] cx = new int [1], cy = new int [1];
+// OS.ImageList_GetIconSize (hImageList, cx, cy);
+// newWidth += (imageIndent + 1) * cx [0];
+// } else {
+// /*
+// * Bug in Windows. When LVM_SETIMAGELIST is used to remove the
+// * image list by setting it to NULL, the item width and height
+// * is not changed and space is reserved for icons despite the
+// * fact that there are none. The fix is to set the image list
+// * to be very small before setting it to NULL. This causes
+// * Windows to reserve the smallest possible space when an image
+// * list is removed. In this case, the scroll width must be one
+// * pixel larger.
+// */
+// newWidth++;
+// }
+// newWidth += INSET * 2;
+// int oldWidth = OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0);
+// if (newWidth > oldWidth) {
+// OS.SendMessage (handle, OS.LVM_SETCOLUMNWIDTH, 0, newWidth);
+// return true;
+// }
+// }
+// return false;
+//}
+
+/**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is cleared before the new items are selected.
+ *
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ *
+ *
+ * @param indices the indices of the items to select
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the array of indices is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#deselectAll()
+ * @see Table#select(int[])
+ */
+public void setSelection (int [] indices) {
+ checkWidget ();
+ if (indices == null) error (SWT.ERROR_NULL_ARGUMENT);
+ deselectAll ();
+ int length = indices.length;
+ if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+ select (indices);
+ int focusIndex = indices [0];
+ if (focusIndex != -1) setFocusIndex (focusIndex);
+ showSelection ();
+}
+
+/**
+ * Sets the receiver's selection to the given item.
+ * The current selection is cleared before the new item is selected.
+ *
+ * If the item is not in the receiver, then it is ignored.
+ *
+ *
+ * @param item the item to select
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the item is null
+ *
ERROR_INVALID_ARGUMENT - if the item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setSelection (TableItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSelection (new TableItem [] {item});
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected.
+ *
+ * Items that are not in the receiver are ignored.
+ * If the receiver is single-select and multiple items are specified,
+ * then all items are ignored.
+ *
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the array of items is null
+ *
ERROR_INVALID_ARGUMENT - if one of the items has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#deselectAll()
+ * @see Table#select(int[])
+ * @see Table#setSelection(int[])
+ */
+public void setSelection (TableItem [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ isAdjustingSelection = true;
+ deselectAll ();
+ isAdjustingSelection = false;
+ int length = items.length;
+ if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return;
+ int focusIndex = -1;
+ for (int i=length-1; i>=0; --i) {
+ int index = indexOf (items [i]);
+ if (index != -1) {
+ select (focusIndex = index);
+ }
+ }
+ if (focusIndex != -1) setFocusIndex (focusIndex);
+ showSelection ();
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver.
+ * The current selection is first cleared, then the new item is selected.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#deselectAll()
+ * @see Table#select(int)
+ */
+public void setSelection (int index) {
+ checkWidget ();
+ deselectAll ();
+ select (index);
+ if (index != -1) setFocusIndex (index);
+ showSelection ();
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is cleared before the new items are selected.
+ *
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ *
+ *
+ * @param start the start index of the items to select
+ * @param end the end index of the items to select
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#deselectAll()
+ * @see Table#select(int,int)
+ */
+public void setSelection (int start, int end) {
+ checkWidget ();
+ deselectAll ();
+ if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return;
+ ((CTable)handle).getSelectionModel().setSelectionInterval(start, end);
+ showSelection ();
+}
+
+/**
+ * Sets the column used by the sort indicator for the receiver. A null
+ * value will clear the sort indicator. The current sort column is cleared
+ * before the new column is set.
+ *
+ * @param column the column used by the sort indicator or null
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the column is disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setSortColumn (TableColumn column) {
+ checkWidget ();
+ if (column != null && column.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ sortColumn = column;
+ handle.repaint();
+}
+
+/**
+ * Sets the direction of the sort indicator for the receiver. The value
+ * can be one of UP, DOWN or NONE.
+ *
+ * @param direction the direction of the sort indicator
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setSortDirection (int direction) {
+ checkWidget ();
+ if ((direction & (SWT.UP | SWT.DOWN)) == 0 && direction != SWT.NONE) return;
+ sortDirection = direction;
+ handle.repaint();
+}
+
+/**
+ * Sets the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items
+ * are scrolled or new items are added and removed.
+ *
+ * @param index the index of the top item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setTopIndex (int index) {
+ checkWidget ();
+ ((CTable)handle).setTopIndex(index);
+}
+
+/**
+ * Shows the column. If the column is already showing in the receiver,
+ * this method simply returns. Otherwise, the columns are scrolled until
+ * the column is visible.
+ *
+ * @param column the column to be shown
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the column is null
+ *
ERROR_INVALID_ARGUMENT - if the column has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public void showColumn (TableColumn column) {
+ checkWidget ();
+ if (column == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (column.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ if (column.parent != this) return;
+ int index = indexOf (column);
+ if (index == -1) return;
+ ((CTable)handle).ensureColumnVisible(index);
+}
+
+//void showItem (int index) {
+// /*
+// * Bug in Windows. For some reason, when there is insufficient space
+// * to show an item, LVM_ENSUREVISIBLE causes blank lines to be
+// * inserted at the top of the widget. A call to LVM_GETTOPINDEX will
+// * return a negative number (this is an impossible result). The fix
+// * is to use LVM_GETCOUNTPERPAGE to detect the case when the number
+// * of visible items is zero and use LVM_ENSUREVISIBLE with the
+// * fPartialOK flag set to true to scroll the table.
+// */
+// if (OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0) <= 0) {
+// /*
+// * Bug in Windows. For some reason, LVM_ENSUREVISIBLE can
+// * scroll one item more or one item less when there is not
+// * enough space to show a single table item. The fix is
+// * to detect the case and call LVM_ENSUREVISIBLE again with
+// * the same arguments. It seems that once LVM_ENSUREVISIBLE
+// * has scrolled into the general area, it is able to scroll
+// * to the exact item.
+// */
+// OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 1);
+// if (index != OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0)) {
+// OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 1);
+// }
+// } else {
+// OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 0);
+// }
+//}
+
+/**
+ * Shows the item. If the item is already showing in the receiver,
+ * this method simply returns. Otherwise, the items are scrolled until
+ * the item is visible.
+ *
+ * @param item the item to be shown
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the item is null
+ *
ERROR_INVALID_ARGUMENT - if the item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#showSelection()
+ */
+public void showItem (TableItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ int index = indexOf (item);
+ if (index != -1) {
+ ((CTable)handle).ensureRowVisible(index);
+ }
+}
+
+/**
+ * Shows the selection. If the selection is already showing in the receiver,
+ * this method simply returns. Otherwise, the items are scrolled until
+ * the selection is visible.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#showItem(TableItem)
+ */
+public void showSelection () {
+ checkWidget ();
+ int selectionIndex = getSelectionIndex();
+ if(selectionIndex == -1) {
+ return;
+ }
+ ((CTable)handle).ensureRowVisible(selectionIndex);
+}
+
+static int checkStyle (int style) {
+ style |= SWT.H_SCROLL | SWT.V_SCROLL;
+ return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+}
+
+//String toolTipText (NMTTDISPINFO hdr) {
+// int hwndToolTip = OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0);
+// if (hwndToolTip == hdr.hwndFrom && toolTipText != null) return ""; //$NON-NLS-1$
+// return super.toolTipText (hdr);
+//}
+//
+//int widgetStyle () {
+// int bits = super.widgetStyle () | OS.LVS_SHAREIMAGELISTS;
+// if ((style & SWT.HIDE_SELECTION) == 0) bits |= OS.LVS_SHOWSELALWAYS;
+// if ((style & SWT.SINGLE) != 0) bits |= OS.LVS_SINGLESEL;
+// /*
+// * This code is intentionally commented. In the future,
+// * the FLAT bit may be used to make the header flat and
+// * unresponsive to mouse clicks.
+// */
+//// if ((style & SWT.FLAT) != 0) bits |= OS.LVS_NOSORTHEADER;
+// bits |= OS.LVS_REPORT | OS.LVS_NOCOLUMNHEADER;
+// if ((style & SWT.VIRTUAL) != 0) bits |= OS.LVS_OWNERDATA;
+// return bits;
+//}
+//
+//TCHAR windowClass () {
+// return TableClass;
+//}
+//
+//int windowProc () {
+// return TableProc;
+//}
+//
+//LRESULT WM_CHAR (int wParam, int lParam) {
+// LRESULT result = super.WM_CHAR (wParam, lParam);
+// if (result != null) return result;
+// switch (wParam) {
+// case SWT.CR:
+// /*
+// * Feature in Windows. Windows sends LVN_ITEMACTIVATE from WM_KEYDOWN
+// * instead of WM_CHAR. This means that application code that expects
+// * to consume the key press and therefore avoid a SWT.DefaultSelection
+// * event will fail. The fix is to ignore LVN_ITEMACTIVATE when it is
+// * caused by WM_KEYDOWN and send SWT.DefaultSelection from WM_CHAR.
+// */
+// int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+// if (index != -1) {
+// Event event = new Event ();
+// event.item = _getItem (index);
+// postEvent (SWT.DefaultSelection, event);
+// }
+// return LRESULT.ZERO;
+// }
+// return result;
+//}
+//
+//LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+// LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * This code is intentionally commented. When a table contains
+// * images that are not in the first column, the work around causes
+// * pixel corruption.
+// */
+//// if (!OS.IsWindowEnabled (handle)) return result;
+//// /*
+//// * Feature in Windows. When WM_ERASEBKGND is called,
+//// * it clears the damaged area by filling it with the
+//// * background color. During WM_PAINT, when the table
+//// * items are drawn, the background for each item is
+//// * also drawn, causing flashing. The fix is to adjust
+//// * the damage by subtracting the bounds of each visible
+//// * table item.
+//// */
+//// int itemCount = getItemCount ();
+//// if (itemCount == 0) return result;
+//// GCData data = new GCData();
+//// data.device = display;
+//// GC gc = GC.win32_new (wParam, data);
+//// Region region = new Region (display);
+//// gc.getClipping (region);
+//// int columnCount = Math.max (1, getColumnCount ());
+//// Rectangle clientArea = getClientArea ();
+//// int i = getTopIndex ();
+//// int bottomIndex = i + OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0);
+//// bottomIndex = Math.min (itemCount, bottomIndex);
+//// while (i < bottomIndex) {
+//// int j = 0;
+//// while (j < columnCount) {
+//// if (j != 0 || (!isSelected (i) && i != getFocusIndex ())) {
+//// RECT rect = new RECT ();
+//// rect.top = j;
+//// rect.left = OS.LVIR_LABEL;
+//// OS.SendMessage (handle, OS. LVM_GETSUBITEMRECT, i, rect);
+//// int width = Math.max (0, rect.right - rect.left);
+//// int height = Math.max (0, rect.bottom - rect.top);
+//// Rectangle rect2 = new Rectangle (rect.left, rect.top, width, height);
+//// if (!rect2.intersects (clientArea)) break;
+//// region.subtract (rect2);
+//// }
+//// j++;
+//// }
+//// i++;
+//// }
+//// gc.setClipping (region);
+//// drawBackground (wParam);
+//// gc.setClipping ((Region) null);
+//// region.dispose ();
+//// gc.dispose ();
+//// return LRESULT.ONE;
+// return result;
+//}
+//
+//LRESULT WM_GETOBJECT (int wParam, int lParam) {
+// /*
+// * Ensure that there is an accessible object created for this
+// * control because support for checked item accessibility is
+// * temporarily implemented in the accessibility package.
+// */
+// if ((style & SWT.CHECK) != 0) {
+// if (accessible == null) accessible = new_Accessible (this);
+// }
+// return super.WM_GETOBJECT (wParam, lParam);
+//}
+//
+//LRESULT WM_KEYDOWN (int wParam, int lParam) {
+// LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+// if (result != null) return result;
+// if ((style & SWT.CHECK) != 0 && wParam == OS.VK_SPACE) {
+// int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+// if (index != -1) {
+// TableItem item = _getItem (index);
+// item.setChecked (!item.getChecked (), true);
+// if (!OS.IsWinCE) {
+// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, index + 1);
+// }
+// }
+// }
+// return result;
+//}
+//
+//LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
+// mouseDown = true;
+//
+// /*
+// * Feature in Windows. When the user selects outside of
+// * a table item, Windows deselects all the items, even
+// * when the table is multi-select. While not strictly
+// * wrong, this is unexpected. The fix is to detect the
+// * case and avoid calling the window proc.
+// */
+// LVHITTESTINFO pinfo = new LVHITTESTINFO ();
+// pinfo.x = (short) (lParam & 0xFFFF);
+// pinfo.y = (short) (lParam >> 16);
+// int index = OS.SendMessage (handle, OS.LVM_HITTEST, 0, pinfo);
+// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+// sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_LBUTTONDBLCLK, wParam, lParam);
+// if (pinfo.iItem != -1) callWindowProc (handle, OS.WM_LBUTTONDBLCLK, wParam, lParam);
+// if (OS.GetCapture () != handle) OS.SetCapture (handle);
+//
+// /* Look for check/uncheck */
+// if ((style & SWT.CHECK) != 0) {
+// /*
+// * Note that when the table has LVS_EX_FULLROWSELECT and the
+// * user clicks anywhere on a row except on the check box, all
+// * of the bits are set. The hit test flags are LVHT_ONITEM.
+// * This means that a bit test for LVHT_ONITEMSTATEICON is not
+// * the correct way to determine that the user has selected
+// * the check box, equality is needed.
+// */
+// if (index != -1 && pinfo.flags == OS.LVHT_ONITEMSTATEICON) {
+// TableItem item = _getItem (index);
+// item.setChecked (!item.getChecked (), true);
+// if (!OS.IsWinCE) {
+// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, index + 1);
+// }
+// }
+// }
+// return LRESULT.ZERO;
+//}
+//
+//LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+// mouseDown = true;
+//
+// /*
+// * Feature in Windows. For some reason, capturing
+// * the mouse after processing the mouse event for the
+// * widget interferes with the normal mouse processing
+// * for the widget. The fix is to avoid the automatic
+// * mouse capture.
+// */
+// LRESULT result = sendMouseDownEvent (SWT.MouseDown, 1, OS.WM_LBUTTONDOWN, wParam, lParam);
+//
+// /* Look for check/uncheck */
+// if ((style & SWT.CHECK) != 0) {
+// LVHITTESTINFO pinfo = new LVHITTESTINFO ();
+// pinfo.x = (short) (lParam & 0xFFFF);
+// pinfo.y = (short) (lParam >> 16);
+// /*
+// * Note that when the table has LVS_EX_FULLROWSELECT and the
+// * user clicks anywhere on a row except on the check box, all
+// * of the bits are set. The hit test flags are LVHT_ONITEM.
+// * This means that a bit test for LVHT_ONITEMSTATEICON is not
+// * the correct way to determine that the user has selected
+// * the check box, equality is needed.
+// */
+// int index = OS.SendMessage (handle, OS.LVM_HITTEST, 0, pinfo);
+// if (index != -1 && pinfo.flags == OS.LVHT_ONITEMSTATEICON) {
+// TableItem item = _getItem (index);
+// item.setChecked (!item.getChecked (), true);
+// if (!OS.IsWinCE) {
+// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, index + 1);
+// }
+// }
+// }
+//
+// return result;
+//}
+//
+//LRESULT WM_LBUTTONUP (int wParam, int lParam) {
+// mouseDown = false;
+// return super.WM_LBUTTONUP (wParam, lParam);
+//}
+//
+//LRESULT WM_MOUSEHOVER (int wParam, int lParam) {
+// /*
+// * Feature in Windows. Despite the fact that hot
+// * tracking is not enabled, the hot tracking code
+// * in WM_MOUSEHOVER is executed causing the item
+// * under the cursor to be selected. The fix is to
+// * avoid calling the window proc.
+// */
+// LRESULT result = super.WM_MOUSEHOVER (wParam, lParam);
+// int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+// int mask = OS.LVS_EX_ONECLICKACTIVATE | OS.LVS_EX_TRACKSELECT | OS.LVS_EX_TWOCLICKACTIVATE;
+// if ((bits & mask) != 0) return result;
+// return LRESULT.ZERO;
+//}
+//
+//LRESULT WM_PAINT (int wParam, int lParam) {
+// if (!ignoreShrink) {
+// /* Resize the item array to match the item count */
+// int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+// if (items.length > 4 && items.length - count > 3) {
+// int length = Math.max (4, (count + 3) / 4 * 4);
+// TableItem [] newItems = new TableItem [length];
+// System.arraycopy (items, 0, newItems, 0, count);
+// items = newItems;
+// }
+// }
+// if (fixScrollWidth) setScrollWidth (null, true);
+// return super.WM_PAINT (wParam, lParam);
+//}
+//
+//LRESULT WM_NOTIFY (int wParam, int lParam) {
+// NMHDR hdr = new NMHDR ();
+// OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+// if (hdr.hwndFrom == hwndHeader) {
+// /*
+// * Feature in Windows. On NT, the automatically created
+// * header control is created as a UNICODE window, not an
+// * ANSI window despite the fact that the parent is created
+// * as an ANSI window. This means that it sends UNICODE
+// * notification messages to the parent window on NT for
+// * no good reason. The data and size in the NMHEADER and
+// * HDITEM structs is identical between the platforms so no
+// * different message is actually necessary. Despite this,
+// * Windows sends different messages. The fix is to look
+// * for both messages, despite the platform. This works
+// * because only one will be sent on either platform, never
+// * both.
+// */
+// switch (hdr.code) {
+// case OS.HDN_BEGINTRACKW:
+// case OS.HDN_BEGINTRACKA:
+// case OS.HDN_DIVIDERDBLCLICKW:
+// case OS.HDN_DIVIDERDBLCLICKA: {
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// if (count == 1 && columns [0] == null) return LRESULT.ONE;
+// NMHEADER phdn = new NMHEADER ();
+// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+// TableColumn column = columns [phdn.iItem];
+// if (column != null && !column.getResizable ()) {
+// return LRESULT.ONE;
+// }
+// break;
+// }
+// case OS.HDN_BEGINDRAG: {
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// if (count == 1 && columns [0] == null) return LRESULT.ONE;
+// NMHEADER phdn = new NMHEADER ();
+// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+// if (phdn.iItem != -1) {
+// TableColumn column = columns [phdn.iItem];
+// if (column != null && !column.getMoveable ()) {
+// OS.ReleaseCapture ();
+// return LRESULT.ONE;
+// }
+// }
+// break;
+// }
+// case OS.HDN_ENDDRAG: {
+// NMHEADER phdn = new NMHEADER ();
+// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+// if (phdn.iItem != -1 && phdn.pitem != 0) {
+// HDITEM pitem = new HDITEM ();
+// OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
+// if ((pitem.mask & OS.HDI_ORDER) != 0 && pitem.iOrder != -1) {
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// if (count == 1 && columns [0] == null) break;
+// int [] order = new int [count];
+// OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, count, order);
+// int index = 0;
+// while (index < order.length) {
+// if (order [index] == phdn.iItem) break;
+// index++;
+// }
+// if (index == order.length) index = 0;
+// if (index == pitem.iOrder) break;
+// int start = Math.min (index, pitem.iOrder);
+// int end = Math.max (index, pitem.iOrder);
+// for (int i=start; i<=end; i++) {
+// TableColumn column = columns [order [i]];
+// if (!column.isDisposed ()) {
+// column.postEvent (SWT.Move);
+// }
+// }
+// }
+// }
+// break;
+// }
+// case OS.HDN_ITEMCHANGEDW:
+// case OS.HDN_ITEMCHANGEDA: {
+// /*
+// * Bug in Windows. When a table has the LVS_EX_GRIDLINES extended
+// * style and the user drags any column over the first column in the
+// * table, making the size become zero, when the user drags a column
+// * such that the size of the first column becomes non-zero, the grid
+// * lines are not redrawn. The fix is to detect the case and force
+// * a redraw of the first column.
+// */
+// int width = OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0);
+// if (lastWidth == 0 && width > 0) {
+// int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+// if ((bits & OS.LVS_EX_GRIDLINES) != 0) {
+// RECT rect = new RECT ();
+// OS.GetClientRect (handle, rect);
+// rect.right = rect.left + width;
+// OS.InvalidateRect (handle, rect, true);
+// }
+// }
+// lastWidth = width;
+// if (!ignoreResize) {
+// NMHEADER phdn = new NMHEADER ();
+// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+// if (phdn.pitem != 0) {
+// HDITEM pitem = new HDITEM ();
+// OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
+// if ((pitem.mask & OS.HDI_WIDTH) != 0) {
+// TableColumn column = columns [phdn.iItem];
+// if (column != null) {
+// column.sendEvent (SWT.Resize);
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the resize
+// * event. If this happens, end the processing of the
+// * Windows message by returning zero as the result of
+// * the window proc.
+// */
+// if (isDisposed ()) return LRESULT.ZERO;
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// if (count == 1 && columns [0] == null) count = 0;
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the column in the move
+// * event. If this happens, process the move event
+// * for those columns that have not been destroyed.
+// */
+// TableColumn [] newColumns = new TableColumn [count];
+// System.arraycopy (columns, 0, newColumns, 0, count);
+// int [] order = new int [count];
+// OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, count, order);
+// boolean moved = false;
+// for (int i=0; i> 16);
+// OS.SendMessage (handle, OS.LVM_HITTEST, 0, pinfo);
+// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_RBUTTONDOWN, wParam, lParam);
+// sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_RBUTTONDBLCLK, wParam, lParam);
+// if (pinfo.iItem != -1) callWindowProc (handle, OS.WM_RBUTTONDBLCLK, wParam, lParam);
+// if (OS.GetCapture () != handle) OS.SetCapture (handle);
+// return LRESULT.ZERO;
+//}
+//
+//LRESULT WM_RBUTTONDOWN (int wParam, int lParam) {
+// /*
+// * Feature in Windows. For some reason, capturing
+// * the mouse after processing the mouse event for the
+// * widget interferes with the normal mouse processing
+// * for the widget. The fix is to avoid the automatic
+// * mouse capture.
+// */
+// return sendMouseDownEvent (SWT.MouseDown, 3, OS.WM_RBUTTONDOWN, wParam, lParam);
+//}
+//
+//LRESULT WM_SETFOCUS (int wParam, int lParam) {
+// LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+// /*
+// * Bug in Windows. For some reason, the table does
+// * not set the default focus rectangle to be the first
+// * item in the table when it gets focus and there is
+// * no selected item. The fix to make the first item
+// * be the focus item.
+// */
+// int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+// if (count == 0) return result;
+// int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+// if (index == -1) {
+// LVITEM lvItem = new LVITEM ();
+// lvItem.state = OS.LVIS_FOCUSED;
+// lvItem.stateMask = OS.LVIS_FOCUSED;
+// ignoreSelect = true;
+// OS.SendMessage (handle, OS.LVM_SETITEMSTATE, 0, lvItem);
+// ignoreSelect = false;
+// }
+// return result;
+//}
+//
+//LRESULT WM_SIZE (int wParam, int lParam) {
+// /*
+// * Bug in Windows. If the table column widths are adjusted
+// * in WM_SIZE, blank lines may be inserted at the top of the
+// * widget. A call to LVM_GETTOPINDEX will return a negative
+// * number (this is an impossible result). The fix is to do
+// * the WM_SIZE processing in WM_WINDOWPOSCHANGED after the
+// * table has been updated.
+// */
+// return null;
+//}
+//
+//LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
+// LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+// if (result != null) return result;
+// if (background == -1) {
+// int pixel = defaultBackground ();
+// OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, pixel);
+// OS.SendMessage (handle, OS.LVM_SETTEXTBKCOLOR, 0, pixel);
+// }
+// if ((style & SWT.CHECK) != 0) setCheckboxImageListColor ();
+// return result;
+//}
+//
+//LRESULT WM_VSCROLL (int wParam, int lParam) {
+// LRESULT result = super.WM_VSCROLL (wParam, lParam);
+// /*
+// * Bug in Windows. When a table is drawing grid lines and the
+// * user scrolls vertically up or down by a line or a page, the
+// * table does not redraw the grid lines for newly exposed items.
+// * The fix is to invalidate the items.
+// */
+// int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+// if ((bits & OS.LVS_EX_GRIDLINES) != 0) {
+// int code = wParam & 0xFFFF;
+// switch (code) {
+// case OS.SB_THUMBPOSITION:
+// case OS.SB_ENDSCROLL:
+// case OS.SB_THUMBTRACK:
+// case OS.SB_TOP:
+// case OS.SB_BOTTOM:
+// break;
+// case OS.SB_LINEDOWN:
+// case OS.SB_LINEUP:
+// int headerHeight = 0;
+// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+// if (hwndHeader != 0) {
+// RECT rect = new RECT ();
+// OS.GetWindowRect (hwndHeader, rect);
+// headerHeight = rect.bottom - rect.top;
+// }
+// RECT rect = new RECT ();
+// OS.GetClientRect (handle, rect);
+// rect.top += headerHeight;
+// int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+// int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
+// int itemHeight = (oneItem >> 16) - (empty >> 16);
+// if (code == OS.SB_LINEDOWN) {
+// rect.top = rect.bottom - itemHeight - GRID_WIDTH;
+// } else {
+// rect.bottom = rect.top + itemHeight + GRID_WIDTH;
+// }
+// OS.InvalidateRect (handle, rect, true);
+// break;
+// case OS.SB_PAGEDOWN:
+// case OS.SB_PAGEUP:
+// OS.InvalidateRect (handle, null, true);
+// break;
+// }
+// }
+// return result;
+//}
+//
+//LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) {
+// if (ignoreResize) return null;
+// LRESULT result = super.WM_WINDOWPOSCHANGED (wParam, lParam);
+// if (result != null) return result;
+// WINDOWPOS lpwp = new WINDOWPOS ();
+// OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+// if ((lpwp.flags & OS.SWP_NOSIZE) == 0) {
+// setResizeChildren (false);
+// int code = callWindowProc (handle, OS.WM_WINDOWPOSCHANGED, wParam, lParam);
+// sendEvent (SWT.Resize);
+// if (isDisposed ()) return new LRESULT (code);
+// if (layout != null) {
+// markLayout (false, false);
+// updateLayout (false, false);
+// }
+// setResizeChildren (true);
+// return new LRESULT (code);
+// }
+// return result;
+//}
+//
+//LRESULT wmNotifyChild (int wParam, int lParam) {
+// NMHDR hdr = new NMHDR ();
+// OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+// switch (hdr.code) {
+// case OS.LVN_ODFINDITEMA:
+// case OS.LVN_ODFINDITEMW: {
+// if ((style & SWT.VIRTUAL) != 0) {
+// NMLVFINDITEM pnmfi = new NMLVFINDITEM ();
+// OS.MoveMemory (pnmfi, lParam, NMLVFINDITEM.sizeof);
+// int index = Math.max (0, pnmfi.iStart - 1);
+// return new LRESULT (index);
+// }
+// break;
+// }
+// case OS.LVN_GETDISPINFOA:
+// case OS.LVN_GETDISPINFOW: {
+//// if (drawCount != 0 || !OS.IsWindowVisible (handle)) break;
+// NMLVDISPINFO plvfi = new NMLVDISPINFO ();
+// OS.MoveMemory (plvfi, lParam, NMLVDISPINFO.sizeof);
+// lastIndexOf = plvfi.iItem;
+// TableItem item = _getItem (plvfi.iItem);
+// /*
+// * The cached flag is used by both virtual and non-virtual
+// * tables to indicate that Windows has asked at least once
+// * for a table item.
+// */
+// if (!item.cached) {
+// if ((style & SWT.VIRTUAL) != 0) {
+// if (!checkData (item, false)) break;
+// TableItem newItem = fixScrollWidth ? null : item;
+// if (setScrollWidth (newItem, true)) {
+// OS.InvalidateRect (handle, null, true);
+// }
+// }
+// item.cached = true;
+// }
+// if ((plvfi.mask & OS.LVIF_TEXT) != 0) {
+// String string = null;
+// if (plvfi.iSubItem == 0) {
+// string = item.text;
+// } else {
+// String [] strings = item.strings;
+// if (strings != null) string = strings [plvfi.iSubItem];
+// }
+// if (string != null) {
+// /*
+// * Bug in Windows. When pszText points to a zero length
+// * NULL terminated string, Windows correctly draws the
+// * empty string but the cache of the bounds for the item
+// * is not reset. This means that when the text for the
+// * item is set and then reset to an empty string, the
+// * selection draws using the bounds of the previous text.
+// * The fix is to use a space rather than an empty string
+// * when anything but a tool tip is requested (to avoid
+// * a tool tip that is a single space).
+// *
+// * NOTE: This is only a problem for items in the first
+// * column. Assigning NULL to other columns stops Windows
+// * from drawing the selection when LVS_EX_FULLROWSELECT
+// * is set.
+// */
+// if (!tipRequested && string.length () == 0 && plvfi.iSubItem == 0) {
+// string = " "; //$NON-NLS-1$
+// }
+// TCHAR buffer = new TCHAR (getCodePage (), string, false);
+// int byteCount = Math.min (buffer.length (), plvfi.cchTextMax - 1) * TCHAR.sizeof;
+// OS.MoveMemory (plvfi.pszText, buffer, byteCount);
+// OS.MoveMemory (plvfi.pszText + byteCount, new byte [TCHAR.sizeof], TCHAR.sizeof);
+// plvfi.cchTextMax = Math.min (plvfi.cchTextMax, string.length () + 1);
+// }
+// }
+// if ((plvfi.mask & OS.LVIF_IMAGE) != 0) {
+// Image image = null;
+// if (plvfi.iSubItem == 0) {
+// image = item.image;
+// } else {
+// Image [] images = item.images;
+// if (images != null) image = images [plvfi.iSubItem];
+// }
+// if (image != null) plvfi.iImage = imageIndex (image);
+// }
+// if ((plvfi.mask & OS.LVIF_STATE) != 0) {
+// if (plvfi.iSubItem == 0) {
+// int state = 1;
+// if (item.checked) state++;
+// if (item.grayed) state +=2;
+// plvfi.state = state << 12;
+// plvfi.stateMask = OS.LVIS_STATEIMAGEMASK;
+// }
+// }
+// if ((plvfi.mask & OS.LVIF_INDENT) != 0) {
+// if (plvfi.iSubItem == 0) plvfi.iIndent = item.imageIndent;
+// }
+// OS.MoveMemory (lParam, plvfi, NMLVDISPINFO.sizeof);
+// break;
+// }
+// case OS.NM_CUSTOMDRAW: {
+// if (!customDraw) break;
+// NMLVCUSTOMDRAW nmcd = new NMLVCUSTOMDRAW ();
+// OS.MoveMemory (nmcd, lParam, NMLVCUSTOMDRAW.sizeof);
+// switch (nmcd.dwDrawStage) {
+// case OS.CDDS_PREPAINT: return new LRESULT (OS.CDRF_NOTIFYITEMDRAW);
+// case OS.CDDS_ITEMPREPAINT: return new LRESULT (OS.CDRF_NOTIFYSUBITEMDRAW);
+// case OS.CDDS_ITEMPREPAINT | OS.CDDS_SUBITEM: {
+// TableItem item = _getItem (nmcd.dwItemSpec);
+// int hFont = item.cellFont != null ? item.cellFont [nmcd.iSubItem] : -1;
+// if (hFont == -1) hFont = item.font;
+// int clrText = item.cellForeground != null ? item.cellForeground [nmcd.iSubItem] : -1;
+// if (clrText == -1) clrText = item.foreground;
+// int clrTextBk = item.cellBackground != null ? item.cellBackground [nmcd.iSubItem] : -1;
+// if (clrTextBk == -1) clrTextBk = item.background;
+// /*
+// * Feature in Windows. When the font is set for one cell in a table,
+// * Windows does not reset the font for the next cell. As a result,
+// * all subsequent cells are drawn using the new font. The fix is to
+// * reset the font to the default.
+// *
+// * NOTE: This does not happen for foreground and background.
+// */
+// if (hFont == -1 && clrText == -1 && clrTextBk == -1) {
+// if (item.cellForeground == null && item.cellBackground == null && item.cellFont == null) {
+// int hwndHeader = OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// if (count == 1) break;
+// }
+// }
+// if (hFont == -1) hFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+// OS.SelectObject (nmcd.hdc, hFont);
+// if (OS.IsWindowEnabled (handle)) {
+// nmcd.clrText = clrText == -1 ? getForegroundPixel () : clrText;
+// nmcd.clrTextBk = clrTextBk == -1 ? getBackgroundPixel () : clrTextBk;
+// OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof);
+// }
+// return new LRESULT (OS.CDRF_NEWFONT);
+// }
+// }
+// break;
+// }
+// case OS.LVN_MARQUEEBEGIN: return LRESULT.ONE;
+// case OS.LVN_BEGINDRAG:
+// case OS.LVN_BEGINRDRAG: {
+// dragStarted = true;
+// if (hdr.code == OS.LVN_BEGINDRAG) {
+// int pos = OS.GetMessagePos ();
+// POINT pt = new POINT ();
+// pt.x = (short) (pos & 0xFFFF);
+// pt.y = (short) (pos >> 16);
+// OS.ScreenToClient (handle, pt);
+// Event event = new Event ();
+// event.x = pt.x;
+// event.y = pt.y;
+// postEvent (SWT.DragDetect, event);
+// }
+// break;
+// }
+// case OS.LVN_COLUMNCLICK: {
+// NMLISTVIEW pnmlv = new NMLISTVIEW ();
+// OS.MoveMemory(pnmlv, lParam, NMLISTVIEW.sizeof);
+// TableColumn column = columns [pnmlv.iSubItem];
+// if (column != null) {
+// column.postEvent (SWT.Selection);
+// }
+// break;
+// }
+// case OS.LVN_ITEMACTIVATE: {
+// if (ignoreActivate) break;
+// NMLISTVIEW pnmlv = new NMLISTVIEW ();
+// OS.MoveMemory(pnmlv, lParam, NMLISTVIEW.sizeof);
+// if (pnmlv.iItem != -1) {
+// Event event = new Event ();
+// event.item = _getItem (pnmlv.iItem);
+// postEvent (SWT.DefaultSelection, event);
+// }
+// break;
+// }
+// case OS.LVN_ITEMCHANGED: {
+// if (!ignoreSelect) {
+// NMLISTVIEW pnmlv = new NMLISTVIEW ();
+// OS.MoveMemory (pnmlv, lParam, NMLISTVIEW.sizeof);
+// if (pnmlv.iItem != -1 && (pnmlv.uChanged & OS.LVIF_STATE) != 0) {
+// boolean isFocus = (pnmlv.uNewState & OS.LVIS_FOCUSED) != 0;
+// int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+// if ((style & SWT.MULTI) != 0) {
+// if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
+// if (!isFocus) {
+// if (index == pnmlv.iItem) {
+// boolean isSelected = (pnmlv.uNewState & OS.LVIS_SELECTED) != 0;
+// boolean wasSelected = (pnmlv.uOldState & OS.LVIS_SELECTED) != 0;
+// isFocus = isSelected != wasSelected;
+// }
+// } else {
+// isFocus = mouseDown;
+// }
+// }
+// }
+// if (OS.GetKeyState (OS.VK_SPACE) < 0) isFocus = true;
+// if (isFocus) {
+// Event event = new Event();
+// if (index != -1) {
+// /*
+// * This code is intentionally commented.
+// */
+//// OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 0);
+// event.item = _getItem (index);
+// }
+// postEvent (SWT.Selection, event);
+// }
+// }
+// }
+// break;
+// }
+// case OS.NM_RECOGNIZEGESTURE:
+// /*
+// * Feature on Pocket PC. The tree and table controls detect the tap
+// * and hold gesture by default. They send a GN_CONTEXTMENU message to show
+// * the popup menu. This default behaviour is unwanted on Pocket PC 2002
+// * when no menu has been set, as it still draws a red circle. The fix
+// * is to disable this default behaviour when no menu is set by returning
+// * TRUE when receiving the Pocket PC 2002 specific NM_RECOGNIZEGESTURE
+// * message.
+// */
+// if (OS.IsPPC) {
+// boolean hasMenu = menu != null && !menu.isDisposed ();
+// if (!hasMenu && !hooks (SWT.MenuDetect)) return LRESULT.ONE;
+// }
+// break;
+// case OS.GN_CONTEXTMENU:
+// if (OS.IsPPC) {
+// boolean hasMenu = menu != null && !menu.isDisposed ();
+// if (hasMenu || hooks (SWT.MenuDetect)) {
+// NMRGINFO nmrg = new NMRGINFO ();
+// OS.MoveMemory (nmrg, lParam, NMRGINFO.sizeof);
+// showMenu (nmrg.x, nmrg.y);
+// return LRESULT.ONE;
+// }
+// }
+// break;
+// }
+// return super.wmNotifyChild (wParam, lParam);
+//}
+
+public void processEvent(EventObject e) {
+ if(e instanceof CellPaintEvent) {
+ switch(((CellPaintEvent)e).getType()) {
+ case CellPaintEvent.ERASE_TYPE: if(!hooks(SWT.EraseItem)) { super.processEvent(e); return; } break;
+ case CellPaintEvent.PAINT_TYPE: if(!hooks(SWT.PaintItem)) { super.processEvent(e); return; } break;
+ case CellPaintEvent.MEASURE_TYPE: if(!hooks(SWT.MeasureItem)) { super.processEvent(e); return; } break;
+ default: super.processEvent(e); return;
+ }
+ } else if(e instanceof ListSelectionEvent) {
+ if(!hooks(SWT.Selection) || isAdjustingSelection) { super.processEvent(e); return; };
+ } else {
+ super.processEvent(e);
+ return;
+ }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ if(e instanceof CellPaintEvent) {
+ CellPaintEvent cellPaintEvent = (CellPaintEvent)e;
+ switch(cellPaintEvent.getType()) {
+ case CellPaintEvent.ERASE_TYPE: {
+ TableItem tableItem = cellPaintEvent.tableItem.getTableItem();
+ Rectangle cellBounds = tableItem.getBounds(cellPaintEvent.column);
+ Event event = new Event();
+ event.x = cellBounds.x;
+ event.y = cellBounds.y;
+ event.width = cellBounds.width;
+ event.height = cellBounds.height;
+ event.item = tableItem;
+ event.index = cellPaintEvent.column;
+ if(!cellPaintEvent.ignoreDrawForeground) event.detail |= SWT.FOREGROUND;
+ if(!cellPaintEvent.ignoreDrawBackground) event.detail |= SWT.BACKGROUND;
+ if(!cellPaintEvent.ignoreDrawSelection) event.detail |= SWT.SELECTED;
+ if(!cellPaintEvent.ignoreDrawFocused) event.detail |= SWT.FOCUSED;
+ event.gc = new GC(this);
+ event.gc.handle.setUserClip(((CTable)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false));
+// event.gc.isSwingPainting = true;
+ sendEvent(SWT.EraseItem, event);
+ if(event.doit) {
+ cellPaintEvent.ignoreDrawForeground = (event.detail & SWT.FOREGROUND) == 0;
+ cellPaintEvent.ignoreDrawBackground = (event.detail & SWT.BACKGROUND) == 0;
+ cellPaintEvent.ignoreDrawSelection = (event.detail & SWT.SELECTED) == 0;
+ cellPaintEvent.ignoreDrawFocused = (event.detail & SWT.FOCUSED) == 0;
+ } else {
+ cellPaintEvent.ignoreDrawForeground = true;
+ cellPaintEvent.ignoreDrawBackground = true;
+ cellPaintEvent.ignoreDrawSelection = true;
+ cellPaintEvent.ignoreDrawFocused = true;
+ }
+// event.gc.isSwingPainting = false;
+ break;
+ }
+ case CellPaintEvent.PAINT_TYPE: {
+ TableItem tableItem = cellPaintEvent.tableItem.getTableItem();
+ Rectangle cellBounds = tableItem.getBounds(cellPaintEvent.column);
+ Event event = new Event();
+ event.x = cellBounds.x;
+ event.y = cellBounds.y;
+ event.width = cellBounds.width;
+ event.height = cellBounds.height;
+ event.item = tableItem;
+ event.index = cellPaintEvent.column;
+ if(!cellPaintEvent.ignoreDrawForeground) event.detail |= SWT.FOREGROUND;
+ if(!cellPaintEvent.ignoreDrawBackground) event.detail |= SWT.BACKGROUND;
+ if(!cellPaintEvent.ignoreDrawSelection) event.detail |= SWT.SELECTED;
+ if(!cellPaintEvent.ignoreDrawFocused) event.detail |= SWT.FOCUSED;
+ event.gc = new GC(this);
+ event.gc.handle.setUserClip(((CTable)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false));
+ sendEvent(SWT.PaintItem, event);
+ break;
+ }
+ case CellPaintEvent.MEASURE_TYPE:
+ TableItem tableItem = cellPaintEvent.tableItem.getTableItem();
+// Rectangle cellBounds = tableItem.getBounds(cellPaintEvent.column);
+ Event event = new Event();
+// event.x = cellBounds.x;
+// event.y = cellBounds.y;
+// event.width = cellBounds.width;
+// event.height = cellBounds.height;
+ event.height = cellPaintEvent.rowHeight;
+ event.item = tableItem;
+ event.index = cellPaintEvent.column;
+ event.gc = new GC(this);
+// event.gc.handle.clip(((CTable)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false));
+ sendEvent(SWT.MeasureItem, event);
+// cellPaintEvent.rowHeight -= event.height - cellBounds.height;
+ cellPaintEvent.rowHeight = event.height;
+ break;
+ }
+ } else if(e instanceof ListSelectionEvent) {
+ if(!((ListSelectionEvent)e).getValueIsAdjusting()) {
+ Event event = new Event ();
+ int selectionIndex = ((CTable)handle).getSelectionModel().getLeadSelectionIndex();
+ if(selectionIndex != -1) {
+ // TODO: should we send the previous item?
+ event.item = _getItem(selectionIndex);
+ }
+ sendEvent(SWT.Selection, event);
+ }
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+public void processEvent(AWTEvent e) {
+ int id = e.getID();
+ switch(id) {
+ case KeyEvent.KEY_PRESSED: {
+ KeyEvent ke = (KeyEvent)e;
+ if(ke.getKeyCode() != KeyEvent.VK_ENTER || ((CTable)handle).getSelectionModel().getLeadSelectionIndex() == -1 || !hooks(SWT.DefaultSelection)) { super.processEvent(e); return; } break;
+ }
+ case MouseEvent.MOUSE_PRESSED: {
+ MouseEvent me = (MouseEvent)e;
+ if(me.getID() != MouseEvent.MOUSE_PRESSED || me.getClickCount() != 2 || ((CTable)handle).getSelectionModel().getLeadSelectionIndex() == -1 || !hooks(SWT.DefaultSelection)) {
+ super.processEvent(e);
+ return;
+ };
+ break;
+ }
+ case ItemEvent.ITEM_STATE_CHANGED: if(!hooks(SWT.Selection) || isAdjustingSelection) { super.processEvent(e); return; } break;
+ default: { super.processEvent(e); return; }
+ }
+ if(isDisposed()) {
+ super.processEvent(e);
+ return;
+ }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ switch(id) {
+ case KeyEvent.KEY_PRESSED:
+ if(((CTable)handle).getSelectionModel().getLeadSelectionIndex() != -1) {
+ Event event = new Event ();
+ event.item = _getItem(((CTable)handle).getSelectionModel().getLeadSelectionIndex());
+ sendEvent(SWT.DefaultSelection, event);
+ }
+ break;
+ case MouseEvent.MOUSE_PRESSED:
+ if(((CTable)handle).getSelectionModel().getLeadSelectionIndex() != -1) {
+ Event event = new Event ();
+ event.item = _getItem(((CTable)handle).getSelectionModel().getLeadSelectionIndex());
+ sendEvent(SWT.DefaultSelection, event);
+ }
+ break;
+ case ItemEvent.ITEM_STATE_CHANGED:
+ Event event = new Event();
+ event.detail = SWT.CHECK;
+ event.item = ((CTableItem)((ItemEvent)e).getItem()).getTableItem();
+ sendEvent(SWT.Selection, event);
+ break;
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TableColumn.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TableColumn.java
new file mode 100644
index 00000000000..4535f6de48d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TableColumn.java
@@ -0,0 +1,686 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.AWTEvent;
+import java.beans.PropertyChangeEvent;
+import java.util.EventObject;
+
+import javax.swing.ImageIcon;
+import javax.swing.SwingConstants;
+import javax.swing.event.TableColumnModelEvent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.internal.swing.CTable;
+import org.eclipse.swt.internal.swing.CTableColumn;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+
+/**
+ * Instances of this class represent a column in a table widget.
+ *
+ *
Styles:
+ *
LEFT, RIGHT, CENTER
+ *
Events:
+ *
Move, Resize, Selection
+ *
+ *
+ * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+public class TableColumn extends Item {
+ Table parent;
+ CTableColumn handle;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Table) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TableColumn (Table parent, int style) {
+ super (parent, checkStyle (style));
+ handle = createHandle();
+ this.parent = parent;
+ parent.createItem (this, parent.getColumnCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Table), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TableColumn (Table parent, int style, int index) {
+ super (parent, checkStyle (style));
+ handle = createHandle();
+ this.parent = parent;
+ parent.createItem (this, index);
+}
+
+/**
+ * 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 ControlListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @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.Resize,typedListener);
+ addListener (SWT.Move,typedListener);
+}
+
+/**
+ * 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 SelectionListener
+ * interface.
+ *
+ * widgetSelected is called when the column header is selected.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+CTableColumn createHandle () {
+ return CTableColumn.Factory.newInstance(this, style);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * LEFT, RIGHT or CENTER.
+ *
+ * @return the alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getAlignment () {
+ checkWidget ();
+ if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+ if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+ if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+ return SWT.LEFT;
+}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a Table.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Table getParent () {
+ checkWidget ();
+ return parent;
+}
+
+boolean moveable;
+
+/**
+ * Gets the moveable attribute. A column that is
+ * not moveable cannot be reordered by the user
+ * by dragging the header but may be reordered
+ * by the programmer.
+ *
+ * @return the moveable attribute
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#getColumnOrder()
+ * @see Table#setColumnOrder(int[])
+ * @see TableColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public boolean getMoveable () {
+ checkWidget ();
+ return moveable;
+}
+
+/**
+ * Gets the resizable attribute. A column that is
+ * not resizable cannot be dragged by the user but
+ * may be resized by the programmer.
+ *
+ * @return the resizable attribute
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getResizable () {
+ checkWidget ();
+ return ((javax.swing.table.TableColumn)handle).getResizable();
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getWidth () {
+ checkWidget ();
+ int index = parent.indexOf (this);
+ if (index == -1) return 0;
+ return ((javax.swing.table.TableColumn)handle).getWidth();
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ */
+public void pack () {
+ checkWidget ();
+ int index = parent.indexOf (this);
+ if (index == -1) return;
+ int oldWidth = getWidth();
+ CTable cTable = (CTable)parent.handle;
+ int newWidth = cTable.getPreferredColumnWidth(index);
+ // TODO: check why in the old SWTSwing, +2 is added.
+ cTable.getColumnModel().getColumn(index).setPreferredWidth(newWidth + 2);
+
+// int hwnd = parent.handle;
+// int oldWidth = OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
+// TCHAR buffer = new TCHAR (parent.getCodePage (), text, true);
+// int headerWidth = OS.SendMessage (hwnd, OS.LVM_GETSTRINGWIDTH, 0, buffer) + Table.HEADER_MARGIN;
+// if (image != null) {
+// int margin = 0;
+// if (OS.COMCTL32_VERSION >= OS.VERSION (5, 80)) {
+// int hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+// margin = OS.SendMessage (hwndHeader, OS.HDM_GETBITMAPMARGIN, 0, 0);
+// } else {
+// margin = OS.GetSystemMetrics (OS.SM_CXEDGE) * 3;
+// }
+// Rectangle rect = image.getBounds ();
+// headerWidth += rect.width + margin * 2;
+// }
+// boolean oldIgnoreRezize = parent.ignoreResize;
+// parent.ignoreResize = true;
+// OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE);
+// int columnWidth = OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
+// if (index == 0) {
+// /*
+// * Bug in Windows. When LVM_SETCOLUMNWIDTH is used with LVSCW_AUTOSIZE
+// * where each item has I_IMAGECALLBACK but there are no images in the
+// * table, the size computed by LVM_SETCOLUMNWIDTH is too small for the
+// * first column, causing long items to be clipped with '...'. The fix
+// * is to increase the column width by a small amount.
+// */
+// if (parent.imageList == null) columnWidth += 2;
+// /*
+// * Bug in Windows. When LVM_SETCOLUMNWIDTH is used with LVSCW_AUTOSIZE
+// * for a table with a state image list, the column is width does not
+// * include space for the state icon. The fix is to increase the column
+// * width by the width of the image list.
+// */
+// if ((parent.style & SWT.CHECK) != 0) {
+// int hStateList = OS.SendMessage (hwnd, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+// if (hStateList != 0) {
+// int [] cx = new int [1], cy = new int [1];
+// OS.ImageList_GetIconSize (hStateList, cx, cy);
+// columnWidth += cx [0];
+// }
+// }
+// }
+// if (headerWidth > columnWidth) {
+// if (image == null) {
+// /*
+// * Feature in Windows. When LVSCW_AUTOSIZE_USEHEADER is used
+// * with LVM_SETCOLUMNWIDTH to resize the last column, the last
+// * column is expanded to fill the client area. The fix is to
+// * resize the table to be small, set the column width and then
+// * restore the table to its original size.
+// */
+// RECT rect = null;
+// boolean fixWidth = index == parent.getColumnCount () - 1;
+// if (fixWidth) {
+// rect = new RECT ();
+// OS.GetWindowRect (hwnd, rect);
+// OS.UpdateWindow (hwnd);
+// int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER;
+// SetWindowPos (hwnd, 0, 0, 0, 0, rect.bottom - rect.top, flags);
+// }
+// OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE_USEHEADER);
+// if (fixWidth) {
+// int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOZORDER;
+// SetWindowPos (hwnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, flags);
+// }
+// } else {
+// OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, headerWidth);
+// }
+// } else {
+// if (index == 0) {
+// OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, columnWidth);
+// }
+// }
+// parent.ignoreResize = oldIgnoreRezize;
+// int newWidth = OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
+ if (oldWidth != newWidth) {
+ sendEvent (SWT.Resize);
+// if (isDisposed ()) return;
+// boolean moved = false;
+// int [] order = parent.getColumnOrder ();
+// TableColumn [] columns = parent.getColumns ();
+// for (int i=0; i
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Move, listener);
+ eventTable.unhook (SWT.Resize, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Controls how text and images will be displayed in the receiver.
+ * The argument should be one of LEFT, RIGHT
+ * or CENTER.
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setAlignment (int alignment) {
+ checkWidget ();
+ if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return;
+ int index = parent.indexOf (this);
+ if (index == -1 || index == 0) return;
+ style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ if ((style & SWT.LEFT) == SWT.LEFT) handle.setAlignment(SwingConstants.LEFT);
+ if ((style & SWT.CENTER) == SWT.CENTER) handle.setAlignment(SwingConstants.CENTER);
+ if ((style & SWT.RIGHT) == SWT.RIGHT) handle.setAlignment(SwingConstants.RIGHT);
+ // TODO: notify change
+}
+
+public void setImage (Image image) {
+ checkWidget();
+ if (image != null && image.isDisposed ()) {
+ error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int index = parent.indexOf (this);
+ if (index == -1) return;
+ super.setImage (image);
+ handle.setIcon(image == null? null: new ImageIcon(image.handle));
+}
+
+/**
+ * Sets the moveable attribute. A column that is
+ * moveable can be reordered by the user by dragging
+ * the header. A column that is not moveable cannot be
+ * dragged by the user but may be reordered
+ * by the programmer.
+ *
+ * @param moveable the moveable attribute
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Table#setColumnOrder(int[])
+ * @see Table#getColumnOrder()
+ * @see TableColumn#getMoveable()
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public void setMoveable (boolean moveable) {
+ checkWidget ();
+ this.moveable = moveable;
+}
+
+/**
+ * Sets the resizable attribute. A column that is
+ * resizable can be resized by the user dragging the
+ * edge of the header. A column that is not resizable
+ * cannot be dragged by the user but may be resized
+ * by the programmer.
+ *
+ * @param resizable the resize attribute
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setResizable (boolean resizable) {
+ checkWidget ();
+ ((javax.swing.table.TableColumn)handle).setResizable(resizable);
+}
+
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (string.equals (text)) return;
+ int index = parent.indexOf (this);
+ if (index == -1) return;
+ super.setText (string);
+ // TODO: check what happens with mnemonics
+ ((javax.swing.table.TableColumn)handle).setHeaderValue(string);
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setToolTipText (String string) {
+ checkWidget();
+ handle.setToolTipText(string);
+}
+
+/**
+ * Sets the width of the receiver.
+ *
+ * @param width the new width
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+
+public class TableItem extends Item {
+ /**
+ * the handle to the OS resource
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ public CTableItem handle;
+ Table parent;
+// String [] strings;
+ Image [] images;
+// boolean checked, grayed
+ boolean cached;
+// int imageIndent, background = -1, foreground = -1, font = -1;
+// int [] cellBackground, cellForeground, cellFont;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Table) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TableItem (Table parent, int style) {
+ this (parent, style, checkNull (parent).getItemCount (), true);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Table), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ */
+public Color getBackground () {
+ checkWidget ();
+ java.awt.Color color = handle.getBackground();
+ if(color == null) return parent.getBackground();
+ return Color.swing_new(display, color);
+}
+
+/**
+ * Returns the background color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the background color
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public Color getBackground (int index) {
+ checkWidget ();
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return getBackground ();
+ java.awt.Color color = handle.getTableItemObject(index).getBackground();
+ if(color == null) {
+ if(index != 0) {
+ return getBackground();
+ }
+ return Color.swing_new(display, parent.handle.getBackground());
+ }
+ return Color.swing_new(display, color);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public Rectangle getBounds () {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int itemIndex = parent.indexOf (this);
+ if (itemIndex == -1) return new Rectangle (0, 0, 0, 0);
+ return getBounds(0);
+// RECT rect = getBounds (itemIndex, 0, true, false, false);
+// int width = rect.right - rect.left, height = rect.bottom - rect.top;
+// return new Rectangle (rect.left, rect.top, width, height);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent at a column in the table.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding column rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Rectangle getBounds (int index) {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ java.awt.Rectangle rect = ((CTable)parent.handle).getCellRect(parent.indexOf(this), index, false);
+ Point offset = parent.getInternalOffset();
+ return new Rectangle(rect.x + offset.x, rect.y + offset.y, rect.width, rect.height);
+}
+
+/**
+ * Returns true if the receiver is checked,
+ * and false otherwise. When the parent does not have
+ * the CHECK style, return false.
+ *
+ * @return the checked state of the checkbox
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getChecked () {
+ checkWidget();
+ if ((parent.style & SWT.CHECK) == 0) return false;
+ return handle.isChecked();
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information for this item.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public Font getFont () {
+ return getFont(0);
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information
+ * for the specified cell in this item.
+ *
+ * @param index the column index
+ * @return the receiver's font
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public Font getFont (int index) {
+ checkWidget ();
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count -1) return getFont ();
+ java.awt.Font font = handle.getTableItemObject(index).getFont();
+ if(font == null) {
+ if(index != 0) {
+ return getFont();
+ }
+ return Font.swing_new(display, parent.handle.getFont());
+ }
+ return Font.swing_new(display, font);
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ */
+public Color getForeground () {
+ checkWidget ();
+ java.awt.Color color = handle.getForeground();
+ if(color == null) return parent.getForeground();
+ return Color.swing_new(display, color);
+}
+
+/**
+ *
+ * Returns the foreground color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the foreground color
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public Color getForeground (int index) {
+ checkWidget ();
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count -1) return getForeground ();
+ java.awt.Color color = handle.getTableItemObject(index).getForeground();
+ if(color == null) {
+ if(index != 0) {
+ return getBackground();
+ }
+ return Color.swing_new(display, parent.handle.getForeground());
+ }
+ return Color.swing_new(display, color);
+}
+
+/**
+ * Returns true if the receiver is grayed,
+ * and false otherwise. When the parent does not have
+ * the CHECK style, return false.
+ *
+ * @return the grayed state of the checkbox
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getGrayed () {
+ checkWidget ();
+ if ((parent.style & SWT.CHECK) == 0) return false;
+ return handle.isGrayed();
+}
+
+public Image getImage () {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return super.getImage ();
+}
+
+/**
+ * Returns the image stored at the given column index in the receiver,
+ * or null if the image has not been set or if the column does not exist.
+ *
+ * @param index the column index
+ * @return the image stored at the given column index in the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Image getImage (int index) {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (index == 0) return getImage ();
+ if (images != null) {
+ if (0 <= index && index < images.length) return images [index];
+ }
+ return null;
+}
+
+/**
+ * Returns a rectangle describing the size and location
+ * relative to its parent of an image at a column in the
+ * table. An empty rectangle is returned if index exceeds
+ * the index of the table's last column.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding image rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Rectangle getImageBounds (int index) {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int itemIndex = parent.indexOf (this);
+ if (itemIndex == -1) return new Rectangle (0, 0, 0, 0);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return new Rectangle (0, 0, 0, 0);
+ java.awt.Rectangle imageBounds = ((CTable)parent.handle).getImageBounds(itemIndex, index);
+ return new Rectangle(imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height);
+// RECT rect = getBounds (itemIndex, index, false, true);
+// int width = rect.right - rect.left, height = rect.bottom - rect.top;
+// return new Rectangle (rect.left, rect.top, width, height);
+}
+
+/**
+ * Gets the image indent.
+ *
+ * @return the indent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getImageIndent () {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ Utils.notImplemented(); return 0;
+// return imageIndent;
+}
+
+String getNameText () {
+ if ((parent.style & SWT.VIRTUAL) != 0) {
+ if (!cached) return "*virtual*"; //$NON-NLS-1$
+ }
+ return super.getNameText ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a Table.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Table getParent () {
+ checkWidget();
+ return parent;
+}
+
+public String getText () {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return super.getText ();
+}
+
+/**
+ * Returns the text stored at the given column index in the receiver,
+ * or empty string if the text has not been set.
+ *
+ * @param index the column index
+ * @return the text stored at the given column index in the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getText (int index) {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return "";
+ return handle.getTableItemObject(index).getText();
+}
+
+//void redraw () {
+// if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+// if (parent.currentItem == this || parent.drawCount != 0) return;
+// int hwnd = parent.handle;
+// if (!OS.IsWindowVisible (hwnd)) return;
+// int index = parent.indexOf (this);
+// if (index == -1) return;
+// OS.SendMessage (hwnd, OS.LVM_REDRAWITEMS, index, index);
+//}
+
+//void redraw (int column, boolean drawText, boolean drawImage) {
+// if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+// if (parent.currentItem == this || parent.drawCount != 0) return;
+// int hwnd = parent.handle;
+// if (!OS.IsWindowVisible (hwnd)) return;
+// int index = parent.indexOf (this);
+// if (index == -1) return;
+// RECT rect = getBounds (index, column, drawText, drawImage);
+// OS.InvalidateRect (hwnd, rect, true);
+//}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ parent = null;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+// strings = null;
+ images = null;
+// cellBackground = cellForeground = cellFont = null;
+}
+
+/**
+ * Sets the receiver's background color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ *
+ */
+public void setBackground (Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ handle.setBackground(color == null? null: color.handle);
+ int index = parent.indexOf(this);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTable)parent.handle).getModel().fireTableRowsUpdated(index, index);
+}
+
+/**
+ * Sets the background color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ *
+ */
+public void setBackground (int index, Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ handle.getTableItemObject(index).setBackground(color == null? null: color.handle);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), index);
+}
+
+/**
+ * Sets the checked state of the checkbox for this item. This state change
+ * only applies if the Table was created with the SWT.CHECK style.
+ *
+ * @param checked the new checked state of the checkbox
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setChecked (boolean checked) {
+ checkWidget();
+ if ((parent.style & SWT.CHECK) == 0) return;
+ handle.setChecked(checked);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ // TODO: is it always 0 if columns are reordered?
+ ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), 0);
+}
+
+//void setChecked (boolean checked, boolean notify) {
+// this.checked = checked;
+// if (notify) {
+// Event event = new Event();
+// event.item = this;
+// event.detail = SWT.CHECK;
+// parent.postEvent (SWT.Selection, event);
+// }
+// redraw ();
+//}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for this item 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
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public void setFont (Font font){
+ checkWidget ();
+ if (font != null && font.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ handle.setFont(font == null? null: font.handle);
+ int index = parent.indexOf(this);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTable)parent.handle).getModel().fireTableRowsUpdated(index, index);
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for the specified cell in this item to the font specified by the
+ * argument, or to the default font for that kind of control if the
+ * argument is null.
+ *
+ * @param index the column index
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public void setFont (int index, Font font) {
+ checkWidget ();
+ if (font != null && font.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ handle.getTableItemObject(index).setFont(font == null? null: font.handle);
+ ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), index);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ parent.adjustColumnWidth();
+}
+
+/**
+ * Sets the receiver's foreground color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ */
+public void setForeground (Color color){
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ handle.setForeground(color == null? null: color.handle);
+ int index = parent.indexOf(this);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTable)parent.handle).getModel().fireTableRowsUpdated(index, index);
+}
+
+/**
+ * Sets the foreground color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public void setForeground (int index, Color color){
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ handle.getTableItemObject(index).setForeground(color == null? null: color.handle);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), index);
+}
+
+/**
+ * Sets the grayed state of the checkbox for this item. This state change
+ * only applies if the Table was created with the SWT.CHECK style.
+ *
+ * @param grayed the new grayed state of the checkbox;
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setGrayed (boolean grayed) {
+ checkWidget ();
+ if ((parent.style & SWT.CHECK) == 0) return;
+ handle.setGrayed(grayed);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ // TODO: is it always 0 if columns are reordered?
+ ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), 0);
+}
+
+/**
+ * Sets the image for multiple columns in the table.
+ *
+ * @param images the array of new images
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the array of images is null
+ *
ERROR_INVALID_ARGUMENT - if one of the images has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setImage (Image [] images) {
+ checkWidget();
+ if (images == null) error (SWT.ERROR_NULL_ARGUMENT);
+ for (int i=0; i
+ *
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setImage (int index, Image image) {
+ checkWidget();
+ if (image != null && image.isDisposed ()) {
+ error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (index == 0) {
+ if (image != null && image.type == SWT.ICON) {
+ if (image.equals (this.image)) return;
+ }
+ super.setImage (image);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if (images == null && index != 0) {
+ images = new Image [count];
+ images [0] = image;
+ }
+ if (images != null) {
+ if (image != null && image.type == SWT.ICON) {
+ if (image.equals (images [index])) return;
+ }
+ images [index] = image;
+ }
+ handle.getTableItemObject(index).setIcon(image != null? new ImageIcon(image.handle): null);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTable)parent.handle).getModel().fireTableCellUpdated(index, index);
+ parent.adjustColumnWidth();
+//
+//
+// if (images == null && index != 0) images = new Image [count];
+// if (images != null) {
+// if (image != null && image.type == SWT.ICON) {
+// if (image.equals (images [index])) return;
+// }
+// images [index] = image;
+// }
+//
+// /* Ensure that the image list is created */
+// parent.imageIndex (image);
+//
+// if (index == 0) parent.setScrollWidth (this, false);
+// redraw (index, false, true);
+}
+
+public void setImage (Image image) {
+ checkWidget ();
+ setImage (0, image);
+}
+
+/**
+ * Sets the indent of the first column's image, expressed in terms of the image's width.
+ *
+ * @param indent the new indent
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @deprecated this functionality is not supported on most platforms
+ */
+public void setImageIndent (int indent) {
+ checkWidget();
+ if (indent < 0) return;
+ Utils.notImplemented();
+// if (imageIndent == indent) return;
+// imageIndent = indent;
+// if ((parent.style & SWT.VIRTUAL) != 0) {
+// cached = true;
+// } else {
+// int index = parent.indexOf (this);
+// if (index != -1) {
+// int hwnd = parent.handle;
+// LVITEM lvItem = new LVITEM ();
+// lvItem.mask = OS.LVIF_INDENT;
+// lvItem.iItem = index;
+// lvItem.iIndent = indent;
+// OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, lvItem);
+// }
+// }
+// parent.setScrollWidth (this, false);
+// redraw ();
+}
+
+/**
+ * Sets the text for multiple columns in the table.
+ *
+ * @param strings the array of new strings
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setText (String [] strings) {
+ checkWidget();
+ if (strings == null) error (SWT.ERROR_NULL_ARGUMENT);
+ for (int i=0; i
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setText (int index, String string) {
+ checkWidget();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if(index == 0) {
+ super.setText(string);
+ }
+ handle.getTableItemObject(index).setText(string);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTable)parent.handle).getModel().fireTableCellUpdated(parent.indexOf(this), index);
+ parent.adjustColumnWidth();
+}
+
+public void setText (String string) {
+ checkWidget();
+ setText (0, string);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Text.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Text.java
new file mode 100644
index 00000000000..4f5a5e94630
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Text.java
@@ -0,0 +1,1796 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.ComponentOrientation;
+import java.awt.Container;
+import java.util.EventObject;
+
+import javax.swing.JButton;
+import javax.swing.RootPaneContainer;
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.BadLocationException;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.swing.CText;
+import org.eclipse.swt.internal.swing.TextFilterEvent;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that allow the user to enter and modify text.
+ *
+ *
+ *
Styles:
+ *
CENTER, LEFT, MULTI, PASSWORD, SINGLE, RIGHT, READ_ONLY, WRAP
+ *
Events:
+ *
DefaultSelection, Modify, Verify
+ *
+ *
+ * Note: Only one of the styles MULTI and SINGLE may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+public class Text extends Scrollable {
+ int tabs, oldStart, oldEnd;
+ boolean doubleClick, ignoreModify, ignoreCharacter;
+
+ /**
+ * The maximum number of characters that can be entered
+ * into a text widget.
+ *
+ * Note that this value is platform dependent, based upon
+ * the native widget implementation.
+ *
+ */
+ public static final int LIMIT;
+
+ /**
+ * The delimiter used by multi-line text widgets. When text
+ * is queried and from the widget, it will be delimited using
+ * this delimiter.
+ */
+ public static final String DELIMITER;
+
+ /*
+ * This code is intentionally commented.
+ */
+// static final char PASSWORD;
+
+ /*
+ * These values can be different on different platforms.
+ * Therefore they are not initialized in the declaration
+ * to stop the compiler from inlining.
+ */
+ static {
+ LIMIT = 0x7FFFFFFF;
+ DELIMITER = System.getProperty("line.separator");//"\n";
+ }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#READ_ONLY
+ * @see SWT#WRAP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Text (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is modified, by sending
+ * it one of the messages defined in the ModifyListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ModifyListener
+ * @see #removeModifyListener
+ */
+public void addModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Modify, typedListener);
+}
+
+/**
+ * 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 SelectionListener
+ * interface.
+ *
+ * widgetSelected is not called for texts.
+ * widgetDefaultSelected is typically called when ENTER is pressed in a single-line text.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is verified, by sending
+ * it one of the messages defined in the VerifyListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * The current selection is first copied to the
+ * clipboard and then deleted from the widget.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void cut () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return;
+ ((CText)handle).cut();
+}
+
+/**
+ * Returns the line number of the caret.
+ *
+ * The line number of the caret is returned.
+ *
+ *
+ * @return the line number
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getCaretLineNumber () {
+ checkWidget ();
+ return ((CText)handle).getCaretLineNumber();
+}
+
+/**
+ * Returns a point describing the receiver's location relative
+ * to its parent (or its display if its parent is null).
+ *
+ * The location of the caret is returned.
+ *
+ *
+ * @return a point, the location of the caret
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getCaretLocation () {
+ checkWidget ();
+ java.awt.Point point = ((CText)handle).getCaretLocation();
+ return new Point(point.x, point.y);
+}
+
+/**
+ * Returns the character position of the caret.
+ *
+ * Indexing is zero based.
+ *
+ *
+ * @return the position of the caret
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getCaretPosition () {
+ checkWidget ();
+ return ((CText)handle).getCaretPosition();
+}
+
+/**
+ * Returns the number of characters.
+ *
+ * @return number of characters in the widget
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * The echo character is the character that is
+ * displayed when the user enters text or the
+ * text is changed by the programmer.
+ *
+ *
+ * @return the echo character
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setEchoChar
+ */
+public char getEchoChar () {
+ checkWidget ();
+ return ((CText)handle).getEchoChar();
+}
+
+/**
+ * Returns the editable state.
+ *
+ * @return whether or not the receiver is editable
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getEditable () {
+ checkWidget ();
+ return ((CText)handle).isEditable();
+}
+
+/**
+ * Returns the number of lines.
+ *
+ * @return the number of lines in the widget
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getLineCount () {
+ checkWidget ();
+ return ((CText)handle).getLineCount();
+}
+
+/**
+ * Returns the line delimiter.
+ *
+ * @return a string that is the line delimiter
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #DELIMITER
+ */
+public String getLineDelimiter () {
+ checkWidget ();
+ return DELIMITER;
+}
+
+/**
+ * Returns the height of a line.
+ *
+ * @return the height of a row of text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getLineHeight () {
+ checkWidget ();
+ return ((CText)handle).getRowHeight();
+}
+
+/**
+ * Returns the orientation of the receiver, which will be one of the
+ * constants SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT.
+ *
+ * @return the orientation style
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.1.2
+ */
+public int getOrientation () {
+ checkWidget();
+ return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+}
+
+/**
+ * Returns a Point whose x coordinate is the
+ * character position representing the start of the selected
+ * text, and whose y coordinate is the character position
+ * representing the end of the selection. An "empty" selection
+ * is indicated by the x and y coordinates having the same value.
+ *
+ * Indexing is zero based. The range of a selection is from
+ * 0..N where N is the number of characters in the widget.
+ *
+ *
+ * @return a point representing the selection start and end
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Point getSelection () {
+ checkWidget ();
+ CText cText = (CText)handle;
+ return new Point(cText.getSelectionStart(), cText.getSelectionEnd());
+}
+
+/**
+ * Returns the number of selected characters.
+ *
+ * @return the number of selected characters.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelectionCount () {
+ checkWidget ();
+ Point selection = getSelection ();
+ return selection.y - selection.x;
+}
+
+/**
+ * Gets the selected text, or an empty string if there is no current selection.
+ *
+ * @return the selected text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getSelectionText () {
+ checkWidget ();
+ /*
+ * NOTE: The current implementation uses substring ()
+ * which can reference a potentially large character
+ * array.
+ */
+ Point selection = getSelection ();
+ return getText ().substring (selection.x, selection.y);
+}
+
+/**
+ * Returns the number of tabs.
+ *
+ * Tab stop spacing is specified in terms of the
+ * space (' ') character. The width of a single
+ * tab stop is the pixel width of the spaces.
+ *
+ *
+ * @return the number of tab characters
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * The text for a text widget is the characters in the widget, or
+ * an empty string if this has never been set.
+ *
+ *
+ * @return the widget text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getText () {
+ checkWidget ();
+ return ((CText)handle).getText();
+}
+
+/**
+ * Returns a range of text. Returns an empty string if the
+ * start of the range is greater than the end.
+ *
+ * Indexing is zero based. The range of
+ * a selection is from 0..N-1 where N is
+ * the number of characters in the widget.
+ *
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ * @return the range of text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getText (int start, int end) {
+ checkWidget ();
+ if (!(start <= end && 0 <= end)) return "";
+ CText cText = (CText)handle;
+ int length = cText.getText().length();
+ end = Math.min (end, length - 1);
+ start = Math.max (0, start);
+ if(start > end) {
+ return "";
+ }
+ try {
+ return cText.getText(start, end - start);
+ } catch(BadLocationException e) {
+ }
+ return "";
+}
+
+/**
+ * Returns the maximum number of characters that the receiver is capable of holding.
+ *
+ * If this has not been changed by setTextLimit(),
+ * it will be the constant Text.LIMIT.
+ *
+ *
+ * @return the text limit
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #LIMIT
+ */
+public int getTextLimit () {
+ checkWidget ();
+ return ((CText)handle).getTextLimit();
+}
+
+/**
+ * Returns the zero-relative index of the line which is currently
+ * at the top of the receiver.
+ *
+ * This index can change when lines are scrolled or new lines are added or removed.
+ *
+ *
+ * @return the index of the top line
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getTopIndex () {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) return 0;
+ return ((CText)handle).getViewPosition().y / getLineHeight();
+}
+
+/**
+ * Returns the top pixel.
+ *
+ * The top pixel is the pixel position of the line
+ * that is currently at the top of the widget. On
+ * some platforms, a text widget can be scrolled by
+ * pixels instead of lines so that a partial line
+ * is displayed at the top of the widget.
+ *
+ * The top pixel changes when the widget is scrolled.
+ * The top pixel does not include the widget trimming.
+ *
+ *
+ * @return the pixel position of the top line
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * The selected text is deleted from the widget
+ * and new text inserted from the clipboard.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void paste () {
+ checkWidget ();
+ if ((style & SWT.READ_ONLY) != 0) return;
+ ((CText)handle).paste();
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's text is modified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ModifyListener
+ * @see #addModifyListener
+ */
+public void removeModifyListener (ModifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Modify, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is verified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see VerifyListener
+ * @see #addVerifyListener
+ */
+public void removeVerifyListener (VerifyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Verify, listener);
+}
+
+/**
+ * Selects all the text in the receiver.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void selectAll () {
+ checkWidget ();
+ ((CText)handle).selectAll();
+}
+
+//boolean sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) {
+// if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
+// return false;
+// }
+// if ((style & SWT.READ_ONLY) != 0) return true;
+// if (ignoreVerify) return true;
+// if (type != SWT.KeyDown) return true;
+// if (msg != OS.WM_CHAR && msg != OS.WM_KEYDOWN && msg != OS.WM_IME_CHAR) {
+// return true;
+// }
+// if (event.character == 0) return true;
+// if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return true;
+// char key = event.character;
+// int stateMask = event.stateMask;
+//
+// /*
+// * Disable all magic keys that could modify the text
+// * and don't send events when Alt, Shift or Ctrl is
+// * pressed.
+// */
+// switch (msg) {
+// case OS.WM_CHAR:
+// if (key != 0x08 && key != 0x7F && key != '\r' && key != '\t' && key != '\n') break;
+// // FALL THROUGH
+// case OS.WM_KEYDOWN:
+// if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) != 0) return false;
+// break;
+// }
+//
+// /*
+// * If the left button is down, the text widget refuses the character.
+// */
+// if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
+// return true;
+// }
+//
+// /* Verify the character */
+// String oldText = "";
+// int [] start = new int [1], end = new int [1];
+// OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+// switch (key) {
+// case 0x08: /* Bs */
+// if (start [0] == end [0]) {
+// if (start [0] == 0) return true;
+// int lineStart = OS.SendMessage (handle, OS.EM_LINEINDEX, -1, 0);
+// if (start [0] == lineStart) {
+// start [0] = start [0] - DELIMITER.length ();
+// } else {
+// start [0] = start [0] - 1;
+// if (OS.IsDBLocale) {
+// int [] newStart = new int [1], newEnd = new int [1];
+// OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
+// OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd);
+// if (start [0] != newStart [0]) start [0] = start [0] - 1;
+// }
+// }
+// start [0] = Math.max (start [0], 0);
+// }
+// break;
+// case 0x7F: /* Del */
+// if (start [0] == end [0]) {
+// int length = OS.GetWindowTextLength (handle);
+// if (start [0] == length) return true;
+// int line = OS.SendMessage (handle, OS.EM_LINEFROMCHAR, end [0], 0);
+// int lineStart = OS.SendMessage (handle, OS.EM_LINEINDEX, line + 1, 0);
+// if (end [0] == lineStart - DELIMITER.length ()) {
+// end [0] = end [0] + DELIMITER.length ();
+// } else {
+// end [0] = end [0] + 1;
+// if (OS.IsDBLocale) {
+// int [] newStart = new int [1], newEnd = new int [1];
+// OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
+// OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd);
+// if (end [0] != newEnd [0]) end [0] = end [0] + 1;
+// }
+// }
+// end [0] = Math.min (end [0], length);
+// }
+// break;
+// case '\r': /* Return */
+// if ((style & SWT.SINGLE) != 0) return true;
+// oldText = DELIMITER;
+// break;
+// default: /* Tab and other characters */
+// if (key != '\t' && key < 0x20) return true;
+// oldText = new String (new char [] {key});
+// break;
+// }
+// String newText = verifyText (oldText, start [0], end [0], event);
+// if (newText == null) return false;
+// if (newText == oldText) return true;
+// newText = Display.withCrLf (newText);
+// TCHAR buffer = new TCHAR (getCodePage (), newText, true);
+// OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
+// /*
+// * Feature in Windows. When an edit control with ES_MULTILINE
+// * style that does not have the WS_VSCROLL style is full (i.e.
+// * there is no space at the end to draw any more characters),
+// * EM_REPLACESEL sends a WM_CHAR with a backspace character
+// * to remove any further text that is added. This is an
+// * implementation detail of the edit control that is unexpected
+// * and can cause endless recursion when EM_REPLACESEL is sent
+// * from a WM_CHAR handler. The fix is to ignore calling the
+// * handler from WM_CHAR.
+// */
+// ignoreCharacter = true;
+// OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
+// ignoreCharacter = false;
+// return false;
+//}
+//
+
+/**
+ * Sets the double click enabled flag.
+ *
+ * The double click flag enables or disables the
+ * default action of the text widget when the user
+ * double clicks.
+ *
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ *
+ *
+ * @param doubleClick the new double click flag
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * The echo character is the character that is
+ * displayed when the user enters text or the
+ * text is changed by the programmer. Setting
+ * the echo character to '\0' clears the echo
+ * character and redraws the original text.
+ * If for any reason the echo character is invalid,
+ * or if the platform does not allow modification
+ * of the echo character, the default echo character
+ * for the platform is used.
+ *
+ *
+ * @param echo the new echo character
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setEchoChar (char echo) {
+ checkWidget ();
+ if ((style & SWT.MULTI) != 0) return;
+ ((CText)handle).setEchoChar(echo);
+}
+
+/**
+ * Sets the editable state.
+ *
+ * @param editable the new editable state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setEditable (boolean editable) {
+ checkWidget ();
+ style &= ~SWT.READ_ONLY;
+ if (!editable) style |= SWT.READ_ONLY;
+ ((CText)handle).setEditable(editable);
+}
+
+/**
+ * Sets the orientation of the receiver, which must be one
+ * of the constants SWT.LEFT_TO_RIGHT or SWT.RIGHT_TO_LEFT.
+ *
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ *
+ * Indexing is zero based. The range of
+ * a selection is from 0..N where N is
+ * the number of characters in the widget.
+ *
+ * Text selections are specified in terms of
+ * caret positions. In a text widget that
+ * contains N characters, there are N+1 caret
+ * positions, ranging from 0..N. This differs
+ * from other functions that address character
+ * position such as getText () that use the
+ * regular array indexing rules.
+ *
+ *
+ * @param start new caret position
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (int start) {
+ checkWidget ();
+ ((CText)handle).setSelectionStart(start);
+ ((CText)handle).setSelectionEnd(start);
+}
+
+/**
+ * Sets the selection to the range specified
+ * by the given start and end indices.
+ *
+ * Indexing is zero based. The range of
+ * a selection is from 0..N where N is
+ * the number of characters in the widget.
+ *
+ * Text selections are specified in terms of
+ * caret positions. In a text widget that
+ * contains N characters, there are N+1 caret
+ * positions, ranging from 0..N. This differs
+ * from other functions that address character
+ * position such as getText () that use the
+ * usual array indexing rules.
+ *
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (int start, int end) {
+ checkWidget ();
+ ((CText)handle).setSelectionStart(start);
+ ((CText)handle).setSelectionEnd(end);
+}
+
+//public void setRedraw (boolean redraw) {
+// checkWidget ();
+// super.setRedraw (redraw);
+// /*
+// * Feature in Windows. When WM_SETREDRAW is used to turn
+// * redraw off, the edit control is not scrolled to show the
+// * i-beam. The fix is to detect that the i-beam has moved
+// * while redraw is turned off and force it to be visible
+// * when redraw is restored.
+// */
+// if (drawCount != 0) return;
+// int [] start = new int [1], end = new int [1];
+// OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+// if (!redraw) {
+// oldStart = start [0]; oldEnd = end [0];
+// } else {
+// if (oldStart == start [0] && oldEnd == end [0]) return;
+// OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
+// }
+//}
+
+/**
+ * Sets the selection to the range specified
+ * by the given point, where the x coordinate
+ * represents the start index and the y coordinate
+ * represents the end index.
+ *
+ * Indexing is zero based. The range of
+ * a selection is from 0..N where N is
+ * the number of characters in the widget.
+ *
+ * Text selections are specified in terms of
+ * caret positions. In a text widget that
+ * contains N characters, there are N+1 caret
+ * positions, ranging from 0..N. This differs
+ * from other functions that address character
+ * position such as getText () that use the
+ * usual array indexing rules.
+ *
+ *
+ * @param selection the point
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (Point selection) {
+ checkWidget ();
+ if (selection == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSelection (selection.x, selection.y);
+}
+
+/**
+ * Sets the number of tabs.
+ *
+ * Tab stop spacing is specified in terms of the
+ * space (' ') character. The width of a single
+ * tab stop is the pixel width of the spaces.
+ *
+ *
+ * @param tabs the number of tabs
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setTabs (int tabs) {
+ checkWidget ();
+ if (tabs < 0) return;
+ setTabStops (this.tabs = tabs);
+}
+
+void setTabStops (int tabs) {
+ ((CText)handle).setTabSize(tabs);
+}
+
+/**
+ * Sets the contents of the receiver to the given string. If the receiver has style
+ * SINGLE and the argument contains multiple lines of text, the result of this
+ * operation is undefined and may vary from platform to platform.
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ CText cText = (CText)handle;
+// if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+// int length = cText.getText().length();
+// string = verifyText (string, 0, length, null);
+// if (string == null) return;
+// }
+ cText.setText(string);
+ if ((style & SWT.MULTI) != 0) {
+ sendEvent (SWT.Modify);
+ // widget could be disposed at this point
+ }
+}
+
+/**
+ * Sets the maximum number of characters that the receiver
+ * is capable of holding to be the argument.
+ *
+ * Instead of trying to set the text limit to zero, consider
+ * creating a read-only text widget.
+ *
+ * To reset this value to the default, use setTextLimit(Text.LIMIT).
+ * Specifying a limit value larger than Text.LIMIT sets the
+ * receiver's limit to Text.LIMIT.
+ *
+ *
+ * @param limit new text limit
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_CANNOT_BE_ZERO - if the limit is zero
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #LIMIT
+ */
+public void setTextLimit (int limit) {
+ checkWidget ();
+ if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
+ ((CText)handle).setTextLimit(limit);
+}
+
+/**
+ * Sets the zero-relative index of the line which is currently
+ * at the top of the receiver. This index can change when lines
+ * are scrolled or new lines are added and removed.
+ *
+ * @param index the index of the top item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * If the selection is already showing
+ * in the receiver, this method simply returns. Otherwise,
+ * lines are scrolled until the selection is visible.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void showSelection () {
+ checkWidget ();
+ ((CText)handle).showSelection();
+}
+
+String verifyText (String string, int start, int end, Event keyEvent) {
+ Event event = new Event ();
+ event.text = string;
+ event.start = start;
+ event.end = end;
+ if (keyEvent != null) {
+ event.character = keyEvent.character;
+ event.keyCode = keyEvent.keyCode;
+ event.stateMask = keyEvent.stateMask;
+ }
+ sendEvent (SWT.Verify, event);
+ if (!event.doit || isDisposed ()) return null;
+ return event.text;
+}
+
+//int wcsToMbcsPos (int wcsPos) {
+// if (wcsPos <= 0) return 0;
+// if (OS.IsUnicode) return wcsPos;
+// int cp = getCodePage ();
+// int wcsTotal = 0, mbcsTotal = 0;
+// byte [] buffer = new byte [128];
+// String delimiter = getLineDelimiter ();
+// int delimiterSize = delimiter.length ();
+// int count = OS.SendMessageA (handle, OS.EM_GETLINECOUNT, 0, 0);
+// for (int line=0; line buffer.length) {
+// buffer = new byte [mbcsSize + delimiterSize];
+// }
+// //ENDIAN
+// buffer [0] = (byte) (mbcsSize & 0xFF);
+// buffer [1] = (byte) (mbcsSize >> 8);
+// mbcsSize = OS.SendMessageA (handle, OS.EM_GETLINE, line, buffer);
+// wcsSize = OS.MultiByteToWideChar (cp, OS.MB_PRECOMPOSED, buffer, mbcsSize, null, 0);
+// }
+// if (line - 1 != count) {
+// for (int i=0; i= wcsPos) {
+// wcsSize = 0;
+// int index = 0;
+// while (index < mbcsSize) {
+// if ((wcsTotal + wcsSize) == wcsPos) {
+// return mbcsTotal + index;
+// }
+// if (OS.IsDBCSLeadByte (buffer [index++])) index++;
+// wcsSize++;
+// }
+// return mbcsTotal + mbcsSize;
+// }
+// wcsTotal += wcsSize;
+// mbcsTotal += mbcsSize;
+// }
+// return mbcsTotal;
+//}
+
+//LRESULT WM_CHAR (int wParam, int lParam) {
+// if (ignoreCharacter) return null;
+// LRESULT result = super.WM_CHAR (wParam, lParam);
+// if (result != null) return result;
+//
+// /*
+// * Bug in Windows. When the user types CTRL and BS
+// * in an edit control, a DEL character is generated.
+// * Rather than deleting the text, the DEL character
+// * is inserted into the control. The fix is to detect
+// * this case and not call the window proc.
+// */
+// switch (wParam) {
+// case SWT.DEL:
+// if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
+// return LRESULT.ZERO;
+// }
+// }
+//
+// /*
+// * Feature in Windows. For some reason, when the
+// * widget is a single line text widget, when the
+// * user presses tab, return or escape, Windows beeps.
+// * The fix is to look for these keys and not call
+// * the window proc.
+// */
+// if ((style & SWT.SINGLE) != 0) {
+// switch (wParam) {
+// case SWT.CR:
+// postEvent (SWT.DefaultSelection);
+// // FALL THROUGH
+// case SWT.TAB:
+// case SWT.ESC: return LRESULT.ZERO;
+// }
+// }
+// return result;
+//}
+//
+//LRESULT WM_CLEAR (int wParam, int lParam) {
+// LRESULT result = super.WM_CLEAR (wParam, lParam);
+// if (result != null) return result;
+// return wmClipboard (OS.WM_CLEAR, wParam, lParam);
+//}
+//
+//LRESULT WM_CUT (int wParam, int lParam) {
+// LRESULT result = super.WM_CUT (wParam, lParam);
+// if (result != null) return result;
+// return wmClipboard (OS.WM_CUT, wParam, lParam);
+//}
+//
+//LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+// LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+// if (result != null) return result;
+//
+// /*
+// * Bug in WinCE PPC. For some reason, sending WM_GETDLGCODE
+// * to a multi-line edit control causes it to ignore return and
+// * tab keys. The fix is to return the value which is normally
+// * returned by the text window proc on other versions of Windows.
+// */
+// if (OS.IsPPC) {
+// if ((style & SWT.MULTI) != 0 && (style & SWT.READ_ONLY) == 0 && lParam == 0) {
+// return new LRESULT (OS.DLGC_HASSETSEL | OS.DLGC_WANTALLKEYS | OS.DLGC_WANTCHARS);
+// }
+// }
+//
+// /*
+// * Feature in Windows. Despite the fact that the
+// * edit control is read only, it still returns a
+// * dialog code indicating that it wants all keys.
+// * The fix is to detect this case and clear the bits.
+// *
+// * NOTE: A read only edit control processes arrow keys
+// * so DLGC_WANTARROWS should not be cleared.
+// */
+// if ((style & SWT.READ_ONLY) != 0) {
+// int code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
+// code &= ~(OS.DLGC_WANTALLKEYS | OS.DLGC_WANTTAB);
+// return new LRESULT (code);
+// }
+// return null;
+//}
+//
+//LRESULT WM_IME_CHAR (int wParam, int lParam) {
+//
+// /* Process a DBCS character */
+// Display display = this.display;
+// display.lastKey = 0;
+// display.lastAscii = wParam;
+// display.lastVirtual = display.lastNull = display.lastDead = false;
+// if (!sendKeyEvent (SWT.KeyDown, OS.WM_IME_CHAR, wParam, lParam)) {
+// return LRESULT.ZERO;
+// }
+//
+// /*
+// * Feature in Windows. The Windows text widget uses
+// * two 2 WM_CHAR's to process a DBCS key instead of
+// * using WM_IME_CHAR. The fix is to allow the text
+// * widget to get the WM_CHAR's but ignore sending
+// * them to the application.
+// */
+// ignoreCharacter = true;
+// int result = callWindowProc (handle, OS.WM_IME_CHAR, wParam, lParam);
+// MSG msg = new MSG ();
+// int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
+// while (OS.PeekMessage (msg, handle, OS.WM_CHAR, OS.WM_CHAR, flags)) {
+// OS.TranslateMessage (msg);
+// OS.DispatchMessage (msg);
+// }
+// ignoreCharacter = false;
+//
+// sendKeyEvent (SWT.KeyUp, OS.WM_IME_CHAR, wParam, lParam);
+// // widget could be disposed at this point
+// display.lastKey = display.lastAscii = 0;
+// return new LRESULT (result);
+//}
+//
+//LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
+// /*
+// * Prevent Windows from processing WM_LBUTTONDBLCLK
+// * when double clicking behavior is disabled by not
+// * calling the window proc.
+// */
+// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+// sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_LBUTTONDBLCLK, wParam, lParam);
+// if (OS.GetCapture () != handle) OS.SetCapture (handle);
+// if (!doubleClick) return LRESULT.ZERO;
+//
+// /*
+// * Bug in Windows. When the last line of text in the
+// * widget is double clicked and the line is empty, Windows
+// * hides the i-beam then moves it to the first line in
+// * the widget but does not scroll to show the user.
+// * If the user types without clicking the mouse, invalid
+// * characters are displayed at the end of each line of
+// * text in the widget. The fix is to detect this case
+// * and avoid calling the window proc.
+// */
+// int [] start = new int [1], end = new int [1];
+// OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+// if (start [0] == end [0]) {
+// int length = OS.GetWindowTextLength (handle);
+// if (length == start [0]) {
+// int result = OS.SendMessage (handle, OS.EM_LINELENGTH, length, 0);
+// if (result == 0) return LRESULT.ZERO;
+// }
+// }
+// return null;
+//}
+//
+//LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+// if (!OS.IsPPC) return super.WM_LBUTTONDOWN (wParam, lParam);
+// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+// /*
+// * Note: On WinCE PPC, only attempt to recognize the gesture for
+// * a context menu when the control contains a valid menu or there
+// * are listeners for the MenuDetect event.
+// *
+// * Note: On WinCE PPC, the gesture that brings up a popup menu
+// * on the text widget must keep the current text selection. As a
+// * result, the window proc is only called if the menu is not shown.
+// */
+// boolean hasMenu = menu != null && !menu.isDisposed ();
+// if (hasMenu || hooks (SWT.MenuDetect)) {
+// int x = (short) (lParam & 0xFFFF);
+// int y = (short) (lParam >> 16);
+// SHRGINFO shrg = new SHRGINFO ();
+// shrg.cbSize = SHRGINFO.sizeof;
+// shrg.hwndClient = handle;
+// shrg.ptDown_x = x;
+// shrg.ptDown_y = y;
+// shrg.dwFlags = OS.SHRG_RETURNCMD;
+// int type = OS.SHRecognizeGesture (shrg);
+// if (type == OS.GN_CONTEXTMENU) {
+// showMenu (x, y);
+// return LRESULT.ONE;
+// }
+// }
+// int result = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+// if (OS.GetCapture () != handle) OS.SetCapture (handle);
+// return new LRESULT (result);
+//}
+//
+//LRESULT WM_PASTE (int wParam, int lParam) {
+// LRESULT result = super.WM_PASTE (wParam, lParam);
+// if (result != null) return result;
+// return wmClipboard (OS.WM_PASTE, wParam, lParam);
+//}
+//
+//LRESULT WM_UNDO (int wParam, int lParam) {
+// LRESULT result = super.WM_UNDO (wParam, lParam);
+// if (result != null) return result;
+// return wmClipboard (OS.WM_UNDO, wParam, lParam);
+//}
+//
+//LRESULT wmClipboard (int msg, int wParam, int lParam) {
+// if ((style & SWT.READ_ONLY) != 0) return null;
+// if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
+// boolean call = false;
+// int [] start = new int [1], end = new int [1];
+// String newText = null;
+// switch (msg) {
+// case OS.WM_CLEAR:
+// case OS.WM_CUT:
+// OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+// if (start [0] != end [0]) {
+// newText = "";
+// call = true;
+// }
+// break;
+// case OS.WM_PASTE:
+// OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+// newText = getClipboardText ();
+// break;
+// case OS.EM_UNDO:
+// case OS.WM_UNDO:
+// if (OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0) != 0) {
+// OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+// ignoreModify = ignoreCharacter = true;
+// callWindowProc (handle, msg, wParam, lParam);
+// newText = getSelectionText ();
+// callWindowProc (handle, msg, wParam, lParam);
+// ignoreModify = ignoreCharacter = false;
+// }
+// break;
+// }
+// if (newText != null) {
+// String oldText = newText;
+// newText = verifyText (newText, start [0], end [0], null);
+// if (newText == null) return LRESULT.ZERO;
+// if (!newText.equals (oldText)) {
+// if (call) {
+// callWindowProc (handle, msg, wParam, lParam);
+// }
+// newText = Display.withCrLf (newText);
+// TCHAR buffer = new TCHAR (getCodePage (), newText, true);
+// /*
+// * Feature in Windows. When an edit control with ES_MULTILINE
+// * style that does not have the WS_VSCROLL style is full (i.e.
+// * there is no space at the end to draw any more characters),
+// * EM_REPLACESEL sends a WM_CHAR with a backspace character
+// * to remove any further text that is added. This is an
+// * implementation detail of the edit control that is unexpected
+// * and can cause endless recursion when EM_REPLACESEL is sent
+// * from a WM_CHAR handler. The fix is to ignore calling the
+// * handler from WM_CHAR.
+// */
+// ignoreCharacter = true;
+// OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
+// ignoreCharacter = false;
+// return LRESULT.ZERO;
+// }
+// }
+// if (msg == OS.WM_UNDO) {
+// ignoreVerify = ignoreCharacter = true;
+// callWindowProc (handle, OS.WM_UNDO, wParam, lParam);
+// ignoreVerify = ignoreCharacter = false;
+// return LRESULT.ONE;
+// }
+// return null;
+//}
+//
+//LRESULT wmCommandChild (int wParam, int lParam) {
+// int code = wParam >> 16;
+// switch (code) {
+// case OS.EN_CHANGE:
+// if (ignoreModify) break;
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the modify
+// * event. If this happens, end the processing of the
+// * Windows message by returning zero as the result of
+// * the window proc.
+// */
+// sendEvent (SWT.Modify);
+// if (isDisposed ()) return LRESULT.ZERO;
+// break;
+// case OS.EN_ALIGN_LTR_EC:
+// style &= ~SWT.RIGHT_TO_LEFT;
+// style |= SWT.LEFT_TO_RIGHT;
+// fixAlignment ();
+// break;
+// case OS.EN_ALIGN_RTL_EC:
+// style &= ~SWT.LEFT_TO_RIGHT;
+// style |= SWT.RIGHT_TO_LEFT;
+// fixAlignment ();
+// break;
+// }
+// return super.wmCommandChild (wParam, lParam);
+//}
+
+public void processEvent(EventObject e) {
+ if(e instanceof TextFilterEvent) {
+ if(!hooks(SWT.Verify)) { super.processEvent(e); return; }
+ } else { super.processEvent(e); return; }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ if(e instanceof TextFilterEvent) {
+ TextFilterEvent filterEvent = (TextFilterEvent)e;
+ filterEvent.setText(verifyText(filterEvent.getText(), filterEvent.getStart(), filterEvent.getStart() + filterEvent.getEnd(), createKeyEvent(filterEvent.getKeyEvent())));
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+protected boolean isTraversalKey(java.awt.event.KeyEvent ke) {
+ switch(ke.getKeyCode()) {
+ case java.awt.event.KeyEvent.VK_ENTER:
+ return (style & SWT.MULTI) == 0 || ((RootPaneContainer)getShell().handle).getRootPane().getDefaultButton() != null;
+ }
+ return super.isTraversalKey(ke);
+}
+
+protected int getTraversalKeyDetail(java.awt.event.KeyEvent ke) {
+ switch(ke.getKeyCode()) {
+ case java.awt.event.KeyEvent.VK_ENTER:
+ return SWT.TRAVERSE_RETURN;
+ }
+ return super.getTraversalKeyDetail(ke);
+}
+
+protected boolean getTraversalKeyDefault(java.awt.event.KeyEvent ke) {
+ switch(ke.getKeyCode()) {
+ case java.awt.event.KeyEvent.VK_TAB:
+ case java.awt.event.KeyEvent.VK_ENTER:
+ int modifiers = ke.getModifiers();
+ if((modifiers & java.awt.event.KeyEvent.CTRL_MASK) == 0 && (modifiers & java.awt.event.KeyEvent.SHIFT_MASK) == 0) {
+ return (style & SWT.MULTI) == 0;
+ }
+ default:
+ return super.getTraversalKeyDefault(ke);
+ }
+}
+
+protected void validateTraversalKey(java.awt.event.KeyEvent ke, Event event) {
+ switch(ke.getKeyCode()) {
+ case java.awt.event.KeyEvent.VK_ENTER:
+ if(event.doit) {
+ if(!hooks(SWT.DefaultSelection)) {
+ if(event.detail == SWT.TRAVERSE_RETURN) {
+ JButton defaultButton = ((RootPaneContainer)getShell().handle).getRootPane().getDefaultButton();
+ if(defaultButton != null) {
+ defaultButton.requestFocus();
+ defaultButton.doClick();
+ }
+ }
+ } else {
+ sendEvent(SWT.DefaultSelection);
+ }
+ ke.consume();
+ } else if((style & SWT.MULTI) == 0) {
+ ke.consume();
+ }
+ break;
+ default:
+ super.validateTraversalKey(ke, event);
+ break;
+ }
+}
+
+public void processEvent(DocumentEvent e) {
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ return;
+ }
+ try {
+ postEvent(SWT.Modify, new Event());
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolBar.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolBar.java
new file mode 100644
index 00000000000..599f90bbc26
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolBar.java
@@ -0,0 +1,575 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.util.ArrayList;
+
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.swing.CControl;
+import org.eclipse.swt.internal.swing.CToolBar;
+import org.eclipse.swt.internal.swing.Utils;
+
+/**
+ * Instances of this class support the layout of selectable
+ * tool bar items.
+ *
+ * The item children that may be added to instances of this class
+ * must be of type ToolItem.
+ *
+ * Note that although this class is a subclass of Composite,
+ * it does not make sense to add Control children to it,
+ * or set a layout on it.
+ *
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+public class ToolBar extends Composite {
+// int lastFocusId;
+ ArrayList itemList = new ArrayList();
+// ToolItem [] items;
+// boolean ignoreResize, ignoreMouse;
+// ImageList imageList, disabledImageList, hotImageList;
+
+// static final int DEFAULT_WIDTH = 24;
+// static final int DEFAULT_HEIGHT = 22;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public ToolItem getItem (int index) {
+ checkWidget ();
+ int count = getItemCount();
+ if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+ return (ToolItem)itemList.get(index);
+// return items [handle.getclpButton.idCommand];
+}
+
+/**
+ * Returns the item at the given point in the receiver
+ * or null if no such item exists. The point is in the
+ * coordinate system of the receiver.
+ *
+ * @param point the point used to locate the item
+ * @return the item at the given point
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemCount () {
+ checkWidget ();
+ return itemList.size();
+}
+
+/**
+ * Returns an array of ToolItems which are the items
+ * in the receiver.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public ToolItem [] getItems () {
+ checkWidget ();
+ return (ToolItem [])itemList.toArray(new ToolItem [0]);
+// int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+// TBBUTTON lpButton = new TBBUTTON ();
+// ToolItem [] result = new ToolItem [count];
+// for (int i=0; iWRAP style, the
+ * number of rows can be greater than one. Otherwise,
+ * the number of rows is always one.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getRowCount () {
+ checkWidget ();
+ Utils.notImplemented(); return 1;
+// if ((style & SWT.VERTICAL) != 0) {
+// return OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+// }
+// return OS.SendMessage (handle, OS.TB_GETROWS, 0, 0);
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the tool item is null
+ *
ERROR_INVALID_ARGUMENT - if the tool item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int indexOf (ToolItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ return itemList.indexOf(item);
+// return OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, item.id, 0);
+}
+
+//void layoutItems () {
+//// if ((style & SWT.WRAP) != 0) {
+//// OS.SendMessage(handle, OS.TB_AUTOSIZE, 0, 0);
+//// }
+// int count = itemList.size();
+// for (int i=0; i
+ *
Styles:
+ *
PUSH, CHECK, RADIO, SEPARATOR, DROP_DOWN
+ *
Events:
+ *
Selection
+ *
+ *
+ * Note: Only one of the styles CHECK, PUSH, RADIO, SEPARATOR and DROP_DOWN
+ * may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+public class ToolItem extends Item {
+ ToolBar parent;
+ Control control;
+ Image disabledImage, hotImage;
+// Image disabledImage2;
+// int id;
+ Container handle;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a ToolBar) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#PUSH
+ * @see SWT#CHECK
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ToolItem (ToolBar parent, int style) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ handle = createHandle();
+ parent.createItem (this, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a ToolBar), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#PUSH
+ * @see SWT#CHECK
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ToolItem (ToolBar parent, int style, int index) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ handle = createHandle();
+ parent.createItem (this, index);
+}
+
+/**
+ * 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 SelectionListener
+ * interface.
+ *
+ * When widgetSelected is called when the mouse is over the arrow portion of a drop-down tool,
+ * the event object detail field contains the value SWT.ARROW.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.DROP_DOWN, 0);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+//void click (boolean dropDown) {
+// int hwnd = parent.handle;
+// if (OS.GetKeyState (OS.VK_LBUTTON) < 0) return;
+// int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
+// RECT rect = new RECT ();
+// OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, rect);
+// int hotIndex = OS.SendMessage (hwnd, OS.TB_GETHOTITEM, 0, 0);
+//
+// /*
+// * In order to emulate all the processing that
+// * happens when a mnemonic key is pressed, fake
+// * a mouse press and release. This will ensure
+// * that radio and pull down items are handled
+// * properly.
+// */
+// int y = rect.top + (rect.bottom - rect.top) / 2;
+// int lParam = (dropDown ? rect.right - 1 : rect.left) | (y << 16);
+// parent.ignoreMouse = true;
+// OS.SendMessage (hwnd, OS.WM_LBUTTONDOWN, 0, lParam);
+// OS.SendMessage (hwnd, OS.WM_LBUTTONUP, 0, lParam);
+// parent.ignoreMouse = false;
+//
+// if (hotIndex != -1) {
+// OS.SendMessage (hwnd, OS.TB_SETHOTITEM, hotIndex, 0);
+// }
+//}
+
+//Image createDisabledImage (Image image, Color color) {
+// /*
+// * In order to be consistent with the way that disabled
+// * images appear in other places in the user interface,
+// * use the SWT Graphics to create a disabled image instead
+// * of calling DrawState().
+// */
+// return new Image (display, image, SWT.IMAGE_DISABLE);
+// /*
+// * This code is intentionally commented.
+// */
+//// if (OS.IsWinCE) {
+//// return new Image (display, image, SWT.IMAGE_DISABLE);
+//// }
+//// Rectangle rect = image.getBounds ();
+//// Image disabled = new Image (display, rect);
+//// GC gc = new GC (disabled);
+//// gc.setBackground (color);
+//// gc.fillRectangle (rect);
+//// int hDC = gc.handle;
+//// int hImage = image.handle;
+//// int fuFlags = OS.DSS_DISABLED;
+//// switch (image.type) {
+//// case SWT.BITMAP: fuFlags |= OS.DST_BITMAP; break;
+//// case SWT.ICON: fuFlags |= OS.DST_ICON; break;
+//// }
+//// OS.DrawState (hDC, 0, 0, hImage, 0, 0, 0, rect.width, rect.height, fuFlags);
+//// gc.dispose ();
+//// return disabled;
+//}
+
+Container createHandle () {
+ return (Container)CToolItem.Factory.newInstance(this, style);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Rectangle getBounds () {
+ checkWidget();
+ java.awt.Rectangle bounds = handle.getBounds();
+ return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
+}
+
+/**
+ * Returns the control that is used to fill the bounds of
+ * the item when the item is a SEPARATOR.
+ *
+ * @return the control
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Control getControl () {
+ checkWidget();
+ return control;
+}
+
+/**
+ * Returns the receiver's disabled image if it has one, or null
+ * if it does not.
+ *
+ * The disabled image is displayed when the receiver is disabled.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Image getDisabledImage () {
+ checkWidget();
+ return disabledImage;
+}
+
+/**
+ * Returns true if the receiver is enabled, and
+ * false 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #isEnabled
+ */
+public boolean getEnabled () {
+ checkWidget();
+ return handle.isEnabled();
+}
+
+/**
+ * Returns the receiver's hot image if it has one, or null
+ * if it does not.
+ *
+ * The hot image is displayed when the mouse enters the receiver.
+ *
+ *
+ * @return the receiver's hot image
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Image getHotImage () {
+ checkWidget();
+ return hotImage;
+}
+
+/**
+ * Returns the receiver's parent, which must be a ToolBar.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public ToolBar getParent () {
+ checkWidget();
+ return parent;
+}
+
+/**
+ * Returns true if the receiver is selected,
+ * and false otherwise.
+ *
+ * When the receiver is of type CHECK or RADIO,
+ * it is selected when it is checked (which some platforms draw as a
+ * pushed in button). If the receiver is of any other type, this method
+ * returns false.
+ *
+ *
+ * @return the selection state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getSelection () {
+ checkWidget();
+ if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false;
+ return ((CToolItem)handle).isSelected();
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getToolTipText () {
+ checkWidget();
+ return toolTipText;
+}
+
+/**
+ * Gets the width of the receiver.
+ *
+ * @return the width
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getWidth () {
+ checkWidget();
+ return handle.getWidth();
+// int hwnd = parent.handle;
+// int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
+// RECT rect = new RECT ();
+// OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, rect);
+// return rect.right - rect.left;
+}
+
+/**
+ * Returns true if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and false
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getEnabled
+ */
+public boolean isEnabled () {
+ checkWidget();
+ return getEnabled () && parent.isEnabled ();
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ parent = null;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ control = null;
+ disabledImage = hotImage = null;
+// if (disabledImage2 != null) disabledImage2.dispose ();
+// disabledImage2 = null;
+}
+
+//void releaseImages () {
+// TBBUTTONINFO info = new TBBUTTONINFO ();
+// info.cbSize = TBBUTTONINFO.sizeof;
+// info.dwMask = OS.TBIF_IMAGE | OS.TBIF_STYLE;
+// int hwnd = parent.handle;
+// OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, info);
+// /*
+// * Feature in Windows. For some reason, a tool item that has
+// * the style BTNS_SEP does not return I_IMAGENONE when queried
+// * for an image index, despite the fact that no attempt has been
+// * made to assign an image to the item. As a result, operations
+// * on an image list that use the wrong index cause random results.
+// * The fix is to ensure that the tool item is not a separator
+// * before using the image index. Since separators cannot have
+// * an image and one is never assigned, this is not a problem.
+// */
+// if ((info.fsStyle & OS.BTNS_SEP) == 0 && info.iImage != OS.I_IMAGENONE) {
+// ImageList imageList = parent.getImageList ();
+// ImageList hotImageList = parent.getHotImageList ();
+// ImageList disabledImageList = parent.getDisabledImageList();
+// if (imageList != null) imageList.put (info.iImage, null);
+// if (hotImageList != null) hotImageList.put (info.iImage, null);
+// if (disabledImageList != null) disabledImageList.put (info.iImage, null);
+// }
+//}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+//void resizeControl () {
+// if (control != null && !control.isDisposed ()) {
+// /*
+// * Set the size and location of the control
+// * separately to minimize flashing in the
+// * case where the control does not resize
+// * to the size that was requested. This
+// * case can occur when the control is a
+// * combo box.
+// */
+// Rectangle itemRect = getBounds ();
+// control.setSize (itemRect.width, itemRect.height);
+// Rectangle rect = control.getBounds ();
+// rect.x = itemRect.x + (itemRect.width - rect.width) / 2;
+// rect.y = itemRect.y + (itemRect.height - rect.height) / 2;
+// control.setLocation (rect.x, rect.y);
+//// } else {
+//// handle.setSize(handle.getPreferredSize());
+//// parent.handle.invalidate();
+//// parent.handle.validate();
+//// parent.handle.repaint();
+// }
+//}
+
+void selectRadio () {
+ int index = 0;
+ ToolItem [] items = parent.getItems ();
+ while (index < items.length && items [index] != this) index++;
+ int i = index - 1;
+ while (i >= 0 && items [i].setRadioSelection (false)) --i;
+ int j = index + 1;
+ while (j < items.length && items [j].setRadioSelection (false)) j++;
+ setSelection (true);
+}
+
+/**
+ * Sets the control that is used to fill the bounds of
+ * the item when the item is a SEPARATOR.
+ *
+ * @param control the new control
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the control has been disposed
+ *
ERROR_INVALID_PARENT - if the control is not in the same widget tree
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setControl (Control control) {
+ checkWidget();
+ if (control != null) {
+ if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+ if (control.parent != parent) error (SWT.ERROR_INVALID_PARENT);
+ }
+ if ((style & SWT.SEPARATOR) == 0) return;
+ if(this.control != null) {
+ handle.remove(this.control.handle);
+ }
+ this.control = control;
+ handle.add(control.handle);
+ handle.invalidate();
+ handle.validate();
+ handle.repaint();
+// handle.setPreferredSize(control.handle.getPreferredSize());
+// resizeControl ();
+}
+
+/**
+ * Enables the receiver if the argument is true,
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setEnabled (boolean enabled) {
+ checkWidget();
+ handle.setEnabled(enabled);
+ // TODO: save the disabled image that is used
+}
+
+/**
+ * Sets the receiver's disabled image to the argument, which may be
+ * null indicating that no disabled image should be displayed.
+ *
+ * The disbled image is displayed when the receiver is disabled.
+ *
+ *
+ * @param image the disabled image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setDisabledImage (Image image) {
+ checkWidget();
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ disabledImage = image;
+ ((CToolItem)handle).setDisabledIcon(image == null? null: new ImageIcon(image.handle));
+// updateImages ();
+}
+
+/**
+ * Sets the receiver's hot image to the argument, which may be
+ * null indicating that no hot image should be displayed.
+ *
+ * The hot image is displayed when the mouse enters the receiver.
+ *
+ *
+ * @param image the hot image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * When the receiver is of type CHECK or RADIO,
+ * it is selected when it is checked (which some platforms draw as a
+ * pushed in button).
+ *
+ *
+ * @param selected the new selection state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setSelection (boolean selected) {
+ checkWidget();
+ if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return;
+ isAdjustingSelection = true;
+ ((CToolItem)handle).setSelected(selected);
+ isAdjustingSelection = false;
+}
+
+/**
+ * Sets the receiver's text. The string may include
+ * the mnemonic character.
+ *
+ *
+ * Mnemonics are indicated by an '&' that causes the next
+ * character to be the mnemonic. When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasised in a platform specific
+ * manner. The mnemonic indicator character '&' can be
+ * escaped by doubling it in the string, causing a single
+ * '&' to be displayed.
+ *
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setText (String string) {
+ checkWidget();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if ((style & SWT.SEPARATOR) != 0) return;
+ if (string.equals (text)) return;
+ super.setText (string);
+ CToolItem cToolItem = (CToolItem)handle;
+ int index = findMnemonicIndex(string);
+ char mnemonic;
+ if(index < 0) {
+ mnemonic = '\0';
+ cToolItem.setText(string);
+ } else {
+ mnemonic = string.charAt(index);
+ cToolItem.setText(string.substring(0, index - 1) + string.substring(index));
+ }
+ cToolItem.setMnemonic(mnemonic);
+// parent.layoutItems ();
+}
+
+String toolTipText;
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setToolTipText (String string) {
+ checkWidget();
+ toolTipText = string;
+ ((CToolItem)handle).setToolTipText(Utils.convertStringToHTML(string));
+}
+
+/**
+ * Sets the width of the receiver, for SEPARATOR ToolItems.
+ *
+ * @param width the new width
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setWidth (int width) {
+ checkWidget();
+ if ((style & SWT.SEPARATOR) == 0) return;
+ if (width < 0) return;
+ ((CToolItem)handle).setWidth(width);
+ parent.handle.invalidate();
+ parent.handle.validate();
+ parent.handle.repaint();
+// parent.layoutItems ();
+}
+
+//void updateImages () {
+// int hwnd = parent.handle;
+// TBBUTTONINFO info = new TBBUTTONINFO ();
+// info.cbSize = TBBUTTONINFO.sizeof;
+// info.dwMask = OS.TBIF_IMAGE;
+// OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, info);
+// if (info.iImage == OS.I_IMAGENONE && image == null) return;
+// ImageList imageList = parent.getImageList ();
+// ImageList hotImageList = parent.getHotImageList ();
+// ImageList disabledImageList = parent.getDisabledImageList();
+// if (info.iImage == OS.I_IMAGENONE) {
+// Rectangle bounds = image.getBounds ();
+// Point size = new Point (bounds.width, bounds.height);
+// if (imageList == null) imageList = display.getToolImageList (size);
+// info.iImage = imageList.add (image);
+// parent.setImageList (imageList);
+// if (disabledImageList == null) disabledImageList = display.getToolDisabledImageList (size);
+// Image disabled = disabledImage;
+// if (disabledImage == null) {
+// if (disabledImage2 != null) disabledImage2.dispose ();
+// disabledImage2 = null;
+// disabled = image;
+// if (!getEnabled ()) {
+// Color color = parent.getBackground ();
+// disabled = disabledImage2 = createDisabledImage (image, color);
+// }
+// }
+// disabledImageList.add (disabled);
+// parent.setDisabledImageList (disabledImageList);
+//// if ((parent.style & SWT.FLAT) != 0) {
+// if (hotImageList == null) hotImageList = display.getToolHotImageList (size);
+// hotImageList.add (hotImage != null ? hotImage : image);
+// parent.setHotImageList (hotImageList);
+//// }
+// } else {
+// if (imageList != null) imageList.put (info.iImage, image);
+// if (disabledImageList != null) {
+// Image disabled = null;
+// if (image != null) {
+// if (disabledImage2 != null) disabledImage2.dispose ();
+// disabledImage2 = null;
+// disabled = disabledImage;
+// if (disabledImage == null) {
+// disabled = image;
+// if (!getEnabled ()) {
+// Color color = parent.getBackground ();
+// disabled = disabledImage2 = createDisabledImage (image, color);
+// }
+// }
+// }
+// disabledImageList.put (info.iImage, disabled);
+// }
+// if (hotImageList != null) {
+// Image hot = null;
+// if (image != null) hot = hotImage != null ? hotImage : image;
+// hotImageList.put (info.iImage, hot);
+// }
+// if (image == null) info.iImage = OS.I_IMAGENONE;
+// }
+//
+// /*
+// * Bug in Windows. If the width of an item has already been
+// * calculated, the tool bar control will not recalculate it to
+// * include the space for the image. The fix is to set the width
+// * to zero, forcing the control recalculate the width for the item.
+// */
+// info.dwMask |= OS.TBIF_SIZE;
+// info.cx = 0;
+// OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, info);
+//
+// parent.layoutItems ();
+//}
+
+//int widgetStyle () {
+// if ((style & SWT.DROP_DOWN) != 0) return OS.BTNS_DROPDOWN;
+// if ((style & SWT.PUSH) != 0) return OS.BTNS_BUTTON;
+// if ((style & SWT.CHECK) != 0) return OS.BTNS_CHECK;
+// /*
+// * This code is intentionally commented. In order to
+// * consistently support radio tool items across platforms,
+// * the platform radio behavior is not used.
+// */
+//// if ((style & SWT.RADIO) != 0) return OS.BTNS_CHECKGROUP;
+// if ((style & SWT.RADIO) != 0) return OS.BTNS_CHECK;
+// if ((style & SWT.SEPARATOR) != 0) return OS.BTNS_SEP;
+// return OS.BTNS_BUTTON;
+//}
+
+//LRESULT wmCommandChild (int wParam, int lParam) {
+// if ((style & SWT.RADIO) != 0) {
+// if ((parent.getStyle () & SWT.NO_RADIO_GROUP) == 0) {
+// selectRadio ();
+// }
+// }
+// postEvent (SWT.Selection);
+// return null;
+//}
+
+public void processEvent(AWTEvent e) {
+ int id = e.getID();
+ switch(id) {
+ case java.awt.event.ActionEvent.ACTION_PERFORMED: if((style & SWT.RADIO) == 0 && (isAdjustingSelection || !hooks(SWT.Selection))) return; break;
+ case java.awt.event.ItemEvent.ITEM_STATE_CHANGED: if(isAdjustingSelection || !hooks(SWT.Selection)) return; break;
+ default: return;
+ }
+ if(isDisposed()) {
+ return;
+ }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ return;
+ }
+ try {
+ switch(id) {
+ case java.awt.event.ActionEvent.ACTION_PERFORMED: {
+ Event event = new Event();
+ if((style & SWT.RADIO) != 0) {
+ if((parent.getStyle () & SWT.NO_RADIO_GROUP) == 0) {
+ selectRadio();
+ }
+ } else if("Arrow".equals(((java.awt.event.ActionEvent)e).getActionCommand())) {
+ event.detail = SWT.ARROW;
+ }
+ if(!isAdjustingSelection) {
+ sendEvent(SWT.Selection, event);
+ }
+ break;
+ }
+ case java.awt.event.ItemEvent.ITEM_STATE_CHANGED: {
+ if(!isAdjustingSelection) {
+ sendEvent(SWT.Selection);
+ }
+ break;
+ }
+ }
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolTip.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolTip.java
new file mode 100644
index 00000000000..29ef02f5b40
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/ToolTip.java
@@ -0,0 +1,567 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.TrayIcon.MessageType;
+
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.swing.Utils;
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class represent popup windows that are used
+ * to inform or warn the user.
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation.
+ *
+ *
+ * @since 3.2
+ */
+
+public class ToolTip extends Widget {
+ Shell parent;
+ TrayItem item;
+ String text = "";
+ String message = "";
+ int x;
+ int y;
+ boolean autoHide = true, hasLocation, visible;
+
+ /**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#ICON_ERROR
+ * @see SWT#ICON_INFORMATION
+ * @see SWT#ICON_WARNING
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public ToolTip (Shell parent, int style) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ checkOrientation (parent);
+ Utils.notImplemented();
+// parent.createToolTip (this);
+}
+
+static int checkStyle (int style) {
+ int mask = SWT.ICON_ERROR | SWT.ICON_INFORMATION | SWT.ICON_WARNING;
+ if ((style & mask) == 0) return style;
+ return checkBits (style, SWT.ICON_INFORMATION, SWT.ICON_WARNING, SWT.ICON_ERROR, 0, 0, 0);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's value changes, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener(listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+void destroyWidget () {
+ Utils.notImplemented();
+// if (parent != null) parent.destroyToolTip (this);
+ releaseHandle ();
+}
+
+/**
+ * Returns true if the receiver is automatically
+ * hidden by the platform, and false otherwise.
+ *
+ * @return the receiver's auto hide state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ */
+public boolean getAutoHide () {
+ checkWidget();
+ return autoHide;
+}
+
+/**
+ * Returns the receiver's message, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's message
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getMessage () {
+ checkWidget();
+ return message;
+}
+
+/**
+ * Returns the receiver's parent, which must be a Shell.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Shell getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getText () {
+ checkWidget();
+ return text;
+}
+
+/**
+ * Returns true if the receiver is visible, and
+ * false otherwise.
+ *
+ * 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.
+ *
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getVisible () {
+ checkWidget();
+ Utils.notImplemented(); return false;
+// if (OS.IsWinCE) return false;
+// if (item != null) return visible;
+// int hwndToolTip = hwndToolTip ();
+// if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) {
+// TOOLINFO lpti = new TOOLINFO ();
+// lpti.cbSize = TOOLINFO.sizeof;
+// if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
+// return (lpti.uFlags & OS.TTF_IDISHWND) == 0 && lpti.uId == id;
+// }
+// }
+// return false;
+}
+
+//int hwndToolTip () {
+// return (style & SWT.BALLOON) != 0 ? parent.balloonTipHandle () : parent.toolTipHandle ();
+//}
+
+/**
+ * Returns true if the receiver is visible and all
+ * of the receiver's ancestors are visible and false
+ * otherwise.
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getVisible
+ */
+public boolean isVisible () {
+ checkWidget ();
+ if (item != null) return getVisible () && item.getVisible ();
+ return getVisible ();
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ parent = null;
+ item = null;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ if (item == null) {
+ if (autoHide) {
+ Utils.notImplemented();
+// int hwndToolTip = hwndToolTip ();
+// if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) {
+// TOOLINFO lpti = new TOOLINFO ();
+// lpti.cbSize = TOOLINFO.sizeof;
+// if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
+// if ((lpti.uFlags & OS.TTF_IDISHWND) == 0) {
+// if (lpti.uId == id) OS.KillTimer (hwndToolTip, TIMER_ID);
+// }
+// }
+// }
+ }
+ }
+ if (item != null && item.toolTip == this) {
+ item.toolTip = null;
+ }
+ item = null;
+ text = message = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's value changes.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Makes the receiver hide automatically when true,
+ * and remain visible when false.
+ *
+ * @param autoHide the auto hide state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getVisible
+ * @see #setVisible
+ */
+public void setAutoHide (boolean autoHide) {
+ checkWidget ();
+ this.autoHide = autoHide;
+ //TODO - update when visible
+}
+
+/**
+ * Sets the location of the receiver, which must be a tooltip,
+ * to the point specified by the arguments which are relative
+ * to the display.
+ *
+ * Note that this is different from most widgets where the
+ * location of the widget is relative to the parent.
+ *
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setLocation (int x, int y) {
+ checkWidget ();
+ this.x = x;
+ this.y = y;
+ hasLocation = true;
+ //TODO - update when visible
+}
+
+/**
+ * Sets the location of the receiver, which must be a tooltip,
+ * to the point specified by the argument which is relative
+ * to the display.
+ *
+ * Note that this is different from most widgets where the
+ * location of the widget is relative to the parent.
+ *
+ * Note that the platform window manager ultimately has control
+ * over the location of tooltips.
+ *
+ *
+ * @param location the new location for the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setMessage (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ message = string;
+ //TODO - update when visible
+}
+
+/**
+ * Sets the receiver's text.
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the text is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ text = string;
+ //TODO - update when visible
+}
+
+/**
+ * Marks the receiver as visible if the argument is true,
+ * and marks it invisible otherwise.
+ *
+ * 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.
+ *
+ *
+ * @param visible the new visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setVisible (boolean visible) {
+ checkWidget ();
+ if (visible == getVisible ()) return;
+ if(item == null) {
+ Utils.notImplemented();
+ } else {
+ if(visible) {
+ MessageType messageType = null;
+ if((style & SWT.ICON_ERROR) != 0) {
+ messageType = MessageType.ERROR;
+ } else if((style & SWT.ICON_WARNING) != 0) {
+ messageType = MessageType.WARNING;
+ } else if((style & SWT.ICON_INFORMATION) != 0) {
+ messageType = MessageType.INFO;
+ } else {
+ messageType = MessageType.NONE;
+ }
+ item.trayIcon.displayMessage(text, message, messageType);
+ sendEvent (SWT.Show);
+ } else {
+ Utils.notImplemented();
+ }
+ }
+// if (OS.IsWinCE) return;
+// if (visible == getVisible ()) return;
+// if (item == null) {
+// int hwnd = parent.handle;
+// TOOLINFO lpti = new TOOLINFO ();
+// lpti.cbSize = TOOLINFO.sizeof;
+// lpti.uId = id;
+// lpti.hwnd = hwnd;
+// int hwndToolTip = hwndToolTip ();
+// if (text.length () != 0) {
+// int icon = OS.TTI_NONE;
+// if ((style & SWT.ICON_INFORMATION) != 0) icon = OS.TTI_INFO;
+// if ((style & SWT.ICON_WARNING) != 0) icon = OS.TTI_WARNING;
+// if ((style & SWT.ICON_ERROR) != 0) icon = OS.TTI_ERROR;
+// TCHAR pszTitle = new TCHAR (parent.getCodePage (), text, true);
+// OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, icon, pszTitle);
+// } else {
+// OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, 0, 0);
+// }
+// int maxWidth = 0;
+// if (OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+// RECT rect = new RECT ();
+// OS.SystemParametersInfo (OS.SPI_GETWORKAREA, 0, rect, 0);
+// maxWidth = (rect.right - rect.left) / 4;
+// } else {
+// int hmonitor = OS.MonitorFromWindow (hwnd, OS.MONITOR_DEFAULTTONEAREST);
+// MONITORINFO lpmi = new MONITORINFO ();
+// lpmi.cbSize = MONITORINFO.sizeof;
+// OS.GetMonitorInfo (hmonitor, lpmi);
+// maxWidth = (lpmi.rcWork_right - lpmi.rcWork_left) / 4;
+// }
+// OS.SendMessage (hwndToolTip, OS.TTM_SETMAXTIPWIDTH, 0, maxWidth);
+// if (visible) {
+// int nX = x, nY = y;
+// if (!hasLocation) {
+// POINT pt = new POINT ();
+// if (OS.GetCursorPos (pt)) {
+// nX = pt.x;
+// nY = pt.y;
+// }
+// }
+// int lParam = nX | (nY << 16);
+// OS.SendMessage (hwndToolTip, OS.TTM_TRACKPOSITION, 0, lParam);
+//
+// /*
+// * Feature in Windows. Windows will not show a tool tip
+// * if the cursor is outside the parent window (even on XP,
+// * TTM_POPUP will not do this). The fix is to temporarily
+// * move the cursor into the tool window, show the tool tip,
+// * and then restore the cursor.
+// */
+// POINT pt = new POINT ();
+// OS.GetCursorPos (pt);
+// RECT rect = new RECT ();
+// OS.GetClientRect (hwnd, rect);
+// OS.MapWindowPoints (hwnd, 0, rect, 2);
+// if (!OS.PtInRect (rect, pt)) {
+// int hCursor = OS.GetCursor ();
+// OS.SetCursor (0);
+// OS.SetCursorPos (rect.left, rect.top);
+// OS.SendMessage (hwndToolTip, OS.TTM_TRACKACTIVATE, 1, lpti);
+// OS.SetCursorPos (pt.x, pt.y);
+// OS.SetCursor (hCursor);
+// } else {
+// OS.SendMessage (hwndToolTip, OS.TTM_TRACKACTIVATE, 1, lpti);
+// }
+//
+// int time = OS.SendMessage (hwndToolTip, OS.TTM_GETDELAYTIME, OS.TTDT_AUTOPOP, 0);
+// OS.SetTimer (hwndToolTip, TIMER_ID, time, 0);
+// } else {
+// OS.SendMessage (hwndToolTip, OS.TTM_TRACKACTIVATE, 0, lpti);
+// OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, 0, 0);
+// OS.SendMessage (hwndToolTip, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+// OS.SendMessage (hwndToolTip, OS.TTM_POP, 0, 0);
+// OS.KillTimer (hwndToolTip, TIMER_ID);
+// }
+// return;
+// }
+// if (item != null && OS.SHELL32_MAJOR >= 5) {
+// if (visible) {
+// NOTIFYICONDATA iconData = OS.IsUnicode ? (NOTIFYICONDATA) new NOTIFYICONDATAW () : new NOTIFYICONDATAA ();
+// TCHAR buffer1 = new TCHAR (0, text, true);
+// TCHAR buffer2 = new TCHAR (0, message, true);
+// if (OS.IsUnicode) {
+// char [] szInfoTitle = ((NOTIFYICONDATAW) iconData).szInfoTitle;
+// int length1 = Math.min (szInfoTitle.length - 1, buffer1.length ());
+// System.arraycopy (buffer1.chars, 0, szInfoTitle, 0, length1);
+// char [] szInfo = ((NOTIFYICONDATAW) iconData).szInfo;
+// int length2 = Math.min (szInfo.length - 1, buffer2.length ());
+// System.arraycopy (buffer2.chars, 0, szInfo, 0, length2);
+// } else {
+// byte [] szInfoTitle = ((NOTIFYICONDATAA) iconData).szInfoTitle;
+// int length = Math.min (szInfoTitle.length - 1, buffer1.length ());
+// System.arraycopy (buffer1.bytes, 0, szInfoTitle, 0, length);
+// byte [] szInfo = ((NOTIFYICONDATAA) iconData).szInfo;
+// int length2 = Math.min (szInfo.length - 1, buffer2.length ());
+// System.arraycopy (buffer2.bytes, 0, szInfo, 0, length2);
+// }
+// Display display = item.getDisplay ();
+// iconData.cbSize = NOTIFYICONDATA.sizeof;
+// iconData.uID = item.id;
+// iconData.hWnd = display.hwndMessage;
+// iconData.uFlags = OS.NIF_INFO;
+// if ((style & SWT.ICON_INFORMATION) != 0) iconData.dwInfoFlags = OS.NIIF_INFO;
+// if ((style & SWT.ICON_WARNING) != 0) iconData.dwInfoFlags = OS.NIIF_WARNING;
+// if ((style & SWT.ICON_ERROR) != 0) iconData.dwInfoFlags = OS.NIIF_ERROR;
+// sendEvent (SWT.Show);
+// this.visible = OS.Shell_NotifyIcon (OS.NIM_MODIFY, iconData);
+// } else {
+// //TODO - hide the tray item
+// }
+// }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tracker.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tracker.java
new file mode 100644
index 00000000000..5848a538fe4
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tracker.java
@@ -0,0 +1,1236 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.Component;
+import java.awt.MouseInfo;
+import java.awt.Point;
+import java.awt.Window;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+
+import javax.swing.SwingUtilities;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.swing.CControl;
+import org.eclipse.swt.internal.swing.Compatibility;
+import org.eclipse.swt.internal.swing.JTracker;
+import org.eclipse.swt.internal.swing.Utils;
+
+/**
+ * Instances of this class implement rubber banding rectangles that are
+ * drawn onto a parent Composite or Display.
+ * These rectangles can be specified to respond to mouse and key events
+ * by either moving or resizing themselves accordingly. Trackers are
+ * typically used to represent window geometries in a lightweight manner.
+ *
+ *
+ *
Styles:
+ *
LEFT, RIGHT, UP, DOWN, RESIZE
+ *
Events:
+ *
Move, Resize
+ *
+ *
+ * Note: Rectangle move behavior is assumed unless RESIZE is specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+public class Tracker extends Widget {
+
+ protected final class JTrackerExtension extends JTracker {
+
+ protected final Window window;
+
+ private JTrackerExtension(Component component, boolean isResizeType, Window window) {
+ super(component, isResizeType);
+ this.window = window;
+ }
+
+ protected TrackerWindow createTrackerWindow(Window ownerWindow) {
+ return new TrackerWindow(ownerWindow) {
+ public java.awt.Cursor getCursor() {
+ return Utils.globalCursor != null? Utils.globalCursor: super.getCursor();
+ }
+ };
+ }
+
+ protected Window createSharedOwnerWindow() {
+ return window != null? window: super.createSharedOwnerWindow();
+ }
+
+ protected void releaseSharedOwnerWindow(Window sharedOwnerWindow) {
+ if(window == null) {
+ super.releaseSharedOwnerWindow(sharedOwnerWindow);
+ }
+ }
+
+ protected void processMouseEvent(MouseEvent me) {
+ if(!Compatibility.IS_JAVA_5_OR_GREATER) {
+ Utils.trackMouseProperties(me);
+ }
+ super.processMouseEvent(me);
+ if(Utils.capturedControl != null) {
+ Component target = ((CControl)Utils.capturedControl.handle).getClientArea();
+ java.awt.Point point = SwingUtilities.convertPoint((Component)me.getSource(), me.getX(), me.getY(), target);
+ if(me.getID() == MouseEvent.MOUSE_WHEEL) {
+ MouseWheelEvent mwe = (MouseWheelEvent)me;
+ me = new MouseWheelEvent(target, mwe.getID(), mwe.getWhen(), mwe.getModifiers(), point.x, point.y, mwe.getClickCount(), mwe.isPopupTrigger(), mwe.getScrollType(), mwe.getScrollAmount(), mwe.getWheelRotation());
+ } else {
+ me = new MouseEvent(target, me.getID(), me.getWhen(), me.getModifiers(), point.x, point.y, me.getClickCount(), me.isPopupTrigger());
+ }
+ target.dispatchEvent(me);
+ }
+ }
+
+ public void updateCursor() {
+ Window ownerWindow = getSharedOwnerWindow();
+ if(ownerWindow == null) {
+ return;
+ }
+ Window w = new Window(ownerWindow) {
+ public boolean isFocusable() {
+ return false;
+ }
+ public java.awt.Cursor getCursor() {
+ return Utils.globalCursor != null? Utils.globalCursor: super.getCursor();
+ }
+ };
+ w.setFocusableWindowState(false);
+ Point mouseLocation;
+ if(Compatibility.IS_JAVA_5_OR_GREATER) {
+ mouseLocation = MouseInfo.getPointerInfo().getLocation();
+ } else {
+ mouseLocation = getLastMouseLocation();
+ }
+ if(mouseLocation != null) {
+ w.setBounds(mouseLocation.x, mouseLocation.y, 1, 1);
+ w.setVisible(true);
+ w.dispose();
+ }
+ }
+
+ public void hide() {
+ Utils.setGlobalCursor(null);
+ updateCursor();
+ super.hide();
+ }
+
+ }
+
+ Control parent;
+ JTrackerExtension handle;
+ boolean stippled;
+ Cursor cursor;
+// boolean tracking, cancelled;
+// Rectangle [] rectangles, proportions;
+// Rectangle bounds;
+// int resizeCursor, clientCursor, cursorOrientation = SWT.NONE;
+// boolean inEvent = false;
+// int oldProc, oldX, oldY;
+
+// /*
+// * The following values mirror step sizes on Windows
+// */
+// final static int STEPSIZE_SMALL = 1;
+// final static int STEPSIZE_LARGE = 9;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#UP
+ * @see SWT#DOWN
+ * @see SWT#RESIZE
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Tracker (Composite parent, int style) {
+ super (parent, checkStyle (style));
+ this.parent = parent;
+ createWidget ();
+}
+
+/**
+ * Constructs a new instance of this class given the display
+ * to create it on and a style value describing its behavior
+ * and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ * Note: Currently, null can be passed in for the display argument.
+ * This has the effect of creating the tracker on the currently active
+ * display if there is one. If there is no current display, the
+ * tracker is created on a "default" display. Passing in null as
+ * the display argument is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.
+ *
+ *
+ * @param display the display to create the tracker on
+ * @param style the style of control to construct
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#UP
+ * @see SWT#DOWN
+ */
+public Tracker (Display display, int style) {
+ if (display == null) display = Display.getCurrent ();
+ if (display == null) display = Display.getDefault ();
+ if (!display.isValidThread ()) {
+ error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ }
+ this.style = checkStyle (style);
+ this.display = display;
+ createWidget ();
+}
+
+/**
+ * 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 ControlListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @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.Resize, typedListener);
+ addListener (SWT.Move, typedListener);
+}
+
+/**
+ * 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 KeyListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see KeyListener
+ * @see #removeKeyListener
+ */
+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);
+}
+
+//Point adjustMoveCursor () {
+// int newX = bounds.x + bounds.width / 2;
+// int newY = bounds.y;
+// Utils.notImplemented(); return null;
+//// POINT pt = new POINT ();
+//// pt.x = newX; pt.y = newY;
+//// /*
+//// * Convert to screen coordinates iff needed
+//// */
+//// if (parent != null) {
+//// OS.ClientToScreen (parent.handle, pt);
+//// }
+//// OS.SetCursorPos (pt.x, pt.y);
+//// return new Point (pt.x, pt.y);
+//}
+
+//Point adjustResizeCursor () {
+// int newX, newY;
+//
+// if ((cursorOrientation & SWT.LEFT) != 0) {
+// newX = bounds.x;
+// } else if ((cursorOrientation & SWT.RIGHT) != 0) {
+// newX = bounds.x + bounds.width;
+// } else {
+// newX = bounds.x + bounds.width / 2;
+// }
+//
+// if ((cursorOrientation & SWT.UP) != 0) {
+// newY = bounds.y;
+// } else if ((cursorOrientation & SWT.DOWN) != 0) {
+// newY = bounds.y + bounds.height;
+// } else {
+// newY = bounds.y + bounds.height / 2;
+// }
+//
+// Utils.notImplemented(); return null;
+// POINT pt = new POINT ();
+// pt.x = newX; pt.y = newY;
+// /*
+// * Convert to screen coordinates iff needed
+// */
+// if (parent != null) {
+// OS.ClientToScreen (parent.handle, pt);
+// }
+// OS.SetCursorPos (pt.x, pt.y);
+//
+// /*
+// * If the client has not provided a custom cursor then determine
+// * the appropriate resize cursor.
+// */
+// if (clientCursor == 0) {
+// int newCursor = 0;
+// switch (cursorOrientation) {
+// case SWT.UP:
+// newCursor = OS.LoadCursor (0, OS.IDC_SIZENS);
+// break;
+// case SWT.DOWN:
+// newCursor = OS.LoadCursor (0, OS.IDC_SIZENS);
+// break;
+// case SWT.LEFT:
+// newCursor = OS.LoadCursor (0, OS.IDC_SIZEWE);
+// break;
+// case SWT.RIGHT:
+// newCursor = OS.LoadCursor (0, OS.IDC_SIZEWE);
+// break;
+// case SWT.LEFT | SWT.UP:
+// newCursor = OS.LoadCursor (0, OS.IDC_SIZENWSE);
+// break;
+// case SWT.RIGHT | SWT.DOWN:
+// newCursor = OS.LoadCursor (0, OS.IDC_SIZENWSE);
+// break;
+// case SWT.LEFT | SWT.DOWN:
+// newCursor = OS.LoadCursor (0, OS.IDC_SIZENESW);
+// break;
+// case SWT.RIGHT | SWT.UP:
+// newCursor = OS.LoadCursor (0, OS.IDC_SIZENESW);
+// break;
+// default:
+// newCursor = OS.LoadCursor (0, OS.IDC_SIZEALL);
+// break;
+// }
+// OS.SetCursor (newCursor);
+// if (resizeCursor != 0) {
+// OS.DestroyCursor (resizeCursor);
+// }
+// resizeCursor = newCursor;
+// }
+//
+// return new Point (pt.x, pt.y);
+//}
+
+static int checkStyle (int style) {
+ if ((style & (SWT.LEFT | SWT.RIGHT | SWT.UP | SWT.DOWN)) == 0) {
+ style |= SWT.LEFT | SWT.RIGHT | SWT.UP | SWT.DOWN;
+ }
+ return style;
+}
+
+/**
+ * Stops displaying the tracker rectangles. Note that this is not considered
+ * to be a cancelation by the user.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void close () {
+ checkWidget ();
+ handle.hide();
+// tracking = false;
+}
+
+//Rectangle computeBounds () {
+// int xMin = rectangles [0].x;
+// int yMin = rectangles [0].y;
+// int xMax = rectangles [0].x + rectangles [0].width;
+// int yMax = rectangles [0].y + rectangles [0].height;
+//
+// for (int i = 1; i < rectangles.length; i++) {
+// if (rectangles [i].x < xMin) xMin = rectangles [i].x;
+// if (rectangles [i].y < yMin) yMin = rectangles [i].y;
+// int rectRight = rectangles [i].x + rectangles [i].width;
+// if (rectRight > xMax) xMax = rectRight;
+// int rectBottom = rectangles [i].y + rectangles [i].height;
+// if (rectBottom > yMax) yMax = rectBottom;
+// }
+//
+// return new Rectangle (xMin, yMin, xMax - xMin, yMax - yMin);
+//}
+
+//Rectangle [] computeProportions (Rectangle [] rects) {
+// Rectangle [] result = new Rectangle [rects.length];
+// bounds = computeBounds ();
+// for (int i = 0; i < rects.length; i++) {
+// int x = 0, y = 0, width = 0, height = 0;
+// if (bounds.width != 0) {
+// x = (rects [i].x - bounds.x) * 100 / bounds.width;
+// width = rects [i].width * 100 / bounds.width;
+// } else {
+// width = 100;
+// }
+// if (bounds.height != 0) {
+// y = (rects [i].y - bounds.y) * 100 / bounds.height;
+// height = rects [i].height * 100 / bounds.height;
+// } else {
+// height = 100;
+// }
+// result [i] = new Rectangle (x, y, width, height);
+// }
+// return result;
+//}
+
+///**
+// * Draw the rectangles displayed by the tracker.
+// */
+//void drawRectangles (Rectangle [] rects, boolean stippled) {
+// int bandWidth = 1;
+// int hwndTrack = OS.GetDesktopWindow ();
+// if (parent != null) hwndTrack = parent.handle;
+// int hDC = OS.GetDCEx (hwndTrack, 0, OS.DCX_CACHE);
+// int hBitmap = 0, hBrush = 0, oldBrush = 0;
+// if (stippled) {
+// bandWidth = 3;
+// byte [] bits = {-86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0};
+// hBitmap = OS.CreateBitmap (8, 8, 1, 1, bits);
+// hBrush = OS.CreatePatternBrush (hBitmap);
+// oldBrush = OS.SelectObject (hDC, hBrush);
+// }
+// for (int i=0; iDisplay then these are screen
+ * coordinates.
+ *
+ * @return the bounds of the Rectangles being drawn
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Rectangle [] getRectangles () {
+ checkWidget();
+ java.awt.Rectangle[] rectangles = handle.getRectangles();
+ int length = 0;
+ if (rectangles != null) length = rectangles.length;
+ Rectangle [] result = new Rectangle [length];
+ for (int i = 0; i < length; i++) {
+ java.awt.Rectangle current = rectangles [i];
+ result [i] = new Rectangle (current.x, current.y, current.width, current.height);
+ }
+ return result;
+}
+
+/**
+ * Returns true if the rectangles are drawn with a stippled line, false otherwise.
+ *
+ * @return the stippled effect of the rectangles
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getStippled () {
+ checkWidget ();
+ return stippled;
+}
+
+//void moveRectangles (int xChange, int yChange) {
+// if (xChange < 0 && ((style & SWT.LEFT) == 0)) xChange = 0;
+// if (xChange > 0 && ((style & SWT.RIGHT) == 0)) xChange = 0;
+// if (yChange < 0 && ((style & SWT.UP) == 0)) yChange = 0;
+// if (yChange > 0 && ((style & SWT.DOWN) == 0)) yChange = 0;
+// if (xChange == 0 && yChange == 0) return;
+// bounds.x += xChange; bounds.y += yChange;
+// for (int i = 0; i < rectangles.length; i++) {
+// rectangles [i].x += xChange;
+// rectangles [i].y += yChange;
+// }
+//}
+
+/**
+ * Displays the Tracker rectangles for manipulation by the user. Returns when
+ * the user has either finished manipulating the rectangles or has cancelled the
+ * Tracker.
+ *
+ * @return true if the user did not cancel the Tracker, false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean open () {
+ checkWidget ();
+ if (!hasRectangles) return false;
+// cancelled = false;
+// tracking = true;
+
+// /*
+// * If exactly one of UP/DOWN is specified as a style then set the cursor
+// * orientation accordingly (the same is done for LEFT/RIGHT styles below).
+// */
+// int vStyle = style & (SWT.UP | SWT.DOWN);
+// if (vStyle == SWT.UP || vStyle == SWT.DOWN) {
+// cursorOrientation |= vStyle;
+// }
+// int hStyle = style & (SWT.LEFT | SWT.RIGHT);
+// if (hStyle == SWT.LEFT || hStyle == SWT.RIGHT) {
+// cursorOrientation |= hStyle;
+// }
+ Utils.setGlobalCursor(cursor == null? null: cursor.handle);
+ boolean isValid = handle.show();
+ Utils.setGlobalCursor(null);
+ return isValid;
+// /*
+// * If this tracker is being created without a mouse drag then
+// * we need to create a transparent window that fills the screen
+// * in order to get all mouse/keyboard events that occur
+// * outside of our visible windows (ie.- over the desktop).
+// */
+// int hwndTransparent = 0;
+// Callback newProc = null;
+// boolean mouseDown = OS.GetKeyState(OS.VK_LBUTTON) < 0;
+// if (!mouseDown) {
+// int width = OS.GetSystemMetrics (OS.SM_CXSCREEN);
+// int height = OS.GetSystemMetrics (OS.SM_CYSCREEN);
+// hwndTransparent = OS.CreateWindowEx (
+// OS.WS_EX_TRANSPARENT,
+// display.windowClass,
+// null,
+// OS.WS_POPUP | OS.WS_VISIBLE,
+// 0, 0,
+// width, height,
+// 0,
+// 0,
+// OS.GetModuleHandle (null),
+// null);
+// oldProc = OS.GetWindowLong (hwndTransparent, OS.GWL_WNDPROC);
+// newProc = new Callback (this, "transparentProc", 4); //$NON-NLS-1$
+// OS.SetWindowLong (hwndTransparent, OS.GWL_WNDPROC, newProc.getAddress ());
+// }
+//
+// update ();
+// drawRectangles (rectangles, stippled);
+// Point cursorPos;
+// if (mouseDown) {
+// POINT pt = new POINT ();
+// OS.GetCursorPos (pt);
+// cursorPos = new Point (pt.x, pt.y);
+// } else {
+// if ((style & SWT.RESIZE) != 0) {
+// cursorPos = adjustResizeCursor ();
+// } else {
+// cursorPos = adjustMoveCursor ();
+// }
+// }
+// oldX = cursorPos.x;
+// oldY = cursorPos.y;
+//
+// /* Tracker behaves like a Dialog with its own OS event loop. */
+// MSG msg = new MSG ();
+// while (tracking && !cancelled) {
+// if (parent != null && parent.isDisposed ()) break;
+// OS.GetMessage (msg, 0, 0, 0);
+// OS.TranslateMessage (msg);
+// switch (msg.message) {
+// case OS.WM_LBUTTONUP:
+// case OS.WM_MOUSEMOVE:
+// wmMouse (msg.message, msg.wParam, msg.lParam);
+// break;
+// case OS.WM_IME_CHAR: wmIMEChar (msg.hwnd, msg.wParam, msg.lParam); break;
+// case OS.WM_CHAR: wmChar (msg.hwnd, msg.wParam, msg.lParam); break;
+// case OS.WM_KEYDOWN: wmKeyDown (msg.hwnd, msg.wParam, msg.lParam); break;
+// case OS.WM_KEYUP: wmKeyUp (msg.hwnd, msg.wParam, msg.lParam); break;
+// case OS.WM_SYSCHAR: wmSysChar (msg.hwnd, msg.wParam, msg.lParam); break;
+// case OS.WM_SYSKEYDOWN: wmSysKeyDown (msg.hwnd, msg.wParam, msg.lParam); break;
+// case OS.WM_SYSKEYUP: wmSysKeyUp (msg.hwnd, msg.wParam, msg.lParam); break;
+// }
+// if (OS.WM_KEYFIRST <= msg.message && msg.message <= OS.WM_KEYLAST) continue;
+// if (OS.WM_MOUSEFIRST <= msg.message && msg.message <= OS.WM_MOUSELAST) continue;
+// if (msg.message == OS.WM_PAINT) {
+// update ();
+// drawRectangles (rectangles, stippled);
+// }
+// OS.DispatchMessage (msg);
+// if (msg.message == OS.WM_PAINT) {
+// drawRectangles (rectangles, stippled);
+// }
+// }
+// if (mouseDown) OS.ReleaseCapture ();
+// if (!isDisposed()) {
+// update ();
+// drawRectangles (rectangles, stippled);
+// }
+// /*
+// * Cleanup: If a transparent window was created in order to capture events then
+// * destroy it and its callback object now.
+// */
+// if (hwndTransparent != 0) {
+// OS.DestroyWindow (hwndTransparent);
+// }
+// if (newProc != null) {
+// newProc.dispose ();
+// oldProc = 0;
+// }
+// /*
+// * Cleanup: If this tracker was resizing then the last cursor that it created
+// * needs to be destroyed.
+// */
+// if (resizeCursor != 0) {
+// OS.DestroyCursor (resizeCursor);
+// resizeCursor = 0;
+// }
+// tracking = false;
+// return !cancelled;
+}
+
+/**
+ * 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
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Resize, listener);
+ eventTable.unhook (SWT.Move, listener);
+}
+
+/**
+ * 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
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see KeyListener
+ * @see #addKeyListener
+ */
+public void removeKeyListener(KeyListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.KeyUp, listener);
+ eventTable.unhook (SWT.KeyDown, listener);
+}
+
+//void resizeRectangles (int xChange, int yChange) {
+// /*
+// * If the cursor orientation has not been set in the orientation of
+// * this change then try to set it here.
+// */
+// if (xChange < 0 && ((style & SWT.LEFT) != 0) && ((cursorOrientation & SWT.RIGHT) == 0)) {
+// cursorOrientation |= SWT.LEFT;
+// }
+// if (xChange > 0 && ((style & SWT.RIGHT) != 0) && ((cursorOrientation & SWT.LEFT) == 0)) {
+// cursorOrientation |= SWT.RIGHT;
+// }
+// if (yChange < 0 && ((style & SWT.UP) != 0) && ((cursorOrientation & SWT.DOWN) == 0)) {
+// cursorOrientation |= SWT.UP;
+// }
+// if (yChange > 0 && ((style & SWT.DOWN) != 0) && ((cursorOrientation & SWT.UP) == 0)) {
+// cursorOrientation |= SWT.DOWN;
+// }
+//
+// /*
+// * If the bounds will flip about the x or y axis then apply the adjustment
+// * up to the axis (ie.- where bounds width/height becomes 0), change the
+// * cursor's orientation accordingly, and flip each Rectangle's origin (only
+// * necessary for > 1 Rectangles)
+// */
+// if ((cursorOrientation & SWT.LEFT) != 0) {
+// if (xChange > bounds.width) {
+// if ((style & SWT.RIGHT) == 0) return;
+// cursorOrientation |= SWT.RIGHT;
+// cursorOrientation &= ~SWT.LEFT;
+// bounds.x += bounds.width;
+// xChange -= bounds.width;
+// bounds.width = 0;
+// if (proportions.length > 1) {
+// for (int i = 0; i < proportions.length; i++) {
+// Rectangle proportion = proportions [i];
+// proportion.x = 100 - proportion.x - proportion.width;
+// }
+// }
+// }
+// } else if ((cursorOrientation & SWT.RIGHT) != 0) {
+// if (bounds.width < -xChange) {
+// if ((style & SWT.LEFT) == 0) return;
+// cursorOrientation |= SWT.LEFT;
+// cursorOrientation &= ~SWT.RIGHT;
+// xChange += bounds.width;
+// bounds.width = 0;
+// if (proportions.length > 1) {
+// for (int i = 0; i < proportions.length; i++) {
+// Rectangle proportion = proportions [i];
+// proportion.x = 100 - proportion.x - proportion.width;
+// }
+// }
+// }
+// }
+// if ((cursorOrientation & SWT.UP) != 0) {
+// if (yChange > bounds.height) {
+// if ((style & SWT.DOWN) == 0) return;
+// cursorOrientation |= SWT.DOWN;
+// cursorOrientation &= ~SWT.UP;
+// bounds.y += bounds.height;
+// yChange -= bounds.height;
+// bounds.height = 0;
+// if (proportions.length > 1) {
+// for (int i = 0; i < proportions.length; i++) {
+// Rectangle proportion = proportions [i];
+// proportion.y = 100 - proportion.y - proportion.height;
+// }
+// }
+// }
+// } else if ((cursorOrientation & SWT.DOWN) != 0) {
+// if (bounds.height < -yChange) {
+// if ((style & SWT.UP) == 0) return;
+// cursorOrientation |= SWT.UP;
+// cursorOrientation &= ~SWT.DOWN;
+// yChange += bounds.height;
+// bounds.height = 0;
+// if (proportions.length > 1) {
+// for (int i = 0; i < proportions.length; i++) {
+// Rectangle proportion = proportions [i];
+// proportion.y = 100 - proportion.y - proportion.height;
+// }
+// }
+// }
+// }
+//
+// // apply the bounds adjustment
+// if ((cursorOrientation & SWT.LEFT) != 0) {
+// bounds.x += xChange;
+// bounds.width -= xChange;
+// } else if ((cursorOrientation & SWT.RIGHT) != 0) {
+// bounds.width += xChange;
+// }
+// if ((cursorOrientation & SWT.UP) != 0) {
+// bounds.y += yChange;
+// bounds.height -= yChange;
+// } else if ((cursorOrientation & SWT.DOWN) != 0) {
+// bounds.height += yChange;
+// }
+//
+// Rectangle [] newRects = new Rectangle [rectangles.length];
+// for (int i = 0; i < rectangles.length; i++) {
+// Rectangle proportion = proportions[i];
+// newRects[i] = new Rectangle (
+// proportion.x * bounds.width / 100 + bounds.x,
+// proportion.y * bounds.height / 100 + bounds.y,
+// proportion.width * bounds.width / 100,
+// proportion.height * bounds.height / 100);
+// }
+// rectangles = newRects;
+//}
+
+/**
+ * Sets the Cursor of the Tracker. If this cursor is null
+ * then the cursor reverts to the default.
+ *
+ * @param newCursor the new Cursor to display
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setCursor(Cursor newCursor) {
+ checkWidget();
+ if(cursor == newCursor) {
+ return;
+ }
+ cursor = newCursor;
+ if(handle.isVisible()) {
+ Utils.setGlobalCursor(cursor == null? null: cursor.handle);
+ }
+ handle.updateCursor();
+}
+
+boolean hasRectangles;
+
+/**
+ * Specifies the rectangles that should be drawn, expressed relative to the parent
+ * widget. If the parent is a Display then these are screen coordinates.
+ *
+ * @param rectangles the bounds of the rectangles to be drawn
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the set of rectangles is null or contains a null rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setRectangles (Rectangle [] rectangles) {
+ checkWidget ();
+ if (rectangles == null) error (SWT.ERROR_NULL_ARGUMENT);
+// int length = rectangles.length;
+// this.rectangles = new Rectangle [length];
+// for (int i = 0; i < length; i++) {
+// Rectangle current = rectangles [i];
+// if (current == null) error (SWT.ERROR_NULL_ARGUMENT);
+// this.rectangles [i] = new Rectangle (current.x, current.y, current.width, current.height);
+// }
+ java.awt.Rectangle[] recs = new java.awt.Rectangle[rectangles.length];
+ for(int i=0; itrue if rectangle should appear stippled
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setStippled (boolean stippled) {
+ checkWidget ();
+ this.stippled = stippled;
+ handle.setAppearance(stippled? JTracker.THICK_BORDER_APPEARANCE: JTracker.SINGLE_LINE_APPEARANCE);
+}
+
+//int transparentProc (int hwnd, int msg, int wParam, int lParam) {
+// switch (msg) {
+// /*
+// * We typically do not want to answer that the transparent window is
+// * transparent to hits since doing so negates the effect of having it
+// * to grab events. However, clients of the tracker should not be aware
+// * of this transparent window. Therefore if there is a hit query
+// * performed as a result of client code then answer that the transparent
+// * window is transparent to hits so that its existence will not impact
+// * the client.
+// */
+// case OS.WM_NCHITTEST:
+// if (inEvent) return OS.HTTRANSPARENT;
+// break;
+// case OS.WM_SETCURSOR:
+// if (clientCursor != 0) {
+// OS.SetCursor (clientCursor);
+// return 1;
+// }
+// if (resizeCursor != 0) {
+// OS.SetCursor (resizeCursor);
+// return 1;
+// }
+// }
+// return OS.CallWindowProc (oldProc, hwnd, msg, wParam, lParam);
+//}
+//
+//void update () {
+// if (parent != null) {
+// if (parent.isDisposed ()) return;
+// Shell shell = parent.getShell ();
+// shell.update (true);
+// } else {
+// display.update ();
+// }
+//}
+//
+//LRESULT wmKeyDown (int hwnd, int wParam, int lParam) {
+// LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
+// if (result != null) return result;
+// boolean isMirrored = parent != null && (parent.style & SWT.MIRRORED) != 0;
+// int stepSize = OS.GetKeyState (OS.VK_CONTROL) < 0 ? STEPSIZE_SMALL : STEPSIZE_LARGE;
+// int xChange = 0, yChange = 0;
+// switch (wParam) {
+// case OS.VK_ESCAPE:
+// cancelled = true;
+// tracking = false;
+// break;
+// case OS.VK_RETURN:
+// tracking = false;
+// break;
+// case OS.VK_LEFT:
+// xChange = isMirrored ? stepSize : -stepSize;
+// break;
+// case OS.VK_RIGHT:
+// xChange = isMirrored ? -stepSize : stepSize;
+// break;
+// case OS.VK_UP:
+// yChange = -stepSize;
+// break;
+// case OS.VK_DOWN:
+// yChange = stepSize;
+// break;
+// }
+// if (xChange != 0 || yChange != 0) {
+// Rectangle [] oldRectangles = rectangles;
+// boolean oldStippled = stippled;
+// Rectangle [] rectsToErase = new Rectangle [rectangles.length];
+// for (int i = 0; i < rectangles.length; i++) {
+// Rectangle current = rectangles [i];
+// rectsToErase [i] = new Rectangle (current.x, current.y, current.width, current.height);
+// }
+// Event event = new Event ();
+// event.x = oldX + xChange;
+// event.y = oldY + yChange;
+// Point cursorPos;
+// if ((style & SWT.RESIZE) != 0) {
+// resizeRectangles (xChange, yChange);
+// inEvent = true;
+// sendEvent (SWT.Resize, event);
+// inEvent = false;
+// /*
+// * It is possible (but unlikely) that application
+// * code could have disposed the widget in the resize
+// * event. If this happens return false to indicate
+// * that the tracking has failed.
+// */
+// if (isDisposed ()) {
+// cancelled = true;
+// return LRESULT.ONE;
+// }
+// boolean draw = false;
+// /*
+// * It is possible that application code could have
+// * changed the rectangles in the resize event. If this
+// * happens then only redraw the tracker if the rectangle
+// * values have changed.
+// */
+// if (rectangles != oldRectangles) {
+// int length = rectangles.length;
+// if (length != rectsToErase.length) {
+// draw = true;
+// } else {
+// for (int i = 0; i < length; i++) {
+// if (!rectangles [i].equals (rectsToErase [i])) {
+// draw = true;
+// break;
+// }
+// }
+// }
+// } else {
+// draw = true;
+// }
+// if (draw) {
+// drawRectangles (rectsToErase, oldStippled);
+// update ();
+// drawRectangles (rectangles, stippled);
+// }
+// cursorPos = adjustResizeCursor ();
+// } else {
+// moveRectangles (xChange, yChange);
+// inEvent = true;
+// sendEvent (SWT.Move, event);
+// inEvent = false;
+// /*
+// * It is possible (but unlikely) that application
+// * code could have disposed the widget in the move
+// * event. If this happens return false to indicate
+// * that the tracking has failed.
+// */
+// if (isDisposed ()) {
+// cancelled = true;
+// return LRESULT.ONE;
+// }
+// boolean draw = false;
+// /*
+// * It is possible that application code could have
+// * changed the rectangles in the move event. If this
+// * happens then only redraw the tracker if the rectangle
+// * values have changed.
+// */
+// if (rectangles != oldRectangles) {
+// int length = rectangles.length;
+// if (length != rectsToErase.length) {
+// draw = true;
+// } else {
+// for (int i = 0; i < length; i++) {
+// if (!rectangles [i].equals (rectsToErase [i])) {
+// draw = true;
+// break;
+// }
+// }
+// }
+// } else {
+// draw = true;
+// }
+// if (draw) {
+// drawRectangles (rectsToErase, oldStippled);
+// update ();
+// drawRectangles (rectangles, stippled);
+// }
+// cursorPos = adjustMoveCursor ();
+// }
+// oldX = cursorPos.x;
+// oldY = cursorPos.y;
+// }
+// return result;
+//}
+//
+//LRESULT wmSysKeyDown (int hwnd, int wParam, int lParam) {
+// LRESULT result = super.wmSysKeyDown (hwnd, wParam, lParam);
+// if (result != null) return result;
+// cancelled = true;
+// tracking = false;
+// return result;
+//}
+//
+//LRESULT wmMouse (int message, int wParam, int lParam) {
+// boolean isMirrored = parent != null && (parent.style & SWT.MIRRORED) != 0;
+// int newPos = OS.GetMessagePos ();
+// int newX = (short) (newPos & 0xFFFF);
+// int newY = (short) (newPos >> 16);
+// if (newX != oldX || newY != oldY) {
+// Rectangle [] oldRectangles = rectangles;
+// boolean oldStippled = stippled;
+// Rectangle [] rectsToErase = new Rectangle [rectangles.length];
+// for (int i = 0; i < rectangles.length; i++) {
+// Rectangle current = rectangles [i];
+// rectsToErase [i] = new Rectangle (current.x, current.y, current.width, current.height);
+// }
+// Event event = new Event ();
+// event.x = newX;
+// event.y = newY;
+// if ((style & SWT.RESIZE) != 0) {
+// if (isMirrored) {
+// resizeRectangles (oldX - newX, newY - oldY);
+// } else {
+// resizeRectangles (newX - oldX, newY - oldY);
+// }
+// inEvent = true;
+// sendEvent (SWT.Resize, event);
+// inEvent = false;
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the resize
+// * event. If this happens, return false to indicate
+// * that the tracking has failed.
+// */
+// if (isDisposed ()) {
+// cancelled = true;
+// return LRESULT.ONE;
+// }
+// boolean draw = false;
+// /*
+// * It is possible that application code could have
+// * changed the rectangles in the resize event. If this
+// * happens then only redraw the tracker if the rectangle
+// * values have changed.
+// */
+// if (rectangles != oldRectangles) {
+// int length = rectangles.length;
+// if (length != rectsToErase.length) {
+// draw = true;
+// } else {
+// for (int i = 0; i < length; i++) {
+// if (!rectangles [i].equals (rectsToErase [i])) {
+// draw = true;
+// break;
+// }
+// }
+// }
+// }
+// else {
+// draw = true;
+// }
+// if (draw) {
+// drawRectangles (rectsToErase, oldStippled);
+// update ();
+// drawRectangles (rectangles, stippled);
+// }
+// Point cursorPos = adjustResizeCursor ();
+// newX = cursorPos.x; newY = cursorPos.y;
+// } else {
+// if (isMirrored) {
+// moveRectangles (oldX - newX, newY - oldY);
+// } else {
+// moveRectangles (newX - oldX, newY - oldY);
+// }
+// inEvent = true;
+// sendEvent (SWT.Move, event);
+// inEvent = false;
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the move
+// * event. If this happens, return false to indicate
+// * that the tracking has failed.
+// */
+// if (isDisposed ()) {
+// cancelled = true;
+// return LRESULT.ONE;
+// }
+// boolean draw = false;
+// /*
+// * It is possible that application code could have
+// * changed the rectangles in the move event. If this
+// * happens then only redraw the tracker if the rectangle
+// * values have changed.
+// */
+// if (rectangles != oldRectangles) {
+// int length = rectangles.length;
+// if (length != rectsToErase.length) {
+// draw = true;
+// } else {
+// for (int i = 0; i < length; i++) {
+// if (!rectangles [i].equals (rectsToErase [i])) {
+// draw = true;
+// break;
+// }
+// }
+// }
+// } else {
+// draw = true;
+// }
+// if (draw) {
+// drawRectangles (rectsToErase, oldStippled);
+// update ();
+// drawRectangles (rectangles, stippled);
+// }
+// }
+// oldX = newX;
+// oldY = newY;
+// }
+// tracking = message != OS.WM_LBUTTONUP;
+// return null;
+//}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TrayItem.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TrayItem.java
new file mode 100644
index 00000000000..79775400985
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TrayItem.java
@@ -0,0 +1,471 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.image.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.internal.swing.*;
+
+/**
+ * Instances of this class represent icons that can be placed on the
+ * system tray or task bar status area.
+ *
+ *
+ *
Styles:
+ *
(none)
+ *
Events:
+ *
DefaultSelection, MenuDetect, Selection
+ *
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @since 3.0
+ */
+public class TrayItem extends Item {
+ Tray parent;
+ ToolTip toolTip;
+ boolean visible = true;
+ TrayIcon trayIcon;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Tray) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TrayItem (Tray parent, int style) {
+ super (parent, style);
+ this.parent = parent;
+ parent.createItem (this, parent.getItemCount ());
+ createWidget();
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver is selected, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * widgetSelected is called when the receiver is selected
+ * widgetDefaultSelected is called when the receiver is double-clicked
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public Tray getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns the receiver's tool tip, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public ToolTip getToolTip () {
+ checkWidget ();
+ return toolTip;
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public String getToolTipText () {
+ checkWidget ();
+ return trayIcon.getToolTip();
+}
+
+/**
+ * Returns true if the receiver is visible and
+ * false otherwise.
+ *
+ * @return the receiver's visibility
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getVisible () {
+ checkWidget ();
+ return visible;
+}
+
+//int messageProc (int hwnd, int msg, int wParam, int lParam) {
+// /*
+// * Feature in Windows. When the user clicks on the tray
+// * icon, another application may be the foreground window.
+// * This means that the event loop is not running and can
+// * cause problems. For example, if a menu is shown, when
+// * the user clicks outside of the menu to cancel it, the
+// * menu is not hidden until an event is processed. If
+// * another application is the foreground window, then the
+// * menu is not hidden. The fix is to force the tray icon
+// * message window to the foreground when sending an event.
+// */
+// switch (lParam) {
+// case OS.WM_LBUTTONDOWN:
+// if (hooks (SWT.Selection)) {
+// OS.SetForegroundWindow (hwnd);
+// postEvent (SWT.Selection);
+// }
+// break;
+// case OS.WM_LBUTTONDBLCLK:
+// case OS.WM_RBUTTONDBLCLK:
+// if (hooks (SWT.DefaultSelection)) {
+// OS.SetForegroundWindow (hwnd);
+// postEvent (SWT.DefaultSelection);
+// }
+// break;
+// case OS.WM_RBUTTONUP: {
+// if (hooks (SWT.MenuDetect)) {
+// OS.SetForegroundWindow (hwnd);
+// sendEvent (SWT.MenuDetect);
+// // widget could be disposed at this point
+// if (isDisposed()) return 0;
+// }
+// break;
+// }
+// case OS.NIN_BALLOONSHOW:
+// if (toolTip != null && !toolTip.visible) {
+// toolTip.visible = true;
+// if (toolTip.hooks (SWT.Show)) {
+// OS.SetForegroundWindow (hwnd);
+// toolTip.sendEvent (SWT.Show);
+// // widget could be disposed at this point
+// if (isDisposed()) return 0;
+// }
+// }
+// break;
+// case OS.NIN_BALLOONHIDE:
+// case OS.NIN_BALLOONTIMEOUT:
+// case OS.NIN_BALLOONUSERCLICK:
+// if (toolTip != null) {
+// if (toolTip.visible) {
+// toolTip.visible = false;
+// if (toolTip.hooks (SWT.Hide)) {
+// OS.SetForegroundWindow (hwnd);
+// toolTip.sendEvent (SWT.Hide);
+// // widget could be disposed at this point
+// if (isDisposed()) return 0;
+// }
+// }
+// if (lParam == OS.NIN_BALLOONUSERCLICK) {
+// if (toolTip.hooks (SWT.Selection)) {
+// OS.SetForegroundWindow (hwnd);
+// toolTip.postEvent (SWT.Selection);
+// // widget could be disposed at this point
+// if (isDisposed()) return 0;
+// }
+// }
+// }
+// break;
+// }
+// display.wakeThread ();
+// return 0;
+//}
+//
+//void recreate () {
+// createWidget ();
+// if (!visible) setVisible (false);
+// if (text.length () != 0) setText (text);
+// if (image != null) setImage (image);
+// if (toolTipText != null) setToolTipText (toolTipText);
+//}
+
+@Override
+void releaseHandle () {
+ super.releaseHandle ();
+ parent = null;
+}
+
+@Override
+void releaseWidget () {
+ super.releaseWidget ();
+ if (toolTip != null) toolTip.item = null;
+ toolTip = null;
+ if(visible) {
+ SystemTray.getSystemTray().remove(trayIcon);
+ }
+ // TODO: send hide event?
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver is selected.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_INVALID_ARGUMENT - if the image has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+@Override
+public void setImage (Image image) {
+ checkWidget ();
+ if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ super.setImage (image);
+ trayIcon.setImage(image.handle);
+}
+
+/**
+ * Sets the receiver's tool tip to the argument, which
+ * may be null indicating that no tool tip should be shown.
+ *
+ * @param toolTip the new tool tip (or null)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setToolTip (ToolTip toolTip) {
+ checkWidget ();
+ ToolTip oldTip = this.toolTip, newTip = toolTip;
+ if (oldTip != null) oldTip.item = null;
+ this.toolTip = newTip;
+ if (newTip != null) newTip.item = this;
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that no tool tip text should be shown.
+ *
+ * @param value the new tool tip text (or null)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setToolTipText (String value) {
+ checkWidget ();
+ trayIcon.setToolTip(value);
+}
+
+/**
+ * Makes the receiver visible if the argument is true,
+ * and makes it invisible otherwise.
+ *
+ * @param visible the new visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setVisible (boolean visible) {
+ checkWidget ();
+ if(this.visible == visible) return;
+ this.visible = visible;
+ if(visible) {
+ try {
+ SystemTray.getSystemTray().add(trayIcon);
+ sendEvent (SWT.Show);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ } else {
+ SystemTray.getSystemTray().remove(trayIcon);
+ sendEvent (SWT.Hide);
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tree.java
new file mode 100644
index 00000000000..c9b0c05aff2
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Tree.java
@@ -0,0 +1,3697 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.AWTEvent;
+import java.awt.Container;
+import java.awt.event.ItemEvent;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.EventObject;
+
+import javax.swing.event.TreeExpansionEvent;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.TreePath;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.TreeListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.swing.CTree;
+import org.eclipse.swt.internal.swing.CTreeItem;
+import org.eclipse.swt.internal.swing.DefaultMutableTreeTableNode;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+import org.eclipse.swt.internal.swing.Utils;
+import org.eclipse.swt.internal.swing.CTree.CellPaintEvent;
+
+/**
+ * Instances of this class provide a selectable user interface object
+ * that displays a hierarchy of items and issues notification when an
+ * item in the hierarchy is selected.
+ *
+ * The item children that may be added to instances of this class
+ * must be of type TreeItem.
+ *
+ * Style VIRTUAL is used to create a Tree whose
+ * TreeItems are to be populated by the client on an on-demand basis
+ * instead of up-front. This can provide significant performance improvements for
+ * trees that are very large or for which TreeItem population is
+ * expensive (for example, retrieving values from an external source).
+ *
+ * Here is an example of using a Tree with style VIRTUAL:
+ *
+ * final Tree tree = new Tree(parent, SWT.VIRTUAL | SWT.BORDER);
+ * tree.setItemCount(20);
+ * tree.addListener(SWT.SetData, new Listener() {
+ * public void handleEvent(Event event) {
+ * TreeItem item = (TreeItem)event.item;
+ * TreeItem parentItem = item.getParentItem();
+ * String text = null;
+ * if (parentItem == null) {
+ * text = "node " + tree.indexOf(item);
+ * } else {
+ * text = parentItem.getText() + " - " + parentItem.indexOf(item);
+ * }
+ * item.setText(text);
+ * System.out.println(text);
+ * item.setItemCount(10);
+ * }
+ * });
+ *
+ *
+ * Note that although this class is a subclass of Composite,
+ * it does not make sense to add Control children to it,
+ * or set a layout on it.
+ *
+ * Note: Only one of the styles SINGLE and MULTI may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+public class Tree extends Composite {
+ ArrayList itemList;
+ ArrayList columnList;
+ TreeItem currentItem;
+// TreeColumn [] columns;
+// int hwndParent, hwndHeader, hAnchor;
+// ImageList imageList;
+// boolean dragStarted, gestureCompleted;
+// boolean ignoreSelect, ignoreExpand, ignoreDeselect, ignoreResize;
+// boolean lockSelection, oldSelected, newSelected;
+// boolean linesVisible, customDraw, printClient;
+// static final int INSET = 3;
+ static final int GRID_WIDTH = 1;
+// static final int HEADER_MARGIN = 10;
+// static final char [] BUTTON = new char [] {'B', 'U', 'T', 'T', 'O', 'N', 0};
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#CHECK
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public Tree (Composite parent, int style) {
+ super (parent, checkStyle (style));
+}
+
+static int checkStyle (int style) {
+// /*
+// * Feature in Windows. It is not possible to create
+// * a tree that scrolls and does not have scroll bars.
+// * The TVS_NOSCROLL style will remove the scroll bars
+// * but the tree will never scroll. Therefore, no matter
+// * what style bits are specified, set the H_SCROLL and
+// * V_SCROLL bits so that the SWT style will match the
+// * widget that Windows creates.
+// */
+ style |= SWT.H_SCROLL | SWT.V_SCROLL;
+ return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+}
+
+void adjustColumnWidth() {
+ // Could be more efficient. Should post, with coalescing?
+ if(getColumnCount() == 0) {
+ CTree cTree = (CTree)handle;
+ cTree.getColumnModel().getColumn(0).setPreferredWidth(cTree.getPreferredColumnWidth(0));
+ }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's selection changes, by sending
+ * it one of the messages defined in the SelectionListener
+ * interface.
+ *
+ * When widgetSelected is called, the item field of the event object is valid.
+ * If the receiver has SWT.CHECK style set and the check selection changes,
+ * the event object detail field contains the value SWT.CHECK.
+ * widgetDefaultSelected is typically called when an item is double-clicked.
+ * The item field of the event object is valid for default selection, but the detail field is not used.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection, typedListener);
+ addListener (SWT.DefaultSelection, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an item in the receiver is expanded or collapsed
+ * by sending it one of the messages defined in the TreeListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see TreeListener
+ * @see #removeTreeListener
+ */
+public void addTreeListener(TreeListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Expand, typedListener);
+ addListener (SWT.Collapse, typedListener);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+boolean checkData (TreeItem item, boolean redraw) {
+ if ((style & SWT.VIRTUAL) == 0) return true;
+ TreeItem parentItem = item.getParentItem ();
+ return checkData (item, parentItem == null ? indexOf (item) : parentItem.indexOf (item), redraw);
+}
+
+boolean checkData (TreeItem item, int index, boolean redraw) {
+ if ((style & SWT.VIRTUAL) == 0) return true;
+ if (!item.cached) {
+ item.cached = true;
+ Event event = new Event ();
+ event.item = item;
+ event.index = index;
+ TreeItem oldItem = currentItem;
+ currentItem = item;
+ sendEvent (SWT.SetData, event);
+ //widget could be disposed at this point
+ currentItem = oldItem;
+ if (isDisposed () || item.isDisposed ()) return false;
+// if (redraw) item.redraw ();
+ }
+ return true;
+}
+
+/**
+ * Clears the item at the given zero-relative index in the receiver.
+ * The text, icon and other attributes of the item are set to the default
+ * value. If the tree was created with the SWT.VIRTUAL style,
+ * these attributes are requested again as needed.
+ *
+ * @param index the index of the item to clear
+ * @param all true if all child items of the indexed item should be
+ * cleared recursively, and false otherwise
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.2
+ */
+public void clear (int index, boolean all) {
+ checkWidget ();
+ getItem(index).clearAll(all);
+// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+// if (hItem == 0) error (SWT.ERROR_INVALID_RANGE);
+// hItem = findItem (hItem, index);
+// if (hItem == 0) error (SWT.ERROR_INVALID_RANGE);
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+// clear (hItem, tvItem);
+// if (all) {
+// hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+// clearAll (hItem, tvItem, all);
+// }
+}
+
+/**
+ * Clears all the items in the receiver. The text, icon and other
+ * attributes of the items are set to their default values. If the
+ * tree was created with the SWT.VIRTUAL style, these
+ * attributes are requested again as needed.
+ *
+ * @param all true if all child items should be cleared
+ * recursively, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.2
+ */
+public void clearAll (boolean all) {
+ checkWidget ();
+ for(int i=getItemCount()-1; i>=0; i--) {
+ getItem(i).clearAll(all);
+ }
+// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+// if (hItem == 0) return;
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+// clearAll (hItem, tvItem, all);
+}
+
+public Rectangle computeTrim(int x, int y, int width, int height) {
+ CTree cTree = (CTree)handle;
+ width += cTree.getVerticalScrollBar().getPreferredSize().width;
+ height += cTree.getHorizontalScrollBar().getPreferredSize().height;
+ return super.computeTrim(x, y, width, height);
+}
+
+void createHandleInit() {
+ super.createHandleInit();
+ state &= ~(CANVAS | THEME_BACKGROUND);
+}
+
+protected Container createHandle () {
+ return (Container)CTree.Factory.newInstance(this, style);
+}
+
+//void createHandle () {
+// super.createHandle ();
+// state &= ~CANVAS;
+//
+// /*
+// * Feature in Windows. In version 5.8 of COMCTL32.DLL,
+// * if the font is changed for an item, the bounds for the
+// * item are not updated, causing the text to be clipped.
+// * The fix is to detect the version of COMCTL32.DLL, and
+// * if it is one of the versions with the problem, then
+// * use version 5.00 of the control (a version that does
+// * not have the problem). This is the recomended work
+// * around from the MSDN.
+// */
+// if (!OS.IsWinCE) {
+// if (OS.COMCTL32_MAJOR < 6) {
+// OS.SendMessage (handle, OS.CCM_SETVERSION, 5, 0);
+// }
+// }
+//
+// /* Set the checkbox image list */
+// if ((style & SWT.CHECK) != 0) setCheckboxImageList ();
+//
+// /*
+// * Feature in Windows. When the control is created,
+// * it does not use the default system font. A new HFONT
+// * is created and destroyed when the control is destroyed.
+// * This means that a program that queries the font from
+// * this control, uses the font in another control and then
+// * destroys this control will have the font unexpectedly
+// * destroyed in the other control. The fix is to assign
+// * the font ourselves each time the control is created.
+// * The control will not destroy a font that it did not
+// * create.
+// */
+// int hFont = OS.GetStockObject (OS.SYSTEM_FONT);
+// OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+//}
+
+void createItem (TreeColumn column, int index) {
+// int columnCount = getColumnCount();
+ for (int i=0; i
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void deselectAll () {
+ checkWidget ();
+ ((CTree)handle).clearSelection();
+}
+
+void destroyItem (TreeColumn column) {
+ int index = columnList.indexOf(column);
+ for (int i=0; i
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public int getGridLineWidth () {
+ checkWidget ();
+ return GRID_WIDTH;
+}
+
+/**
+ * Returns the height of the receiver's header
+ *
+ * @return the height of the header or zero if the header is not visible
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public int getHeaderHeight () {
+ checkWidget ();
+ JTableHeader tableHeader = ((CTree)handle).getTableHeader();
+ return tableHeader.isVisible()? tableHeader.getHeight(): 0;
+}
+
+/**
+ * Returns true if the receiver's header is visible,
+ * and false otherwise.
+ *
+ * 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.
+ *
+ *
+ * @return the receiver's header's visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public boolean getHeaderVisible () {
+ checkWidget ();
+ return ((CTree)handle).getTableHeader().isVisible();
+}
+
+//Point getImageSize () {
+// if (imageList != null) return imageList.getImageSize ();
+// return new Point (0, getItemHeight ());
+//}
+
+/**
+ * Returns the column at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ * Columns are returned in the order that they were created.
+ * If no TreeColumns were created by the programmer,
+ * this method will throw ERROR_INVALID_RANGE despite
+ * the fact that a single column of data may be visible in the tree.
+ * This occurs when the programmer uses the tree like a list, adding
+ * items but never creating a column.
+ *
+ * @param index the index of the column to return
+ * @return the column at the given index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Tree#getColumnOrder()
+ * @see Tree#setColumnOrder(int[])
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public TreeColumn getColumn (int index) {
+ checkWidget ();
+ if (columnList == null) error (SWT.ERROR_INVALID_RANGE);
+ int count = getColumnCount();
+ if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+ return (TreeColumn)columnList.get(index);
+}
+
+/**
+ * Returns the number of columns contained in the receiver.
+ * If no TreeColumns were created by the programmer,
+ * this value is zero, despite the fact that visually, one column
+ * of items may be visible. This occurs when the programmer uses
+ * the tree like a list, adding items but never creating a column.
+ *
+ * @return the number of columns
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public int getColumnCount () {
+ checkWidget ();
+ if (columnList == null) return 0;
+ return columnList.size();
+}
+
+/**
+ * Returns an array of zero-relative integers that map
+ * the creation order of the receiver's items to the
+ * order in which they are currently being displayed.
+ *
+ * Specifically, the indices of the returned array represent
+ * the current visual order of the items, and the contents
+ * of the array represent the creation order of the items.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the current visual order of the receiver's items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Tree#setColumnOrder(int[])
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public int[] getColumnOrder () {
+ checkWidget ();
+ return ((CTree)handle).getColumnOrder();
+// if (hwndHeader == 0) return new int [0];
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// int [] order = new int [count];
+// OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order);
+// return order;
+}
+
+/**
+ * Returns an array of TreeColumns which are the
+ * columns in the receiver. Columns are returned in the order
+ * that they were created. If no TreeColumns were
+ * created by the programmer, the array is empty, despite the fact
+ * that visually, one column of items may be visible. This occurs
+ * when the programmer uses the tree like a list, adding items but
+ * never creating a column.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Tree#getColumnOrder()
+ * @see Tree#setColumnOrder(int[])
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public TreeColumn [] getColumns () {
+ checkWidget ();
+ if (columnList == null) return new TreeColumn [0];
+ return (TreeColumn[])columnList.toArray(new TreeColumn[0]);
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public TreeItem getItem (int index) {
+ checkWidget ();
+ if (index < 0) error (SWT.ERROR_INVALID_RANGE);
+ if (index >= itemList.size()) error (SWT.ERROR_INVALID_RANGE);
+ return (TreeItem)itemList.get(index);
+}
+
+/**
+ * Returns the item at the given point in the receiver
+ * or null if no such item exists. The point is in the
+ * coordinate system of the receiver.
+ *
+ * The item that is returned represents an item that could be selected by the user.
+ * For example, if selection only occurs in items in the first column, then null is
+ * returned if the point is outside of the item.
+ * Note that the SWT.FULL_SELECTION style hint, which specifies the selection policy,
+ * determines the extent of the selection.
+ *
+ *
+ * @param point the point used to locate the item
+ * @return the item at the given point, or null if the point is not in a selectable item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the point is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TreeItem getItem (Point point) {
+ checkWidget ();
+ if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TreePath treePath = ((CTree)handle).getPathForLocation(point.x, point.y);
+ if(treePath == null) {
+ return null;
+ }
+ CTreeItem.TreeItemObject treeItemObject = ((CTreeItem.TreeItemObject)((DefaultMutableTreeNode)treePath.getLastPathComponent()).getUserObject());
+ return treeItemObject.getTreeItem().getTreeItem();
+}
+
+/**
+ * Returns the number of items contained in the receiver
+ * that are direct item children of the receiver. The
+ * number that is returned is the number of roots in the
+ * tree.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemCount () {
+ checkWidget ();
+ return itemList == null? 0: itemList.size();
+}
+
+//int getItemCount (int hItem) {
+// int count = 0;
+// while (hItem != 0) {
+// hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+// count++;
+// }
+// return count;
+//}
+
+/**
+ * Returns the height of the area which would be used to
+ * display one of the items in the tree.
+ *
+ * @return the height of one item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemHeight () {
+ checkWidget ();
+ return ((CTree)handle).getRowHeight();
+}
+
+/**
+ * Returns a (possibly empty) array of items contained in the
+ * receiver that are direct item children of the receiver. These
+ * are the roots of the tree.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TreeItem [] getItems () {
+ checkWidget ();
+ return (TreeItem[])itemList.toArray(new TreeItem[0]);
+}
+
+//TreeItem [] getItems (int hTreeItem) {
+// int count = 0, hItem = hTreeItem;
+// while (hItem != 0) {
+// hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+// count++;
+// }
+// int index = 0;
+// TreeItem [] result = new TreeItem [count];
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+// tvItem.hItem = hTreeItem;
+// /*
+// * Feature in Windows. In some cases an expand or collapse message
+// * can occurs from within TVM_DELETEITEM. When this happens, the item
+// * being destroyed has been removed from the list of items but has not
+// * been deleted from the tree. The fix is to check for null items and
+// * remove them from the list.
+// */
+// while (tvItem.hItem != 0) {
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// TreeItem item = items [tvItem.lParam];
+// if (item != null) result [index++] = item;
+// tvItem.hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, tvItem.hItem);
+// }
+// if (index != count) {
+// TreeItem [] newResult = new TreeItem [index];
+// System.arraycopy (result, 0, newResult, 0, index);
+// result = newResult;
+// }
+// return result;
+//}
+
+/**
+ * Returns true if the receiver's lines are visible,
+ * and false otherwise.
+ *
+ * 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.
+ *
+ *
+ * @return the visibility state of the lines
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public boolean getLinesVisible () {
+ checkWidget ();
+ return ((CTree)handle).isGridVisible();
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * TreeItem or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TreeItem getParentItem () {
+ checkWidget ();
+ return null;
+}
+
+/**
+ * Returns an array of TreeItems that are currently
+ * selected in the receiver. The order of the items is unspecified.
+ * An empty array indicates that no items are selected.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ *
+ * @return an array representing the selection
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getSelectionCount () {
+ checkWidget ();
+ return ((CTree)handle).getSelectionModel().getSelectionCount();
+}
+
+TreeColumn sortColumn;
+int sortDirection;
+
+/**
+ * Returns the column which shows the sort indicator for
+ * the receiver. The value may be null if no column shows
+ * the sort indicator.
+ *
+ * @return the sort indicator
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setSortColumn(TreeColumn)
+ *
+ * @since 3.2
+ */
+public TreeColumn getSortColumn () {
+ checkWidget ();
+ return sortColumn;
+}
+
+/**
+ * Returns the direction of the sort indicator for the receiver.
+ * The value will be one of UP, DOWN
+ * or NONE.
+ *
+ * @return the sort direction
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setSortDirection(int)
+ *
+ * @since 3.2
+ */
+public int getSortDirection () {
+ checkWidget ();
+ return sortDirection;
+}
+
+/**
+ * Returns the item which is currently at the top of the receiver.
+ * This item can change when items are expanded, collapsed, scrolled
+ * or new items are added or removed.
+ *
+ * @return the item at the top of the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.1
+ */
+public TreeItem getTopItem () {
+ checkWidget ();
+ int index = ((CTree)handle).getTopIndex();
+ if(index < 0) return null;
+ return ((CTreeItem)((CTree)handle).getPathForRow(index).getLastPathComponent()).getTreeItem();
+}
+
+//int imageIndex (Image image) {
+// if (image == null) return OS.I_IMAGENONE;
+// if (imageList == null) {
+// int hOldList = OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0);
+// if (hOldList != 0) OS.ImageList_Destroy (hOldList);
+// Rectangle bounds = image.getBounds ();
+// imageList = display.getImageList (new Point (bounds.width, bounds.height));
+// int index = imageList.indexOf (image);
+// if (index == -1) index = imageList.add (image);
+// int hImageList = imageList.getHandle ();
+// OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_NORMAL, hImageList);
+// if (hwndHeader != 0) {
+// OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hImageList);
+// }
+// updateScrollBar ();
+// return index;
+// }
+// int index = imageList.indexOf (image);
+// if (index != -1) return index;
+// return imageList.add (image);
+//}
+
+//int indexOf (int hItem, int hChild) {
+// int index = 0;
+// while (hItem != 0 && hItem != hChild) {
+// hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+// index++;
+// }
+// return hItem == hChild ? index : -1;
+//}
+
+/**
+ * Searches the receiver's list starting at the first column
+ * (index 0) until a column is found that is equal to the
+ * argument, and returns the index of that column. If no column
+ * is found, returns -1.
+ *
+ * @param column the search column
+ * @return the index of the column
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the string is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public int indexOf (TreeColumn column) {
+ checkWidget ();
+ if (column == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (column.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ return columnList.indexOf(column);
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the tool item is null
+ *
ERROR_INVALID_ARGUMENT - if the tool item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void removeAll () {
+ checkWidget ();
+ for (int i=itemList.size()-1; i>=0; i--) {
+ TreeItem item = (TreeItem)itemList.get(i);
+ if (item != null && !item.isDisposed ()) {
+ item.dispose();
+// item.release (false);
+ } else {
+ itemList.remove(i);
+ }
+ }
+// ((CTree)handle).getRoot().removeAllChildren();
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's selection changes.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when items in the receiver are expanded or collapsed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see TreeListener
+ * @see #addTreeListener
+ */
+public void removeTreeListener(TreeListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Expand, listener);
+ eventTable.unhook (SWT.Collapse, listener);
+}
+
+/**
+ * Display a mark indicating the point at which an item will be inserted.
+ * The drop insert item has a visual hint to show where a dragged item
+ * will be inserted when dropped on the tree.
+ *
+ * @param item the insert item. Null will clear the insertion mark.
+ * @param before true places the insert mark above 'item'. false places
+ * the insert mark below 'item'.
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setInsertMark (TreeItem item, boolean before) {
+ checkWidget ();
+ Utils.notImplemented();
+// int hItem = 0;
+// if (item != null) {
+// if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+// hItem = item.handle;
+// }
+// OS.SendMessage (handle, OS.TVM_SETINSERTMARK, (before) ? 0 : 1, hItem);
+}
+
+/**
+ * Sets the number of root-level items contained in the receiver.
+ *
+ * @param count the number of items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+/*public*/ void setItemHeight (int itemHeight) {
+ checkWidget ();
+ if (itemHeight < -1) error (SWT.ERROR_INVALID_ARGUMENT);
+ ((CTree)handle).setRowHeight(itemHeight);
+}
+
+/**
+ * Marks the receiver's lines as visible if the argument is true,
+ * and marks it invisible otherwise.
+ *
+ * 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.
+ *
+ *
+ * @param show the new visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void setLinesVisible (boolean show) {
+ checkWidget ();
+ ((CTree)handle).setGridVisible(show);
+}
+
+//int scrolledHandle () {
+// if (hwndHeader == 0) return handle;
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// return count == 0 ? handle : hwndParent;
+//}
+
+/**
+ * Selects all of the items in the receiver.
+ *
+ * If the receiver is single-select, do nothing.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void selectAll () {
+ checkWidget ();
+ if ((style & SWT.SINGLE) != 0) return;
+ ((CTree)handle).selectAll();
+}
+
+//void setBounds (int x, int y, int width, int height, int flags) {
+// /*
+// * Ensure that the selection is visible when the tree is resized
+// * from a zero size to a size that can show the selection.
+// */
+// boolean fixSelection = false;
+// if ((flags & OS.SWP_NOSIZE) == 0 && (width != 0 || height != 0)) {
+// if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) == 0) {
+// fixSelection = true;
+// }
+// }
+// super.setBounds (x, y, width, height, flags);
+// if (fixSelection) {
+// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+// if (hItem != 0) showItem (hItem);
+// }
+//}
+
+//void setCursor () {
+// /*
+// * Bug in Windows. Under certain circumstances, when WM_SETCURSOR
+// * is sent from SendMessage(), Windows GP's in the window proc for
+// * the tree. The fix is to avoid calling the tree window proc and
+// * set the cursor for the tree outside of WM_SETCURSOR.
+// *
+// * NOTE: This code assumes that the default cursor for the tree
+// * is IDC_ARROW.
+// */
+// Cursor cursor = findCursor ();
+// int hCursor = cursor == null ? OS.LoadCursor (0, OS.IDC_ARROW) : cursor.handle;
+// OS.SetCursor (hCursor);
+//}
+
+//void setCheckboxImageList () {
+// if ((style & SWT.CHECK) == 0) return;
+// int count = 5;
+// int height = OS.SendMessage (handle, OS.TVM_GETITEMHEIGHT, 0, 0), width = height;
+// int flags = ImageList.COLOR_FLAGS;
+// if ((style & SWT.RIGHT_TO_LEFT) != 0) flags |= OS.ILC_MIRROR;
+// int hImageList = OS.ImageList_Create (width, height, flags, count, count);
+// int hDC = OS.GetDC (handle);
+// int memDC = OS.CreateCompatibleDC (hDC);
+// int hBitmap = OS.CreateCompatibleBitmap (hDC, width * count, height);
+// int hOldBitmap = OS.SelectObject (memDC, hBitmap);
+// RECT rect = new RECT ();
+// OS.SetRect (rect, 0, 0, width * count, height);
+// int hBrush = OS.CreateSolidBrush (_getBackgroundPixel ());
+// OS.FillRect (memDC, rect, hBrush);
+// OS.DeleteObject (hBrush);
+// int oldFont = OS.SelectObject (hDC, defaultFont ());
+// TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA ();
+// OS.GetTextMetrics (hDC, tm);
+// OS.SelectObject (hDC, oldFont);
+// int itemWidth = Math.min (tm.tmHeight, width);
+// int itemHeight = Math.min (tm.tmHeight, height);
+// int left = (width - itemWidth) / 2, top = (height - itemHeight) / 2 + 1;
+// OS.SetRect (rect, left + width, top, left + width + itemWidth, top + itemHeight);
+// if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+// int hTheme = OS.OpenThemeData (handle, BUTTON);
+// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, rect, null);
+// rect.left += width; rect.right += width;
+// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_CHECKEDNORMAL, rect, null);
+// rect.left += width; rect.right += width;
+// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, rect, null);
+// rect.left += width; rect.right += width;
+// OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_MIXEDNORMAL, rect, null);
+// OS.CloseThemeData (hTheme);
+// } else {
+// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_FLAT);
+// rect.left += width; rect.right += width;
+// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_CHECKED | OS.DFCS_FLAT);
+// rect.left += width; rect.right += width;
+// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_INACTIVE | OS.DFCS_FLAT);
+// rect.left += width; rect.right += width;
+// OS.DrawFrameControl (memDC, rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_CHECKED | OS.DFCS_INACTIVE | OS.DFCS_FLAT);
+// }
+// OS.SelectObject (memDC, hOldBitmap);
+// OS.DeleteDC (memDC);
+// OS.ReleaseDC (handle, hDC);
+// OS.ImageList_Add (hImageList, hBitmap, 0);
+// OS.DeleteObject (hBitmap);
+// int hOldList = OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_STATE, 0);
+// OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_STATE, hImageList);
+// if (hOldList != 0) OS.ImageList_Destroy (hOldList);
+//}
+
+/**
+ * Sets the order that the items in the receiver should
+ * be displayed in to the given argument which is described
+ * in terms of the zero-relative ordering of when the items
+ * were added.
+ *
+ * @param order the new order to display the items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the item order is null
+ *
ERROR_INVALID_ARGUMENT - if the item order is not the same length as the number of items
+ *
+ *
+ * @see Tree#getColumnOrder()
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(boolean)
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public void setColumnOrder (int [] order) {
+ checkWidget ();
+ if (order == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int columnCount = getColumnCount();
+ if (order.length != columnCount) error (SWT.ERROR_INVALID_ARGUMENT);
+ ((CTree)handle).setColumnOrder(order);
+// int count = 0;
+// if (hwndHeader != 0) {
+// count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// }
+// if (count == 0) {
+// if (order.length != 0) error (SWT.ERROR_INVALID_ARGUMENT);
+// return;
+// }
+// if (order.length != count) error (SWT.ERROR_INVALID_ARGUMENT);
+// int [] oldOrder = new int [count];
+// OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, oldOrder);
+// boolean reorder = false;
+// boolean [] seen = new boolean [count];
+// for (int i=0; i= count) error (SWT.ERROR_INVALID_RANGE);
+// if (seen [index]) error (SWT.ERROR_INVALID_ARGUMENT);
+// seen [index] = true;
+// if (index != oldOrder [i]) reorder = true;
+// }
+// if (reorder) {
+// RECT [] oldRects = new RECT [count];
+// for (int i=0; itrue,
+ * and marks it invisible otherwise.
+ *
+ * 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.
+ *
+ *
+ * @param show the new visibility state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void setHeaderVisible (boolean show) {
+ checkWidget ();
+ ((CTree)handle).setHeaderVisible(show);
+}
+
+//void setScrollWidth () {
+// if (hwndHeader == 0 || hwndParent == 0) return;
+// int width = 0;
+// HDITEM hdItem = new HDITEM ();
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// for (int i=0; i
+ * If the item is not in the receiver, then it is ignored.
+ *
+ *
+ * @param item the item to select
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the item is null
+ *
ERROR_INVALID_ARGUMENT - if the item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setSelection (TreeItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ setSelection (new TreeItem [] {item});
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected.
+ *
+ * Items that are not in the receiver are ignored.
+ * If the receiver is single-select and multiple items are specified,
+ * then all items are ignored.
+ *
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the array of items is null
+ *
ERROR_INVALID_ARGUMENT - if one of the items has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Tree#deselectAll()
+ */
+public void setSelection (TreeItem [] items) {
+ checkWidget ();
+ if (items == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int length = items.length;
+ if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) {
+ deselectAll();
+ return;
+ }
+ TreePath[] paths = new TreePath[items.length];
+ for (int i = 0; i < items.length; i++) {
+ paths[i] = new TreePath(items[i].handle.getPath());
+ }
+ ((CTree)handle).getSelectionModel().setSelectionPaths(paths);
+}
+
+/**
+ * Sets the column used by the sort indicator for the receiver. A null
+ * value will clear the sort indicator. The current sort column is cleared
+ * before the new column is set.
+ *
+ * @param column the column used by the sort indicator or null
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the column is disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setSortColumn (TreeColumn column) {
+ checkWidget ();
+ if (column != null && column.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ sortColumn = column;
+ handle.repaint();
+}
+
+/**
+ * Sets the direction of the sort indicator for the receiver. The value
+ * can be one of UP, DOWN or NONE.
+ *
+ * @param direction the direction of the sort indicator
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setSortDirection (int direction) {
+ checkWidget ();
+ if ((direction & (SWT.UP | SWT.DOWN)) == 0 && direction != SWT.NONE) return;
+ sortDirection = direction;
+ handle.repaint();
+}
+
+/**
+ * Sets the item which is currently at the top of the receiver.
+ * This item can change when items are expanded, collapsed, scrolled
+ * or new items are added or removed.
+ *
+ * @param item the item to be shown
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the item is null
+ *
ERROR_INVALID_ARGUMENT - if the item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Tree#getTopItem()
+ *
+ * @since 2.1
+ */
+public void setTopItem (TreeItem item) {
+ checkWidget ();
+ if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ int row = ((CTree)handle).getRowForPath(new TreePath(item.handle.getPath()));
+ if(row < 0) {
+ return;
+ }
+ ((CTree)handle).setTopIndex(row);
+}
+
+//void showItem (int hItem) {
+// /*
+// * Bug in Windows. When TVM_ENSUREVISIBLE is used to ensure
+// * that an item is visible and the client area of the tree is
+// * smaller that the size of one item, TVM_ENSUREVISIBLE makes
+// * the next item in the tree visible by making it the top item
+// * instead of making the desired item visible. The fix is to
+// * detect the case when the client area is too small and make
+// * the desired visible item be the top item in the tree.
+// */
+// if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) == 0) {
+// boolean fixScroll = checkScroll (hItem);
+// if (fixScroll) {
+// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+// }
+// OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hItem);
+// OS.SendMessage (handle, OS.WM_HSCROLL, OS.SB_TOP, 0);
+// if (fixScroll) {
+// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+// }
+// } else {
+// boolean scroll = true;
+// RECT itemRect = new RECT ();
+// itemRect.left = hItem;
+// if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, itemRect) != 0) {
+// forceResize ();
+// RECT rect = new RECT ();
+// OS.GetClientRect (handle, rect);
+// POINT pt = new POINT ();
+// pt.x = itemRect.left;
+// pt.y = itemRect.top;
+// if (OS.PtInRect (rect, pt)) {
+// pt.y = itemRect.bottom;
+// if (OS.PtInRect (rect, pt)) scroll = false;
+// }
+// }
+// if (scroll) {
+// boolean fixScroll = checkScroll (hItem);
+// if (fixScroll) {
+// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+// }
+// OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, hItem);
+// if (fixScroll) {
+// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+// }
+// }
+// }
+// if (hwndParent != 0) {
+// RECT itemRect = new RECT ();
+// itemRect.left = hItem;
+// if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, itemRect) != 0) {
+// forceResize ();
+// RECT rect = new RECT ();
+// OS.GetClientRect (hwndParent, rect);
+// OS.MapWindowPoints (hwndParent, handle, rect, 2);
+// POINT pt = new POINT ();
+// pt.x = itemRect.left;
+// pt.y = itemRect.top;
+// if (!OS.PtInRect (rect, pt)) {
+// pt.y = itemRect.bottom;
+// if (!OS.PtInRect (rect, pt)) {
+// SCROLLINFO info = new SCROLLINFO ();
+// info.cbSize = SCROLLINFO.sizeof;
+// info.fMask = OS.SIF_POS;
+// info.nPos = Math.max (0, pt.x - Tree.INSET / 2);
+// OS.SetScrollInfo (hwndParent, OS.SB_HORZ, info, true);
+// setScrollWidth ();
+// }
+// }
+// }
+// }
+// updateScrollBar ();
+//}
+
+/**
+ * Shows the column. If the column is already showing in the receiver,
+ * this method simply returns. Otherwise, the columns are scrolled until
+ * the column is visible.
+ *
+ * @param column the column to be shown
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the item is null
+ *
ERROR_INVALID_ARGUMENT - if the item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void showColumn (TreeColumn column) {
+ checkWidget ();
+ if (column == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (column.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+ if (column.parent != this) return;
+ int index = indexOf (column);
+ if (index == -1) return;
+ ((CTree)handle).ensureColumnVisible(index);
+}
+
+/**
+ * Shows the item. If the item is already showing in the receiver,
+ * this method simply returns. Otherwise, the items are scrolled
+ * and expanded until the item is visible.
+ *
+ * @param item the item to be shown
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the item is null
+ *
ERROR_INVALID_ARGUMENT - if the item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Tree#showSelection()
+ */
+public void showItem (TreeItem item) {
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+ int row = ((CTree)handle).getRowForPath(new TreePath(item.handle.getPath()));
+ if(row < 0) {
+ return;
+ }
+ ((CTree)handle).ensureRowVisible(row);
+}
+
+/**
+ * Shows the selection. If the selection is already showing in the receiver,
+ * this method simply returns. Otherwise, the items are scrolled until
+ * the selection is visible.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Tree#showItem(TreeItem)
+ */
+public void showSelection () {
+ checkWidget ();
+ int selectionRow = ((CTree)handle).getSelectionModel().getLeadSelectionRow();
+ if(selectionRow == -1) {
+ return;
+ }
+ ((CTree)handle).ensureRowVisible(selectionRow);
+}
+
+//void showWidget (boolean visible) {
+// super.showWidget (visible);
+// if (hwndParent != 0) {
+// OS.ShowWindow (hwndParent, visible ? OS.SW_SHOW : OS.SW_HIDE);
+// }
+//}
+//
+//void updateScrollBar () {
+// if (hwndParent != 0) {
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// if (count != 0) {
+// SCROLLINFO info = new SCROLLINFO ();
+// info.cbSize = SCROLLINFO.sizeof;
+// info.fMask = OS.SIF_ALL;
+// OS.GetScrollInfo (handle, OS.SB_VERT, info);
+// OS.SetScrollInfo (hwndParent, OS.SB_VERT, info, true);
+// }
+// }
+//}
+//
+//TCHAR windowClass () {
+// return TreeClass;
+//}
+//
+//int windowProc () {
+// return TreeProc;
+//}
+//
+//int windowProc (int hwnd, int msg, int wParam, int lParam) {
+// if (hwndParent != 0 && hwnd == hwndParent) {
+// switch (msg) {
+// case OS.WM_MOVE: {
+// sendEvent (SWT.Move);
+// return 0;
+// }
+// case OS.WM_SIZE: {
+// setScrollWidth ();
+// if (ignoreResize) return 0;
+// setResizeChildren (false);
+// int code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam);
+// sendEvent (SWT.Resize);
+// if (isDisposed ()) return 0;
+// if (layout != null) {
+// markLayout (false, false);
+// updateLayout (false, false);
+// }
+// setResizeChildren (true);
+// return code;
+// }
+// case OS.WM_COMMAND:
+// case OS.WM_NOTIFY:
+// case OS.WM_SYSCOLORCHANGE: {
+// return OS.SendMessage (handle, msg, wParam, lParam);
+// }
+// case OS.WM_VSCROLL: {
+// SCROLLINFO info = new SCROLLINFO ();
+// info.cbSize = SCROLLINFO.sizeof;
+// info.fMask = OS.SIF_ALL;
+// OS.GetScrollInfo (hwndParent, OS.SB_VERT, info);
+// OS.SetScrollInfo (handle, OS.SB_VERT, info, true);
+// int code = OS.SendMessage (handle, OS.WM_VSCROLL, wParam, lParam);
+// OS.GetScrollInfo (handle, OS.SB_VERT, info);
+// OS.SetScrollInfo (hwndParent, OS.SB_VERT, info, true);
+// return code;
+// }
+// case OS.WM_HSCROLL: {
+// /*
+// * Bug on WinCE. lParam should be NULL when the message is not sent
+// * by a scroll bar control, but it contains the handle to the window.
+// * When the message is sent by a scroll bar control, it correctly
+// * contains the handle to the scroll bar. The fix is to check for
+// * both.
+// */
+// if (horizontalBar != null && (lParam == 0 || lParam == hwndParent)) {
+// wmScroll (horizontalBar, true, hwndParent, OS.WM_HSCROLL, wParam, lParam);
+// }
+// setScrollWidth ();
+// break;
+// }
+// }
+// return callWindowProc (hwnd, msg, wParam, lParam);
+// }
+// int code = super.windowProc (handle, msg, wParam, lParam);
+// switch (msg) {
+// /* Keyboard messages */
+// case OS.WM_CHAR:
+// case OS.WM_IME_CHAR:
+// case OS.WM_KEYDOWN:
+// case OS.WM_KEYUP:
+// case OS.WM_SYSCHAR:
+// case OS.WM_SYSKEYDOWN:
+// case OS.WM_SYSKEYUP:
+//
+// /* Mouse messages */
+// case OS.WM_LBUTTONDBLCLK:
+// case OS.WM_LBUTTONDOWN:
+// case OS.WM_LBUTTONUP:
+// case OS.WM_MBUTTONDBLCLK:
+// case OS.WM_MBUTTONDOWN:
+// case OS.WM_MBUTTONUP:
+// case OS.WM_MOUSEHOVER:
+// case OS.WM_MOUSELEAVE:
+// case OS.WM_MOUSEMOVE:
+// case OS.WM_MOUSEWHEEL:
+// case OS.WM_RBUTTONDBLCLK:
+// case OS.WM_RBUTTONDOWN:
+// case OS.WM_RBUTTONUP:
+// case OS.WM_XBUTTONDBLCLK:
+// case OS.WM_XBUTTONDOWN:
+// case OS.WM_XBUTTONUP:
+//
+// /* Other messages */
+// case OS.WM_SIZE:
+// case OS.WM_SETFONT:
+// case OS.WM_TIMER: {
+// updateScrollBar ();
+// }
+// }
+// return code;
+//}
+//
+//LRESULT WM_CHAR (int wParam, int lParam) {
+// LRESULT result = super.WM_CHAR (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Feature in Windows. The tree control beeps
+// * in WM_CHAR when the search for the item that
+// * matches the key stroke fails. This is the
+// * standard tree behavior but is unexpected when
+// * the key that was typed was ESC, CR or SPACE.
+// * The fix is to avoid calling the tree window
+// * proc in these cases.
+// */
+// switch (wParam) {
+// case SWT.CR:
+// /*
+// * Feature in Windows. Windows sends NM_RETURN from WM_KEYDOWN
+// * instead of using WM_CHAR. This means that application code
+// * that expects to consume the key press and therefore avoid a
+// * SWT.DefaultSelection event from WM_CHAR will fail. The fix
+// * is to implement SWT.DefaultSelection in WM_CHAR instead of
+// * using NM_RETURN.
+// */
+// Event event = new Event ();
+// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+// if (hItem != 0) {
+// TVITEM tvItem = new TVITEM ();
+// tvItem.hItem = hItem;
+// tvItem.mask = OS.TVIF_PARAM;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// event.item = items [tvItem.lParam];
+// }
+// postEvent (SWT.DefaultSelection, event);
+// //FALL THROUGH
+// case SWT.ESC:
+// case ' ':
+// return LRESULT.ZERO;
+// }
+// return result;
+//}
+//
+//LRESULT WM_GETOBJECT (int wParam, int lParam) {
+// /*
+// * Ensure that there is an accessible object created for this
+// * control because support for checked item and tree column
+// * accessibility is temporarily implemented in the accessibility
+// * package.
+// */
+// if ((style & SWT.CHECK) != 0 || hwndParent != 0) {
+// if (accessible == null) accessible = new_Accessible (this);
+// }
+// return super.WM_GETOBJECT (wParam, lParam);
+//}
+//
+//LRESULT WM_KEYDOWN (int wParam, int lParam) {
+// LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+// if (result != null) return result;
+// switch (wParam) {
+// case OS.VK_SPACE: {
+// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+// if (hItem != 0) {
+// hAnchor = hItem;
+// OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, hItem);
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_STATE | OS.TVIF_PARAM;
+// tvItem.hItem = hItem;
+// if ((style & SWT.CHECK) != 0) {
+// tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// int state = tvItem.state >> 12;
+// if ((state & 0x1) != 0) {
+// state++;
+// } else {
+// --state;
+// }
+// tvItem.state = state << 12;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// if (!OS.IsWinCE) {
+// int id = hItem;
+// if (OS.COMCTL32_MAJOR >= 6) {
+// id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, hItem, 0);
+// }
+// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, id);
+// }
+// }
+// tvItem.stateMask = OS.TVIS_SELECTED;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// if ((style & SWT.MULTI) != 0 && OS.GetKeyState (OS.VK_CONTROL) < 0) {
+// if ((tvItem.state & OS.TVIS_SELECTED) != 0) {
+// tvItem.state &= ~OS.TVIS_SELECTED;
+// } else {
+// tvItem.state |= OS.TVIS_SELECTED;
+// }
+// } else {
+// tvItem.state |= OS.TVIS_SELECTED;
+// }
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// Event event = new Event ();
+// event.item = items [tvItem.lParam];
+// postEvent (SWT.Selection, event);
+// if ((style & SWT.CHECK) != 0) {
+// event = new Event ();
+// event.item = items [tvItem.lParam];
+// event.detail = SWT.CHECK;
+// postEvent (SWT.Selection, event);
+// }
+// return LRESULT.ZERO;
+// }
+// break;
+// }
+// case OS.VK_UP:
+// case OS.VK_DOWN:
+// case OS.VK_PRIOR:
+// case OS.VK_NEXT:
+// case OS.VK_HOME:
+// case OS.VK_END: {
+// if ((style & SWT.SINGLE) != 0) break;
+// OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+// if (OS.GetKeyState (OS.VK_SHIFT) < 0) {
+// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+// if (hItem != 0) {
+// if (hAnchor == 0) hAnchor = hItem;
+// ignoreSelect = ignoreDeselect = true;
+// int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+// ignoreSelect = ignoreDeselect = false;
+// int hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_STATE;
+// tvItem.stateMask = OS.TVIS_SELECTED;
+// int hDeselectItem = hItem;
+// RECT rect1 = new RECT ();
+// rect1.left = hAnchor;
+// OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect1);
+// RECT rect2 = rect2 = new RECT ();
+// rect2.left = hDeselectItem;
+// OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect2);
+// int flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
+// while (hDeselectItem != hAnchor) {
+// tvItem.hItem = hDeselectItem;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// hDeselectItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hDeselectItem);
+// }
+// int hSelectItem = hAnchor;
+// rect1.left = hNewItem;
+// OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect1);
+// rect2.left = hSelectItem;
+// OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect2);
+// tvItem.state = OS.TVIS_SELECTED;
+// flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
+// while (hSelectItem != hNewItem) {
+// tvItem.hItem = hSelectItem;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// hSelectItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hSelectItem);
+// }
+// tvItem.hItem = hNewItem;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// tvItem.mask = OS.TVIF_PARAM;
+// tvItem.hItem = hNewItem;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// Event event = new Event ();
+// event.item = items [tvItem.lParam];
+// postEvent (SWT.Selection, event);
+// return new LRESULT (code);
+// }
+// }
+// if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
+// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+// if (hItem != 0) {
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_STATE;
+// tvItem.stateMask = OS.TVIS_SELECTED;
+// tvItem.hItem = hItem;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// boolean oldSelected = (tvItem.state & OS.TVIS_SELECTED) != 0;
+// int hNewItem = 0;
+// switch (wParam) {
+// case OS.VK_UP:
+// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUSVISIBLE, hItem);
+// break;
+// case OS.VK_DOWN:
+// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+// break;
+// case OS.VK_HOME:
+// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+// break;
+// case OS.VK_PRIOR:
+// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+// if (hNewItem == hItem) {
+// OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEUP, 0);
+// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+// }
+// break;
+// case OS.VK_NEXT:
+// RECT rect = new RECT (), clientRect = new RECT ();
+// OS.GetClientRect (handle, clientRect);
+// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+// do {
+// int hVisible = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNewItem);
+// if (hVisible == 0) break;
+// rect.left = hVisible;
+// OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect);
+// if (rect.bottom > clientRect.bottom) break;
+// if ((hNewItem = hVisible) == hItem) {
+// OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEDOWN, 0);
+// }
+// } while (hNewItem != 0);
+// break;
+// case OS.VK_END:
+// hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0);
+// break;
+// }
+// if (hNewItem != 0) {
+// OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, hNewItem);
+// tvItem.hItem = hNewItem;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// boolean newSelected = (tvItem.state & OS.TVIS_SELECTED) != 0;
+// if (!newSelected && drawCount == 0) {
+// OS.UpdateWindow (handle);
+// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+// /*
+// * This code is intentionally commented.
+// */
+//// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+// }
+// ignoreSelect = true;
+// OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, hNewItem);
+// ignoreSelect = false;
+// if (oldSelected) {
+// tvItem.state = OS.TVIS_SELECTED;
+// tvItem.hItem = hItem;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// }
+// if (!newSelected) {
+// tvItem.state = 0;
+// tvItem.hItem = hNewItem;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// }
+// if (!newSelected && drawCount == 0) {
+// RECT rect1 = new RECT (), rect2 = new RECT ();
+// rect1.left = hItem; rect2.left = hNewItem;
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// int fItemRect = (bits & OS.TVS_FULLROWSELECT) != 0 ? 0 : 1;
+// OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, rect1);
+// OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, rect2);
+// /*
+// * This code is intentionally commented.
+// */
+//// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+// if (OS.IsWinCE) {
+// OS.InvalidateRect (handle, rect1, false);
+// OS.InvalidateRect (handle, rect2, false);
+// OS.UpdateWindow (handle);
+// } else {
+// int flags = OS.RDW_UPDATENOW | OS.RDW_INVALIDATE;
+// OS.RedrawWindow (handle, rect1, 0, flags);
+// OS.RedrawWindow (handle, rect2, 0, flags);
+// }
+// }
+// return LRESULT.ZERO;
+// }
+// }
+// }
+// int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+// hAnchor = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+// return new LRESULT (code);
+// }
+// }
+// return result;
+//}
+//
+//LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+// LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+// if ((style & SWT.SINGLE) != 0) return result;
+// /*
+// * Feature in Windows. When multiple item have
+// * the TVIS_SELECTED state, Windows redraws only
+// * the focused item in the color used to show the
+// * selection when the tree loses or gains focus.
+// * The fix is to force Windows to redraw all the
+// * visible items when focus is gained or lost.
+// */
+// OS.InvalidateRect (handle, null, false);
+// return result;
+//}
+//
+//LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
+// if ((style & SWT.CHECK) != 0) {
+// TVHITTESTINFO lpht = new TVHITTESTINFO ();
+// lpht.x = (short) (lParam & 0xFFFF);
+// lpht.y = (short) (lParam >> 16);
+// OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+// if ((lpht.flags & OS.TVHT_ONITEMSTATEICON) != 0) {
+// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+// sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_LBUTTONDBLCLK, wParam, lParam);
+// if (OS.GetCapture () != handle) OS.SetCapture (handle);
+// TVITEM tvItem = new TVITEM ();
+// tvItem.hItem = lpht.hItem;
+// tvItem.mask = OS.TVIF_PARAM | OS.TVIF_STATE;
+// tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// int state = tvItem.state >> 12;
+// if ((state & 0x1) != 0) {
+// state++;
+// } else {
+// --state;
+// }
+// tvItem.state = state << 12;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// if (!OS.IsWinCE) {
+// int id = tvItem.hItem;
+// if (OS.COMCTL32_MAJOR >= 6) {
+// id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, tvItem.hItem, 0);
+// }
+// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, id);
+// }
+// Event event = new Event ();
+// event.item = items [tvItem.lParam];
+// event.detail = SWT.CHECK;
+// postEvent (SWT.Selection, event);
+// return LRESULT.ZERO;
+// }
+// }
+// return super.WM_LBUTTONDBLCLK (wParam, lParam);
+//}
+//
+//LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+// /*
+// * In a multi-select tree, if the user is collapsing a subtree that
+// * contains selected items, clear the selection from these items and
+// * issue a selection event. Only items that are selected and visible
+// * are cleared. This code also runs in the case when no item is selected.
+// */
+// TVHITTESTINFO lpht = new TVHITTESTINFO ();
+// lpht.x = (short) (lParam & 0xFFFF);
+// lpht.y = (short) (lParam >> 16);
+// OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+// if (lpht.hItem == 0 || (lpht.flags & OS.TVHT_ONITEMBUTTON) != 0) {
+// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+// boolean fixSelection = false, deselected = false;
+// if (lpht.hItem != 0 && (style & SWT.MULTI) != 0) {
+// int hSelection = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+// if (hSelection != 0) {
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_STATE | OS.TVIF_PARAM;
+// tvItem.hItem = lpht.hItem;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// if ((tvItem.state & OS.TVIS_EXPANDED) != 0) {
+// fixSelection = true;
+// tvItem.stateMask = OS.TVIS_SELECTED;
+// int hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, lpht.hItem);
+// int hLast = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, lpht.hItem);
+// int hNext = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, lpht.hItem);
+// while (hNext != 0 && hNext != hLast) {
+// tvItem.hItem = hNext;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// if ((tvItem.state & OS.TVIS_SELECTED) != 0) deselected = true;
+// tvItem.state = 0;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// if ((hNext = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNext)) == 0) break;
+// if (hParent == OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hNext)) break;
+// }
+// }
+// }
+// }
+// dragStarted = gestureCompleted = false;
+// if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = true;
+// int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+// if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = false;
+// if (dragStarted && OS.GetCapture () != handle) OS.SetCapture (handle);
+// if (deselected) {
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_PARAM;
+// tvItem.hItem = lpht.hItem;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// Event event = new Event ();
+// event.item = items [tvItem.lParam];
+// postEvent (SWT.Selection, event);
+// }
+// return new LRESULT (code);
+// }
+//
+// /* Look for check/uncheck */
+// if ((style & SWT.CHECK) != 0) {
+// if ((lpht.flags & OS.TVHT_ONITEMSTATEICON) != 0) {
+// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+// if (OS.GetCapture () != handle) OS.SetCapture (handle);
+// TVITEM tvItem = new TVITEM ();
+// tvItem.hItem = lpht.hItem;
+// tvItem.mask = OS.TVIF_PARAM | OS.TVIF_STATE;
+// tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// int state = tvItem.state >> 12;
+// if ((state & 0x1) != 0) {
+// state++;
+// } else {
+// --state;
+// }
+// tvItem.state = state << 12;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// if (!OS.IsWinCE) {
+// int id = tvItem.hItem;
+// if (OS.COMCTL32_MAJOR >= 6) {
+// id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, tvItem.hItem, 0);
+// }
+// OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, id);
+// }
+// Event event = new Event ();
+// event.item = items [tvItem.lParam];
+// event.detail = SWT.CHECK;
+// postEvent (SWT.Selection, event);
+// return LRESULT.ZERO;
+// }
+// }
+//
+// /* Get the selected state of the item under the mouse */
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_STATE;
+// tvItem.stateMask = OS.TVIS_SELECTED;
+// boolean hittestSelected = false;
+// if ((style & SWT.MULTI) != 0) {
+// tvItem.hItem = lpht.hItem;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// hittestSelected = (tvItem.state & OS.TVIS_SELECTED) != 0;
+// }
+//
+// /* Get the selected state of the last selected item */
+// int hOldItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+// if ((style & SWT.MULTI) != 0) {
+// tvItem.hItem = hOldItem;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+//
+// /* Check for CONTROL or drag selection */
+// if (hittestSelected || (wParam & OS.MK_CONTROL) != 0) {
+// if (drawCount == 0) {
+// OS.UpdateWindow (handle);
+// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+// /*
+// * This code is intentionally commented.
+// */
+//// OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+// }
+// } else {
+// deselectAll ();
+// }
+// }
+//
+// /* Do the selection */
+// sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+// dragStarted = gestureCompleted = false;
+// ignoreDeselect = ignoreSelect = true;
+// int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+// ignoreDeselect = ignoreSelect = false;
+// if (dragStarted && OS.GetCapture () != handle) OS.SetCapture (handle);
+// int hNewItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+//
+// /*
+// * Feature in Windows. When the old and new focused item
+// * are the same, Windows does not check to make sure that
+// * the item is actually selected, not just focused. The
+// * fix is to force the item to draw selected by setting
+// * the state mask. This is only necessary when the tree
+// * is single select.
+// */
+// if ((style & SWT.SINGLE) != 0) {
+// if (hOldItem == hNewItem) {
+// tvItem.mask = OS.TVIF_STATE;
+// tvItem.state = OS.TVIS_SELECTED;
+// tvItem.stateMask = OS.TVIS_SELECTED;
+// tvItem.hItem = hNewItem;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// }
+// }
+//
+// /* Reselect the last item that was unselected */
+// if ((style & SWT.MULTI) != 0) {
+//
+// /* Check for CONTROL and reselect the last item */
+// if (hittestSelected || (wParam & OS.MK_CONTROL) != 0) {
+// if (hOldItem == hNewItem && hOldItem == lpht.hItem) {
+// if ((wParam & OS.MK_CONTROL) != 0) {
+// tvItem.state ^= OS.TVIS_SELECTED;
+// if (dragStarted) tvItem.state = OS.TVIS_SELECTED;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// }
+// } else {
+// if ((tvItem.state & OS.TVIS_SELECTED) != 0) {
+// tvItem.state = OS.TVIS_SELECTED;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// }
+// if ((wParam & OS.MK_CONTROL) != 0 && !dragStarted) {
+// if (hittestSelected) {
+// tvItem.state = 0;
+// tvItem.hItem = lpht.hItem;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// }
+// }
+// }
+// if (drawCount == 0) {
+// RECT rect1 = new RECT (), rect2 = new RECT ();
+// rect1.left = hOldItem; rect2.left = hNewItem;
+// int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+// int fItemRect = (bits & OS.TVS_FULLROWSELECT) != 0 ? 0 : 1;
+// OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, rect1);
+// OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, rect2);
+// /*
+// * This code is intentionally commented.
+// */
+//// OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+// OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+// if (OS.IsWinCE) {
+// OS.InvalidateRect (handle, rect1, false);
+// OS.InvalidateRect (handle, rect2, false);
+// OS.UpdateWindow (handle);
+// } else {
+// int flags = OS.RDW_UPDATENOW | OS.RDW_INVALIDATE;
+// OS.RedrawWindow (handle, rect1, 0, flags);
+// OS.RedrawWindow (handle, rect2, 0, flags);
+// }
+// }
+// }
+//
+// /* Check for SHIFT or normal select and delect/reselect items */
+// if ((wParam & OS.MK_CONTROL) == 0) {
+// if (!hittestSelected || !dragStarted) {
+// tvItem.state = 0;
+// int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
+// OS.SetWindowLong (handle, OS.GWL_WNDPROC, TreeProc);
+// for (int i=0; i> 16);
+// postEvent (SWT.DragDetect, event);
+// } else {
+// sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam);
+// }
+// dragStarted = false;
+// return new LRESULT (code);
+//}
+//
+//LRESULT WM_MOVE (int wParam, int lParam) {
+// if (ignoreResize) return null;
+// return super.WM_MOVE (wParam, lParam);
+//}
+//
+//LRESULT WM_NOTIFY (int wParam, int lParam) {
+// NMHDR hdr = new NMHDR ();
+// OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+// if (hwndHeader != 0 && hdr.hwndFrom == hwndHeader) {
+// /*
+// * Feature in Windows. On NT, the automatically created
+// * header control is created as a UNICODE window, not an
+// * ANSI window despite the fact that the parent is created
+// * as an ANSI window. This means that it sends UNICODE
+// * notification messages to the parent window on NT for
+// * no good reason. The data and size in the NMHEADER and
+// * HDITEM structs is identical between the platforms so no
+// * different message is actually necessary. Despite this,
+// * Windows sends different messages. The fix is to look
+// * for both messages, despite the platform. This works
+// * because only one will be sent on either platform, never
+// * both.
+// */
+// switch (hdr.code) {
+// case OS.HDN_BEGINTRACKW:
+// case OS.HDN_BEGINTRACKA:
+// case OS.HDN_DIVIDERDBLCLICKW:
+// case OS.HDN_DIVIDERDBLCLICKA: {
+// NMHEADER phdn = new NMHEADER ();
+// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+// TreeColumn column = columns [phdn.iItem];
+// if (column != null && !column.getResizable ()) {
+// return LRESULT.ONE;
+// }
+// break;
+// }
+// case OS.HDN_ITEMCHANGINGW:
+// case OS.HDN_ITEMCHANGINGA: {
+// NMHEADER phdn = new NMHEADER ();
+// OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
+// if (phdn.pitem != 0) {
+// HDITEM newItem = new HDITEM ();
+// OS.MoveMemory (newItem, phdn.pitem, HDITEM.sizeof);
+// if ((newItem.mask & OS.HDI_WIDTH) != 0) {
+// HDITEM oldItem = new HDITEM ();
+// oldItem.mask = OS.HDI_WIDTH;
+// OS.SendMessage (hwndHeader, OS.HDM_GETITEM, phdn.iItem, oldItem);
+// int deltaX = newItem.cxy - oldItem.cxy;
+// RECT rect = new RECT (), itemRect = new RECT ();
+// OS.GetClientRect (handle, rect);
+// OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, phdn.iItem, itemRect);
+// int gridWidth = getLinesVisible () ? GRID_WIDTH : 0;
+// rect.left = itemRect.right - gridWidth;
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// if (phdn.iItem < count - 1) {
+// for (int i=phdn.iItem; i> 16);
+// OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+// if (lpht.hItem != 0 && (lpht.flags & (OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL)) != 0) {
+// if ((wParam & (OS.MK_CONTROL | OS.MK_SHIFT)) == 0) {
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_STATE;
+// tvItem.stateMask = OS.TVIS_SELECTED;
+// tvItem.hItem = lpht.hItem;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// if ((tvItem.state & OS.TVIS_SELECTED) == 0) {
+// ignoreSelect = true;
+// OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, 0);
+// ignoreSelect = false;
+// OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem);
+// }
+// }
+// }
+// return LRESULT.ZERO;
+//}
+//
+//LRESULT WM_PRINTCLIENT (int wParam, int lParam) {
+// LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+// if (result != null) return result;
+// /*
+// * Feature in Windows. For some reason, when WM_PRINT is used
+// * to capture an image of a hierarchy that contains a tree with
+// * columns, the clipping that is used to stop the first column
+// * from drawing on top of subsequent columns stops the first
+// * column and the tree lines from drawing. This does not happen
+// * during WM_PAINT. The fix is to draw without clipping and
+// * then draw the rest of the columns on top. Since the drawing
+// * is happening in WM_PRINTCLIENT, the redrawing is not visible.
+// */
+// printClient = true;
+// int code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
+// printClient = false;
+// return new LRESULT (code);
+//}
+//
+//LRESULT WM_SETFOCUS (int wParam, int lParam) {
+// LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+// if ((style & SWT.SINGLE) != 0) return result;
+// /*
+// * Feature in Windows. When multiple item have
+// * the TVIS_SELECTED state, Windows redraws only
+// * the focused item in the color used to show the
+// * selection when the tree loses or gains focus.
+// * The fix is to force Windows to redraw all the
+// * visible items when focus is gained or lost.
+// */
+// OS.InvalidateRect (handle, null, false);
+// return result;
+//}
+//
+//LRESULT WM_SETFONT (int wParam, int lParam) {
+// LRESULT result = super.WM_SETFONT (wParam, lParam);
+// if (result != null) return result;
+// if (hwndHeader != 0) OS.SendMessage (hwndHeader, OS.WM_SETFONT, wParam, lParam);
+// return result;
+//}
+//
+//LRESULT WM_SIZE (int wParam, int lParam) {
+// if (ignoreResize) return null;
+// return super.WM_SIZE (wParam, lParam);
+//}
+//
+//LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
+// LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+// if (result != null) return result;
+// if ((style & SWT.CHECK) != 0) setCheckboxImageList ();
+// return result;
+//}
+//
+//LRESULT wmColorChild (int wParam, int lParam) {
+// /*
+// * Feature in Windows. Tree controls send WM_CTLCOLOREDIT
+// * to allow application code to change the default colors.
+// * This is undocumented and conflicts with TVM_SETTEXTCOLOR
+// * and TVM_SETBKCOLOR, the documented way to do this. The
+// * fix is to ignore WM_CTLCOLOREDIT messages from trees.
+// */
+// return null;
+//}
+//
+//LRESULT wmNotifyChild (int wParam, int lParam) {
+// NMHDR hdr = new NMHDR ();
+// OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+// switch (hdr.code) {
+// case OS.TVN_GETDISPINFOA:
+// case OS.TVN_GETDISPINFOW: {
+// NMTVDISPINFO lptvdi = new NMTVDISPINFO ();
+// OS.MoveMemory (lptvdi, lParam, NMTVDISPINFO.sizeof);
+// /*
+// * Feature in Windows. When a new tree item is inserted
+// * using TVM_INSERTITEM, a TVN_GETDISPINFO is sent before
+// * TVM_INSERTITEM returns and before the item is added to
+// * the items array. The fix is to check for null.
+// *
+// * NOTE: This only happens on XP with the version 6.00 of
+// * COMCTL32.DLL,
+// */
+// if (items == null) break;
+// TreeItem item = items [lptvdi.lParam];
+// if (item == null) break;
+// if ((lptvdi.mask & OS.TVIF_TEXT) != 0) {
+// String string = item.text;
+// TCHAR buffer = new TCHAR (getCodePage (), string, false);
+// int byteCount = Math.min (buffer.length (), lptvdi.cchTextMax - 1) * TCHAR.sizeof;
+// OS.MoveMemory (lptvdi.pszText, buffer, byteCount);
+// OS.MoveMemory (lptvdi.pszText + byteCount, new byte [TCHAR.sizeof], TCHAR.sizeof);
+// lptvdi.cchTextMax = Math.min (lptvdi.cchTextMax, string.length () + 1);
+// }
+// if ((lptvdi.mask & (OS.TVIF_IMAGE | OS.TVIF_SELECTEDIMAGE)) != 0) {
+// Image image = item.image;
+// lptvdi.iImage = OS.I_IMAGENONE;
+// if (image != null) {
+// lptvdi.iImage = lptvdi.iSelectedImage = imageIndex (image);
+// }
+// }
+// OS.MoveMemory (lParam, lptvdi, NMTVDISPINFO.sizeof);
+// break;
+// }
+// case OS.NM_CUSTOMDRAW: {
+// if (!customDraw) break;
+// NMTVCUSTOMDRAW nmcd = new NMTVCUSTOMDRAW ();
+// OS.MoveMemory (nmcd, lParam, NMTVCUSTOMDRAW.sizeof);
+// switch (nmcd.dwDrawStage) {
+// case OS.CDDS_PREPAINT: {
+// return new LRESULT (OS.CDRF_NOTIFYITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT);
+// }
+// case OS.CDDS_POSTPAINT: {
+// if (linesVisible) {
+// int hDC = nmcd.hdc;
+// if (hwndHeader != 0) {
+// int x = 0;
+// RECT rect = new RECT ();
+// HDITEM hdItem = new HDITEM ();
+// hdItem.mask = OS.HDI_WIDTH;
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// for (int i=0; i= nmcd.right || nmcd.top >= nmcd.bottom) {
+// break;
+// }
+// int hDC = nmcd.hdc;
+// OS.SaveDC (hDC);
+// if (linesVisible) {
+// RECT rect = new RECT ();
+// OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+// OS.DrawEdge (hDC, rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
+// }
+// if (!printClient && (style & SWT.FULL_SELECTION) == 0) {
+// if (hwndHeader != 0) {
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// if (count != 0) {
+// HDITEM hdItem = new HDITEM ();
+// hdItem.mask = OS.HDI_WIDTH;
+// OS.SendMessage (hwndHeader, OS.HDM_GETITEM, 0, hdItem);
+// int hRgn = OS.CreateRectRgn (nmcd.left, nmcd.top, nmcd.left + hdItem.cxy, nmcd.bottom);
+// OS.SelectClipRgn (hDC, hRgn);
+// OS.DeleteObject (hRgn);
+// }
+// }
+// }
+// if (item.font == -1 && item.foreground == -1 && item.background == -1) {
+// if (item.cellForeground == null && item.cellBackground == null && item.cellFont == null) {
+// return new LRESULT (OS.CDRF_DODEFAULT | OS.CDRF_NOTIFYPOSTPAINT);
+// }
+// }
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_STATE;
+// tvItem.hItem = item.handle;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// int hFont = item.cellFont != null ? item.cellFont [0] : item.font;
+// if (hFont != -1) OS.SelectObject (hDC, hFont);
+// if ((tvItem.state & (OS.TVIS_SELECTED | OS.TVIS_DROPHILITED)) == 0) {
+// if (OS.IsWindowEnabled (handle)) {
+// int clrText = item.cellForeground != null ? item.cellForeground [0] : item.foreground;
+// nmcd.clrText = clrText == -1 ? getForegroundPixel () : clrText;
+// int clrTextBk = item.cellBackground != null ? item.cellBackground [0] : item.background;
+// nmcd.clrTextBk = clrTextBk == -1 ? getBackgroundPixel () : clrTextBk;
+// OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+// }
+// }
+// return new LRESULT (OS.CDRF_NEWFONT | OS.CDRF_NOTIFYPOSTPAINT);
+// }
+// case OS.CDDS_ITEMPOSTPAINT: {
+// TreeItem item = items [nmcd.lItemlParam];
+// if (item == null) break;
+// /*
+// * Feature in Windows. Under certain circumstances, Windows
+// * sends CDDS_ITEMPOSTPAINT for an empty rectangle. This is
+// * not a problem providing that graphics do not occur outside
+// * the rectangle. The fix is to test for the rectangle and
+// * draw nothing.
+// *
+// * NOTE: This seems to happen when both I_IMAGECALLBACK
+// * and LPSTR_TEXTCALLBACK are used at the same time with
+// * TVM_SETITEM.
+// */
+// if (nmcd.left >= nmcd.right || nmcd.top >= nmcd.bottom) {
+// break;
+// }
+// int hDC = nmcd.hdc;
+// OS.RestoreDC (hDC, -1);
+// OS.SetBkMode (hDC, OS.TRANSPARENT);
+// boolean useColor = OS.IsWindowEnabled (handle);
+// if (useColor) {
+// if ((style & SWT.FULL_SELECTION) != 0) {
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_STATE;
+// tvItem.hItem = item.handle;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// if ((tvItem.state & OS.TVIS_SELECTED) != 0) {
+// useColor = false;
+// } else {
+// /*
+// * Feature in Windows. When the mouse is pressed and the
+// * selection is first drawn for a tree, the item is drawn
+// * selected, but the TVIS_SELECTED bits for the item are
+// * not set. When the user moves the mouse slightly and
+// * a drag and drop operation is not started, the item is
+// * drawn again and this time TVIS_SELECTED is set. This
+// * means that an item that is in a tree that has the style
+// * TVS_FULLROWSELECT and that also contains colored cells
+// * will not draw the entire row selected until the user
+// * moves the mouse. The fix is to test for the selection
+// * colors and guess that the item is selected.
+// *
+// * NOTE: This code doesn't work when the foreground and
+// * background of the tree are set to the selection colors
+// * but this does not happen in a regular application.
+// */
+// int clrForeground = OS.GetTextColor (hDC);
+// if (clrForeground == OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT)) {
+// int clrBackground = OS.GetBkColor (hDC);
+// if (clrBackground == OS.GetSysColor (OS.COLOR_HIGHLIGHT)) {
+// useColor = false;
+// }
+// }
+// }
+// } else {
+// OS.SetTextColor (hDC, getForegroundPixel ());
+// }
+// }
+// if (hwndHeader != 0) {
+// GCData data = new GCData();
+// data.device = display;
+// GC gc = GC.win32_new (hDC, data);
+// int x = 0;
+// Point size = null;
+// RECT rect = new RECT ();
+// HDITEM hdItem = new HDITEM ();
+// hdItem.mask = OS.HDI_WIDTH;
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// for (int i=0; i 0) {
+// OS.SetRect (rect, x, nmcd.top, x + hdItem.cxy, nmcd.bottom - GRID_WIDTH);
+// if (printClient || (style & SWT.FULL_SELECTION) != 0) {
+// drawBackground (hDC, OS.GetBkColor (hDC), rect);
+// }
+// if (useColor) {
+// int clrTextBk = item.cellBackground != null ? item.cellBackground [i] : item.background;
+// if (clrTextBk != -1) drawBackground (hDC, clrTextBk, rect);
+// }
+// Image image = item.images != null ? item.images [i] : null;
+// if (image != null) {
+// Rectangle bounds = image.getBounds ();
+// if (size == null) size = getImageSize ();
+// gc.drawImage (image, 0, 0, bounds.width, bounds.height, rect.left, rect.top, size.x, size.y);
+// OS.SetRect (rect, rect.left + size.x + INSET, rect.top, rect.right - INSET, rect.bottom);
+// } else {
+// OS.SetRect (rect, rect.left + INSET, rect.top, rect.right - INSET, rect.bottom);
+// }
+// /*
+// * Bug in Windows. When DrawText() is used with DT_VCENTER
+// * and DT_ENDELLIPSIS, the ellipsis can draw outside of the
+// * rectangle when the rectangle is empty. The fix is avoid
+// * all text drawing for empty rectangles.
+// */
+// if (rect.left < rect.right) {
+// if (item.strings != null && item.strings [i] != null) {
+// int hFont = item.cellFont != null ? item.cellFont [i] : item.font;
+// hFont = hFont != -1 ? OS.SelectObject (hDC, hFont) : -1;
+// int clrText = -1;
+// if (useColor) {
+// clrText = item.cellForeground != null ? item.cellForeground [i] : item.foreground;
+// clrText = clrText != -1? OS.SetTextColor (hDC, clrText) : -1;
+// }
+// int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER | OS.DT_ENDELLIPSIS;
+// TreeColumn column = columns [i];
+// if ((column.style & SWT.LEFT) != 0) flags |= OS.DT_LEFT;
+// if ((column.style & SWT.CENTER) != 0) flags |= OS.DT_CENTER;
+// if ((column.style & SWT.RIGHT) != 0) flags |= OS.DT_RIGHT;
+// TCHAR buffer = new TCHAR (getCodePage (), item.strings [i], false);
+// OS.DrawText (hDC, buffer, buffer.length (), rect, flags);
+// if (hFont != -1) OS.SelectObject (hDC, hFont);
+// if (clrText != -1) OS.SetTextColor (hDC, clrText);
+// }
+// }
+// }
+// x += hdItem.cxy;
+// }
+// gc.dispose ();
+// }
+// if (linesVisible) {
+// if (printClient && (style & SWT.FULL_SELECTION) == 0) {
+// if (hwndHeader != 0) {
+// int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+// if (count != 0 && printClient) {
+// HDITEM hdItem = new HDITEM ();
+// hdItem.mask = OS.HDI_WIDTH;
+// OS.SendMessage (hwndHeader, OS.HDM_GETITEM, 0, hdItem);
+// RECT rect = new RECT ();
+// OS.SetRect (rect, nmcd.left + hdItem.cxy, nmcd.top, nmcd.right, nmcd.bottom);
+// OS.DrawEdge (hDC, rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
+// }
+// }
+// }
+// RECT rect = new RECT ();
+// if (OS.COMCTL32_MAJOR < 6 || (style & SWT.FULL_SELECTION) != 0) {
+// OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
+// } else {
+// rect.left = item.handle;
+// if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, rect) != 0) {
+// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+// if (hItem == item.handle) {
+// OS.SetRect (rect, rect.right, nmcd.top, nmcd.right, nmcd.bottom);
+// } else {
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_STATE;
+// tvItem.hItem = item.handle;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// if ((tvItem.state & OS.TVIS_SELECTED) != 0) {
+// OS.SetRect (rect, rect.right, nmcd.top, nmcd.right, nmcd.bottom);
+// } else {
+// OS.SetRect (rect, rect.left, nmcd.top, nmcd.right, nmcd.bottom);
+// }
+// }
+// } else {
+// rect.left = 0;
+// }
+// }
+// OS.DrawEdge (hDC, rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
+// }
+// return new LRESULT (OS.CDRF_DODEFAULT);
+// }
+// }
+// break;
+// }
+// case OS.NM_DBLCLK: {
+// if (!ignoreSelect) {
+// int pos = OS.GetMessagePos ();
+// POINT pt = new POINT ();
+// pt.x = (short) (pos & 0xFFFF);
+// pt.y = (short) (pos >> 16);
+// OS.ScreenToClient (handle, pt);
+// TVHITTESTINFO lpht = new TVHITTESTINFO ();
+// lpht.x = pt.x;
+// lpht.y = pt.y;
+// OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+// if ((lpht.flags & OS.TVHT_ONITEM) == 0) break;
+// Event event = new Event ();
+// int hItem = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+// if (hItem != 0) {
+// TVITEM tvItem = new TVITEM ();
+// tvItem.hItem = hItem;
+// tvItem.mask = OS.TVIF_PARAM;
+// OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+// event.item = items [tvItem.lParam];
+// }
+// postEvent (SWT.DefaultSelection, event);
+// }
+// if (hooks (SWT.DefaultSelection)) return LRESULT.ONE;
+// break;
+// }
+// case OS.TVN_SELCHANGEDA:
+// case OS.TVN_SELCHANGEDW: {
+// if ((style & SWT.MULTI) != 0) {
+// if (lockSelection) {
+// /* Restore the old selection state of both items */
+// if (oldSelected) {
+// TVITEM tvItem = new TVITEM ();
+// int offset = NMHDR.sizeof + 4;
+// OS.MoveMemory (tvItem, lParam + offset, TVITEM.sizeof);
+// tvItem.mask = OS.TVIF_STATE;
+// tvItem.stateMask = OS.TVIS_SELECTED;
+// tvItem.state = OS.TVIS_SELECTED;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// }
+// if (!newSelected && ignoreSelect) {
+// TVITEM tvItem = new TVITEM ();
+// int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
+// OS.MoveMemory (tvItem, lParam + offset, TVITEM.sizeof);
+// tvItem.mask = OS.TVIF_STATE;
+// tvItem.stateMask = OS.TVIS_SELECTED;
+// tvItem.state = 0;
+// OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+// }
+// }
+// }
+// if (!ignoreSelect) {
+// TVITEM tvItem = new TVITEM ();
+// int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
+// OS.MoveMemory (tvItem, lParam + offset, TVITEM.sizeof);
+// hAnchor = tvItem.hItem;
+// Event event = new Event ();
+// event.item = items [tvItem.lParam];
+// postEvent (SWT.Selection, event);
+// }
+// updateScrollBar ();
+// break;
+// }
+// case OS.TVN_SELCHANGINGA:
+// case OS.TVN_SELCHANGINGW: {
+// if ((style & SWT.MULTI) != 0) {
+// if (lockSelection) {
+// /* Save the old selection state for both items */
+// TVITEM tvItem = new TVITEM ();
+// int offset1 = NMHDR.sizeof + 4;
+// OS.MoveMemory (tvItem, lParam + offset1, TVITEM.sizeof);
+// oldSelected = (tvItem.state & OS.TVIS_SELECTED) != 0;
+// int offset2 = NMHDR.sizeof + 4 + TVITEM.sizeof;
+// OS.MoveMemory (tvItem, lParam + offset2, TVITEM.sizeof);
+// newSelected = (tvItem.state & OS.TVIS_SELECTED) != 0;
+// }
+// }
+// if (!ignoreSelect && !ignoreDeselect) {
+// hAnchor = 0;
+// if ((style & SWT.MULTI) != 0) deselectAll ();
+// }
+// break;
+// }
+// case OS.TVN_ITEMEXPANDEDA:
+// case OS.TVN_ITEMEXPANDEDW: {
+// updateScrollBar ();
+// break;
+// }
+// case OS.TVN_ITEMEXPANDINGA:
+// case OS.TVN_ITEMEXPANDINGW: {
+// if (!ignoreExpand) {
+// TVITEM tvItem = new TVITEM ();
+// int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
+// OS.MoveMemory (tvItem, lParam + offset, TVITEM.sizeof);
+// /*
+// * Feature in Windows. In some cases, TVM_ITEMEXPANDING
+// * is sent from within TVM_DELETEITEM for the tree item
+// * being destroyed. By the time the message is sent,
+// * the item has already been removed from the list of
+// * items. The fix is to check for null.
+// */
+// if (items == null) break;
+// TreeItem item = items [tvItem.lParam];
+// if (item == null) break;
+// Event event = new Event ();
+// event.item = item;
+// int [] action = new int [1];
+// OS.MoveMemory (action, lParam + NMHDR.sizeof, 4);
+// switch (action [0]) {
+// case OS.TVE_EXPAND:
+// /*
+// * Bug in Windows. When the numeric keypad asterisk
+// * key is used to expand every item in the tree, Windows
+// * sends TVN_ITEMEXPANDING to items in the tree that
+// * have already been expanded. The fix is to detect
+// * that the item is already expanded and ignore the
+// * notification.
+// */
+// if ((tvItem.state & OS.TVIS_EXPANDED) == 0) {
+// sendEvent (SWT.Expand, event);
+// if (isDisposed ()) return LRESULT.ZERO;
+// }
+// break;
+// case OS.TVE_COLLAPSE:
+// sendEvent (SWT.Collapse, event);
+// if (isDisposed ()) return LRESULT.ZERO;
+// break;
+// }
+// }
+// break;
+// }
+// case OS.TVN_BEGINDRAGA:
+// case OS.TVN_BEGINDRAGW:
+// case OS.TVN_BEGINRDRAGA:
+// case OS.TVN_BEGINRDRAGW: {
+// TVITEM tvItem = new TVITEM ();
+// int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
+// OS.MoveMemory (tvItem, lParam + offset, TVITEM.sizeof);
+// if (tvItem.hItem != 0 && (tvItem.state & OS.TVIS_SELECTED) == 0) {
+// ignoreSelect = ignoreDeselect = true;
+// OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, tvItem.hItem);
+// ignoreSelect = ignoreDeselect = false;
+// }
+// dragStarted = true;
+// break;
+// }
+// case OS.NM_RECOGNIZEGESTURE: {
+// /*
+// * Feature in Pocket PC. The tree and table controls detect the tap
+// * and hold gesture by default. They send a GN_CONTEXTMENU message to show
+// * the popup menu. This default behaviour is unwanted on Pocket PC 2002
+// * when no menu has been set, as it still draws a red circle. The fix
+// * is to disable this default behaviour when no menu is set by returning
+// * TRUE when receiving the Pocket PC 2002 specific NM_RECOGNIZEGESTURE
+// * message.
+// */
+// if (OS.IsPPC) {
+// boolean hasMenu = menu != null && !menu.isDisposed ();
+// if (!hasMenu && !hooks (SWT.MenuDetect)) return LRESULT.ONE;
+// }
+// break;
+// }
+// case OS.GN_CONTEXTMENU: {
+// if (OS.IsPPC) {
+// boolean hasMenu = menu != null && !menu.isDisposed ();
+// if (hasMenu || hooks (SWT.MenuDetect)) {
+// NMRGINFO nmrg = new NMRGINFO ();
+// OS.MoveMemory (nmrg, lParam, NMRGINFO.sizeof);
+// showMenu (nmrg.x, nmrg.y);
+// gestureCompleted = true;
+// return LRESULT.ONE;
+// }
+// }
+// break;
+// }
+// }
+// return super.wmNotifyChild (wParam, lParam);
+//}
+
+Point minimumSize (int wHint, int hHint, boolean changed) {
+ java.awt.Dimension size = handle.getPreferredSize();
+ return new Point(size.width, size.height);
+}
+
+public void processEvent(AWTEvent e) {
+ int id = e.getID();
+ switch(id) {
+ case MouseEvent.MOUSE_CLICKED: if(!hooks(SWT.DefaultSelection) || ((MouseEvent)e).getClickCount() != 2) { super.processEvent(e); return; } break;
+ case ItemEvent.ITEM_STATE_CHANGED: if(!hooks(SWT.Selection)) { super.processEvent(e); return; } break;
+ default: { super.processEvent(e); return; }
+ }
+ if(isDisposed()) {
+ super.processEvent(e);
+ return;
+ }
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ try {
+ switch(id) {
+ case MouseEvent.MOUSE_CLICKED:
+ MouseEvent me = (MouseEvent)e;
+ if(me.getClickCount() == 2) {
+ java.awt.Point location = me.getPoint();
+ TreePath path = ((CTree)handle).getPathForLocation(location.x, location.y);
+ if(path != null) {
+ Event event = new Event();
+ event.item = ((CTreeItem)path.getLastPathComponent()).getTreeItem();
+ sendEvent(SWT.DefaultSelection, event);
+ }
+ }
+ break;
+ case ItemEvent.ITEM_STATE_CHANGED:
+ Event event = new Event();
+ event.detail = SWT.CHECK;
+ event.item = ((CTreeItem)((ItemEvent)e).getItem()).getTreeItem();
+ sendEvent(SWT.Selection, event);
+ break;
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+public void processEvent(EventObject e) {
+ if(e instanceof TreeExpansionEvent) {
+ TreePath path = ((TreeExpansionEvent)e).getPath();
+ if(!(path.getLastPathComponent() instanceof CTreeItem)) {
+ super.processEvent(e);
+ return;
+ }
+ boolean isExpanded = ((CTree)handle).isExpanded(path);
+ if(isExpanded) {
+ if(!hooks(SWT.Expand)) { super.processEvent(e); return; }
+ } else {
+ if(!hooks(SWT.Collapse)) { super.processEvent(e); return; }
+ }
+ } else if(e instanceof TreeSelectionEvent) {
+ TreePath path = ((TreeSelectionEvent)e).getPath();
+ if(!(path.getLastPathComponent() instanceof CTreeItem)) {
+ super.processEvent(e);
+ return;
+ }
+ if(!hooks(SWT.Selection)) { super.processEvent(e); return; }
+ } else if(e instanceof CellPaintEvent) {
+ switch(((CellPaintEvent)e).getType()) {
+ case CellPaintEvent.ERASE_TYPE: if(!hooks(SWT.EraseItem)) { super.processEvent(e); return; } break;
+ case CellPaintEvent.PAINT_TYPE: if(!hooks(SWT.PaintItem)) { super.processEvent(e); return; } break;
+ case CellPaintEvent.MEASURE_TYPE: if(!hooks(SWT.MeasureItem)) { super.processEvent(e); return; } break;
+ default: super.processEvent(e); return;
+ }
+ } else {
+ super.processEvent(e);
+ return;
+ }
+ if(isDisposed()) {
+ super.processEvent(e);
+ return;
+ }
+ try {
+ UIThreadUtils.startExclusiveSection(getDisplay());
+ if(isDisposed()) {
+ UIThreadUtils.stopExclusiveSection();
+ super.processEvent(e);
+ return;
+ }
+ if(e instanceof TreeExpansionEvent) {
+ TreePath path = ((TreeExpansionEvent)e).getPath();
+ boolean isExpanded = ((CTree)handle).isExpanded(path);
+ Event event = new Event();
+ event.item = ((CTreeItem)path.getLastPathComponent()).getTreeItem();
+ if(isExpanded) {
+ sendEvent(SWT.Expand, event);
+ ((CTree)handle).expandPath(path);
+ } else {
+ sendEvent(SWT.Collapse, event);
+ ((CTree)handle).collapsePath(path);
+ }
+ } else if(e instanceof TreeSelectionEvent) {
+ TreePath path = ((TreeSelectionEvent)e).getPath();
+ Event event = new Event();
+ event.item = ((CTreeItem)path.getLastPathComponent()).getTreeItem();
+ sendEvent(SWT.Selection, event);
+ } else if(e instanceof CellPaintEvent) {
+ CellPaintEvent cellPaintEvent = (CellPaintEvent)e;
+ switch(cellPaintEvent.getType()) {
+ case CellPaintEvent.ERASE_TYPE: {
+ TreeItem treeItem = cellPaintEvent.treeItem.getTreeItem();
+ Rectangle cellBounds = treeItem.getBounds(cellPaintEvent.column);
+ Event event = new Event();
+ event.x = cellBounds.x;
+ event.y = cellBounds.y;
+ event.width = cellBounds.width;
+ event.height = cellBounds.height;
+ event.item = treeItem;
+ event.index = cellPaintEvent.column;
+ if(!cellPaintEvent.ignoreDrawForeground) event.detail |= SWT.FOREGROUND;
+ if(!cellPaintEvent.ignoreDrawBackground) event.detail |= SWT.BACKGROUND;
+ if(!cellPaintEvent.ignoreDrawSelection) event.detail |= SWT.SELECTED;
+ if(!cellPaintEvent.ignoreDrawFocused) event.detail |= SWT.FOCUSED;
+ event.gc = new GC(this);
+ event.gc.handle.setUserClip(((CTree)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false));
+// event.gc.isSwingPainting = true;
+ sendEvent(SWT.EraseItem, event);
+ if(event.doit) {
+ cellPaintEvent.ignoreDrawForeground = (event.detail & SWT.FOREGROUND) == 0;
+ cellPaintEvent.ignoreDrawBackground = (event.detail & SWT.BACKGROUND) == 0;
+ cellPaintEvent.ignoreDrawSelection = (event.detail & SWT.SELECTED) == 0;
+ cellPaintEvent.ignoreDrawFocused = (event.detail & SWT.FOCUSED) == 0;
+ } else {
+ cellPaintEvent.ignoreDrawForeground = true;
+ cellPaintEvent.ignoreDrawBackground = true;
+ cellPaintEvent.ignoreDrawSelection = true;
+ cellPaintEvent.ignoreDrawFocused = true;
+ }
+// event.gc.isSwingPainting = false;
+ break;
+ }
+ case CellPaintEvent.PAINT_TYPE: {
+ TreeItem treeItem = cellPaintEvent.treeItem.getTreeItem();
+ Rectangle cellBounds = treeItem.getBounds(cellPaintEvent.column);
+ Event event = new Event();
+ event.x = cellBounds.x;
+ event.y = cellBounds.y;
+ event.width = cellBounds.width;
+ event.height = cellBounds.height;
+ event.item = treeItem;
+ event.index = cellPaintEvent.column;
+ if(!cellPaintEvent.ignoreDrawForeground) event.detail |= SWT.FOREGROUND;
+ if(!cellPaintEvent.ignoreDrawBackground) event.detail |= SWT.BACKGROUND;
+ if(!cellPaintEvent.ignoreDrawSelection) event.detail |= SWT.SELECTED;
+ if(!cellPaintEvent.ignoreDrawFocused) event.detail |= SWT.FOCUSED;
+ event.gc = new GC(this);
+ event.gc.handle.setUserClip(((CTree)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false));
+ sendEvent(SWT.PaintItem, event);
+ break;
+ }
+ case CellPaintEvent.MEASURE_TYPE:
+ TreeItem treeItem = cellPaintEvent.treeItem.getTreeItem();
+// Rectangle cellBounds = tableItem.getBounds(cellPaintEvent.column);
+ Event event = new Event();
+// event.x = cellBounds.x;
+// event.y = cellBounds.y;
+// event.width = cellBounds.width;
+// event.height = cellBounds.height;
+ event.height = cellPaintEvent.rowHeight;
+ event.item = treeItem;
+ event.index = cellPaintEvent.column;
+ event.gc = new GC(this);
+// event.gc.handle.clip(((CTree)handle).getCellRect(cellPaintEvent.row, cellPaintEvent.column, false));
+ sendEvent(SWT.MeasureItem, event);
+// cellPaintEvent.rowHeight -= event.height - cellBounds.height;
+ cellPaintEvent.rowHeight = event.height;
+ break;
+ }
+ }
+ super.processEvent(e);
+ } catch(Throwable t) {
+ UIThreadUtils.storeException(t);
+ } finally {
+ UIThreadUtils.stopExclusiveSection();
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TreeColumn.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TreeColumn.java
new file mode 100644
index 00000000000..8924944b4fe
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/TreeColumn.java
@@ -0,0 +1,649 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.awt.AWTEvent;
+import java.beans.PropertyChangeEvent;
+import java.util.EventObject;
+
+import javax.swing.ImageIcon;
+import javax.swing.SwingConstants;
+import javax.swing.event.TableColumnModelEvent;
+import javax.swing.table.TableColumn;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.internal.swing.CTree;
+import org.eclipse.swt.internal.swing.CTreeColumn;
+import org.eclipse.swt.internal.swing.UIThreadUtils;
+import org.eclipse.swt.internal.swing.Utils;
+
+/**
+ * Instances of this class represent a column in a tree widget.
+ *
+ *
Styles:
+ *
LEFT, RIGHT, CENTER
+ *
Events:
+ *
Move, Resize, Selection
+ *
+ *
+ * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ *
+ * @since 3.1
+ */
+public class TreeColumn extends Item {
+ Tree parent;
+ CTreeColumn handle;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Tree) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TreeColumn (Tree parent, int style) {
+ super (parent, checkStyle (style));
+ handle = createHandle();
+ this.parent = parent;
+ parent.createItem (this, parent.getColumnCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Tree), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @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
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TreeColumn (Tree parent, int style, int index) {
+ super (parent, checkStyle (style));
+ handle = createHandle();
+ this.parent = parent;
+ parent.createItem (this, index);
+}
+
+/**
+ * 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 ControlListener
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @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.Resize,typedListener);
+ addListener (SWT.Move,typedListener);
+}
+
+/**
+ * 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 SelectionListener
+ * interface.
+ *
+ * widgetSelected is called when the column header is selected.
+ * widgetDefaultSelected is not called.
+ *
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Selection,typedListener);
+ addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+ return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+CTreeColumn createHandle () {
+ return CTreeColumn.Factory.newInstance(this, style);
+}
+
+void destroyWidget () {
+ parent.destroyItem (this);
+ releaseHandle ();
+}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * LEFT, RIGHT or CENTER.
+ *
+ * @return the alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getAlignment () {
+ checkWidget ();
+ if ((style & SWT.LEFT) != 0) return SWT.LEFT;
+ if ((style & SWT.CENTER) != 0) return SWT.CENTER;
+ if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
+ return SWT.LEFT;
+}
+
+boolean moveable;
+
+/**
+ * Gets the moveable attribute. A column that is
+ * not moveable cannot be reordered by the user
+ * by dragging the header but may be reordered
+ * by the programmer.
+ *
+ * @return the moveable attribute
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Tree getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Gets the resizable attribute. A column that is
+ * not resizable cannot be dragged by the user but
+ * may be resized by the programmer.
+ *
+ * @return the resizable attribute
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getResizable () {
+ checkWidget ();
+ return ((TableColumn)handle).getResizable();
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getWidth () {
+ checkWidget ();
+ return ((TableColumn)handle).getWidth();
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ */
+public void pack () {
+ checkWidget ();
+ int index = parent.indexOf (this);
+ if (index == -1) return;
+// int oldWidth = getWidth();
+ CTree cTree = (CTree)parent.handle;
+ int newWidth = cTree.getPreferredColumnWidth(index);
+ // TODO: check why in the old SWTSwing, +2 is added.
+ cTree.getColumnModel().getColumn(index).setPreferredWidth(newWidth + 2);
+// checkWidget ();
+// int columnWidth = 0;
+// int hwnd = parent.handle;
+// int hDC = OS.GetDC (hwnd);
+// int oldFont = 0, newFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+// if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
+// int cp = parent.getCodePage ();
+// RECT rect = new RECT ();
+// int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX;
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_PARAM;
+// int hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+// while (hItem != 0) {
+// hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+// tvItem.hItem = hItem;
+// OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
+// TreeItem item = parent.items [tvItem.lParam];
+// if (index == 0) {
+// rect.left = item.handle;
+// if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 1, rect) != 0) {
+// columnWidth = Math.max (columnWidth, rect.right);
+// }
+// } else {
+// int imageWidth = 0, textWidth = 0;
+// Image image = item.images != null ? item.images [index] : null;
+// if (image != null) {
+// Rectangle bounds = image.getBounds ();
+// imageWidth = bounds.width;
+// }
+// String string = item.strings != null ? item.strings [index] : null;
+// if (string != null) {
+// TCHAR buffer = new TCHAR (cp, string, false);
+// OS.DrawText (hDC, buffer, buffer.length (), rect, flags);
+// textWidth = rect.right - rect.left;
+// }
+// columnWidth = Math.max (columnWidth, imageWidth + textWidth + Tree.INSET * 3);
+// }
+// }
+// TCHAR buffer = new TCHAR (cp, text, true);
+// OS.DrawText (hDC, buffer, buffer.length (), rect, flags);
+// int headerWidth = rect.right - rect.left + Tree.HEADER_MARGIN;
+// if (image != null) {
+// int margin = 0, hwndHeader = parent.hwndHeader;
+// if (hwndHeader != 0 && OS.COMCTL32_VERSION >= OS.VERSION (5, 80)) {
+// margin = OS.SendMessage (hwndHeader, OS.HDM_GETBITMAPMARGIN, 0, 0);
+// } else {
+// margin = OS.GetSystemMetrics (OS.SM_CXEDGE) * 3;
+// }
+// Rectangle bounds = image.getBounds ();
+// headerWidth += bounds.width + margin * 2;
+// }
+// if (newFont != 0) OS.SelectObject (hDC, oldFont);
+// OS.ReleaseDC (hwnd, hDC);
+// setWidth (Math.max (headerWidth, columnWidth));
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ parent = null;
+}
+
+/**
+ * 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
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Move, listener);
+ eventTable.unhook (SWT.Resize, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+ checkWidget ();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Selection, listener);
+ eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Controls how text and images will be displayed in the receiver.
+ * The argument should be one of LEFT, RIGHT
+ * or CENTER.
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setAlignment (int alignment) {
+ checkWidget ();
+ if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return;
+ int index = parent.indexOf (this);
+ if (index == -1 || index == 0) return;
+ style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+ if ((style & SWT.LEFT) == SWT.LEFT) handle.setAlignment(SwingConstants.LEFT);
+ if ((style & SWT.CENTER) == SWT.CENTER) handle.setAlignment(SwingConstants.CENTER);
+ if ((style & SWT.RIGHT) == SWT.RIGHT) handle.setAlignment(SwingConstants.RIGHT);
+ // TODO: notify change
+}
+
+public void setImage (Image image) {
+ checkWidget();
+ if (image != null && image.isDisposed ()) {
+ error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int index = parent.indexOf (this);
+ if (index == -1) return;
+ super.setImage (image);
+ handle.setIcon(image == null? null: new ImageIcon(image.handle));
+ // TODO: notify repaint
+}
+
+/**
+ * Sets the moveable attribute. A column that is
+ * moveable can be reordered by the user by dragging
+ * the header. A column that is not moveable cannot be
+ * dragged by the user but may be reordered
+ * by the programmer.
+ *
+ * @param moveable the moveable attribute
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Tree#setColumnOrder(int[])
+ * @see Tree#getColumnOrder()
+ * @see TreeColumn#getMoveable()
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public void setMoveable (boolean moveable) {
+ checkWidget ();
+ this.moveable = moveable;
+}
+
+/**
+ * Sets the resizable attribute. A column that is
+ * not resizable cannot be dragged by the user but
+ * may be resized by the programmer.
+ *
+ * @param resizable the resize attribute
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setResizable (boolean resizable) {
+ checkWidget ();
+ ((TableColumn)handle).setResizable(resizable);
+}
+
+public void setText (String string) {
+ checkWidget ();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (string.equals (text)) return;
+ super.setText (string);
+ // TODO: check what happens with mnemonics
+ ((TableColumn)handle).setHeaderValue(string);
+}
+
+/**
+ * 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
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.2
+ */
+public void setToolTipText (String string) {
+ checkWidget();
+ handle.setToolTipText(string);
+// toolTipText = string;
+// int hwndHeaderToolTip = parent.headerToolTipHandle;
+// if (hwndHeaderToolTip == 0) {
+// parent.createHeaderToolTips ();
+// parent.updateHeaderToolTips ();
+// }
+}
+
+/**
+ * Sets the width of the receiver.
+ *
+ * @param width the new width
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ */
+
+public class TreeItem extends Item {
+ /**
+ * the handle to the OS resource
+ * (Warning: This field is platform dependent)
+ *
+ * IMPORTANT: This field is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms and should never be accessed from application code.
+ *
+ */
+ CTreeItem handle;
+ Tree parent;
+ TreeItem parentItem;
+ ArrayList itemList;
+// String [] strings;
+ Image [] images;
+ boolean cached;
+// int background = -1, foreground = -1, font = -1;
+// int [] cellBackground, cellForeground, cellFont;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Tree or a TreeItem)
+ * and a style value describing its behavior and appearance.
+ * The item is added to the end of the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a tree control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TreeItem (Tree parent, int style) {
+ super (parent, style);
+ this.parent = parent;
+ handle = createHandle();
+ parent.createItem (this, ((CTree)parent.handle).getRoot().getChildCount());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Tree or a TreeItem),
+ * a style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a tree control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TreeItem (Tree parent, int style, int index) {
+ super (parent, style);
+ if (index < 0) error (SWT.ERROR_INVALID_RANGE);
+ this.parent = parent;
+ handle = createHandle();
+ parent.createItem (this, index);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Tree or a TreeItem)
+ * and a style value describing its behavior and appearance.
+ * The item is added to the end of the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TreeItem (TreeItem parentItem, int style) {
+ super (checkNull (parentItem).parent, style);
+ parent = parentItem.parent;
+ this.parentItem = parentItem;
+ handle = createHandle();
+ parent.createItem (this, parentItem, parentItem.handle.getChildCount());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a Tree or a TreeItem),
+ * a style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ * @param index the zero-relative index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public TreeItem (TreeItem parentItem, int style, int index) {
+ super (checkNull (parentItem).parent, style);
+ if (index < 0) error (SWT.ERROR_INVALID_RANGE);
+ parent = parentItem.parent;
+ this.parentItem = parentItem;
+ handle = createHandle();
+ parent.createItem (this, parentItem, index);
+}
+
+static TreeItem checkNull (TreeItem item) {
+ if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return item;
+}
+
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+CTreeItem createHandle () {
+ return CTreeItem.Factory.newInstance(this, style);
+}
+
+/**
+ * Clears the item at the given zero-relative index in the receiver.
+ * The text, icon and other attributes of the item are set to the default
+ * value. If the tree was created with the SWT.VIRTUAL style,
+ * these attributes are requested again as needed.
+ *
+ * @param index the index of the item to clear
+ * @param all true if all child items of the indexed item should be
+ * cleared recursively, and false otherwise
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.2
+ */
+public void clear (int index, boolean all) {
+ checkWidget ();
+ TreeItemObject treeItemObject = handle.getTreeItemObject(index);
+ treeItemObject.setText(null);
+ treeItemObject.setBackground(null);
+ treeItemObject.setForeground(null);
+ treeItemObject.setFont(null);
+ treeItemObject.setIcon(null);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = false;
+ ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle);
+ if(all) {
+ TreeItem[] items = getItems();
+ for(int i=0; iSWT.VIRTUAL style, these
+ * attributes are requested again as needed.
+ *
+ * @param all true if all child items should be cleared
+ * recursively, and false otherwise
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ *
+ */
+public Color getBackground () {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ java.awt.Color color = handle.getBackground();
+ if(color == null) return parent.getBackground();
+ return Color.swing_new(display, color);
+}
+
+/**
+ * Returns the background color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the background color
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public Color getBackground (int index) {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return getBackground ();
+ java.awt.Color color = handle.getTreeItemObject(index).getBackground();
+ if(color == null) {
+ if(index != 0) {
+ return getBackground();
+ }
+ return Color.swing_new(display, parent.handle.getBackground());
+ }
+ return Color.swing_new(display, color);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Rectangle getBounds () {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return getBounds(0);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent at a column in the tree.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding column rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public Rectangle getBounds (int index) {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ CTree tree = (CTree)parent.handle;
+ int row = tree.getRowForPath(new TreePath(handle.getPath()));
+ if(row == -1) return new Rectangle(0, 0, 0, 0);
+ java.awt.Rectangle rect = tree.getCellRect(row, index, false);
+ return new Rectangle(rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Returns true if the receiver is checked,
+ * and false otherwise. When the parent does not have
+ * the CHECK style, return false.
+ *
+ *
+ * @return the checked state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getChecked () {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if ((parent.style & SWT.CHECK) == 0) return false;
+ return handle.isChecked();
+}
+
+/**
+ * Returns true if the receiver is expanded,
+ * and false otherwise.
+ *
+ *
+ * @return the expanded state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getExpanded () {
+ checkWidget ();
+ return ((CTree)parent.handle).isExpanded(new TreePath(handle.getPath()));
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information for this item.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public Font getFont () {
+ return getFont(0);
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information
+ * for the specified cell in this item.
+ *
+ * @param index the column index
+ * @return the receiver's font
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public Font getFont (int index) {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count -1) return getFont ();
+ java.awt.Font font = handle.getTreeItemObject(index).getFont();
+ if(font == null) {
+ if(index != 0) {
+ return getFont();
+ }
+ return Font.swing_new(display, parent.handle.getFont());
+ }
+ return Font.swing_new(display, font);
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ *
+ */
+public Color getForeground () {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ java.awt.Color color = handle.getForeground();
+ if(color == null) return parent.getForeground();
+ return Color.swing_new(display, color);
+}
+
+/**
+ *
+ * Returns the foreground color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the foreground color
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public Color getForeground (int index) {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count -1) return getForeground ();
+ java.awt.Color color = handle.getTreeItemObject(index).getForeground();
+ if(color == null) {
+ if(index != 0) {
+ return getBackground();
+ }
+ return Color.swing_new(display, parent.handle.getForeground());
+ }
+ return Color.swing_new(display, color);
+}
+
+/**
+ * Returns true if the receiver is grayed,
+ * and false otherwise. When the parent does not have
+ * the CHECK style, return false.
+ *
+ *
+ * @return the grayed state of the checkbox
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public boolean getGrayed () {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if ((parent.style & SWT.CHECK) == 0) return false;
+ return handle.isGrayed();
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public TreeItem getItem (int index) {
+ checkWidget ();
+ if (index < 0) error (SWT.ERROR_INVALID_RANGE);
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if(index < 0 || index >= getItemCount()) error (SWT.ERROR_INVALID_RANGE);
+ return (TreeItem)itemList.get(index);
+// int hwnd = parent.handle;
+// int hFirstItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+// if (hFirstItem == 0) error (SWT.ERROR_INVALID_RANGE);
+// int hItem = parent.findItem (hFirstItem, index);
+// if (hItem == 0) error (SWT.ERROR_INVALID_RANGE);
+// return parent._getItem (hItem);
+}
+
+/**
+ * Returns the number of items contained in the receiver
+ * that are direct item children of the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getItemCount () {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return itemList == null? 0: itemList.size();
+}
+
+/**
+ * Returns a (possibly empty) array of TreeItems which
+ * are the direct item children of the receiver.
+ *
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TreeItem [] getItems () {
+ checkWidget ();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return itemList == null? new TreeItem [0]: (TreeItem [])itemList.toArray(new TreeItem [0]);
+}
+
+public Image getImage () {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return super.getImage ();
+}
+
+/**
+ * Returns the image stored at the given column index in the receiver,
+ * or null if the image has not been set or if the column does not exist.
+ *
+ * @param index the column index
+ * @return the image stored at the given column index in the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public Image getImage (int index) {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ if (index == 0) return getImage ();
+ if (images != null) {
+ if (0 <= index && index < images.length) return images [index];
+ }
+ return null;
+}
+
+/**
+ * Returns a rectangle describing the size and location
+ * relative to its parent of an image at a column in the
+ * tree.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding image rectangle
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public Rectangle getImageBounds (int index) {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count -1) return new Rectangle(0, 0, 0, 0);
+ CTree cTree = ((CTree)parent.handle);
+ int row = cTree.getRowForPath(new TreePath(handle.getPath()));
+ java.awt.Rectangle imageBounds = ((CTree)parent.handle).getImageBounds(row, index);
+ return new Rectangle(imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height);
+
+// java.awt.Color color = handle.getTreeItemObject(index).getForeground();
+// RECT rect = getBounds (index, false, true, false);
+// int width = rect.right - rect.left, height = rect.bottom - rect.top;
+// return new Rectangle (rect.left, rect.top, width, height);
+}
+
+/**
+ * Returns the receiver's parent, which must be a Tree.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public Tree getParent () {
+ checkWidget ();
+ return parent;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * TreeItem or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public TreeItem getParentItem () {
+ checkWidget ();
+ return parentItem;
+}
+
+public String getText () {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ return super.getText ();
+}
+
+/**
+ * Returns the text stored at the given column index in the receiver,
+ * or empty string if the text has not been set.
+ *
+ * @param index the column index
+ * @return the text stored at the given column index in the receiver
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public String getText (int index) {
+ checkWidget();
+ if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return "";
+ return handle.getTreeItemObject(index).getText();
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the tool item is null
+ *
ERROR_INVALID_ARGUMENT - if the tool item has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public int indexOf (TreeItem item) {
+ //TODO - make public and add Tree.indexOf(TreeItem) and TreeItem.indexOf(TreeItem)?
+ checkWidget ();
+ if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+ return itemList == null? -1: itemList.indexOf(item);
+}
+
+void releaseChildren (boolean destroy) {
+ if (destroy) {
+ parent.destroyItem (this);
+ }
+ super.releaseChildren (destroy);
+}
+
+void releaseHandle () {
+ super.releaseHandle ();
+ handle = null;
+ parent = null;
+}
+
+void releaseWidget() {
+ super.releaseWidget();
+ images = null;
+}
+
+/**
+ * Removes all of the items from the receiver.
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void removeAll () {
+ checkWidget ();
+ if(itemList != null) {
+ for (int i=itemList.size()-1; i>=0; i--) {
+ TreeItem item = (TreeItem)itemList.get(i);
+ if (item != null && !item.isDisposed ()) {
+ item.dispose();
+// item.release(false);
+ } else {
+ itemList.remove(i);
+ }
+ }
+ }
+// int hwnd = parent.handle;
+// TVITEM tvItem = new TVITEM ();
+// tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+// tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+// while (tvItem.hItem != 0) {
+// OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
+// TreeItem item = tvItem.lParam != -1 ? parent.items [tvItem.lParam] : null;
+// if (item != null && !item.isDisposed ()) {
+// item.dispose ();
+// } else {
+// parent.releaseItem (tvItem.hItem, tvItem, false);
+// parent.destroyItem (null, tvItem.hItem);
+// }
+// tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+// }
+}
+
+/**
+ * Sets the receiver's background color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ *
+ */
+public void setBackground (Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ handle.setBackground(color == null? null: color.handle);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle);
+ parent.handle.repaint();
+}
+
+/**
+ * Sets the background color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ *
+ */
+public void setBackground (int index, Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ handle.getTreeItemObject(index).setBackground(color == null? null: color.handle);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle);
+ parent.handle.repaint();
+}
+
+/**
+ * Sets the checked state of the receiver.
+ *
+ *
+ * @param checked the new checked state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setChecked (boolean checked) {
+ checkWidget ();
+ if ((parent.style & SWT.CHECK) == 0) return;
+ handle.setChecked(checked);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle);
+}
+
+/**
+ * Sets the expanded state of the receiver.
+ *
+ *
+ * @param expanded the new expanded state
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setExpanded (boolean expanded) {
+ checkWidget ();
+
+ CTree tree = ((CTree)parent.handle);
+ if(expanded) {
+ tree.expandPath(new TreePath(handle.getPath()));
+ } else {
+ tree.collapsePath(new TreePath(handle.getPath()));
+ }
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for this item 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
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.0
+ */
+public void setFont (Font font){
+ checkWidget ();
+ if (font != null && font.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ handle.setFont(font == null? null: font.handle);
+ ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle);
+ parent.handle.repaint();
+}
+
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for the specified cell in this item to the font specified by the
+ * argument, or to the default font for that kind of control if the
+ * argument is null.
+ *
+ * @param index the column index
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void setFont (int index, Font font) {
+ checkWidget ();
+ if (font != null && font.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ handle.getTreeItemObject(index).setFont(font == null? null: font.handle);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle);
+ parent.handle.repaint();
+}
+
+/**
+ * Sets the receiver's foreground color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @since 2.0
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 2.0
+ *
+ */
+public void setForeground (Color color) {
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ handle.setForeground(color == null? null: color.handle);
+ ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle);
+ parent.handle.repaint();
+}
+
+/**
+ * Sets the foreground color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_INVALID_ARGUMENT - if the argument has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ *
+ */
+public void setForeground (int index, Color color){
+ checkWidget ();
+ if (color != null && color.isDisposed ()) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ handle.getTreeItemObject(index).setForeground(color == null? null: color.handle);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle);
+ parent.handle.repaint();
+}
+
+/**
+ * Sets the grayed state of the checkbox for this item. This state change
+ * only applies if the Tree was created with the SWT.CHECK style.
+ *
+ * @param grayed the new grayed state of the checkbox
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void setGrayed (boolean grayed) {
+ checkWidget ();
+ if ((parent.style & SWT.CHECK) == 0) return;
+ handle.setGrayed(grayed);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle);
+}
+
+/**
+ * Sets the image for multiple columns in the tree.
+ *
+ * @param images the array of new images
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the array of images is null
+ *
ERROR_INVALID_ARGUMENT - if one of the images has been disposed
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @since 3.1
+ */
+public void setText (int index, String string) {
+ checkWidget();
+ if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int count = Math.max (1, parent.getColumnCount ());
+ if (0 > index || index > count - 1) return;
+ if(index == 0) {
+ super.setText(string);
+ }
+ handle.getTreeItemObject(index).setText(string);
+ if ((parent.style & SWT.VIRTUAL) != 0) cached = true;
+ ((CTree)parent.handle).getModel().nodeChanged((TreeNode)handle);
+ parent.adjustColumnWidth();
+}
+
+public void setText (String string) {
+ checkWidget();
+ setText (0, string);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Widget.java
new file mode 100644
index 00000000000..4884c655822
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/swing/org/eclipse/swt/widgets/Widget.java
@@ -0,0 +1,2208 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.widgets;
+
+
+import java.util.*;
+
+import javax.swing.*;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.swing.*;
+
+/**
+ * This class is the abstract superclass of all user interface objects.
+ * Widgets are created, disposed and issue notification to listeners
+ * when events occur which affect them.
+ *
+ *
Styles:
+ *
(none)
+ *
Events:
+ *
Dispose
+ *
+ *
+ * IMPORTANT: This class is intended to be subclassed only
+ * within the SWT implementation. However, it has not been marked
+ * final to allow those outside of the SWT development team to implement
+ * patched versions of the class in order to get around specific
+ * limitations in advance of when those limitations can be addressed
+ * by the team. Any class built using subclassing to access the internals
+ * of this class will likely fail to compile or run between releases and
+ * may be strongly platform specific. Subclassing should not be attempted
+ * without an intimate and detailed understanding of the workings of the
+ * hierarchy. No support is provided for user-written classes which are
+ * implemented as subclasses of this class.
+ *
+ *
+ * @see #checkSubclass
+ */
+
+public abstract class Widget {
+ int style, state;
+ Display display;
+ EventTable eventTable;
+ Object data;
+
+ /* Global state flags */
+ static final int DISPOSED = 1<<0;
+ static final int CANVAS = 1<<1;
+ static final int KEYED_DATA = 1<<2;
+// static final int DISABLED = 1<<3;
+// static final int HIDDEN = 1<<4;
+
+ /* A layout was requested on this widget */
+ static final int LAYOUT_NEEDED = 1<<5;
+
+ /* The preferred size of a child has changed */
+ static final int LAYOUT_CHANGED = 1<<6;
+
+ /* A layout was requested in this widget hierachy */
+ static final int LAYOUT_CHILD = 1<<7;
+
+ /* Background flags */
+ static final int THEME_BACKGROUND = 1<<8;
+ static final int DRAW_BACKGROUND = 1<<9;
+ static final int PARENT_BACKGROUND = 1<<10;
+
+ /* Dispose and release flags */
+ static final int RELEASED = 1<<11;
+ static final int DISPOSE_SENT = 1<<12;
+
+ /* Default size for widgets */
+ static final int DEFAULT_WIDTH = 64;
+ static final int DEFAULT_HEIGHT = 64;
+
+// /* Check and initialize the Common Controls DLL */
+// static final int MAJOR = 5, MINOR = 80;
+// static {
+// if (!OS.IsWinCE) {
+// if (OS.COMCTL32_VERSION < OS.VERSION (MAJOR, MINOR)) {
+// System.out.println ("***WARNING: SWT requires comctl32.dll version " + MAJOR + "." + MINOR + " or greater"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+// System.out.println ("***WARNING: Detected: " + OS.COMCTL32_MAJOR + "." + OS.COMCTL32_MINOR); //$NON-NLS-1$ //$NON-NLS-2$
+// }
+// }
+// OS.InitCommonControls ();
+// }
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Widget () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ *
+ * The style value is either one of the style constants defined in
+ * class SWT which is applicable to instances of this
+ * class, or must be built by bitwise OR'ing together
+ * (that is, using the int "|" operator) two or more
+ * of those SWT style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_ARGUMENT - if the parent is disposed
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ *
+ * @see SWT
+ * @see #checkSubclass
+ * @see #getStyle
+ */
+public Widget (Widget parent, int style) {
+ checkSubclass ();
+ checkParent (parent);
+ this.style = style;
+ display = parent.display;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notifed when an event of the given type occurs. When the
+ * event does occur in the widget, the listener is notified by
+ * sending it the handleEvent() message. The event
+ * type is one of the event constants defined in class SWT.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should be notified when the event occurs
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Listener
+ * @see SWT
+ * @see #removeListener
+ * @see #notifyListeners
+ */
+public void addListener (int eventType, Listener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) eventTable = new EventTable ();
+ eventTable.hook (eventType, listener);
+}
+
+protected void addTypedListener (EventListener listener, int... eventTypes) {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+protected void removeTypedListener (int eventType, EventListener listener) {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notifed when the widget is disposed. When the widget is
+ * disposed, the listener is notified by sending it the
+ * widgetDisposed() message.
+ *
+ * @param listener the listener which should be notified when the receiver is disposed
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DisposeListener
+ * @see #removeDisposeListener
+ */
+public void addDisposeListener (DisposeListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener (listener);
+ addListener (SWT.Dispose, typedListener);
+}
+
+//int callWindowProc (int hwnd, int msg, int wParam, int lParam) {
+// return 0;
+//}
+
+/**
+ * Returns a style with exactly one style bit set out of
+ * the specified set of exclusive style bits. All other
+ * possible bits are cleared when the first matching bit
+ * is found. Bits that are not part of the possible set
+ * are untouched.
+ *
+ * @param style the original style bits
+ * @param int0 the 0th possible style bit
+ * @param int1 the 1st possible style bit
+ * @param int2 the 2nd possible style bit
+ * @param int3 the 3rd possible style bit
+ * @param int4 the 4th possible style bit
+ * @param int5 the 5th possible style bit
+ *
+ * @return the new style bits
+ */
+static int checkBits (int style, int int0, int int1, int int2, int int3, int int4, int int5) {
+ int mask = int0 | int1 | int2 | int3 | int4 | int5;
+ if ((style & mask) == 0) style |= int0;
+ if ((style & int0) != 0) style = (style & ~mask) | int0;
+ if ((style & int1) != 0) style = (style & ~mask) | int1;
+ if ((style & int2) != 0) style = (style & ~mask) | int2;
+ if ((style & int3) != 0) style = (style & ~mask) | int3;
+ if ((style & int4) != 0) style = (style & ~mask) | int4;
+ if ((style & int5) != 0) style = (style & ~mask) | int5;
+ return style;
+}
+
+void checkOrientation (Widget parent) {
+ style &= ~SWT.MIRRORED;
+ if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) == 0) {
+ if (parent != null) {
+ if ((parent.style & SWT.LEFT_TO_RIGHT) != 0) style |= SWT.LEFT_TO_RIGHT;
+ if ((parent.style & SWT.RIGHT_TO_LEFT) != 0) style |= SWT.RIGHT_TO_LEFT;
+ }
+ }
+ style = checkBits (style, SWT.LEFT_TO_RIGHT, SWT.RIGHT_TO_LEFT, 0, 0, 0, 0);
+}
+
+void checkOpened () {
+ /* Do nothing */
+}
+
+/**
+ * Throws an exception if the specified widget can not be
+ * used as a parent for the receiver.
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the parent is null
+ *
ERROR_INVALID_ARGUMENT - if the parent is disposed
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
+ *
+ */
+void checkParent (Widget parent) {
+ if (parent == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (parent.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ parent.checkWidget ();
+ parent.checkOpened ();
+}
+
+/**
+ * Checks that this class can be subclassed.
+ *
+ * The SWT class library is intended to be subclassed
+ * only at specific, controlled points (most notably,
+ * Composite and Canvas when
+ * implementing new widgets). This method enforces this
+ * rule unless it is overridden.
+ *
+ * IMPORTANT: By providing an implementation of this
+ * method that allows a subclass of a class which does not
+ * normally allow subclassing to be created, the implementer
+ * agrees to be fully responsible for the fact that any such
+ * subclass will likely fail between SWT releases and will be
+ * strongly platform specific. No support is provided for
+ * user-written classes which are implemented in this fashion.
+ *
+ * The ability to subclass outside of the allowed SWT classes
+ * is intended purely to enable those not on the SWT development
+ * team to implement patches in order to get around specific
+ * limitations in advance of when those limitations can be
+ * addressed by the team. Subclassing should not be attempted
+ * without an intimate and detailed understanding of the hierarchy.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
+ *
+ */
+protected void checkSubclass () {
+ if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+/**
+ * Throws an SWTException if the receiver can not
+ * be accessed by the caller. This may include both checks on
+ * the state of the receiver and more generally on the entire
+ * execution context. This method should be called by
+ * widget implementors to enforce the standard SWT invariants.
+ *
+ * Currently, it is an error to invoke any method (other than
+ * isDisposed()) on a widget that has had its
+ * dispose() method called. It is also an error
+ * to call widget methods from any thread that is different
+ * from the thread that created the widget.
+ *
+ * In future releases of SWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public void checkWidget () {
+ Display display = this.display;
+ if (display == null) error (SWT.ERROR_WIDGET_DISPOSED);
+ Thread currentThread = Thread.currentThread ();
+ if (display.thread != currentThread && !SwingUtilities.isEventDispatchThread()) {
+ String name = currentThread.getName();
+ if(name == null /*|| !name.startsWith(Utils.getSWTSwingUIThreadsNamePrefix())*/) {
+ error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ }
+ }
+ if ((state & DISPOSED) != 0) error (SWT.ERROR_WIDGET_DISPOSED);
+}
+
+/**
+ * Destroys the widget in the operating system and releases
+ * the widget's handle. If the widget does not have a handle,
+ * this method may hide the widget, mark the widget as destroyed
+ * or do nothing, depending on the widget.
+ *
+ * When a widget is destroyed in the operating system, its
+ * descendents are also destroyed by the operating system.
+ * This means that it is only necessary to call destroyWidget
+ * on the root of the widget tree.
+ *
+ * This method is called after releaseWidget().
+ *
+ * See also releaseChild(), releaseWidget()
+ * and releaseHandle().
+ *
+ *
+ * @see #dispose
+ */
+void destroyWidget () {
+ releaseHandle ();
+}
+
+//int DeferWindowPos(int hWinPosInfo, int hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags){
+// if (OS.IsWinCE) {
+// /*
+// * Feature in Windows. On Windows CE, DeferWindowPos always causes
+// * a WM_SIZE message, even when the new size is the same as the old
+// * size. The fix is to detect that the size has not changed and set
+// * SWP_NOSIZE.
+// */
+// if ((uFlags & OS.SWP_NOSIZE) == 0) {
+// RECT lpRect = new RECT ();
+// OS.GetWindowRect (hWnd, lpRect);
+// if (cy == lpRect.bottom - lpRect.top && cx == lpRect.right - lpRect.left) {
+// /*
+// * Feature in Windows. On Windows CE, DeferWindowPos when called
+// * with SWP_DRAWFRAME always causes a WM_SIZE message, even
+// * when SWP_NOSIZE is set and when the new size is the same as the
+// * old size. The fix is to clear SWP_DRAWFRAME when the size is
+// * the same.
+// */
+// uFlags &= ~OS.SWP_DRAWFRAME;
+// uFlags |= OS.SWP_NOSIZE;
+// }
+// }
+// }
+// return OS.DeferWindowPos (hWinPosInfo, hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
+//}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the receiver and all its descendents. After this method has
+ * been invoked, the receiver and all descendents will answer
+ * true when sent the message isDisposed().
+ * Any internal connections between the widgets in the tree will
+ * have been removed to facilitate garbage collection.
+ *
+ * NOTE: This method is not called recursively on the descendents
+ * of the receiver. This means that, widget implementers can not
+ * detect when a widget is being disposed of by re-implementing
+ * this method, but should instead listen for the Dispose
+ * event.
+ *
+ *
+ * @exception SWTException
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #addDisposeListener
+ * @see #removeDisposeListener
+ * @see #checkWidget
+ */
+public void dispose () {
+ /*
+ * Note: It is valid to attempt to dispose a widget
+ * more than once. If this happens, fail silently.
+ */
+ if (isDisposed ()) return;
+ if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+ release (true);
+}
+
+/**
+ * Does whatever widget specific cleanup is required, and then
+ * uses the code in SWTError.error to handle the error.
+ *
+ * @param code the descriptive error code
+ *
+ * @see SWT#error(int)
+ */
+void error (int code) {
+ SWT.error(code);
+}
+
+boolean filters (int eventType) {
+ return display.filters (eventType);
+}
+
+//Widget findItem (int id) {
+// return null;
+//}
+
+//char [] fixMnemonic (String string) {
+// char [] buffer = new char [string.length ()];
+// string.getChars (0, string.length (), buffer, 0);
+// int i = 0, j = 0;
+// while (i < buffer.length) {
+// if (buffer [i] == '&') {
+// if (i + 1 < buffer.length && buffer [i + 1] == '&') {
+// buffer [j++] = ' ';
+// i++;
+// }
+// i++;
+// } else {
+// buffer [j++] = buffer [i++];
+// }
+// }
+// while (j < buffer.length) buffer [j++] = 0;
+// return buffer;
+//}
+
+int findMnemonicIndex (String string) {
+ int index = 0;
+ int length = string.length ();
+ do {
+ while (index < length && string.charAt (index) != '&') index++;
+ if (++index >= length) return -1;
+ if (string.charAt (index) != '&') return index;
+ index++;
+ } while (index < length);
+ return -1;
+}
+
+String fixMnemonic (String string) {
+ char [] buffer = new char [string.length ()];
+ string.getChars (0, string.length (), buffer, 0);
+ int i = 0, j = 0;
+ while (i < buffer.length) {
+ if (buffer [i] == '&') {
+ if (i + 1 < buffer.length && buffer [i + 1] == '&') {
+ buffer [j++] = ' ';
+ i++;
+ }
+ i++;
+ } else {
+ buffer [j++] = buffer [i++];
+ }
+ }
+ while (j < buffer.length) buffer [j++] = 0;
+ return new String(buffer, 0, j);
+}
+
+/**
+ * Returns the application defined widget data associated
+ * with the receiver, or null if it has not been set. The
+ * widget data is a single, unnamed field that is
+ * stored with every widget.
+ *
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the widget data needs to be notified
+ * when the widget is disposed of, it is the application's
+ * responsibility to hook the Dispose event on the widget and
+ * do so.
+ *
+ *
+ * @return the widget data
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - when the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread
+ *
+ *
+ * @see #setData(Object)
+ */
+public Object getData () {
+ checkWidget();
+ return (state & KEYED_DATA) != 0 ? ((Object []) data) [0] : data;
+}
+
+/**
+ * Returns the application defined property of the receiver
+ * with the specified name, or null if it has not been set.
+ *
+ * Applications may have associated arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the widget is disposed
+ * of, it is the application's responsibility to hook the
+ * Dispose event on the widget and do so.
+ *
+ *
+ * @param key the name of the property
+ * @return the value of the property or null if it has not been set
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the key is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #setData(String, Object)
+ */
+public Object getData (String key) {
+ checkWidget();
+ if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if ((state & KEYED_DATA) != 0) {
+ Object [] table = (Object []) data;
+ for (int i=1; iDisplay that is associated with
+ * the receiver.
+ *
+ * A widget's display is either provided when it is created
+ * (for example, top level Shells) or is the
+ * same as its parent's display.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
+ */
+public Display getDisplay () {
+ Display display = this.display;
+ if (display == null) error (SWT.ERROR_WIDGET_DISPOSED);
+ return display;
+}
+
+Menu getMenu () {
+ return null;
+}
+
+/**
+ * Returns the name of the widget. This is the name of
+ * the class without the package name.
+ *
+ * @return the name of the widget
+ */
+String getName () {
+ String string = getClass ().getName ();
+ int index = string.lastIndexOf ('.');
+ if (index == -1) return string;
+ return string.substring (index + 1, string.length ());
+}
+
+/*
+ * Returns a short printable representation for the contents
+ * of a widget. For example, a button may answer the label
+ * text. This is used by toString to provide a
+ * more meaningful description of the widget.
+ *
+ * @return the contents string for the widget
+ *
+ * @see #toString
+ */
+String getNameText () {
+ return ""; //$NON-NLS-1$
+}
+
+/**
+ * Returns the receiver's style information.
+ *
+ * Note that the value which is returned by this method may
+ * not match the value which was provided to the constructor
+ * when the receiver was created. This can occur when the underlying
+ * operating system does not support a particular combination of
+ * requested styles. For example, if the platform widget used to
+ * implement a particular SWT widget always has scroll bars, the
+ * result of calling this method would always have the
+ * SWT.H_SCROLL and SWT.V_SCROLL bits set.
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ */
+public int getStyle () {
+ checkWidget();
+ return style;
+}
+
+/*
+ * Returns true if the specified eventType is
+ * hooked, and false otherwise. Implementations
+ * of SWT can avoid creating objects and sending events
+ * when an event happens in the operating system but
+ * there are no listeners hooked for the event.
+ *
+ * @param eventType the event to be checked
+ *
+ * @return true when the eventType is hooked and false otherwise
+ *
+ * @see #isListening
+ */
+boolean hooks (int eventType) {
+ if (eventTable == null) return false;
+ return eventTable.hooks (eventType);
+}
+
+/**
+ * Returns true if the widget has been disposed,
+ * and false otherwise.
+ *
+ * This method gets the dispose state for the widget.
+ * When a widget has been disposed, it is an error to
+ * invoke any other method using the widget.
+ *
+ *
+ * @return true when the widget is disposed and false otherwise
+ */
+public boolean isDisposed () {
+ return (state & DISPOSED) != 0;
+}
+
+/**
+ * Returns true if there are any listeners
+ * for the specified event type associated with the receiver,
+ * and false otherwise. The event type is one of
+ * the event constants defined in class SWT.
+ *
+ * @param eventType the type of event
+ * @return true if the event is hooked
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see SWT
+ */
+public boolean isListening (int eventType) {
+ checkWidget();
+ return hooks (eventType);
+}
+
+/*
+ * Returns true when subclassing is
+ * allowed and false otherwise
+ *
+ * @return true when subclassing is allowed and false otherwise
+ */
+boolean isValidSubclass () {
+ return Display.isValidClass (getClass ());
+}
+
+/*
+ * Returns true when the current thread is
+ * the thread that created the widget and false
+ * otherwise.
+ *
+ * @return true when the current thread is the thread that created the widget and false otherwise
+ */
+boolean isValidThread () {
+ return getDisplay ().isValidThread ();
+}
+
+void mapEvent (int hwnd, Event event) {
+}
+
+GC new_GC (GCData data) {
+ return null;
+}
+
+/**
+ * Notifies all of the receiver's listeners for events
+ * of the given type that one such event has occurred by
+ * invoking their handleEvent() method. The
+ * event type is one of the event constants defined in class
+ * SWT.
+ *
+ * @param eventType the type of event which has occurred
+ * @param event the event data
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ * Typically, a widget with children will broadcast this
+ * message to all children so that they too can release their
+ * resources. The releaseHandle method is used
+ * as part of this broadcast to zero the handle fields of the
+ * children without calling destroyWidget. In
+ * this scenario, the children are actually destroyed later,
+ * when the operating system destroys the widget tree.
+ *
+ *
+ * @param destroy indicates that the receiver should be destroyed
+ *
+ * @see #dispose
+ * @see #releaseHandle
+ * @see #releaseParent
+ * @see #releaseWidget
+*/
+void release (boolean destroy) {
+ if ((state & DISPOSE_SENT) == 0) {
+ state |= DISPOSE_SENT;
+ sendEvent (SWT.Dispose);
+ }
+ if ((state & DISPOSED) == 0) {
+ releaseChildren (destroy);
+ }
+ if ((state & RELEASED) == 0) {
+ state |= RELEASED;
+ if (destroy) {
+ releaseParent ();
+ releaseWidget ();
+ destroyWidget ();
+ } else {
+ releaseWidget ();
+ releaseHandle ();
+ }
+ }
+}
+
+void releaseChildren (boolean destroy) {
+}
+
+/*
+ * Releases the widget's handle by zero'ing it out.
+ * Does not destroy or release any operating system
+ * resources.
+ *
+ * This method is called after releaseWidget
+ * or from destroyWidget when a widget is being
+ * destroyed to ensure that the widget is marked as destroyed
+ * in case the act of destroying the widget in the operating
+ * system causes application code to run in callback that
+ * could access the widget.
+ *
+ *
+ * @see #dispose
+ * @see #releaseChildren
+ * @see #releaseParent
+ * @see #releaseWidget
+ */
+void releaseHandle () {
+ state |= DISPOSED;
+ display = null;
+}
+
+/*
+ * Releases the receiver, a child in a widget hierarchy,
+ * from its parent.
+ *
+ * When a widget is destroyed, it may be necessary to remove
+ * it from an internal data structure of the parent. When
+ * a widget has no handle, it may also be necessary for the
+ * parent to hide the widget or otherwise indicate that the
+ * widget has been disposed. For example, disposing a menu
+ * bar requires that the menu bar first be released from the
+ * shell when the menu bar is active. This could not be done
+ * in destroyWidget for the menu bar because the
+ * parent shell as well as other fields have been null'd out
+ * already by releaseWidget.
+ *
+ * This method is called first when a widget is disposed.
+ *
+ * @see #dispose
+ * @see #releaseChild
+ * @see #releaseWidget
+ * @see #releaseHandle
+ */
+void releaseParent () {
+}
+
+/*
+ * Releases any internal resources back to the operating
+ * system and clears all fields except the widget handle.
+ *
+ * When a widget is destroyed, resources that were acquired
+ * on behalf of the programmer need to be returned to the
+ * operating system. For example, if the widget made a
+ * copy of an icon, supplied by the programmer, this copy
+ * would be freed in releaseWidget. Also,
+ * to assist the garbage collector and minimize the amount
+ * of memory that is not reclaimed when the programmer keeps
+ * a reference to a disposed widget, all fields except the
+ * handle are zero'd. The handle is needed by destroyWidget.
+ *
+ *
+ * @see #dispose
+ * @see #releaseChildren
+ * @see #releaseHandle
+ * @see #releaseParent
+ */
+void releaseWidget () {
+ eventTable = null;
+ data = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notifed when an event of the given type occurs. The event
+ * type is one of the event constants defined in class SWT.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified when the event occurs
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Listener
+ * @see SWT
+ * @see #addListener
+ * @see #notifyListeners
+ */
+public void removeListener (int eventType, Listener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (eventType, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notifed when an event of the given type occurs.
+ *
+ * IMPORTANT: This method is not part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ *
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified when the event occurs
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see Listener
+ * @see #addListener
+ */
+protected void removeListener (int eventType, SWTEventListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (eventType, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notifed when the widget is disposed.
+ *
+ * @param listener the listener which should no longer be notified when the receiver is disposed
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the listener is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see DisposeListener
+ * @see #addDisposeListener
+ */
+public void removeDisposeListener (DisposeListener listener) {
+ checkWidget();
+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
+ if (eventTable == null) return;
+ eventTable.unhook (SWT.Dispose, listener);
+}
+
+void sendEvent (Event event) {
+ Display display = event.display;
+ if (!display.filterEvent (event)) {
+ if (eventTable != null) eventTable.sendEvent (event);
+ }
+}
+
+void sendEvent (int eventType) {
+ sendEvent (eventType, null, true);
+}
+
+void sendEvent (int eventType, Event event) {
+ sendEvent (eventType, event, true);
+}
+
+void sendEvent (int eventType, Event event, boolean send) {
+ if (eventTable == null && !display.filters (eventType)) {
+ return;
+ }
+ if (event == null) event = new Event ();
+ event.type = eventType;
+ event.display = display;
+ event.widget = this;
+ if (event.time == 0) {
+ event.time = Utils.getCurrentTime ();
+ }
+ if (send) {
+ sendEvent (event);
+ } else {
+ display.postEvent (event);
+ }
+}
+
+//boolean sendKeyEvent (int type, int msg, int wParam, int lParam) {
+// Event event = new Event ();
+// if (!setKeyState (event, type, wParam, lParam)) return true;
+// return sendKeyEvent (type, msg, wParam, lParam, event);
+//}
+//
+//boolean sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) {
+// sendEvent (type, event);
+// if (isDisposed ()) return false;
+// return event.doit;
+//}
+//
+//boolean sendMouseEvent (int type, int button, int hwnd, int msg, int wParam, int lParam) {
+// return sendMouseEvent (type, button, 0, 0, false, hwnd, msg, wParam, lParam);
+//}
+//
+//boolean sendMouseEvent (int type, int button, int count, int detail, boolean send, int hwnd, int msg, int wParam, int lParam) {
+// if (!hooks (type) && !filters (type)) return true;
+// Event event = new Event ();
+// event.button = button;
+// event.detail = detail;
+// event.count = count;
+// event.x = (short) (lParam & 0xFFFF);
+// event.y = (short) (lParam >> 16);
+// setInputState (event, type);
+// mapEvent (hwnd, event);
+// if (send) {
+// sendEvent (type, event);
+// if (isDisposed ()) return false;
+// } else {
+// postEvent (type, event);
+// }
+// return event.doit;
+//}
+
+/**
+ * Sets the application defined widget data associated
+ * with the receiver to be the argument. The widget
+ * data is a single, unnamed field that is stored
+ * with every widget.
+ *
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the widget data needs to be notified
+ * when the widget is disposed of, it is the application's
+ * responsibility to hook the Dispose event on the widget and
+ * do so.
+ *
+ *
+ * @param data the widget data
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - when the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread
+ *
+ *
+ * @see #getData()
+ */
+public void setData (Object data) {
+ checkWidget();
+ if ((state & KEYED_DATA) != 0) {
+ ((Object []) this.data) [0] = data;
+ } else {
+ this.data = data;
+ }
+}
+
+/**
+ * Sets the application defined property of the receiver
+ * with the specified name to the given value.
+ *
+ * Applications may associate arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the widget is disposed
+ * of, it is the application's responsibility to hook the
+ * Dispose event on the widget and do so.
+ *
+ *
+ * @param key the name of the property
+ * @param value the new value for the property
+ *
+ * @exception IllegalArgumentException
+ *
ERROR_NULL_ARGUMENT - if the key is null
+ *
+ * @exception SWTException
+ *
ERROR_WIDGET_DISPOSED - if the receiver has been disposed
+ *
ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
+ *
+ *
+ * @see #getData(String)
+ */
+public void setData (String key, Object value) {
+ checkWidget();
+ if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
+ int index = 1;
+ Object [] table = null;
+ if ((state & KEYED_DATA) != 0) {
+ table = (Object []) data;
+ while (index < table.length) {
+ if (key.equals (table [index])) break;
+ index += 2;
+ }
+ }
+ if (value != null) {
+ if ((state & KEYED_DATA) != 0) {
+ if (index == table.length) {
+ Object [] newTable = new Object [table.length + 2];
+ System.arraycopy (table, 0, newTable, 0, table.length);
+ data = table = newTable;
+ }
+ } else {
+ table = new Object [3];
+ table [0] = data;
+ data = table;
+ state |= KEYED_DATA;
+ }
+ table [index] = key;
+ table [index + 1] = value;
+ } else {
+ if ((state & KEYED_DATA) != 0) {
+ if (index != table.length) {
+ int length = table.length - 2;
+ if (length == 1) {
+ data = table [0];
+ state &= ~KEYED_DATA;
+ } else {
+ Object [] newTable = new Object [length];
+ System.arraycopy (table, 0, newTable, 0, index);
+ System.arraycopy (table, index + 2, newTable, index, length - index);
+ data = newTable;
+ }
+ }
+ }
+ }
+}
+
+boolean sendFocusEvent (int type) {
+ sendEvent (type);
+ // widget could be disposed at this point
+ return true;
+}
+
+boolean setInputState (Event event, int type) {
+ event.stateMask |= Display.getInputState();
+ switch (type) {
+ case SWT.MouseDown:
+ case SWT.MouseDoubleClick:
+ if (event.button == 1) event.stateMask &= ~SWT.BUTTON1;
+ if (event.button == 2) event.stateMask &= ~SWT.BUTTON2;
+ if (event.button == 3) event.stateMask &= ~SWT.BUTTON3;
+ if (event.button == 4) event.stateMask &= ~SWT.BUTTON4;
+ if (event.button == 5) event.stateMask &= ~SWT.BUTTON5;
+ break;
+ case SWT.MouseUp:
+ if (event.button == 1) event.stateMask |= SWT.BUTTON1;
+ if (event.button == 2) event.stateMask |= SWT.BUTTON2;
+ if (event.button == 3) event.stateMask |= SWT.BUTTON3;
+ if (event.button == 4) event.stateMask |= SWT.BUTTON4;
+ if (event.button == 5) event.stateMask |= SWT.BUTTON5;
+ break;
+ case SWT.KeyDown:
+ case SWT.Traverse:
+ if (event.keyCode == SWT.ALT) event.stateMask &= ~SWT.ALT;
+ if (event.keyCode == SWT.SHIFT) event.stateMask &= ~SWT.SHIFT;
+ if (event.keyCode == SWT.CONTROL) event.stateMask &= ~SWT.CONTROL;
+ break;
+ case SWT.KeyUp:
+ if (event.keyCode == SWT.ALT) event.stateMask |= SWT.ALT;
+ if (event.keyCode == SWT.SHIFT) event.stateMask |= SWT.SHIFT;
+ if (event.keyCode == SWT.CONTROL) event.stateMask |= SWT.CONTROL;
+ break;
+ }
+ return true;
+}
+
+//boolean setKeyState (Event event, int type, int wParam, int lParam) {
+//
+// /*
+// * Feature in Windows. When the user presses Ctrl+Backspace
+// * or Ctrl+Enter, Windows sends a WM_CHAR with Delete (0x7F)
+// * and '\n' instead of '\b' and '\r'. This is the correct
+// * platform behavior but is not portable. The fix is to detect
+// * these cases and convert the character.
+// */
+// switch (display.lastAscii) {
+// case SWT.DEL:
+// if (display.lastKey == SWT.BS) display.lastAscii = SWT.BS;
+// break;
+// case SWT.LF:
+// if (display.lastKey == SWT.CR) display.lastAscii = SWT.CR;
+// break;
+// }
+//
+// /*
+// * Feature in Windows. When the user presses either the Enter
+// * key or the numeric keypad Enter key, Windows sends a WM_KEYDOWN
+// * with wParam=VK_RETURN in both cases. In order to distinguish
+// * between the keys, the extended key bit is tested. If the bit
+// * is set, assume that the numeric keypad Enter was pressed.
+// */
+// if (display.lastKey == SWT.CR && display.lastAscii == SWT.CR) {
+// if ((lParam & 0x1000000) != 0) display.lastKey = SWT.KEYPAD_CR;
+// }
+//
+// if (display.lastVirtual) {
+// /*
+// * Feature in Windows. The virtual key VK_DELETE is not
+// * treated as both a virtual key and an ASCII key by Windows.
+// * Therefore, we will not receive a WM_CHAR for this key.
+// * The fix is to treat VK_DELETE as a special case and map
+// * the ASCII value explictly (Delete is 0x7F).
+// */
+// if (display.lastKey == OS.VK_DELETE) display.lastAscii = 0x7F;
+//
+// /*
+// * Feature in Windows. When the user presses Ctrl+Pause, the
+// * VK_CANCEL key is generated and a WM_CHAR is sent with 0x03,
+// * possibly to allow an application to look for Ctrl+C and the
+// * the Break key at the same time. This is unexpected and
+// * unwanted. The fix is to detect the case and set the character
+// * to zero.
+// */
+// if (display.lastKey == OS.VK_CANCEL) display.lastAscii = 0x0;
+//
+// event.keyCode = Display.translateKey (display.lastKey);
+// } else {
+// event.keyCode = display.lastKey;
+// }
+// if (display.lastAscii != 0 || display.lastNull) {
+// event.character = Display.mbcsToWcs ((char) display.lastAscii);
+// }
+// if (event.keyCode == 0 && event.character == 0) {
+// if (!display.lastNull) return false;
+// }
+// return setInputState (event, type);
+//}
+//
+//boolean SetWindowPos (int hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags) {
+// if (OS.IsWinCE) {
+// /*
+// * Feature in Windows. On Windows CE, SetWindowPos() always causes
+// * a WM_SIZE message, even when the new size is the same as the old
+// * size. The fix is to detect that the size has not changed and set
+// * SWP_NOSIZE.
+// */
+// if ((uFlags & OS.SWP_NOSIZE) == 0) {
+// RECT lpRect = new RECT ();
+// OS.GetWindowRect (hWnd, lpRect);
+// if (cy == lpRect.bottom - lpRect.top && cx == lpRect.right - lpRect.left) {
+// /*
+// * Feature in Windows. On Windows CE, SetWindowPos() when called
+// * with SWP_DRAWFRAME always causes a WM_SIZE message, even
+// * when SWP_NOSIZE is set and when the new size is the same as the
+// * old size. The fix is to clear SWP_DRAWFRAME when the size is
+// * the same.
+// */
+// uFlags &= ~OS.SWP_DRAWFRAME;
+// uFlags |= OS.SWP_NOSIZE;
+// }
+// }
+// }
+// return OS.SetWindowPos (hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
+//}
+
+boolean showMenu (int x, int y) {
+ Event event = new Event ();
+ event.x = x;
+ event.y = y;
+ sendEvent (SWT.MenuDetect, event);
+ if (!event.doit) return true;
+ Menu menu = getMenu ();
+ if (menu != null && !menu.isDisposed ()) {
+ if (x != event.x || y != event.y) {
+ menu.setLocation (event.x, event.y);
+ }
+ menu.setVisible (true);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+@Override
+public String toString () {
+ String string = "*Disposed*"; //$NON-NLS-1$
+ if (!isDisposed ()) {
+ string = "*Wrong Thread*"; //$NON-NLS-1$
+ if (isValidThread ()) string = getNameText ();
+ }
+ return getName () + " {" + string + "}"; //$NON-NLS-1$ //$NON-NLS-2$
+}
+
+//LRESULT wmChar (int hwnd, int wParam, int lParam) {
+// /*
+// * Do not report a lead byte as a key pressed.
+// */
+// if (!OS.IsUnicode && OS.IsDBLocale) {
+// byte lead = (byte) (wParam & 0xFF);
+// if (OS.IsDBCSLeadByte (lead)) return null;
+// }
+// display.lastAscii = wParam;
+// display.lastNull = wParam == 0;
+// if (!sendKeyEvent (SWT.KeyDown, OS.WM_CHAR, wParam, lParam)) {
+// return LRESULT.ONE;
+// }
+// // widget could be disposed at this point
+// return null;
+//}
+//
+//LRESULT wmContextMenu (int hwnd, int wParam, int lParam) {
+// if (wParam != hwnd) return null;
+//
+// /*
+// * Feature in Windows. SHRecognizeGesture() sends an undocumented
+// * WM_CONTEXTMENU notification when the flag SHRG_NOTIFY_PARENT is
+// * not set. This causes the context menu to be displayed twice,
+// * once by the caller of SHRecognizeGesture() and once from this
+// * method. The fix is to ignore WM_CONTEXTMENU notifications on
+// * all WinCE platforms.
+// *
+// * NOTE: This only happens on WM2003. Previous WinCE versions did
+// * not support WM_CONTEXTMENU.
+// */
+// if (OS.IsWinCE) return null;
+//
+// /*
+// * Feature in Windows. When the user presses WM_NCRBUTTONUP,
+// * a WM_CONTEXTMENU message is generated. This happens when
+// * the user releases the mouse over a scroll bar. Normally,
+// * window displays the default scrolling menu but applications
+// * can process WM_CONTEXTMENU to display a different menu.
+// * Typically, an application does not want to supply a special
+// * scroll menu. The fix is to look for a WM_CONTEXTMENU that
+// * originated from a mouse event and display the menu when the
+// * mouse was released in the client area.
+// */
+// int x = 0, y = 0;
+// if (lParam != -1) {
+// POINT pt = new POINT ();
+// x = pt.x = (short) (lParam & 0xFFFF);
+// y = pt.y = (short) (lParam >> 16);
+// OS.ScreenToClient (hwnd, pt);
+// RECT rect = new RECT ();
+// OS.GetClientRect (hwnd, rect);
+// if (!OS.PtInRect (rect, pt)) return null;
+// } else {
+// int pos = OS.GetMessagePos ();
+// x = (short) (pos & 0xFFFF);
+// y = (short) (pos >> 16);
+// }
+//
+// /* Show the menu */
+// return showMenu (x, y) ? LRESULT.ZERO : null;
+//}
+//
+//LRESULT wmIMEChar (int hwnd, int wParam, int lParam) {
+// Display display = this.display;
+// display.lastKey = 0;
+// display.lastAscii = wParam;
+// display.lastVirtual = display.lastNull = display.lastDead = false;
+// if (!sendKeyEvent (SWT.KeyDown, OS.WM_IME_CHAR, wParam, lParam)) {
+// return LRESULT.ONE;
+// }
+// sendKeyEvent (SWT.KeyUp, OS.WM_IME_CHAR, wParam, lParam);
+// // widget could be disposed at this point
+// display.lastKey = display.lastAscii = 0;
+// return LRESULT.ONE;
+//}
+//
+//LRESULT wmKeyDown (int hwnd, int wParam, int lParam) {
+//
+// /* Ignore repeating modifier keys by testing key down state */
+// switch (wParam) {
+// case OS.VK_SHIFT:
+// case OS.VK_MENU:
+// case OS.VK_CONTROL:
+// case OS.VK_CAPITAL:
+// case OS.VK_NUMLOCK:
+// case OS.VK_SCROLL:
+// if ((lParam & 0x40000000) != 0) return null;
+// }
+//
+// /* Clear last key and last ascii because a new key has been typed */
+// display.lastAscii = display.lastKey = 0;
+// display.lastVirtual = display.lastNull = display.lastDead = false;
+//
+// /*
+// * Do not report a lead byte as a key pressed.
+// */
+// if (!OS.IsUnicode && OS.IsDBLocale) {
+// byte lead = (byte) (wParam & 0xFF);
+// if (OS.IsDBCSLeadByte (lead)) return null;
+// }
+//
+// /* Map the virtual key */
+// /*
+// * Bug in WinCE. MapVirtualKey() returns incorrect values.
+// * The fix is to rely on a key mappings table to determine
+// * whether the key event must be sent now or if a WM_CHAR
+// * event will follow. The key mappings table maps virtual
+// * keys to SWT key codes and does not contain mappings for
+// * Windows virtual keys like VK_A. Virtual keys that are
+// * both virtual and ASCII are a special case.
+// */
+// int mapKey = 0;
+// if (OS.IsWinCE) {
+// switch (wParam) {
+// case OS.VK_BACK: mapKey = SWT.BS; break;
+// case OS.VK_RETURN: mapKey = SWT.CR; break;
+// case OS.VK_DELETE: mapKey = SWT.DEL; break;
+// case OS.VK_ESCAPE: mapKey = SWT.ESC; break;
+// case OS.VK_TAB: mapKey = SWT.TAB; break;
+// }
+// } else {
+// mapKey = OS.MapVirtualKey (wParam, 2);
+// }
+//
+// /*
+// * Bug in Windows 95 and NT. When the user types an accent key such
+// * as ^ to get an accented character on a German keyboard, the accent
+// * key should be ignored and the next key that the user types is the
+// * accented key. The fix is to detect the accent key stroke (called
+// * a dead key) by testing the high bit of the value returned by
+// * MapVirtualKey(). A further problem is that the high bit on
+// * Windows NT is bit 32 while the high bit on Windows 95 is bit 16.
+// * They should both be bit 32.
+// *
+// * When the user types an accent key that does not correspond to a
+// * virtual key, MapVirtualKey() won't set the high bit to indicate
+// * a dead key. This happens when an accent key, such as '^' is the
+// * result of a modifier such as Shift key and MapVirtualKey() always
+// * returns the unshifted key. The fix is to peek for a WM_DEADCHAR
+// * and avoid issuing the event.
+// */
+// if (OS.IsWinNT) {
+// if ((mapKey & 0x80000000) != 0) return null;
+// } else {
+// if ((mapKey & 0x8000) != 0) return null;
+// }
+// MSG msg = new MSG ();
+// int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
+// if (OS.PeekMessage (msg, hwnd, OS.WM_DEADCHAR, OS.WM_DEADCHAR, flags)) {
+// display.lastDead = true;
+// display.lastVirtual = mapKey == 0;
+// display.lastKey = display.lastVirtual ? wParam : mapKey;
+// return null;
+// }
+//
+// /*
+// * If we are going to get a WM_CHAR, ensure that last key has
+// * the correct character value for the key down and key up
+// * events. It is not sufficient to ignore the WM_KEYDOWN
+// * (when we know we are going to get a WM_CHAR) and compute
+// * the key in WM_CHAR because there is not enough information
+// * by the time we get the WM_CHAR. For example, when the user
+// * types Ctrl+Shift+6 on a US keyboard, we get a WM_CHAR with
+// * wParam=30. When the user types Ctrl+Shift+6 on a German
+// * keyboard, we also get a WM_CHAR with wParam=30. On the US
+// * keyboard Shift+6 is ^, on the German keyboard Shift+6 is &.
+// * There is no way to map wParam=30 in WM_CHAR to the correct
+// * value. Also, on international keyboards, the control key
+// * may be down when the user has not entered a control character.
+// *
+// * NOTE: On Windows 98, keypad keys are virtual despite the
+// * fact that a WM_CHAR is issued. On Windows 2000 and XP,
+// * they are not virtual. Therefore it is necessary to force
+// * numeric keypad keys to be virtual.
+// */
+// display.lastVirtual = mapKey == 0 || display.numpadKey (wParam) != 0;
+// if (display.lastVirtual) {
+// display.lastKey = wParam;
+// /*
+// * Feature in Windows. The virtual key VK_DELETE is not
+// * treated as both a virtual key and an ASCII key by Windows.
+// * Therefore, we will not receive a WM_CHAR for this key.
+// * The fix is to treat VK_DELETE as a special case and map
+// * the ASCII value explictly (Delete is 0x7F).
+// */
+// if (display.lastKey == OS.VK_DELETE) display.lastAscii = 0x7F;
+//
+// /*
+// * It is possible to get a WM_CHAR for a virtual key when
+// * Num Lock is on. If the user types Home while Num Lock
+// * is down, a WM_CHAR is issued with WPARM=55 (for the
+// * character 7). If we are going to get a WM_CHAR we need
+// * to ensure that the last key has the correct value. Note
+// * that Ctrl+Home does not issue a WM_CHAR when Num Lock is
+// * down.
+// */
+// if (OS.VK_NUMPAD0 <= display.lastKey && display.lastKey <= OS.VK_DIVIDE) {
+// /*
+// * Feature in Windows. Calling to ToAscii() or ToUnicode(), clears
+// * the accented state such that the next WM_CHAR loses the accent.
+// * This makes is critical that the accent key is detected. Also,
+// * these functions clear the character that is entered using the
+// * special Windows keypad sequence when NumLock is down (ie. typing
+// * ALT+0231 should gives 'c' with a cedilla when NumLock is down).
+// */
+// if (display.asciiKey (display.lastKey) != 0) return null;
+// display.lastAscii = display.numpadKey (display.lastKey);
+// }
+// } else {
+// /*
+// * Convert LastKey to lower case because Windows non-virtual
+// * keys that are also ASCII keys, such as like VK_A, are have
+// * upper case values in WM_KEYDOWN despite the fact that the
+// * Shift was not pressed.
+// */
+// display.lastKey = OS.CharLower ((short) mapKey);
+//
+// /*
+// * Feature in Windows. The virtual key VK_CANCEL is treated
+// * as both a virtual key and ASCII key by Windows. This
+// * means that a WM_CHAR with WPARAM=3 will be issued for
+// * this key. In order to distinguish between this key and
+// * Ctrl+C, mark the key as virtual.
+// */
+// if (wParam == OS.VK_CANCEL) display.lastVirtual = true;
+//
+// /*
+// * Some key combinations map to Windows ASCII keys depending
+// * on the keyboard. For example, Ctrl+Alt+Q maps to @ on a
+// * German keyboard. If the current key combination is special,
+// * the correct character is placed in wParam for processing in
+// * WM_CHAR. If this is the case, issue the key down event from
+// * inside WM_CHAR.
+// */
+// int asciiKey = display.asciiKey (wParam);
+// if (asciiKey != 0) {
+// /*
+// * When the user types Ctrl+Space, ToAscii () maps this to
+// * Space. Normally, ToAscii () maps a key to a different
+// * key if both a WM_KEYDOWN and a WM_CHAR will be issued.
+// * To avoid the extra SWT.KeyDown, look for a space and
+// * issue the event from WM_CHAR.
+// */
+// if (asciiKey == ' ') return null;
+// if (asciiKey != wParam) return null;
+// /*
+// * Feature in Windows. The virtual key VK_CANCEL is treated
+// * as both a virtual key and ASCII key by Windows. This
+// * means that a WM_CHAR with WPARAM=3 will be issued for
+// * this key. To avoid the extra SWT.KeyDown, look for
+// * VK_CANCEL and issue the event from WM_CHAR.
+// */
+// if (wParam == OS.VK_CANCEL) return null;
+// }
+//
+// /*
+// * If the control key is not down at this point, then
+// * the key that was pressed was an accent key or a regular
+// * key such as 'A' or Shift+A. In that case, issue the
+// * key event from WM_CHAR.
+// */
+// if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return null;
+//
+// /*
+// * Get the shifted state or convert to lower case if necessary.
+// * If the user types Ctrl+A, LastAscii should be 'a', not 'A'.
+// * If the user types Ctrl+Shift+A, LastAscii should be 'A'.
+// * If the user types Ctrl+Shift+6, the value of LastAscii will
+// * depend on the international keyboard.
+// */
+// if (OS.GetKeyState (OS.VK_SHIFT) < 0) {
+// display.lastAscii = display.shiftedKey (wParam);
+// if (display.lastAscii == 0) display.lastAscii = mapKey;
+// } else {
+// display.lastAscii = OS.CharLower ((short) mapKey);
+// }
+//
+// /* Note that Ctrl+'@' is ASCII NUL and is delivered in WM_CHAR */
+// if (display.lastAscii == '@') return null;
+// display.lastAscii = display.controlKey (display.lastAscii);
+// }
+// if (!sendKeyEvent (SWT.KeyDown, OS.WM_KEYDOWN, wParam, lParam)) {
+// return LRESULT.ONE;
+// }
+// // widget could be disposed at this point
+// return null;
+//}
+//
+//LRESULT wmKeyUp (int hwnd, int wParam, int lParam) {
+// Display display = this.display;
+//
+// /* Check for hardware keys */
+// if (OS.IsWinCE) {
+// if (OS.VK_APP1 <= wParam && wParam <= OS.VK_APP6) {
+// display.lastKey = display.lastAscii = 0;
+// display.lastVirtual = display.lastNull = display.lastDead = false;
+// Event event = new Event ();
+// event.detail = wParam - OS.VK_APP1 + 1;
+// /* Check the bit 30 to get the key state */
+// int type = (lParam & 0x40000000) != 0 ? SWT.HardKeyUp : SWT.HardKeyDown;
+// if (setInputState (event, type)) sendEvent (type, event);
+// // widget could be disposed at this point
+// return null;
+// }
+// }
+//
+// /*
+// * If the key up is not hooked, reset last key
+// * and last ascii in case the key down is hooked.
+// */
+// if (!hooks (SWT.KeyUp) && !display.filters (SWT.KeyUp)) {
+// display.lastKey = display.lastAscii = 0;
+// display.lastVirtual = display.lastNull = display.lastDead = false;
+// return null;
+// }
+//
+// /* Map the virtual key. */
+// /*
+// * Bug in WinCE. MapVirtualKey() returns incorrect values.
+// * The fix is to rely on a key mappings table to determine
+// * whether the key event must be sent now or if a WM_CHAR
+// * event will follow. The key mappings table maps virtual
+// * keys to SWT key codes and does not contain mappings for
+// * Windows virtual keys like VK_A. Virtual keys that are
+// * both virtual and ASCII are a special case.
+// */
+// int mapKey = 0;
+// if (OS.IsWinCE) {
+// switch (wParam) {
+// case OS.VK_BACK: mapKey = SWT.BS; break;
+// case OS.VK_RETURN: mapKey = SWT.CR; break;
+// case OS.VK_DELETE: mapKey = SWT.DEL; break;
+// case OS.VK_ESCAPE: mapKey = SWT.ESC; break;
+// case OS.VK_TAB: mapKey = SWT.TAB; break;
+// }
+// } else {
+// mapKey = OS.MapVirtualKey (wParam, 2);
+// }
+//
+// /*
+// * Bug in Windows 95 and NT. When the user types an accent key such
+// * as ^ to get an accented character on a German keyboard, the accent
+// * key should be ignored and the next key that the user types is the
+// * accented key. The fix is to detect the accent key stroke (called
+// * a dead key) by testing the high bit of the value returned by
+// * MapVirtualKey (). A further problem is that the high bit on
+// * Windows NT is bit 32 while the high bit on Windows 95 is bit 16.
+// * They should both be bit 32.
+// */
+// if (OS.IsWinNT) {
+// if ((mapKey & 0x80000000) != 0) return null;
+// } else {
+// if ((mapKey & 0x8000) != 0) return null;
+// }
+// if (display.lastDead) return null;
+//
+// /*
+// * NOTE: On Windows 98, keypad keys are virtual despite the
+// * fact that a WM_CHAR is issued. On Windows 2000 and XP,
+// * they are not virtual. Therefore it is necessary to force
+// * numeric keypad keys to be virtual.
+// */
+// display.lastVirtual = mapKey == 0 || display.numpadKey (wParam) != 0;
+// if (display.lastVirtual) {
+// display.lastKey = wParam;
+// } else {
+// /*
+// * Feature in Windows. The virtual key VK_CANCEL is treated
+// * as both a virtual key and ASCII key by Windows. This
+// * means that a WM_CHAR with WPARAM=3 will be issued for
+// * this key. In order to distingush between this key and
+// * Ctrl+C, mark the key as virtual.
+// */
+// if (wParam == OS.VK_CANCEL) display.lastVirtual = true;
+// if (display.lastKey == 0) {
+// display.lastAscii = 0;
+// display.lastNull = display.lastDead = false;
+// return null;
+// }
+// }
+// LRESULT result = null;
+// if (!sendKeyEvent (SWT.KeyUp, OS.WM_KEYUP, wParam, lParam)) {
+// result = LRESULT.ONE;
+// }
+// // widget could be disposed at this point
+// display.lastKey = display.lastAscii = 0;
+// display.lastVirtual = display.lastNull = display.lastDead = false;
+// return result;
+//}
+//
+//LRESULT wmKillFocus (int hwnd, int wParam, int lParam) {
+// int code = callWindowProc (hwnd, OS.WM_KILLFOCUS, wParam, lParam);
+// sendFocusEvent (SWT.FocusOut);
+// // widget could be disposed at this point
+//
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the focus
+// * or deactivate events. If this happens, end the
+// * processing of the Windows message by returning
+// * zero as the result of the window proc.
+// */
+// if (isDisposed ()) return LRESULT.ZERO;
+// if (code == 0) return LRESULT.ZERO;
+// return new LRESULT (code);
+//}
+//
+//LRESULT wmLButtonDblClk (int hwnd, int wParam, int lParam) {
+// /*
+// * Feature in Windows. Windows sends the following
+// * messages when the user double clicks the mouse:
+// *
+// * WM_LBUTTONDOWN - mouse down
+// * WM_LBUTTONUP - mouse up
+// * WM_LBUTTONDBLCLK - double click
+// * WM_LBUTTONUP - mouse up
+// *
+// * Applications that expect matching mouse down/up
+// * pairs will not see the second mouse down. The
+// * fix is to send a mouse down event.
+// */
+// sendMouseEvent (SWT.MouseDown, 1, hwnd, OS.WM_LBUTTONDOWN, wParam, lParam);
+// sendMouseEvent (SWT.MouseDoubleClick, 1, hwnd, OS.WM_LBUTTONDBLCLK, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_LBUTTONDBLCLK, wParam, lParam);
+// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd);
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmLButtonDown (int hwnd, int wParam, int lParam) {
+// boolean dragging = false, mouseDown = true;
+// boolean dragDetect = hooks (SWT.DragDetect);
+// if (dragDetect) {
+// if (!OS.IsWinCE) {
+// /*
+// * Feature in Windows. It's possible that the drag
+// * operation will not be started while the mouse is
+// * down, meaning that the mouse should be captured.
+// * This can happen when the user types the ESC key
+// * to cancel the drag. The fix is to query the state
+// * of the mouse and capture the mouse accordingly.
+// */
+// POINT pt = new POINT ();
+// pt.x = (short) (lParam & 0xFFFF);
+// pt.y = (short) (lParam >> 16);
+// OS.ClientToScreen (hwnd, pt);
+// dragging = OS.DragDetect (hwnd, pt);
+// mouseDown = OS.GetKeyState (OS.VK_LBUTTON) < 0;
+// }
+// }
+// sendMouseEvent (SWT.MouseDown, 1, hwnd, OS.WM_LBUTTONDOWN, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_LBUTTONDOWN, wParam, lParam);
+// if (OS.IsPPC) {
+// /*
+// * Note: On WinCE PPC, only attempt to recognize the gesture for
+// * a context menu when the control contains a valid menu or there
+// * are listeners for the MenuDetect event.
+// */
+// Menu menu = getMenu ();
+// boolean hasMenu = menu != null && !menu.isDisposed ();
+// if (hasMenu || hooks (SWT.MenuDetect)) {
+// int x = (short) (lParam & 0xFFFF);
+// int y = (short) (lParam >> 16);
+// SHRGINFO shrg = new SHRGINFO ();
+// shrg.cbSize = SHRGINFO.sizeof;
+// shrg.hwndClient = hwnd;
+// shrg.ptDown_x = x;
+// shrg.ptDown_y = y;
+// shrg.dwFlags = OS.SHRG_RETURNCMD;
+// int type = OS.SHRecognizeGesture (shrg);
+// if (type == OS.GN_CONTEXTMENU) showMenu (x, y);
+// }
+// }
+// if (mouseDown) {
+// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd);
+// }
+// if (dragging) {
+// Event event = new Event ();
+// event.x = (short) (lParam & 0xFFFF);
+// event.y = (short) (lParam >> 16);
+// postEvent (SWT.DragDetect, event);
+// } else {
+// if (dragDetect) {
+// /*
+// * Feature in Windows. DragDetect() captures the mouse
+// * and tracks its movement until the user releases the
+// * left mouse button, presses the ESC key, or moves the
+// * mouse outside the drag rectangle. If the user moves
+// * the mouse outside of the drag rectangle, DragDetect()
+// * returns true and a drag and drop operation can be
+// * started. When the left mouse button is released or
+// * the ESC key is pressed, these events are consumed by
+// * DragDetect() so that application code that matches
+// * mouse down/up pairs or looks for the ESC key will not
+// * function properly. The fix is to send the missing
+// * events when the drag has not started.
+// *
+// * NOTE: For now, don't send a fake WM_KEYDOWN/WM_KEYUP
+// * events for the ESC key. This would require computing
+// * wParam (the key) and lParam (the repeat count, scan code,
+// * extended-key flag, context code, previous key-state flag,
+// * and transition-state flag) which is non-trivial.
+// */
+// if (OS.GetKeyState (OS.VK_ESCAPE) >= 0) {
+// OS.SendMessage (hwnd, OS.WM_LBUTTONUP, wParam, lParam);
+// }
+// }
+// }
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmLButtonUp (int hwnd, int wParam, int lParam) {
+// sendMouseEvent (SWT.MouseUp, 1, hwnd, OS.WM_LBUTTONUP, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_LBUTTONUP, wParam, lParam);
+// int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON | OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
+// if (((wParam & 0xFFFF) & mask) == 0) {
+// if (OS.GetCapture () == hwnd) OS.ReleaseCapture ();
+// }
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmMButtonDblClk (int hwnd, int wParam, int lParam) {
+// /*
+// * Feature in Windows. Windows sends the following
+// * messages when the user double clicks the mouse:
+// *
+// * WM_MBUTTONDOWN - mouse down
+// * WM_MBUTTONUP - mouse up
+// * WM_MLBUTTONDBLCLK - double click
+// * WM_MBUTTONUP - mouse up
+// *
+// * Applications that expect matching mouse down/up
+// * pairs will not see the second mouse down. The
+// * fix is to send a mouse down event.
+// */
+// sendMouseEvent (SWT.MouseDown, 2, hwnd, OS.WM_MBUTTONDOWN, wParam, lParam);
+// sendMouseEvent (SWT.MouseDoubleClick, 2, hwnd, OS.WM_MBUTTONDBLCLK, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_MBUTTONDBLCLK, wParam, lParam);
+// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd);
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmMButtonDown (int hwnd, int wParam, int lParam) {
+// sendMouseEvent (SWT.MouseDown, 2, hwnd, OS.WM_MBUTTONDOWN, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_MBUTTONDOWN, wParam, lParam);
+// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd);
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmMButtonUp (int hwnd, int wParam, int lParam) {
+// sendMouseEvent (SWT.MouseUp, 2, hwnd, OS.WM_MBUTTONUP, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_MBUTTONUP, wParam, lParam);
+// int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON | OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
+// if (((wParam & 0xFFFF) & mask) == 0) {
+// if (OS.GetCapture () == hwnd) OS.ReleaseCapture ();
+// }
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmMouseHover (int hwnd, int wParam, int lParam) {
+// sendMouseEvent (SWT.MouseHover, 0, hwnd, OS.WM_MOUSEHOVER, wParam, lParam);
+// return null;
+//}
+//
+//LRESULT wmMouseLeave (int hwnd, int wParam, int lParam) {
+// if (!hooks (SWT.MouseExit) && !filters (SWT.MouseExit)) return null;
+// int pos = OS.GetMessagePos ();
+// POINT pt = new POINT ();
+// pt.x = (short) (pos & 0xFFFF);
+// pt.y = (short) (pos >> 16);
+// OS.ScreenToClient (hwnd, pt);
+// lParam = pt.x | (pt.y << 16);
+// sendMouseEvent (SWT.MouseExit, 0, hwnd, OS.WM_MOUSELEAVE, wParam, lParam);
+// return null;
+//}
+//
+//LRESULT wmMouseMove (int hwnd, int wParam, int lParam) {
+// int pos = OS.GetMessagePos ();
+// if (pos != display.lastMouse) {
+// if (!OS.IsWinCE) {
+// boolean mouseEnter = hooks (SWT.MouseEnter) || display.filters (SWT.MouseEnter);
+// boolean mouseExit = hooks (SWT.MouseExit) || display.filters (SWT.MouseExit);
+// boolean mouseHover = hooks (SWT.MouseHover) || display.filters (SWT.MouseHover);
+// if (mouseEnter || mouseExit || mouseHover) {
+// TRACKMOUSEEVENT lpEventTrack = new TRACKMOUSEEVENT ();
+// lpEventTrack.cbSize = TRACKMOUSEEVENT.sizeof;
+// lpEventTrack.dwFlags = OS.TME_QUERY;
+// lpEventTrack.hwndTrack = hwnd;
+// OS.TrackMouseEvent (lpEventTrack);
+// if (lpEventTrack.dwFlags == 0) {
+// lpEventTrack.dwFlags = OS.TME_LEAVE | OS.TME_HOVER;
+// lpEventTrack.hwndTrack = hwnd;
+// OS.TrackMouseEvent (lpEventTrack);
+// if (mouseEnter) {
+// /*
+// * Force all outstanding WM_MOUSELEAVE messages to be dispatched before
+// * issuing a mouse enter. This causes mouse exit events to be processed
+// * before mouse enter events. Note that WM_MOUSELEAVE is posted to the
+// * event queue by TrackMouseEvent().
+// */
+// MSG msg = new MSG ();
+// int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
+// while (OS.PeekMessage (msg, 0, OS.WM_MOUSELEAVE, OS.WM_MOUSELEAVE, flags)) {
+// OS.TranslateMessage (msg);
+// OS.DispatchMessage (msg);
+// }
+// sendMouseEvent (SWT.MouseEnter, 0, hwnd, OS.WM_MOUSEMOVE, wParam, lParam);
+// }
+// } else {
+// lpEventTrack.dwFlags = OS.TME_HOVER;
+// OS.TrackMouseEvent (lpEventTrack);
+// }
+// }
+// }
+// display.lastMouse = pos;
+// sendMouseEvent (SWT.MouseMove, 0, hwnd, OS.WM_MOUSEMOVE, wParam, lParam);
+// }
+// return null;
+//}
+//
+//LRESULT wmMouseWheel (int hwnd, int wParam, int lParam) {
+// if (!hooks (SWT.MouseWheel) && !filters (SWT.MouseWheel)) return null;
+// int delta = wParam >> 16;
+// int [] value = new int [1];
+// int count, detail;
+// OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, value, 0);
+// if (value [0] == OS.WHEEL_PAGESCROLL) {
+// detail = SWT.SCROLL_PAGE;
+// count = delta / OS.WHEEL_DELTA;
+// } else {
+// detail = SWT.SCROLL_LINE;
+// count = value [0] * delta / OS.WHEEL_DELTA;
+// }
+// POINT pt = new POINT ();
+// pt.x = (short) (lParam & 0xFFFF);
+// pt.y = (short) (lParam >> 16);
+// OS.ScreenToClient (hwnd, pt);
+// lParam = pt.x | (pt.y << 16);
+// if (!sendMouseEvent (SWT.MouseWheel, 0, count, detail, true, hwnd, OS.WM_MOUSEWHEEL, wParam, lParam)) {
+// return LRESULT.ZERO;
+// }
+// return null;
+//}
+//
+//LRESULT wmPaint (int hwnd, int wParam, int lParam) {
+//
+// /* Exit early - don't draw the background */
+// if (!hooks (SWT.Paint) && !filters (SWT.Paint)) {
+// return null;
+// }
+//
+// /* Get the damage */
+// int result = 0;
+// if (OS.IsWinCE) {
+// RECT rect = new RECT ();
+// OS.GetUpdateRect (hwnd, rect, false);
+// result = callWindowProc (hwnd, OS.WM_PAINT, wParam, lParam);
+// OS.InvalidateRect (hwnd, rect, false);
+// } else {
+// int rgn = OS.CreateRectRgn (0, 0, 0, 0);
+// OS.GetUpdateRgn (hwnd, rgn, false);
+// result = callWindowProc (hwnd, OS.WM_PAINT, wParam, lParam);
+// /*
+// * Bug in Windows. When InvalidateRgn(), InvalidateRect()
+// * or RedrawWindow() with RDW_INVALIDATE is called from
+// * within WM_PAINT to invalidate a region for a further
+// * BeginPaint(), the caret is not properly erased causing
+// * pixel corruption. The fix is to hide and show the
+// * caret.
+// */
+// OS.HideCaret (hwnd);
+// OS.InvalidateRgn (hwnd, rgn, false);
+// OS.ShowCaret (hwnd);
+// OS.DeleteObject (rgn);
+// }
+//
+// /* Send the paint event */
+// PAINTSTRUCT ps = new PAINTSTRUCT ();
+// GCData data = new GCData ();
+// data.ps = ps;
+// data.hwnd = hwnd;
+// GC gc = new_GC (data);
+// if (gc != null) {
+// int width = ps.right - ps.left;
+// int height = ps.bottom - ps.top;
+// if (width != 0 && height != 0) {
+// Event event = new Event ();
+// event.gc = gc;
+// event.x = ps.left;
+// event.y = ps.top;
+// event.width = width;
+// event.height = height;
+// sendEvent (SWT.Paint, event);
+// // widget could be disposed at this point
+// event.gc = null;
+// }
+// gc.dispose ();
+// }
+// if (result == 0) return LRESULT.ZERO;
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmRButtonDblClk (int hwnd, int wParam, int lParam) {
+// /*
+// * Feature in Windows. Windows sends the following
+// * messages when the user double clicks the mouse:
+// *
+// * WM_RBUTTONDOWN - mouse down
+// * WM_RBUTTONUP - mouse up
+// * WM_RBUTTONDBLCLK - double click
+// * WM_LBUTTONUP - mouse up
+// *
+// * Applications that expect matching mouse down/up
+// * pairs will not see the second mouse down. The
+// * fix is to send a mouse down event.
+// */
+// sendMouseEvent (SWT.MouseDown, 3, hwnd, OS.WM_RBUTTONDOWN, wParam, lParam);
+// sendMouseEvent (SWT.MouseDoubleClick, 3, hwnd, OS.WM_RBUTTONDBLCLK, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_RBUTTONDBLCLK, wParam, lParam);
+// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd);
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmRButtonDown (int hwnd, int wParam, int lParam) {
+// sendMouseEvent (SWT.MouseDown, 3, hwnd, OS.WM_RBUTTONDOWN, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_RBUTTONDOWN, wParam, lParam);
+// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd);
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmRButtonUp (int hwnd, int wParam, int lParam) {
+// sendMouseEvent (SWT.MouseUp, 3, hwnd, OS.WM_RBUTTONUP, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_RBUTTONUP, wParam, lParam);
+// int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON | OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
+// if (((wParam & 0xFFFF) & mask) == 0) {
+// if (OS.GetCapture () == hwnd) OS.ReleaseCapture ();
+// }
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmSetFocus (int hwnd, int wParam, int lParam) {
+// int code = callWindowProc (hwnd, OS.WM_SETFOCUS, wParam, lParam);
+// sendFocusEvent (SWT.FocusIn);
+// // widget could be disposed at this point
+//
+// /*
+// * It is possible (but unlikely), that application
+// * code could have disposed the widget in the focus
+// * or activate events. If this happens, end the
+// * processing of the Windows message by returning
+// * zero as the result of the window proc.
+// */
+// if (isDisposed ()) return LRESULT.ZERO;
+// if (code == 0) return LRESULT.ZERO;
+// return new LRESULT (code);
+//}
+//
+//LRESULT wmSysChar (int hwnd, int wParam, int lParam) {
+// Display display = this.display;
+// display.lastAscii = wParam;
+// display.lastNull = wParam == 0;
+//
+// /* Do not issue a key down if a menu bar mnemonic was invoked */
+// if (!hooks (SWT.KeyDown) && !display.filters (SWT.KeyDown)) {
+// return null;
+// }
+//
+// /* Call the window proc to determine whether it is a system key or mnemonic */
+// boolean oldKeyHit = display.mnemonicKeyHit;
+// display.mnemonicKeyHit = true;
+// int result = callWindowProc (hwnd, OS.WM_SYSCHAR, wParam, lParam);
+// boolean consumed = false;
+// if (!display.mnemonicKeyHit) {
+// consumed = !sendKeyEvent (SWT.KeyDown, OS.WM_SYSCHAR, wParam, lParam);
+// // widget could be disposed at this point
+// }
+// consumed |= display.mnemonicKeyHit;
+// display.mnemonicKeyHit = oldKeyHit;
+// return consumed ? LRESULT.ONE : new LRESULT (result);
+//}
+//
+//LRESULT wmSysKeyDown (int hwnd, int wParam, int lParam) {
+// /*
+// * Feature in Windows. When WM_SYSKEYDOWN is sent,
+// * the user pressed ALT+ or F10 to get to the
+// * menu bar. In order to issue events for F10 but
+// * ignore other key presses when the ALT is not down,
+// * make sure that either F10 was pressed or that ALT
+// * is pressed.
+// */
+// if (wParam != OS.VK_F10) {
+// /* Make sure WM_SYSKEYDOWN was sent by ALT-. */
+// if ((lParam & 0x20000000) == 0) return null;
+// }
+//
+// /* Ignore well known system keys */
+// switch (wParam) {
+// case OS.VK_F4: return null;
+// }
+//
+// /* Ignore repeating modifier keys by testing key down state */
+// switch (wParam) {
+// case OS.VK_SHIFT:
+// case OS.VK_MENU:
+// case OS.VK_CONTROL:
+// case OS.VK_CAPITAL:
+// case OS.VK_NUMLOCK:
+// case OS.VK_SCROLL:
+// if ((lParam & 0x40000000) != 0) return null;
+// }
+//
+// /* Clear last key and last ascii because a new key has been typed */
+// display.lastAscii = display.lastKey = 0;
+// display.lastVirtual = display.lastNull = display.lastDead = false;
+//
+// /* If are going to get a WM_SYSCHAR, ignore this message. */
+// /*
+// * Bug in WinCE. MapVirtualKey() returns incorrect values.
+// * The fix is to rely on a key mappings table to determine
+// * whether the key event must be sent now or if a WM_CHAR
+// * event will follow. The key mappings table maps virtual
+// * keys to SWT key codes and does not contain mappings for
+// * Windows virtual keys like VK_A. Virtual keys that are
+// * both virtual and ASCII are a special case.
+// */
+// int mapKey = 0;
+// if (OS.IsWinCE) {
+// switch (wParam) {
+// case OS.VK_BACK: mapKey = SWT.BS; break;
+// case OS.VK_RETURN: mapKey = SWT.CR; break;
+// case OS.VK_DELETE: mapKey = SWT.DEL; break;
+// case OS.VK_ESCAPE: mapKey = SWT.ESC; break;
+// case OS.VK_TAB: mapKey = SWT.TAB; break;
+// }
+// } else {
+// mapKey = OS.MapVirtualKey (wParam, 2);
+// }
+// display.lastVirtual = mapKey == 0 || display.numpadKey (wParam) != 0;
+// if (display.lastVirtual) {
+// display.lastKey = wParam;
+// /*
+// * Feature in Windows. The virtual key VK_DELETE is not
+// * treated as both a virtual key and an ASCII key by Windows.
+// * Therefore, we will not receive a WM_SYSCHAR for this key.
+// * The fix is to treat VK_DELETE as a special case and map
+// * the ASCII value explictly (Delete is 0x7F).
+// */
+// if (display.lastKey == OS.VK_DELETE) display.lastAscii = 0x7F;
+//
+// /* When a keypad key is typed, a WM_SYSCHAR is not issued */
+// if (OS.VK_NUMPAD0 <= display.lastKey && display.lastKey <= OS.VK_DIVIDE) {
+// display.lastAscii = display.numpadKey (display.lastKey);
+// }
+// } else {
+// /*
+// * Convert LastKey to lower case because Windows non-virtual
+// * keys that are also ASCII keys, such as like VK_A, are have
+// * upper case values in WM_SYSKEYDOWN despite the fact that the
+// * Shift was not pressed.
+// */
+// display.lastKey = OS.CharLower ((short) mapKey);
+//
+// /*
+// * Feature in Windows 98. MapVirtualKey() indicates that
+// * a WM_SYSCHAR message will occur for Alt+Enter but
+// * this message never happens. The fix is to issue the
+// * event from WM_SYSKEYDOWN and map VK_RETURN to '\r'.
+// */
+// if (OS.IsWinNT) return null;
+// if (wParam != OS.VK_RETURN) return null;
+// display.lastAscii = '\r';
+// }
+//
+// if (!sendKeyEvent (SWT.KeyDown, OS.WM_SYSKEYDOWN, wParam, lParam)) {
+// return LRESULT.ONE;
+// }
+// // widget could be disposed at this point
+// return null;
+//}
+//
+//LRESULT wmSysKeyUp (int hwnd, int wParam, int lParam) {
+// return wmKeyUp (hwnd, wParam, lParam);
+//}
+//
+//LRESULT wmXButtonDblClk (int hwnd, int wParam, int lParam) {
+// /*
+// * Feature in Windows. Windows sends the following
+// * messages when the user double clicks the mouse:
+// *
+// * WM_XBUTTONDOWN - mouse down
+// * WM_XBUTTONUP - mouse up
+// * WM_XLBUTTONDBLCLK - double click
+// * WM_XBUTTONUP - mouse up
+// *
+// * Applications that expect matching mouse down/up
+// * pairs will not see the second mouse down. The
+// * fix is to send a mouse down event.
+// */
+// int button = (wParam >> 16 == OS.XBUTTON1) ? 4 : 5;
+// sendMouseEvent (SWT.MouseDown, button, hwnd, OS.WM_XBUTTONDOWN, wParam, lParam);
+// sendMouseEvent (SWT.MouseDoubleClick, button, hwnd, OS.WM_XBUTTONDBLCLK, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_XBUTTONDBLCLK, wParam, lParam);
+// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd);
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmXButtonDown (int hwnd, int wParam, int lParam) {
+// int button = (wParam >> 16 == OS.XBUTTON1) ? 4 : 5;
+// sendMouseEvent (SWT.MouseDown, button, hwnd, OS.WM_XBUTTONDOWN, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_XBUTTONDOWN, wParam, lParam);
+// if (OS.GetCapture () != hwnd) OS.SetCapture (hwnd);
+// return new LRESULT (result);
+//}
+//
+//LRESULT wmXButtonUp (int hwnd, int wParam, int lParam) {
+// int button = (wParam >> 16 == OS.XBUTTON1) ? 4 : 5;
+// sendMouseEvent (SWT.MouseUp, button, hwnd, OS.WM_XBUTTONUP, wParam, lParam);
+// int result = callWindowProc (hwnd, OS.WM_XBUTTONUP, wParam, lParam);
+// int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON | OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
+// if (((wParam & 0xFFFF) & mask) == 0) {
+// if (OS.GetCapture () == hwnd) OS.ReleaseCapture ();
+// }
+// return new LRESULT (result);
+//
+public void reskin(int flags) {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+void reskinChildren (int flags) {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+void reskinWidget() {
+ throw new UnsupportedOperationException("Not implemented yet");
+}
+}
diff --git a/examples/org.eclipse.swt.snippets/.classpath_swing b/examples/org.eclipse.swt.snippets/.classpath_swing
new file mode 100644
index 00000000000..327658cb814
--- /dev/null
+++ b/examples/org.eclipse.swt.snippets/.classpath_swing
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/examples/org.eclipse.swt.snippets/.project b/examples/org.eclipse.swt.snippets/.project
index e84855c94e0..0883ce95177 100644
--- a/examples/org.eclipse.swt.snippets/.project
+++ b/examples/org.eclipse.swt.snippets/.project
@@ -26,6 +26,11 @@
org.eclipse.pde.PluginNature
+
+ .classpath
+ 1
+ PROJECT_LOC/.classpath_swing
+
.settings/org.eclipse.jdt.core.prefs1