comparison dwt/widgets/Control.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 649b8e223d5a 2952d5604c0a
comparison
equal deleted inserted replaced
-1:000000000000 0:380af2bdd8e5
1 /*******************************************************************************
2 * Copyright (c) 2000, 2007 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 module dwt.widgets.Control;
12
13 import dwt.dwthelper.utils;
14
15 import dwt.DWT;
16 import dwt.DWTException;
17 import dwt.accessibility.Accessible;
18 import dwt.events.ControlListener;
19 import dwt.events.DragDetectListener;
20 import dwt.events.FocusListener;
21 import dwt.events.HelpListener;
22 import dwt.events.KeyListener;
23 import dwt.events.MenuDetectListener;
24 import dwt.events.MouseEvent;
25 import dwt.events.MouseListener;
26 import dwt.events.MouseMoveListener;
27 import dwt.events.MouseTrackListener;
28 import dwt.events.MouseWheelListener;
29 import dwt.events.PaintListener;
30 import dwt.events.TraverseListener;
31 import dwt.graphics.Color;
32 import dwt.graphics.Cursor;
33 import dwt.graphics.Drawable;
34 import dwt.graphics.Font;
35 import dwt.graphics.GC;
36 import dwt.graphics.GCData;
37 import dwt.graphics.Image;
38 import dwt.graphics.Point;
39 import dwt.graphics.Rectangle;
40 import dwt.graphics.Region;
41 import dwt.internal.cocoa.NSControl;
42 import dwt.internal.cocoa.NSEvent;
43 import dwt.internal.cocoa.NSFont;
44 import dwt.internal.cocoa.NSGraphicsContext;
45 import dwt.internal.cocoa.NSPoint;
46 import dwt.internal.cocoa.NSRect;
47 import dwt.internal.cocoa.NSSize;
48 import dwt.internal.cocoa.NSString;
49 import dwt.internal.cocoa.NSView;
50 import dwt.internal.cocoa.NSWindow;
51 import dwt.internal.cocoa.OS;
52 import dwt.internal.cocoa.objc_super;
53
54 /**
55 * Control is the abstract superclass of all windowed user interface classes.
56 * <p>
57 * <dl>
58 * <dt><b>Styles:</b>
59 * <dd>BORDER</dd>
60 * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
61 * <dt><b>Events:</b>
62 * <dd>DragDetect, FocusIn, FocusOut, Help, KeyDown, KeyUp, MenuDetect, MouseDoubleClick, MouseDown, MouseEnter,
63 * MouseExit, MouseHover, MouseUp, MouseMove, Move, Paint, Resize, Traverse</dd>
64 * </dl>
65 * </p><p>
66 * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
67 * </p><p>
68 * IMPORTANT: This class is intended to be subclassed <em>only</em>
69 * within the DWT implementation.
70 * </p>
71 */
72 public abstract class Control extends Widget implements Drawable {
73 /**
74 * the handle to the OS resource
75 * (Warning: This field is platform dependent)
76 * <p>
77 * <b>IMPORTANT:</b> This field is <em>not</em> part of the DWT
78 * public API. It is marked public only so that it can be shared
79 * within the packages provided by DWT. It is not available on all
80 * platforms and should never be accessed from application code.
81 * </p>
82 */
83 public NSView view;
84 Composite parent;
85 String toolTipText;
86 Object layoutData;
87 int drawCount;
88 // int visibleRgn;
89 Menu menu;
90 Color foreground, background;
91 Image backgroundImage;
92 Font font;
93 Cursor cursor;
94 Region region;
95 // GCData gcs[];
96 Accessible accessible;
97
98 // static final String RESET_VISIBLE_REGION = "dwt.internal.resetVisibleRegion";
99
100 Control () {
101 /* Do nothing */
102 }
103
104 /**
105 * Constructs a new instance of this class given its parent
106 * and a style value describing its behavior and appearance.
107 * <p>
108 * The style value is either one of the style constants defined in
109 * class <code>DWT</code> which is applicable to instances of this
110 * class, or must be built by <em>bitwise OR</em>'ing together
111 * (that is, using the <code>int</code> "|" operator) two or more
112 * of those <code>DWT</code> style constants. The class description
113 * lists the style constants that are applicable to the class.
114 * Style bits are also inherited from superclasses.
115 * </p>
116 *
117 * @param parent a composite control which will be the parent of the new instance (cannot be null)
118 * @param style the style of control to construct
119 *
120 * @exception IllegalArgumentException <ul>
121 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
122 * </ul>
123 * @exception DWTException <ul>
124 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
125 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
126 * </ul>
127 *
128 * @see DWT#BORDER
129 * @see Widget#checkSubclass
130 * @see Widget#getStyle
131 */
132 public Control (Composite parent, int style) {
133 super (parent, style);
134 this.parent = parent;
135 createWidget ();
136 }
137
138 bool acceptsFirstResponder () {
139 objc_super super_struct = new objc_super();
140 super_struct.receiver = view.id;
141 super_struct.cls = OS.objc_msgSend(view.id, OS.sel_superclass);
142 return OS.objc_msgSendSuper(super_struct, OS.sel_acceptsFirstResponder) !is 0;
143 }
144
145 bool becomeFirstResponder () {
146 //TODO - query focusControl() in DWT.FocusIn/Out is the control
147 sendEvent (DWT.FocusIn);
148 objc_super super_struct = new objc_super();
149 super_struct.receiver = view.id;
150 super_struct.cls = OS.objc_msgSend(view.id, OS.sel_superclass);
151 return OS.objc_msgSendSuper(super_struct, OS.sel_becomeFirstResponder) !is 0;
152 }
153
154 bool resignFirstResponder () {
155 //TODO - query focusControl() in DWT.FocusIn/Out is the control
156 sendEvent (DWT.FocusOut);
157 objc_super super_struct = new objc_super();
158 super_struct.receiver = view.id;
159 super_struct.cls = OS.objc_msgSend(view.id, OS.sel_superclass);
160 return OS.objc_msgSendSuper(super_struct, OS.sel_resignFirstResponder) !is 0;
161 }
162
163 /**
164 * Adds the listener to the collection of listeners who will
165 * be notified when the control is moved or resized, by sending
166 * it one of the messages defined in the <code>ControlListener</code>
167 * interface.
168 *
169 * @param listener the listener which should be notified
170 *
171 * @exception IllegalArgumentException <ul>
172 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
173 * </ul>
174 * @exception DWTException <ul>
175 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
176 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
177 * </ul>
178 *
179 * @see ControlListener
180 * @see #removeControlListener
181 */
182 public void addControlListener(ControlListener listener) {
183 checkWidget();
184 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
185 TypedListener typedListener = new TypedListener (listener);
186 addListener (DWT.Resize,typedListener);
187 addListener (DWT.Move,typedListener);
188 }
189
190 /**
191 * Adds the listener to the collection of listeners who will
192 * be notified when a drag gesture occurs, by sending it
193 * one of the messages defined in the <code>DragDetectListener</code>
194 * interface.
195 *
196 * @param listener the listener which should be notified
197 *
198 * @exception IllegalArgumentException <ul>
199 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
200 * </ul>
201 * @exception DWTException <ul>
202 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
203 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
204 * </ul>
205 *
206 * @see DragDetectListener
207 * @see #removeDragDetectListener
208 *
209 * @since 3.3
210 */
211 public void addDragDetectListener (DragDetectListener listener) {
212 checkWidget ();
213 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
214 TypedListener typedListener = new TypedListener (listener);
215 addListener (DWT.DragDetect,typedListener);
216 }
217
218 /**
219 * Adds the listener to the collection of listeners who will
220 * be notified when the control gains or loses focus, by sending
221 * it one of the messages defined in the <code>FocusListener</code>
222 * interface.
223 *
224 * @param listener the listener which should be notified
225 *
226 * @exception IllegalArgumentException <ul>
227 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
228 * </ul>
229 * @exception DWTException <ul>
230 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
231 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
232 * </ul>
233 *
234 * @see FocusListener
235 * @see #removeFocusListener
236 */
237 public void addFocusListener(FocusListener listener) {
238 checkWidget();
239 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
240 TypedListener typedListener = new TypedListener (listener);
241 addListener(DWT.FocusIn,typedListener);
242 addListener(DWT.FocusOut,typedListener);
243 }
244
245 /**
246 * Adds the listener to the collection of listeners who will
247 * be notified when help events are generated for the control,
248 * by sending it one of the messages defined in the
249 * <code>HelpListener</code> interface.
250 *
251 * @param listener the listener which should be notified
252 *
253 * @exception IllegalArgumentException <ul>
254 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
255 * </ul>
256 * @exception DWTException <ul>
257 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
258 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
259 * </ul>
260 *
261 * @see HelpListener
262 * @see #removeHelpListener
263 */
264 public void addHelpListener (HelpListener listener) {
265 checkWidget();
266 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
267 TypedListener typedListener = new TypedListener (listener);
268 addListener (DWT.Help, typedListener);
269 }
270
271 /**
272 * Adds the listener to the collection of listeners who will
273 * be notified when keys are pressed and released on the system keyboard, by sending
274 * it one of the messages defined in the <code>KeyListener</code>
275 * interface.
276 * <p>
277 * When a key listener is added to a control, the control
278 * will take part in widget traversal. By default, all
279 * traversal keys (such as the tab key and so on) are
280 * delivered to the control. In order for a control to take
281 * part in traversal, it should listen for traversal events.
282 * Otherwise, the user can traverse into a control but not
283 * out. Note that native controls such as table and tree
284 * implement key traversal in the operating system. It is
285 * not necessary to add traversal listeners for these controls,
286 * unless you want to override the default traversal.
287 * </p>
288 * @param listener the listener which should be notified
289 *
290 * @exception IllegalArgumentException <ul>
291 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
292 * </ul>
293 * @exception DWTException <ul>
294 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
295 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
296 * </ul>
297 *
298 * @see KeyListener
299 * @see #removeKeyListener
300 */
301 public void addKeyListener(KeyListener listener) {
302 checkWidget();
303 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
304 TypedListener typedListener = new TypedListener (listener);
305 addListener(DWT.KeyUp,typedListener);
306 addListener(DWT.KeyDown,typedListener);
307 }
308
309 /**
310 * Adds the listener to the collection of listeners who will
311 * be notified when the platform-specific context menu trigger
312 * has occurred, by sending it one of the messages defined in
313 * the <code>MenuDetectListener</code> interface.
314 *
315 * @param listener the listener which should be notified
316 *
317 * @exception IllegalArgumentException <ul>
318 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
319 * </ul>
320 * @exception DWTException <ul>
321 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
322 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
323 * </ul>
324 *
325 * @see MenuDetectListener
326 * @see #removeMenuDetectListener
327 *
328 * @since 3.3
329 */
330 public void addMenuDetectListener (MenuDetectListener listener) {
331 checkWidget ();
332 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
333 TypedListener typedListener = new TypedListener (listener);
334 addListener (DWT.MenuDetect, typedListener);
335 }
336
337 /**
338 * Adds the listener to the collection of listeners who will
339 * be notified when mouse buttons are pressed and released, by sending
340 * it one of the messages defined in the <code>MouseListener</code>
341 * interface.
342 *
343 * @param listener the listener which should be notified
344 *
345 * @exception IllegalArgumentException <ul>
346 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
347 * </ul>
348 * @exception DWTException <ul>
349 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
350 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
351 * </ul>
352 *
353 * @see MouseListener
354 * @see #removeMouseListener
355 */
356 public void addMouseListener(MouseListener listener) {
357 checkWidget();
358 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
359 TypedListener typedListener = new TypedListener (listener);
360 addListener(DWT.MouseDown,typedListener);
361 addListener(DWT.MouseUp,typedListener);
362 addListener(DWT.MouseDoubleClick,typedListener);
363 }
364
365 /**
366 * Adds the listener to the collection of listeners who will
367 * be notified when the mouse passes or hovers over controls, by sending
368 * it one of the messages defined in the <code>MouseTrackListener</code>
369 * interface.
370 *
371 * @param listener the listener which should be notified
372 *
373 * @exception IllegalArgumentException <ul>
374 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
375 * </ul>
376 * @exception DWTException <ul>
377 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
378 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
379 * </ul>
380 *
381 * @see MouseTrackListener
382 * @see #removeMouseTrackListener
383 */
384 public void addMouseTrackListener (MouseTrackListener listener) {
385 checkWidget();
386 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
387 TypedListener typedListener = new TypedListener (listener);
388 addListener (DWT.MouseEnter,typedListener);
389 addListener (DWT.MouseExit,typedListener);
390 addListener (DWT.MouseHover,typedListener);
391 }
392
393 /**
394 * Adds the listener to the collection of listeners who will
395 * be notified when the mouse moves, by sending it one of the
396 * messages defined in the <code>MouseMoveListener</code>
397 * interface.
398 *
399 * @param listener the listener which should be notified
400 *
401 * @exception IllegalArgumentException <ul>
402 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
403 * </ul>
404 * @exception DWTException <ul>
405 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
406 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
407 * </ul>
408 *
409 * @see MouseMoveListener
410 * @see #removeMouseMoveListener
411 */
412 public void addMouseMoveListener(MouseMoveListener listener) {
413 checkWidget();
414 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
415 TypedListener typedListener = new TypedListener (listener);
416 addListener(DWT.MouseMove,typedListener);
417 }
418
419 /**
420 * Adds the listener to the collection of listeners who will
421 * be notified when the mouse wheel is scrolled, by sending
422 * it one of the messages defined in the
423 * <code>MouseWheelListener</code> interface.
424 *
425 * @param listener the listener which should be notified
426 *
427 * @exception IllegalArgumentException <ul>
428 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
429 * </ul>
430 * @exception DWTException <ul>
431 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
432 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
433 * </ul>
434 *
435 * @see MouseWheelListener
436 * @see #removeMouseWheelListener
437 *
438 * @since 3.3
439 */
440 public void addMouseWheelListener (MouseWheelListener listener) {
441 checkWidget ();
442 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
443 TypedListener typedListener = new TypedListener (listener);
444 addListener (DWT.MouseWheel, typedListener);
445 }
446
447 /**
448 * Adds the listener to the collection of listeners who will
449 * be notified when the receiver needs to be painted, by sending it
450 * one of the messages defined in the <code>PaintListener</code>
451 * interface.
452 *
453 * @param listener the listener which should be notified
454 *
455 * @exception IllegalArgumentException <ul>
456 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
457 * </ul>
458 * @exception DWTException <ul>
459 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
460 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
461 * </ul>
462 *
463 * @see PaintListener
464 * @see #removePaintListener
465 */
466 public void addPaintListener(PaintListener listener) {
467 checkWidget();
468 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
469 TypedListener typedListener = new TypedListener (listener);
470 addListener(DWT.Paint,typedListener);
471 }
472
473 /**
474 * Adds the listener to the collection of listeners who will
475 * be notified when traversal events occur, by sending it
476 * one of the messages defined in the <code>TraverseListener</code>
477 * interface.
478 *
479 * @param listener the listener which should be notified
480 *
481 * @exception IllegalArgumentException <ul>
482 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
483 * </ul>
484 * @exception DWTException <ul>
485 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
486 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
487 * </ul>
488 *
489 * @see TraverseListener
490 * @see #removeTraverseListener
491 */
492 public void addTraverseListener (TraverseListener listener) {
493 checkWidget();
494 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
495 TypedListener typedListener = new TypedListener (listener);
496 addListener (DWT.Traverse,typedListener);
497 }
498
499 void checkBackground () {
500 Shell shell = getShell ();
501 if (this is shell) return;
502 state &= ~PARENT_BACKGROUND;
503 Composite composite = parent;
504 do {
505 int mode = composite.backgroundMode;
506 if (mode !is 0) {
507 if (mode is DWT.INHERIT_DEFAULT) {
508 Control control = this;
509 do {
510 if ((control.state & THEME_BACKGROUND) is 0) {
511 return;
512 }
513 control = control.parent;
514 } while (control !is composite);
515 }
516 state |= PARENT_BACKGROUND;
517 return;
518 }
519 if (composite is shell) break;
520 composite = composite.parent;
521 } while (true);
522 }
523
524 void checkBuffered () {
525 style |= DWT.DOUBLE_BUFFERED;
526 }
527
528 /**
529 * Returns the preferred size of the receiver.
530 * <p>
531 * The <em>preferred size</em> of a control is the size that it would
532 * best be displayed at. The width hint and height hint arguments
533 * allow the caller to ask a control questions such as "Given a particular
534 * width, how high does the control need to be to show all of the contents?"
535 * To indicate that the caller does not wish to constrain a particular
536 * dimension, the constant <code>DWT.DEFAULT</code> is passed for the hint.
537 * </p>
538 *
539 * @param wHint the width hint (can be <code>DWT.DEFAULT</code>)
540 * @param hHint the height hint (can be <code>DWT.DEFAULT</code>)
541 * @return the preferred size of the control
542 *
543 * @exception DWTException <ul>
544 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
545 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
546 * </ul>
547 *
548 * @see Layout
549 * @see #getBorderWidth
550 * @see #getBounds
551 * @see #getSize
552 * @see #pack(bool)
553 * @see "computeTrim, getClientArea for controls that implement them"
554 */
555 public Point computeSize (int wHint, int hHint) {
556 return computeSize (wHint, hHint, true);
557 }
558
559 /**
560 * Returns the preferred size of the receiver.
561 * <p>
562 * The <em>preferred size</em> of a control is the size that it would
563 * best be displayed at. The width hint and height hint arguments
564 * allow the caller to ask a control questions such as "Given a particular
565 * width, how high does the control need to be to show all of the contents?"
566 * To indicate that the caller does not wish to constrain a particular
567 * dimension, the constant <code>DWT.DEFAULT</code> is passed for the hint.
568 * </p><p>
569 * If the changed flag is <code>true</code>, it indicates that the receiver's
570 * <em>contents</em> have changed, therefore any caches that a layout manager
571 * containing the control may have been keeping need to be flushed. When the
572 * control is resized, the changed flag will be <code>false</code>, so layout
573 * manager caches can be retained.
574 * </p>
575 *
576 * @param wHint the width hint (can be <code>DWT.DEFAULT</code>)
577 * @param hHint the height hint (can be <code>DWT.DEFAULT</code>)
578 * @param changed <code>true</code> if the control's contents have changed, and <code>false</code> otherwise
579 * @return the preferred size of the control.
580 *
581 * @exception DWTException <ul>
582 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
583 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
584 * </ul>
585 *
586 * @see Layout
587 * @see #getBorderWidth
588 * @see #getBounds
589 * @see #getSize
590 * @see #pack(bool)
591 * @see "computeTrim, getClientArea for controls that implement them"
592 */
593 public Point computeSize (int wHint, int hHint, bool changed) {
594 checkWidget();
595 int width = DEFAULT_WIDTH;
596 int height = DEFAULT_HEIGHT;
597 // if (wHint !is DWT.DEFAULT) width = wHint;
598 // if (hHint !is DWT.DEFAULT) height = hHint;
599 // int border = getBorderWidth ();
600 // width += border * 2;
601 // height += border * 2;
602 // return new Point (width, height);
603 if (topView() instanceof NSControl) {
604 NSRect oldRect = topView().frame();
605 ((NSControl)topView()).sizeToFit();
606 NSRect newRect = topView().frame();
607 topView().setFrame (oldRect);
608 return new Point ((int)newRect.width, (int)newRect.height);
609 }
610 return new Point (width, height);
611 }
612
613 Control computeTabGroup () {
614 if (isTabGroup()) return this;
615 return parent.computeTabGroup ();
616 }
617
618 Control[] computeTabList() {
619 if (isTabGroup()) {
620 if (getVisible() && getEnabled()) {
621 return new Control[] {this};
622 }
623 }
624 return new Control[0];
625 }
626
627 Control computeTabRoot () {
628 Control[] tabList = parent._getTabList();
629 if (tabList !is null) {
630 int index = 0;
631 while (index < tabList.length) {
632 if (tabList [index] is this) break;
633 index++;
634 }
635 if (index is tabList.length) {
636 if (isTabGroup ()) return this;
637 }
638 }
639 return parent.computeTabRoot ();
640 }
641
642 void createWidget () {
643 state |= DRAG_DETECT;
644 checkOrientation (parent);
645 super.createWidget ();
646 checkBackground ();
647 checkBuffered ();
648 setDefaultFont ();
649 setZOrder ();
650 }
651
652 Color defaultBackground () {
653 return display.getSystemColor (DWT.COLOR_WIDGET_BACKGROUND);
654 }
655
656 Font defaultFont () {
657 //TODO - Controls only, does this leak?
658 if (view instanceof NSControl) {
659 NSFont nsFont = ((NSControl)view).font ();
660 if (nsFont !is null) {
661 return Font.cocoa_new (display, nsFont);
662 }
663 }
664 return display.getSystemFont ();
665 }
666
667 Color defaultForeground () {
668 return display.getSystemColor (DWT.COLOR_WIDGET_FOREGROUND);
669 }
670
671 void destroyWidget () {
672 NSView view = topView ();
673 view.removeFromSuperview ();
674 releaseHandle ();
675 }
676
677 /**
678 * Detects a drag and drop gesture. This method is used
679 * to detect a drag gesture when called from within a mouse
680 * down listener.
681 *
682 * <p>By default, a drag is detected when the gesture
683 * occurs anywhere within the client area of a control.
684 * Some controls, such as tables and trees, override this
685 * behavior. In addition to the operating system specific
686 * drag gesture, they require the mouse to be inside an
687 * item. Custom widget writers can use <code>setDragDetect</code>
688 * to disable the default detection, listen for mouse down,
689 * and then call <code>dragDetect()</code> from within the
690 * listener to conditionally detect a drag.
691 * </p>
692 *
693 * @param event the mouse down event
694 *
695 * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
696 *
697 * @exception IllegalArgumentException <ul>
698 * <li>ERROR_NULL_ARGUMENT when the event is null</li>
699 * </ul>
700 * @exception DWTException <ul>
701 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
702 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
703 * </ul>
704 *
705 * @see DragDetectListener
706 * @see #addDragDetectListener
707 *
708 * @see #getDragDetect
709 * @see #setDragDetect
710 *
711 * @since 3.3
712 */
713 public bool dragDetect (Event event) {
714 checkWidget ();
715 if (event is null) error (DWT.ERROR_NULL_ARGUMENT);
716 return dragDetect (event.button, event.count, event.stateMask, event.x, event.y);
717 }
718
719 /**
720 * Detects a drag and drop gesture. This method is used
721 * to detect a drag gesture when called from within a mouse
722 * down listener.
723 *
724 * <p>By default, a drag is detected when the gesture
725 * occurs anywhere within the client area of a control.
726 * Some controls, such as tables and trees, override this
727 * behavior. In addition to the operating system specific
728 * drag gesture, they require the mouse to be inside an
729 * item. Custom widget writers can use <code>setDragDetect</code>
730 * to disable the default detection, listen for mouse down,
731 * and then call <code>dragDetect()</code> from within the
732 * listener to conditionally detect a drag.
733 * </p>
734 *
735 * @param event the mouse down event
736 *
737 * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
738 *
739 * @exception IllegalArgumentException <ul>
740 * <li>ERROR_NULL_ARGUMENT when the event is null</li>
741 * </ul>
742 * @exception DWTException <ul>
743 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
744 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
745 * </ul>
746 *
747 * @see DragDetectListener
748 * @see #addDragDetectListener
749 *
750 * @see #getDragDetect
751 * @see #setDragDetect
752 *
753 * @since 3.3
754 */
755 public bool dragDetect (MouseEvent event) {
756 checkWidget ();
757 if (event is null) error (DWT.ERROR_NULL_ARGUMENT);
758 return dragDetect (event.button, event.count, event.stateMask, event.x, event.y);
759 }
760
761 bool dragDetect (int button, int count, int stateMask, int x, int y) {
762 if (button !is 1 || count !is 1) return false;
763 if (!dragDetect (x, y, false, null)) return false;
764 return sendDragEvent (button, stateMask, x, y);
765 }
766
767 bool dragDetect (int x, int y, bool filter, bool [] consume) {
768 // Rect rect = new Rect ();
769 // int window = OS.GetControlOwner (handle);
770 // CGPoint pt = new CGPoint ();
771 // OS.HIViewConvertPoint (pt, handle, 0);
772 // x += (int) pt.x;
773 // y += (int) pt.y;
774 // OS.GetWindowBounds (window, (short) OS.kWindowStructureRgn, rect);
775 // x += rect.left;
776 // y += rect.top;
777 // dwt.internal.carbon.Point pt1 = new dwt.internal.carbon.Point ();
778 // pt1.h = (short) x;
779 // pt1.v = (short) y;
780 // return OS.WaitMouseMoved (pt1);
781 return false;
782 }
783
784 bool drawGripper (int x, int y, int width, int height, bool vertical) {
785 return false;
786 }
787
788 void drawRect(int id, NSRect rect) {
789 super.drawRect(id, rect);
790 if (!hooks (DWT.Paint) && !filters (DWT.Paint)) return;
791
792 /* Send paint event */
793 GCData data = new GCData ();
794 data.paintRect = rect;
795 GC gc = GC.cocoa_new (this, data);
796 Event event = new Event ();
797 event.gc = gc;
798 event.x = (int)rect.x;
799 event.y = (int)rect.y;
800 event.width = (int)rect.width;
801 event.height = (int)rect.height;
802 sendEvent (DWT.Paint, event);
803 event.gc = null;
804 gc.dispose ();
805 }
806
807 void enableWidget (bool enabled) {
808 //TODO - other views
809 if (view instanceof NSControl) {
810 ((NSControl)view).setEnabled(enabled);
811 }
812 }
813
814 Cursor findCursor () {
815 if (cursor !is null) return cursor;
816 return parent.findCursor ();
817 }
818
819 Control findBackgroundControl () {
820 if (backgroundImage !is null || background !is null) return this;
821 return (state & PARENT_BACKGROUND) !is 0 ? parent.findBackgroundControl () : null;
822 }
823
824 Menu [] findMenus (Control control) {
825 if (menu !is null && this !is control) return new Menu [] {menu};
826 return new Menu [0];
827 }
828
829 void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
830 oldShell.fixShell (newShell, this);
831 oldDecorations.fixDecorations (newDecorations, this, menus);
832 }
833
834 void fixFocus (Control focusControl) {
835 Shell shell = getShell ();
836 Control control = this;
837 while (control !is shell && (control = control.parent) !is null) {
838 if (control.setFocus ()) return;
839 }
840 shell.setSavedFocus (focusControl);
841 // int window = OS.GetControlOwner (handle);
842 // OS.ClearKeyboardFocus (window);
843 }
844
845 /**
846 * Forces the receiver to have the <em>keyboard focus</em>, causing
847 * all keyboard events to be delivered to it.
848 *
849 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
850 *
851 * @exception DWTException <ul>
852 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
853 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
854 * </ul>
855 *
856 * @see #setFocus
857 */
858 public bool forceFocus () {
859 checkWidget();
860 // if (display.focusEvent is DWT.FocusOut) return false;
861 Decorations shell = menuShell ();
862 shell.setSavedFocus (this);
863 if (!isEnabled () || !isVisible ()/* || !isActive ()*/) return false;
864 if (isFocusControl ()) return true;
865 shell.setSavedFocus (null);
866 shell.bringToTop (false);
867 if (isDisposed ()) return false;
868 view.window ().makeFirstResponder (view);
869 if (isDisposed ()) return false;
870 shell.setSavedFocus (this);
871 return hasFocus ();
872 }
873
874 /**
875 * Returns the accessible object for the receiver.
876 * If this is the first time this object is requested,
877 * then the object is created and returned.
878 *
879 * @return the accessible object
880 *
881 * @exception DWTException <ul>
882 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
883 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
884 * </ul>
885 *
886 * @see Accessible#addAccessibleListener
887 * @see Accessible#addAccessibleControlListener
888 *
889 * @since 2.0
890 */
891 public Accessible getAccessible () {
892 checkWidget ();
893 if (accessible is null) accessible = new_Accessible (this);
894 return accessible;
895 }
896
897 /**
898 * Returns the receiver's background color.
899 *
900 * @return the background color
901 *
902 * @exception DWTException <ul>
903 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
904 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
905 * </ul>
906 */
907 public Color getBackground () {
908 checkWidget();
909 Control control = findBackgroundControl ();
910 if (control is null) control = this;
911 return control.getBackgroundColor ();
912 }
913
914 Color getBackgroundColor () {
915 return background !is null ? background : defaultBackground ();
916 }
917
918 /**
919 * Returns the receiver's background image.
920 *
921 * @return the background image
922 *
923 * @exception DWTException <ul>
924 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
925 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
926 * </ul>
927 *
928 * @since 3.2
929 */
930 public Image getBackgroundImage () {
931 checkWidget();
932 Control control = findBackgroundControl ();
933 if (control is null) control = this;
934 return control.backgroundImage;
935 }
936
937 /**
938 * Returns the receiver's border width.
939 *
940 * @return the border width
941 *
942 * @exception DWTException <ul>
943 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
944 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
945 * </ul>
946 */
947 public int getBorderWidth () {
948 checkWidget();
949 return 0;
950 }
951
952 /**
953 * Returns a rectangle describing the receiver's size and location
954 * relative to its parent (or its display if its parent is null),
955 * unless the receiver is a shell. In this case, the location is
956 * relative to the display.
957 *
958 * @return the receiver's bounding rectangle
959 *
960 * @exception DWTException <ul>
961 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
962 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
963 * </ul>
964 */
965 public Rectangle getBounds () {
966 checkWidget();
967 NSRect rect = topView().frame();
968 return new Rectangle((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
969 }
970
971 /**
972 * Returns <code>true</code> if the receiver is detecting
973 * drag gestures, and <code>false</code> otherwise.
974 *
975 * @return the receiver's drag detect state
976 *
977 * @exception DWTException <ul>
978 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
979 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
980 * </ul>
981 *
982 * @since 3.3
983 */
984 public bool getDragDetect () {
985 checkWidget ();
986 return (state & DRAG_DETECT) !is 0;
987 }
988
989 /**
990 * Returns the receiver's cursor, or null if it has not been set.
991 * <p>
992 * When the mouse pointer passes over a control its appearance
993 * is changed to match the control's cursor.
994 * </p>
995 * </ul>
996 * @exception DWTException <ul>
997 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
998 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
999 * </ul>
1000 *
1001 * @since 3.3
1002 */
1003 public Cursor getCursor () {
1004 checkWidget();
1005 return cursor;
1006 }
1007
1008 /**
1009 * Returns <code>true</code> if the receiver is enabled, and
1010 * <code>false</code> otherwise. A disabled control is typically
1011 * not selectable from the user interface and draws with an
1012 * inactive or "grayed" look.
1013 *
1014 * @return the receiver's enabled state
1015 *
1016 * @exception DWTException <ul>
1017 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1018 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1019 * </ul>
1020 *
1021 * @see #isEnabled
1022 */
1023 public bool getEnabled () {
1024 checkWidget();
1025 return (state & DISABLED) is 0;
1026 }
1027
1028 /**
1029 * Returns the font that the receiver will use to paint textual information.
1030 *
1031 * @return the receiver's font
1032 *
1033 * @exception DWTException <ul>
1034 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1035 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1036 * </ul>
1037 */
1038 public Font getFont () {
1039 checkWidget();
1040 return font !is null ? font : defaultFont ();
1041 }
1042
1043 /**
1044 * Returns the foreground color that the receiver will use to draw.
1045 *
1046 * @return the receiver's foreground color
1047 *
1048 * @exception DWTException <ul>
1049 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1050 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1051 * </ul>
1052 */
1053 public Color getForeground () {
1054 checkWidget();
1055 return getForegroundColor ();
1056 }
1057
1058 Color getForegroundColor () {
1059 return foreground !is null ? foreground: defaultForeground ();
1060 }
1061
1062 /**
1063 * Returns layout data which is associated with the receiver.
1064 *
1065 * @return the receiver's layout data
1066 *
1067 * @exception DWTException <ul>
1068 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1069 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1070 * </ul>
1071 */
1072 public Object getLayoutData () {
1073 checkWidget();
1074 return layoutData;
1075 }
1076
1077 /**
1078 * Returns a point describing the receiver's location relative
1079 * to its parent (or its display if its parent is null), unless
1080 * the receiver is a shell. In this case, the point is
1081 * relative to the display.
1082 *
1083 * @return the receiver's location
1084 *
1085 * @exception DWTException <ul>
1086 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1087 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1088 * </ul>
1089 */
1090 public Point getLocation () {
1091 checkWidget();
1092 NSRect rect = topView().frame();
1093 return new Point((int)rect.x, (int)rect.y);
1094 }
1095
1096 /**
1097 * Returns the receiver's pop up menu if it has one, or null
1098 * if it does not. All controls may optionally have a pop up
1099 * menu that is displayed when the user requests one for
1100 * the control. The sequence of key strokes, button presses
1101 * and/or button releases that are used to request a pop up
1102 * menu is platform specific.
1103 *
1104 * @return the receiver's menu
1105 *
1106 * @exception DWTException <ul>
1107 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1108 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1109 * </ul>
1110 */
1111 public Menu getMenu () {
1112 checkWidget();
1113 return menu;
1114 }
1115
1116 int getMininumHeight () {
1117 return 0;
1118 }
1119
1120 /**
1121 * Returns the receiver's monitor.
1122 *
1123 * @return the receiver's monitor
1124 *
1125 * @since 3.0
1126 */
1127 public Monitor getMonitor () {
1128 checkWidget();
1129 Monitor [] monitors = display.getMonitors ();
1130 if (monitors.length is 1) return monitors [0];
1131 int index = -1, value = -1;
1132 Rectangle bounds = getBounds ();
1133 if (this !is getShell ()) {
1134 bounds = display.map (this.parent, null, bounds);
1135 }
1136 for (int i=0; i<monitors.length; i++) {
1137 Rectangle rect = bounds.intersection (monitors [i].getBounds ());
1138 int area = rect.width * rect.height;
1139 if (area > 0 && area > value) {
1140 index = i;
1141 value = area;
1142 }
1143 }
1144 if (index >= 0) return monitors [index];
1145 int centerX = bounds.x + bounds.width / 2, centerY = bounds.y + bounds.height / 2;
1146 for (int i=0; i<monitors.length; i++) {
1147 Rectangle rect = monitors [i].getBounds ();
1148 int x = centerX < rect.x ? rect.x - centerX : centerX > rect.x + rect.width ? centerX - rect.x - rect.width : 0;
1149 int y = centerY < rect.y ? rect.y - centerY : centerY > rect.y + rect.height ? centerY - rect.y - rect.height : 0;
1150 int distance = x * x + y * y;
1151 if (index is -1 || distance < value) {
1152 index = i;
1153 value = distance;
1154 }
1155 }
1156 return monitors [index];
1157 }
1158
1159 /**
1160 * Returns the receiver's parent, which must be a <code>Composite</code>
1161 * or null when the receiver is a shell that was created with null or
1162 * a display for a parent.
1163 *
1164 * @return the receiver's parent
1165 *
1166 * @exception DWTException <ul>
1167 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1168 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1169 * </ul>
1170 */
1171 public Composite getParent () {
1172 checkWidget();
1173 return parent;
1174 }
1175
1176 Control [] getPath () {
1177 int count = 0;
1178 Shell shell = getShell ();
1179 Control control = this;
1180 while (control !is shell) {
1181 count++;
1182 control = control.parent;
1183 }
1184 control = this;
1185 Control [] result = new Control [count];
1186 while (control !is shell) {
1187 result [--count] = control;
1188 control = control.parent;
1189 }
1190 return result;
1191 }
1192
1193 public Region getRegion () {
1194 checkWidget ();
1195 return region;
1196 }
1197
1198 /**
1199 * Returns the receiver's shell. For all controls other than
1200 * shells, this simply returns the control's nearest ancestor
1201 * shell. Shells return themselves, even if they are children
1202 * of other shells.
1203 *
1204 * @return the receiver's shell
1205 *
1206 * @exception DWTException <ul>
1207 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1208 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1209 * </ul>
1210 *
1211 * @see #getParent
1212 */
1213 public Shell getShell () {
1214 checkWidget();
1215 return parent.getShell ();
1216 }
1217
1218 /**
1219 * Returns a point describing the receiver's size. The
1220 * x coordinate of the result is the width of the receiver.
1221 * The y coordinate of the result is the height of the
1222 * receiver.
1223 *
1224 * @return the receiver's size
1225 *
1226 * @exception DWTException <ul>
1227 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1228 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1229 * </ul>
1230 */
1231 public Point getSize () {
1232 checkWidget();
1233 NSRect rect = topView().frame();
1234 return new Point((int)rect.width, (int)rect.height);
1235 }
1236
1237 /**
1238 * Returns the receiver's tool tip text, or null if it has
1239 * not been set.
1240 *
1241 * @return the receiver's tool tip text
1242 *
1243 * @exception DWTException <ul>
1244 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1245 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1246 * </ul>
1247 */
1248 public String getToolTipText () {
1249 checkWidget();
1250 return toolTipText;
1251 }
1252
1253 /**
1254 * Returns <code>true</code> if the receiver is visible, and
1255 * <code>false</code> otherwise.
1256 * <p>
1257 * If one of the receiver's ancestors is not visible or some
1258 * other condition makes the receiver not visible, this method
1259 * may still indicate that it is considered visible even though
1260 * it may not actually be showing.
1261 * </p>
1262 *
1263 * @return the receiver's visibility state
1264 *
1265 * @exception DWTException <ul>
1266 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1267 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1268 * </ul>
1269 */
1270 public bool getVisible () {
1271 checkWidget();
1272 return (state & HIDDEN) is 0;
1273 }
1274
1275 bool hasBorder () {
1276 return (style & DWT.BORDER) !is 0;
1277 }
1278
1279 bool hasFocus () {
1280 return this is display.getFocusControl ();
1281 }
1282
1283 /**
1284 * Invokes platform specific functionality to allocate a new GC handle.
1285 * <p>
1286 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
1287 * API for <code>Control</code>. It is marked public only so that it
1288 * can be shared within the packages provided by DWT. It is not
1289 * available on all platforms, and should never be called from
1290 * application code.
1291 * </p>
1292 *
1293 * @param data the platform specific GC data
1294 * @return the platform specific GC handle
1295 */
1296 public int internal_new_GC (GCData data) {
1297 checkWidget();
1298 int context = 0;
1299 if (data !is null && data.paintRect !is null) {
1300 context = NSGraphicsContext.currentContext().id;
1301 } else {
1302 context = NSGraphicsContext.graphicsContextWithWindow(view.window()).id;
1303 }
1304 if (data !is null) {
1305 int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT;
1306 if ((data.style & mask) is 0) {
1307 data.style |= style & (mask | DWT.MIRRORED);
1308 }
1309 data.device = display;
1310 data.view = view;
1311 data.foreground = getForegroundColor ().handle;
1312 Control control = findBackgroundControl ();
1313 if (control is null) control = this;
1314 data.background = control.getBackgroundColor ().handle;
1315 data.font = font !is null ? font : defaultFont ();
1316 }
1317 return context;
1318 }
1319
1320 /**
1321 * Invokes platform specific functionality to dispose a GC handle.
1322 * <p>
1323 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
1324 * API for <code>Control</code>. It is marked public only so that it
1325 * can be shared within the packages provided by DWT. It is not
1326 * available on all platforms, and should never be called from
1327 * application code.
1328 * </p>
1329 *
1330 * @param hDC the platform specific GC handle
1331 * @param data the platform specific GC data
1332 */
1333 public void internal_dispose_GC (int context, GCData data) {
1334 checkWidget ();
1335 }
1336
1337 /**
1338 * Returns <code>true</code> if the receiver is enabled and all
1339 * ancestors up to and including the receiver's nearest ancestor
1340 * shell are enabled. Otherwise, <code>false</code> is returned.
1341 * A disabled control is typically not selectable from the user
1342 * interface and draws with an inactive or "grayed" look.
1343 *
1344 * @return the receiver's enabled state
1345 *
1346 * @exception DWTException <ul>
1347 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1348 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1349 * </ul>
1350 *
1351 * @see #getEnabled
1352 */
1353 public bool isEnabled () {
1354 checkWidget();
1355 return getEnabled () && parent.isEnabled ();
1356 }
1357
1358 bool isEnabledCursor () {
1359 return isEnabled ();
1360 }
1361
1362 bool isFocusAncestor (Control control) {
1363 while (control !is null && control !is this && !(control instanceof Shell)) {
1364 control = control.parent;
1365 }
1366 return control is this;
1367 }
1368
1369 /**
1370 * Returns <code>true</code> if the receiver has the user-interface
1371 * focus, and <code>false</code> otherwise.
1372 *
1373 * @return the receiver's focus state
1374 *
1375 * @exception DWTException <ul>
1376 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1377 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1378 * </ul>
1379 */
1380 public bool isFocusControl () {
1381 checkWidget();
1382 // Control focusControl = display.focusControl;
1383 // if (focusControl !is null && !focusControl.isDisposed ()) {
1384 // return this is focusControl;
1385 // }
1386 return hasFocus ();
1387 }
1388
1389 /**
1390 * Returns <code>true</code> if the underlying operating
1391 * system supports this reparenting, otherwise <code>false</code>
1392 *
1393 * @return <code>true</code> if the widget can be reparented, otherwise <code>false</code>
1394 *
1395 * @exception DWTException <ul>
1396 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1397 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1398 * </ul>
1399 */
1400 public bool isReparentable () {
1401 checkWidget();
1402 return true;
1403 }
1404
1405 bool isShowing () {
1406 /*
1407 * This is not complete. Need to check if the
1408 * widget is obscurred by a parent or sibling.
1409 */
1410 if (!isVisible ()) return false;
1411 Control control = this;
1412 while (control !is null) {
1413 Point size = control.getSize ();
1414 if (size.x is 0 || size.y is 0) {
1415 return false;
1416 }
1417 control = control.parent;
1418 }
1419 return true;
1420 }
1421
1422 bool isTabGroup () {
1423 Control [] tabList = parent._getTabList ();
1424 if (tabList !is null) {
1425 for (int i=0; i<tabList.length; i++) {
1426 if (tabList [i] is this) return true;
1427 }
1428 }
1429 int code = traversalCode (0, null);
1430 if ((code & (DWT.TRAVERSE_ARROW_PREVIOUS | DWT.TRAVERSE_ARROW_NEXT)) !is 0) return false;
1431 return (code & (DWT.TRAVERSE_TAB_PREVIOUS | DWT.TRAVERSE_TAB_NEXT)) !is 0;
1432 }
1433
1434 bool isTabItem () {
1435 Control [] tabList = parent._getTabList ();
1436 if (tabList !is null) {
1437 for (int i=0; i<tabList.length; i++) {
1438 if (tabList [i] is this) return false;
1439 }
1440 }
1441 int code = traversalCode (0, null);
1442 return (code & (DWT.TRAVERSE_ARROW_PREVIOUS | DWT.TRAVERSE_ARROW_NEXT)) !is 0;
1443 }
1444
1445 /**
1446 * Returns <code>true</code> if the receiver is visible and all
1447 * ancestors up to and including the receiver's nearest ancestor
1448 * shell are visible. Otherwise, <code>false</code> is returned.
1449 *
1450 * @return the receiver's visibility state
1451 *
1452 * @exception DWTException <ul>
1453 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1454 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1455 * </ul>
1456 *
1457 * @see #getVisible
1458 */
1459 public bool isVisible () {
1460 checkWidget();
1461 return getVisible () && parent.isVisible ();
1462 }
1463
1464 int menuForEvent (int nsEvent) {
1465 NSPoint pt = NSEvent.mouseLocation();
1466 NSWindow window = view.window();
1467 pt.y = (int) (window.screen().frame().height - pt.y);
1468 int x = (int) pt.x;
1469 int y = (int) pt.y;
1470 Event event = new Event ();
1471 event.x = x;
1472 event.y = y;
1473 sendEvent (DWT.MenuDetect, event);
1474 if (!event.doit) return 0;
1475 Menu menu = getMenu ();
1476 if (menu !is null && !menu.isDisposed ()) {
1477 if (x !is event.x || y !is event.y) {
1478 menu.setLocation (event.x, event.y);
1479 }
1480 return menu.nsMenu.id;
1481 }
1482 objc_super super_struct = new objc_super();
1483 super_struct.receiver = view.id;
1484 super_struct.cls = OS.objc_msgSend(view.id, OS.sel_superclass);
1485 return OS.objc_msgSendSuper(super_struct, OS.sel_menuForEvent_1, nsEvent);
1486 }
1487
1488 Decorations menuShell () {
1489 return parent.menuShell ();
1490 }
1491
1492 bool setInputState (Event event, NSEvent nsEvent, int type) {
1493 int modifierFlags = nsEvent.modifierFlags();
1494 if ((modifierFlags & OS.NSAlternateKeyMask) !is 0) event.stateMask |= DWT.ALT;
1495 if ((modifierFlags & OS.NSShiftKeyMask) !is 0) event.stateMask |= DWT.SHIFT;
1496 if ((modifierFlags & OS.NSControlKeyMask) !is 0) event.stateMask |= DWT.CONTROL;
1497 if ((modifierFlags & OS.NSCommandKeyMask) !is 0) event.stateMask |= DWT.COMMAND;
1498
1499 //WRONG
1500 if ((modifierFlags & OS.NSLeftMouseDownMask) !is 0) event.stateMask |= DWT.BUTTON1;
1501 if ((modifierFlags & OS.NSLeftMouseDraggedMask) !is 0) event.stateMask |= DWT.BUTTON1;
1502 if ((modifierFlags & OS.NSLeftMouseUpMask) !is 0) event.stateMask |= DWT.BUTTON1;
1503 if ((modifierFlags & OS.NSOtherMouseDownMask) !is 0) event.stateMask |= DWT.BUTTON2;
1504 if ((modifierFlags & OS.NSOtherMouseDraggedMask) !is 0) event.stateMask |= DWT.BUTTON2;
1505 if ((modifierFlags & OS.NSOtherMouseUpMask) !is 0) event.stateMask |= DWT.BUTTON1;
1506 if ((modifierFlags & OS.NSRightMouseDownMask) !is 0) event.stateMask |= DWT.BUTTON3;
1507 if ((modifierFlags & OS.NSRightMouseDraggedMask) !is 0) event.stateMask |= DWT.BUTTON3;
1508 if ((modifierFlags & OS.NSRightMouseUpMask) !is 0) event.stateMask |= DWT.BUTTON3;
1509
1510 // if (OS.GetKeyState (OS.VK_XBUTTON1) < 0) event.stateMask |= DWT.BUTTON4;
1511 // if (OS.GetKeyState (OS.VK_XBUTTON2) < 0) event.stateMask |= DWT.BUTTON5;
1512 // switch (type) {
1513 // case DWT.MouseDown:
1514 // case DWT.MouseDoubleClick:
1515 // if (event.button is 1) event.stateMask &= ~DWT.BUTTON1;
1516 // if (event.button is 2) event.stateMask &= ~DWT.BUTTON2;
1517 // if (event.button is 3) event.stateMask &= ~DWT.BUTTON3;
1518 // if (event.button is 4) event.stateMask &= ~DWT.BUTTON4;
1519 // if (event.button is 5) event.stateMask &= ~DWT.BUTTON5;
1520 // break;
1521 // case DWT.MouseUp:
1522 // if (event.button is 1) event.stateMask |= DWT.BUTTON1;
1523 // if (event.button is 2) event.stateMask |= DWT.BUTTON2;
1524 // if (event.button is 3) event.stateMask |= DWT.BUTTON3;
1525 // if (event.button is 4) event.stateMask |= DWT.BUTTON4;
1526 // if (event.button is 5) event.stateMask |= DWT.BUTTON5;
1527 // break;
1528 // case DWT.KeyDown:
1529 // case DWT.Traverse:
1530 // if (event.keyCode is DWT.ALT) event.stateMask &= ~DWT.ALT;
1531 // if (event.keyCode is DWT.SHIFT) event.stateMask &= ~DWT.SHIFT;
1532 // if (event.keyCode is DWT.CONTROL) event.stateMask &= ~DWT.CONTROL;
1533 // break;
1534 // case DWT.KeyUp:
1535 // if (event.keyCode is DWT.ALT) event.stateMask |= DWT.ALT;
1536 // if (event.keyCode is DWT.SHIFT) event.stateMask |= DWT.SHIFT;
1537 // if (event.keyCode is DWT.CONTROL) event.stateMask |= DWT.CONTROL;
1538 // break;
1539 // }
1540 return true;
1541 }
1542
1543 void sendMouseEvent (NSEvent nsEvent, int type, int button) {
1544 Event event = new Event ();
1545 event.button = button;
1546 // event.detail = detail;
1547 event.count = nsEvent.clickCount();
1548 NSPoint location = nsEvent.locationInWindow();
1549 NSPoint point = view.convertPoint_fromView_(location, null);
1550 event.x = (int) point.x;
1551 event.y = (int) point.y;
1552 setInputState (event, nsEvent, type);
1553 sendEvent (type, event);
1554 }
1555
1556 void mouseDown(int theEvent) {
1557 NSEvent nsEvent = new NSEvent (theEvent);
1558 sendMouseEvent (nsEvent, DWT.MouseDown, 1);
1559 }
1560
1561 void mouseDragged(int theEvent) {
1562 NSEvent nsEvent = new NSEvent (theEvent);
1563 sendMouseEvent (nsEvent, DWT.MouseMove, 1);
1564 }
1565
1566 void mouseUp(int theEvent) {
1567 NSEvent nsEvent = new NSEvent (theEvent);
1568 sendMouseEvent (nsEvent, DWT.MouseUp, 1);
1569 }
1570
1571 bool sendKeyEvent (Event event) {
1572 sendEvent (event);
1573 return event.doit;
1574 }
1575
1576 //TODO - missing modifier keys (see flagsChanged:)
1577 bool sendKeyEvent (NSEvent nsEvent, int type) {
1578 if ((state & SAFARI_EVENTS_FIX) !is 0) return false;
1579 int count = 0;
1580 NSString keys = nsEvent.characters();
1581 //TODO - check lowercase doesn't mangle char codes
1582 NSString keyCodes = nsEvent.charactersIgnoringModifiers().lowercaseString();
1583 char [] chars = new char [keys.length()];
1584 for (int i=0; i<keys.length(); i++) {
1585 Event event = new Event ();
1586 int keyCode = Display.translateKey (keys.characterAtIndex (i) & 0xFFFF);
1587 if (keyCode !is 0) {
1588 event.keyCode = keyCode;
1589 } else {
1590 event.character = (char) keys.characterAtIndex (i);
1591 //TODO - get unshifted values for Shift+1
1592 event.keyCode = keyCodes.characterAtIndex (i);
1593 }
1594 setInputState (event, nsEvent, type);
1595 if (!setKeyState(event, type, nsEvent)) return false;
1596 if (sendKeyEvent (type, event)) {
1597 chars [count++] = chars [i];
1598 }
1599 }
1600 // if (count is 0) return false;
1601 if (count !is keys.length () - 1) {
1602 // OS.SetEventParameter (theEvent, OS.kEventParamKeyUnicodes, OS.typeUnicodeText, count * 2, chars);
1603 }
1604 return count is keys.length ();
1605 }
1606
1607 void markLayout (bool changed, bool all) {
1608 /* Do nothing */
1609 }
1610
1611 /**
1612 * Moves the receiver above the specified control in the
1613 * drawing order. If the argument is null, then the receiver
1614 * is moved to the top of the drawing order. The control at
1615 * the top of the drawing order will not be covered by other
1616 * controls even if they occupy intersecting areas.
1617 *
1618 * @param control the sibling control (or null)
1619 *
1620 * @exception IllegalArgumentException <ul>
1621 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
1622 * </ul>
1623 * @exception DWTException <ul>
1624 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1625 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1626 * </ul>
1627 *
1628 * @see Control#moveBelow
1629 * @see Composite#getChildren
1630 */
1631 public void moveAbove (Control control) {
1632 checkWidget();
1633 if (control !is null) {
1634 if (control.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
1635 if (parent !is control.parent) return;
1636 }
1637 setZOrder (control, true);
1638 }
1639
1640 /**
1641 * Moves the receiver below the specified control in the
1642 * drawing order. If the argument is null, then the receiver
1643 * is moved to the bottom of the drawing order. The control at
1644 * the bottom of the drawing order will be covered by all other
1645 * controls which occupy intersecting areas.
1646 *
1647 * @param control the sibling control (or null)
1648 *
1649 * @exception IllegalArgumentException <ul>
1650 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
1651 * </ul>
1652 * @exception DWTException <ul>
1653 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1654 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1655 * </ul>
1656 *
1657 * @see Control#moveAbove
1658 * @see Composite#getChildren
1659 */
1660 public void moveBelow (Control control) {
1661 checkWidget();
1662 if (control !is null) {
1663 if (control.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
1664 if (parent !is control.parent) return;
1665 }
1666 setZOrder (control, false);
1667 }
1668
1669 Accessible new_Accessible (Control control) {
1670 return Accessible.internal_new_Accessible (this);
1671 }
1672
1673 /**
1674 * Causes the receiver to be resized to its preferred size.
1675 * For a composite, this involves computing the preferred size
1676 * from its layout, if there is one.
1677 *
1678 * @exception DWTException <ul>
1679 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1680 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1681 * </ul>
1682 *
1683 * @see #computeSize(int, int, bool)
1684 */
1685 public void pack () {
1686 checkWidget();
1687 pack (true);
1688 }
1689
1690 /**
1691 * Causes the receiver to be resized to its preferred size.
1692 * For a composite, this involves computing the preferred size
1693 * from its layout, if there is one.
1694 * <p>
1695 * If the changed flag is <code>true</code>, it indicates that the receiver's
1696 * <em>contents</em> have changed, therefore any caches that a layout manager
1697 * containing the control may have been keeping need to be flushed. When the
1698 * control is resized, the changed flag will be <code>false</code>, so layout
1699 * manager caches can be retained.
1700 * </p>
1701 *
1702 * @param changed whether or not the receiver's contents have changed
1703 *
1704 * @exception DWTException <ul>
1705 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1706 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1707 * </ul>
1708 *
1709 * @see #computeSize(int, int, bool)
1710 */
1711 public void pack (bool changed) {
1712 checkWidget();
1713 setSize (computeSize (DWT.DEFAULT, DWT.DEFAULT, changed));
1714 }
1715
1716 public bool print (GC gc) {
1717 checkWidget ();
1718 if (gc is null) error (DWT.ERROR_NULL_ARGUMENT);
1719 if (gc.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
1720 // int [] outImage = new int [1];
1721 // CGRect outFrame = new CGRect ();
1722 // if (OS.HIViewCreateOffscreenImage (handle, 0, outFrame, outImage) is OS.noErr) {
1723 // int width = OS.CGImageGetWidth (outImage [0]);
1724 // int height = OS.CGImageGetHeight (outImage [0]);
1725 // CGRect rect = new CGRect();
1726 // rect.width = width;
1727 // rect.height = height;
1728 // //TODO - does not draw the browser (cocoa widgets?)
1729 // OS.HIViewDrawCGImage (gc.handle, rect, outImage [0]);
1730 // OS.CGImageRelease (outImage [0]);
1731 // }
1732 // return true;
1733 return false;
1734 }
1735
1736 /**
1737 * Causes the entire bounds of the receiver to be marked
1738 * as needing to be redrawn. The next time a paint request
1739 * is processed, the control will be completely painted,
1740 * including the background.
1741 *
1742 * @exception DWTException <ul>
1743 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1744 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1745 * </ul>
1746 *
1747 * @see #update()
1748 * @see PaintListener
1749 * @see DWT#Paint
1750 * @see DWT#NO_BACKGROUND
1751 * @see DWT#NO_REDRAW_RESIZE
1752 * @see DWT#NO_MERGE_PAINTS
1753 * @see DWT#DOUBLE_BUFFERED
1754 */
1755 public void redraw () {
1756 checkWidget();
1757 view.setNeedsDisplay(true);
1758 }
1759
1760 void redraw (bool children) {
1761 // checkWidget();
1762
1763 }
1764
1765 /**
1766 * Causes the rectangular area of the receiver specified by
1767 * the arguments to be marked as needing to be redrawn.
1768 * The next time a paint request is processed, that area of
1769 * the receiver will be painted, including the background.
1770 * If the <code>all</code> flag is <code>true</code>, any
1771 * children of the receiver which intersect with the specified
1772 * area will also paint their intersecting areas. If the
1773 * <code>all</code> flag is <code>false</code>, the children
1774 * will not be painted.
1775 *
1776 * @param x the x coordinate of the area to draw
1777 * @param y the y coordinate of the area to draw
1778 * @param width the width of the area to draw
1779 * @param height the height of the area to draw
1780 * @param all <code>true</code> if children should redraw, and <code>false</code> otherwise
1781 *
1782 * @exception DWTException <ul>
1783 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1784 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1785 * </ul>
1786 *
1787 * @see #update()
1788 * @see PaintListener
1789 * @see DWT#Paint
1790 * @see DWT#NO_BACKGROUND
1791 * @see DWT#NO_REDRAW_RESIZE
1792 * @see DWT#NO_MERGE_PAINTS
1793 * @see DWT#DOUBLE_BUFFERED
1794 */
1795 public void redraw (int x, int y, int width, int height, bool all) {
1796 checkWidget ();
1797 NSRect rect = new NSRect();
1798 rect.x = x;
1799 rect.y = y;
1800 rect.width = width;
1801 rect.height = height;
1802 view.setNeedsDisplayInRect(rect);
1803 }
1804
1805 void releaseHandle () {
1806 super.releaseHandle ();
1807 if (view !is null) {
1808 OS.objc_msgSend(view.id, OS.sel_setTag_1, -1);
1809 view.release();
1810 }
1811 view = null;
1812 parent = null;
1813 }
1814
1815 void releaseParent () {
1816 // setVisible (topHandle (), false);
1817 parent.removeControl (this);
1818 }
1819
1820 void releaseWidget () {
1821 super.releaseWidget ();
1822 if (menu !is null && !menu.isDisposed ()) {
1823 menu.dispose ();
1824 }
1825 menu = null;
1826 layoutData = null;
1827 if (accessible !is null) {
1828 accessible.internal_dispose_Accessible ();
1829 }
1830 accessible = null;
1831 region = null;
1832 }
1833
1834 /**
1835 * Removes the listener from the collection of listeners who will
1836 * be notified when the control is moved or resized.
1837 *
1838 * @param listener the listener which should no longer be notified
1839 *
1840 * @exception IllegalArgumentException <ul>
1841 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1842 * </ul>
1843 * @exception DWTException <ul>
1844 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1845 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1846 * </ul>
1847 *
1848 * @see ControlListener
1849 * @see #addControlListener
1850 */
1851 public void removeControlListener (ControlListener listener) {
1852 checkWidget();
1853 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
1854 if (eventTable is null) return;
1855 eventTable.unhook (DWT.Move, listener);
1856 eventTable.unhook (DWT.Resize, listener);
1857 }
1858
1859 /**
1860 * Removes the listener from the collection of listeners who will
1861 * be notified when a drag gesture occurs.
1862 *
1863 * @param listener the listener which should no longer be notified
1864 *
1865 * @exception IllegalArgumentException <ul>
1866 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1867 * </ul>
1868 * @exception DWTException <ul>
1869 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1870 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1871 * </ul>
1872 *
1873 * @see DragDetectListener
1874 * @see #addDragDetectListener
1875 *
1876 * @since 3.3
1877 */
1878 public void removeDragDetectListener(DragDetectListener listener) {
1879 checkWidget ();
1880 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
1881 if (eventTable is null) return;
1882 eventTable.unhook (DWT.DragDetect, listener);
1883 }
1884
1885 /**
1886 * Removes the listener from the collection of listeners who will
1887 * be notified when the control gains or loses focus.
1888 *
1889 * @param listener the listener which should no longer be notified
1890 *
1891 * @exception IllegalArgumentException <ul>
1892 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1893 * </ul>
1894 * @exception DWTException <ul>
1895 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1896 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1897 * </ul>
1898 *
1899 * @see FocusListener
1900 * @see #addFocusListener
1901 */
1902 public void removeFocusListener(FocusListener listener) {
1903 checkWidget();
1904 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
1905 if (eventTable is null) return;
1906 eventTable.unhook(DWT.FocusIn, listener);
1907 eventTable.unhook(DWT.FocusOut, listener);
1908 }
1909
1910 /**
1911 * Removes the listener from the collection of listeners who will
1912 * be notified when the help events are generated for the control.
1913 *
1914 * @param listener the listener which should no longer be notified
1915 *
1916 * @exception IllegalArgumentException <ul>
1917 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1918 * </ul>
1919 * @exception DWTException <ul>
1920 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1921 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1922 * </ul>
1923 *
1924 * @see HelpListener
1925 * @see #addHelpListener
1926 */
1927 public void removeHelpListener (HelpListener listener) {
1928 checkWidget();
1929 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
1930 if (eventTable is null) return;
1931 eventTable.unhook (DWT.Help, listener);
1932 }
1933
1934 /**
1935 * Removes the listener from the collection of listeners who will
1936 * be notified when keys are pressed and released on the system keyboard.
1937 *
1938 * @param listener the listener which should no longer be notified
1939 *
1940 * @exception IllegalArgumentException <ul>
1941 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1942 * </ul>
1943 * @exception DWTException <ul>
1944 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1945 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1946 * </ul>
1947 *
1948 * @see KeyListener
1949 * @see #addKeyListener
1950 */
1951 public void removeKeyListener(KeyListener listener) {
1952 checkWidget();
1953 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
1954 if (eventTable is null) return;
1955 eventTable.unhook(DWT.KeyUp, listener);
1956 eventTable.unhook(DWT.KeyDown, listener);
1957 }
1958
1959 /**
1960 * Removes the listener from the collection of listeners who will
1961 * be notified when the platform-specific context menu trigger has
1962 * occurred.
1963 *
1964 * @param listener the listener which should no longer be notified
1965 *
1966 * @exception IllegalArgumentException <ul>
1967 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1968 * </ul>
1969 * @exception DWTException <ul>
1970 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1971 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1972 * </ul>
1973 *
1974 * @see MenuDetectListener
1975 * @see #addMenuDetectListener
1976 *
1977 * @since 3.3
1978 */
1979 public void removeMenuDetectListener (MenuDetectListener listener) {
1980 checkWidget ();
1981 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
1982 if (eventTable is null) return;
1983 eventTable.unhook (DWT.MenuDetect, listener);
1984 }
1985
1986 /**
1987 * Removes the listener from the collection of listeners who will
1988 * be notified when mouse buttons are pressed and released.
1989 *
1990 * @param listener the listener which should no longer be notified
1991 *
1992 * @exception IllegalArgumentException <ul>
1993 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1994 * </ul>
1995 * @exception DWTException <ul>
1996 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1997 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1998 * </ul>
1999 *
2000 * @see MouseListener
2001 * @see #addMouseListener
2002 */
2003 public void removeMouseListener(MouseListener listener) {
2004 checkWidget();
2005 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
2006 if (eventTable is null) return;
2007 eventTable.unhook(DWT.MouseDown, listener);
2008 eventTable.unhook(DWT.MouseUp, listener);
2009 eventTable.unhook(DWT.MouseDoubleClick, listener);
2010 }
2011
2012 /**
2013 * Removes the listener from the collection of listeners who will
2014 * be notified when the mouse moves.
2015 *
2016 * @param listener the listener which should no longer be notified
2017 *
2018 * @exception IllegalArgumentException <ul>
2019 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2020 * </ul>
2021 * @exception DWTException <ul>
2022 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2023 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2024 * </ul>
2025 *
2026 * @see MouseMoveListener
2027 * @see #addMouseMoveListener
2028 */
2029 public void removeMouseMoveListener(MouseMoveListener listener) {
2030 checkWidget();
2031 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
2032 if (eventTable is null) return;
2033 eventTable.unhook(DWT.MouseMove, listener);
2034 }
2035
2036 /**
2037 * Removes the listener from the collection of listeners who will
2038 * be notified when the mouse passes or hovers over controls.
2039 *
2040 * @param listener the listener which should no longer be notified
2041 *
2042 * @exception IllegalArgumentException <ul>
2043 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2044 * </ul>
2045 * @exception DWTException <ul>
2046 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2047 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2048 * </ul>
2049 *
2050 * @see MouseTrackListener
2051 * @see #addMouseTrackListener
2052 */
2053 public void removeMouseTrackListener(MouseTrackListener listener) {
2054 checkWidget();
2055 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
2056 if (eventTable is null) return;
2057 eventTable.unhook (DWT.MouseEnter, listener);
2058 eventTable.unhook (DWT.MouseExit, listener);
2059 eventTable.unhook (DWT.MouseHover, listener);
2060 }
2061
2062 /**
2063 * Removes the listener from the collection of listeners who will
2064 * be notified when the mouse wheel is scrolled.
2065 *
2066 * @param listener the listener which should no longer be notified
2067 *
2068 * @exception IllegalArgumentException <ul>
2069 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2070 * </ul>
2071 * @exception DWTException <ul>
2072 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2073 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2074 * </ul>
2075 *
2076 * @see MouseWheelListener
2077 * @see #addMouseWheelListener
2078 *
2079 * @since 3.3
2080 */
2081 public void removeMouseWheelListener (MouseWheelListener listener) {
2082 checkWidget ();
2083 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
2084 if (eventTable is null) return;
2085 eventTable.unhook (DWT.MouseWheel, listener);
2086 }
2087
2088 /**
2089 * Removes the listener from the collection of listeners who will
2090 * be notified when the receiver needs to be painted.
2091 *
2092 * @param listener the listener which should no longer be notified
2093 *
2094 * @exception IllegalArgumentException <ul>
2095 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2096 * </ul>
2097 * @exception DWTException <ul>
2098 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2099 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2100 * </ul>
2101 *
2102 * @see PaintListener
2103 * @see #addPaintListener
2104 */
2105 public void removePaintListener(PaintListener listener) {
2106 checkWidget();
2107 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
2108 if (eventTable is null) return;
2109 eventTable.unhook(DWT.Paint, listener);
2110 }
2111
2112 /**
2113 * Removes the listener from the collection of listeners who will
2114 * be notified when traversal events occur.
2115 *
2116 * @param listener the listener which should no longer be notified
2117 *
2118 * @exception IllegalArgumentException <ul>
2119 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2120 * </ul>
2121 * @exception DWTException <ul>
2122 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2123 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2124 * </ul>
2125 *
2126 * @see TraverseListener
2127 * @see #addTraverseListener
2128 */
2129 public void removeTraverseListener(TraverseListener listener) {
2130 checkWidget();
2131 if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
2132 if (eventTable is null) return;
2133 eventTable.unhook (DWT.Traverse, listener);
2134 }
2135
2136 bool sendDragEvent (int button, int stateMask, int x, int y) {
2137 Event event = new Event ();
2138 event.button = button;
2139 event.x = x;
2140 event.y = y;
2141 event.stateMask = stateMask;
2142 postEvent (DWT.DragDetect, event);
2143 return event.doit;
2144 }
2145
2146 bool sendDragEvent (int button, int chord, int modifiers, int x, int y) {
2147 Event event = new Event ();
2148 switch (button) {
2149 case 1: event.button = 1; break;
2150 case 2: event.button = 3; break;
2151 case 3: event.button = 2; break;
2152 case 4: event.button = 4; break;
2153 case 5: event.button = 5; break;
2154 }
2155 event.x = x;
2156 event.y = y;
2157 setInputState (event, DWT.DragDetect, chord, modifiers);
2158 postEvent (DWT.DragDetect, event);
2159 return event.doit;
2160 }
2161
2162 void sendFocusEvent (int type, bool post) {
2163 Display display = this.display;
2164 Shell shell = getShell ();
2165 /*
2166 * Feature in the Macintosh. GetKeyboardFocus() returns NULL during
2167 * kEventControlSetFocusPart if the focus part is not kControlFocusNoPart.
2168 * The fix is to remember the focus control and return it during
2169 * kEventControlSetFocusPart.
2170 */
2171 // display.focusControl = this;
2172 // display.focusEvent = type;
2173 if (post) {
2174 postEvent (type);
2175 } else {
2176 sendEvent (type);
2177 }
2178 /*
2179 * It is possible that the shell may be
2180 * disposed at this point. If this happens
2181 * don't send the activate and deactivate
2182 * events.
2183 */
2184 if (!shell.isDisposed ()) {
2185 switch (type) {
2186 case DWT.FocusIn:
2187 shell.setActiveControl (this);
2188 break;
2189 case DWT.FocusOut:
2190 if (shell !is display.getActiveShell ()) {
2191 shell.setActiveControl (null);
2192 }
2193 break;
2194 }
2195 }
2196 // display.focusEvent = DWT.None;
2197 // display.focusControl = null;
2198 }
2199
2200 bool sendMouseEvent (int type, short button, int count, int detail, bool send, int theEvent) {
2201 // CGPoint pt = new CGPoint ();
2202 // OS.GetEventParameter (theEvent, OS.kEventParamWindowMouseLocation, OS.typeHIPoint, null, CGPoint.sizeof, null, pt);
2203 // OS.HIViewConvertPoint (pt, 0, handle);
2204 // int x = (int) pt.x;
2205 // int y = (int) pt.y;
2206 // display.lastX = x;
2207 // display.lastY = y;
2208 // int [] chord = new int [1];
2209 // OS.GetEventParameter (theEvent, OS.kEventParamMouseChord, OS.typeUInt32, null, 4, null, chord);
2210 // int [] modifiers = new int [1];
2211 // OS.GetEventParameter (theEvent, OS.kEventParamKeyModifiers, OS.typeUInt32, null, 4, null, modifiers);
2212 // return sendMouseEvent (type, button, count, detail, send, chord [0], (short) x, (short) y, modifiers [0]);
2213 return false;
2214 }
2215
2216 bool sendMouseEvent (int type, short button, int count, bool send, int chord, short x, short y, int modifiers) {
2217 return sendMouseEvent (type, button, count, 0, send, chord, x, y, modifiers);
2218 }
2219
2220 bool sendMouseEvent (int type, short button, int count, int detail, bool send, int chord, short x, short y, int modifiers) {
2221 if (!hooks (type) && !filters (type)) return true;
2222 Event event = new Event ();
2223 switch (button) {
2224 case 1: event.button = 1; break;
2225 case 2: event.button = 3; break;
2226 case 3: event.button = 2; break;
2227 case 4: event.button = 4; break;
2228 case 5: event.button = 5; break;
2229 }
2230 event.x = x;
2231 event.y = y;
2232 event.count = count;
2233 event.detail = detail;
2234 setInputState (event, type, chord, modifiers);
2235 if (send) {
2236 sendEvent (type, event);
2237 if (isDisposed ()) return false;
2238 } else {
2239 postEvent (type, event);
2240 }
2241 return event.doit;
2242 }
2243
2244 bool sendMouseWheel (short wheelAxis, int wheelDelta) {
2245 return false;
2246 }
2247
2248 void setBackground () {
2249 // redrawWidget (handle, false);
2250 }
2251
2252 /**
2253 * Sets the receiver's background color to the color specified
2254 * by the argument, or to the default system color for the control
2255 * if the argument is null.
2256 * <p>
2257 * Note: This operation is a hint and may be overridden by the platform.
2258 * For example, on Windows the background of a Button cannot be changed.
2259 * </p>
2260 * @param color the new color (or null)
2261 *
2262 * @exception IllegalArgumentException <ul>
2263 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
2264 * </ul>
2265 * @exception DWTException <ul>
2266 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2267 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2268 * </ul>
2269 */
2270 public void setBackground (Color color) {
2271 checkWidget();
2272 if (color !is null) {
2273 if (color.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
2274 }
2275 // if (equals (background, this.background)) return;
2276 this.background = color;
2277 setBackground (color !is null ? color.handle : null);
2278 view.setNeedsDisplay(true);
2279 }
2280
2281 /**
2282 * Sets the receiver's background image to the image specified
2283 * by the argument, or to the default system color for the control
2284 * if the argument is null. The background image is tiled to fill
2285 * the available space.
2286 * <p>
2287 * Note: This operation is a hint and may be overridden by the platform.
2288 * For example, on Windows the background of a Button cannot be changed.
2289 * </p>
2290 * @param image the new image (or null)
2291 *
2292 * @exception IllegalArgumentException <ul>
2293 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
2294 * <li>ERROR_INVALID_ARGUMENT - if the argument is not a bitmap</li>
2295 * </ul>
2296 * @exception DWTException <ul>
2297 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2298 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2299 * </ul>
2300 *
2301 * @since 3.2
2302 */
2303 public void setBackgroundImage (Image image) {
2304 checkWidget();
2305 if (image !is null && image.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
2306 if (image is backgroundImage) return;
2307 backgroundImage = image;
2308 // redrawWidget (handle, false);
2309 }
2310
2311 void setBackground (float [] color) {
2312 }
2313
2314 void setBackground (int control, float [] color) {
2315 // ControlFontStyleRec fontStyle = new ControlFontStyleRec ();
2316 // OS.GetControlData (control, (short) OS.kControlEntireControl, OS.kControlFontStyleTag, ControlFontStyleRec.sizeof, fontStyle, null);
2317 // if (color !is null) {
2318 // fontStyle.backColor_red = (short) (color [0] * 0xffff);
2319 // fontStyle.backColor_green = (short) (color [1] * 0xffff);
2320 // fontStyle.backColor_blue = (short) (color [2] * 0xffff);
2321 // fontStyle.flags |= OS.kControlUseBackColorMask;
2322 // } else {
2323 // fontStyle.flags &= ~OS.kControlUseBackColorMask;
2324 // }
2325 // OS.SetControlFontStyle (control, fontStyle);
2326 }
2327
2328 /**
2329 * Sets the receiver's size and location to the rectangular
2330 * area specified by the arguments. The <code>x</code> and
2331 * <code>y</code> arguments are relative to the receiver's
2332 * parent (or its display if its parent is null), unless
2333 * the receiver is a shell. In this case, the <code>x</code>
2334 * and <code>y</code> arguments are relative to the display.
2335 * <p>
2336 * Note: Attempting to set the width or height of the
2337 * receiver to a negative number will cause that
2338 * value to be set to zero instead.
2339 * </p>
2340 *
2341 * @param x the new x coordinate for the receiver
2342 * @param y the new y coordinate for the receiver
2343 * @param width the new width for the receiver
2344 * @param height the new height for the receiver
2345 *
2346 * @exception DWTException <ul>
2347 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2348 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2349 * </ul>
2350 */
2351 public void setBounds (int x, int y, int width, int height) {
2352 checkWidget();
2353 setBounds (x, y, Math.max (0, width), Math.max (0, height), true, true);
2354 }
2355
2356 int setBounds (int x, int y, int width, int height, bool move, bool resize) {
2357 int result = 0;
2358 NSView topView = topView();
2359 NSRect rect = topView.frame();
2360 if (move && resize) {
2361 if (rect.x !is x || rect.y !is y) result |= MOVED;
2362 if (rect.width !is width || rect.height !is height) result |= RESIZED;
2363 if (result !is 0) {
2364 rect.x = x;
2365 rect.y = y;
2366 rect.width = width;
2367 rect.height = height;
2368 topView.setFrame (rect);
2369 }
2370 } else if (move) {
2371 if (rect.x !is x || rect.y !is y) {
2372 result |= MOVED;
2373 NSPoint point = new NSPoint();
2374 point.x = x;
2375 point.y = y;
2376 topView.setFrameOrigin(point);
2377 }
2378 } else if (resize) {
2379 if (rect.width !is width || rect.height !is height) {
2380 result |= RESIZED;
2381 NSSize size = new NSSize();
2382 size.width = width;
2383 size.height = height;
2384 topView.setFrameSize(size);
2385 }
2386 }
2387 if ((result & MOVED) !is 0) {
2388 sendEvent(DWT.Move);
2389 }
2390 if ((result & RESIZED) !is 0) {
2391 sendEvent(DWT.Resize);
2392 }
2393 return result;
2394 }
2395
2396 /**
2397 * Sets the receiver's size and location to the rectangular
2398 * area specified by the argument. The <code>x</code> and
2399 * <code>y</code> fields of the rectangle are relative to
2400 * the receiver's parent (or its display if its parent is null).
2401 * <p>
2402 * Note: Attempting to set the width or height of the
2403 * receiver to a negative number will cause that
2404 * value to be set to zero instead.
2405 * </p>
2406 *
2407 * @param rect the new bounds for the receiver
2408 *
2409 * @exception DWTException <ul>
2410 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2411 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2412 * </ul>
2413 */
2414 public void setBounds (Rectangle rect) {
2415 checkWidget ();
2416 if (rect is null) error (DWT.ERROR_NULL_ARGUMENT);
2417 setBounds (rect.x, rect.y, Math.max (0, rect.width), Math.max (0, rect.height), true, true);
2418 }
2419
2420 /**
2421 * If the argument is <code>true</code>, causes the receiver to have
2422 * all mouse events delivered to it until the method is called with
2423 * <code>false</code> as the argument.
2424 *
2425 * @param capture <code>true</code> to capture the mouse, and <code>false</code> to release it
2426 *
2427 * @exception DWTException <ul>
2428 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2429 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2430 * </ul>
2431 */
2432 public void setCapture (bool capture) {
2433 checkWidget();
2434 }
2435
2436 /**
2437 * Sets the receiver's cursor to the cursor specified by the
2438 * argument, or to the default cursor for that kind of control
2439 * if the argument is null.
2440 * <p>
2441 * When the mouse pointer passes over a control its appearance
2442 * is changed to match the control's cursor.
2443 * </p>
2444 *
2445 * @param cursor the new cursor (or null)
2446 *
2447 * @exception IllegalArgumentException <ul>
2448 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
2449 * </ul>
2450 * @exception DWTException <ul>
2451 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2452 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2453 * </ul>
2454 */
2455 public void setCursor (Cursor cursor) {
2456 checkWidget();
2457 if (cursor !is null && cursor.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
2458 this.cursor = cursor;
2459 //TODO null
2460 // view.addCursorRect(view.frame(), cursor.handle);
2461 }
2462
2463 void setDefaultFont () {
2464 // if (display.smallFonts) setFontStyle (defaultFont ());
2465 }
2466
2467 /**
2468 * Sets the receiver's drag detect state. If the argument is
2469 * <code>true</code>, the receiver will detect drag gestures,
2470 * otherwise these gestures will be ignored.
2471 *
2472 * @param dragDetect the new drag detect state
2473 *
2474 * @exception DWTException <ul>
2475 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2476 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2477 * </ul>
2478 *
2479 * @since 3.3
2480 */
2481 public void setDragDetect (bool dragDetect) {
2482 checkWidget ();
2483 if (dragDetect) {
2484 state |= DRAG_DETECT;
2485 } else {
2486 state &= ~DRAG_DETECT;
2487 }
2488 }
2489
2490 /**
2491 * Enables the receiver if the argument is <code>true</code>,
2492 * and disables it otherwise. A disabled control is typically
2493 * not selectable from the user interface and draws with an
2494 * inactive or "grayed" look.
2495 *
2496 * @param enabled the new enabled state
2497 *
2498 * @exception DWTException <ul>
2499 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2500 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2501 * </ul>
2502 */
2503 public void setEnabled (bool enabled) {
2504 checkWidget();
2505 if (((state & DISABLED) is 0) is enabled) return;
2506 Control control = null;
2507 bool fixFocus = false;
2508 if (!enabled) {
2509 // if (display.focusEvent !is DWT.FocusOut) {
2510 control = display.getFocusControl ();
2511 fixFocus = isFocusAncestor (control);
2512 // }
2513 }
2514 if (enabled) {
2515 state &= ~DISABLED;
2516 } else {
2517 state |= DISABLED;
2518 }
2519 enableWidget (enabled);
2520 if (fixFocus) fixFocus (control);
2521 }
2522
2523 /**
2524 * Causes the receiver to have the <em>keyboard focus</em>,
2525 * such that all keyboard events will be delivered to it. Focus
2526 * reassignment will respect applicable platform constraints.
2527 *
2528 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
2529 *
2530 * @exception DWTException <ul>
2531 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2532 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2533 * </ul>
2534 *
2535 * @see #forceFocus
2536 */
2537 public bool setFocus () {
2538 checkWidget();
2539 if ((style & DWT.NO_FOCUS) !is 0) return false;
2540 return forceFocus ();
2541 }
2542
2543 /**
2544 * Sets the font that the receiver will use to paint textual information
2545 * to the font specified by the argument, or to the default font for that
2546 * kind of control if the argument is null.
2547 *
2548 * @param font the new font (or null)
2549 *
2550 * @exception IllegalArgumentException <ul>
2551 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
2552 * </ul>
2553 * @exception DWTException <ul>
2554 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2555 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2556 * </ul>
2557 */
2558 public void setFont (Font font) {
2559 checkWidget();
2560 if (font !is null) {
2561 if (font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
2562 }
2563 this.font = font;
2564 setFont (font !is null ? font.handle : defaultFont().handle);
2565 }
2566
2567 void setFont (NSFont font) {
2568 //TODO - bad cast
2569 if (view instanceof NSControl) {
2570 ((NSControl)view).setFont(font);
2571 }
2572 }
2573
2574 /**
2575 * Sets the receiver's foreground color to the color specified
2576 * by the argument, or to the default system color for the control
2577 * if the argument is null.
2578 * <p>
2579 * Note: This operation is a hint and may be overridden by the platform.
2580 * </p>
2581 * @param color the new color (or null)
2582 *
2583 * @exception IllegalArgumentException <ul>
2584 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
2585 * </ul>
2586 * @exception DWTException <ul>
2587 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2588 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2589 * </ul>
2590 */
2591 public void setForeground (Color color) {
2592 checkWidget();
2593 if (color !is null) {
2594 if (color.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
2595 }
2596 // if (equals (foreground, this.foreground)) return;
2597 this.foreground = color;
2598 setForeground (color !is null ? color.handle : null);
2599 view.setNeedsDisplay(true);
2600 }
2601
2602 void setForeground (float [] color) {
2603 }
2604
2605 void setForeground (int control, float [] color) {
2606 // ControlFontStyleRec fontStyle = new ControlFontStyleRec ();
2607 // OS.GetControlData (control, (short) OS.kControlEntireControl, OS.kControlFontStyleTag, ControlFontStyleRec.sizeof, fontStyle, null);
2608 // if (color !is null) {
2609 // fontStyle.foreColor_red = (short) (color [0] * 0xffff);
2610 // fontStyle.foreColor_green = (short) (color [1] * 0xffff);
2611 // fontStyle.foreColor_blue = (short) (color [2] * 0xffff);
2612 // fontStyle.flags |= OS.kControlUseForeColorMask;
2613 // } else {
2614 // fontStyle.flags &= ~OS.kControlUseForeColorMask;
2615 // }
2616 // OS.SetControlFontStyle (control, fontStyle);
2617 }
2618
2619 /**
2620 * Sets the layout data associated with the receiver to the argument.
2621 *
2622 * @param layoutData the new layout data for the receiver.
2623 *
2624 * @exception DWTException <ul>
2625 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2626 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2627 * </ul>
2628 */
2629 public void setLayoutData (Object layoutData) {
2630 checkWidget();
2631 this.layoutData = layoutData;
2632 }
2633
2634 /**
2635 * Sets the receiver's location to the point specified by
2636 * the arguments which are relative to the receiver's
2637 * parent (or its display if its parent is null), unless
2638 * the receiver is a shell. In this case, the point is
2639 * relative to the display.
2640 *
2641 * @param x the new x coordinate for the receiver
2642 * @param y the new y coordinate for the receiver
2643 *
2644 * @exception DWTException <ul>
2645 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2646 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2647 * </ul>
2648 */
2649 public void setLocation (int x, int y) {
2650 checkWidget();
2651 setBounds (x, y, 0, 0, true, false);
2652 }
2653
2654 /**
2655 * Sets the receiver's location to the point specified by
2656 * the arguments which are relative to the receiver's
2657 * parent (or its display if its parent is null), unless
2658 * the receiver is a shell. In this case, the point is
2659 * relative to the display.
2660 *
2661 * @param location the new location for the receiver
2662 *
2663 * @exception DWTException <ul>
2664 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2665 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2666 * </ul>
2667 */
2668 public void setLocation (Point location) {
2669 checkWidget();
2670 if (location is null) error (DWT.ERROR_NULL_ARGUMENT);
2671 setBounds (location.x, location.y, 0, 0, true, false);
2672 }
2673
2674 /**
2675 * Sets the receiver's pop up menu to the argument.
2676 * All controls may optionally have a pop up
2677 * menu that is displayed when the user requests one for
2678 * the control. The sequence of key strokes, button presses
2679 * and/or button releases that are used to request a pop up
2680 * menu is platform specific.
2681 * <p>
2682 * Note: Disposing of a control that has a pop up menu will
2683 * dispose of the menu. To avoid this behavior, set the
2684 * menu to null before the control is disposed.
2685 * </p>
2686 *
2687 * @param menu the new pop up menu
2688 *
2689 * @exception IllegalArgumentException <ul>
2690 * <li>ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu</li>
2691 * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
2692 * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
2693 * </ul>
2694 * @exception DWTException <ul>
2695 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2696 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2697 * </ul>
2698 */
2699 public void setMenu (Menu menu) {
2700 checkWidget();
2701 if (menu !is null) {
2702 if (menu.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
2703 if ((menu.style & DWT.POP_UP) is 0) {
2704 error (DWT.ERROR_MENU_NOT_POP_UP);
2705 }
2706 if (menu.parent !is menuShell ()) {
2707 error (DWT.ERROR_INVALID_PARENT);
2708 }
2709 }
2710 this.menu = menu;
2711 }
2712
2713 /**
2714 * Changes the parent of the widget to be the one provided if
2715 * the underlying operating system supports this feature.
2716 * Returns <code>true</code> if the parent is successfully changed.
2717 *
2718 * @param parent the new parent for the control.
2719 * @return <code>true</code> if the parent is changed and <code>false</code> otherwise.
2720 *
2721 * @exception IllegalArgumentException <ul>
2722 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
2723 * <li>ERROR_NULL_ARGUMENT - if the parent is <code>null</code></li>
2724 * </ul>
2725 * @exception DWTException <ul>
2726 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2727 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2728 * </ul>
2729 */
2730 public bool setParent (Composite parent) {
2731 checkWidget();
2732 if (parent is null) error (DWT.ERROR_NULL_ARGUMENT);
2733 if (parent.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
2734 if (this.parent is parent) return true;
2735 if (!isReparentable ()) return false;
2736 releaseParent ();
2737 Shell newShell = parent.getShell (), oldShell = getShell ();
2738 Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell ();
2739 if (oldShell !is newShell || oldDecorations !is newDecorations) {
2740 Menu [] menus = oldShell.findMenus (this);
2741 fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
2742 }
2743 // int topHandle = topHandle ();
2744 // OS.HIViewAddSubview (parent.handle, topHandle);
2745 // OS.HIViewSetVisible (topHandle, (state & HIDDEN) is 0);
2746 // OS.HIViewSetZOrder (topHandle, OS.kHIViewZOrderBelow, 0);
2747 this.parent = parent;
2748 return true;
2749 }
2750
2751 /**
2752 * If the argument is <code>false</code>, causes subsequent drawing
2753 * operations in the receiver to be ignored. No drawing of any kind
2754 * can occur in the receiver until the flag is set to true.
2755 * Graphics operations that occurred while the flag was
2756 * <code>false</code> are lost. When the flag is set to <code>true</code>,
2757 * the entire widget is marked as needing to be redrawn. Nested calls
2758 * to this method are stacked.
2759 * <p>
2760 * Note: This operation is a hint and may not be supported on some
2761 * platforms or for some widgets.
2762 * </p>
2763 *
2764 * @param redraw the new redraw state
2765 *
2766 * @exception DWTException <ul>
2767 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2768 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2769 * </ul>
2770 *
2771 * @see #redraw(int, int, int, int, bool)
2772 * @see #update()
2773 */
2774 public void setRedraw (bool redraw) {
2775 checkWidget();
2776 if (redraw) {
2777 if (--drawCount is 0) {
2778 // OS.HIViewSetDrawingEnabled (handle, true);
2779 // invalidateVisibleRegion (handle);
2780 // redrawWidget (handle, true);
2781 }
2782 } else {
2783 if (drawCount is 0) {
2784 // OS.HIViewSetDrawingEnabled (handle, false);
2785 // invalidateVisibleRegion (handle);
2786 }
2787 drawCount++;
2788 }
2789 }
2790
2791 public void setRegion (Region region) {
2792 checkWidget ();
2793 if (region !is null && region.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT);
2794 this.region = region;
2795 // redrawWidget (handle, true);
2796 }
2797
2798 bool setRadioSelection (bool value){
2799 return false;
2800 }
2801
2802 /**
2803 * Sets the receiver's size to the point specified by the arguments.
2804 * <p>
2805 * Note: Attempting to set the width or height of the
2806 * receiver to a negative number will cause that
2807 * value to be set to zero instead.
2808 * </p>
2809 *
2810 * @param width the new width for the receiver
2811 * @param height the new height for the receiver
2812 *
2813 * @exception DWTException <ul>
2814 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2815 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2816 * </ul>
2817 */
2818 public void setSize (int width, int height) {
2819 checkWidget();
2820 setBounds (0, 0, Math.max (0, width), Math.max (0, height), false, true);
2821 }
2822
2823 /**
2824 * Sets the receiver's size to the point specified by the argument.
2825 * <p>
2826 * Note: Attempting to set the width or height of the
2827 * receiver to a negative number will cause them to be
2828 * set to zero instead.
2829 * </p>
2830 *
2831 * @param size the new size for the receiver
2832 *
2833 * @exception IllegalArgumentException <ul>
2834 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
2835 * </ul>
2836 * @exception DWTException <ul>
2837 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2838 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2839 * </ul>
2840 */
2841 public void setSize (Point size) {
2842 checkWidget ();
2843 if (size is null) error (DWT.ERROR_NULL_ARGUMENT);
2844 setBounds (0, 0, Math.max (0, size.x), Math.max (0, size.y), false, true);
2845 }
2846
2847 bool setTabGroupFocus () {
2848 return setTabItemFocus ();
2849 }
2850
2851 bool setTabItemFocus () {
2852 if (!isShowing ()) return false;
2853 return forceFocus ();
2854 }
2855
2856 /**
2857 * Sets the receiver's tool tip text to the argument, which
2858 * may be null indicating that no tool tip text should be shown.
2859 *
2860 * @param string the new tool tip text (or null)
2861 *
2862 * @exception DWTException <ul>
2863 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2864 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2865 * </ul>
2866 */
2867 public void setToolTipText (String string) {
2868 checkWidget();
2869 toolTipText = string;
2870 view.setToolTip(string !is null ? NSString.stringWith(string) : null);
2871 }
2872
2873 /**
2874 * Marks the receiver as visible if the argument is <code>true</code>,
2875 * and marks it invisible otherwise.
2876 * <p>
2877 * If one of the receiver's ancestors is not visible or some
2878 * other condition makes the receiver not visible, marking
2879 * it visible may not actually cause it to be displayed.
2880 * </p>
2881 *
2882 * @param visible the new visibility state
2883 *
2884 * @exception DWTException <ul>
2885 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2886 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2887 * </ul>
2888 */
2889 public void setVisible (bool visible) {
2890 checkWidget();
2891 if (visible) {
2892 if ((state & HIDDEN) is 0) return;
2893 state &= ~HIDDEN;
2894 } else {
2895 if ((state & HIDDEN) !is 0) return;
2896 state |= HIDDEN;
2897 }
2898 if (visible) {
2899 /*
2900 * It is possible (but unlikely), that application
2901 * code could have disposed the widget in the show
2902 * event. If this happens, just return.
2903 */
2904 sendEvent (DWT.Show);
2905 if (isDisposed ()) return;
2906 }
2907
2908 /*
2909 * Feature in the Macintosh. If the receiver has focus, hiding
2910 * the receiver causes no control to have focus. Also, the focus
2911 * needs to be cleared from any TXNObject so that it stops blinking
2912 * the caret. The fix is to assign focus to the first ancestor
2913 * control that takes focus. If no control will take focus, clear
2914 * the focus control.
2915 */
2916 Control control = null;
2917 bool fixFocus = false;
2918 if (!visible) {
2919 // if (display.focusEvent !is DWT.FocusOut) {
2920 control = display.getFocusControl ();
2921 fixFocus = isFocusAncestor (control);
2922 // }
2923 }
2924 topView().setHidden(!visible);
2925 if (!visible) {
2926 /*
2927 * It is possible (but unlikely), that application
2928 * code could have disposed the widget in the show
2929 * event. If this happens, just return.
2930 */
2931 sendEvent (DWT.Hide);
2932 if (isDisposed ()) return;
2933 }
2934 if (fixFocus) fixFocus (control);
2935 }
2936
2937 void setZOrder () {
2938 // int topHandle = topHandle ();
2939 // int parentHandle = parent.handle;
2940 // OS.HIViewAddSubview (parentHandle, topHandle);
2941 // OS.HIViewSetZOrder (topHandle, OS.kHIViewZOrderBelow, 0);
2942 // Rect rect = getInset ();
2943 // rect.right = rect.left;
2944 // rect.bottom = rect.top;
2945 // OS.SetControlBounds (topHandle, rect);
2946 }
2947
2948 void setZOrder (Control control, bool above) {
2949 NSView otherView = control is null ? null : control.topView ();
2950 view.retain();
2951 view.removeFromSuperview();
2952 parent.contentView().addSubview_positioned_relativeTo_(view, above ? OS.NSWindowAbove : OS.NSWindowBelow, otherView);
2953 view.release();
2954 }
2955
2956 void sort (int [] items) {
2957 /* Shell Sort from K&R, pg 108 */
2958 int length = items.length;
2959 for (int gap=length/2; gap>0; gap/=2) {
2960 for (int i=gap; i<length; i++) {
2961 for (int j=i-gap; j>=0; j-=gap) {
2962 if (items [j] <= items [j + gap]) {
2963 int swap = items [j];
2964 items [j] = items [j + gap];
2965 items [j + gap] = swap;
2966 }
2967 }
2968 }
2969 }
2970 }
2971
2972 /**
2973 * Returns a point which is the result of converting the
2974 * argument, which is specified in display relative coordinates,
2975 * to coordinates relative to the receiver.
2976 * <p>
2977 * @param x the x coordinate to be translated
2978 * @param y the y coordinate to be translated
2979 * @return the translated coordinates
2980 *
2981 * @exception DWTException <ul>
2982 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2983 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2984 * </ul>
2985 *
2986 * @since 2.1
2987 */
2988 public Point toControl (int x, int y) {
2989 checkWidget();
2990 return display.map (null, this, x, y);
2991 }
2992
2993 /**
2994 * Returns a point which is the result of converting the
2995 * argument, which is specified in display relative coordinates,
2996 * to coordinates relative to the receiver.
2997 * <p>
2998 * @param point the point to be translated (must not be null)
2999 * @return the translated coordinates
3000 *
3001 * @exception IllegalArgumentException <ul>
3002 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
3003 * </ul>
3004 * @exception DWTException <ul>
3005 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3006 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3007 * </ul>
3008 */
3009 public Point toControl (Point point) {
3010 checkWidget();
3011 if (point is null) error (DWT.ERROR_NULL_ARGUMENT);
3012 return toControl (point.x, point.y);
3013 }
3014
3015 /**
3016 * Returns a point which is the result of converting the
3017 * argument, which is specified in coordinates relative to
3018 * the receiver, to display relative coordinates.
3019 * <p>
3020 * @param x the x coordinate to be translated
3021 * @param y the y coordinate to be translated
3022 * @return the translated coordinates
3023 *
3024 * @exception DWTException <ul>
3025 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3026 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3027 * </ul>
3028 *
3029 * @since 2.1
3030 */
3031 public Point toDisplay (int x, int y) {
3032 checkWidget();
3033 return display.map (this, null, x, y);
3034 }
3035
3036 /**
3037 * Returns a point which is the result of converting the
3038 * argument, which is specified in coordinates relative to
3039 * the receiver, to display relative coordinates.
3040 * <p>
3041 * @param point the point to be translated (must not be null)
3042 * @return the translated coordinates
3043 *
3044 * @exception IllegalArgumentException <ul>
3045 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
3046 * </ul>
3047 * @exception DWTException <ul>
3048 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3049 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3050 * </ul>
3051 */
3052 public Point toDisplay (Point point) {
3053 checkWidget();
3054 if (point is null) error (DWT.ERROR_NULL_ARGUMENT);
3055 return toDisplay (point.x, point.y);
3056 }
3057
3058 NSView topView () {
3059 return view;
3060 }
3061
3062 bool translateTraversal (int key, NSEvent theEvent, bool [] consume) {
3063 int detail = DWT.TRAVERSE_NONE;
3064 int code = traversalCode (key, theEvent);
3065 bool all = false;
3066 switch (key) {
3067 case 53: /* Esc */ {
3068 all = true;
3069 detail = DWT.TRAVERSE_ESCAPE;
3070 break;
3071 }
3072 case 76: /* KP Enter */
3073 case 36: /* Return */ {
3074 all = true;
3075 detail = DWT.TRAVERSE_RETURN;
3076 break;
3077 }
3078 case 48: /* Tab */ {
3079 int modifiers = display.lastModifiers;
3080 bool next = (modifiers & OS.NSShiftKeyMask) is 0;
3081 detail = next ? DWT.TRAVERSE_TAB_NEXT : DWT.TRAVERSE_TAB_PREVIOUS;
3082 break;
3083 }
3084 case 126: /* Up arrow */
3085 case 123: /* Left arrow */
3086 case 125: /* Down arrow */
3087 case 124: /* Right arrow */ {
3088 bool next = key is 125 /* Down arrow */ || key is 124 /* Right arrow */;
3089 detail = next ? DWT.TRAVERSE_ARROW_NEXT : DWT.TRAVERSE_ARROW_PREVIOUS;
3090 break;
3091 }
3092 case 116: /* Page up */
3093 case 121: /* Page down */ {
3094 all = true;
3095 // int [] modifiers = new int [1];
3096 // OS.GetEventParameter (theEvent, OS.kEventParamKeyModifiers, OS.typeUInt32, null, 4, null, modifiers);
3097 // if ((modifiers [0] & OS.controlKey) is 0) return false;
3098 // detail = key is 121 /* Page down */ ? DWT.TRAVERSE_PAGE_NEXT : DWT.TRAVERSE_PAGE_PREVIOUS;
3099 break;
3100 }
3101 default:
3102 return false;
3103 }
3104 Event event = new Event ();
3105 event.doit = consume [0] = (code & detail) !is 0;
3106 event.detail = detail;
3107 if (!setKeyState (event, DWT.Traverse, theEvent)) return false;
3108 Shell shell = getShell ();
3109 Control control = this;
3110 do {
3111 if (control.traverse (event)) return true;
3112 if (!event.doit && control.hooks (DWT.Traverse)) {
3113 return false;
3114 }
3115 if (control is shell) return false;
3116 control = control.parent;
3117 } while (all && control !is null);
3118 return false;
3119 }
3120
3121 int traversalCode (int key, NSEvent theEvent) {
3122 int code = DWT.TRAVERSE_RETURN | DWT.TRAVERSE_TAB_NEXT | DWT.TRAVERSE_TAB_PREVIOUS;
3123 Shell shell = getShell ();
3124 if (shell.parent !is null) code |= DWT.TRAVERSE_ESCAPE;
3125 return code;
3126 }
3127
3128 bool traverseMnemonic (char key) {
3129 return false;
3130 }
3131
3132 /**
3133 * Based on the argument, perform one of the expected platform
3134 * traversal action. The argument should be one of the constants:
3135 * <code>DWT.TRAVERSE_ESCAPE</code>, <code>DWT.TRAVERSE_RETURN</code>,
3136 * <code>DWT.TRAVERSE_TAB_NEXT</code>, <code>DWT.TRAVERSE_TAB_PREVIOUS</code>,
3137 * <code>DWT.TRAVERSE_ARROW_NEXT</code> and <code>DWT.TRAVERSE_ARROW_PREVIOUS</code>.
3138 *
3139 * @param traversal the type of traversal
3140 * @return true if the traversal succeeded
3141 *
3142 * @exception DWTException <ul>
3143 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3144 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3145 * </ul>
3146 */
3147 public bool traverse (int traversal) {
3148 checkWidget();
3149 Event event = new Event ();
3150 event.doit = true;
3151 event.detail = traversal;
3152 return traverse (event);
3153 }
3154
3155 bool traverse (Event event) {
3156 sendEvent (DWT.Traverse, event);
3157 if (isDisposed ()) return true;
3158 if (!event.doit) return false;
3159 switch (event.detail) {
3160 case DWT.TRAVERSE_NONE: return true;
3161 case DWT.TRAVERSE_ESCAPE: return traverseEscape ();
3162 case DWT.TRAVERSE_RETURN: return traverseReturn ();
3163 case DWT.TRAVERSE_TAB_NEXT: return traverseGroup (true);
3164 case DWT.TRAVERSE_TAB_PREVIOUS: return traverseGroup (false);
3165 case DWT.TRAVERSE_ARROW_NEXT: return traverseItem (true);
3166 case DWT.TRAVERSE_ARROW_PREVIOUS: return traverseItem (false);
3167 case DWT.TRAVERSE_MNEMONIC: return traverseMnemonic (event);
3168 case DWT.TRAVERSE_PAGE_NEXT: return traversePage (true);
3169 case DWT.TRAVERSE_PAGE_PREVIOUS: return traversePage (false);
3170 }
3171 return false;
3172 }
3173
3174 bool traverseEscape () {
3175 return false;
3176 }
3177
3178 bool traverseGroup (bool next) {
3179 Control root = computeTabRoot ();
3180 Control group = computeTabGroup ();
3181 Control [] list = root.computeTabList ();
3182 int length = list.length;
3183 int index = 0;
3184 while (index < length) {
3185 if (list [index] is group) break;
3186 index++;
3187 }
3188 /*
3189 * It is possible (but unlikely), that application
3190 * code could have disposed the widget in focus in
3191 * or out events. Ensure that a disposed widget is
3192 * not accessed.
3193 */
3194 if (index is length) return false;
3195 int start = index, offset = (next) ? 1 : -1;
3196 while ((index = ((index + offset + length) % length)) !is start) {
3197 Control control = list [index];
3198 if (!control.isDisposed () && control.setTabGroupFocus ()) {
3199 return true;
3200 }
3201 }
3202 if (group.isDisposed ()) return false;
3203 return group.setTabGroupFocus ();
3204 }
3205
3206 bool traverseItem (bool next) {
3207 Control [] children = parent._getChildren ();
3208 int length = children.length;
3209 int index = 0;
3210 while (index < length) {
3211 if (children [index] is this) break;
3212 index++;
3213 }
3214 /*
3215 * It is possible (but unlikely), that application
3216 * code could have disposed the widget in focus in
3217 * or out events. Ensure that a disposed widget is
3218 * not accessed.
3219 */
3220 if (index is length) return false;
3221 int start = index, offset = (next) ? 1 : -1;
3222 while ((index = (index + offset + length) % length) !is start) {
3223 Control child = children [index];
3224 if (!child.isDisposed () && child.isTabItem ()) {
3225 if (child.setTabItemFocus ()) return true;
3226 }
3227 }
3228 return false;
3229 }
3230
3231 bool traverseReturn () {
3232 return false;
3233 }
3234
3235 bool traversePage (bool next) {
3236 return false;
3237 }
3238
3239 bool traverseMnemonic (Event event) {
3240 return false;
3241 }
3242
3243 /**
3244 * Forces all outstanding paint requests for the widget
3245 * to be processed before this method returns. If there
3246 * are no outstanding paint request, this method does
3247 * nothing.
3248 * <p>
3249 * Note: This method does not cause a redraw.
3250 * </p>
3251 *
3252 * @exception DWTException <ul>
3253 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3254 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3255 * </ul>
3256 *
3257 * @see #redraw()
3258 * @see #redraw(int, int, int, int, bool)
3259 * @see PaintListener
3260 * @see DWT#Paint
3261 */
3262 public void update () {
3263 checkWidget();
3264 update (false);
3265 }
3266
3267 void update (bool all) {
3268 // checkWidget();
3269 //TODO - not all
3270 // OS.HIViewRender (handle);
3271 }
3272
3273 void updateBackgroundMode () {
3274 int oldState = state & PARENT_BACKGROUND;
3275 checkBackground ();
3276 if (oldState !is (state & PARENT_BACKGROUND)) {
3277 setBackground ();
3278 }
3279 }
3280
3281 void updateLayout (bool all) {
3282 /* Do nothing */
3283 }
3284
3285 }