Mercurial > projects > dwt-mac
diff dwt/widgets/Widget.d @ 0:380af2bdd8e5
Upload of whole dwt tree
author | Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com> |
---|---|
date | Sat, 09 Aug 2008 17:00:02 +0200 |
parents | |
children | 1a8b3cb347e0 f565d3a95c0a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/widgets/Widget.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,1270 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 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 + *******************************************************************************/ +module dwt.widgets.Widget; + +import dwt.dwthelper.utils; + + +import dwt.DWT; +import dwt.DWTException; +import dwt.events.DisposeListener; +import dwt.internal.DWTEventListener; +import dwt.internal.cocoa.NSEvent; +import dwt.internal.cocoa.NSRect; +import dwt.internal.cocoa.OS; +import dwt.internal.cocoa.objc_super; + + +/** + * 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. + * <dl> + * <dt><b>Styles:</b></dt> + * <dd>(none)</dd> + * <dt><b>Events:</b></dt> + * <dd>Dispose</dd> + * </dl> + * <p> + * IMPORTANT: This class is intended to be subclassed <em>only</em> + * within the DWT implementation. However, it has not been marked + * final to allow those outside of the DWT 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. + * </p> + * + * @see #checkSubclass + */ +public abstract class Widget { + int style, state; + Display display; + EventTable eventTable; + Object data; + + int jniRef; + + /* 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; + static final int GRAB = 1 << 5; + static final int MOVED = 1 << 6; + static final int RESIZED = 1 << 7; + static final int EXPANDING = 1 << 8; + static final int IGNORE_WHEEL = 1 << 9; + static final int PARENT_BACKGROUND = 1 << 10; + static final int THEME_BACKGROUND = 1 << 11; + + /* A layout was requested on this widget */ + static final int LAYOUT_NEEDED = 1<<12; + + /* The preferred size of a child has changed */ + static final int LAYOUT_CHANGED = 1<<13; + + /* A layout was requested in this widget hierachy */ + static final int LAYOUT_CHILD = 1<<14; + + /* More global state flags */ + static final int RELEASED = 1<<15; + static final int DISPOSE_SENT = 1<<16; + static final int FOREIGN_HANDLE = 1<<17; + static final int DRAG_DETECT = 1<<18; + + /* Safari fixes */ + static final int SAFARI_EVENTS_FIX = 1<<19; + static final String SAFARI_EVENTS_FIX_KEY = "dwt.internal.safariEventsFix"; //$NON-NLS-1$ + + /* Default size for widgets */ + static final int DEFAULT_WIDTH = 64; + static final int DEFAULT_HEIGHT = 64; + +Widget () { + /* Do nothing */ +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + * <p> + * The style value is either one of the style constants defined in + * class <code>DWT</code> which is applicable to instances of this + * class, or must be built by <em>bitwise OR</em>'ing together + * (that is, using the <code>int</code> "|" operator) two or more + * of those <code>DWT</code> style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + * </p> + * + * @param parent a widget which will be the parent of the new instance (cannot be null) + * @param style the style of widget to construct + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> + * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> + * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> + * </ul> + * + * @see DWT + * @see #checkSubclass + * @see #getStyle + */ +public Widget (Widget parent, int style) { + checkSubclass (); + checkParent (parent); + this.style = style; + display = parent.display; +} + +void callSuper(int id, int selector, int arg0) { + objc_super super_struct = new objc_super(); + super_struct.receiver = id; + super_struct.cls = OS.objc_msgSend(id, OS.sel_superclass); + OS.objc_msgSendSuper(super_struct, selector, arg0); +} + +bool acceptsFirstResponder () { + return false; +} + +bool becomeFirstResponder () { + return true; +} + +bool resignFirstResponder () { + return true; +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when an event of the given type occurs. When the + * event does occur in the widget, the listener is notified by + * sending it the <code>handleEvent()</code> message. The event + * type is one of the event constants defined in class <code>DWT</code>. + * + * @param eventType the type of event to listen for + * @param listener the listener which should be notified when the event occurs + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see Listener + * @see DWT + * @see #removeListener(int, Listener) + * @see #notifyListeners + */ +public void addListener (int eventType, Listener listener) { + checkWidget(); + if (listener is null) error (DWT.ERROR_NULL_ARGUMENT); + _addListener (eventType, listener); +} + +void _addListener (int eventType, Listener listener) { + if (eventTable is null) eventTable = new EventTable (); + eventTable.hook (eventType, listener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the widget is disposed. When the widget is + * disposed, the listener is notified by sending it the + * <code>widgetDisposed()</code> message. + * + * @param listener the listener which should be notified when the receiver is disposed + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see DisposeListener + * @see #removeDisposeListener + */ +public void addDisposeListener (DisposeListener listener) { + checkWidget(); + if (listener is null) error (DWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (DWT.Dispose, typedListener); +} + +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) is 0) style |= int0; + if ((style & int0) !is 0) style = (style & ~mask) | int0; + if ((style & int1) !is 0) style = (style & ~mask) | int1; + if ((style & int2) !is 0) style = (style & ~mask) | int2; + if ((style & int3) !is 0) style = (style & ~mask) | int3; + if ((style & int4) !is 0) style = (style & ~mask) | int4; + if ((style & int5) !is 0) style = (style & ~mask) | int5; + return style; +} + +void checkOpen () { + /* Do nothing */ +} + +void checkOrientation (Widget parent) { + style &= ~DWT.MIRRORED; + if ((style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT)) is 0) { + if (parent !is null) { + if ((parent.style & DWT.LEFT_TO_RIGHT) !is 0) style |= DWT.LEFT_TO_RIGHT; + if ((parent.style & DWT.RIGHT_TO_LEFT) !is 0) style |= DWT.RIGHT_TO_LEFT; + } + } + style = checkBits (style, DWT.LEFT_TO_RIGHT, DWT.RIGHT_TO_LEFT, 0, 0, 0, 0); +} + +void checkParent (Widget parent) { + if (parent is null) error (DWT.ERROR_NULL_ARGUMENT); + if (parent.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); + parent.checkWidget (); + parent.checkOpen (); +} + +/** + * Checks that this class can be subclassed. + * <p> + * The DWT class library is intended to be subclassed + * only at specific, controlled points (most notably, + * <code>Composite</code> and <code>Canvas</code> when + * implementing new widgets). This method enforces this + * rule unless it is overridden. + * </p><p> + * <em>IMPORTANT:</em> 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 DWT releases and will be + * strongly platform specific. No support is provided for + * user-written classes which are implemented in this fashion. + * </p><p> + * The ability to subclass outside of the allowed DWT classes + * is intended purely to enable those not on the DWT 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. + * </p> + * + * @exception DWTException <ul> + * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> + * </ul> + */ +protected void checkSubclass () { + if (!isValidSubclass ()) error (DWT.ERROR_INVALID_SUBCLASS); +} + +/** + * Throws an <code>DWTException</code> 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 <em>should</em> be called by + * widget implementors to enforce the standard DWT invariants. + * <p> + * Currently, it is an error to invoke any method (other than + * <code>isDisposed()</code>) on a widget that has had its + * <code>dispose()</code> method called. It is also an error + * to call widget methods from any thread that is different + * from the thread that created the widget. + * </p><p> + * In future releases of DWT, there may be more or fewer error + * checks and exceptions may be thrown for different reasons. + * </p> + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +protected void checkWidget () { + Display display = this.display; + if (display is null) error (DWT.ERROR_WIDGET_DISPOSED); + if (display.thread !is Thread.currentThread ()) error (DWT.ERROR_THREAD_INVALID_ACCESS); + if ((state & DISPOSED) !is 0) error (DWT.ERROR_WIDGET_DISPOSED); +} + +bool clickOnLink(int textView, int link, int charIndex) { + return true; +} + +void comboBoxSelectionDidChange(int notification) { +} + +void createHandle () { +} + +void createJNIRef () { + jniRef = OS.NewGlobalRef(this); + if (jniRef is 0) error (DWT.ERROR_NO_HANDLES); +} + +void createWidget () { + createJNIRef (); + createHandle (); +} + +void destroyWidget () { + releaseHandle (); +} + +/** + * Disposes of the operating system resources associated with + * the receiver and all its descendants. After this method has + * been invoked, the receiver and all descendants will answer + * <code>true</code> when sent the message <code>isDisposed()</code>. + * Any internal connections between the widgets in the tree will + * have been removed to facilitate garbage collection. + * <p> + * NOTE: This method is not called recursively on the descendants + * 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 <code>Dispose</code> + * event. + * </p> + * + * @exception DWTException <ul> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @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 (DWT.ERROR_THREAD_INVALID_ACCESS); + release (true); +} + +void drawBackground (int control, int context) { + /* Do nothing */ +} + +void drawRect(int id, NSRect rect) { + objc_super super_struct = new objc_super(); + super_struct.receiver = id; + super_struct.cls = OS.objc_msgSend(id, OS.sel_superclass); + OS.objc_msgSendSuper(super_struct, OS.sel_drawRect_1, rect); +} + +void drawWidget (int control, int context, int damageRgn, int visibleRgn, int theEvent) { +} + +void error (int code) { + DWT.error(code); +} + +bool filters (int eventType) { + return display.filters (eventType); +} + +int fixMnemonic (char [] buffer) { + int i=0, j=0; + while (i < buffer.length) { + if ((buffer [j++] = buffer [i++]) is '&') { + if (i is buffer.length) {continue;} + if (buffer [i] is '&') {i++; continue;} + j--; + } + } + return j; +} + +/** + * Returns the application defined widget data associated + * with the receiver, or null if it has not been set. The + * <em>widget data</em> is a single, unnamed field that is + * stored with every widget. + * <p> + * 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. + * </p> + * + * @return the widget data + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - when the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread</li> + * </ul> + * + * @see #setData(Object) + */ +public Object getData () { + checkWidget(); + return (state & KEYED_DATA) !is 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. + * <p> + * 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. + * </p> + * + * @param key the name of the property + * @return the value of the property or null if it has not been set + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the key is null</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see #setData(String, Object) + */ +public Object getData (String key) { + checkWidget(); + if (key is null) error (DWT.ERROR_NULL_ARGUMENT); + if ((state & KEYED_DATA) !is 0) { + Object [] table = (Object []) data; + for (int i=1; i<table.length; i+=2) { + if (key.equals (table [i])) return table [i+1]; + } + } + return null; +} + +/** + * Returns the <code>Display</code> that is associated with + * the receiver. + * <p> + * A widget's display is either provided when it is created + * (for example, top level <code>Shell</code>s) or is the + * same as its parent's display. + * </p> + * + * @return the receiver's display + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * </ul> + */ +public Display getDisplay () { + Display display = this.display; + if (display is null) error (DWT.ERROR_WIDGET_DISPOSED); + return display; +} + +/** + * Returns an array of listeners who will be notified when an event + * of the given type occurs. The event type is one of the event constants + * defined in class <code>DWT</code>. + * + * @param eventType the type of event to listen for + * @return an array of listeners that will be notified when the event occurs + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see Listener + * @see DWT + * @see #addListener(int, Listener) + * @see #removeListener(int, Listener) + * @see #notifyListeners + * + * @since 3.4 + */ +public Listener[] getListeners (int eventType) { + checkWidget(); + if (eventTable is null) return new Listener[0]; + return eventTable.getListeners(eventType); +} + +String getName () { + String string = getClass ().getName (); + int index = string.lastIndexOf ('.'); + if (index is -1) return string; + return string.substring (index + 1, string.length ()); +} + +String getNameText () { + return ""; +} + +/** + * Returns the receiver's style information. + * <p> + * Note that the value which is returned by this method <em>may + * not match</em> 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 DWT widget always has scroll bars, the + * result of calling this method would always have the + * <code>DWT.H_SCROLL</code> and <code>DWT.V_SCROLL</code> bits set. + * </p> + * + * @return the style bits + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public int getStyle () { + checkWidget(); + return style; +} + +void helpRequested(int theEvent) { +} + +bool hooks (int eventType) { + if (eventTable is null) return false; + return eventTable.hooks (eventType); +} + +/** + * Returns <code>true</code> if the widget has been disposed, + * and <code>false</code> otherwise. + * <p> + * 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. + * </p> + * + * @return <code>true</code> when the widget is disposed and <code>false</code> otherwise + */ +public bool isDisposed () { + return (state & DISPOSED) !is 0; +} + +bool isFlipped () { + return true; +} + +/** + * Returns <code>true</code> if there are any listeners + * for the specified event type associated with the receiver, + * and <code>false</code> otherwise. The event type is one of + * the event constants defined in class <code>DWT</code>. + * + * @param eventType the type of event + * @return true if the event is hooked + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see DWT + */ +public bool isListening (int eventType) { + checkWidget(); + return hooks (eventType); +} + +bool isTrimHandle (int trimHandle) { + return false; +} + +bool isValidSubclass () { + return Display.isValidClass (getClass ()); +} + +bool isValidThread () { + return getDisplay ().isValidThread (); +} + +void flagsChanged(int event) { +} + +void mouseDragged(int event) { +} + +void mouseDown(int event) { +} + +void rightMouseDown(int event) { +} + +void mouseEntered(int event) { +} + +void mouseUp(int event) { +} + +int menuForEvent (int event) { + return 0; +} + +void menuNeedsUpdate(int menu) { +} + +void menu_willHighlightItem(int menu, int item) { +} + +void menuWillClose(int menu) { +} + +void menuWillOpen(int menu) { +} + +int numberOfRowsInTableView(int aTableView) { + return 0; +} + +int outlineView_child_ofItem(int outlineView, int index, int item) { + return 0; +} + +int outlineView_objectValueForTableColumn_byItem(int outlineView, int tableColumn, int item) { + return 0; +} + +bool outlineView_isItemExpandable(int outlineView, int item) { + return false; +} + +int outlineView_numberOfChildrenOfItem(int outlineView, int item) { + return 0; +} + +void outlineView_willDisplayCell_forTableColumn_item(int outlineView, int cell, int tableColumn, int item) { +} + +bool outlineView_shouldCollapseItem(int outlineView, int item) { + return false; +} + +bool outlineView_shouldExpandItem(int outlineView, int item) { + return false; +} + +void outlineViewSelectionDidChange(int notification) { +} + +void outlineView_setObjectValue_forTableColumn_byItem(int outlineView, int object, int tableColumn, int item) { +} + +/** + * Notifies all of the receiver's listeners for events + * of the given type that one such event has occurred by + * invoking their <code>handleEvent()</code> method. The + * event type is one of the event constants defined in class + * <code>DWT</code>. + * + * @param eventType the type of event which has occurred + * @param event the event data + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see DWT + * @see #addListener + * @see #removeListener(int, Listener) + */ +public void notifyListeners (int eventType, Event event) { + checkWidget(); + if (event is null) event = new Event (); + sendEvent (eventType, event); +} + +void postEvent (int eventType) { + sendEvent (eventType, null, false); +} + +void postEvent (int eventType, Event event) { + sendEvent (eventType, event, false); +} + +void release (bool destroy) { + if ((state & DISPOSE_SENT) is 0) { + state |= DISPOSE_SENT; + sendEvent (DWT.Dispose); + } + if ((state & DISPOSED) is 0) { + releaseChildren (destroy); + } + if ((state & RELEASED) is 0) { + state |= RELEASED; + if (destroy) { + releaseParent (); + releaseWidget (); + destroyWidget (); + } else { + releaseWidget (); + releaseHandle (); + } + } +} + +void releaseChildren (bool destroy) { +} + +void releaseHandle () { + state |= DISPOSED; + display = null; + if (jniRef !is 0) OS.DeleteGlobalRef(jniRef); + jniRef = 0; +} + +void releaseParent () { + /* Do nothing */ +} + +void releaseWidget () { + eventTable = null; + data = null; +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when an event of the given type occurs. The event + * type is one of the event constants defined in class <code>DWT</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 <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see Listener + * @see DWT + * @see #addListener + * @see #notifyListeners + */ +public void removeListener (int eventType, Listener handler) { + checkWidget(); + if (handler is null) error (DWT.ERROR_NULL_ARGUMENT); + if (eventTable is null) return; + eventTable.unhook (eventType, handler); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when an event of the given type occurs. + * <p> + * <b>IMPORTANT:</b> This method is <em>not</em> part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It should never be + * referenced from application code. + * </p> + * + * @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 <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see Listener + * @see #addListener + */ +protected void removeListener (int eventType, DWTEventListener handler) { + checkWidget(); + if (handler is null) error (DWT.ERROR_NULL_ARGUMENT); + if (eventTable is null) return; + eventTable.unhook (eventType, handler); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the widget is disposed. + * + * @param listener the listener which should no longer be notified when the receiver is disposed + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see DisposeListener + * @see #addDisposeListener + */ +public void removeDisposeListener (DisposeListener listener) { + checkWidget(); + if (listener is null) error (DWT.ERROR_NULL_ARGUMENT); + if (eventTable is null) return; + eventTable.unhook (DWT.Dispose, listener); +} + +void sendArrowSelection () { +} + +void sendEvent (Event event) { + Display display = event.display; + if (!display.filterEvent (event)) { + if (eventTable !is 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, bool send) { + if (eventTable is null && !display.filters (eventType)) { + return; + } + if (event is null) event = new Event (); + event.type = eventType; + event.display = display; + event.widget = this; + if (event.time is 0) { + event.time = display.getLastEventTime (); + } + if (send) { + sendEvent (event); + } else { + display.postEvent (event); + } +} + +bool sendKeyEvent (int type, int theEvent) { +// int [] length = new int [1]; +// int status = OS.GetEventParameter (theEvent, OS.kEventParamKeyUnicodes, OS.typeUnicodeText, null, 4, length, (char[])null); +// if (status is OS.noErr && length [0] > 2) { +// int count = 0; +// int [] chord = new int [1]; +// OS.GetEventParameter (theEvent, OS.kEventParamMouseChord, OS.typeUInt32, null, 4, null, chord); +// int [] modifiers = new int [1]; +// OS.GetEventParameter (theEvent, OS.kEventParamKeyModifiers, OS.typeUInt32, null, 4, null, modifiers); +// char [] chars = new char [length [0] / 2]; +// OS.GetEventParameter (theEvent, OS.kEventParamKeyUnicodes, OS.typeUnicodeText, null, chars.length * 2, null, chars); +// for (int i=0; i<chars.length; i++) { +// Event event = new Event (); +// event.character = chars [i]; +// setInputState (event, type, chord [0], modifiers [0]); +// if (sendKeyEvent (type, event)) chars [count++] = chars [i]; +// } +// if (count is 0) return false; +// if (count !is chars.length - 1) { +// OS.SetEventParameter (theEvent, OS.kEventParamKeyUnicodes, OS.typeUnicodeText, count * 2, chars); +// } +// return true; +// } else { +// Event event = new Event (); +// if (!setKeyState (event, type, theEvent)) return true; +// return sendKeyEvent (type, event); +// } + return false; +} + +bool sendKeyEvent (int type, Event event) { + sendEvent (type, event); + // widget could be disposed at this point + + /* + * It is possible (but unlikely), that application + * code could have disposed the widget in the key + * events. If this happens, end the processing of + * the key by returning false. + */ + if (isDisposed ()) return false; + return event.doit; +} + +void sendDoubleSelection() { +} + +void sendHorizontalSelection () { +} + +void sendSelection () { +} + +void sendVerticalSelection () { +} + +/** + * Sets the application defined widget data associated + * with the receiver to be the argument. The <em>widget + * data</em> is a single, unnamed field that is stored + * with every widget. + * <p> + * 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. + * </p> + * + * @param data the widget data + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - when the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread</li> + * </ul> + * + * @see #getData() + */ +public void setData (Object data) { + checkWidget(); + if (SAFARI_EVENTS_FIX_KEY.equals (data)) { + state |= SAFARI_EVENTS_FIX; + return; + } + if ((state & KEYED_DATA) !is 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. + * <p> + * 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. + * </p> + * + * @param key the name of the property + * @param value the new value for the property + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the key is null</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @see #getData(String) + */ +public void setData (String key, Object value) { + checkWidget(); + if (key is null) error (DWT.ERROR_NULL_ARGUMENT); + int index = 1; + Object [] table = null; + if ((state & KEYED_DATA) !is 0) { + table = (Object []) data; + while (index < table.length) { + if (key.equals (table [index])) break; + index += 2; + } + } + if (value !is null) { + if ((state & KEYED_DATA) !is 0) { + if (index is 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) !is 0) { + if (index !is table.length) { + int length = table.length - 2; + if (length is 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; + } + } + } + } +} + +bool setInputState (Event event, int type, int chord, int modifiers) { +// if ((chord & 0x01) !is 0) event.stateMask |= DWT.BUTTON1; +// if ((chord & 0x02) !is 0) event.stateMask |= DWT.BUTTON3; +// if ((chord & 0x04) !is 0) event.stateMask |= DWT.BUTTON2; +// if ((chord & 0x08) !is 0) event.stateMask |= DWT.BUTTON4; +// if ((chord & 0x10) !is 0) event.stateMask |= DWT.BUTTON5; +// +// if ((modifiers & OS.optionKey) !is 0) event.stateMask |= DWT.ALT; +// if ((modifiers & OS.shiftKey) !is 0) event.stateMask |= DWT.SHIFT; +// if ((modifiers & OS.controlKey) !is 0) event.stateMask |= DWT.CONTROL; +// if ((modifiers & OS.cmdKey) !is 0) event.stateMask |= DWT.COMMAND; +// switch (type) { +// case DWT.MouseDown: +// case DWT.MouseDoubleClick: +// if (event.button is 1) event.stateMask &= ~DWT.BUTTON1; +// if (event.button is 2) event.stateMask &= ~DWT.BUTTON2; +// if (event.button is 3) event.stateMask &= ~DWT.BUTTON3; +// if (event.button is 4) event.stateMask &= ~DWT.BUTTON4; +// if (event.button is 5) event.stateMask &= ~DWT.BUTTON5; +// break; +// case DWT.MouseUp: +// if (event.button is 1) event.stateMask |= DWT.BUTTON1; +// if (event.button is 2) event.stateMask |= DWT.BUTTON2; +// if (event.button is 3) event.stateMask |= DWT.BUTTON3; +// if (event.button is 4) event.stateMask |= DWT.BUTTON4; +// if (event.button is 5) event.stateMask |= DWT.BUTTON5; +// break; +// case DWT.KeyDown: +// case DWT.Traverse: { +// if (event.keyCode !is 0 || event.character !is 0) return true; +// int lastModifiers = display.lastModifiers; +// if ((modifiers & OS.alphaLock) !is 0 && (lastModifiers & OS.alphaLock) is 0) { +// event.keyCode = DWT.CAPS_LOCK; +// return true; +// } +// if ((modifiers & OS.shiftKey) !is 0 && (lastModifiers & OS.shiftKey) is 0) { +// event.stateMask &= ~DWT.SHIFT; +// event.keyCode = DWT.SHIFT; +// return true; +// } +// if ((modifiers & OS.controlKey) !is 0 && (lastModifiers & OS.controlKey) is 0) { +// event.stateMask &= ~DWT.CONTROL; +// event.keyCode = DWT.CONTROL; +// return true; +// } +// if ((modifiers & OS.cmdKey) !is 0 && (lastModifiers & OS.cmdKey) is 0) { +// event.stateMask &= ~DWT.COMMAND; +// event.keyCode = DWT.COMMAND; +// return true; +// } +// if ((modifiers & OS.optionKey) !is 0 && (lastModifiers & OS.optionKey) is 0) { +// event.stateMask &= ~DWT.ALT; +// event.keyCode = DWT.ALT; +// return true; +// } +// break; +// } +// case DWT.KeyUp: { +// if (event.keyCode !is 0 || event.character !is 0) return true; +// int lastModifiers = display.lastModifiers; +// if ((modifiers & OS.alphaLock) is 0 && (lastModifiers & OS.alphaLock) !is 0) { +// event.keyCode = DWT.CAPS_LOCK; +// return true; +// } +// if ((modifiers & OS.shiftKey) is 0 && (lastModifiers & OS.shiftKey) !is 0) { +// event.stateMask |= DWT.SHIFT; +// event.keyCode = DWT.SHIFT; +// return true; +// } +// if ((modifiers & OS.controlKey) is 0 && (lastModifiers & OS.controlKey) !is 0) { +// event.stateMask |= DWT.CONTROL; +// event.keyCode = DWT.CONTROL; +// return true; +// } +// if ((modifiers & OS.cmdKey) is 0 && (lastModifiers & OS.cmdKey) !is 0) { +// event.stateMask |= DWT.COMMAND; +// event.keyCode = DWT.COMMAND; +// return true; +// } +// if ((modifiers & OS.optionKey) is 0 && (lastModifiers & OS.optionKey) !is 0) { +// event.stateMask |= DWT.ALT; +// event.keyCode = DWT.ALT; +// return true; +// } +// break; +// } +// } + return true; +} + +bool setKeyState (Event event, int type, NSEvent nsEvent) { +// bool isNull = false; +// int [] keyCode = new int [1]; +// OS.GetEventParameter (theEvent, OS.kEventParamKeyCode, OS.typeUInt32, null, keyCode.length * 4, null, keyCode); +// event.keyCode = Display.translateKey (keyCode [0]); + switch (event.keyCode) { +// case DWT.LF: { +// /* +// * Feature in the Macintosh. When the numeric key pad +// * Enter key is pressed, it generates '\n'. This is the +// * correct platform behavior but is not portable. The +// * fix is to convert the '\n' into '\r'. +// */ +// event.keyCode = DWT.KEYPAD_CR; +// event.character = '\r'; +// break; +// } + case DWT.BS: event.character = '\b'; break; +// case DWT.CR: event.character = '\r'; break; + case DWT.DEL: event.character = 0x7F; break; +// case DWT.ESC: event.character = 0x1B; break; +// case DWT.TAB: event.character = '\t'; break; +// default: { +// if (event.keyCode is 0 || (DWT.KEYPAD_MULTIPLY <= event.keyCode && event.keyCode <= DWT.KEYPAD_CR)) { +// int [] length = new int [1]; +// int status = OS.GetEventParameter (theEvent, OS.kEventParamKeyUnicodes, OS.typeUnicodeText, null, 4, length, (char[])null); +// if (status is OS.noErr && length [0] !is 0) { +// char [] chars = new char [1]; +// OS.GetEventParameter (theEvent, OS.kEventParamKeyUnicodes, OS.typeUnicodeText, null, 2, null, chars); +// event.character = chars [0]; +// } +// /* +// * Bug in the Mactonish. For some reason, Ctrl+Shift+'2' and Ctrl+Shift+'6' +// * fail to give 0x0 (^@ or ASCII NUL) and 0x1e (^^). Other control character +// * key sequences such as ^A or even Ctrl+Shift+'-' (^_ or 0x1f) are correctly +// * translated to control characters. Since it is not possible to know which +// * key combination gives '@' on an international keyboard, there is no way to +// * test for either character and convert it to a control character (Shift+'2' +// * gives '@' only on an English keyboard) to work around the problem. +// * +// * There is no fix at this time. +// */ +// } +// if (event.keyCode is 0) { +// int kchrPtr = OS.GetScriptManagerVariable ((short) OS.smKCHRCache); +// if (display.kchrPtr !is kchrPtr) { +// display.kchrPtr = kchrPtr; +// display.kchrState [0] = 0; +// } +// int result = OS.KeyTranslate (display.kchrPtr, (short)keyCode [0], display.kchrState); +// if (result <= 0x7f) { +// event.keyCode = result & 0x7f; +// } else { +// int [] encoding = new int [1]; +// short keyScript = (short) OS.GetScriptManagerVariable ((short) OS.smKeyScript); +// short regionCode = (short) OS.GetScriptManagerVariable ((short) OS.smRegionCode); +// if (OS.UpgradeScriptInfoToTextEncoding (keyScript, (short) OS.kTextLanguageDontCare, regionCode, null, encoding) is OS.paramErr) { +// if (OS.UpgradeScriptInfoToTextEncoding (keyScript, (short) OS.kTextLanguageDontCare, (short) OS.kTextRegionDontCare, null, encoding) is OS.paramErr) { +// encoding [0] = OS.kTextEncodingMacRoman; +// } +// } +// int [] encodingInfo = new int [1]; +// OS.CreateTextToUnicodeInfoByEncoding (encoding [0], encodingInfo); +// if (encodingInfo [0] !is 0) { +// char [] chars = new char [1]; +// int [] nchars = new int [1]; +// byte [] buffer = new byte [2]; +// buffer [0] = 1; +// buffer [1] = (byte) (result & 0xFF); +// OS.ConvertFromPStringToUnicode (encodingInfo [0], buffer, chars.length * 2, nchars, chars); +// OS.DisposeTextToUnicodeInfo (encodingInfo); +// event.keyCode = chars [0]; +// } +// } +// } +// break; +// } + } +// if (event.keyCode is 0 && event.character is 0) { +// if (!isNull) return false; +// } +// int [] chord = new int [1]; +// OS.GetEventParameter (theEvent, OS.kEventParamMouseChord, OS.typeUInt32, null, 4, null, chord); +// int [] modifiers = new int [1]; +// OS.GetEventParameter (theEvent, OS.kEventParamKeyModifiers, OS.typeUInt32, null, 4, null, modifiers); +// return setInputState (event, type, chord [0], modifiers [0]); + return true; +} + +void tableViewSelectionDidChange (int aNotification) { +} + +int tableView_objectValueForTableColumn_row(int aTableView, int aTableColumn, int rowIndex) { + return 0; +} + +void tableView_setObjectValue_forTableColumn_row(int aTableView, int anObject, int aTableColumn, int rowIndex) { +} + +bool tableView_shouldEditTableColumn_row(int aTableView, int aTableColumn, int rowIndex) { + return true; +} + +void tableView_willDisplayCell_forTableColumn_row(int aTableView, int aCell, int aTableColumn, int rowIndex) { +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +public String toString () { + String string = "*Disposed*"; + if (!isDisposed ()) { + string = "*Wrong Thread*"; + if (isValidThread ()) string = getNameText (); + } + return getName () + " {" + string + "}"; +} + +void willSelectTabViewItem(int tabView, int tabViewItem) { +} + +void windowDidMove(int notification) { +} + +void windowDidResize(int notification) { +} + +void windowDidResignKey(int notification) { +} + +void windowDidBecomeKey(int notification) { +} + +void windowSendEvent(int id, int event) { + callSuper(id, OS.sel_sendEvent_1, event); +} + +bool windowShouldClose(int window) { + return false; +} + +void windowWillClose(int notification) { +} + +}