]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/ui/SWTPopupMenuParticipant.java
Reading background color of a ICanvasContext with SCL
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / ui / SWTPopupMenuParticipant.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.ui;
13
14 import java.awt.geom.Point2D;
15
16 import org.eclipse.jface.action.GroupMarker;
17 import org.eclipse.jface.action.IMenuListener2;
18 import org.eclipse.jface.action.IMenuManager;
19 import org.eclipse.jface.action.MenuManager;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.events.MenuAdapter;
22 import org.eclipse.swt.events.MenuEvent;
23 import org.eclipse.swt.events.MenuListener;
24 import org.eclipse.swt.graphics.Point;
25 import org.eclipse.swt.widgets.Control;
26 import org.eclipse.swt.widgets.Display;
27 import org.eclipse.swt.widgets.Event;
28 import org.eclipse.swt.widgets.Listener;
29 import org.eclipse.swt.widgets.Menu;
30 import org.eclipse.swt.widgets.Widget;
31 import org.eclipse.ui.IWorkbenchActionConstants;
32 import org.eclipse.ui.IWorkbenchPartSite;
33 import org.simantics.g2d.canvas.ICanvasContext;
34 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
35 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
36 import org.simantics.g2d.diagram.DiagramHints;
37 import org.simantics.g2d.participant.TransformUtil;
38 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
39 import org.simantics.scenegraph.g2d.events.command.CommandEvent;
40 import org.simantics.scenegraph.g2d.events.command.ShowPopup;
41 import org.simantics.utils.datastructures.hints.HintListenerAdapter;
42 import org.simantics.utils.datastructures.hints.IHintContext.Key;
43 import org.simantics.utils.datastructures.hints.IHintListener;
44 import org.simantics.utils.datastructures.hints.IHintObservable;
45
46 /**
47  * A participant that initializes an SWT pop-up menu and registers it with the
48  * Eclipse workbench if a workbench site is provided. The client can specify the
49  * ID of the menu to create which allows the user to control contributions via
50  * Eclipse's declarative command mechanisms.
51  * 
52  * @author Tuukka Lehtonen
53  */
54 public class SWTPopupMenuParticipant extends AbstractCanvasParticipant {
55
56     @Dependency
57     WorkbenchSelectionProvider wbsp;
58     @Dependency
59     TransformUtil              trUtil;
60
61     IWorkbenchPartSite         site;
62     Control                    control;
63     Display                    display;
64     MenuManager                menuManager;
65     String                     menuId;
66
67     IHintListener popupListener = new HintListenerAdapter() {
68         @Override
69         public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
70             if (key == DiagramHints.SHOW_POPUP_MENU) {
71                 if (newValue != null) {
72                     Control c = control;
73                     if (display.isDisposed() || c == null || c.isDisposed())
74                         return;
75
76                     showPopup((Point2D) newValue);
77                 }
78             }
79         }
80     };
81
82     IMenuListener2 menuManagerListener = new IMenuListener2() {
83         @Override
84         public void menuAboutToShow(IMenuManager manager) {
85             manager.add(new GroupMarker(IWorkbenchActionConstants.WB_START));
86 //            manager.add(new GroupMarker(IWorkbenchActionConstants.NEW_EXT));
87 //            manager.add(new GroupMarker(IWorkbenchActionConstants.IMPORT_EXT));
88 //            manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
89 //            manager.add(new GroupMarker(IWorkbenchActionConstants.WB_END));
90         }
91         @Override
92         public void menuAboutToHide(IMenuManager manager) {
93         }
94     };
95
96     MenuListener menuListener = new MenuAdapter() {
97         @Override
98         public void menuShown(MenuEvent e) {
99                 SWTPopupMenuParticipant.this.menuShown(e);
100         }
101         @Override
102         public void menuHidden(MenuEvent e) {
103                 SWTPopupMenuParticipant.this.menuHidden(e);
104         }
105     };
106     
107     protected void menuShown(MenuEvent e) {
108         asyncExec(new Runnable() {
109             @Override
110             public void run() {
111                 final long time = System.currentTimeMillis();
112                 //System.out.println("popup shown: " + time);
113                 setHint(DiagramHints.POPUP_MENU_SHOWN, time);
114                 removeHint(DiagramHints.POPUP_MENU_HIDDEN);
115                 
116             }
117         });
118     }
119     
120     protected void menuHidden(MenuEvent e) {
121         asyncExec(new Runnable() {
122             @Override
123             public void run() {
124                 final long time = System.currentTimeMillis();
125                 //System.out.println("popup closed: " + time);
126                 removeHint(DiagramHints.POPUP_MENU_SHOWN);
127                 setHint(DiagramHints.POPUP_MENU_HIDDEN, time);
128             }
129         });
130     }
131
132     /**
133      * NOTE: this constructor must currently be invoked from the SWT display
134      * thread.
135      * 
136      * @param site
137      * @param control
138      * @param menuId
139      * @deprecated use {@link #SWTPopupMenuParticipant(IWorkbenchPartSite, Control, Display, String)} instead
140      */
141     public SWTPopupMenuParticipant(IWorkbenchPartSite site, Control control, String menuId) {
142         this(site, control, control.getDisplay(), menuId);
143     }
144
145     public SWTPopupMenuParticipant(IWorkbenchPartSite site, Control control, Display display, String menuId) {
146         super();
147         this.site = site;
148         this.control = control;
149         this.display = display;
150         this.menuId = menuId;
151         control.addListener(SWT.Dispose, new Listener() {
152
153             @Override
154             public void handleEvent(Event event) {
155                 runDispose();
156             }
157             
158         });
159     }
160
161     protected void runDispose() {
162         SWTPopupMenuParticipant.this.control = null;
163         if(menuManager != null) {
164             menuManager.removeAll();
165             menuManager.dispose();
166             menuManager = null;
167         }
168     }
169     
170     @Override
171     public void addedToContext(ICanvasContext ctx) {
172         super.addedToContext(ctx);
173
174         display.asyncExec(new Runnable() {
175             @Override
176             public void run() {
177                createControl();
178             }
179         });
180
181         getHintStack().addKeyHintListener(DiagramHints.SHOW_POPUP_MENU, popupListener);
182     }
183     
184     protected void createControl() {
185          if (control == null || control.isDisposed())
186              return;
187          menuManager = createPopupMenu();
188          if (menuManager != null) {
189              Menu menu = menuManager.createContextMenu(control);
190              menu.addMenuListener(menuListener);
191              control.setMenu(menu);
192              if (site != null) {
193                  site.registerContextMenu(menuManager.getId(), menuManager, wbsp);
194              }
195          }
196     }
197
198     @Override
199     public void removedFromContext(ICanvasContext ctx) {
200         getHintStack().removeKeyHintListener(DiagramHints.SHOW_POPUP_MENU, popupListener);
201         super.removedFromContext(ctx);
202     }
203
204     protected MenuManager createPopupMenu() {
205         final MenuManager mm = new MenuManager("Canvas Popup", menuId);
206         mm.setRemoveAllWhenShown(true);
207         mm.addMenuListener(menuManagerListener);
208         return mm;
209     }
210
211     @EventHandler(priority = 0)
212     public boolean handleCommands(CommandEvent e) {
213         if (e.command instanceof ShowPopup) {
214             showPopup(((ShowPopup) e.command).getControlPosition());
215             return true;
216         }
217         return false;
218     }
219
220     /**
221      * @param newValue
222      * @thread canvas-thread (AWT)
223      */
224     protected void showPopup(Point2D newValue) {
225         final Point2D cp = (Point2D) newValue;
226         setHint(DiagramHints.POPUP_MENU_CONTROL_POSITION, cp);
227         setHint(DiagramHints.POPUP_MENU_CANVAS_POSITION, trUtil.controlToCanvas(cp, null));
228         display.asyncExec(new Runnable() {
229             @Override
230             public void run() {
231                 if (control == null || control.isDisposed())
232                     return;
233                 
234                 Point p = control.toDisplay((int) cp.getX(), (int) cp.getY());
235                 menuManager.getMenu().setLocation(p);
236                 menuManager.getMenu().setVisible(true);
237             }
238         });
239     }
240
241 }