1 /*******************************************************************************
2 * Copyright (c) 2000, 2017 IBM Corporation and others.
3 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
11 * Contributors:
12 * IBM Corporation - initial API and implementation
13 * Stefan Xenos (Google) - bug 468854 - Add a requestLayout method to Control
14 *******************************************************************************/
15 package org.eclipse.swt.widgets;
16
17 import org.eclipse.swt.*;
18 import org.eclipse.swt.accessibility.*;
19 import org.eclipse.swt.events.*;
20 import org.eclipse.swt.graphics.*;
21 import org.eclipse.swt.internal.*;
22 import org.eclipse.swt.internal.cocoa.*;
23
24 /**
25 * Control is the abstract superclass of all windowed user interface classes.
26 * <dl>
27 * <dt><b>Styles:</b>
28 * <dd>BORDER</dd>
29 * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT, FLIP_TEXT_DIRECTION</dd>
30 * <dt><b>Events:</b>
31 * <dd>DragDetect, FocusIn, FocusOut, Help, KeyDown, KeyUp, MenuDetect, MouseDoubleClick, MouseDown, MouseEnter,
32 * MouseExit, MouseHover, MouseUp, MouseMove, MouseWheel, MouseHorizontalWheel, MouseVerticalWheel, Move,
33 * Paint, Resize, Traverse</dd>
34 * </dl>
35 * <p>
36 * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
37 * </p><p>
38 * IMPORTANT: This class is intended to be subclassed <em>only</em>
39 * within the SWT implementation.
40 * </p>
41 *
42 * @see <a href="http://www.eclipse.org/swt/snippets/#control">Control snippets</a>
43 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
44 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
45 * @noextend This class is not intended to be subclassed by clients.
46 */
47 public abstract class Control extends Widget implements Drawable {
48 /**
49 * the handle to the OS resource
50 * (Warning: This field is platform dependent)
51 * <p>
52 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
53 * public API. It is marked public only so that it can be shared
54 * within the packages provided by SWT. It is not available on all
55 * platforms and should never be accessed from application code.
56 * </p>
57 *
58 * @noreference This field is not intended to be referenced by clients.
59 */
60 public NSView view;
61 Composite parent;
62 String toolTipText;
63 Object layoutData;
64 int drawCount, backgroundAlpha = 255;
65 Menu menu;
66 double [] foreground, background;
67 Image backgroundImage;
68 Font font;
69 Cursor cursor;
70 Region region;
71 NSBezierPath regionPath;
72 long visibleRgn;
73 Accessible accessible;
74 boolean inCacheDisplayInRect;
75 boolean touchEnabled;
76
77 final static int CLIPPING = 1 << 10;
78 final static int VISIBLE_REGION = 1 << 12;
79
80 /**
81 * Magic number comes from experience. There's no API for this value in Cocoa.
82 */
83 static final int DEFAULT_DRAG_HYSTERESIS = 5;
84
Control()85 Control () {
86 /* Do nothing */
87 }
88
89 /**
90 * Constructs a new instance of this class given its parent
91 * and a style value describing its behavior and appearance.
92 * <p>
93 * The style value is either one of the style constants defined in
94 * class <code>SWT</code> which is applicable to instances of this
95 * class, or must be built by <em>bitwise OR</em>'ing together
96 * (that is, using the <code>int</code> "|" operator) two or more
97 * of those <code>SWT</code> style constants. The class description
98 * lists the style constants that are applicable to the class.
99 * Style bits are also inherited from superclasses.
100 * </p>
101 *
102 * @param parent a composite control which will be the parent of the new instance (cannot be null)
103 * @param style the style of control to construct
104 *
105 * @exception IllegalArgumentException <ul>
106 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
107 * </ul>
108 * @exception SWTException <ul>
109 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
110 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
111 * </ul>
112 *
113 * @see SWT#BORDER
114 * @see SWT#LEFT_TO_RIGHT
115 * @see SWT#RIGHT_TO_LEFT
116 * @see Widget#checkSubclass
117 * @see Widget#getStyle
118 */
Control(Composite parent, int style)119 public Control (Composite parent, int style) {
120 super (parent, style);
121 this.parent = parent;
122 createWidget ();
123 }
124
125 @Override
acceptsFirstMouse(long id, long sel, long theEvent)126 boolean acceptsFirstMouse (long id, long sel, long theEvent) {
127 Shell shell = getShell ();
128 if ((shell.style & SWT.ON_TOP) != 0) return true;
129 return super.acceptsFirstMouse (id, sel, theEvent);
130 }
131
132 @Override
accessibleHandle()133 long accessibleHandle() {
134 long returnValue = view.id;
135
136 if (view instanceof NSControl) {
137 if (((NSControl) view).cell() != null) {
138 returnValue = ((NSControl) view).cell().id;
139 }
140
141 }
142 return returnValue;
143 }
144
145 @Override
accessibilityActionDescription(long id, long sel, long arg0)146 long accessibilityActionDescription(long id, long sel, long arg0) {
147 if (id == accessibleHandle() && accessible != null) {
148 NSString actionName = new NSString(arg0);
149 id returnValue = accessible.internal_accessibilityActionDescription(actionName, ACC.CHILDID_SELF);
150 if (returnValue != null) return returnValue.id;
151 }
152 return super.accessibilityActionDescription(id, sel, arg0);
153 }
154
155 @Override
accessibilityActionNames(long id, long sel)156 long accessibilityActionNames(long id, long sel) {
157 long returnValue = super.accessibilityActionNames(id, sel);
158 if (handleIsAccessible(id)) {
159 if (accessible != null) {
160 NSArray baseArray = accessible.internal_accessibilityActionNames(ACC.CHILDID_SELF);
161 if (baseArray != null) returnValue = baseArray.id;
162 }
163 if (hooks(SWT.MenuDetect) || (menu != null && !menu.isDisposed())) {
164 NSArray baseArray = new NSArray(returnValue);
165 NSMutableArray ourNames = NSMutableArray.arrayWithCapacity(baseArray.count() + 1);
166 ourNames.addObjectsFromArray(baseArray);
167 ourNames.addObject(OS.NSAccessibilityShowMenuAction);
168 returnValue = ourNames.id;
169 }
170 }
171 return returnValue;
172 }
173
174 @Override
accessibilityAttributeNames(long id, long sel)175 long accessibilityAttributeNames(long id, long sel) {
176
177 long returnValue = 0;
178
179 if (handleIsAccessible(id) && accessible != null) {
180 // See if the accessible is defining the attribute set for the control.
181 id value = accessible.internal_accessibilityAttributeNames(ACC.CHILDID_SELF);
182 returnValue = (value != null ? value.id : 0);
183
184 // If not, ask Cocoa for the set for this control.
185 if (returnValue == 0) returnValue = super.accessibilityAttributeNames(id, sel);
186
187 // Add relationship attributes.
188 returnValue = accessible.internal_addRelationAttributes(returnValue);
189 }
190
191 // If the SWT accessibility didn't give us anything get the default for the view/cell.
192 if (returnValue == 0) returnValue = super.accessibilityAttributeNames(id, sel);
193
194 return returnValue;
195 }
196
197 /**
198 * @param id NSView/NSCell that makes up this control. Could be the view itself.
199 * @return true if id is something whose accessible properties can be augmented
200 * or overridden by the SWT Accessible. false if the Cocoa defaults for the control should
201 * be used.
202 */
handleIsAccessible(long id)203 boolean handleIsAccessible(long id) {
204 return id == accessibleHandle();
205 }
206
207 @Override
accessibilityParameterizedAttributeNames(long id, long sel)208 long accessibilityParameterizedAttributeNames(long id, long sel) {
209
210 if (handleIsAccessible(id) && accessible != null) {
211 NSArray returnValue = accessible.internal_accessibilityParameterizedAttributeNames(ACC.CHILDID_SELF);
212 if (returnValue != null) return returnValue.id;
213 }
214
215 return super.accessibilityParameterizedAttributeNames(id, sel);
216 }
217
218 @Override
accessibilityPerformAction(long id, long sel, long arg0)219 void accessibilityPerformAction(long id, long sel, long arg0) {
220 if (handleIsAccessible(id) && accessible != null) {
221 NSString action = new NSString(arg0);
222 if (accessible.internal_accessibilityPerformAction(action, ACC.CHILDID_SELF)) return;
223 }
224 super.accessibilityPerformAction(id, sel, arg0);
225 }
226
227 @Override
accessibilityFocusedUIElement(long id, long sel)228 long accessibilityFocusedUIElement(long id, long sel) {
229 id returnValue = null;
230
231 if (handleIsAccessible(id) && accessible != null) {
232 returnValue = accessible.internal_accessibilityFocusedUIElement(ACC.CHILDID_SELF);
233 }
234
235 // If we had an accessible and it didn't handle the attribute request, let the
236 // superclass handle it.
237 if (returnValue == null)
238 return super.accessibilityFocusedUIElement(id, sel);
239 else
240 return returnValue.id;
241 }
242
243 @Override
accessibilityHitTest(long id, long sel, NSPoint point)244 long accessibilityHitTest(long id, long sel, NSPoint point) {
245 id returnValue = null;
246
247 if (handleIsAccessible(id) && accessible != null) {
248 returnValue = accessible.internal_accessibilityHitTest(point, ACC.CHILDID_SELF);
249 }
250
251 // If we had an accessible and it didn't handle the attribute request, let the
252 // superclass handle it.
253 if (returnValue == null)
254 return super.accessibilityHitTest(id, sel, point);
255 else
256 return returnValue.id;
257 }
258
259 @Override
accessibilityAttributeValue(long id, long sel, long arg0)260 long accessibilityAttributeValue(long id, long sel, long arg0) {
261 NSString attribute = new NSString(arg0);
262 long returnValue = 0;
263 id returnObject = null;
264
265 if (handleIsAccessible(id) && accessible != null) {
266 returnObject = accessible.internal_accessibilityAttributeValue(attribute, ACC.CHILDID_SELF);
267 }
268
269 // If we had an accessible and it didn't handle the attribute request, let the
270 // superclass handle it.
271 if (returnObject == null) {
272 returnValue = super.accessibilityAttributeValue(id, sel, arg0);
273
274 // Feature in Cocoa: SWT doesn't use setToolTip for tooltip support, so if the
275 // help attribute was requested return toolTipText.
276 if (returnObject == null) {
277 if (attribute.isEqualToString(OS.NSAccessibilityHelpAttribute)) {
278 if (toolTipText != null) returnValue = NSString.stringWith(toolTipText).id;
279 }
280 }
281
282 } else {
283 returnValue = returnObject.id;
284 }
285
286 return returnValue;
287 }
288
289 @Override
accessibilityAttributeValue_forParameter(long id, long sel, long arg0, long arg1)290 long accessibilityAttributeValue_forParameter(long id, long sel, long arg0, long arg1) {
291 NSString attribute = new NSString(arg0);
292
293 id returnValue = null;
294
295 if (handleIsAccessible(id) && accessible != null) {
296 id parameter = new id(arg1);
297 returnValue = accessible.internal_accessibilityAttributeValue_forParameter(attribute, parameter, ACC.CHILDID_SELF);
298 }
299
300 // If we had an accessible and it didn't handle the attribute request, let the
301 // superclass handle it.
302 if (returnValue == null)
303 return super.accessibilityAttributeValue_forParameter(id, sel, arg0, arg1);
304 else
305 return returnValue.id;
306 }
307
308 @Override
accessibilityIsAttributeSettable(long id, long sel, long arg0)309 boolean accessibilityIsAttributeSettable(long id, long sel, long arg0) {
310 boolean returnValue = false;
311 if (handleIsAccessible(id) && accessible != null) {
312 NSString attribute = new NSString (arg0);
313 returnValue = accessible.internal_accessibilityIsAttributeSettable(attribute, ACC.CHILDID_SELF);
314 }
315 if (!returnValue) {
316 returnValue = super.accessibilityIsAttributeSettable(id, sel, arg0);
317 }
318 return returnValue;
319 }
320
321 @Override
accessibilitySetValue_forAttribute(long id, long sel, long arg0, long arg1)322 void accessibilitySetValue_forAttribute(long id, long sel, long arg0, long arg1) {
323 if (handleIsAccessible(id) && accessible != null) {
324 id value = new id(arg0);
325 NSString attribute = new NSString(arg1);
326 accessible.internal_accessibilitySetValue_forAttribute(value, attribute, ACC.CHILDID_SELF);
327 } else {
328 super.accessibilitySetValue_forAttribute(id, sel, arg0, arg1);
329 }
330 }
331
332 /**
333 * Adds the listener to the collection of listeners who will
334 * be notified when the control is moved or resized, by sending
335 * it one of the messages defined in the <code>ControlListener</code>
336 * interface.
337 *
338 * @param listener the listener which should be notified
339 *
340 * @exception IllegalArgumentException <ul>
341 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
342 * </ul>
343 * @exception SWTException <ul>
344 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
345 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
346 * </ul>
347 *
348 * @see ControlListener
349 * @see #removeControlListener
350 */
addControlListener(ControlListener listener)351 public void addControlListener(ControlListener listener) {
352 checkWidget();
353 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
354 TypedListener typedListener = new TypedListener (listener);
355 addListener (SWT.Resize,typedListener);
356 addListener (SWT.Move,typedListener);
357 }
358
359 /**
360 * Adds the listener to the collection of listeners who will
361 * be notified when a drag gesture occurs, by sending it
362 * one of the messages defined in the <code>DragDetectListener</code>
363 * interface.
364 *
365 * @param listener the listener which should be notified
366 *
367 * @exception IllegalArgumentException <ul>
368 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
369 * </ul>
370 * @exception SWTException <ul>
371 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
372 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
373 * </ul>
374 *
375 * @see DragDetectListener
376 * @see #removeDragDetectListener
377 *
378 * @since 3.3
379 */
addDragDetectListener(DragDetectListener listener)380 public void addDragDetectListener (DragDetectListener listener) {
381 checkWidget ();
382 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
383 TypedListener typedListener = new TypedListener (listener);
384 addListener (SWT.DragDetect,typedListener);
385 }
386
387 /**
388 * Adds the listener to the collection of listeners who will
389 * be notified when the control gains or loses focus, by sending
390 * it one of the messages defined in the <code>FocusListener</code>
391 * interface.
392 *
393 * @param listener the listener which should be notified
394 *
395 * @exception IllegalArgumentException <ul>
396 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
397 * </ul>
398 * @exception SWTException <ul>
399 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
400 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
401 * </ul>
402 *
403 * @see FocusListener
404 * @see #removeFocusListener
405 */
addFocusListener(FocusListener listener)406 public void addFocusListener(FocusListener listener) {
407 checkWidget();
408 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
409 TypedListener typedListener = new TypedListener (listener);
410 addListener(SWT.FocusIn,typedListener);
411 addListener(SWT.FocusOut,typedListener);
412 }
413
414 /**
415 * Adds the listener to the collection of listeners who will
416 * be notified when gesture events are generated for the control,
417 * by sending it one of the messages defined in the
418 * <code>GestureListener</code> interface.
419 * <p>
420 * NOTE: If <code>setTouchEnabled(true)</code> has previously been
421 * invoked on the receiver then <code>setTouchEnabled(false)</code>
422 * must be invoked on it to specify that gesture events should be
423 * sent instead of touch events.
424 * </p>
425 * <p>
426 * <b>Warning</b>: This API is currently only implemented on Windows and Cocoa.
427 * SWT doesn't send Gesture or Touch events on GTK.
428 * </p>
429 *
430 * @param listener the listener which should be notified
431 *
432 * @exception IllegalArgumentException <ul>
433 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
434 * </ul>
435 * @exception SWTException <ul>
436 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
437 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
438 * </ul>
439 *
440 * @see GestureListener
441 * @see #removeGestureListener
442 * @see #setTouchEnabled
443 *
444 * @since 3.7
445 */
addGestureListener(GestureListener listener)446 public void addGestureListener (GestureListener listener) {
447 checkWidget();
448 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
449 TypedListener typedListener = new TypedListener (listener);
450 addListener (SWT.Gesture, typedListener);
451 }
452
453 /**
454 * Adds the listener to the collection of listeners who will
455 * be notified when help events are generated for the control,
456 * by sending it one of the messages defined in the
457 * <code>HelpListener</code> interface.
458 *
459 * @param listener the listener which should be notified
460 *
461 * @exception IllegalArgumentException <ul>
462 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
463 * </ul>
464 * @exception SWTException <ul>
465 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
466 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
467 * </ul>
468 *
469 * @see HelpListener
470 * @see #removeHelpListener
471 */
addHelpListener(HelpListener listener)472 public void addHelpListener (HelpListener listener) {
473 checkWidget();
474 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
475 TypedListener typedListener = new TypedListener (listener);
476 addListener (SWT.Help, typedListener);
477 }
478
479 /**
480 * Adds the listener to the collection of listeners who will
481 * be notified when keys are pressed and released on the system keyboard, by sending
482 * it one of the messages defined in the <code>KeyListener</code>
483 * interface.
484 * <p>
485 * When a key listener is added to a control, the control
486 * will take part in widget traversal. By default, all
487 * traversal keys (such as the tab key and so on) are
488 * delivered to the control. In order for a control to take
489 * part in traversal, it should listen for traversal events.
490 * Otherwise, the user can traverse into a control but not
491 * out. Note that native controls such as table and tree
492 * implement key traversal in the operating system. It is
493 * not necessary to add traversal listeners for these controls,
494 * unless you want to override the default traversal.
495 * </p>
496 * @param listener the listener which should be notified
497 *
498 * @exception IllegalArgumentException <ul>
499 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
500 * </ul>
501 * @exception SWTException <ul>
502 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
503 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
504 * </ul>
505 *
506 * @see KeyListener
507 * @see #removeKeyListener
508 */
addKeyListener(KeyListener listener)509 public void addKeyListener(KeyListener listener) {
510 checkWidget();
511 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
512 TypedListener typedListener = new TypedListener (listener);
513 addListener(SWT.KeyUp,typedListener);
514 addListener(SWT.KeyDown,typedListener);
515 }
516
517 /**
518 * Adds the listener to the collection of listeners who will
519 * be notified when the platform-specific context menu trigger
520 * has occurred, by sending it one of the messages defined in
521 * the <code>MenuDetectListener</code> interface.
522 *
523 * @param listener the listener which should be notified
524 *
525 * @exception IllegalArgumentException <ul>
526 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
527 * </ul>
528 * @exception SWTException <ul>
529 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
530 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
531 * </ul>
532 *
533 * @see MenuDetectListener
534 * @see #removeMenuDetectListener
535 *
536 * @since 3.3
537 */
addMenuDetectListener(MenuDetectListener listener)538 public void addMenuDetectListener (MenuDetectListener listener) {
539 checkWidget ();
540 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
541 TypedListener typedListener = new TypedListener (listener);
542 addListener (SWT.MenuDetect, typedListener);
543 }
544
545 /**
546 * Adds the listener to the collection of listeners who will
547 * be notified when mouse buttons are pressed and released, by sending
548 * it one of the messages defined in the <code>MouseListener</code>
549 * interface.
550 *
551 * @param listener the listener which should be notified
552 *
553 * @exception IllegalArgumentException <ul>
554 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
555 * </ul>
556 * @exception SWTException <ul>
557 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
558 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
559 * </ul>
560 *
561 * @see MouseListener
562 * @see #removeMouseListener
563 */
addMouseListener(MouseListener listener)564 public void addMouseListener(MouseListener listener) {
565 checkWidget();
566 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
567 TypedListener typedListener = new TypedListener (listener);
568 addListener(SWT.MouseDown,typedListener);
569 addListener(SWT.MouseUp,typedListener);
570 addListener(SWT.MouseDoubleClick,typedListener);
571 }
572
573 /**
574 * Adds the listener to the collection of listeners who will
575 * be notified when the mouse passes or hovers over controls, by sending
576 * it one of the messages defined in the <code>MouseTrackListener</code>
577 * interface.
578 *
579 * @param listener the listener which should be notified
580 *
581 * @exception IllegalArgumentException <ul>
582 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
583 * </ul>
584 * @exception SWTException <ul>
585 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
586 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
587 * </ul>
588 *
589 * @see MouseTrackListener
590 * @see #removeMouseTrackListener
591 */
addMouseTrackListener(MouseTrackListener listener)592 public void addMouseTrackListener (MouseTrackListener listener) {
593 checkWidget();
594 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
595 TypedListener typedListener = new TypedListener (listener);
596 addListener (SWT.MouseEnter,typedListener);
597 addListener (SWT.MouseExit,typedListener);
598 addListener (SWT.MouseHover,typedListener);
599 }
600
601 /**
602 * Adds the listener to the collection of listeners who will
603 * be notified when the mouse moves, by sending it one of the
604 * messages defined in the <code>MouseMoveListener</code>
605 * interface.
606 *
607 * @param listener the listener which should be notified
608 *
609 * @exception IllegalArgumentException <ul>
610 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
611 * </ul>
612 * @exception SWTException <ul>
613 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
614 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
615 * </ul>
616 *
617 * @see MouseMoveListener
618 * @see #removeMouseMoveListener
619 */
addMouseMoveListener(MouseMoveListener listener)620 public void addMouseMoveListener(MouseMoveListener listener) {
621 checkWidget();
622 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
623 TypedListener typedListener = new TypedListener (listener);
624 addListener(SWT.MouseMove,typedListener);
625 }
626
627 /**
628 * Adds the listener to the collection of listeners who will
629 * be notified when the mouse wheel is scrolled, by sending
630 * it one of the messages defined in the
631 * <code>MouseWheelListener</code> interface.
632 *
633 * @param listener the listener which should be notified
634 *
635 * @exception IllegalArgumentException <ul>
636 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
637 * </ul>
638 * @exception SWTException <ul>
639 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
640 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
641 * </ul>
642 *
643 * @see MouseWheelListener
644 * @see #removeMouseWheelListener
645 *
646 * @since 3.3
647 */
addMouseWheelListener(MouseWheelListener listener)648 public void addMouseWheelListener (MouseWheelListener listener) {
649 checkWidget ();
650 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
651 TypedListener typedListener = new TypedListener (listener);
652 addListener (SWT.MouseWheel, typedListener);
653 }
654
addRelation(Control control)655 void addRelation (Control control) {
656 }
657
658 /**
659 * Adds the listener to the collection of listeners who will
660 * be notified when the receiver needs to be painted, by sending it
661 * one of the messages defined in the <code>PaintListener</code>
662 * interface.
663 *
664 * @param listener the listener which should be notified
665 *
666 * @exception IllegalArgumentException <ul>
667 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
668 * </ul>
669 * @exception SWTException <ul>
670 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
671 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
672 * </ul>
673 *
674 * @see PaintListener
675 * @see #removePaintListener
676 */
addPaintListener(PaintListener listener)677 public void addPaintListener(PaintListener listener) {
678 checkWidget();
679 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
680 TypedListener typedListener = new TypedListener (listener);
681 addListener(SWT.Paint,typedListener);
682 }
683
684 static final double SYNTHETIC_BOLD = -2.5;
685 static final double SYNTHETIC_ITALIC = 0.2;
686
addTraits(NSMutableDictionary dict, Font font)687 void addTraits(NSMutableDictionary dict, Font font) {
688 if ((font.extraTraits & OS.NSBoldFontMask) != 0) {
689 dict.setObject(NSNumber.numberWithDouble(SYNTHETIC_BOLD), OS.NSStrokeWidthAttributeName);
690 }
691 if ((font.extraTraits & OS.NSItalicFontMask) != 0) {
692 dict.setObject(NSNumber.numberWithDouble(SYNTHETIC_ITALIC), OS.NSObliquenessAttributeName);
693 }
694 }
695
696 /**
697 * Adds the listener to the collection of listeners who will
698 * be notified when touch events occur, by sending it
699 * one of the messages defined in the <code>TouchListener</code>
700 * interface.
701 * <p>
702 * NOTE: You must also call <code>setTouchEnabled(true)</code> to
703 * specify that touch events should be sent, which will cause gesture
704 * events to not be sent.
705 * </p>
706 * <p>
707 * <b>Warning</b>: This API is currently only implemented on Windows and Cocoa.
708 * SWT doesn't send Gesture or Touch events on GTK.
709 * </p>
710 *
711 * @param listener the listener which should be notified
712 *
713 * @exception IllegalArgumentException <ul>
714 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
715 * </ul>
716 * @exception SWTException <ul>
717 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
718 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
719 * </ul>
720 *
721 * @see TouchListener
722 * @see #removeTouchListener
723 * @see #setTouchEnabled
724 *
725 * @since 3.7
726 */
addTouchListener(TouchListener listener)727 public void addTouchListener (TouchListener listener) {
728 checkWidget();
729 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
730 TypedListener typedListener = new TypedListener (listener);
731 addListener (SWT.Touch,typedListener);
732 }
733
734 /**
735 * Adds the listener to the collection of listeners who will
736 * be notified when traversal events occur, by sending it
737 * one of the messages defined in the <code>TraverseListener</code>
738 * interface.
739 *
740 * @param listener the listener which should be notified
741 *
742 * @exception IllegalArgumentException <ul>
743 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
744 * </ul>
745 * @exception SWTException <ul>
746 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
747 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
748 * </ul>
749 *
750 * @see TraverseListener
751 * @see #removeTraverseListener
752 */
addTraverseListener(TraverseListener listener)753 public void addTraverseListener (TraverseListener listener) {
754 checkWidget();
755 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
756 TypedListener typedListener = new TypedListener (listener);
757 addListener (SWT.Traverse,typedListener);
758 }
759
760 @Override
becomeFirstResponder(long id, long sel)761 boolean becomeFirstResponder (long id, long sel) {
762 if ((state & DISABLED) != 0) return false;
763 return super.becomeFirstResponder (id, sel);
764 }
765
calculateVisibleRegion(NSView view, long visibleRgn, boolean clipChildren)766 void calculateVisibleRegion (NSView view, long visibleRgn, boolean clipChildren) {
767 long tempRgn = OS.NewRgn ();
768 if (!view.isHiddenOrHasHiddenAncestor() && isDrawing()) {
769 long childRgn = OS.NewRgn ();
770 NSWindow window = view.window ();
771 NSView contentView = window.contentView();
772 NSView frameView = contentView.superview();
773 NSRect bounds = contentView.visibleRect();
774 bounds = contentView.convertRect_toView_(bounds, view);
775 short[] rect = new short[4];
776 OS.SetRect(rect, (short)bounds.x, (short)bounds.y, (short)(bounds.x + bounds.width), (short)(bounds.y + bounds.height));
777 OS.RectRgn(visibleRgn, rect);
778 NSView tempView = view, lastControl = null;
779 while (tempView.id != frameView.id) {
780 bounds = tempView.visibleRect();
781 bounds = tempView.convertRect_toView_(bounds, view);
782 OS.SetRect(rect, (short)bounds.x, (short)bounds.y, (short)(bounds.x + bounds.width), (short)(bounds.y + bounds.height));
783 OS.RectRgn(tempRgn, rect);
784 OS.SectRgn (tempRgn, visibleRgn, visibleRgn);
785 if (OS.EmptyRgn (visibleRgn)) break;
786 if (clipChildren || tempView.id != view.id) {
787 NSArray subviews = tempView.subviews();
788 long count = subviews.count();
789 for (int i = 0; i < count; i++) {
790 NSView child = new NSView (subviews.objectAtIndex(count - i - 1));
791 if (lastControl != null && child.id == lastControl.id) break;
792 if (child.isHidden()) continue;
793 bounds = child.visibleRect();
794 bounds = child.convertRect_toView_(bounds, view);
795 OS.SetRect(rect, (short)bounds.x, (short)bounds.y, (short)(bounds.x + bounds.width), (short)(bounds.y + bounds.height));
796 OS.RectRgn(tempRgn, rect);
797 OS.UnionRgn (tempRgn, childRgn, childRgn);
798 }
799 }
800 lastControl = tempView;
801 tempView = tempView.superview();
802 }
803 OS.DiffRgn (visibleRgn, childRgn, visibleRgn);
804 OS.DisposeRgn (childRgn);
805 } else {
806 OS.CopyRgn (tempRgn, visibleRgn);
807 }
808 OS.DisposeRgn (tempRgn);
809 }
810
811 @Override
cancelOperation(long id, long sel, long sender)812 void cancelOperation(long id, long sel, long sender) {
813 // Cmd-. and escape arrive here. Forward the current event as a key event.
814 if (hasKeyboardFocus(id)) {
815 NSEvent nsEvent = NSApplication.sharedApplication().currentEvent();
816 Shell s = this.getShell();
817 s.keyInputHappened = false;
818 boolean [] consume = new boolean [1];
819 if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return;
820 if (isDisposed ()) return;
821 if (!sendKeyEvent (nsEvent, SWT.KeyDown)) return;
822 }
823 }
824
checkBackground()825 void checkBackground () {
826 Shell shell = getShell ();
827 if (this == shell) return;
828 state &= ~PARENT_BACKGROUND;
829 Composite composite = parent;
830 do {
831 int mode = composite.backgroundMode;
832 if (mode != 0 || backgroundAlpha == 0) {
833 if (mode == SWT.INHERIT_DEFAULT || backgroundAlpha == 0) {
834 Control control = this;
835 do {
836 if ((control.state & THEME_BACKGROUND) == 0) {
837 return;
838 }
839 control = control.parent;
840 } while (control != composite);
841 }
842 state |= PARENT_BACKGROUND;
843 return;
844 }
845 if (composite == shell) break;
846 composite = composite.parent;
847 } while (true);
848 }
849
checkBuffered()850 void checkBuffered () {
851 style |= SWT.DOUBLE_BUFFERED;
852 }
853
checkToolTip(Widget target)854 void checkToolTip (Widget target) {
855 if (isVisible () && display.tooltipControl == this && (target == null || display.tooltipTarget == target)) {
856 Shell shell = getShell ();
857 shell.sendToolTipEvent (false);
858 shell.sendToolTipEvent (true);
859 }
860 }
861
862 /**
863 * Returns the preferred size (in points) of the receiver.
864 * <p>
865 * The <em>preferred size</em> of a control is the size that it would
866 * best be displayed at. The width hint and height hint arguments
867 * allow the caller to ask a control questions such as "Given a particular
868 * width, how high does the control need to be to show all of the contents?"
869 * To indicate that the caller does not wish to constrain a particular
870 * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
871 * </p>
872 *
873 * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
874 * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
875 * @return the preferred size of the control
876 *
877 * @exception SWTException <ul>
878 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
879 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
880 * </ul>
881 *
882 * @see Layout
883 * @see #getBorderWidth
884 * @see #getBounds
885 * @see #getSize
886 * @see #pack(boolean)
887 * @see "computeTrim, getClientArea for controls that implement them"
888 */
computeSize(int wHint, int hHint)889 public Point computeSize (int wHint, int hHint) {
890 return computeSize (wHint, hHint, true);
891 }
892
893 /**
894 * Returns the preferred size (in points) of the receiver.
895 * <p>
896 * The <em>preferred size</em> of a control is the size that it would
897 * best be displayed at. The width hint and height hint arguments
898 * allow the caller to ask a control questions such as "Given a particular
899 * width, how high does the control need to be to show all of the contents?"
900 * To indicate that the caller does not wish to constrain a particular
901 * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
902 * </p><p>
903 * If the changed flag is <code>true</code>, it indicates that the receiver's
904 * <em>contents</em> have changed, therefore any caches that a layout manager
905 * containing the control may have been keeping need to be flushed. When the
906 * control is resized, the changed flag will be <code>false</code>, so layout
907 * manager caches can be retained.
908 * </p>
909 *
910 * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
911 * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
912 * @param changed <code>true</code> if the control's contents have changed, and <code>false</code> otherwise
913 * @return the preferred size of the control.
914 *
915 * @exception SWTException <ul>
916 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
917 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
918 * </ul>
919 *
920 * @see Layout
921 * @see #getBorderWidth
922 * @see #getBounds
923 * @see #getSize
924 * @see #pack(boolean)
925 * @see "computeTrim, getClientArea for controls that implement them"
926 */
computeSize(int wHint, int hHint, boolean changed)927 public Point computeSize (int wHint, int hHint, boolean changed) {
928 checkWidget ();
929 int width = DEFAULT_WIDTH;
930 int height = DEFAULT_HEIGHT;
931 if (wHint != SWT.DEFAULT) width = wHint;
932 if (hHint != SWT.DEFAULT) height = hHint;
933 int border = getBorderWidth ();
934 width += border * 2;
935 height += border * 2;
936 return new Point (width, height);
937 }
938
computeTabGroup()939 Widget computeTabGroup () {
940 if (isTabGroup()) return this;
941 return parent.computeTabGroup ();
942 }
943
computeTabList()944 Widget[] computeTabList() {
945 if (isTabGroup()) {
946 if (getVisible() && getEnabled()) {
947 return new Widget[] {this};
948 }
949 }
950 return new Widget[0];
951 }
952
computeTabRoot()953 Control computeTabRoot () {
954 Control[] tabList = parent._getTabList();
955 if (tabList != null) {
956 int index = 0;
957 while (index < tabList.length) {
958 if (tabList [index] == this) break;
959 index++;
960 }
961 if (index == tabList.length) {
962 if (isTabGroup ()) return this;
963 }
964 }
965 return parent.computeTabRoot ();
966 }
967
contentView()968 NSView contentView () {
969 return view;
970 }
971
createString(String string, Font font, double [] foreground, int alignment, boolean wrap, boolean enabled, boolean mnemonics)972 NSAttributedString createString (String string, Font font, double [] foreground, int alignment, boolean wrap, boolean enabled, boolean mnemonics) {
973 NSMutableDictionary dict = ((NSMutableDictionary)new NSMutableDictionary().alloc()).initWithCapacity(5);
974 if (font == null) font = this.font != null ? this.font : defaultFont();
975 dict.setObject (font.handle, OS.NSFontAttributeName);
976 addTraits(dict, font);
977 if (enabled) {
978 if (foreground != null) {
979 NSColor color = NSColor.colorWithDeviceRed(foreground[0], foreground[1], foreground[2], foreground[3]);
980 dict.setObject (color, OS.NSForegroundColorAttributeName);
981 }
982 } else {
983 dict.setObject (NSColor.disabledControlTextColor (), OS.NSForegroundColorAttributeName);
984 }
985 NSMutableParagraphStyle paragraphStyle = (NSMutableParagraphStyle)new NSMutableParagraphStyle ().alloc ().init ();
986 paragraphStyle.setLineBreakMode (wrap ? OS.NSLineBreakByWordWrapping : OS.NSLineBreakByClipping);
987 if (alignment != 0) {
988 int align = OS.NSTextAlignmentLeft;
989 if ((alignment & SWT.CENTER) != 0) {
990 align = OS.NSTextAlignmentCenter;
991 } else if ((alignment & SWT.RIGHT) != 0) {
992 align = OS.NSTextAlignmentRight;
993 }
994 paragraphStyle.setAlignment (align);
995 }
996 if ((style & SWT.RIGHT_TO_LEFT) != 0) {
997 paragraphStyle.setBaseWritingDirection(OS.NSWritingDirectionRightToLeft);
998 } else {
999 paragraphStyle.setBaseWritingDirection(OS.NSWritingDirectionLeftToRight);
1000 }
1001 dict.setObject (paragraphStyle, OS.NSParagraphStyleAttributeName);
1002 paragraphStyle.release ();
1003 int length = string.length ();
1004 char [] chars = new char [length];
1005 string.getChars (0, chars.length, chars, 0);
1006 if (mnemonics) length = fixMnemonic (chars);
1007 NSString str = ((NSString)new NSString().alloc()).initWithCharacters(chars, length);
1008 NSAttributedString attribStr = ((NSAttributedString) new NSAttributedString ().alloc ()).initWithString (str, dict);
1009 str.release();
1010 dict.release();
1011 return attribStr;
1012 }
1013
1014 @Override
createWidget()1015 void createWidget () {
1016 state |= DRAG_DETECT;
1017 checkOrientation (parent);
1018 super.createWidget ();
1019 checkBackground ();
1020 checkBuffered ();
1021 setDefaultFont ();
1022 setZOrder ();
1023 setRelations ();
1024 if ((state & PARENT_BACKGROUND) != 0) {
1025 setBackground ();
1026 }
1027 display.clearPool ();
1028 }
1029
defaultBackground()1030 Color defaultBackground () {
1031 return display.getWidgetColor (SWT.COLOR_WIDGET_BACKGROUND);
1032 }
1033
defaultFont()1034 Font defaultFont () {
1035 if (display.smallFonts) return display.getSystemFont ();
1036 return Font.cocoa_new (display, defaultNSFont ());
1037 }
1038
defaultForeground()1039 Color defaultForeground () {
1040 return display.getWidgetColor (SWT.COLOR_WIDGET_FOREGROUND);
1041 }
1042
defaultNSFont()1043 NSFont defaultNSFont () {
1044 return display.getSystemFont().handle;
1045 }
1046
1047 @Override
deregister()1048 void deregister () {
1049 super.deregister ();
1050 display.removeWidget (view);
1051 }
1052
1053 @Override
destroyWidget()1054 void destroyWidget () {
1055 NSView view = topView ();
1056 view.removeFromSuperview ();
1057 releaseHandle ();
1058 }
1059
1060 @Override
doCommandBySelector(long id, long sel, long selector)1061 void doCommandBySelector (long id, long sel, long selector) {
1062 if (hasKeyboardFocus(id)) {
1063 if (imeInComposition ()) return;
1064 Shell s = this.getShell();
1065 NSEvent nsEvent = NSApplication.sharedApplication ().currentEvent ();
1066 if (nsEvent != null && nsEvent.type () == OS.NSKeyDown) {
1067 /*
1068 * Feature in Cocoa. Pressing Alt+UpArrow invokes doCommandBySelector
1069 * twice, with selectors moveBackward and moveToBeginningOfParagraph
1070 * (Alt+DownArrow behaves similarly). In order to avoid sending
1071 * multiple events for these keys, do not send a KeyDown if we already sent one
1072 * during this keystroke. This rule does not apply if the command key
1073 * is down, because we likely triggered the current key sequence via flagsChanged.
1074 */
1075 long modifiers = nsEvent.modifierFlags();
1076 if (s.keyInputHappened == false || (modifiers & OS.NSCommandKeyMask) != 0) {
1077 s.keyInputHappened = true;
1078 boolean [] consume = new boolean [1];
1079 if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return;
1080 if (isDisposed ()) return;
1081 if (!sendKeyEvent (nsEvent, SWT.KeyDown)) return;
1082 if (consume [0]) return;
1083 }
1084 }
1085 if ((state & CANVAS) != 0) return;
1086 }
1087 super.doCommandBySelector (id, sel, selector);
1088 }
1089
1090 /**
1091 * Detects a drag and drop gesture. This method is used
1092 * to detect a drag gesture when called from within a mouse
1093 * down listener.
1094 *
1095 * <p>By default, a drag is detected when the gesture
1096 * occurs anywhere within the client area of a control.
1097 * Some controls, such as tables and trees, override this
1098 * behavior. In addition to the operating system specific
1099 * drag gesture, they require the mouse to be inside an
1100 * item. Custom widget writers can use <code>setDragDetect</code>
1101 * to disable the default detection, listen for mouse down,
1102 * and then call <code>dragDetect()</code> from within the
1103 * listener to conditionally detect a drag.
1104 * </p>
1105 *
1106 * @param event the mouse down event
1107 *
1108 * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
1109 *
1110 * @exception IllegalArgumentException <ul>
1111 * <li>ERROR_NULL_ARGUMENT if the event is null</li>
1112 * </ul>
1113 * @exception SWTException <ul>
1114 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1115 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1116 * </ul>
1117 *
1118 * @see DragDetectListener
1119 * @see #addDragDetectListener
1120 *
1121 * @see #getDragDetect
1122 * @see #setDragDetect
1123 *
1124 * @since 3.3
1125 */
dragDetect(Event event)1126 public boolean dragDetect (Event event) {
1127 checkWidget ();
1128 if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
1129 return dragDetect (event.button, event.count, event.stateMask, event.x, event.y);
1130 }
1131
1132 /**
1133 * Detects a drag and drop gesture. This method is used
1134 * to detect a drag gesture when called from within a mouse
1135 * down listener.
1136 *
1137 * <p>By default, a drag is detected when the gesture
1138 * occurs anywhere within the client area of a control.
1139 * Some controls, such as tables and trees, override this
1140 * behavior. In addition to the operating system specific
1141 * drag gesture, they require the mouse to be inside an
1142 * item. Custom widget writers can use <code>setDragDetect</code>
1143 * to disable the default detection, listen for mouse down,
1144 * and then call <code>dragDetect()</code> from within the
1145 * listener to conditionally detect a drag.
1146 * </p>
1147 *
1148 * @param event the mouse down event
1149 *
1150 * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
1151 *
1152 * @exception IllegalArgumentException <ul>
1153 * <li>ERROR_NULL_ARGUMENT if the event is null</li>
1154 * </ul>
1155 * @exception SWTException <ul>
1156 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1157 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1158 * </ul>
1159 *
1160 * @see DragDetectListener
1161 * @see #addDragDetectListener
1162 *
1163 * @see #getDragDetect
1164 * @see #setDragDetect
1165 *
1166 * @since 3.3
1167 */
dragDetect(MouseEvent event)1168 public boolean dragDetect (MouseEvent event) {
1169 checkWidget ();
1170 if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
1171 return dragDetect (event.button, event.count, event.stateMask, event.x, event.y);
1172 }
1173
dragDetect(int button, int count, int stateMask, int x, int y)1174 boolean dragDetect (int button, int count, int stateMask, int x, int y) {
1175 if (button != 1 || count != 1) return false;
1176 if (!dragDetect (x, y, false, null)) return false;
1177 return sendDragEvent (button, stateMask, x, y);
1178 }
1179
dragDetect(int x, int y, boolean filter, boolean [] consume)1180 boolean dragDetect (int x, int y, boolean filter, boolean [] consume) {
1181 /**
1182 * Feature in Cocoa. Mouse drag events do not account for hysteresis.
1183 * As soon as the mouse drags a mouse dragged event is fired. Fix is to
1184 * check for another mouse drag event that is at least 5 pixels away
1185 * from the start of the drag.
1186 */
1187 NSApplication application = NSApplication.sharedApplication();
1188 boolean dragging = false;
1189 long eventType = OS.NSLeftMouseDown;
1190 double dragX = x;
1191 double dragY = y;
1192
1193 /**
1194 * To check for an actual drag we need to pull off mouse moved and mouse up events
1195 * to detect if the user dragged outside of a 10 x 10 box centered on the mouse down location.
1196 * We still want the view to see the events, so save them and re-post when done checking.
1197 * If no motion happens for .3 seconds, bail.
1198 */
1199 NSEvent mouseUpEvent = null;
1200 NSMutableArray dragEvents = NSMutableArray.arrayWithCapacity(10);
1201 NSDate timeout = NSDate.dateWithTimeIntervalSinceNow(0.3);
1202
1203 while (eventType != OS.NSLeftMouseUp) {
1204 NSEvent event = application.nextEventMatchingMask((OS.NSLeftMouseUpMask | OS.NSLeftMouseDraggedMask),
1205 timeout, OS.NSEventTrackingRunLoopMode, true);
1206 // No event means nextEventMatchingMask timed out.
1207 if (event == null) {
1208 dragging = true;
1209 break;
1210 }
1211 eventType = event.type();
1212
1213 if (eventType == OS.NSLeftMouseDragged) {
1214 dragEvents.addObject(event);
1215 NSPoint windowLoc = event.locationInWindow();
1216 NSPoint viewLoc = view.convertPoint_fromView_(windowLoc, null);
1217 if (!view.isFlipped ()) {
1218 viewLoc.y = view.bounds().height - viewLoc.y;
1219 }
1220 if ((Math.abs(viewLoc.x - dragX) > DEFAULT_DRAG_HYSTERESIS) || (Math.abs(viewLoc.y - dragY) > DEFAULT_DRAG_HYSTERESIS)) {
1221 dragging = true;
1222 break;
1223 }
1224 } else if (eventType == OS.NSLeftMouseUp) {
1225 mouseUpEvent = event;
1226 }
1227 }
1228
1229 // Push back any events we took out of the queue so the control can receive them.
1230 if (mouseUpEvent != null) application.postEvent(mouseUpEvent, true);
1231
1232 if (dragEvents.count() > 0) {
1233 while (dragEvents.count() > 0) {
1234 NSEvent currEvent = new NSEvent(dragEvents.objectAtIndex(dragEvents.count() - 1).id);
1235 dragEvents.removeLastObject();
1236 application.postEvent(currEvent, true);
1237 }
1238 }
1239
1240 return dragging;
1241 }
1242
drawGripper(GC gc, int x, int y, int width, int height, boolean vertical)1243 boolean drawGripper (GC gc, int x, int y, int width, int height, boolean vertical) {
1244 return false;
1245 }
1246
drawsBackground()1247 boolean drawsBackground() {
1248 return true;
1249 }
1250
1251 @Override
drawWidget(long id, NSGraphicsContext context, NSRect rect)1252 void drawWidget (long id, NSGraphicsContext context, NSRect rect) {
1253 if (id != paintView().id) return;
1254 if (!hooks (SWT.Paint) && !filters (SWT.Paint)) return;
1255
1256 /* Send paint event */
1257 GCData data = new GCData ();
1258 data.paintRect = rect;
1259 GC gc = GC.cocoa_new (this, data);
1260 Event event = new Event ();
1261 event.gc = gc;
1262 event.x = (int)rect.x;
1263 event.y = (int)rect.y;
1264 event.width = (int)rect.width;
1265 event.height = (int)rect.height;
1266 sendEvent (SWT.Paint, event);
1267 event.gc = null;
1268 gc.dispose ();
1269 }
1270
enableWidget(boolean enabled)1271 void enableWidget (boolean enabled) {
1272 if (view instanceof NSControl) {
1273 ((NSControl)view).setEnabled(enabled);
1274 }
1275 updateCursorRects (isEnabled ());
1276 }
1277
equals(double [] color1, double [] color2)1278 boolean equals(double [] color1, double [] color2) {
1279 if (color1 == color2) return true;
1280 if (color1 == null) return color2 == null;
1281 if (color2 == null) return color1 == null;
1282 for (int i = 0; i < color1.length; i++) {
1283 if (color1 [i] != color2 [i]) return false;
1284 }
1285 return true;
1286 }
1287
eventView()1288 NSView eventView () {
1289 return view;
1290 }
1291
fillBackground(NSView view, NSGraphicsContext context, NSRect rect, int imgHeight)1292 void fillBackground (NSView view, NSGraphicsContext context, NSRect rect, int imgHeight) {
1293 fillBackground(view, context, rect, imgHeight, null, 0, 0);
1294 }
1295
fillBackground(NSView view, NSGraphicsContext context, NSRect rect, int imgHeight, NSView gcView, int tx, int ty)1296 void fillBackground (NSView view, NSGraphicsContext context, NSRect rect, int imgHeight, NSView gcView, int tx, int ty) {
1297 if (!drawsBackground()) return;
1298 Control control = findBackgroundControl();
1299 if (control == null) control = this;
1300 Image image = control.backgroundImage;
1301 if (image != null && !image.isDisposed()) {
1302 context.saveGraphicsState();
1303 NSColor.colorWithPatternImage(image.handle).setFill();
1304 NSPoint phase = new NSPoint();
1305 NSView controlView = control.view;
1306 if (!controlView.isFlipped()) {
1307 phase.y = controlView.bounds().height;
1308 }
1309 if (imgHeight == -1) {
1310 NSView contentView = controlView.window().contentView();
1311 phase = controlView.convertPoint_toView_(phase, contentView);
1312 phase.y = contentView.bounds().height - phase.y;
1313 } else {
1314 phase = view.convertPoint_toView_(phase, controlView);
1315 phase.y += imgHeight - backgroundImage.getBounds().height;
1316 }
1317 if (gcView != null) {
1318 NSPoint pt = gcView.convertPoint_toView_(new NSPoint(), view);
1319 phase.x += pt.x;
1320 phase.y -= pt.y;
1321 }
1322 phase.x -= tx;
1323 phase.y += ty;
1324 context.setPatternPhase(phase);
1325 NSBezierPath.fillRect(rect);
1326 context.restoreGraphicsState();
1327 return;
1328 }
1329
1330 double [] background = control.background;
1331 double alpha;
1332 if (background == null) {
1333 if (isTransparent()) return;
1334 background = control.defaultBackground ().handle;
1335 alpha = getThemeAlpha ();
1336 } else {
1337 alpha = background[3];
1338 }
1339 context.saveGraphicsState ();
1340 NSColor.colorWithDeviceRed (background [0], background [1], background [2], alpha).setFill ();
1341 NSBezierPath.fillRect (rect);
1342 context.restoreGraphicsState ();
1343 }
1344
findCursor()1345 Cursor findCursor () {
1346 if (cursor != null) return cursor;
1347 return parent.findCursor ();
1348 }
1349
findBackgroundControl()1350 Control findBackgroundControl () {
1351 if ((backgroundImage != null || background != null) && backgroundAlpha > 0) return this;
1352 return (parent != null && !isTransparent() && (state & PARENT_BACKGROUND) != 0) ? parent.findBackgroundControl () : null;
1353 }
1354
findMenus(Control control)1355 Menu [] findMenus (Control control) {
1356 if (menu != null && this != control) return new Menu [] {menu};
1357 return new Menu [0];
1358 }
1359
findTooltip(NSPoint pt)1360 Widget findTooltip (NSPoint pt) {
1361 return this;
1362 }
1363
fixChildren(Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus)1364 void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
1365 oldShell.fixShell (newShell, this);
1366 oldDecorations.fixDecorations (newDecorations, this, menus);
1367 }
1368
fixFocus(Control focusControl)1369 void fixFocus (Control focusControl) {
1370 Shell shell = getShell ();
1371 Control control = this;
1372 while (control != shell && (control = control.parent) != null) {
1373 if (control.setFocus ()) return;
1374 }
1375 shell.setSavedFocus (focusControl);
1376 NSWindow window = view.window();
1377 if (!window.makeFirstResponder(null)) {
1378 // Force first responder to resign.
1379 window.endEditingFor(null);
1380 }
1381 }
1382
1383 @Override
flagsChanged(long id, long sel, long theEvent)1384 void flagsChanged (long id, long sel, long theEvent) {
1385 if (hasKeyboardFocus(id)) {
1386 if ((state & WEBKIT_EVENTS_FIX) == 0) {
1387 Shell s = this.getShell();
1388 s.keyInputHappened = false;
1389 int mask = 0;
1390 NSEvent nsEvent = new NSEvent (theEvent);
1391 long modifiers = nsEvent.modifierFlags ();
1392 int keyCode = Display.translateKey (nsEvent.keyCode ());
1393 switch (keyCode) {
1394 case SWT.ALT: mask = OS.NSAlternateKeyMask; break;
1395 case SWT.CONTROL: mask = OS.NSControlKeyMask; break;
1396 case SWT.COMMAND: mask = OS.NSCommandKeyMask; break;
1397 case SWT.SHIFT: mask = OS.NSShiftKeyMask; break;
1398 case SWT.CAPS_LOCK:
1399 Event event = new Event();
1400 event.keyCode = keyCode;
1401 setInputState (event, nsEvent, SWT.KeyDown);
1402 sendKeyEvent (SWT.KeyDown, event);
1403 setInputState (event, nsEvent, SWT.KeyUp);
1404 sendKeyEvent (SWT.KeyUp, event);
1405 break;
1406 }
1407 if (mask != 0) {
1408 s.keyInputHappened = true;
1409 int type = (mask & modifiers) != 0 ? SWT.KeyDown : SWT.KeyUp;
1410 Event event = new Event();
1411 event.keyCode = keyCode;
1412 setLocationMask(event, nsEvent);
1413 setInputState (event, nsEvent, type);
1414 if (!sendKeyEvent (type, event)) return;
1415 }
1416 }
1417 }
1418 super.flagsChanged (id, sel, theEvent);
1419 }
1420
focusView()1421 NSView focusView () {
1422 return view;
1423 }
1424
1425 /**
1426 * Forces the receiver to have the <em>keyboard focus</em>, causing
1427 * all keyboard events to be delivered to it.
1428 *
1429 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
1430 *
1431 * @exception SWTException <ul>
1432 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1433 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1434 * </ul>
1435 *
1436 * @see #setFocus
1437 */
forceFocus()1438 public boolean forceFocus () {
1439 checkWidget();
1440 if (display.focusEvent == SWT.FocusOut) return false;
1441 Decorations shell = menuShell ();
1442 shell.setSavedFocus (this);
1443 if (!isEnabled () || !isVisible () || !isActive ()) return false;
1444 if (isFocusControl ()) return true;
1445 shell.setSavedFocus (null);
1446 NSView focusView = focusView ();
1447 if (!focusView.canBecomeKeyView()) return false;
1448 boolean result = forceFocus(focusView);
1449 if (isDisposed ()) return false;
1450 shell.setSavedFocus (this);
1451 /*
1452 * Feature in Cocoa. If the window is inactive when forceFocus is called bringToTop
1453 * eventually calls makeKeyAndOrderFront. This activates the window immediately, but unlike other platforms,
1454 * it also immediately fire notifications that the window was activated, as opposed to posting an event
1455 * to be handled on the next pass of readAndDispatch().
1456 *
1457 * Shell#windowDidBecomeKey will call Decorations#restoreFocus, so the saved focus must be set
1458 * before the window is activated or the wrong control will get focus.
1459 */
1460 shell.bringToTop (false);
1461 if (isDisposed ()) return false;
1462 return result;
1463 }
1464
forceFocus(NSView focusView)1465 boolean forceFocus (NSView focusView) {
1466 NSWindow window = view.window ();
1467 if(window == null) { return false; }
1468 return window.makeFirstResponder (focusView);
1469 }
1470
gestureEvent(long id, long eventPtr, int detail)1471 boolean gestureEvent(long id, long eventPtr, int detail) {
1472 if (!display.sendEvent) return true;
1473 display.sendEvent = false;
1474 // For cross-platform compatibility, touch events and gestures are mutually exclusive.
1475 // Don't send a gesture if touch events are enabled for this control.
1476 if (touchEnabled) return true;
1477 if (!isEventView (id)) return true;
1478 if (!hooks(SWT.Gesture) && !filters(SWT.Gesture)) return true;
1479 NSEvent nsEvent = new NSEvent(eventPtr);
1480 Event event = new Event();
1481 NSPoint windowPoint;
1482 NSView view = eventView ();
1483 windowPoint = nsEvent.locationInWindow();
1484 NSPoint point = view.convertPoint_fromView_(windowPoint, null);
1485 if (!view.isFlipped ()) {
1486 point.y = view.bounds().height - point.y;
1487 }
1488 event.x = (int) point.x;
1489 event.y = (int) point.y;
1490 setInputState (event, nsEvent, SWT.Gesture);
1491
1492 long phase = nsEvent.phase();
1493 if (phase == OS.NSEventPhaseBegan) {
1494 detail = SWT.GESTURE_BEGIN;
1495 display.rotation = 0.0;
1496 display.magnification = 1.0;
1497 display.gestureActive = true;
1498 } else if (phase == OS.NSEventPhaseCancelled || phase == OS.NSEventPhaseEnded) {
1499 detail = SWT.GESTURE_END;
1500 display.gestureActive = false;
1501 }
1502 event.detail = detail;
1503
1504 switch (detail) {
1505 case SWT.GESTURE_SWIPE:
1506 event.xDirection = (int) -nsEvent.deltaX();
1507 event.yDirection = (int) -nsEvent.deltaY();
1508 break;
1509 case SWT.GESTURE_ROTATE: {
1510 display.rotation += nsEvent.rotation();
1511 event.rotation = display.rotation;
1512 break;
1513 }
1514 case SWT.GESTURE_MAGNIFY:
1515 display.magnification *= (1.0 + nsEvent.magnification());
1516 event.magnification = display.magnification;
1517 break;
1518 case SWT.GESTURE_PAN:
1519 // Panning increment is expressed in terms of the direction of movement,
1520 // not in terms of scrolling increment.
1521 if (display.gestureActive) {
1522 event.xDirection = (int) nsEvent.deltaX();
1523 event.yDirection = (int) nsEvent.deltaY();
1524 }
1525 if (event.xDirection == 0 && event.yDirection == 0) return true;
1526 break;
1527 }
1528
1529 sendEvent (SWT.Gesture, event);
1530 return event.doit;
1531 }
1532
1533 /**
1534 * Returns the accessible object for the receiver.
1535 * <p>
1536 * If this is the first time this object is requested,
1537 * then the object is created and returned. The object
1538 * returned by getAccessible() does not need to be disposed.
1539 * </p>
1540 *
1541 * @return the accessible object
1542 *
1543 * @exception SWTException <ul>
1544 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1545 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1546 * </ul>
1547 *
1548 * @see Accessible#addAccessibleListener
1549 * @see Accessible#addAccessibleControlListener
1550 *
1551 * @since 2.0
1552 */
getAccessible()1553 public Accessible getAccessible () {
1554 checkWidget ();
1555 if (accessible == null) accessible = new_Accessible (this);
1556 return accessible;
1557 }
1558
1559 /**
1560 * Returns the receiver's background color.
1561 * <p>
1562 * Note: This operation is a hint and may be overridden by the platform.
1563 * For example, on some versions of Windows the background of a TabFolder,
1564 * is a gradient rather than a solid color.
1565 * </p>
1566 * @return the background color
1567 *
1568 * @exception SWTException <ul>
1569 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1570 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1571 * </ul>
1572 */
getBackground()1573 public Color getBackground () {
1574 checkWidget();
1575 if (backgroundAlpha == 0) {
1576 Color color = Color.cocoa_new (display, background, 0);
1577 return color;
1578 }
1579 else {
1580 Control control = findBackgroundControl ();
1581 if (control == null) control = this;
1582 return control.getBackgroundColor ();
1583 }
1584 }
1585
getBackgroundColor()1586 Color getBackgroundColor () {
1587 return background != null ? Color.cocoa_new (display, background, backgroundAlpha) : defaultBackground ();
1588 }
1589
1590 /**
1591 * Returns the receiver's background image.
1592 *
1593 * @return the background image
1594 *
1595 * @exception SWTException <ul>
1596 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1597 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1598 * </ul>
1599 *
1600 * @since 3.2
1601 */
getBackgroundImage()1602 public Image getBackgroundImage () {
1603 checkWidget();
1604 Control control = findBackgroundControl ();
1605 if (control == null) control = this;
1606 return control.backgroundImage;
1607 }
1608
1609 /**
1610 * Returns the receiver's border width in points.
1611 *
1612 * @return the border width
1613 *
1614 * @exception SWTException <ul>
1615 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1616 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1617 * </ul>
1618 */
getBorderWidth()1619 public int getBorderWidth () {
1620 checkWidget();
1621 return 0;
1622 }
1623
1624 /**
1625 * Returns a rectangle describing the receiver's size and location in points
1626 * relative to its parent (or its display if its parent is null),
1627 * unless the receiver is a shell. In this case, the location is
1628 * relative to the display.
1629 *
1630 * @return the receiver's bounding rectangle
1631 *
1632 * @exception SWTException <ul>
1633 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1634 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1635 * </ul>
1636 */
getBounds()1637 public Rectangle getBounds () {
1638 checkWidget();
1639 NSRect rect = topView().frame();
1640 return new Rectangle((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
1641 }
1642
1643 /**
1644 * Returns <code>true</code> if the receiver is detecting
1645 * drag gestures, and <code>false</code> otherwise.
1646 *
1647 * @return the receiver's drag detect state
1648 *
1649 * @exception SWTException <ul>
1650 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1651 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1652 * </ul>
1653 *
1654 * @since 3.3
1655 */
getDragDetect()1656 public boolean getDragDetect () {
1657 checkWidget ();
1658 return (state & DRAG_DETECT) != 0;
1659 }
1660
1661 @Override
getDrawing()1662 boolean getDrawing () {
1663 return drawCount <= 0;
1664 }
1665
1666 /**
1667 * Returns the receiver's cursor, or null if it has not been set.
1668 * <p>
1669 * When the mouse pointer passes over a control its appearance
1670 * is changed to match the control's cursor.
1671 * </p>
1672 *
1673 * @return the receiver's cursor or <code>null</code>
1674 *
1675 * @exception SWTException <ul>
1676 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1677 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1678 * </ul>
1679 *
1680 * @since 3.3
1681 */
getCursor()1682 public Cursor getCursor () {
1683 checkWidget();
1684 return cursor;
1685 }
1686
1687 /**
1688 * Returns <code>true</code> if the receiver is enabled, and
1689 * <code>false</code> otherwise. A disabled control is typically
1690 * not selectable from the user interface and draws with an
1691 * inactive or "grayed" look.
1692 *
1693 * @return the receiver's enabled state
1694 *
1695 * @exception SWTException <ul>
1696 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1697 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1698 * </ul>
1699 *
1700 * @see #isEnabled
1701 */
getEnabled()1702 public boolean getEnabled () {
1703 checkWidget();
1704 return (state & DISABLED) == 0;
1705 }
1706
1707 /**
1708 * Returns the font that the receiver will use to paint textual information.
1709 *
1710 * @return the receiver's font
1711 *
1712 * @exception SWTException <ul>
1713 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1714 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1715 * </ul>
1716 */
getFont()1717 public Font getFont () {
1718 checkWidget();
1719 return font != null ? font : defaultFont ();
1720 }
1721
1722 /**
1723 * Returns the foreground color that the receiver will use to draw.
1724 *
1725 * @return the receiver's foreground color
1726 *
1727 * @exception SWTException <ul>
1728 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1729 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1730 * </ul>
1731 */
getForeground()1732 public Color getForeground () {
1733 checkWidget();
1734 return getForegroundColor ();
1735 }
1736
getForegroundColor()1737 Color getForegroundColor () {
1738 return foreground != null ? Color.cocoa_new (display, foreground) : defaultForeground ();
1739 }
1740
1741 /**
1742 * Returns layout data which is associated with the receiver.
1743 *
1744 * @return the receiver's layout data
1745 *
1746 * @exception SWTException <ul>
1747 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1748 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1749 * </ul>
1750 */
getLayoutData()1751 public Object getLayoutData () {
1752 checkWidget();
1753 return layoutData;
1754 }
1755
1756 /**
1757 * Returns a point describing the receiver's location relative
1758 * to its parent in points (or its display if its parent is null), unless
1759 * the receiver is a shell. In this case, the point is
1760 * relative to the display.
1761 *
1762 * @return the receiver's location
1763 *
1764 * @exception SWTException <ul>
1765 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1766 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1767 * </ul>
1768 */
getLocation()1769 public Point getLocation () {
1770 checkWidget();
1771 NSRect rect = topView().frame();
1772 return new Point((int)rect.x, (int)rect.y);
1773 }
1774
1775 /**
1776 * Returns the receiver's pop up menu if it has one, or null
1777 * if it does not. All controls may optionally have a pop up
1778 * menu that is displayed when the user requests one for
1779 * the control. The sequence of key strokes, button presses
1780 * and/or button releases that are used to request a pop up
1781 * menu is platform specific.
1782 *
1783 * @return the receiver's menu
1784 *
1785 * @exception SWTException <ul>
1786 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1787 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1788 * </ul>
1789 */
getMenu()1790 public Menu getMenu () {
1791 checkWidget();
1792 return menu;
1793 }
1794
getMininumHeight()1795 int getMininumHeight () {
1796 return 0;
1797 }
1798
1799 /**
1800 * Returns the receiver's monitor.
1801 *
1802 * @return the receiver's monitor
1803 *
1804 * @exception SWTException <ul>
1805 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1806 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1807 * </ul>
1808 *
1809 * @since 3.0
1810 */
getMonitor()1811 public Monitor getMonitor () {
1812 checkWidget();
1813 Monitor [] monitors = display.getMonitors ();
1814 if (monitors.length == 1) return monitors [0];
1815 int index = -1, value = -1;
1816 Rectangle bounds = getBounds ();
1817 if (this != getShell ()) {
1818 bounds = display.map (this.parent, null, bounds);
1819 }
1820 for (int i=0; i<monitors.length; i++) {
1821 Rectangle rect = bounds.intersection (monitors [i].getBounds ());
1822 int area = rect.width * rect.height;
1823 if (area > 0 && area > value) {
1824 index = i;
1825 value = area;
1826 }
1827 }
1828 if (index >= 0) return monitors [index];
1829 int centerX = bounds.x + bounds.width / 2, centerY = bounds.y + bounds.height / 2;
1830 for (int i=0; i<monitors.length; i++) {
1831 Rectangle rect = monitors [i].getBounds ();
1832 int x = centerX < rect.x ? rect.x - centerX : centerX > rect.x + rect.width ? centerX - rect.x - rect.width : 0;
1833 int y = centerY < rect.y ? rect.y - centerY : centerY > rect.y + rect.height ? centerY - rect.y - rect.height : 0;
1834 int distance = x * x + y * y;
1835 if (index == -1 || distance < value) {
1836 index = i;
1837 value = distance;
1838 }
1839 }
1840 return monitors [index];
1841 }
1842
1843 /**
1844 * Returns the orientation of the receiver, which will be one of the
1845 * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
1846 *
1847 * @return the orientation style
1848 *
1849 * @exception SWTException <ul>
1850 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1851 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1852 * </ul>
1853 *
1854 * @since 3.7
1855 */
getOrientation()1856 public int getOrientation () {
1857 checkWidget ();
1858 return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
1859 }
1860
1861 /**
1862 * Returns the receiver's parent, which must be a <code>Composite</code>
1863 * or null when the receiver is a shell that was created with null or
1864 * a display for a parent.
1865 *
1866 * @return the receiver's parent
1867 *
1868 * @exception SWTException <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 */
getParent()1873 public Composite getParent () {
1874 checkWidget();
1875 return parent;
1876 }
1877
getPath()1878 Control [] getPath () {
1879 int count = 0;
1880 Shell shell = getShell ();
1881 Control control = this;
1882 while (control != shell) {
1883 count++;
1884 control = control.parent;
1885 }
1886 control = this;
1887 Control [] result = new Control [count];
1888 while (control != shell) {
1889 result [--count] = control;
1890 control = control.parent;
1891 }
1892 return result;
1893 }
1894
getPath(Region region)1895 NSBezierPath getPath(Region region) {
1896 if (region == null) return null;
1897 return getPath(region.handle);
1898 }
1899
getPath(long region)1900 NSBezierPath getPath(long region) {
1901 Callback callback = new Callback(this, "regionToRects", 4);
1902 NSBezierPath path = NSBezierPath.bezierPath();
1903 path.retain();
1904 OS.QDRegionToRects(region, OS.kQDParseRegionFromTopLeft, callback.getAddress(), path.id);
1905 callback.dispose();
1906 if (path.isEmpty()) path.appendBezierPathWithRect(new NSRect());
1907 return path;
1908 }
1909
1910 /**
1911 * Returns the region that defines the shape of the control,
1912 * or null if the control has the default shape.
1913 *
1914 * @return the region that defines the shape of the shell (or null)
1915 *
1916 * @exception SWTException <ul>
1917 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1918 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1919 * </ul>
1920 *
1921 * @since 3.4
1922 */
getRegion()1923 public Region getRegion () {
1924 checkWidget ();
1925 return region;
1926 }
1927
1928 /**
1929 * Returns the receiver's shell. For all controls other than
1930 * shells, this simply returns the control's nearest ancestor
1931 * shell. Shells return themselves, even if they are children
1932 * of other shells.
1933 *
1934 * @return the receiver's shell
1935 *
1936 * @exception SWTException <ul>
1937 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1938 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1939 * </ul>
1940 *
1941 * @see #getParent
1942 */
getShell()1943 public Shell getShell () {
1944 checkWidget();
1945 return parent.getShell ();
1946 }
1947
1948 /**
1949 * Returns a point describing the receiver's size in points. The
1950 * x coordinate of the result is the width of the receiver.
1951 * The y coordinate of the result is the height of the
1952 * receiver.
1953 *
1954 * @return the receiver's size
1955 *
1956 * @exception SWTException <ul>
1957 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1958 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1959 * </ul>
1960 */
getSize()1961 public Point getSize () {
1962 checkWidget();
1963 NSRect rect = topView().frame();
1964 return new Point((int)rect.width, (int)rect.height);
1965 }
1966
1967 /**
1968 * Returns the text direction of the receiver, which will be one of the
1969 * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
1970 *
1971 * @return the text direction style
1972 *
1973 * @exception SWTException <ul>
1974 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1975 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1976 * </ul>
1977 *
1978 * @since 3.102
1979 */
getTextDirection()1980 public int getTextDirection() {
1981 checkWidget ();
1982 /* return the widget orientation */
1983 return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
1984 }
1985
getThemeAlpha()1986 float getThemeAlpha () {
1987 return 1 * parent.getThemeAlpha ();
1988 }
1989
1990 /**
1991 * Returns the receiver's tool tip text, or null if it has
1992 * not been set.
1993 *
1994 * @return the receiver's tool tip text
1995 *
1996 * @exception SWTException <ul>
1997 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1998 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1999 * </ul>
2000 */
getToolTipText()2001 public String getToolTipText () {
2002 checkWidget();
2003 return toolTipText;
2004 }
2005
2006 /**
2007 * Returns <code>true</code> if this control is set to send touch events, or
2008 * <code>false</code> if it is set to send gesture events instead. This method
2009 * also returns <code>false</code> if a touch-based input device is not detected
2010 * (this can be determined with <code>Display#getTouchEnabled()</code>). Use
2011 * {@link #setTouchEnabled(boolean)} to switch the events that a control sends
2012 * between touch events and gesture events.
2013 *
2014 * @return <code>true</code> if the control is set to send touch events, or <code>false</code> otherwise
2015 *
2016 * @exception SWTException <ul>
2017 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2018 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2019 * </ul>
2020 *
2021 * @see #setTouchEnabled
2022 * @see Display#getTouchEnabled
2023 *
2024 * @since 3.7
2025 */
getTouchEnabled()2026 public boolean getTouchEnabled() {
2027 checkWidget();
2028 return display.getTouchEnabled() && touchEnabled;
2029 }
2030
2031 /**
2032 * Returns <code>true</code> if the receiver is visible, and
2033 * <code>false</code> otherwise.
2034 * <p>
2035 * If one of the receiver's ancestors is not visible or some
2036 * other condition makes the receiver not visible, this method
2037 * may still indicate that it is considered visible even though
2038 * it may not actually be showing.
2039 * </p>
2040 *
2041 * @return the receiver's visibility state
2042 *
2043 * @exception SWTException <ul>
2044 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2045 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2046 * </ul>
2047 */
getVisible()2048 public boolean getVisible () {
2049 checkWidget();
2050 return (state & HIDDEN) == 0;
2051 }
2052
getVisibleRegion()2053 long getVisibleRegion () {
2054 if (visibleRgn == 0) {
2055 visibleRgn = OS.NewRgn ();
2056 calculateVisibleRegion (view, visibleRgn, true);
2057 }
2058 long result = OS.NewRgn ();
2059 OS.CopyRgn (visibleRgn, result);
2060 return result;
2061 }
2062
hasBorder()2063 boolean hasBorder () {
2064 return (style & SWT.BORDER) != 0;
2065 }
2066
hasFocus()2067 boolean hasFocus () {
2068 return display.getFocusControl() == this;
2069 }
2070
hasRegion()2071 boolean hasRegion () {
2072 return region != null || parent.hasRegion ();
2073 }
2074
2075 @Override
hitTest(long id, long sel, NSPoint point)2076 long hitTest (long id, long sel, NSPoint point) {
2077 if ((state & DISABLED) != 0) return 0;
2078 if (!isActive ()) return 0;
2079 if (regionPath != null) {
2080 NSView rgnView = topView ();
2081 if (!rgnView.isFlipped()) rgnView = eventView ();
2082 NSPoint pt = rgnView.convertPoint_fromView_ (point, new NSView (id).superview());
2083 if (!regionPath.containsPoint(pt)) return 0;
2084 }
2085 return super.hitTest(id, sel, point);
2086 }
2087
imeInComposition()2088 boolean imeInComposition () {
2089 return false;
2090 }
2091
2092 @Override
insertText(long id, long sel, long string)2093 boolean insertText (long id, long sel, long string) {
2094 // sendKeyEvent may do something to run the event loop. That would cause
2095 // 'string' to be released before any superclass could use it, so save it
2096 // until this method finishes.
2097 NSObject saver = new NSObject(string);
2098 saver.retain();
2099 try {
2100 if (hasKeyboardFocus(id)) {
2101 Shell s = this.getShell();
2102 NSEvent nsEvent = NSApplication.sharedApplication ().currentEvent ();
2103 if (nsEvent != null) {
2104 long type = nsEvent.type ();
2105 if (type == OS.NSKeyDown || type == OS.NSKeyUp || type == OS.NSSystemDefined) {
2106 NSString str = new NSString (string);
2107 if (str.isKindOfClass (OS.class_NSAttributedString)) {
2108 str = new NSAttributedString (string).string ();
2109 }
2110 int length = (int)str.length ();
2111 char[] buffer = new char [length];
2112 str.getCharacters(buffer);
2113 for (int i = 0; i < buffer.length; i++) {
2114 s.keyInputHappened = true;
2115 Event event = new Event ();
2116 if (i == 0 && type == OS.NSKeyDown) setKeyState (event, SWT.KeyDown, nsEvent);
2117 event.character = buffer [i];
2118 if (!sendKeyEvent (SWT.KeyDown, event)) return false;
2119 }
2120 }
2121 }
2122 if ((state & CANVAS) != 0) return true;
2123 }
2124
2125 return super.insertText (id, sel, string);
2126 } finally {
2127 saver.release();
2128 }
2129 }
2130
2131 /**
2132 * Invokes platform specific functionality to allocate a new GC handle.
2133 * <p>
2134 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
2135 * API for <code>Control</code>. It is marked public only so that it
2136 * can be shared within the packages provided by SWT. It is not
2137 * available on all platforms, and should never be called from
2138 * application code.
2139 * </p>
2140 *
2141 * @param data the platform specific GC data
2142 * @return the platform specific GC handle
2143 *
2144 * @noreference This method is not intended to be referenced by clients.
2145 */
2146 @Override
internal_new_GC(GCData data)2147 public long internal_new_GC (GCData data) {
2148 checkWidget();
2149 NSView view = paintView();
2150 NSGraphicsContext graphicsContext = null;
2151 if (data != null && data.paintRect != null) {
2152 graphicsContext = NSGraphicsContext.currentContext();
2153 if (!view.isFlipped()) data.state &= ~VISIBLE_REGION;
2154 }
2155 if (graphicsContext == null) {
2156 NSWindow window = view.window();
2157 /*
2158 * Force the device to be created before attempting
2159 * to create a GC on a deferred NSWindow.
2160 */
2161 if (window.windowNumber() <= 0) {
2162 double alpha = window.alphaValue();
2163 window.setAlphaValue(0);
2164 window.orderBack(null);
2165 window.orderOut(null);
2166 window.setAlphaValue(alpha);
2167 }
2168 graphicsContext = NSGraphicsContext.graphicsContextWithWindow (window);
2169 if (graphicsContext == null) {
2170 // create a bitmap based context, which will still work e.g. for text size computations
2171 // it is unclear if the bitmap needs to be larger than the text to be measured.
2172 // the following values should be big enough in any case.
2173 int width = 1920;
2174 int height = 256;
2175 NSBitmapImageRep rep = (NSBitmapImageRep) new NSBitmapImageRep().alloc();
2176 rep = rep.initWithBitmapDataPlanes(0, width, height, 8, 3, false, false, OS.NSDeviceRGBColorSpace,
2177 OS.NSAlphaFirstBitmapFormat, width * 4, 32);
2178 graphicsContext = NSGraphicsContext.graphicsContextWithBitmapImageRep(rep);
2179 rep.release();
2180 }
2181 NSGraphicsContext flippedContext = NSGraphicsContext.graphicsContextWithGraphicsPort(graphicsContext.graphicsPort(), true);
2182 graphicsContext = flippedContext;
2183 if (data != null) {
2184 data.flippedContext = flippedContext;
2185 data.state &= ~VISIBLE_REGION;
2186 data.visibleRgn = getVisibleRegion();
2187 display.addContext (data);
2188 }
2189 }
2190 if (data != null) {
2191 int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
2192 if ((data.style & mask) == 0) {
2193 data.style |= style & (mask | SWT.MIRRORED);
2194 }
2195 data.device = display;
2196 data.thread = display.thread;
2197 data.view = view;
2198 data.view.retain();
2199 data.view.window().retain();
2200 data.foreground = getForegroundColor ().handle;
2201 Control control = findBackgroundControl ();
2202 if (control == null) control = this;
2203 data.background = control.getBackgroundColor ().handle;
2204 data.font = font != null ? font : defaultFont ();
2205 }
2206 if (graphicsContext != null) {
2207 return graphicsContext.id;
2208 }
2209 return 0;
2210 }
2211
2212 /**
2213 * Invokes platform specific functionality to dispose a GC handle.
2214 * <p>
2215 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
2216 * API for <code>Control</code>. It is marked public only so that it
2217 * can be shared within the packages provided by SWT. It is not
2218 * available on all platforms, and should never be called from
2219 * application code.
2220 * </p>
2221 *
2222 * @param hDC the platform specific GC handle
2223 * @param data the platform specific GC data
2224 *
2225 * @noreference This method is not intended to be referenced by clients.
2226 */
2227 @Override
internal_dispose_GC(long hDC, GCData data)2228 public void internal_dispose_GC (long hDC, GCData data) {
2229 checkWidget ();
2230 long context = hDC;
2231 NSGraphicsContext graphicsContext = new NSGraphicsContext (context);
2232 display.removeContext (data);
2233 if (data != null) {
2234 if (data.paintRect == null) graphicsContext.flushGraphics ();
2235 if (data.visibleRgn != 0) OS.DisposeRgn(data.visibleRgn);
2236 data.visibleRgn = 0;
2237 if (data.view != null) {
2238 data.view.window().release();
2239 data.view.release();
2240 data.view = null;
2241 }
2242 }
2243 }
2244
invalidateChildrenVisibleRegion()2245 void invalidateChildrenVisibleRegion () {
2246 }
2247
invalidateVisibleRegion()2248 void invalidateVisibleRegion () {
2249 int index = 0;
2250 Control[] siblings = parent._getChildren ();
2251 while (index < siblings.length && siblings [index] != this) index++;
2252 for (int i=index; i<siblings.length; i++) {
2253 Control sibling = siblings [i];
2254 sibling.resetVisibleRegion ();
2255 sibling.invalidateChildrenVisibleRegion ();
2256 }
2257 parent.resetVisibleRegion ();
2258 }
2259
2260 @Override
isActive()2261 boolean isActive () {
2262 if (getShell().getModalShell () != null) return false;
2263 Dialog dialog = display.getModalDialog();
2264 if (dialog == null) return true;
2265 NSPanel panel = display.getModalPanel();
2266 if (panel == null) return false;
2267 NSWindow parentWindow = view.window().parentWindow();
2268 return parentWindow == null || parentWindow.id == panel.id;
2269 }
2270
2271 /*
2272 * Answers a boolean indicating whether a Label that precedes the receiver in
2273 * a layout should be read by screen readers as the recevier's label.
2274 */
isDescribedByLabel()2275 boolean isDescribedByLabel () {
2276 return true;
2277 }
2278
2279 @Override
isDrawing()2280 boolean isDrawing () {
2281 return getDrawing() && parent.isDrawing();
2282 }
2283
2284 /**
2285 * Returns <code>true</code> if the receiver is enabled and all
2286 * ancestors up to and including the receiver's nearest ancestor
2287 * shell are enabled. Otherwise, <code>false</code> is returned.
2288 * A disabled control is typically not selectable from the user
2289 * interface and draws with an inactive or "grayed" look.
2290 *
2291 * @return the receiver's enabled state
2292 *
2293 * @exception SWTException <ul>
2294 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2295 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2296 * </ul>
2297 *
2298 * @see #getEnabled
2299 */
isEnabled()2300 public boolean isEnabled () {
2301 checkWidget();
2302 return getEnabled () && parent.isEnabled ();
2303 }
2304
isEnabledCursor()2305 boolean isEnabledCursor () {
2306 return isEnabled ();
2307 }
2308
isFocusAncestor(Control control)2309 boolean isFocusAncestor (Control control) {
2310 while (control != null && control != this && !(control instanceof Shell)) {
2311 control = control.parent;
2312 }
2313 return control == this;
2314 }
2315
2316 /**
2317 * Returns <code>true</code> if the receiver has the user-interface
2318 * focus, and <code>false</code> otherwise.
2319 *
2320 * @return the receiver's focus state
2321 *
2322 * @exception SWTException <ul>
2323 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2324 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2325 * </ul>
2326 */
isFocusControl()2327 public boolean isFocusControl () {
2328 checkWidget();
2329 Control focusControl = display.focusControl;
2330 if (focusControl != null && !focusControl.isDisposed ()) {
2331 return this == focusControl;
2332 }
2333 return hasFocus ();
2334 }
2335
isObscured()2336 boolean isObscured () {
2337 long visibleRgn = getVisibleRegion(), boundsRgn = OS.NewRgn();
2338 short[] rect = new short[4];
2339 NSRect bounds = view.visibleRect();
2340 OS.SetRect(rect, (short)bounds.x, (short)bounds.y, (short)(bounds.x + bounds.width), (short)(bounds.y + bounds.height));
2341 OS.RectRgn(boundsRgn, rect);
2342 OS.DiffRgn(boundsRgn, visibleRgn, boundsRgn);
2343 boolean obscured = !OS.EmptyRgn (boundsRgn);
2344 OS.DisposeRgn(boundsRgn);
2345 OS.DisposeRgn(visibleRgn);
2346 return obscured;
2347 }
2348
2349 /**
2350 * Returns <code>true</code> if the underlying operating
2351 * system supports this reparenting, otherwise <code>false</code>
2352 *
2353 * @return <code>true</code> if the widget can be reparented, otherwise <code>false</code>
2354 *
2355 * @exception SWTException <ul>
2356 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2357 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2358 * </ul>
2359 */
isReparentable()2360 public boolean isReparentable () {
2361 checkWidget();
2362 return true;
2363 }
2364
isResizing()2365 boolean isResizing () {
2366 return (state & RESIZING) != 0 || parent.isResizing();
2367 }
2368
isShowing()2369 boolean isShowing () {
2370 /*
2371 * This is not complete. Need to check if the
2372 * widget is obscurred by a parent or sibling.
2373 */
2374 if (!isVisible ()) return false;
2375 Control control = this;
2376 while (control != null) {
2377 Point size = control.getSize ();
2378 if (size.x == 0 || size.y == 0) {
2379 return false;
2380 }
2381 control = control.parent;
2382 }
2383 return true;
2384 }
2385
isTabGroup()2386 boolean isTabGroup () {
2387 Control [] tabList = parent._getTabList ();
2388 if (tabList != null) {
2389 for (int i=0; i<tabList.length; i++) {
2390 if (tabList [i] == this) return true;
2391 }
2392 }
2393 int code = traversalCode (0, null);
2394 if ((code & (SWT.TRAVERSE_ARROW_PREVIOUS | SWT.TRAVERSE_ARROW_NEXT)) != 0) return false;
2395 return (code & (SWT.TRAVERSE_TAB_PREVIOUS | SWT.TRAVERSE_TAB_NEXT)) != 0;
2396 }
2397
isTabItem()2398 boolean isTabItem () {
2399 Control [] tabList = parent._getTabList ();
2400 if (tabList != null) {
2401 for (int i=0; i<tabList.length; i++) {
2402 if (tabList [i] == this) return false;
2403 }
2404 }
2405 int code = traversalCode (0, null);
2406 return (code & (SWT.TRAVERSE_ARROW_PREVIOUS | SWT.TRAVERSE_ARROW_NEXT)) != 0;
2407 }
2408
isTransparent()2409 boolean isTransparent() {
2410 if (background != null) return false;
2411 return parent.isTransparent();
2412 }
2413
isTrim(NSView view)2414 boolean isTrim (NSView view) {
2415 return false;
2416 }
2417
2418 /**
2419 * Returns <code>true</code> if the receiver is visible and all
2420 * ancestors up to and including the receiver's nearest ancestor
2421 * shell are visible. Otherwise, <code>false</code> is returned.
2422 *
2423 * @return the receiver's visibility state
2424 *
2425 * @exception SWTException <ul>
2426 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2427 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2428 * </ul>
2429 *
2430 * @see #getVisible
2431 */
isVisible()2432 public boolean isVisible () {
2433 checkWidget();
2434 return getVisible () && parent.isVisible ();
2435 }
2436
2437 @Override
keyDown(long id, long sel, long theEvent)2438 void keyDown (long id, long sel, long theEvent) {
2439 if (hasKeyboardFocus(id)) {
2440 Shell s = this.getShell();
2441 s.keyInputHappened = false;
2442 boolean textInput = OS.objc_msgSend (id, OS.sel_conformsToProtocol_, OS.objc_getProtocol ("NSTextInput")) != 0;
2443 if (!textInput) {
2444 // Not a text field, so send a key event here.
2445 NSEvent nsEvent = new NSEvent (theEvent);
2446 boolean [] consume = new boolean [1];
2447 if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return;
2448 if (isDisposed ()) return;
2449 if (!sendKeyEvent (nsEvent, SWT.KeyDown)) return;
2450 if (consume [0]) return;
2451 } else {
2452 // Control is some kind of text field, so the key event will be sent from insertText: or doCommandBySelector:
2453 super.keyDown (id, sel, theEvent);
2454
2455 if (imeInComposition ()) return;
2456 // If none of those methods triggered a key event send one now.
2457 if (!s.keyInputHappened) {
2458 NSEvent nsEvent = new NSEvent (theEvent);
2459 boolean [] consume = new boolean [1];
2460 if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return;
2461 if (isDisposed ()) return;
2462 if (!sendKeyEvent (nsEvent, SWT.KeyDown)) return;
2463 if (consume [0]) return;
2464 }
2465
2466 return;
2467 }
2468 }
2469 super.keyDown (id, sel, theEvent);
2470 }
2471
hasKeyboardFocus(long inId)2472 boolean hasKeyboardFocus(long inId) {
2473 return view.window().firstResponder().id == inId;
2474 }
2475
2476 @Override
keyUp(long id, long sel, long theEvent)2477 void keyUp (long id, long sel, long theEvent) {
2478 if (hasKeyboardFocus(id)) {
2479 NSEvent nsEvent = new NSEvent (theEvent);
2480 if (!sendKeyEvent (nsEvent, SWT.KeyUp)) return;
2481 }
2482 super.keyUp (id, sel, theEvent);
2483 }
2484
2485 @Override
magnifyWithEvent(long id, long sel, long event)2486 void magnifyWithEvent(long id, long sel, long event) {
2487 if (!gestureEvent(id, event, SWT.GESTURE_MAGNIFY)) return;
2488 super.magnifyWithEvent(id, sel, event);
2489 }
2490
markLayout(boolean changed, boolean all)2491 void markLayout (boolean changed, boolean all) {
2492 /* Do nothing */
2493 }
2494
2495 @Override
menuForEvent(long id, long sel, long theEvent)2496 long menuForEvent (long id, long sel, long theEvent) {
2497 if (display.lastHandledMenuForEventId == theEvent) return 0;
2498 display.lastHandledMenuForEventId = theEvent;
2499 if (!isEnabled ()) return 0;
2500
2501 NSPoint pt = NSEvent.mouseLocation();
2502 pt.y = (int) (display.getPrimaryFrame().height - pt.y);
2503 int x = (int) pt.x;
2504 int y = (int) pt.y;
2505 Event event = new Event ();
2506 event.x = x;
2507 event.y = y;
2508 NSEvent nsEvent = new NSEvent(theEvent);
2509 event.detail = (nsEvent.type() == OS.NSLeftMouseDown || nsEvent.buttonNumber() > 0) ? SWT.MENU_MOUSE : SWT.MENU_KEYBOARD;
2510 sendEvent (SWT.MenuDetect, event);
2511 //widget could be disposed at this point
2512 if (isDisposed ()) return 0;
2513 if (!event.doit) return 0;
2514 Menu menu = getMenu ();
2515 if (menu != null && !menu.isDisposed ()) {
2516 if (x != event.x || y != event.y) {
2517 menu.setLocation (event.x, event.y);
2518 }
2519 menu.setVisible(true);
2520 return 0;
2521 }
2522 return super.menuForEvent (id, sel, theEvent);
2523 }
2524
menuShell()2525 Decorations menuShell () {
2526 return parent.menuShell ();
2527 }
2528
2529 @Override
scrollWheel(long id, long sel, long theEvent)2530 void scrollWheel (long id, long sel, long theEvent) {
2531 boolean handled = false;
2532 if (id == view.id) {
2533 NSEvent nsEvent = new NSEvent(theEvent);
2534 if ((hooks(SWT.Gesture) || filters(SWT.Gesture))) {
2535 if (!gestureEvent(id, theEvent, SWT.GESTURE_PAN)) {
2536 handled = true;
2537 }
2538 }
2539 if (!handled) {
2540 if (hooks (SWT.MouseWheel) || filters (SWT.MouseWheel)) {
2541 if (nsEvent.deltaY() != 0) {
2542 if (!sendMouseEvent(nsEvent, SWT.MouseWheel, true)) {
2543 handled = true;
2544 }
2545 }
2546 }
2547 if (hooks (SWT.MouseHorizontalWheel) || filters (SWT.MouseHorizontalWheel)) {
2548 if (nsEvent.deltaX() != 0) {
2549 if (!sendMouseEvent(nsEvent, SWT.MouseHorizontalWheel, true)) {
2550 handled = true;
2551 }
2552 }
2553 }
2554 }
2555 }
2556 if (!handled) super.scrollWheel(id, sel, theEvent);
2557 }
2558
isEventView(long id)2559 boolean isEventView (long id) {
2560 return true;
2561 }
2562
mouseEvent(long id, long sel, long theEvent, int type)2563 boolean mouseEvent (long id, long sel, long theEvent, int type) {
2564 if (!display.sendEvent) return true;
2565 display.sendEvent = false;
2566 if (!isEventView (id)) return true;
2567 boolean dragging = false;
2568 boolean[] consume = null;
2569 NSEvent nsEvent = new NSEvent(theEvent);
2570 int nsType = (int)nsEvent.type();
2571 NSInputManager manager = NSInputManager.currentInputManager ();
2572 if (manager != null && manager.wantsToHandleMouseEvents ()) {
2573 if (manager.handleMouseEvent (nsEvent)) {
2574 return true;
2575 }
2576 }
2577
2578 boolean runEnterExit = false;
2579 Control runEnterExitControl = null;
2580
2581 switch (nsType) {
2582 case OS.NSLeftMouseDown:
2583 if (nsEvent.clickCount() == 1 && (nsEvent.modifierFlags() & OS.NSControlKeyMask) == 0 && (state & DRAG_DETECT) != 0 && hooks (SWT.DragDetect)) {
2584 consume = new boolean[1];
2585 NSPoint location = view.convertPoint_fromView_(nsEvent.locationInWindow(), null);
2586 if (!view.isFlipped ()) {
2587 location.y = view.bounds().height - location.y;
2588 }
2589 dragging = dragDetect((int)location.x, (int)location.y, false, consume);
2590 }
2591 break;
2592 case OS.NSLeftMouseDragged:
2593 case OS.NSRightMouseDragged:
2594 case OS.NSOtherMouseDragged:
2595 runEnterExit = true;
2596 runEnterExitControl = this;
2597 break;
2598 case OS.NSLeftMouseUp:
2599 case OS.NSRightMouseUp:
2600 case OS.NSOtherMouseUp:
2601 if (display.clickCount == 2) {
2602 sendMouseEvent (nsEvent, SWT.MouseDoubleClick, false);
2603 }
2604 runEnterExit = true;
2605 runEnterExitControl = display.findControl(true);
2606 break;
2607 }
2608 sendMouseEvent (nsEvent, type, false);
2609 if (dragging) sendMouseEvent(nsEvent, SWT.DragDetect, false);
2610 if (runEnterExit) display.checkEnterExit (runEnterExitControl, nsEvent, false);
2611 if (consume != null && consume[0]) return false;
2612 return true;
2613 }
2614
2615 @Override
mouseDown(long id, long sel, long theEvent)2616 void mouseDown(long id, long sel, long theEvent) {
2617 if (!mouseEvent(id, sel, theEvent, SWT.MouseDown)) return;
2618 boolean tracking = isEventView (id);
2619 Display display = this.display;
2620 if (tracking) display.trackingControl = this;
2621 super.mouseDown(id, sel, theEvent);
2622 if (tracking) display.trackingControl = null;
2623 }
2624
2625 @Override
mouseUp(long id, long sel, long theEvent)2626 void mouseUp(long id, long sel, long theEvent) {
2627 if (!mouseEvent(id, sel, theEvent, SWT.MouseUp)) return;
2628 super.mouseUp(id, sel, theEvent);
2629 }
2630
2631 @Override
mouseDragged(long id, long sel, long theEvent)2632 void mouseDragged(long id, long sel, long theEvent) {
2633 if (!mouseEvent(id, sel, theEvent, SWT.MouseMove)) return;
2634 super.mouseDragged(id, sel, theEvent);
2635 }
2636
2637 @Override
rightMouseDown(long id, long sel, long theEvent)2638 void rightMouseDown(long id, long sel, long theEvent) {
2639 if (!mouseEvent(id, sel, theEvent, SWT.MouseDown)) return;
2640 super.rightMouseDown(id, sel, theEvent);
2641 }
2642
2643 @Override
rightMouseUp(long id, long sel, long theEvent)2644 void rightMouseUp(long id, long sel, long theEvent) {
2645 if (!mouseEvent(id, sel, theEvent, SWT.MouseUp)) return;
2646 super.rightMouseUp(id, sel, theEvent);
2647 }
2648
2649 @Override
rightMouseDragged(long id, long sel, long theEvent)2650 void rightMouseDragged(long id, long sel, long theEvent) {
2651 if (!mouseEvent(id, sel, theEvent, SWT.MouseMove)) return;
2652 super.rightMouseDragged(id, sel, theEvent);
2653 }
2654
2655 @Override
otherMouseDown(long id, long sel, long theEvent)2656 void otherMouseDown(long id, long sel, long theEvent) {
2657 if (!mouseEvent(id, sel, theEvent, SWT.MouseDown)) return;
2658 super.otherMouseDown(id, sel, theEvent);
2659 }
2660
2661 @Override
otherMouseUp(long id, long sel, long theEvent)2662 void otherMouseUp(long id, long sel, long theEvent) {
2663 if (!mouseEvent(id, sel, theEvent, SWT.MouseUp)) return;
2664 super.otherMouseUp(id, sel, theEvent);
2665 }
2666
2667 @Override
otherMouseDragged(long id, long sel, long theEvent)2668 void otherMouseDragged(long id, long sel, long theEvent) {
2669 if (!mouseEvent(id, sel, theEvent, SWT.MouseMove)) return;
2670 super.otherMouseDragged(id, sel, theEvent);
2671 }
2672
moved()2673 void moved () {
2674 sendEvent (SWT.Move);
2675 }
2676
2677 /**
2678 * Moves the receiver above the specified control in the
2679 * drawing order. If the argument is null, then the receiver
2680 * is moved to the top of the drawing order. The control at
2681 * the top of the drawing order will not be covered by other
2682 * controls even if they occupy intersecting areas.
2683 *
2684 * @param control the sibling control (or null)
2685 *
2686 * @exception IllegalArgumentException <ul>
2687 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
2688 * </ul>
2689 * @exception SWTException <ul>
2690 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2691 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2692 * </ul>
2693 *
2694 * @see Control#moveBelow
2695 * @see Composite#getChildren
2696 */
moveAbove(Control control)2697 public void moveAbove (Control control) {
2698 checkWidget();
2699 if (control != null) {
2700 if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
2701 if (parent != control.parent) return;
2702 }
2703 setZOrder (control, true);
2704 }
2705
2706 /**
2707 * Moves the receiver below the specified control in the
2708 * drawing order. If the argument is null, then the receiver
2709 * is moved to the bottom of the drawing order. The control at
2710 * the bottom of the drawing order will be covered by all other
2711 * controls which occupy intersecting areas.
2712 *
2713 * @param control the sibling control (or null)
2714 *
2715 * @exception IllegalArgumentException <ul>
2716 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
2717 * </ul>
2718 * @exception SWTException <ul>
2719 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2720 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2721 * </ul>
2722 *
2723 * @see Control#moveAbove
2724 * @see Composite#getChildren
2725 */
moveBelow(Control control)2726 public void moveBelow (Control control) {
2727 checkWidget();
2728 if (control != null) {
2729 if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
2730 if (parent != control.parent) return;
2731 }
2732 setZOrder (control, false);
2733 }
2734
new_Accessible(Control control)2735 Accessible new_Accessible (Control control) {
2736 return Accessible.internal_new_Accessible (this);
2737 }
2738
2739 /**
2740 * Causes the receiver to be resized to its preferred size.
2741 * For a composite, this involves computing the preferred size
2742 * from its layout, if there is one.
2743 *
2744 * @exception SWTException <ul>
2745 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2746 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2747 * </ul>
2748 *
2749 * @see #computeSize(int, int, boolean)
2750 */
pack()2751 public void pack () {
2752 checkWidget();
2753 pack (true);
2754 }
2755
2756 /**
2757 * Causes the receiver to be resized to its preferred size.
2758 * For a composite, this involves computing the preferred size
2759 * from its layout, if there is one.
2760 * <p>
2761 * If the changed flag is <code>true</code>, it indicates that the receiver's
2762 * <em>contents</em> have changed, therefore any caches that a layout manager
2763 * containing the control may have been keeping need to be flushed. When the
2764 * control is resized, the changed flag will be <code>false</code>, so layout
2765 * manager caches can be retained.
2766 * </p>
2767 *
2768 * @param changed whether or not the receiver's contents have changed
2769 *
2770 * @exception SWTException <ul>
2771 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2772 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2773 * </ul>
2774 *
2775 * @see #computeSize(int, int, boolean)
2776 */
pack(boolean changed)2777 public void pack (boolean changed) {
2778 checkWidget();
2779 setSize (computeSize (SWT.DEFAULT, SWT.DEFAULT, changed));
2780 }
2781
paintView()2782 NSView paintView () {
2783 return eventView ();
2784 }
2785
2786 /**
2787 * Prints the receiver and all children.
2788 *
2789 * @param gc the gc where the drawing occurs
2790 * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
2791 *
2792 * @exception IllegalArgumentException <ul>
2793 * <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
2794 * <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li>
2795 * </ul>
2796 * @exception SWTException <ul>
2797 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2798 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2799 * </ul>
2800 *
2801 * @since 3.4
2802 */
print(GC gc)2803 public boolean print (GC gc) {
2804 checkWidget ();
2805 if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
2806 if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
2807
2808 if (OS.VERSION < OS.VERSION(10, 13, 0)) {
2809 NSGraphicsContext.static_saveGraphicsState();
2810 NSGraphicsContext.setCurrentContext(gc.handle);
2811 NSAffineTransform transform = NSAffineTransform.transform ();
2812 transform.translateXBy (0, view.bounds().height);
2813 transform.scaleXBy (1, -1);
2814 transform.concat ();
2815 view.displayRectIgnoringOpacity(view.bounds(), gc.handle);
2816 NSGraphicsContext.static_restoreGraphicsState();
2817 } else {
2818 view.displayRectIgnoringOpacity (view.bounds (), gc.handle);
2819 }
2820 return true;
2821 }
2822
2823 /**
2824 * Requests that this control and all of its ancestors be repositioned by
2825 * their layouts at the earliest opportunity. This should be invoked after
2826 * modifying the control in order to inform any dependent layouts of
2827 * the change.
2828 * <p>
2829 * The control will not be repositioned synchronously. This method is
2830 * fast-running and only marks the control for future participation in
2831 * a deferred layout.
2832 * <p>
2833 * Invoking this method multiple times before the layout occurs is an
2834 * inexpensive no-op.
2835 *
2836 * @since 3.105
2837 */
requestLayout()2838 public void requestLayout () {
2839 getShell ().layout (new Control[] {this}, SWT.DEFER);
2840 }
2841
2842 /**
2843 * Causes the entire bounds of the receiver to be marked
2844 * as needing to be redrawn. The next time a paint request
2845 * is processed, the control will be completely painted,
2846 * including the background.
2847 * <p>
2848 * Schedules a paint request if the invalidated area is visible
2849 * or becomes visible later. It is not necessary for the caller
2850 * to explicitly call {@link #update()} after calling this method,
2851 * but depending on the platform, the automatic repaints may be
2852 * delayed considerably.
2853 * </p>
2854 *
2855 * @exception SWTException <ul>
2856 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2857 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2858 * </ul>
2859 *
2860 * @see #update()
2861 * @see PaintListener
2862 * @see SWT#Paint
2863 * @see SWT#NO_BACKGROUND
2864 * @see SWT#NO_REDRAW_RESIZE
2865 * @see SWT#NO_MERGE_PAINTS
2866 * @see SWT#DOUBLE_BUFFERED
2867 */
redraw()2868 public void redraw () {
2869 checkWidget();
2870 view.setNeedsDisplay(true);
2871 }
2872
redraw(boolean children)2873 void redraw (boolean children) {
2874 // checkWidget();
2875 view.setNeedsDisplay(true);
2876 }
2877
2878 /**
2879 * Causes the rectangular area of the receiver specified by
2880 * the arguments to be marked as needing to be redrawn.
2881 * The next time a paint request is processed, that area of
2882 * the receiver will be painted, including the background.
2883 * If the <code>all</code> flag is <code>true</code>, any
2884 * children of the receiver which intersect with the specified
2885 * area will also paint their intersecting areas. If the
2886 * <code>all</code> flag is <code>false</code>, the children
2887 * will not be painted.
2888 * <p>
2889 * Schedules a paint request if the invalidated area is visible
2890 * or becomes visible later. It is not necessary for the caller
2891 * to explicitly call {@link #update()} after calling this method,
2892 * but depending on the platform, the automatic repaints may be
2893 * delayed considerably.
2894 * </p>
2895 *
2896 * @param x the x coordinate of the area to draw
2897 * @param y the y coordinate of the area to draw
2898 * @param width the width of the area to draw
2899 * @param height the height of the area to draw
2900 * @param all <code>true</code> if children should redraw, and <code>false</code> otherwise
2901 *
2902 * @exception SWTException <ul>
2903 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2904 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2905 * </ul>
2906 *
2907 * @see #update()
2908 * @see PaintListener
2909 * @see SWT#Paint
2910 * @see SWT#NO_BACKGROUND
2911 * @see SWT#NO_REDRAW_RESIZE
2912 * @see SWT#NO_MERGE_PAINTS
2913 * @see SWT#DOUBLE_BUFFERED
2914 */
redraw(int x, int y, int width, int height, boolean all)2915 public void redraw (int x, int y, int width, int height, boolean all) {
2916 checkWidget ();
2917 NSRect rect = new NSRect();
2918 rect.x = x;
2919 rect.y = y;
2920 rect.width = width;
2921 rect.height = height;
2922 view.setNeedsDisplayInRect(rect);
2923 }
2924
regionToRects(long message, long rgn, long r, long path)2925 long regionToRects(long message, long rgn, long r, long path) {
2926 NSPoint pt = new NSPoint();
2927 short[] rect = new short[4];
2928 if (message == OS.kQDRegionToRectsMsgParse) {
2929 C.memmove(rect, r, rect.length * 2);
2930 pt.x = rect[1];
2931 pt.y = rect[0];
2932 OS.objc_msgSend(path, OS.sel_moveToPoint_, pt);
2933 pt.x = rect[3];
2934 OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
2935 pt.x = rect[3];
2936 pt.y = rect[2];
2937 OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
2938 pt.x = rect[1];
2939 OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
2940 OS.objc_msgSend(path, OS.sel_closePath);
2941 }
2942 return 0;
2943 }
2944
2945 @Override
register()2946 void register () {
2947 super.register ();
2948 display.addWidget (view, this);
2949 }
2950
2951 @Override
release(boolean destroy)2952 void release (boolean destroy) {
2953 Control next = null, previous = null;
2954 if (destroy && parent != null) {
2955 Control[] children = parent._getChildren ();
2956 int index = 0;
2957 while (index < children.length) {
2958 if (children [index] == this) break;
2959 index++;
2960 }
2961 if (0 < index && (index + 1) < children.length) {
2962 next = children [index + 1];
2963 previous = children [index - 1];
2964 }
2965 }
2966 super.release (destroy);
2967 if (destroy) {
2968 if (previous != null) previous.addRelation (next);
2969 }
2970 }
2971
2972 @Override
releaseHandle()2973 void releaseHandle () {
2974 super.releaseHandle ();
2975 if (view != null) view.release();
2976 view = null;
2977 parent = null;
2978 }
2979
2980 @Override
releaseParent()2981 void releaseParent () {
2982 invalidateVisibleRegion ();
2983 parent.removeControl (this);
2984 }
2985
2986 @Override
releaseWidget()2987 void releaseWidget () {
2988 super.releaseWidget ();
2989 if (display.currentControl == this) {
2990 display.currentControl = null;
2991 display.timerExec(-1, display.hoverTimer);
2992 }
2993 if (display.trackingControl == this) display.trackingControl = null;
2994 if (display.tooltipControl == this) display.tooltipControl = null;
2995 if (menu != null && !menu.isDisposed ()) {
2996 menu.dispose ();
2997 }
2998 menu = null;
2999 if (visibleRgn != 0) OS.DisposeRgn (visibleRgn);
3000 visibleRgn = 0;
3001 layoutData = null;
3002 if (accessible != null) {
3003 accessible.internal_dispose_Accessible ();
3004 }
3005 accessible = null;
3006 region = null;
3007 if (regionPath != null) regionPath.release();
3008 regionPath = null;
3009 }
3010
3011 /**
3012 * Removes the listener from the collection of listeners who will
3013 * be notified when the control is moved or resized.
3014 *
3015 * @param listener the listener which should no longer be notified
3016 *
3017 * @exception IllegalArgumentException <ul>
3018 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3019 * </ul>
3020 * @exception SWTException <ul>
3021 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3022 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3023 * </ul>
3024 *
3025 * @see ControlListener
3026 * @see #addControlListener
3027 */
removeControlListener(ControlListener listener)3028 public void removeControlListener (ControlListener listener) {
3029 checkWidget();
3030 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3031 if (eventTable == null) return;
3032 eventTable.unhook (SWT.Move, listener);
3033 eventTable.unhook (SWT.Resize, listener);
3034 }
3035
3036 /**
3037 * Removes the listener from the collection of listeners who will
3038 * be notified when a drag gesture occurs.
3039 *
3040 * @param listener the listener which should no longer be notified
3041 *
3042 * @exception IllegalArgumentException <ul>
3043 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3044 * </ul>
3045 * @exception SWTException <ul>
3046 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3047 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3048 * </ul>
3049 *
3050 * @see DragDetectListener
3051 * @see #addDragDetectListener
3052 *
3053 * @since 3.3
3054 */
removeDragDetectListener(DragDetectListener listener)3055 public void removeDragDetectListener(DragDetectListener listener) {
3056 checkWidget ();
3057 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3058 if (eventTable == null) return;
3059 eventTable.unhook (SWT.DragDetect, listener);
3060 }
3061
3062 /**
3063 * Removes the listener from the collection of listeners who will
3064 * be notified when the control gains or loses focus.
3065 *
3066 * @param listener the listener which should no longer be notified
3067 *
3068 * @exception IllegalArgumentException <ul>
3069 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3070 * </ul>
3071 * @exception SWTException <ul>
3072 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3073 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3074 * </ul>
3075 *
3076 * @see FocusListener
3077 * @see #addFocusListener
3078 */
removeFocusListener(FocusListener listener)3079 public void removeFocusListener(FocusListener listener) {
3080 checkWidget();
3081 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3082 if (eventTable == null) return;
3083 eventTable.unhook(SWT.FocusIn, listener);
3084 eventTable.unhook(SWT.FocusOut, listener);
3085 }
3086
3087 /**
3088 * Removes the listener from the collection of listeners who will
3089 * be notified when gesture events are generated for the control.
3090 *
3091 * @param listener the listener which should no longer be notified
3092 *
3093 * @exception IllegalArgumentException <ul>
3094 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3095 * </ul>
3096 * @exception SWTException <ul>
3097 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3098 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3099 * </ul>
3100 *
3101 * @see GestureListener
3102 * @see #addGestureListener
3103 *
3104 * @since 3.7
3105 */
removeGestureListener(GestureListener listener)3106 public void removeGestureListener (GestureListener listener) {
3107 checkWidget();
3108 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3109 if (eventTable == null) return;
3110 eventTable.unhook(SWT.Gesture, listener);
3111 }
3112
3113 /**
3114 * Removes the listener from the collection of listeners who will
3115 * be notified when the help events are generated for the control.
3116 *
3117 * @param listener the listener which should no longer be notified
3118 *
3119 * @exception IllegalArgumentException <ul>
3120 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3121 * </ul>
3122 * @exception SWTException <ul>
3123 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3124 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3125 * </ul>
3126 *
3127 * @see HelpListener
3128 * @see #addHelpListener
3129 */
removeHelpListener(HelpListener listener)3130 public void removeHelpListener (HelpListener listener) {
3131 checkWidget();
3132 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3133 if (eventTable == null) return;
3134 eventTable.unhook (SWT.Help, listener);
3135 }
3136
3137 /**
3138 * Removes the listener from the collection of listeners who will
3139 * be notified when keys are pressed and released on the system keyboard.
3140 *
3141 * @param listener the listener which should no longer be notified
3142 *
3143 * @exception IllegalArgumentException <ul>
3144 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3145 * </ul>
3146 * @exception SWTException <ul>
3147 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3148 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3149 * </ul>
3150 *
3151 * @see KeyListener
3152 * @see #addKeyListener
3153 */
removeKeyListener(KeyListener listener)3154 public void removeKeyListener(KeyListener listener) {
3155 checkWidget();
3156 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3157 if (eventTable == null) return;
3158 eventTable.unhook(SWT.KeyUp, listener);
3159 eventTable.unhook(SWT.KeyDown, listener);
3160 }
3161
3162 /**
3163 * Removes the listener from the collection of listeners who will
3164 * be notified when the platform-specific context menu trigger has
3165 * occurred.
3166 *
3167 * @param listener the listener which should no longer be notified
3168 *
3169 * @exception IllegalArgumentException <ul>
3170 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3171 * </ul>
3172 * @exception SWTException <ul>
3173 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3174 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3175 * </ul>
3176 *
3177 * @see MenuDetectListener
3178 * @see #addMenuDetectListener
3179 *
3180 * @since 3.3
3181 */
removeMenuDetectListener(MenuDetectListener listener)3182 public void removeMenuDetectListener (MenuDetectListener listener) {
3183 checkWidget ();
3184 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3185 if (eventTable == null) return;
3186 eventTable.unhook (SWT.MenuDetect, listener);
3187 }
3188
3189 /**
3190 * Removes the listener from the collection of listeners who will
3191 * be notified when mouse buttons are pressed and released.
3192 *
3193 * @param listener the listener which should no longer be notified
3194 *
3195 * @exception IllegalArgumentException <ul>
3196 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3197 * </ul>
3198 * @exception SWTException <ul>
3199 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3200 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3201 * </ul>
3202 *
3203 * @see MouseListener
3204 * @see #addMouseListener
3205 */
removeMouseListener(MouseListener listener)3206 public void removeMouseListener(MouseListener listener) {
3207 checkWidget();
3208 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3209 if (eventTable == null) return;
3210 eventTable.unhook(SWT.MouseDown, listener);
3211 eventTable.unhook(SWT.MouseUp, listener);
3212 eventTable.unhook(SWT.MouseDoubleClick, listener);
3213 }
3214
3215 /**
3216 * Removes the listener from the collection of listeners who will
3217 * be notified when the mouse moves.
3218 *
3219 * @param listener the listener which should no longer be notified
3220 *
3221 * @exception IllegalArgumentException <ul>
3222 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3223 * </ul>
3224 * @exception SWTException <ul>
3225 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3226 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3227 * </ul>
3228 *
3229 * @see MouseMoveListener
3230 * @see #addMouseMoveListener
3231 */
removeMouseMoveListener(MouseMoveListener listener)3232 public void removeMouseMoveListener(MouseMoveListener listener) {
3233 checkWidget();
3234 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3235 if (eventTable == null) return;
3236 eventTable.unhook(SWT.MouseMove, listener);
3237 }
3238
3239 /**
3240 * Removes the listener from the collection of listeners who will
3241 * be notified when the mouse passes or hovers over controls.
3242 *
3243 * @param listener the listener which should no longer be notified
3244 *
3245 * @exception IllegalArgumentException <ul>
3246 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3247 * </ul>
3248 * @exception SWTException <ul>
3249 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3250 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3251 * </ul>
3252 *
3253 * @see MouseTrackListener
3254 * @see #addMouseTrackListener
3255 */
removeMouseTrackListener(MouseTrackListener listener)3256 public void removeMouseTrackListener(MouseTrackListener listener) {
3257 checkWidget();
3258 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3259 if (eventTable == null) return;
3260 eventTable.unhook (SWT.MouseEnter, listener);
3261 eventTable.unhook (SWT.MouseExit, listener);
3262 eventTable.unhook (SWT.MouseHover, listener);
3263 }
3264
3265 /**
3266 * Removes the listener from the collection of listeners who will
3267 * be notified when the mouse wheel is scrolled.
3268 *
3269 * @param listener the listener which should no longer be notified
3270 *
3271 * @exception IllegalArgumentException <ul>
3272 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3273 * </ul>
3274 * @exception SWTException <ul>
3275 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3276 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3277 * </ul>
3278 *
3279 * @see MouseWheelListener
3280 * @see #addMouseWheelListener
3281 *
3282 * @since 3.3
3283 */
removeMouseWheelListener(MouseWheelListener listener)3284 public void removeMouseWheelListener (MouseWheelListener listener) {
3285 checkWidget ();
3286 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3287 if (eventTable == null) return;
3288 eventTable.unhook (SWT.MouseWheel, listener);
3289 }
3290
3291 /**
3292 * Removes the listener from the collection of listeners who will
3293 * be notified when the receiver needs to be painted.
3294 *
3295 * @param listener the listener which should no longer be notified
3296 *
3297 * @exception IllegalArgumentException <ul>
3298 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3299 * </ul>
3300 * @exception SWTException <ul>
3301 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3302 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3303 * </ul>
3304 *
3305 * @see PaintListener
3306 * @see #addPaintListener
3307 */
removePaintListener(PaintListener listener)3308 public void removePaintListener(PaintListener listener) {
3309 checkWidget();
3310 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3311 if (eventTable == null) return;
3312 eventTable.unhook(SWT.Paint, listener);
3313 }
3314
3315 /*
3316 * Remove "Labeled by" relations from the receiver.
3317 */
removeRelation()3318 void removeRelation () {
3319 if (!isDescribedByLabel()) return;
3320 NSObject accessibleElement = focusView();
3321
3322 if (accessibleElement instanceof NSControl) {
3323 NSControl viewAsControl = (NSControl) accessibleElement;
3324 if (viewAsControl.cell() != null) accessibleElement = viewAsControl.cell();
3325 }
3326
3327 accessibleElement.accessibilitySetOverrideValue(accessibleElement, OS.NSAccessibilityTitleUIElementAttribute);
3328 }
3329
3330
3331 /**
3332 * Removes the listener from the collection of listeners who will
3333 * be notified when touch events occur.
3334 *
3335 * @param listener the listener which should no longer be notified
3336 *
3337 * @exception IllegalArgumentException <ul>
3338 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3339 * </ul>
3340 * @exception SWTException <ul>
3341 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3342 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3343 * </ul>
3344 *
3345 * @see TouchListener
3346 * @see #addTouchListener
3347 *
3348 * @since 3.7
3349 */
removeTouchListener(TouchListener listener)3350 public void removeTouchListener(TouchListener listener) {
3351 checkWidget();
3352 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3353 if (eventTable == null) return;
3354 eventTable.unhook (SWT.Touch, listener);
3355 }
3356
3357 /**
3358 * Removes the listener from the collection of listeners who will
3359 * be notified when traversal events occur.
3360 *
3361 * @param listener the listener which should no longer be notified
3362 *
3363 * @exception IllegalArgumentException <ul>
3364 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3365 * </ul>
3366 * @exception SWTException <ul>
3367 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3368 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3369 * </ul>
3370 *
3371 * @see TraverseListener
3372 * @see #addTraverseListener
3373 */
removeTraverseListener(TraverseListener listener)3374 public void removeTraverseListener(TraverseListener listener) {
3375 checkWidget();
3376 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
3377 if (eventTable == null) return;
3378 eventTable.unhook (SWT.Traverse, listener);
3379 }
3380
resetVisibleRegion()3381 void resetVisibleRegion () {
3382 if (visibleRgn != 0) {
3383 OS.DisposeRgn (visibleRgn);
3384 visibleRgn = 0;
3385 }
3386 GCData[] gcs = display.contexts;
3387 if (gcs != null) {
3388 long visibleRgn = 0;
3389 for (int i=0; i<gcs.length; i++) {
3390 GCData data = gcs [i];
3391 if (data != null) {
3392 if (data.view == view) {
3393 if (visibleRgn == 0) visibleRgn = getVisibleRegion ();
3394 data.state &= ~VISIBLE_REGION;
3395 OS.CopyRgn (visibleRgn, data.visibleRgn);
3396 }
3397 }
3398 }
3399 if (visibleRgn != 0) OS.DisposeRgn (visibleRgn);
3400 }
3401 }
3402
resized()3403 void resized () {
3404 sendEvent (SWT.Resize);
3405 }
3406
3407 @Override
rotateWithEvent(long id, long sel, long event)3408 void rotateWithEvent(long id, long sel, long event) {
3409 if (!gestureEvent(id, event, SWT.GESTURE_ROTATE)) return;
3410 super.rotateWithEvent(id, sel, event);
3411 }
3412
sendDragEvent(int button, int stateMask, int x, int y)3413 boolean sendDragEvent (int button, int stateMask, int x, int y) {
3414 Event event = new Event ();
3415 event.button = button;
3416 event.x = x;
3417 event.y = y;
3418 event.stateMask = stateMask;
3419 postEvent (SWT.DragDetect, event);
3420 return event.doit;
3421 }
3422
sendFocusEvent(int type)3423 void sendFocusEvent (int type) {
3424 Display display = this.display;
3425 Shell shell = getShell ();
3426
3427 display.focusEvent = type;
3428 display.focusControl = this;
3429 sendEvent (type);
3430 // widget could be disposed at this point
3431 display.focusEvent = SWT.None;
3432 display.focusControl = null;
3433
3434 /*
3435 * It is possible that the shell may be
3436 * disposed at this point. If this happens
3437 * don't send the activate and deactivate
3438 * events.
3439 */
3440 if (!shell.isDisposed ()) {
3441 switch (type) {
3442 case SWT.FocusIn:
3443 shell.setActiveControl (this);
3444 break;
3445 case SWT.FocusOut:
3446 if (shell != display.getActiveShell ()) {
3447 shell.setActiveControl (null);
3448 }
3449 break;
3450 }
3451 }
3452 }
3453
sendMouseEvent(NSEvent nsEvent, int type, boolean send)3454 boolean sendMouseEvent (NSEvent nsEvent, int type, boolean send) {
3455 Shell shell = null;
3456 Event event = new Event ();
3457 switch (type) {
3458 case SWT.MouseDown:
3459 shell = getShell ();
3460 //FALL THROUGH
3461 case SWT.MouseUp:
3462 case SWT.MouseDoubleClick:
3463 case SWT.DragDetect:
3464 int button = (int)nsEvent.buttonNumber();
3465 switch (button) {
3466 case 0: event.button = 1; break;
3467 case 1: event.button = 3; break;
3468 case 2: event.button = 2; break;
3469 case 3: event.button = 4; break;
3470 case 4: event.button = 5; break;
3471 }
3472 break;
3473 case SWT.MouseWheel: {
3474 event.detail = SWT.SCROLL_LINE;
3475 double delta = nsEvent.deltaY();
3476 event.count = delta > 0 ? Math.max (1, (int)delta) : Math.min (-1, (int)delta);
3477 break;
3478 }
3479 case SWT.MouseHorizontalWheel: {
3480 double delta = nsEvent.deltaX();
3481 event.count = delta > 0 ? Math.max (1, (int)delta) : Math.min (-1, (int)delta);
3482 break;
3483 }
3484 }
3485 if (event.button != 0) event.count = display.clickCount;
3486 NSPoint windowPoint;
3487 NSView view = eventView ();
3488 if (nsEvent == null || nsEvent.type() == OS.NSMouseMoved) {
3489 NSWindow window = view.window();
3490 windowPoint = window.convertScreenToBase(NSEvent.mouseLocation());
3491 } else {
3492 windowPoint = nsEvent.locationInWindow();
3493 }
3494 NSPoint point = view.convertPoint_fromView_(windowPoint, null);
3495 if (!view.isFlipped ()) {
3496 point.y = view.bounds().height - point.y;
3497 }
3498 event.x = (int) point.x;
3499 event.y = (int) point.y;
3500 setInputState (event, nsEvent, type);
3501 if (send) {
3502 sendEvent (type, event);
3503 if (isDisposed ()) return false;
3504 } else {
3505 postEvent (type, event);
3506 }
3507 if (shell != null) shell.setActiveControl(this, SWT.MouseDown);
3508 return event.doit;
3509 }
3510
touchStateFromNSTouch(NSTouch touch)3511 Touch touchStateFromNSTouch(NSTouch touch) {
3512 TouchSource source = display.findTouchSource(touch);
3513 long osPhase = touch.phase();
3514 long identity = OS.objc_msgSend(touch.id, OS.sel_identity);
3515 int state = 0;
3516
3517 switch ((int)osPhase) {
3518 case OS.NSTouchPhaseBegan:
3519 state = SWT.TOUCHSTATE_DOWN;
3520 break;
3521 case OS.NSTouchPhaseMoved:
3522 state = SWT.TOUCHSTATE_MOVE;
3523 break;
3524 case OS.NSTouchPhaseEnded:
3525 case OS.NSTouchPhaseCancelled:
3526 state = SWT.TOUCHSTATE_UP;
3527 break;
3528 }
3529
3530 display.touchCounter++;
3531 boolean primary = false;
3532 NSPoint normalizedPos = touch.normalizedPosition();
3533 double normalizedX = normalizedPos.x;
3534 double normalizedY = 1 - normalizedPos.y;
3535 if (display.currentTouches().count() == 1) display.primaryIdentifier = identity;
3536 if (display.primaryIdentifier == identity) primary = true;
3537 NSSize deviceSize = touch.deviceSize();
3538 int deviceX = (int) (normalizedX * deviceSize.width);
3539 int deviceY = (int) (normalizedY * deviceSize.height);
3540 Touch newTS = new Touch(identity, source, state, primary, deviceX, deviceY);
3541 return newTS;
3542 }
3543
findTouchWithId(NSArray touches, NSObject identity)3544 NSTouch findTouchWithId(NSArray touches, NSObject identity) {
3545 long count = touches.count();
3546 for (long i = 0; i < count; i++) {
3547 NSTouch aTouch = new NSTouch(touches.objectAtIndex(i).id);
3548 NSObject currIdentity = new NSObject(OS.objc_msgSend(aTouch.id, OS.sel_identity));
3549 if (currIdentity.isEqual(identity)) return aTouch;
3550 }
3551 return null;
3552 }
3553
setBackground()3554 void setBackground () {
3555 if (!drawsBackground()) return;
3556 Control control = findBackgroundControl ();
3557 if (control == null) control = this;
3558 if (control.backgroundImage != null) {
3559 setBackgroundImage (control.backgroundImage.handle);
3560 } else {
3561 double [] color = control.background != null ? control.background : control.defaultBackground().handle;
3562 NSColor nsColor = NSColor.colorWithDeviceRed(color[0], color[1], color[2], color[3]);
3563 setBackgroundColor (nsColor);
3564 }
3565 }
3566
3567 /**
3568 * Sets the receiver's background color to the color specified
3569 * by the argument, or to the default system color for the control
3570 * if the argument is null.
3571 * <p>
3572 * Note: This operation is a hint and may be overridden by the platform.
3573 * </p>
3574 * @param color the new color (or null)
3575 *
3576 * @exception IllegalArgumentException <ul>
3577 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
3578 * </ul>
3579 * @exception SWTException <ul>
3580 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3581 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3582 * </ul>
3583 */
setBackground(Color color)3584 public void setBackground (Color color) {
3585 checkWidget ();
3586 _setBackground (color);
3587 if (color != null) {
3588 this.updateBackgroundMode ();
3589 }
3590 }
3591
_setBackground(Color color)3592 private void _setBackground (Color color) {
3593 if (color != null) {
3594 if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
3595 }
3596 double [] background = color != null ? color.handle : null;
3597 int alpha = color != null ? color.getAlpha() : 255;
3598 if (equals (background, this.background) && alpha == this.backgroundAlpha) return;
3599 this.background = background;
3600 this.backgroundAlpha = alpha;
3601 updateBackgroundColor ();
3602 redrawWidget(view, true);
3603 }
3604
3605 /**
3606 * Sets the receiver's background image to the image specified
3607 * by the argument, or to the default system color for the control
3608 * if the argument is null. The background image is tiled to fill
3609 * the available space.
3610 * <p>
3611 * Note: This operation is a hint and may be overridden by the platform.
3612 * For example, on Windows the background of a Button cannot be changed.
3613 * </p>
3614 * @param image the new image (or null)
3615 *
3616 * @exception IllegalArgumentException <ul>
3617 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
3618 * <li>ERROR_INVALID_ARGUMENT - if the argument is not a bitmap</li>
3619 * </ul>
3620 * @exception SWTException <ul>
3621 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3622 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3623 * </ul>
3624 *
3625 * @since 3.2
3626 */
setBackgroundImage(Image image)3627 public void setBackgroundImage (Image image) {
3628 checkWidget();
3629 if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
3630 if (image == backgroundImage && backgroundAlpha > 0) return;
3631 backgroundAlpha = 255;
3632 backgroundImage = image;
3633 updateBackgroundImage();
3634 }
3635
setBackgroundImage(NSImage image)3636 void setBackgroundImage (NSImage image) {
3637 redrawWidget(view, true);
3638 }
3639
setBackgroundColor(NSColor nsColor)3640 void setBackgroundColor (NSColor nsColor) {
3641 }
3642
3643 /**
3644 * Sets the receiver's size and location in points to the rectangular
3645 * area specified by the arguments. The <code>x</code> and
3646 * <code>y</code> arguments are relative to the receiver's
3647 * parent (or its display if its parent is null), unless
3648 * the receiver is a shell. In this case, the <code>x</code>
3649 * and <code>y</code> arguments are relative to the display.
3650 * <p>
3651 * Note: Attempting to set the width or height of the
3652 * receiver to a negative number will cause that
3653 * value to be set to zero instead.
3654 * </p>
3655 * <p>
3656 * Note: On GTK, attempting to set the width or height of the
3657 * receiver to a number higher or equal 2^14 will cause them to be
3658 * set to (2^14)-1 instead.
3659 * </p>
3660 *
3661 * @param x the new x coordinate for the receiver
3662 * @param y the new y coordinate for the receiver
3663 * @param width the new width for the receiver
3664 * @param height the new height for the receiver
3665 *
3666 * @exception SWTException <ul>
3667 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3668 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3669 * </ul>
3670 */
setBounds(int x, int y, int width, int height)3671 public void setBounds (int x, int y, int width, int height) {
3672 checkWidget();
3673 setBounds (x, y, Math.max (0, width), Math.max (0, height), true, true);
3674 }
3675
setBounds(int x, int y, int width, int height, boolean move, boolean resize)3676 void setBounds (int x, int y, int width, int height, boolean move, boolean resize) {
3677 /*
3678 * Bug in Cocoa. On Mac 10.8, a text control loses and gains focus
3679 * when its bounds changes. The fix is to ignore these events.
3680 */
3681 Display display = this.display;
3682 Control oldIgnoreFocusControl = display.ignoreFocusControl;
3683 display.ignoreFocusControl = this;
3684 NSView topView = topView();
3685 if (move && resize) {
3686 NSRect rect = new NSRect();
3687 rect.x = x;
3688 rect.y = y;
3689 rect.width = width;
3690 rect.height = height;
3691 topView.setFrame (rect);
3692 } else if (move) {
3693 NSPoint point = new NSPoint();
3694 point.x = x;
3695 point.y = y;
3696 topView.setFrameOrigin(point);
3697 } else if (resize) {
3698 NSSize size = new NSSize();
3699 size.width = width;
3700 size.height = height;
3701 topView.setFrameSize(size);
3702 }
3703 display.ignoreFocusControl = oldIgnoreFocusControl;
3704 }
3705
3706 /**
3707 * Sets the receiver's size and location in points to the rectangular
3708 * area specified by the argument. The <code>x</code> and
3709 * <code>y</code> fields of the rectangle are relative to
3710 * the receiver's parent (or its display if its parent is null).
3711 * <p>
3712 * Note: Attempting to set the width or height of the
3713 * receiver to a negative number will cause that
3714 * value to be set to zero instead.
3715 * </p>
3716 * <p>
3717 * Note: On GTK, attempting to set the width or height of the
3718 * receiver to a number higher or equal 2^14 will cause them to be
3719 * set to (2^14)-1 instead.
3720 * </p>
3721 *
3722 * @param rect the new bounds for the receiver
3723 *
3724 * @exception SWTException <ul>
3725 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3726 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3727 * </ul>
3728 */
setBounds(Rectangle rect)3729 public void setBounds (Rectangle rect) {
3730 checkWidget ();
3731 if (rect == null) error (SWT.ERROR_NULL_ARGUMENT);
3732 setBounds (rect.x, rect.y, Math.max (0, rect.width), Math.max (0, rect.height), true, true);
3733 }
3734
3735 /**
3736 * If the argument is <code>true</code>, causes the receiver to have
3737 * all mouse events delivered to it until the method is called with
3738 * <code>false</code> as the argument. Note that on some platforms,
3739 * a mouse button must currently be down for capture to be assigned.
3740 *
3741 * @param capture <code>true</code> to capture the mouse, and <code>false</code> to release it
3742 *
3743 * @exception SWTException <ul>
3744 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3745 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3746 * </ul>
3747 */
setCapture(boolean capture)3748 public void setCapture (boolean capture) {
3749 checkWidget();
3750 }
3751
3752 @Override
setClipRegion(NSView view)3753 void setClipRegion (NSView view) {
3754 if (regionPath != null) {
3755 NSView rgnView = topView ();
3756 if (!rgnView.isFlipped ()) rgnView = eventView ();
3757 NSPoint pt = view.convertPoint_toView_(new NSPoint(), rgnView);
3758 NSAffineTransform transform = NSAffineTransform.transform();
3759 transform.translateXBy(-pt.x, -pt.y);
3760 regionPath.transformUsingAffineTransform(transform);
3761 regionPath.addClip();
3762 transform.translateXBy(2*pt.x, 2*pt.y);
3763 regionPath.transformUsingAffineTransform(transform);
3764 }
3765 parent.setClipRegion(view);
3766 }
3767
3768 /**
3769 * Sets the receiver's cursor to the cursor specified by the
3770 * argument, or to the default cursor for that kind of control
3771 * if the argument is null.
3772 * <p>
3773 * When the mouse pointer passes over a control its appearance
3774 * is changed to match the control's cursor.
3775 * </p>
3776 *
3777 * @param cursor the new cursor (or null)
3778 *
3779 * @exception IllegalArgumentException <ul>
3780 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
3781 * </ul>
3782 * @exception SWTException <ul>
3783 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3784 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3785 * </ul>
3786 */
setCursor(Cursor cursor)3787 public void setCursor (Cursor cursor) {
3788 checkWidget();
3789 if (cursor != null && cursor.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
3790 this.cursor = cursor;
3791 if (!isEnabled()) return;
3792 if (!view.window().areCursorRectsEnabled()) return;
3793 display.setCursor (display.currentControl);
3794 }
3795
setDefaultFont()3796 void setDefaultFont () {
3797 if (display.smallFonts) {
3798 setFont (defaultFont ().handle);
3799 setSmallSize ();
3800 }
3801 }
3802
3803 /**
3804 * Sets the receiver's drag detect state. If the argument is
3805 * <code>true</code>, the receiver will detect drag gestures,
3806 * otherwise these gestures will be ignored.
3807 *
3808 * @param dragDetect the new drag detect state
3809 *
3810 * @exception SWTException <ul>
3811 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3812 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3813 * </ul>
3814 *
3815 * @since 3.3
3816 */
setDragDetect(boolean dragDetect)3817 public void setDragDetect (boolean dragDetect) {
3818 checkWidget ();
3819 if (dragDetect) {
3820 state |= DRAG_DETECT;
3821 } else {
3822 state &= ~DRAG_DETECT;
3823 }
3824 }
3825
3826 /**
3827 * Enables the receiver if the argument is <code>true</code>,
3828 * and disables it otherwise. A disabled control is typically
3829 * not selectable from the user interface and draws with an
3830 * inactive or "grayed" look.
3831 *
3832 * @param enabled the new enabled state
3833 *
3834 * @exception SWTException <ul>
3835 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3836 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3837 * </ul>
3838 */
setEnabled(boolean enabled)3839 public void setEnabled (boolean enabled) {
3840 checkWidget();
3841 if (((state & DISABLED) == 0) == enabled) return;
3842 Control control = null;
3843 boolean fixFocus = false;
3844 if (!enabled) {
3845 if (display.focusEvent != SWT.FocusOut) {
3846 control = display.getFocusControl ();
3847 fixFocus = isFocusAncestor (control);
3848 }
3849 }
3850 if (enabled) {
3851 state &= ~DISABLED;
3852 } else {
3853 state |= DISABLED;
3854 }
3855 enableWidget (enabled);
3856 if (fixFocus) fixFocus (control);
3857 }
3858
3859 /**
3860 * Causes the receiver to have the <em>keyboard focus</em>,
3861 * such that all keyboard events will be delivered to it. Focus
3862 * reassignment will respect applicable platform constraints.
3863 *
3864 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
3865 *
3866 * @exception SWTException <ul>
3867 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3868 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3869 * </ul>
3870 *
3871 * @see #forceFocus
3872 */
setFocus()3873 public boolean setFocus () {
3874 checkWidget();
3875 if ((style & SWT.NO_FOCUS) != 0) return false;
3876 return forceFocus ();
3877 }
3878
3879 /**
3880 * Sets the font that the receiver will use to paint textual information
3881 * to the font specified by the argument, or to the default font for that
3882 * kind of control if the argument is null.
3883 *
3884 * @param font the new font (or null)
3885 *
3886 * @exception IllegalArgumentException <ul>
3887 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
3888 * </ul>
3889 * @exception SWTException <ul>
3890 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3891 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3892 * </ul>
3893 */
setFont(Font font)3894 public void setFont (Font font) {
3895 checkWidget();
3896 if (font != null) {
3897 if (font.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
3898 }
3899 this.font = font;
3900 setFont (font != null ? font.handle : defaultFont().handle);
3901 }
3902
setFont(NSFont font)3903 void setFont (NSFont font) {
3904 if (view instanceof NSControl) {
3905 ((NSControl)view).setFont(font);
3906 }
3907 }
3908
3909 /**
3910 * Sets the receiver's foreground color to the color specified
3911 * by the argument, or to the default system color for the control
3912 * if the argument is null.
3913 * <p>
3914 * Note: This operation is a hint and may be overridden by the platform.
3915 * </p>
3916 * @param color the new color (or null)
3917 *
3918 * @exception IllegalArgumentException <ul>
3919 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
3920 * </ul>
3921 * @exception SWTException <ul>
3922 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3923 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3924 * </ul>
3925 */
setForeground(Color color)3926 public void setForeground (Color color) {
3927 checkWidget();
3928 if (color != null) {
3929 if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
3930 }
3931 double [] foreground = color != null ? color.handle : null;
3932 if (equals (foreground, this.foreground)) return;
3933 this.foreground = foreground;
3934 setForeground (foreground);
3935 redrawWidget (view, false);
3936 }
3937
setForeground(double [] color)3938 void setForeground (double [] color) {
3939 }
3940
3941 @Override
setFrameOrigin(long id, long sel, NSPoint point)3942 void setFrameOrigin (long id, long sel, NSPoint point) {
3943 NSView topView = topView ();
3944 if (topView.id != id) {
3945 super.setFrameOrigin(id, sel, point);
3946 return;
3947 }
3948 NSRect frame = topView.frame();
3949 super.setFrameOrigin(id, sel, point);
3950 if (frame.x != point.x || frame.y != point.y) {
3951 invalidateVisibleRegion();
3952 moved ();
3953 }
3954 }
3955
3956 @Override
setFrameSize(long id, long sel, NSSize size)3957 void setFrameSize (long id, long sel, NSSize size) {
3958 NSView topView = topView ();
3959 if (topView.id != id) {
3960 super.setFrameSize(id, sel, size);
3961 return;
3962 }
3963 NSRect frame = topView.frame();
3964 super.setFrameSize(id, sel, size);
3965 if (frame.width != size.width || frame.height != size.height) {
3966 invalidateVisibleRegion();
3967 boolean oldResizing = (state & RESIZING) != 0;
3968 state |= RESIZING;
3969 resized ();
3970 if (!oldResizing) state &= ~RESIZING;
3971 }
3972 }
3973
3974 @Override
cacheDisplayInRect_toBitmapImageRep(long id, long sel, NSRect rect, long rep)3975 void cacheDisplayInRect_toBitmapImageRep (long id, long sel, NSRect rect, long rep) {
3976 /*
3977 * When a GC is created with a control as the Drawable and GC.copyArea() is
3978 * called, a SWT.Paint event will be sent, unexpectedly. This happens because
3979 * NSView.cacheDisplayInRect() calls drawRect() which causes a SWT.Paint event
3980 * to be sent. This leads to recursion if GC.copyArea() is called inside the PaintListener.
3981 *
3982 * The fix is to prevent recursive calls to cacheDisplayInRect_toBitmapImageRep.
3983 */
3984 if (inCacheDisplayInRect) return;
3985 inCacheDisplayInRect = true;
3986 super.cacheDisplayInRect_toBitmapImageRep(id, sel, rect, rep);
3987 inCacheDisplayInRect = false;
3988 }
3989
3990 /**
3991 * Sets the layout data associated with the receiver to the argument.
3992 *
3993 * @param layoutData the new layout data for the receiver.
3994 *
3995 * @exception SWTException <ul>
3996 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
3997 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3998 * </ul>
3999 */
setLayoutData(Object layoutData)4000 public void setLayoutData (Object layoutData) {
4001 checkWidget();
4002 this.layoutData = layoutData;
4003 }
4004
4005 /**
4006 * Sets the receiver's location to the point specified by
4007 * the arguments which are relative to the receiver's
4008 * parent (or its display if its parent is null), unless
4009 * the receiver is a shell. In this case, the point is
4010 * relative to the display.
4011 *
4012 * @param x the new x coordinate for the receiver
4013 * @param y the new y coordinate for the receiver
4014 *
4015 * @exception SWTException <ul>
4016 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4017 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4018 * </ul>
4019 */
setLocation(int x, int y)4020 public void setLocation (int x, int y) {
4021 checkWidget();
4022 setBounds (x, y, 0, 0, true, false);
4023 }
4024
4025 /**
4026 * Sets the receiver's location to the point specified by
4027 * the arguments which are relative to the receiver's
4028 * parent (or its display if its parent is null), unless
4029 * the receiver is a shell. In this case, the point is
4030 * relative to the display.
4031 *
4032 * @param location the new location for the receiver
4033 *
4034 * @exception SWTException <ul>
4035 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4036 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4037 * </ul>
4038 */
setLocation(Point location)4039 public void setLocation (Point location) {
4040 checkWidget();
4041 if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
4042 setBounds (location.x, location.y, 0, 0, true, false);
4043 }
4044
4045 /**
4046 * Sets the receiver's pop up menu to the argument.
4047 * All controls may optionally have a pop up
4048 * menu that is displayed when the user requests one for
4049 * the control. The sequence of key strokes, button presses
4050 * and/or button releases that are used to request a pop up
4051 * menu is platform specific.
4052 * <p>
4053 * Note: Disposing of a control that has a pop up menu will
4054 * dispose of the menu. To avoid this behavior, set the
4055 * menu to null before the control is disposed.
4056 * </p>
4057 *
4058 * @param menu the new pop up menu
4059 *
4060 * @exception IllegalArgumentException <ul>
4061 * <li>ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu</li>
4062 * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
4063 * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
4064 * </ul>
4065 * @exception SWTException <ul>
4066 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4067 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4068 * </ul>
4069 */
setMenu(Menu menu)4070 public void setMenu (Menu menu) {
4071 checkWidget();
4072 if (menu != null) {
4073 if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
4074 if ((menu.style & SWT.POP_UP) == 0) {
4075 error (SWT.ERROR_MENU_NOT_POP_UP);
4076 }
4077 if (menu.parent != menuShell ()) {
4078 error (SWT.ERROR_INVALID_PARENT);
4079 }
4080 }
4081 this.menu = menu;
4082 }
4083
4084 /**
4085 * Sets the orientation of the receiver, which must be one
4086 * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
4087 * <p>
4088 *
4089 * @param orientation new orientation style
4090 *
4091 * @exception SWTException <ul>
4092 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4093 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4094 * </ul>
4095 *
4096 * @since 3.7
4097 */
setOrientation(int orientation)4098 public void setOrientation (int orientation) {
4099 checkWidget ();
4100 }
4101
4102 /**
4103 * Changes the parent of the widget to be the one provided.
4104 * Returns <code>true</code> if the parent is successfully changed.
4105 *
4106 * @param parent the new parent for the control.
4107 * @return <code>true</code> if the parent is changed and <code>false</code> otherwise.
4108 *
4109 * @exception IllegalArgumentException <ul>
4110 * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
4111 * <li>ERROR_NULL_ARGUMENT - if the parent is <code>null</code></li>
4112 * </ul>
4113 * @exception SWTException <ul>
4114 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4115 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4116 * </ul>
4117 */
setParent(Composite parent)4118 public boolean setParent (Composite parent) {
4119 checkWidget();
4120 if (parent == null) error (SWT.ERROR_NULL_ARGUMENT);
4121 if (parent.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
4122 if (this.parent == parent) return true;
4123 if (!isReparentable ()) return false;
4124 releaseParent ();
4125 Shell newShell = parent.getShell (), oldShell = getShell ();
4126 Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell ();
4127 if (oldShell != newShell || oldDecorations != newDecorations) {
4128 Menu [] menus = oldShell.findMenus (this);
4129 fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
4130 }
4131 NSView topView = topView ();
4132 topView.retain();
4133 topView.removeFromSuperview();
4134 parent.contentView().addSubview(topView, OS.NSWindowBelow, null);
4135 topView.release();
4136 this.parent = parent;
4137 reskin (SWT.ALL);
4138 return true;
4139 }
4140
4141 /**
4142 * If the argument is <code>false</code>, causes subsequent drawing
4143 * operations in the receiver to be ignored. No drawing of any kind
4144 * can occur in the receiver until the flag is set to true.
4145 * Graphics operations that occurred while the flag was
4146 * <code>false</code> are lost. When the flag is set to <code>true</code>,
4147 * the entire widget is marked as needing to be redrawn. Nested calls
4148 * to this method are stacked.
4149 * <p>
4150 * Note: This operation is a hint and may not be supported on some
4151 * platforms or for some widgets.
4152 * </p>
4153 *
4154 * @param redraw the new redraw state
4155 *
4156 * @exception SWTException <ul>
4157 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4158 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4159 * </ul>
4160 *
4161 * @see #redraw(int, int, int, int, boolean)
4162 * @see #update()
4163 */
setRedraw(boolean redraw)4164 public void setRedraw (boolean redraw) {
4165 checkWidget();
4166 if (redraw) {
4167 if (--drawCount == 0) {
4168 invalidateVisibleRegion ();
4169 redrawWidget(topView (), true);
4170 }
4171 } else {
4172 if (drawCount == 0) {
4173 invalidateVisibleRegion ();
4174 }
4175 drawCount++;
4176 }
4177 }
4178
4179 /**
4180 * Sets the shape of the control to the region specified
4181 * by the argument. When the argument is null, the
4182 * default shape of the control is restored.
4183 *
4184 * @param region the region that defines the shape of the control (or null)
4185 *
4186 * @exception IllegalArgumentException <ul>
4187 * <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
4188 * </ul>
4189 * @exception SWTException <ul>
4190 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4191 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4192 * </ul>
4193 *
4194 * @since 3.4
4195 */
setRegion(Region region)4196 public void setRegion (Region region) {
4197 checkWidget ();
4198 if (region != null && region.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
4199 this.region = region;
4200 if (regionPath != null) regionPath.release();
4201 regionPath = getPath(region);
4202 redrawWidget(view, true);
4203 }
4204
setRelations()4205 void setRelations () {
4206 if (parent == null) return;
4207 Control [] children = parent._getChildren ();
4208 int count = children.length;
4209 if (count > 1) {
4210 /*
4211 * the receiver is the last item in the list, so its predecessor will
4212 * be the second-last item in the list
4213 */
4214 Control child = children [count - 2];
4215 if (child != this) {
4216 child.addRelation (this);
4217 }
4218 }
4219 }
4220
setRadioSelection(boolean value)4221 boolean setRadioSelection (boolean value){
4222 return false;
4223 }
4224
4225 /**
4226 * Sets the receiver's size to the point specified by the arguments.
4227 * <p>
4228 * Note: Attempting to set the width or height of the
4229 * receiver to a negative number will cause that
4230 * value to be set to zero instead.
4231 * </p>
4232 * <p>
4233 * Note: On GTK, attempting to set the width or height of the
4234 * receiver to a number higher or equal 2^14 will cause them to be
4235 * set to (2^14)-1 instead.
4236 * </p>
4237 *
4238 * @param width the new width in points for the receiver
4239 * @param height the new height in points for the receiver
4240 *
4241 * @exception SWTException <ul>
4242 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4243 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4244 * </ul>
4245 */
setSize(int width, int height)4246 public void setSize (int width, int height) {
4247 checkWidget();
4248 setBounds (0, 0, Math.max (0, width), Math.max (0, height), false, true);
4249 }
4250
4251 /**
4252 * Sets the receiver's size to the point specified by the argument.
4253 * <p>
4254 * Note: Attempting to set the width or height of the
4255 * receiver to a negative number will cause them to be
4256 * set to zero instead.
4257 * </p>
4258 * <p>
4259 * Note: On GTK, attempting to set the width or height of the
4260 * receiver to a number higher or equal 2^14 will cause them to be
4261 * set to (2^14)-1 instead.
4262 * </p>
4263 *
4264 * @param size the new size in points for the receiver
4265 *
4266 * @exception IllegalArgumentException <ul>
4267 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
4268 * </ul>
4269 * @exception SWTException <ul>
4270 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4271 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4272 * </ul>
4273 */
setSize(Point size)4274 public void setSize (Point size) {
4275 checkWidget ();
4276 if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
4277 setBounds (0, 0, Math.max (0, size.x), Math.max (0, size.y), false, true);
4278 }
4279
setSmallSize()4280 void setSmallSize () {
4281 if (view instanceof NSControl) {
4282 NSCell cell = ((NSControl)view).cell();
4283 if (cell != null) cell.setControlSize (OS.NSSmallControlSize);
4284 }
4285 }
4286
4287 @Override
setTabItemFocus()4288 boolean setTabItemFocus () {
4289 if (!isShowing ()) return false;
4290 return forceFocus ();
4291 }
4292
4293 /**
4294 * Sets the base text direction (a.k.a. "paragraph direction") of the receiver,
4295 * which must be one of the constants <code>SWT.LEFT_TO_RIGHT</code>,
4296 * <code>SWT.RIGHT_TO_LEFT</code>, or <code>SWT.AUTO_TEXT_DIRECTION</code>.
4297 * <p>
4298 * <code>setOrientation</code> would override this value with the text direction
4299 * that is consistent with the new orientation.
4300 * </p>
4301 * <p>
4302 * <b>Warning</b>: This API is currently only implemented on Windows.
4303 * It doesn't set the base text direction on GTK and Cocoa.
4304 * </p>
4305 *
4306 * @param textDirection the base text direction style
4307 *
4308 * @exception SWTException <ul>
4309 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4310 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4311 * </ul>
4312 *
4313 * @see SWT#LEFT_TO_RIGHT
4314 * @see SWT#RIGHT_TO_LEFT
4315 * @see SWT#AUTO_TEXT_DIRECTION
4316 * @see SWT#FLIP_TEXT_DIRECTION
4317 *
4318 * @since 3.102
4319 */
setTextDirection(int textDirection)4320 public void setTextDirection(int textDirection) {
4321 checkWidget ();
4322 }
4323
4324 /**
4325 * Sets the receiver's tool tip text to the argument, which
4326 * may be null indicating that the default tool tip for the
4327 * control will be shown. For a control that has a default
4328 * tool tip, such as the Tree control on Windows, setting
4329 * the tool tip text to an empty string replaces the default,
4330 * causing no tool tip text to be shown.
4331 * <p>
4332 * The mnemonic indicator (character '&') is not displayed in a tool tip.
4333 * To display a single '&' in the tool tip, the character '&' can be
4334 * escaped by doubling it in the string.
4335 * </p>
4336 * <p>
4337 * NOTE: This operation is a hint and behavior is platform specific, on Windows
4338 * for CJK-style mnemonics of the form " (&C)" at the end of the tooltip text
4339 * are not shown in tooltip.
4340 * </p>
4341 *
4342 * @param string the new tool tip text (or null)
4343 *
4344 * @exception SWTException <ul>
4345 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4346 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4347 * </ul>
4348 */
setToolTipText(String string)4349 public void setToolTipText (String string) {
4350 checkWidget();
4351 toolTipText = string;
4352 checkToolTip (null);
4353 }
4354
4355 /**
4356 * Sets whether this control should send touch events (by default controls do not).
4357 * Setting this to <code>false</code> causes the receiver to send gesture events
4358 * instead. No exception is thrown if a touch-based input device is not
4359 * detected (this can be determined with <code>Display#getTouchEnabled()</code>).
4360 *
4361 * @param enabled the new touch-enabled state
4362 *
4363 * @exception SWTException <ul>
4364 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4365 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4366 * </ul>
4367 *
4368 * @see Display#getTouchEnabled
4369 *
4370 * @since 3.7
4371 */
setTouchEnabled(boolean enabled)4372 public void setTouchEnabled(boolean enabled) {
4373 checkWidget();
4374 eventView().setAcceptsTouchEvents(enabled);
4375 touchEnabled = enabled;
4376 }
4377
4378 /**
4379 * Marks the receiver as visible if the argument is <code>true</code>,
4380 * and marks it invisible otherwise.
4381 * <p>
4382 * If one of the receiver's ancestors is not visible or some
4383 * other condition makes the receiver not visible, marking
4384 * it visible may not actually cause it to be displayed.
4385 * </p>
4386 *
4387 * @param visible the new visibility state
4388 *
4389 * @exception SWTException <ul>
4390 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4391 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4392 * </ul>
4393 */
setVisible(boolean visible)4394 public void setVisible (boolean visible) {
4395 checkWidget();
4396 if (visible) {
4397 if ((state & HIDDEN) == 0) return;
4398 state &= ~HIDDEN;
4399 } else {
4400 if ((state & HIDDEN) != 0) return;
4401 state |= HIDDEN;
4402 }
4403 if (visible) {
4404 /*
4405 * It is possible (but unlikely), that application
4406 * code could have disposed the widget in the show
4407 * event. If this happens, just return.
4408 */
4409 sendEvent (SWT.Show);
4410 if (isDisposed ()) return;
4411 }
4412
4413 /*
4414 * Feature in the Macintosh. If the receiver has focus, hiding
4415 * the receiver causes no control to have focus. Also, the focus
4416 * needs to be cleared from any TXNObject so that it stops blinking
4417 * the caret. The fix is to assign focus to the first ancestor
4418 * control that takes focus. If no control will take focus, clear
4419 * the focus control.
4420 */
4421 Control control = null;
4422 boolean fixFocus = false;
4423 if (!visible) {
4424 if (display.focusEvent != SWT.FocusOut) {
4425 control = display.getFocusControl ();
4426 fixFocus = isFocusAncestor (control);
4427 }
4428 }
4429 topView().setHidden(!visible);
4430 if (isDisposed ()) return;
4431 invalidateVisibleRegion();
4432 if (!visible) {
4433 /*
4434 * It is possible (but unlikely), that application
4435 * code could have disposed the widget in the show
4436 * event. If this happens, just return.
4437 */
4438 sendEvent (SWT.Hide);
4439 if (isDisposed ()) return;
4440 }
4441 if (fixFocus) fixFocus (control);
4442 }
4443
setZOrder()4444 void setZOrder () {
4445 NSView topView = topView ();
4446 parent.contentView().addSubview(topView, OS.NSWindowBelow, null);
4447 }
4448
4449 @Override
shouldDelayWindowOrderingForEvent(long id, long sel, long theEvent)4450 boolean shouldDelayWindowOrderingForEvent (long id, long sel, long theEvent) {
4451 Shell shell = getShell ();
4452 if ((shell.style & SWT.ON_TOP) != 0) return false;
4453 return super.shouldDelayWindowOrderingForEvent (id, sel, theEvent);
4454 }
4455
setZOrder(Control sibling, boolean above)4456 void setZOrder (Control sibling, boolean above) {
4457 int index = 0, siblingIndex = 0, oldNextIndex = -1;
4458 Control[] children = null;
4459 /* determine the receiver's and sibling's indexes in the parent */
4460 children = parent._getChildren ();
4461 while (index < children.length) {
4462 if (children [index] == this) break;
4463 index++;
4464 }
4465 if (sibling != null) {
4466 while (siblingIndex < children.length) {
4467 if (children [siblingIndex] == sibling) break;
4468 siblingIndex++;
4469 }
4470 }
4471 /* remove "Labeled by" relationships that will no longer be valid */
4472 removeRelation ();
4473 if (index + 1 < children.length) {
4474 oldNextIndex = index + 1;
4475 children [oldNextIndex].removeRelation ();
4476 }
4477 if (sibling != null) {
4478 if (above) {
4479 sibling.removeRelation ();
4480 } else {
4481 if (siblingIndex + 1 < children.length) {
4482 children [siblingIndex + 1].removeRelation ();
4483 }
4484 }
4485 }
4486
4487 NSView otherView = sibling == null ? null : sibling.topView ();
4488 NSView topView = topView();
4489 topView.retain();
4490 topView.removeFromSuperview();
4491 parent.contentView().addSubview(topView, above ? OS.NSWindowAbove : OS.NSWindowBelow, otherView);
4492 topView.release();
4493 invalidateVisibleRegion();
4494
4495 /* determine the receiver's new index in the parent */
4496 if (sibling != null) {
4497 if (above) {
4498 index = siblingIndex - (index < siblingIndex ? 1 : 0);
4499 } else {
4500 index = siblingIndex + (siblingIndex < index ? 1 : 0);
4501 }
4502 } else {
4503 if (above) {
4504 index = 0;
4505 } else {
4506 index = children.length - 1;
4507 }
4508 }
4509
4510 /* add new "Labeled by" relations as needed */
4511 children = parent._getChildren ();
4512 if (0 < index) {
4513 children [index - 1].addRelation (this);
4514 }
4515 if (index + 1 < children.length) {
4516 addRelation (children [index + 1]);
4517 }
4518 if (oldNextIndex != -1) {
4519 if (oldNextIndex <= index) oldNextIndex--;
4520 /* the last two conditions below ensure that duplicate relations are not hooked */
4521 if (0 < oldNextIndex && oldNextIndex != index && oldNextIndex != index + 1) {
4522 children [oldNextIndex - 1].addRelation (children [oldNextIndex]);
4523 }
4524 }
4525 }
4526
sort(int [] items)4527 void sort (int [] items) {
4528 /* Shell Sort from K&R, pg 108 */
4529 int length = items.length;
4530 for (int gap=length/2; gap>0; gap/=2) {
4531 for (int i=gap; i<length; i++) {
4532 for (int j=i-gap; j>=0; j-=gap) {
4533 if (items [j] <= items [j + gap]) {
4534 int swap = items [j];
4535 items [j] = items [j + gap];
4536 items [j + gap] = swap;
4537 }
4538 }
4539 }
4540 }
4541 }
4542
4543 @Override
swipeWithEvent(long id, long sel, long event)4544 void swipeWithEvent(long id, long sel, long event) {
4545 if (!gestureEvent(id, event, SWT.GESTURE_SWIPE)) return;
4546 super.swipeWithEvent(id, sel, event);
4547 }
4548
textExtent(String string)4549 NSSize textExtent (String string) {
4550 NSAttributedString attribStr = createString(string, null, null, 0, false, true, false);
4551 NSSize size = attribStr.size();
4552 attribStr.release();
4553 return size;
4554 }
4555
4556 @Override
tooltipText()4557 String tooltipText () {
4558 return toolTipText;
4559 }
4560
4561 /**
4562 * Returns a point which is the result of converting the
4563 * argument, which is specified in display relative coordinates,
4564 * to coordinates relative to the receiver.
4565 * <p>
4566 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
4567 * {@link Display#map(Control, Control, Rectangle)}.
4568 * </p>
4569 *
4570 * @param x the x coordinate in points to be translated
4571 * @param y the y coordinate in points to be translated
4572 * @return the translated coordinates
4573 *
4574 * @exception SWTException <ul>
4575 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4576 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4577 * </ul>
4578 *
4579 * @since 2.1
4580 */
toControl(int x, int y)4581 public Point toControl (int x, int y) {
4582 checkWidget();
4583 return display.map (null, this, x, y);
4584 }
4585
4586 /**
4587 * Returns a point which is the result of converting the
4588 * argument, which is specified in display relative coordinates,
4589 * to coordinates relative to the receiver.
4590 * <p>
4591 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
4592 * {@link Display#map(Control, Control, Rectangle)}.
4593 * </p>
4594 *
4595 * @param point the point to be translated (must not be null)
4596 * @return the translated coordinates
4597 *
4598 * @exception IllegalArgumentException <ul>
4599 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
4600 * </ul>
4601 * @exception SWTException <ul>
4602 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4603 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4604 * </ul>
4605 */
toControl(Point point)4606 public Point toControl (Point point) {
4607 checkWidget();
4608 if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
4609 return toControl (point.x, point.y);
4610 }
4611
4612 /**
4613 * Returns a point which is the result of converting the
4614 * argument, which is specified in coordinates relative to
4615 * the receiver, to display relative coordinates.
4616 * <p>
4617 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
4618 * {@link Display#map(Control, Control, Rectangle)}.
4619 * </p>
4620 *
4621 * @param x the x coordinate to be translated
4622 * @param y the y coordinate to be translated
4623 * @return the translated coordinates
4624 *
4625 * @exception SWTException <ul>
4626 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4627 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4628 * </ul>
4629 *
4630 * @since 2.1
4631 */
toDisplay(int x, int y)4632 public Point toDisplay (int x, int y) {
4633 checkWidget();
4634 return display.map (this, null, x, y);
4635 }
4636
4637 /**
4638 * Returns a point which is the result of converting the
4639 * argument, which is specified in coordinates relative to
4640 * the receiver, to display relative coordinates.
4641 * <p>
4642 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
4643 * {@link Display#map(Control, Control, Rectangle)}.
4644 * </p>
4645 *
4646 * @param point the point to be translated (must not be null)
4647 * @return the translated coordinates
4648 *
4649 * @exception IllegalArgumentException <ul>
4650 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
4651 * </ul>
4652 * @exception SWTException <ul>
4653 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4654 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4655 * </ul>
4656 */
toDisplay(Point point)4657 public Point toDisplay (Point point) {
4658 checkWidget();
4659 if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
4660 return toDisplay (point.x, point.y);
4661 }
4662
topView()4663 NSView topView () {
4664 return view;
4665 }
4666
touchEvent(long id, long sel, long eventPtr)4667 boolean touchEvent(long id, long sel, long eventPtr) {
4668 if (!display.sendEvent) return true;
4669 display.sendEvent = false;
4670 if (!(hooks(SWT.Touch) || filters(SWT.Touch))) return true;
4671 if (!isEventView (id)) return true;
4672 if (!touchEnabled) return true;
4673 NSEvent nsEvent = new NSEvent(eventPtr);
4674 NSMutableArray currentTouches = display.currentTouches();
4675 Event event = new Event ();
4676 NSPoint location = view.convertPoint_fromView_(nsEvent.locationInWindow(), null);
4677 if (!view.isFlipped ()) {
4678 location.y = view.bounds().height - location.y;
4679 }
4680 event.x = (int) location.x;
4681 event.y = (int) location.y;
4682 setInputState (event, nsEvent, SWT.Touch);
4683 NSSet allTouchesSet = nsEvent.touchesMatchingPhase(OS.NSTouchPhaseAny, null);
4684 long touchCount = allTouchesSet.count();
4685 Touch touches[] = new Touch[(int)touchCount];
4686 int currTouchIndex = 0;
4687
4688 // Process removed/cancelled touches first.
4689 NSArray endedTouches = nsEvent.touchesMatchingPhase(OS.NSTouchPhaseEnded | OS.NSTouchPhaseCancelled, null).allObjects();
4690
4691 for (int i = 0; i < endedTouches.count(); i++) {
4692 NSTouch touch = new NSTouch(endedTouches.objectAtIndex(i).id);
4693 NSObject identity = new NSObject(OS.objc_msgSend(touch.id, OS.sel_identity));
4694 NSTouch endedTouch = findTouchWithId(currentTouches, identity);
4695 if (endedTouch != null) currentTouches.removeObject(endedTouch);
4696 touches[currTouchIndex++] = touchStateFromNSTouch(touch);
4697 }
4698
4699 if (currentTouches.count() == 0) display.touchCounter = 0;
4700
4701 // Process touches in progress or starting.
4702 NSArray activeTouches = nsEvent.touchesMatchingPhase(OS.NSTouchPhaseBegan | OS.NSTouchPhaseMoved | OS.NSTouchPhaseStationary, null).allObjects();
4703
4704 for (int i = 0; i < activeTouches.count(); i++) {
4705 NSTouch touch = new NSTouch(activeTouches.objectAtIndex(i).id);
4706 NSObject identity = new NSObject(OS.objc_msgSend(touch.id, OS.sel_identity));
4707 NSTouch activeTouch = findTouchWithId(currentTouches, identity);
4708 if (activeTouch == null) currentTouches.addObject(touch);
4709 touches[currTouchIndex++] = touchStateFromNSTouch(touch);
4710 }
4711
4712 if (activeTouches.count() != currentTouches.count()) {
4713 /**
4714 * Bug in Cocoa. Under some situations we don't get the NSTouchPhaseEnded/Cancelled notification. Most commonly this happens
4715 * if a 4-finger gesture occurs and the application switcher appears. Workaround is to generate a TOUCHSTATE_UP for the
4716 * orphaned touch.
4717 */
4718 for (long j = currentTouches.count() - 1; j >= 0 ; j--) {
4719 NSTouch touch = new NSTouch(currentTouches.objectAtIndex(j).id);
4720 NSObject identity = new NSObject(OS.objc_msgSend(touch.id, OS.sel_identity));
4721 NSTouch activeTouch = findTouchWithId(activeTouches, identity);
4722 if (activeTouch == null) {
4723 Touch fakeTouchUp = touchStateFromNSTouch(touch);
4724 fakeTouchUp.state = SWT.TOUCHSTATE_UP;
4725
4726 if (currTouchIndex == touches.length) {
4727 Touch newTouchStates[] = new Touch[touches.length + 1];
4728 System.arraycopy(touches, 0, newTouchStates, 0, touches.length);
4729 touches = newTouchStates;
4730 }
4731
4732 touches[currTouchIndex++] = fakeTouchUp;
4733 currentTouches.removeObject(activeTouch);
4734 }
4735 }
4736 }
4737
4738 event.touches = touches;
4739 postEvent (SWT.Touch, event);
4740 return true;
4741 }
4742
4743 @Override
touchesBeganWithEvent(long id, long sel, long event)4744 void touchesBeganWithEvent (long id, long sel, long event) {
4745 if (!touchEvent(id, sel, event)) return;
4746 super.touchesBeganWithEvent(id, sel, event);
4747 }
4748
4749 @Override
touchesCancelledWithEvent(long id, long sel, long event)4750 void touchesCancelledWithEvent (long id, long sel, long event) {
4751 if (!touchEvent(id, sel, event)) return;
4752 super.touchesCancelledWithEvent(id, sel, event);
4753 }
4754
4755 @Override
touchesEndedWithEvent(long id, long sel, long event)4756 void touchesEndedWithEvent (long id, long sel, long event) {
4757 if (!touchEvent(id, sel, event)) return;
4758 super.touchesEndedWithEvent(id, sel, event);
4759 }
4760
4761 @Override
touchesMovedWithEvent(long id, long sel, long event)4762 void touchesMovedWithEvent (long id, long sel, long event) {
4763 if (!touchEvent(id, sel, event)) return;
4764 super.touchesMovedWithEvent(id, sel, event);
4765 }
4766
translateTraversal(int key, NSEvent theEvent, boolean [] consume)4767 boolean translateTraversal (int key, NSEvent theEvent, boolean [] consume) {
4768 int detail = SWT.TRAVERSE_NONE;
4769 int code = traversalCode (key, theEvent);
4770 boolean all = false;
4771 switch (key) {
4772 case 53: /* Esc */ {
4773 all = true;
4774 detail = SWT.TRAVERSE_ESCAPE;
4775 break;
4776 }
4777 case 76: /* KP Enter */
4778 case 36: /* Return */ {
4779 all = true;
4780 detail = SWT.TRAVERSE_RETURN;
4781 break;
4782 }
4783 case 48: /* Tab */ {
4784 long modifiers = theEvent.modifierFlags ();
4785 boolean next = (modifiers & OS.NSShiftKeyMask) == 0;
4786 detail = next ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS;
4787 break;
4788 }
4789 case 126: /* Up arrow */
4790 case 123: /* Left arrow */
4791 case 125: /* Down arrow */
4792 case 124: /* Right arrow */ {
4793 boolean next = key == 125 /* Down arrow */ || key == 124 /* Right arrow */;
4794 detail = next ? SWT.TRAVERSE_ARROW_NEXT : SWT.TRAVERSE_ARROW_PREVIOUS;
4795 break;
4796 }
4797 case 116: /* Page up */
4798 case 121: /* Page down */ {
4799 all = true;
4800 long modifiers = theEvent.modifierFlags ();
4801 if ((modifiers & OS.NSControlKeyMask) == 0) return false;
4802 detail = key == 121 /* Page down */ ? SWT.TRAVERSE_PAGE_NEXT : SWT.TRAVERSE_PAGE_PREVIOUS;
4803 break;
4804 }
4805 default:
4806 return false;
4807 }
4808 Event event = new Event ();
4809 event.doit = consume [0] = (code & detail) != 0;
4810 event.detail = detail;
4811 if (!setKeyState (event, SWT.Traverse, theEvent)) return false;
4812 Shell shell = getShell ();
4813 Control control = this;
4814 do {
4815 if (control.traverse (event)) return true;
4816 if (!event.doit && control.hooks (SWT.Traverse)) {
4817 return false;
4818 }
4819 if (control == shell) return false;
4820 control = control.parent;
4821 } while (all && control != null);
4822 return false;
4823 }
4824
traversalCode(int key, NSEvent theEvent)4825 int traversalCode (int key, NSEvent theEvent) {
4826 int code = SWT.TRAVERSE_RETURN | SWT.TRAVERSE_TAB_NEXT | SWT.TRAVERSE_TAB_PREVIOUS | SWT.TRAVERSE_PAGE_NEXT | SWT.TRAVERSE_PAGE_PREVIOUS;
4827 Shell shell = getShell ();
4828 if (shell.parent != null) code |= SWT.TRAVERSE_ESCAPE;
4829 return code;
4830 }
4831
traverseMnemonic(char key)4832 boolean traverseMnemonic (char key) {
4833 return false;
4834 }
4835
4836 /**
4837 * Performs a platform traversal action corresponding to a <code>KeyDown</code> event.
4838 *
4839 * <p>Valid traversal values are
4840 * <code>SWT.TRAVERSE_NONE</code>, <code>SWT.TRAVERSE_MNEMONIC</code>,
4841 * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
4842 * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
4843 * <code>SWT.TRAVERSE_ARROW_NEXT</code>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
4844 * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_PREVIOUS</code>.
4845 * If <code>traversal</code> is <code>SWT.TRAVERSE_NONE</code> then the Traverse
4846 * event is created with standard values based on the KeyDown event. If
4847 * <code>traversal</code> is one of the other traversal constants then the Traverse
4848 * event is created with this detail, and its <code>doit</code> is taken from the
4849 * KeyDown event.
4850 * </p>
4851 *
4852 * @param traversal the type of traversal, or <code>SWT.TRAVERSE_NONE</code> to compute
4853 * this from <code>event</code>
4854 * @param event the KeyDown event
4855 *
4856 * @return <code>true</code> if the traversal succeeded
4857 *
4858 * @exception IllegalArgumentException <ul>
4859 * <li>ERROR_NULL_ARGUMENT if the event is null</li>
4860 * </ul>
4861 * @exception SWTException <ul>
4862 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4863 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4864 * </ul>
4865 *
4866 * @since 3.6
4867 */
traverse(int traversal, Event event)4868 public boolean traverse (int traversal, Event event) {
4869 checkWidget ();
4870 if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
4871 return traverse (traversal, event.character, event.keyCode, event.keyLocation, event.stateMask, event.doit);
4872 }
4873
4874 /**
4875 * Performs a platform traversal action corresponding to a <code>KeyDown</code> event.
4876 *
4877 * <p>Valid traversal values are
4878 * <code>SWT.TRAVERSE_NONE</code>, <code>SWT.TRAVERSE_MNEMONIC</code>,
4879 * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
4880 * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
4881 * <code>SWT.TRAVERSE_ARROW_NEXT</code>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
4882 * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_PREVIOUS</code>.
4883 * If <code>traversal</code> is <code>SWT.TRAVERSE_NONE</code> then the Traverse
4884 * event is created with standard values based on the KeyDown event. If
4885 * <code>traversal</code> is one of the other traversal constants then the Traverse
4886 * event is created with this detail, and its <code>doit</code> is taken from the
4887 * KeyDown event.
4888 * </p>
4889 *
4890 * @param traversal the type of traversal, or <code>SWT.TRAVERSE_NONE</code> to compute
4891 * this from <code>event</code>
4892 * @param event the KeyDown event
4893 *
4894 * @return <code>true</code> if the traversal succeeded
4895 *
4896 * @exception IllegalArgumentException <ul>
4897 * <li>ERROR_NULL_ARGUMENT if the event is null</li>
4898 * </ul>
4899 * @exception SWTException <ul>
4900 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4901 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4902 * </ul>
4903 *
4904 * @since 3.6
4905 */
traverse(int traversal, KeyEvent event)4906 public boolean traverse (int traversal, KeyEvent event) {
4907 checkWidget ();
4908 if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
4909 return traverse (traversal, event.character, event.keyCode, event.keyLocation, event.stateMask, event.doit);
4910 }
4911
traverse(int traversal, char character, int keyCode, int keyLocation, int stateMask, boolean doit)4912 boolean traverse (int traversal, char character, int keyCode, int keyLocation, int stateMask, boolean doit) {
4913 if (traversal == SWT.TRAVERSE_NONE) {
4914 switch (keyCode) {
4915 case SWT.ESC: {
4916 traversal = SWT.TRAVERSE_ESCAPE;
4917 doit = true;
4918 break;
4919 }
4920 case SWT.CR: {
4921 traversal = SWT.TRAVERSE_RETURN;
4922 doit = true;
4923 break;
4924 }
4925 case SWT.ARROW_DOWN:
4926 case SWT.ARROW_RIGHT: {
4927 traversal = SWT.TRAVERSE_ARROW_NEXT;
4928 doit = false;
4929 break;
4930 }
4931 case SWT.ARROW_UP:
4932 case SWT.ARROW_LEFT: {
4933 traversal = SWT.TRAVERSE_ARROW_PREVIOUS;
4934 doit = false;
4935 break;
4936 }
4937 case SWT.TAB: {
4938 traversal = (stateMask & SWT.SHIFT) != 0 ? SWT.TRAVERSE_TAB_PREVIOUS : SWT.TRAVERSE_TAB_NEXT;
4939 doit = true;
4940 break;
4941 }
4942 case SWT.PAGE_DOWN: {
4943 if ((stateMask & SWT.CTRL) != 0) {
4944 traversal = SWT.TRAVERSE_PAGE_NEXT;
4945 doit = true;
4946 }
4947 break;
4948 }
4949 case SWT.PAGE_UP: {
4950 if ((stateMask & SWT.CTRL) != 0) {
4951 traversal = SWT.TRAVERSE_PAGE_PREVIOUS;
4952 doit = true;
4953 }
4954 break;
4955 }
4956 default: {
4957 /* keyCode does not have a corresponding traversal action */
4958 return false;
4959 }
4960 }
4961 }
4962
4963 Event event = new Event ();
4964 event.character = character;
4965 event.detail = traversal;
4966 event.doit = doit;
4967 event.keyCode = keyCode;
4968 event.keyLocation = keyLocation;
4969 event.stateMask = stateMask;
4970 Shell shell = getShell ();
4971
4972 boolean all = false;
4973 switch (traversal) {
4974 case SWT.TRAVERSE_ESCAPE:
4975 case SWT.TRAVERSE_RETURN:
4976 case SWT.TRAVERSE_PAGE_NEXT:
4977 case SWT.TRAVERSE_PAGE_PREVIOUS: {
4978 all = true;
4979 // FALL THROUGH
4980 }
4981 case SWT.TRAVERSE_ARROW_NEXT:
4982 case SWT.TRAVERSE_ARROW_PREVIOUS:
4983 case SWT.TRAVERSE_TAB_NEXT:
4984 case SWT.TRAVERSE_TAB_PREVIOUS: {
4985 /* traversal is a valid traversal action */
4986 break;
4987 }
4988 case SWT.TRAVERSE_MNEMONIC: /* not supported on OS X */
4989 // FALL THROUGH
4990 default: {
4991 /* traversal is not a valid traversal action */
4992 return false;
4993 }
4994 }
4995
4996 Control control = this;
4997 do {
4998 if (control.traverse (event)) return true;
4999 if (!event.doit && control.hooks (SWT.Traverse)) return false;
5000 if (control == shell) return false;
5001 control = control.parent;
5002 } while (all && control != null);
5003 return false;
5004 }
5005
5006 /**
5007 * Based on the argument, perform one of the expected platform
5008 * traversal action. The argument should be one of the constants:
5009 * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
5010 * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
5011 * <code>SWT.TRAVERSE_ARROW_NEXT</code>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
5012 * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_PREVIOUS</code>.
5013 *
5014 * @param traversal the type of traversal
5015 * @return true if the traversal succeeded
5016 *
5017 * @exception SWTException <ul>
5018 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
5019 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
5020 * </ul>
5021 */
traverse(int traversal)5022 public boolean traverse (int traversal) {
5023 checkWidget();
5024 Event event = new Event ();
5025 event.doit = true;
5026 event.detail = traversal;
5027 return traverse (event);
5028 }
5029
traverse(Event event)5030 boolean traverse (Event event) {
5031 sendEvent (SWT.Traverse, event);
5032 if (isDisposed ()) return true;
5033 if (!event.doit) return false;
5034 switch (event.detail) {
5035 case SWT.TRAVERSE_NONE: return true;
5036 case SWT.TRAVERSE_ESCAPE: return traverseEscape ();
5037 case SWT.TRAVERSE_RETURN: return traverseReturn ();
5038 case SWT.TRAVERSE_TAB_NEXT: return traverseGroup (true);
5039 case SWT.TRAVERSE_TAB_PREVIOUS: return traverseGroup (false);
5040 case SWT.TRAVERSE_ARROW_NEXT: return traverseItem (true);
5041 case SWT.TRAVERSE_ARROW_PREVIOUS: return traverseItem (false);
5042 case SWT.TRAVERSE_MNEMONIC: return traverseMnemonic (event);
5043 case SWT.TRAVERSE_PAGE_NEXT: return traversePage (true);
5044 case SWT.TRAVERSE_PAGE_PREVIOUS: return traversePage (false);
5045 }
5046 return false;
5047 }
5048
traverseEscape()5049 boolean traverseEscape () {
5050 return false;
5051 }
5052
traverseGroup(boolean next)5053 boolean traverseGroup (boolean next) {
5054 Control root = computeTabRoot ();
5055 Widget group = computeTabGroup ();
5056 Widget [] list = root.computeTabList ();
5057 int length = list.length;
5058 int index = 0;
5059 while (index < length) {
5060 if (list [index] == group) break;
5061 index++;
5062 }
5063 /*
5064 * It is possible (but unlikely), that application
5065 * code could have disposed the widget in focus in
5066 * or out events. Ensure that a disposed widget is
5067 * not accessed.
5068 */
5069 if (index == length) return false;
5070 int start = index, offset = (next) ? 1 : -1;
5071 while ((index = ((index + offset + length) % length)) != start) {
5072 Widget widget = list [index];
5073 if (!widget.isDisposed () && widget.setTabGroupFocus ()) {
5074 return true;
5075 }
5076 }
5077 if (group.isDisposed ()) return false;
5078 return group.setTabGroupFocus ();
5079 }
5080
traverseItem(boolean next)5081 boolean traverseItem (boolean next) {
5082 Control [] children = parent._getChildren ();
5083 int length = children.length;
5084 int index = 0;
5085 while (index < length) {
5086 if (children [index] == this) break;
5087 index++;
5088 }
5089 /*
5090 * It is possible (but unlikely), that application
5091 * code could have disposed the widget in focus in
5092 * or out events. Ensure that a disposed widget is
5093 * not accessed.
5094 */
5095 if (index == length) return false;
5096 int start = index, offset = (next) ? 1 : -1;
5097 while ((index = (index + offset + length) % length) != start) {
5098 Control child = children [index];
5099 if (!child.isDisposed () && child.isTabItem ()) {
5100 if (child.setTabItemFocus ()) return true;
5101 }
5102 }
5103 return false;
5104 }
5105
traverseReturn()5106 boolean traverseReturn () {
5107 return false;
5108 }
5109
traversePage(boolean next)5110 boolean traversePage (boolean next) {
5111 return false;
5112 }
5113
traverseMnemonic(Event event)5114 boolean traverseMnemonic (Event event) {
5115 return false;
5116 }
5117
5118 /**
5119 * Forces all outstanding paint requests for the widget
5120 * to be processed before this method returns. If there
5121 * are no outstanding paint request, this method does
5122 * nothing.
5123 * <p>
5124 * Note: This method does not cause a redraw.
5125 * </p>
5126 *
5127 * @exception SWTException <ul>
5128 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
5129 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
5130 * </ul>
5131 *
5132 * @see #redraw()
5133 * @see #redraw(int, int, int, int, boolean)
5134 * @see PaintListener
5135 * @see SWT#Paint
5136 */
update()5137 public void update () {
5138 checkWidget();
5139 update (false);
5140 }
5141
update(boolean all)5142 boolean update (boolean all) {
5143 if (NSGraphicsContext.currentContext() == null) {
5144 if (!view.lockFocusIfCanDraw()) {
5145 return false;
5146 }
5147 boolean contextAvailableAfterLockFocus = NSGraphicsContext.currentContext() != null;
5148 view.unlockFocus();
5149 if (!contextAvailableAfterLockFocus) {
5150 /*
5151 * If linked against macOS 10.14 SDK, or when native dark mode support is
5152 * enabled via Info.plist, views are displayed using Core Animation and drawing
5153 * is only possible, when cocoa invokes drawRect of a dirty view (which it does
5154 * by a run loop observer invoked during calls of
5155 * NSApplication#nextEventMatchingMask, only after more than approx. 10ms have
5156 * passed since the last redraw).
5157 */
5158 return false;
5159 }
5160 }
5161 // checkWidget();
5162 NSArray isPainting = display.isPainting;
5163 if (isPainting.containsObject(view)) return false;
5164 for (int i = 0, length = (int)isPainting.count(); i < length; i++) {
5165 NSView view = new NSView(isPainting.objectAtIndex(i));
5166 if (view.isDescendantOf(this.view)) return false;
5167 }
5168 if (isResizing()) return false;
5169 Shell shell = getShell();
5170 NSWindow window = shell.deferFlushing && shell.scrolling ? view.window() : null;
5171 try {
5172 if (window != null) {
5173 window.retain();
5174 window.disableFlushWindow();
5175 }
5176 //TODO - not all
5177 view.displayIfNeeded ();
5178 } finally {
5179 if (window != null) {
5180 window.enableFlushWindow();
5181 window.release();
5182 }
5183 }
5184 return true;
5185 }
5186
updateBackgroundColor()5187 void updateBackgroundColor () {
5188 Control control = findBackgroundControl ();
5189 if (control == null) control = this;
5190 double [] color = control.background != null ? control.background : control.defaultBackground().handle;
5191 NSColor nsColor = NSColor.colorWithDeviceRed(color[0], color[1], color[2], color[3]);
5192 setBackgroundColor (nsColor);
5193 }
5194
updateBackgroundImage()5195 void updateBackgroundImage () {
5196 Control control = findBackgroundControl ();
5197 Image image = control != null ? control.backgroundImage : backgroundImage;
5198 setBackgroundImage (image != null ? image.handle : null);
5199 }
5200
updateBackgroundMode()5201 void updateBackgroundMode () {
5202 int oldState = state & PARENT_BACKGROUND;
5203 checkBackground ();
5204 if (oldState != (state & PARENT_BACKGROUND)) {
5205 setBackground ();
5206 }
5207 }
5208
5209 @Override
resetCursorRects(long id, long sel)5210 void resetCursorRects (long id, long sel) {
5211 if (isEnabled ()) callSuper (id, sel);
5212 }
5213
5214 @Override
updateTrackingAreas(long id, long sel)5215 void updateTrackingAreas (long id, long sel) {
5216 if (isEnabled ()) callSuper (id, sel);
5217 }
5218
updateCursorRects(boolean enabled)5219 void updateCursorRects (boolean enabled) {
5220 updateCursorRects (enabled, view);
5221 }
5222
updateCursorRects(boolean enabled, NSView widget)5223 void updateCursorRects (boolean enabled, NSView widget) {
5224 if (enabled) {
5225 widget.resetCursorRects ();
5226 widget.updateTrackingAreas ();
5227 } else {
5228 widget.discardCursorRects ();
5229 NSArray areas = widget.trackingAreas ();
5230 for (int i = 0; i < areas.count(); i++) {
5231 widget.removeTrackingArea (new NSTrackingArea (areas.objectAtIndex (i)));
5232 }
5233 }
5234 }
5235
updateLayout(boolean all)5236 void updateLayout (boolean all) {
5237 /* Do nothing */
5238 }
5239
calcDiff(double component, double factor, boolean wantDarker)5240 static double calcDiff (double component, double factor, boolean wantDarker) {
5241 if (wantDarker) {
5242 return component * -1 * factor;
5243 } else {
5244 return (1f - component) * factor;
5245 }
5246 }
5247
getLighterOrDarkerColor(double [] pixel, double factor, boolean wantDarker)5248 static double [] getLighterOrDarkerColor (double [] pixel, double factor, boolean wantDarker) {
5249 double red = pixel[0];
5250 double green = pixel[1];
5251 double blue = pixel[2];
5252 red += calcDiff(red, factor, wantDarker);
5253 green += calcDiff(green, factor, wantDarker);
5254 blue += calcDiff(blue, factor, wantDarker);
5255 return new double [] { red, green, blue, pixel[3] };
5256 }
5257
5258 /**
5259 * @return luma according to ITU BT.709: Y = 0.2126 R + 0.7152 G + 0.0722 B
5260 */
luma(double[] rgbColor)5261 static double luma (double[] rgbColor) {
5262 return 0.2126f * rgbColor[0] + 0.7152f * rgbColor[1] + 0.0722f * rgbColor[2];
5263 }
5264 }
5265