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