1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.diagram.symbollibrary.ui;
14 import org.eclipse.jface.action.GroupMarker;
15 import org.eclipse.jface.action.IMenuListener;
16 import org.eclipse.jface.action.IMenuManager;
17 import org.eclipse.jface.action.MenuManager;
18 import org.eclipse.jface.viewers.ISelection;
19 import org.eclipse.jface.viewers.StructuredSelection;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.events.DisposeEvent;
22 import org.eclipse.swt.events.DisposeListener;
23 import org.eclipse.swt.widgets.Composite;
24 import org.eclipse.swt.widgets.Control;
25 import org.eclipse.swt.widgets.Display;
26 import org.eclipse.swt.widgets.Menu;
27 import org.eclipse.ui.IWorkbenchActionConstants;
28 import org.eclipse.ui.part.IPageSite;
29 import org.eclipse.ui.part.Page;
30 import org.simantics.diagram.symbolcontribution.SymbolProviderFactory;
31 import org.simantics.diagram.symbollibrary.ISymbolGroup;
32 import org.simantics.diagram.symbollibrary.ISymbolItem;
33 import org.simantics.g2d.canvas.ICanvasContext;
34 import org.simantics.g2d.gallery.GalleryViewer;
35 import org.simantics.scenegraph.g2d.events.Event;
36 import org.simantics.scenegraph.g2d.events.EventTypes;
37 import org.simantics.scenegraph.g2d.events.IEventHandler;
38 import org.simantics.scenegraph.g2d.events.MouseEvent;
39 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonEvent;
40 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;
41 import org.simantics.utils.threads.AWTThread;
42 import org.simantics.utils.ui.SWTUtils;
43 import org.simantics.utils.ui.jface.BaseSelectionProvider;
46 * A page container for {@link SymbolLibraryComposite}.
49 * Supports context menu whose ID can be set with the
50 * {@link #SymbolLibraryPage(SymbolProviderFactory, String)} constructor. By
51 * default the page registers a context menu with name
52 * {@value #DEFAULT_CONTEXT_MENU_ID}. The context menu selection provider
53 * contain one of the following:
55 * <li>StructuredSelection of {@link ISymbolItem}s if the user clicks inside a
57 * <li>StructuredSelection of a single {@link ISymbolGroup} if the user clicks a
58 * single symbol group title</li>
59 * <li>Empty selection if the user clicks on empty space</li>
63 * @author Tuukka Lehtonen
65 public class SymbolLibraryPage extends Page {
67 public static final String DEFAULT_CONTEXT_MENU_ID = "#SymbolLibrary";
69 SymbolProviderFactory symbolProviderFactory;
71 SymbolLibraryComposite library;
76 String contextMenuId = DEFAULT_CONTEXT_MENU_ID;
77 MenuManager menuManager;
79 BaseSelectionProvider selectionProvider = new BaseSelectionProvider();
82 * An internal adapter from {@link IEventHandler} to
83 * {@link SymbolLibraryEventHandler} interface.
86 * Attempts to retrieve the {@link ISymbolGroup} and the selection within
87 * the corresponding GalleryViewer to give them to the possibly existing
88 * external {@link SymbolLibraryEventHandler}.
90 IEventHandler internalEventAdapter = new IEventHandler() {
92 public int getEventMask() {
93 return EventTypes.MouseButtonMask;
96 public boolean handleEvent(Event e) {
97 SymbolLibraryEventHandler h = externalEventHandler;
101 // MouseButtonEvent be = (MouseButtonEvent) e;
102 // System.out.println("event:");
103 // System.out.println("\tcontext: " + e.getContext());
104 // System.out.println("\tscreen pos: " + be.screenPosition);
106 if (e.context instanceof ICanvasContext) {
107 // GalleryViewer clicked
108 ICanvasContext ctx = (ICanvasContext) e.context;
109 GalleryViewer viewer = ctx.getHintStack().getHint(GalleryViewer.KEY_VIEWER);
110 ISymbolGroup group = null;
111 if (viewer != null) {
112 Object input = viewer.getInput();
113 if (input instanceof ISymbolGroup)
114 group = (ISymbolGroup) input;
116 h.handleEvent(e, group, viewer);
117 } else if (e.context instanceof Control) {
118 Control control = (Control) e.context;
119 ISymbolGroup group = (ISymbolGroup) control.getData(SymbolLibraryKeys.KEY_GROUP);
120 //GalleryViewer viewer = (GalleryViewer) control.getData(SymbolLibraryKeys.KEY_GALLERY);
121 h.handleEvent(e, group, null);
124 h.handleEvent(e, null, null);
131 * Default event handler handler that shows the popup context menu of this
132 * SymbolLibraryPage. It will set {@link #selectionProvider} selection to
133 * provide Eclipse menu extensions the possibility to examine the clicked
136 volatile SymbolLibraryEventHandler externalEventHandler = new SymbolLibraryEventHandler() {
138 public boolean handleEvent(Event event, final ISymbolGroup group, final GalleryViewer viewer) {
139 if (event instanceof MouseButtonReleasedEvent) {
140 final MouseButtonEvent be = (MouseButtonEvent) event;
141 if (be.button != MouseEvent.RIGHT_BUTTON)
144 // asyncExec to AWT to get proper selection from viewer
145 AWTThread.getThreadAccess().asyncExec(new Runnable() {
148 ISelection _selection = StructuredSelection.EMPTY;
150 _selection = viewer.getSelection();
151 if (_selection.isEmpty() && group != null)
152 _selection = new StructuredSelection(group);
154 final ISelection selection = _selection;
156 // asyncExec to SWT to show popup
157 SWTUtils.asyncExec(display, new Runnable() {
160 if (library.isDisposed())
162 selectionProvider.setAndFireNonEqualSelection(selection);
163 menu.setLocation((int) be.screenPosition.getX(), (int) be.screenPosition.getY());
164 menu.setVisible(true);
174 public SymbolLibraryPage(SymbolProviderFactory symbolProviderFactory) {
175 this.symbolProviderFactory = symbolProviderFactory;
178 // public SymbolLibraryPage(SymbolProviderFactory symbolProviderFactory, String contextMenuId) {
179 // this.symbolProviderFactory = symbolProviderFactory;
180 // this.contextMenuId = contextMenuId;
184 * Set an event handler for the controls of this symbol library page (i.e.
185 * SymbolLibraryComposite) that will receive all mouse events concerning the
186 * symbol library controls. The events will be delivered in both SWT and AWT
187 * threads since controls of both toolkits are involved in the UI of the
188 * page. Actions performed in the event handler should be such that they are
189 * scheduled to run in the according thread asynchronously and not handled
190 * synchronously in the handler.
193 * This mechanism allows setting only a single event handler. Handler
194 * chaining is possible.
196 * @param handler the handler to set for the page
198 * @see #getEventHandler()
200 public SymbolLibraryEventHandler setEventHandler(SymbolLibraryEventHandler handler) {
201 SymbolLibraryEventHandler old = this.externalEventHandler;
202 this.externalEventHandler = handler;
206 public SymbolLibraryEventHandler getEventHandler() {
207 return externalEventHandler;
211 public void createControl(Composite parent) {
212 display = parent.getDisplay();
213 library = new SymbolLibraryComposite(parent, SWT.NONE, symbolProviderFactory);
214 library.setEventHandler(internalEventAdapter);
215 library.addDisposeListener(new DisposeListener() {
217 public void widgetDisposed(DisposeEvent e) {
222 IPageSite site = getSite();
223 if (site != null && contextMenuId != null) {
224 menuManager = new MenuManager("Symbol Library", contextMenuId);
225 menuManager.setRemoveAllWhenShown(true);
226 menuManager.addMenuListener(new IMenuListener() {
228 public void menuAboutToShow(IMenuManager manager) {
229 menuManager.add(new GroupMarker(IWorkbenchActionConstants.WB_START));
231 // // FIXME: this is debug, remove
232 // menuManager.add(new Action("Test") {
234 // public void run() {
235 // System.out.println("Selection: " + selectionProvider.getSelection());
236 // MessageDialog.openInformation(null, "Symbol Library Action", selectionProvider.getSelection().toString());
242 menu = menuManager.createContextMenu(library);
243 library.setMenu(menu);
244 site.registerContextMenu(menuManager.getId(), menuManager, selectionProvider);
249 public Control getControl() {
253 public void setAllExpandedStates(boolean value) {
254 library.setAllExpandedStates(value);
258 public void setFocus() {
259 if (library != null && !library.isDisposed())