Project

General

Profile

Download (16.7 KB) Statistics
| Branch: | Tag: | Revision:
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.draw2d;
12

    
13
import org.eclipse.draw2d.rap.swt.SWT;
14
import org.eclipse.swt.accessibility.AccessibleControlEvent;
15
import org.eclipse.swt.accessibility.AccessibleControlListener;
16
import org.eclipse.swt.accessibility.AccessibleEvent;
17
import org.eclipse.swt.accessibility.AccessibleListener;
18
import org.eclipse.swt.events.DisposeEvent;
19
import org.eclipse.swt.events.TraverseEvent;
20
import org.eclipse.swt.graphics.Cursor;
21
import org.eclipse.swt.widgets.Control;
22

    
23
/**
24
 * The SWTEventDispatcher provides draw2d with the ability to dispatch SWT
25
 * Events. The {@link org.eclipse.draw2d.LightweightSystem} adds SWT event
26
 * listeners on its Canvas. When the Canvas receives an SWT event, it calls the
27
 * appropriate dispatcher method in SWTEventDispatcher.
28
 */
29
public class SWTEventDispatcher extends EventDispatcher {
30

    
31
	/**
32
	 * Used to tell if any button is pressed without regard to the specific
33
	 * button.
34
	 * 
35
	 * @deprecated Use {@link SWT#BUTTON_MASK} instead.
36
	 */
37
	protected static final int ANY_BUTTON = SWT.BUTTON_MASK;
38

    
39
	private boolean figureTraverse = true;
40

    
41
	private boolean captured;
42
	private IFigure root;
43
	private IFigure mouseTarget;
44
	private IFigure cursorTarget;
45
	private IFigure focusOwner;
46
	private IFigure hoverSource;
47

    
48
	private MouseEvent currentEvent;
49
	private Cursor cursor;
50
	/** The control this dispatcher is listening to. */
51
	protected org.eclipse.swt.widgets.Control control;
52

    
53
	private ToolTipHelper toolTipHelper;
54
	private FocusTraverseManager focusManager = new FocusTraverseManager();
55

    
56
	/**
57
	 * Implements {@link EventDispatcher.AccessibilityDispatcher} but does
58
	 * nothing in the implementation.
59
	 */
60
	protected class FigureAccessibilityDispatcher extends
61
			AccessibilityDispatcher {
62
		/** @see AccessibleControlListener#getChildAtPoint(AccessibleControlEvent) */
63
		public void getChildAtPoint(AccessibleControlEvent e) {
64
		}
65

    
66
		/** @see AccessibleControlListener#getChildCount(AccessibleControlEvent) */
67
		public void getChildCount(AccessibleControlEvent e) {
68
		}
69

    
70
		/** @see AccessibleControlListener#getChildren(AccessibleControlEvent) */
71
		public void getChildren(AccessibleControlEvent e) {
72
		}
73

    
74
		/** @see AccessibleControlListener#getDefaultAction(AccessibleControlEvent) */
75
		public void getDefaultAction(AccessibleControlEvent e) {
76
		}
77

    
78
		/** @see AccessibleListener#getDescription(AccessibleEvent) */
79
		public void getDescription(AccessibleEvent e) {
80
		}
81

    
82
		/** @see AccessibleControlListener#getFocus(AccessibleControlEvent) */
83
		public void getFocus(AccessibleControlEvent e) {
84
		}
85

    
86
		/** @see AccessibleListener#getHelp(AccessibleEvent) */
87
		public void getHelp(AccessibleEvent e) {
88
		}
89

    
90
		/** @see AccessibleListener#getKeyboardShortcut(AccessibleEvent) */
91
		public void getKeyboardShortcut(AccessibleEvent e) {
92
		}
93

    
94
		/** @see AccessibleControlListener#getLocation(AccessibleControlEvent) */
95
		public void getLocation(AccessibleControlEvent e) {
96
		}
97

    
98
		/** @see AccessibleListener#getName(AccessibleEvent) */
99
		public void getName(AccessibleEvent e) {
100
		}
101

    
102
		/** @see AccessibleControlListener#getRole(AccessibleControlEvent) */
103
		public void getRole(AccessibleControlEvent e) {
104
		}
105

    
106
		/** @see AccessibleControlListener#getSelection(AccessibleControlEvent) */
107
		public void getSelection(AccessibleControlEvent e) {
108
		}
109

    
110
		/** @see AccessibleControlListener#getState(AccessibleControlEvent) */
111
		public void getState(AccessibleControlEvent e) {
112
		}
113

    
114
		/** @see AccessibleControlListener#getValue(AccessibleControlEvent) */
115
		public void getValue(AccessibleControlEvent e) {
116
		}
117
	}
118

    
119
	/**
120
	 * @see EventDispatcher#dispatchFocusGained(org.eclipse.swt.events.FocusEvent)
121
	 */
122
	public void dispatchFocusGained(org.eclipse.swt.events.FocusEvent e) {
123
		IFigure currentFocusOwner = getFocusTraverseManager()
124
				.getCurrentFocusOwner();
125

    
126
		/*
127
		 * Upon focus gained, if there is no current focus owner, set focus on
128
		 * first focusable child.
129
		 */
130
		if (currentFocusOwner == null)
131
			currentFocusOwner = getFocusTraverseManager()
132
					.getNextFocusableFigure(root, focusOwner);
133
		setFocus(currentFocusOwner);
134
	}
135

    
136
	/**
137
	 * @see EventDispatcher#dispatchFocusLost(org.eclipse.swt.events.FocusEvent)
138
	 */
139
	public void dispatchFocusLost(org.eclipse.swt.events.FocusEvent e) {
140
		setFocus(null);
141
	}
142

    
143
	/**
144
	 * @see EventDispatcher#dispatchKeyPressed(org.eclipse.swt.events.KeyEvent)
145
	 */
146
	public void dispatchKeyPressed(org.eclipse.swt.events.KeyEvent e) {
147
		if (focusOwner != null) {
148
			KeyEvent event = new KeyEvent(this, focusOwner, e);
149
			focusOwner.handleKeyPressed(event);
150
		}
151
	}
152

    
153
	/**
154
	 * @see EventDispatcher#dispatchKeyReleased(org.eclipse.swt.events.KeyEvent)
155
	 */
156
	public void dispatchKeyReleased(org.eclipse.swt.events.KeyEvent e) {
157
		if (focusOwner != null) {
158
			KeyEvent event = new KeyEvent(this, focusOwner, e);
159
			focusOwner.handleKeyReleased(event);
160
		}
161
	}
162

    
163
	/**
164
	 * @see EventDispatcher#dispatchKeyTraversed(TraverseEvent)
165
	 */
166
	public void dispatchKeyTraversed(TraverseEvent e) {
167
		if (!figureTraverse)
168
			return;
169
		IFigure nextFigure = null;
170

    
171
		if (e.detail == SWT.TRAVERSE_TAB_NEXT)
172
			nextFigure = getFocusTraverseManager().getNextFocusableFigure(root,
173
					focusOwner);
174
		else if (e.detail == SWT.TRAVERSE_TAB_PREVIOUS)
175
			nextFigure = getFocusTraverseManager().getPreviousFocusableFigure(
176
					root, focusOwner);
177

    
178
		if (nextFigure != null) {
179
			e.doit = false;
180
			setFocus(nextFigure);
181
		}
182
	}
183

    
184
	/**
185
	 * @see EventDispatcher#dispatchMouseHover(org.eclipse.swt.events.MouseEvent)
186
	 */
187
	public void dispatchMouseHover(org.eclipse.swt.events.MouseEvent me) {
188
		receive(me);
189
		if (mouseTarget != null)
190
			mouseTarget.handleMouseHover(currentEvent);
191
		/*
192
		 * Check Tooltip source. Get Tooltip source's Figure. Set that tooltip
193
		 * as the lws contents on the helper.
194
		 */
195
		if (hoverSource != null) {
196
			toolTipHelper = getToolTipHelper();
197
			IFigure tip = hoverSource.getToolTip();
198
			Control control = (Control) me.getSource();
199
			org.eclipse.swt.graphics.Point absolute;
200
			absolute = control.toDisplay(new org.eclipse.swt.graphics.Point(
201
					me.x, me.y));
202
			toolTipHelper.displayToolTipNear(hoverSource, tip, absolute.x,
203
					absolute.y);
204
		}
205
	}
206

    
207
	/**
208
	 * @see EventDispatcher#dispatchMouseDoubleClicked(org.eclipse.swt.events.MouseEvent)
209
	 */
210
	public void dispatchMouseDoubleClicked(org.eclipse.swt.events.MouseEvent me) {
211
		receive(me);
212
		if (mouseTarget != null)
213
			mouseTarget.handleMouseDoubleClicked(currentEvent);
214
	}
215

    
216
	/**
217
	 * @see EventDispatcher#dispatchMouseEntered(org.eclipse.swt.events.MouseEvent)
218
	 */
219
	public void dispatchMouseEntered(org.eclipse.swt.events.MouseEvent me) {
220
		receive(me);
221
	}
222

    
223
	/**
224
	 * @see EventDispatcher#dispatchMouseExited(org.eclipse.swt.events.MouseEvent)
225
	 */
226
	public void dispatchMouseExited(org.eclipse.swt.events.MouseEvent me) {
227
		setHoverSource(null, me);
228
		if (mouseTarget != null) {
229
			currentEvent = new MouseEvent(me.x, me.y, this, mouseTarget,
230
					me.button, me.stateMask);
231
			mouseTarget.handleMouseExited(currentEvent);
232
			releaseCapture();
233
			mouseTarget = null;
234
		}
235
	}
236

    
237
	/**
238
	 * @see EventDispatcher#dispatchMousePressed(org.eclipse.swt.events.MouseEvent)
239
	 */
240
	public void dispatchMousePressed(org.eclipse.swt.events.MouseEvent me) {
241
		receive(me);
242
		if (mouseTarget != null) {
243
			mouseTarget.handleMousePressed(currentEvent);
244
			if (currentEvent.isConsumed())
245
				setCapture(mouseTarget);
246
		}
247
	}
248

    
249
	/**
250
	 * @see EventDispatcher#dispatchMouseMoved(org.eclipse.swt.events.MouseEvent)
251
	 */
252
	public void dispatchMouseMoved(org.eclipse.swt.events.MouseEvent me) {
253
		receive(me);
254
		if (mouseTarget != null) {
255
			if ((me.stateMask & SWT.BUTTON_MASK) != 0)
256
				mouseTarget.handleMouseDragged(currentEvent);
257
			else
258
				mouseTarget.handleMouseMoved(currentEvent);
259
		}
260
	}
261

    
262
	/**
263
	 * @see EventDispatcher#dispatchMouseReleased(org.eclipse.swt.events.MouseEvent)
264
	 */
265
	public void dispatchMouseReleased(org.eclipse.swt.events.MouseEvent me) {
266
		receive(me);
267
		if (mouseTarget != null) {
268
			mouseTarget.handleMouseReleased(currentEvent);
269
		}
270
		releaseCapture();
271
		receive(me);
272
	}
273

    
274
	/**
275
	 * @see EventDispatcher#getAccessibilityDispatcher()
276
	 */
277
	protected AccessibilityDispatcher getAccessibilityDispatcher() {
278
		return null;
279
	}
280

    
281
	/**
282
	 * Returns the current mouse event.
283
	 * 
284
	 * @return the current mouse event; can be <code>null</code>
285
	 */
286
	protected MouseEvent getCurrentEvent() {
287
		return currentEvent;
288
	}
289

    
290
	private IFigure getCurrentToolTip() {
291
		if (hoverSource != null)
292
			return hoverSource.getToolTip();
293
		else
294
			return null;
295
	}
296

    
297
	/**
298
	 * Returns the figure that the cursor is over.
299
	 * 
300
	 * @return the cursor target
301
	 */
302
	protected IFigure getCursorTarget() {
303
		return cursorTarget;
304
	}
305

    
306
	/**
307
	 * Returns the ToolTipHelper used to display tooltips on hover events.
308
	 * 
309
	 * @return the ToolTipHelper
310
	 */
311
	protected ToolTipHelper getToolTipHelper() {
312
		if (toolTipHelper == null)
313
			toolTipHelper = new ToolTipHelper(control);
314
		return toolTipHelper;
315
	}
316

    
317
	/**
318
	 * Returns the FocusTraverseManager which is used to determine which figure
319
	 * will get focus when a TAB or ALT+TAB key sequence occurs.
320
	 * 
321
	 * @return the FocusTraverseManager
322
	 */
323
	protected final FocusTraverseManager getFocusTraverseManager() {
324
		if (focusManager == null) {
325
			focusManager = new FocusTraverseManager();
326
		}
327
		return focusManager;
328
	}
329

    
330
	/**
331
	 * @see EventDispatcher#getFocusOwner()
332
	 * @since 3.6
333
	 */
334
	public IFigure getFocusOwner() {
335
		return focusOwner;
336
	}
337

    
338
	/**
339
	 * Returns the figure that is the target of mouse events. This may not be
340
	 * the figure beneath the cursor because another figure may have captured
341
	 * the mouse and will continue to get mouse events until capture is
342
	 * released.
343
	 * 
344
	 * @return the mouse target
345
	 */
346
	protected IFigure getMouseTarget() {
347
		return mouseTarget;
348
	}
349

    
350
	/**
351
	 * Returns the root figure for this dispatcher.
352
	 * 
353
	 * @return the root figure
354
	 */
355
	protected IFigure getRoot() {
356
		return root;
357
	}
358

    
359
	/**
360
	 * @see EventDispatcher#isCaptured()
361
	 */
362
	public boolean isCaptured() {
363
		return captured;
364
	}
365

    
366
	private void receive(org.eclipse.swt.events.MouseEvent me) {
367
		currentEvent = null;
368
		updateFigureUnderCursor(me);
369
		int state = me.stateMask;
370
		if (captured) {
371
			if (mouseTarget != null)
372
				currentEvent = new MouseEvent(me.x, me.y, this, mouseTarget,
373
						me.button, state);
374
		} else {
375
			IFigure f = root.findMouseEventTargetAt(me.x, me.y);
376
			if (f == mouseTarget) {
377
				if (mouseTarget != null)
378
					currentEvent = new MouseEvent(me.x, me.y, this,
379
							mouseTarget, me.button, state);
380
				return;
381
			}
382
			if (mouseTarget != null) {
383
				currentEvent = new MouseEvent(me.x, me.y, this, mouseTarget,
384
						me.button, state);
385
				mouseTarget.handleMouseExited(currentEvent);
386
			}
387
			setMouseTarget(f);
388
			if (mouseTarget != null) {
389
				currentEvent = new MouseEvent(me.x, me.y, this, mouseTarget,
390
						me.button, state);
391
				mouseTarget.handleMouseEntered(currentEvent);
392
			}
393
		}
394
	}
395

    
396
	/**
397
	 * @see EventDispatcher#releaseCapture()
398
	 */
399
	protected void releaseCapture() {
400
		captured = false;
401
	}
402

    
403
	/**
404
	 * @see EventDispatcher#requestFocus(IFigure)
405
	 */
406
	public void requestFocus(IFigure fig) {
407
		setFocus(fig);
408
	}
409

    
410
	/**
411
	 * @see EventDispatcher#requestRemoveFocus(IFigure)
412
	 */
413
	public void requestRemoveFocus(IFigure fig) {
414
		if (getFocusOwner() == fig)
415
			setFocus(null);
416
		if (mouseTarget == fig)
417
			mouseTarget = null;
418
		if (cursorTarget == fig)
419
			cursorTarget = null;
420
		if (hoverSource == fig)
421
			hoverSource = null;
422
		getFocusTraverseManager().setCurrentFocusOwner(null);
423
	}
424

    
425
	/**
426
	 * @see EventDispatcher#setCapture(IFigure)
427
	 */
428
	protected void setCapture(IFigure figure) {
429
		captured = true;
430
		mouseTarget = figure;
431
	}
432

    
433
	/**
434
	 * @see EventDispatcher#setControl(Control)
435
	 */
436
	public void setControl(Control c) {
437
		if (c == control)
438
			return;
439
		if (control != null && !control.isDisposed())
440
			throw new RuntimeException(
441
					"Can not set control again once it has been set"); //$NON-NLS-1$
442
		if (c != null)
443
			c.addDisposeListener(new org.eclipse.swt.events.DisposeListener() {
444
				public void widgetDisposed(DisposeEvent e) {
445
					if (toolTipHelper != null)
446
						toolTipHelper.dispose();
447
				}
448
			});
449
		control = c;
450
	}
451

    
452
	/**
453
	 * Sets the mouse cursor.
454
	 * 
455
	 * @param c
456
	 *            the new cursor
457
	 */
458
	protected void setCursor(Cursor c) {
459
		if (c == null && cursor == null) {
460
			return;
461
		} else if ((c != cursor) || (!c.equals(cursor))) {
462
			cursor = c;
463
			if (control != null && !control.isDisposed())
464
				control.setCursor(c);
465
		}
466
	}
467

    
468
	/**
469
	 * Enables key traversal via TAB and ALT+TAB if <i>traverse</i> is
470
	 * <code>true</code>. Disables it otherwise.
471
	 * 
472
	 * @param traverse
473
	 *            whether key traversal should be enabled
474
	 */
475
	public void setEnableKeyTraversal(boolean traverse) {
476
		figureTraverse = traverse;
477
	}
478

    
479
	/**
480
	 * Sets the figure under the mouse cursor.
481
	 * 
482
	 * @param f
483
	 *            the new figure under the cursor
484
	 */
485
	protected void setFigureUnderCursor(IFigure f) {
486
		if (cursorTarget == f)
487
			return;
488
		cursorTarget = f;
489
		updateCursor();
490
	}
491

    
492
	/**
493
	 * Sets the focus figure. If the figure currently with focus is not
494
	 * <code>null</code>, {@link IFigure#handleFocusLost(FocusEvent)} is called
495
	 * on the current focused figure. If the new focus figure is not
496
	 * <code>null</code>, this will call
497
	 * {@link IFigure#handleFocusGained(FocusEvent)} on the new focused figure.
498
	 * 
499
	 * @param fig
500
	 *            the new focus figure
501
	 */
502
	protected void setFocus(IFigure fig) {
503
		if (fig == focusOwner)
504
			return;
505
		FocusEvent fe = new FocusEvent(focusOwner, fig);
506
		IFigure oldOwner = focusOwner;
507
		focusOwner = fig;
508
		if (oldOwner != null)
509
			oldOwner.handleFocusLost(fe);
510
		if (fig != null)
511
			getFocusTraverseManager().setCurrentFocusOwner(fig);
512
		if (focusOwner != null)
513
			focusOwner.handleFocusGained(fe);
514
	}
515

    
516
	/**
517
	 * Sets the figure that the mouse cursor is hovering over.
518
	 * 
519
	 * @param figure
520
	 *            the new hover source
521
	 * @param me
522
	 *            the mouse event
523
	 */
524
	protected void setHoverSource(Figure figure,
525
			org.eclipse.swt.events.MouseEvent me) {
526
		hoverSource = figure;
527
		if (figure != null) {
528
			Control control = (Control) me.getSource();
529
			org.eclipse.swt.graphics.Point absolute;
530
			absolute = control.toDisplay(new org.eclipse.swt.graphics.Point(
531
					me.x, me.y));
532
			toolTipHelper = getToolTipHelper();
533
			toolTipHelper.updateToolTip(hoverSource, getCurrentToolTip(),
534
					absolute.x, absolute.y);
535
		} else if (toolTipHelper != null) {
536
			// Update with null to clear hoverSource in ToolTipHelper
537
			toolTipHelper.updateToolTip(hoverSource, getCurrentToolTip(), me.x,
538
					me.y);
539
		}
540
	}
541

    
542
	/**
543
	 * Sets the given figure to be the target of future mouse events.
544
	 * 
545
	 * @param figure
546
	 *            the new mouse target
547
	 */
548
	protected void setMouseTarget(IFigure figure) {
549
		mouseTarget = figure;
550
	}
551

    
552
	/**
553
	 * @see EventDispatcher#setRoot(IFigure)
554
	 */
555
	public void setRoot(IFigure figure) {
556
		root = figure;
557
	}
558

    
559
	/**
560
	 * @see EventDispatcher#updateCursor()
561
	 */
562
	protected void updateCursor() {
563
		Cursor newCursor = null;
564
		if (cursorTarget != null)
565
			newCursor = cursorTarget.getCursor();
566
		setCursor(newCursor);
567
	}
568

    
569
	/**
570
	 * Updates the figure under the cursor, unless the mouse is captured, in
571
	 * which case all mouse events will be routed to the figure that captured
572
	 * the mouse.
573
	 * 
574
	 * @param me
575
	 *            the mouse event
576
	 */
577
	protected void updateFigureUnderCursor(org.eclipse.swt.events.MouseEvent me) {
578
		if (!captured) {
579
			IFigure f = root.findFigureAt(me.x, me.y);
580
			setFigureUnderCursor(f);
581
			if (cursorTarget != hoverSource)
582
				updateHoverSource(me);
583
		}
584
	}
585

    
586
	/**
587
	 * Updates the figure that will receive hover events. The hover source must
588
	 * have a tooltip. If the figure under the mouse doesn't have a tooltip set,
589
	 * this method will walk up the ancestor hierarchy until either a figure
590
	 * with a tooltip is found or it gets to the root figure.
591
	 * 
592
	 * @param me
593
	 *            the mouse event
594
	 */
595
	protected void updateHoverSource(org.eclipse.swt.events.MouseEvent me) {
596
		/*
597
		 * Derive source from figure under cursor. Set the source in
598
		 * setHoverSource(); If figure.getToolTip() is null, get parent's
599
		 * toolTip Continue parent traversal until a toolTip is found or root is
600
		 * reached.
601
		 */
602
		if (cursorTarget != null) {
603
			boolean sourceFound = false;
604
			Figure source = (Figure) cursorTarget;
605
			while (!sourceFound && source.getParent() != null) {
606
				if (source.getToolTip() != null)
607
					sourceFound = true;
608
				else
609
					source = (Figure) source.getParent();
610
			}
611
			setHoverSource(source, me);
612
		} else {
613
			setHoverSource(null, me);
614
		}
615
	}
616

    
617
}
(134-134/171)