Project

General

Profile

Download (15.9 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.gef.internal.ui.palette.editparts;
12

    
13
import org.eclipse.swt.accessibility.ACC;
14
import org.eclipse.swt.accessibility.AccessibleControlEvent;
15
import org.eclipse.swt.accessibility.AccessibleEvent;
16
import org.eclipse.swt.dnd.DragSourceEvent;
17
import org.eclipse.swt.graphics.Image;
18
import org.eclipse.swt.graphics.Point;
19

    
20
import org.eclipse.ui.IMemento;
21

    
22
import org.eclipse.draw2d.ActionEvent;
23
import org.eclipse.draw2d.ActionListener;
24
import org.eclipse.draw2d.Border;
25
import org.eclipse.draw2d.ButtonBorder;
26
import org.eclipse.draw2d.ButtonModel;
27
import org.eclipse.draw2d.Clickable;
28
import org.eclipse.draw2d.ColorConstants;
29
import org.eclipse.draw2d.Graphics;
30
import org.eclipse.draw2d.IFigure;
31
import org.eclipse.draw2d.MarginBorder;
32
import org.eclipse.draw2d.Toggle;
33
import org.eclipse.draw2d.geometry.Insets;
34
import org.eclipse.draw2d.geometry.Rectangle;
35
import org.eclipse.draw2d.rap.swt.SWT;
36

    
37
import org.eclipse.gef.AccessibleEditPart;
38
import org.eclipse.gef.DragTracker;
39
import org.eclipse.gef.Request;
40
import org.eclipse.gef.RequestConstants;
41
import org.eclipse.gef.internal.ui.palette.PaletteColorUtil;
42
import org.eclipse.gef.palette.PaletteEntry;
43
import org.eclipse.gef.palette.PaletteStack;
44
import org.eclipse.gef.palette.ToolEntry;
45
import org.eclipse.gef.ui.palette.PaletteViewerPreferences;
46
import org.eclipse.gef.ui.palette.editparts.IPinnableEditPart;
47
import org.eclipse.gef.ui.palette.editparts.PaletteEditPart;
48

    
49
public class ToolEntryEditPart extends PaletteEditPart {
50

    
51
	class MenuTimer implements Runnable {
52
		public static final int MENU_TIMER_DELAY = 400;
53

    
54
		private boolean enabled = true;
55

    
56
		public void disable() {
57
			enabled = false;
58
		}
59

    
60
		public void run() {
61
			if (enabled) {
62
				getButtonModel().setArmed(false);
63
				getButtonModel().setPressed(false);
64
				((IPaletteStackEditPart) getParent()).openMenu();
65
				getViewer().getEditDomain().loadDefaultTool();
66
			}
67
		}
68
	}
69

    
70
	abstract class ToggleButtonTracker extends SingleSelectionTracker {
71
		private MenuTimer timer = null;
72

    
73
		protected void enableTimer() {
74
			timer = new MenuTimer();
75
			getViewer().getControl().getDisplay()
76
					.timerExec(MenuTimer.MENU_TIMER_DELAY, timer);
77
		}
78

    
79
		protected void disableTimer() {
80
			if (timer != null) {
81
				timer.disable();
82
				timer = null;
83
			}
84
		}
85

    
86
		protected boolean handleButtonDown(int button) {
87
			if (getParent() instanceof IPaletteStackEditPart)
88
				enableTimer();
89

    
90
			if (button == 2 && isInState(STATE_INITIAL))
91
				performConditionalSelection();
92
			super.handleButtonDown(button);
93
			if (button == 1) {
94
				getFigure().internalGetEventDispatcher().requestRemoveFocus(
95
						getFigure());
96
				getButtonModel().setArmed(true);
97
				getButtonModel().setPressed(true);
98
			}
99
			return true;
100
		}
101

    
102
		protected boolean handleDrag() {
103
			org.eclipse.draw2d.geometry.Point point = getLocation().getCopy();
104
			getFigure().translateToRelative(point);
105
			if (!getFigure().containsPoint(point)) {
106
				getButtonModel().setArmed(false);
107
				getButtonModel().setMouseOver(false);
108
				disableTimer();
109
			} else {
110
				getButtonModel().setArmed(true);
111
				getButtonModel().setMouseOver(true);
112
			}
113
			return true;
114
		}
115

    
116
		protected boolean handleNativeDragFinished(DragSourceEvent event) {
117
			getPaletteViewer().setActiveTool(null);
118
			return true;
119
		}
120
	}
121

    
122
	class GTKToggleButtonTracker extends ToggleButtonTracker {
123
		int gtkState = 0;
124

    
125
		public void deactivate() {
126
			disableTimer();
127
			super.deactivate();
128
		}
129

    
130
		protected boolean handleButtonUp(int button) {
131
			disableTimer();
132

    
133
			// Workaround for Bug 96351. It should be removed when Bug 35585 is
134
			// fixed.
135
			if (gtkState == 1) {
136
				handleNativeDragFinished(null);
137
				return true;
138
			}
139

    
140
			if (button == 1) {
141
				getButtonModel().setPressed(false);
142
				getButtonModel().setArmed(false);
143
			}
144
			return super.handleButtonUp(button);
145
		}
146

    
147
		protected boolean handleNativeDragStarted(DragSourceEvent event) {
148
			disableTimer();
149
			gtkState = 1;
150
			return true;
151
		}
152
	}
153

    
154
	class OtherToggleButtonTracker extends ToggleButtonTracker {
155

    
156
		private static final int WIN_THRESHOLD = 3;
157

    
158
		private Point mouseDownLoc = null;
159

    
160
		public void deactivate() {
161
			disableTimer();
162
			getButtonModel().setPressed(false);
163
			getButtonModel().setArmed(false);
164
			super.deactivate();
165
		}
166

    
167
		protected boolean handleButtonDown(int button) {
168
			mouseDownLoc = new Point(getLocation().x, getLocation().y);
169
			return super.handleButtonDown(button);
170
		}
171

    
172
		protected boolean handleButtonUp(int button) {
173
			disableTimer();
174

    
175
			if (button == 1) {
176
				getButtonModel().setPressed(false);
177
				getButtonModel().setArmed(false);
178
			}
179
			return super.handleButtonUp(button);
180
		}
181

    
182
		protected boolean handleNativeDragStarted(DragSourceEvent event) {
183
			disableTimer();
184

    
185
			// win hack because button down is delayed
186
			if (getParent() instanceof IPaletteStackEditPart
187
					&& SWT.getPlatform().equals("win32")) { //$NON-NLS-1$
188
				Point nds = getPaletteViewer().getControl().toControl(
189
						event.display.getCursorLocation());
190
				if (mouseDownLoc != null
191
						&& (Math.abs(nds.x - mouseDownLoc.x) + Math.abs(nds.y
192
								- mouseDownLoc.y)) < WIN_THRESHOLD) {
193
					getButtonModel().setArmed(false);
194
					getButtonModel().setPressed(false);
195
					((IPaletteStackEditPart) getParent()).openMenu();
196
					getViewer().getEditDomain().loadDefaultTool();
197
					event.doit = false;
198
					return false;
199
				}
200
			}
201

    
202
			getButtonModel().setPressed(false);
203
			getButtonModel().setArmed(false);
204
			return true;
205
		}
206
	}
207

    
208
	/**
209
	 * The figure for for a <code>ToolEntryEditPart</code>.
210
	 */
211
	class ToolEntryToggle extends Toggle {
212

    
213
		private boolean showHoverFeedback = false;
214

    
215
		ToolEntryToggle(IFigure contents) {
216
			super(contents);
217
			setOpaque(false);
218
			setEnabled(true);
219
			if (isToolbarItem()) {
220
				setStyle(Clickable.STYLE_BUTTON | Clickable.STYLE_TOGGLE);
221
				setBorder(TOOLBAR_ITEM_BORDER);
222
			}
223
		}
224

    
225
		public boolean containsPoint(int x, int y) {
226
			Rectangle rect = getBounds().getCopy();
227
			if (customLabel.getBorder() == ICON_BORDER) {
228
				rect.width -= PinnablePaletteStackFigure.ARROW_WIDTH;
229
			} else if (customLabel.getBorder() == LIST_BORDER) {
230
				rect.width -= PinnablePaletteStackFigure.ARROW_WIDTH;
231
				rect.x += PinnablePaletteStackFigure.ARROW_WIDTH;
232
			}
233
			return rect.contains(x, y);
234
		}
235

    
236
		public IFigure findMouseEventTargetAt(int x, int y) {
237
			return null;
238
		}
239

    
240
		public IFigure getToolTip() {
241
			return createToolTip();
242
		}
243

    
244
		public void setEnabled(boolean value) {
245
			super.setEnabled(value);
246
			if (isEnabled()) {
247
				setRolloverEnabled(true);
248
				if (getFlag(STYLE_BUTTON)) {
249
					setBorder(TOOLBAR_ITEM_BORDER);
250
				}
251
				setForegroundColor(null);
252
			} else {
253
				if (getFlag(STYLE_BUTTON)) {
254
					setBorder(null);
255
				}
256
				setRolloverEnabled(false);
257
				setForegroundColor(ColorConstants.gray);
258
			}
259
		}
260

    
261
		protected void paintFigure(Graphics graphics) {
262
			super.paintFigure(graphics);
263

    
264
			if (!isToolbarItem() && isEnabled() && isRolloverEnabled()) {
265
				ButtonModel model = getModel();
266

    
267
				if (model.isSelected()) {
268
					graphics.setBackgroundColor(PaletteColorUtil
269
							.getSelectedColor());
270
					graphics.fillRoundRectangle(
271
							getSelectionRectangle(getLayoutSetting(),
272
									customLabel), 3, 3);
273
				} else if (model.isMouseOver() || showHoverFeedback) {
274
					graphics.setBackgroundColor(PaletteColorUtil
275
							.getHoverColor());
276
					graphics.fillRoundRectangle(
277
							getSelectionRectangle(getLayoutSetting(),
278
									customLabel), 3, 3);
279
				}
280
			}
281
		}
282

    
283
		protected void paintBorder(Graphics graphics) {
284
			if (isEnabled()) {
285

    
286
				if (getBorder() != null)
287
					getBorder().paint(this, graphics, NO_INSETS);
288
				if (hasFocus()) {
289
					graphics.setForegroundColor(ColorConstants.black);
290
					graphics.setBackgroundColor(ColorConstants.white);
291

    
292
					Rectangle area = isToolbarItem() ? getClientArea()
293
							: getSelectionRectangle(getLayoutSetting(),
294
									customLabel);
295
					if (isStyle(STYLE_BUTTON))
296
						graphics.drawFocus(area.x, area.y, area.width,
297
								area.height);
298
					else
299
						graphics.drawFocus(area.x, area.y, area.width - 1,
300
								area.height - 1);
301
				}
302
			} else {
303
				super.paintBorder(graphics);
304
			}
305
		}
306

    
307
		/**
308
		 * Should hover feedback be shown? Allows other palette entities to
309
		 * control when the hover feedback should be shown on this tool entry.
310
		 * 
311
		 * @param showHoverFeedback
312
		 *            true if the hover feedback is to be shown; false
313
		 *            otherwise.
314
		 */
315
		public void setShowHoverFeedback(boolean showHoverFeedback) {
316
			this.showHoverFeedback = showHoverFeedback;
317
			repaint();
318
		}
319
	}
320

    
321
	private static final String ACTIVE_STATE = "active"; //$NON-NLS-1$
322
	private DetailedLabelFigure customLabel;
323

    
324
	public ToolEntryEditPart(PaletteEntry paletteEntry) {
325
		super(paletteEntry);
326
	}
327

    
328
	public Object getAdapter(Class key) {
329
		if (key == IPinnableEditPart.class) {
330
			if ((getParent() instanceof PinnablePaletteStackEditPart)
331
					&& ((PinnablePaletteStackEditPart) getParent())
332
							.canBePinned()
333
					&& ((PaletteStack) getParent().getModel()).getActiveEntry()
334
							.equals(getModel())) {
335
				return getParent();
336
			}
337
		}
338
		return super.getAdapter(key);
339
	}
340

    
341
	protected AccessibleEditPart createAccessible() {
342
		return new AccessibleGraphicalEditPart() {
343
			public void getDescription(AccessibleEvent e) {
344
				e.result = getPaletteEntry().getDescription();
345
			}
346

    
347
			public void getName(AccessibleEvent e) {
348
				e.result = getPaletteEntry().getLabel();
349
			}
350

    
351
			public void getRole(AccessibleControlEvent e) {
352
				if (getParent() instanceof IPaletteStackEditPart
353
						&& (ToolEntryEditPart.this == ((IPaletteStackEditPart) getParent())
354
								.getActiveEntry())) {
355
					e.detail = ACC.ROLE_COMBOBOX;
356
				} else {
357
					e.detail = ACC.ROLE_PUSHBUTTON;
358
				}
359
			}
360

    
361
			public void getState(AccessibleControlEvent e) {
362
				super.getState(e);
363
				if (getButtonModel().isSelected())
364
					e.detail |= ACC.STATE_CHECKED;
365
			}
366
		};
367
	}
368

    
369
	static final Border TOOLBAR_ITEM_BORDER = new ButtonBorder(
370
			ButtonBorder.SCHEMES.TOOLBAR);
371

    
372
	// The following are the insets that the bounds of the label figure should
373
	// be
374
	// cropped to paint the blue/orange select and hover feedback rectangles.
375
	static final Insets LIST_HIGHLIGHT_INSETS = new Insets(1, 5, 2, 0);
376
	static final Insets ICON_HIGHLIGHT_INSETS = new Insets(2, 1, 2, 1);
377

    
378
	// The following are the borders that go around the entire tool figure to
379
	// provide room to draw the arrow and outline of the palette stack figure if
380
	// this tool happens to appear as the active tool of a stack.
381
	static final Border LIST_BORDER = new MarginBorder(3,
382
			PinnablePaletteStackFigure.ARROW_WIDTH + 7, 4, 0);
383
	static final Border ICON_BORDER = new MarginBorder(4, 4, 3,
384
			PinnablePaletteStackFigure.ARROW_WIDTH + 4);
385

    
386
	public IFigure createFigure() {
387

    
388
		customLabel = new DetailedLabelFigure();
389
		Clickable button = new ToolEntryToggle(customLabel);
390
		button.addActionListener(new ActionListener() {
391
			public void actionPerformed(ActionEvent event) {
392
				getPaletteViewer().setActiveTool(getToolEntry());
393
			}
394
		});
395

    
396
		return button;
397
	}
398

    
399
	/**
400
	 * @see org.eclipse.gef.ui.palette.editparts.PaletteEditPart#deactivate()
401
	 */
402
	public void deactivate() {
403
		customLabel.dispose();
404
		super.deactivate();
405
	}
406

    
407
	/**
408
	 * @see org.eclipse.gef.EditPart#eraseTargetFeedback(Request)
409
	 */
410
	public void eraseTargetFeedback(Request request) {
411
		if (RequestConstants.REQ_SELECTION.equals(request.getType()))
412
			getButtonModel().setMouseOver(false);
413
		super.eraseTargetFeedback(request);
414
	}
415

    
416
	private ButtonModel getButtonModel() {
417
		Clickable c = (Clickable) getFigure();
418
		return c.getModel();
419
	}
420

    
421
	/**
422
	 * @see PaletteEditPart#getDragTracker(Request)
423
	 */
424
	public DragTracker getDragTracker(Request request) {
425
		if (SWT.getPlatform().equals("gtk")) //$NON-NLS-1$
426
			return new GTKToggleButtonTracker();
427
		else
428
			return new OtherToggleButtonTracker();
429
	}
430

    
431
	private ToolEntry getToolEntry() {
432
		return (ToolEntry) getPaletteEntry();
433
	}
434

    
435
	/**
436
	 * @see org.eclipse.gef.ui.palette.editparts.PaletteEditPart#getToolTipText()
437
	 */
438
	protected String getToolTipText() {
439
		String result = null;
440
		if (getLayoutSetting() != PaletteViewerPreferences.LAYOUT_DETAILS) {
441
			result = super.getToolTipText();
442
		}
443
		return result;
444
	}
445

    
446
	/**
447
	 * If this edit part's name is truncated in its label, the name should be
448
	 * prepended to the tooltip.
449
	 * 
450
	 * @return whether the name needs to be included in the tooltip
451
	 */
452
	protected boolean nameNeededInToolTip() {
453
		DetailedLabelFigure label = (DetailedLabelFigure) getFigure()
454
				.getChildren().get(0);
455
		return label.isNameTruncated() || super.nameNeededInToolTip();
456
	}
457

    
458
	/**
459
	 * @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()
460
	 */
461
	protected void refreshVisuals() {
462
		PaletteEntry entry = getPaletteEntry();
463

    
464
		customLabel.setName(entry.getLabel());
465
		customLabel.setDescription(entry.getDescription());
466
		if (getPreferenceSource().useLargeIcons())
467
			setImageDescriptor(entry.getLargeIcon());
468
		else
469
			setImageDescriptor(entry.getSmallIcon());
470
		int layoutMode = getLayoutSetting();
471
		customLabel.setLayoutMode(layoutMode);
472
		if (layoutMode == PaletteViewerPreferences.LAYOUT_COLUMNS) {
473
			customLabel.setBorder(ICON_BORDER);
474
		} else if (layoutMode == PaletteViewerPreferences.LAYOUT_LIST
475
				|| layoutMode == PaletteViewerPreferences.LAYOUT_DETAILS) {
476
			customLabel.setBorder(LIST_BORDER);
477
		} else if (layoutMode == PaletteViewerPreferences.LAYOUT_ICONS
478
				&& !isToolbarItem()) {
479
			customLabel.setBorder(ICON_BORDER);
480
		} else {
481
			customLabel.setBorder(null);
482
		}
483

    
484
		super.refreshVisuals();
485
	}
486

    
487
	/**
488
	 * @see org.eclipse.gef.EditPart#removeNotify()
489
	 */
490
	public void removeNotify() {
491
		if (getButtonModel().isSelected())
492
			getPaletteViewer().setActiveTool(null);
493
		super.removeNotify();
494
	}
495

    
496
	public void setToolSelected(boolean value) {
497
		getButtonModel().setSelected(value);
498
	}
499

    
500
	public void restoreState(IMemento memento) {
501
		if (new Boolean(memento.getString(ACTIVE_STATE)).booleanValue())
502
			getPaletteViewer().setActiveTool(getToolEntry());
503
		super.restoreState(memento);
504
	}
505

    
506
	public void saveState(IMemento memento) {
507
		memento.putString(ACTIVE_STATE, new Boolean(getPaletteViewer()
508
				.getActiveTool() == getToolEntry()).toString());
509
		super.saveState(memento);
510
	}
511

    
512
	/**
513
	 * @see PaletteEditPart#setImageInFigure(Image)
514
	 */
515
	protected void setImageInFigure(Image image) {
516
		DetailedLabelFigure fig = (DetailedLabelFigure) (getFigure()
517
				.getChildren().get(0));
518
		fig.setImage(image);
519
	}
520

    
521
	/**
522
	 * @see org.eclipse.gef.EditPart#setSelected(int)
523
	 */
524
	public void setSelected(int value) {
525
		super.setSelected(value);
526
		if (value == SELECTED_PRIMARY
527
				&& getPaletteViewer().getControl() != null
528
				&& !getPaletteViewer().getControl().isDisposed()
529
				&& getPaletteViewer().getControl().isFocusControl())
530
			getFigure().requestFocus();
531
	}
532

    
533
	/**
534
	 * @see org.eclipse.gef.EditPart#showTargetFeedback(Request)
535
	 */
536
	public void showTargetFeedback(Request request) {
537
		if (RequestConstants.REQ_SELECTION.equals(request.getType()))
538
			getButtonModel().setMouseOver(true);
539
		super.showTargetFeedback(request);
540
	}
541

    
542
	static Rectangle getSelectionRectangle(int layoutMode,
543
			DetailedLabelFigure labelFigure) {
544
		Rectangle rect = Rectangle.SINGLETON;
545
		rect.setBounds(labelFigure.getBounds());
546
		if (layoutMode == PaletteViewerPreferences.LAYOUT_LIST
547
				|| layoutMode == PaletteViewerPreferences.LAYOUT_DETAILS) {
548

    
549
			rect.x += PinnablePaletteStackFigure.ARROW_WIDTH;
550
			rect.width -= PinnablePaletteStackFigure.ARROW_WIDTH;
551
			int newWidth = labelFigure.getPreferredSize().width + 17;
552
			if (newWidth < rect.width) {
553
				rect.width = newWidth;
554
			}
555
			rect.crop(LIST_HIGHLIGHT_INSETS);
556
		} else {
557
			rect.width -= PinnablePaletteStackFigure.ARROW_WIDTH;
558
			rect.crop(ICON_HIGHLIGHT_INSETS);
559
		}
560
		return rect;
561
	}
562

    
563
}
(21-21/22)