]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/symbollibrary/ui/SymbolLibraryPage.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / symbollibrary / ui / SymbolLibraryPage.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.diagram.symbollibrary.ui;\r
13 \r
14 import org.eclipse.jface.action.GroupMarker;\r
15 import org.eclipse.jface.action.IMenuListener;\r
16 import org.eclipse.jface.action.IMenuManager;\r
17 import org.eclipse.jface.action.MenuManager;\r
18 import org.eclipse.jface.viewers.ISelection;\r
19 import org.eclipse.jface.viewers.StructuredSelection;\r
20 import org.eclipse.swt.SWT;\r
21 import org.eclipse.swt.events.DisposeEvent;\r
22 import org.eclipse.swt.events.DisposeListener;\r
23 import org.eclipse.swt.widgets.Composite;\r
24 import org.eclipse.swt.widgets.Control;\r
25 import org.eclipse.swt.widgets.Display;\r
26 import org.eclipse.swt.widgets.Menu;\r
27 import org.eclipse.ui.IWorkbenchActionConstants;\r
28 import org.eclipse.ui.part.IPageSite;\r
29 import org.eclipse.ui.part.Page;\r
30 import org.simantics.diagram.symbolcontribution.SymbolProviderFactory;\r
31 import org.simantics.diagram.symbollibrary.ISymbolGroup;\r
32 import org.simantics.diagram.symbollibrary.ISymbolItem;\r
33 import org.simantics.g2d.canvas.ICanvasContext;\r
34 import org.simantics.g2d.gallery.GalleryViewer;\r
35 import org.simantics.scenegraph.g2d.events.Event;\r
36 import org.simantics.scenegraph.g2d.events.EventTypes;\r
37 import org.simantics.scenegraph.g2d.events.IEventHandler;\r
38 import org.simantics.scenegraph.g2d.events.MouseEvent;\r
39 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonEvent;\r
40 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;\r
41 import org.simantics.utils.threads.AWTThread;\r
42 import org.simantics.utils.ui.SWTUtils;\r
43 import org.simantics.utils.ui.jface.BaseSelectionProvider;\r
44 \r
45 /**\r
46  * A page container for {@link SymbolLibraryComposite}.\r
47  * \r
48  * <p>\r
49  * Supports context menu whose ID can be set with the\r
50  * {@link #SymbolLibraryPage(SymbolProviderFactory, String)} constructor. By\r
51  * default the page registers a context menu with name\r
52  * {@value #DEFAULT_CONTEXT_MENU_ID}. The context menu selection provider\r
53  * contain one of the following:\r
54  * <ul>\r
55  * <li>StructuredSelection of {@link ISymbolItem}s if the user clicks inside a\r
56  * symbol group</li>\r
57  * <li>StructuredSelection of a single {@link ISymbolGroup} if the user clicks a\r
58  * single symbol group title</li>\r
59  * <li>Empty selection if the user clicks on empty space</li>\r
60  * </ul>\r
61  * </p>\r
62  * \r
63  * @author Tuukka Lehtonen\r
64  */\r
65 public class SymbolLibraryPage extends Page {\r
66 \r
67     public static final String         DEFAULT_CONTEXT_MENU_ID = "#SymbolLibrary";\r
68 \r
69     SymbolProviderFactory              symbolProviderFactory;\r
70 \r
71     SymbolLibraryComposite             library;\r
72 \r
73     Display                            display;\r
74 \r
75     // Context menu stuff\r
76     String                             contextMenuId           = DEFAULT_CONTEXT_MENU_ID;\r
77     MenuManager                        menuManager;\r
78     Menu                               menu;\r
79     BaseSelectionProvider              selectionProvider       = new BaseSelectionProvider();\r
80 \r
81     /**\r
82      * An internal adapter from {@link IEventHandler} to\r
83      * {@link SymbolLibraryEventHandler} interface.\r
84      * \r
85      * <p>\r
86      * Attempts to retrieve the {@link ISymbolGroup} and the selection within\r
87      * the corresponding GalleryViewer to give them to the possibly existing\r
88      * external {@link SymbolLibraryEventHandler}.\r
89      */\r
90     IEventHandler          internalEventAdapter = new IEventHandler() {\r
91         @Override\r
92         public int getEventMask() {\r
93             return EventTypes.MouseButtonMask;\r
94         }\r
95         @Override\r
96         public boolean handleEvent(Event e) {\r
97             SymbolLibraryEventHandler h = externalEventHandler;\r
98             if (h == null)\r
99                 return false;\r
100 \r
101 //            MouseButtonEvent be = (MouseButtonEvent) e;\r
102 //            System.out.println("event:");\r
103 //            System.out.println("\tcontext: " + e.getContext());\r
104 //            System.out.println("\tscreen pos: " + be.screenPosition);\r
105 \r
106             if (e.context instanceof ICanvasContext) {\r
107                 // GalleryViewer clicked\r
108                 ICanvasContext ctx = (ICanvasContext) e.context;\r
109                 GalleryViewer viewer = ctx.getHintStack().getHint(GalleryViewer.KEY_VIEWER);\r
110                 ISymbolGroup group = null;\r
111                 if (viewer != null) {\r
112                     Object input = viewer.getInput();\r
113                     if (input instanceof ISymbolGroup)\r
114                         group = (ISymbolGroup) input;\r
115                 }\r
116                 h.handleEvent(e, group, viewer);\r
117             } else if (e.context instanceof Control) {\r
118                 Control control = (Control) e.context;\r
119                 ISymbolGroup group = (ISymbolGroup) control.getData(SymbolLibraryKeys.KEY_GROUP);\r
120                 //GalleryViewer viewer = (GalleryViewer) control.getData(SymbolLibraryKeys.KEY_GALLERY);\r
121                 h.handleEvent(e, group, null);\r
122             } else {\r
123                 // empty space event\r
124                 h.handleEvent(e, null, null);\r
125             }\r
126             return false;\r
127         }\r
128     };\r
129 \r
130     /**\r
131      * Default event handler handler that shows the popup context menu of this\r
132      * SymbolLibraryPage. It will set {@link #selectionProvider} selection to\r
133      * provide Eclipse menu extensions the possibility to examine the clicked\r
134      * selection.\r
135      */\r
136     volatile SymbolLibraryEventHandler externalEventHandler = new SymbolLibraryEventHandler() {\r
137         @Override\r
138         public boolean handleEvent(Event event, final ISymbolGroup group, final GalleryViewer viewer) {\r
139             if (event instanceof MouseButtonReleasedEvent) {\r
140                 final MouseButtonEvent be = (MouseButtonEvent) event;\r
141                 if (be.button != MouseEvent.RIGHT_BUTTON)\r
142                     return false;\r
143 \r
144                 // asyncExec to AWT to get proper selection from viewer\r
145                 AWTThread.getThreadAccess().asyncExec(new Runnable() {\r
146                     @Override\r
147                     public void run() {\r
148                         ISelection _selection = StructuredSelection.EMPTY;\r
149                         if (viewer != null)\r
150                             _selection = viewer.getSelection();\r
151                         if (_selection.isEmpty() && group != null)\r
152                             _selection = new StructuredSelection(group);\r
153 \r
154                         final ISelection selection = _selection;\r
155 \r
156                         // asyncExec to SWT to show popup\r
157                         SWTUtils.asyncExec(display, new Runnable() {\r
158                             @Override\r
159                             public void run() {\r
160                                 if (library.isDisposed())\r
161                                     return;\r
162                                 selectionProvider.setAndFireNonEqualSelection(selection);\r
163                                 menu.setLocation((int) be.screenPosition.getX(), (int) be.screenPosition.getY());\r
164                                 menu.setVisible(true);\r
165                             }\r
166                         });\r
167                     }\r
168                 });\r
169             }\r
170             return false;\r
171         }\r
172     };\r
173 \r
174     public SymbolLibraryPage(SymbolProviderFactory symbolProviderFactory) {\r
175         this.symbolProviderFactory = symbolProviderFactory;\r
176     }\r
177 \r
178 //    public SymbolLibraryPage(SymbolProviderFactory symbolProviderFactory, String contextMenuId) {\r
179 //        this.symbolProviderFactory = symbolProviderFactory;\r
180 //        this.contextMenuId = contextMenuId;\r
181 //    }\r
182 \r
183     /**\r
184      * Set an event handler for the controls of this symbol library page (i.e.\r
185      * SymbolLibraryComposite) that will receive all mouse events concerning the\r
186      * symbol library controls. The events will be delivered in both SWT and AWT\r
187      * threads since controls of both toolkits are involved in the UI of the\r
188      * page. Actions performed in the event handler should be such that they are\r
189      * scheduled to run in the according thread asynchronously and not handled\r
190      * synchronously in the handler.\r
191      * \r
192      * <p>\r
193      * This mechanism allows setting only a single event handler. Handler\r
194      * chaining is possible.\r
195      * \r
196      * @param handler the handler to set for the page\r
197      * @return \r
198      * @see #getEventHandler()\r
199      */\r
200     public SymbolLibraryEventHandler setEventHandler(SymbolLibraryEventHandler handler) {\r
201         SymbolLibraryEventHandler old = this.externalEventHandler;\r
202         this.externalEventHandler = handler;\r
203         return old;\r
204     }\r
205 \r
206     public SymbolLibraryEventHandler getEventHandler() {\r
207         return externalEventHandler;\r
208     }\r
209 \r
210     @Override\r
211     public void createControl(Composite parent) {\r
212         display = parent.getDisplay();\r
213         library = new SymbolLibraryComposite(parent, SWT.NONE, symbolProviderFactory);\r
214         library.setEventHandler(internalEventAdapter);\r
215         library.addDisposeListener(new DisposeListener() {\r
216             @Override\r
217             public void widgetDisposed(DisposeEvent e) {\r
218                 library = null;\r
219             }\r
220         });\r
221 \r
222         IPageSite site = getSite();\r
223         if (site != null && contextMenuId != null) {\r
224             menuManager = new MenuManager("Symbol Library", contextMenuId);\r
225             menuManager.setRemoveAllWhenShown(true);\r
226             menuManager.addMenuListener(new IMenuListener() {\r
227                 @Override\r
228                 public void menuAboutToShow(IMenuManager manager) {\r
229                     menuManager.add(new GroupMarker(IWorkbenchActionConstants.WB_START));\r
230 \r
231 //                    // FIXME: this is debug, remove\r
232 //                    menuManager.add(new Action("Test") {\r
233 //                        @Override\r
234 //                        public void run() {\r
235 //                            System.out.println("Selection: " + selectionProvider.getSelection());\r
236 //                            MessageDialog.openInformation(null, "Symbol Library Action", selectionProvider.getSelection().toString());\r
237 //                        }\r
238 //                    });\r
239                 }\r
240             });\r
241 \r
242             menu = menuManager.createContextMenu(library);\r
243             library.setMenu(menu);\r
244             site.registerContextMenu(menuManager.getId(), menuManager, selectionProvider);\r
245         }\r
246     }\r
247 \r
248     @Override\r
249     public Control getControl() {\r
250         return library;\r
251     }\r
252 \r
253     public void setAllExpandedStates(boolean value) {\r
254         library.setAllExpandedStates(value);\r
255     }\r
256     \r
257     @Override\r
258     public void setFocus() {\r
259         if (library != null && !library.isDisposed())\r
260             library.setFocus();\r
261     }\r
262 \r
263 }\r