]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/symbollibrary/ui/SymbolLibraryPage.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / symbollibrary / ui / SymbolLibraryPage.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.diagram.symbollibrary.ui;
13
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;
44
45 /**
46  * A page container for {@link SymbolLibraryComposite}.
47  * 
48  * <p>
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:
54  * <ul>
55  * <li>StructuredSelection of {@link ISymbolItem}s if the user clicks inside a
56  * symbol group</li>
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>
60  * </ul>
61  * </p>
62  * 
63  * @author Tuukka Lehtonen
64  */
65 public class SymbolLibraryPage extends Page {
66
67     public static final String         DEFAULT_CONTEXT_MENU_ID = "#SymbolLibrary";
68
69     SymbolProviderFactory              symbolProviderFactory;
70
71     SymbolLibraryComposite             library;
72
73     Display                            display;
74
75     // Context menu stuff
76     String                             contextMenuId           = DEFAULT_CONTEXT_MENU_ID;
77     MenuManager                        menuManager;
78     Menu                               menu;
79     BaseSelectionProvider              selectionProvider       = new BaseSelectionProvider();
80
81     /**
82      * An internal adapter from {@link IEventHandler} to
83      * {@link SymbolLibraryEventHandler} interface.
84      * 
85      * <p>
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}.
89      */
90     IEventHandler          internalEventAdapter = new IEventHandler() {
91         @Override
92         public int getEventMask() {
93             return EventTypes.MouseButtonMask;
94         }
95         @Override
96         public boolean handleEvent(Event e) {
97             SymbolLibraryEventHandler h = externalEventHandler;
98             if (h == null)
99                 return false;
100
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);
105
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;
115                 }
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);
122             } else {
123                 // empty space event
124                 h.handleEvent(e, null, null);
125             }
126             return false;
127         }
128     };
129
130     /**
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
134      * selection.
135      */
136     volatile SymbolLibraryEventHandler externalEventHandler = new SymbolLibraryEventHandler() {
137         @Override
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)
142                     return false;
143
144                 // asyncExec to AWT to get proper selection from viewer
145                 AWTThread.getThreadAccess().asyncExec(new Runnable() {
146                     @Override
147                     public void run() {
148                         ISelection _selection = StructuredSelection.EMPTY;
149                         if (viewer != null)
150                             _selection = viewer.getSelection();
151                         if (_selection.isEmpty() && group != null)
152                             _selection = new StructuredSelection(group);
153
154                         final ISelection selection = _selection;
155
156                         // asyncExec to SWT to show popup
157                         SWTUtils.asyncExec(display, new Runnable() {
158                             @Override
159                             public void run() {
160                                 if (library.isDisposed())
161                                     return;
162                                 selectionProvider.setAndFireNonEqualSelection(selection);
163                                 menu.setLocation((int) be.screenPosition.getX(), (int) be.screenPosition.getY());
164                                 menu.setVisible(true);
165                             }
166                         });
167                     }
168                 });
169             }
170             return false;
171         }
172     };
173
174     public SymbolLibraryPage(SymbolProviderFactory symbolProviderFactory) {
175         this.symbolProviderFactory = symbolProviderFactory;
176     }
177
178 //    public SymbolLibraryPage(SymbolProviderFactory symbolProviderFactory, String contextMenuId) {
179 //        this.symbolProviderFactory = symbolProviderFactory;
180 //        this.contextMenuId = contextMenuId;
181 //    }
182
183     /**
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.
191      * 
192      * <p>
193      * This mechanism allows setting only a single event handler. Handler
194      * chaining is possible.
195      * 
196      * @param handler the handler to set for the page
197      * @return 
198      * @see #getEventHandler()
199      */
200     public SymbolLibraryEventHandler setEventHandler(SymbolLibraryEventHandler handler) {
201         SymbolLibraryEventHandler old = this.externalEventHandler;
202         this.externalEventHandler = handler;
203         return old;
204     }
205
206     public SymbolLibraryEventHandler getEventHandler() {
207         return externalEventHandler;
208     }
209
210     @Override
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() {
216             @Override
217             public void widgetDisposed(DisposeEvent e) {
218                 library = null;
219             }
220         });
221
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() {
227                 @Override
228                 public void menuAboutToShow(IMenuManager manager) {
229                     menuManager.add(new GroupMarker(IWorkbenchActionConstants.WB_START));
230
231 //                    // FIXME: this is debug, remove
232 //                    menuManager.add(new Action("Test") {
233 //                        @Override
234 //                        public void run() {
235 //                            System.out.println("Selection: " + selectionProvider.getSelection());
236 //                            MessageDialog.openInformation(null, "Symbol Library Action", selectionProvider.getSelection().toString());
237 //                        }
238 //                    });
239                 }
240             });
241
242             menu = menuManager.createContextMenu(library);
243             library.setMenu(menu);
244             site.registerContextMenu(menuManager.getId(), menuManager, selectionProvider);
245         }
246     }
247
248     @Override
249     public Control getControl() {
250         return library;
251     }
252
253     public void setAllExpandedStates(boolean value) {
254         library.setAllExpandedStates(value);
255     }
256     
257     @Override
258     public void setFocus() {
259         if (library != null && !library.isDisposed())
260             library.setFocus();
261     }
262
263 }