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 '&amp;') is not displayed in a tool tip.
4333  * To display a single '&amp;' in the tool tip, the character '&amp;' 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 " (&amp;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