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.modeling.ui.diagramEditor;
14 import java.awt.geom.Point2D;
15 import java.awt.geom.Rectangle2D;
16 import java.util.function.Consumer;
18 import org.eclipse.jface.action.IStatusLineManager;
19 import org.eclipse.jface.resource.ImageDescriptor;
20 import org.eclipse.jface.resource.JFaceResources;
21 import org.eclipse.jface.resource.ResourceManager;
22 import org.eclipse.swt.graphics.Image;
23 import org.eclipse.swt.widgets.Control;
24 import org.eclipse.swt.widgets.Display;
25 import org.eclipse.ui.IWorkbenchPart;
26 import org.simantics.Simantics;
27 import org.simantics.databoard.util.ObjectUtils;
28 import org.simantics.db.ReadGraph;
29 import org.simantics.db.common.procedure.adapter.ProcedureAdapter;
30 import org.simantics.db.common.request.BinaryRead;
31 import org.simantics.db.exception.DatabaseException;
32 import org.simantics.g2d.canvas.ICanvasContext;
33 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
34 import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
35 import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;
36 import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil;
37 import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo;
38 import org.simantics.g2d.participant.TransformUtil;
39 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
40 import org.simantics.scenegraph.g2d.events.KeyEvent;
41 import org.simantics.scenegraph.g2d.events.KeyEvent.KeyPressedEvent;
42 import org.simantics.scenegraph.g2d.events.MouseEvent;
43 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
44 import org.simantics.utils.datastructures.hints.IHintContext.Key;
45 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
46 import org.simantics.utils.ui.ErrorLogger;
47 import org.simantics.utils.ui.SWTUtils;
48 import org.simantics.utils.ui.workbench.WorkbenchUtils;
51 * Shows information about the terminal under the mouse in the Workbench status
54 * @author Tuukka Lehtonen
56 public class TerminalInformer extends AbstractDiagramParticipant {
58 public static interface TerminalNamingStrategy {
59 String getName(ReadGraph graph, TerminalInfo info) throws DatabaseException;
63 * If this hint is not set or set to <code>false</code>, this participant
64 * will show terminal information in the status bar.
66 public static final Key TERMINAL_INFO_DISABLED = new KeyOf(Boolean.class);
69 protected PointerInteractor pointerInteractor;
72 transient Display display;
73 IStatusLineManager statusLine;
74 ImageDescriptor currentImage;
79 Point2D p1 = new Point2D.Double();
80 Point2D p2 = new Point2D.Double();
81 Rectangle2D rect = new Rectangle2D.Double();
82 String viewingMessage;
84 final TerminalNamingStrategy terminalNamingStrategy;
87 * @param parentControl
88 * @param resourceManager deprecated argument, use <code>null</code>
90 * @param terminalNamingStrategy
92 public TerminalInformer(Control parentControl, ResourceManager resourceManager, IStatusLineManager statusLine, TerminalNamingStrategy terminalNamingStrategy) {
93 this.control = parentControl;
94 this.statusLine = statusLine;
95 this.terminalNamingStrategy = terminalNamingStrategy;
99 public void removedFromContext(ICanvasContext ctx) {
100 super.removedFromContext(ctx);
102 final IStatusLineManager statusLine = this.statusLine;
103 if (display != null && statusLine != null) {
104 SWTUtils.asyncExec(display, new Runnable() {
107 if (statusLine != null) {
108 statusLine.setMessage(null, null);
109 statusLine.setErrorMessage(null, null);
111 if (currentImage != null) {
112 JFaceResources.getResources().destroyImage(currentImage);
119 public boolean infoDisabled() {
120 return Boolean.TRUE.equals(getHint(TERMINAL_INFO_DISABLED));
123 private boolean infoEvent(MouseMovedEvent me) {
124 return (me.stateMask & MouseEvent.CTRL_MASK) != 0;
127 private boolean infoEvent(KeyEvent ke) {
128 return ke.keyCode == java.awt.event.KeyEvent.VK_CONTROL && (ke instanceof KeyPressedEvent);
131 @EventHandler(priority = 0)
132 public boolean handleKeys(KeyEvent ke) {
133 if (infoDisabled() || !infoEvent(ke)) {
142 @EventHandler(priority = 0)
143 public boolean handleMove(MouseMovedEvent me) {
144 double pickDist = pointerInteractor.getPickDistance();
145 p1.setLocation(me.controlPosition.getX() - pickDist, me.controlPosition.getY() - pickDist);
146 p2.setLocation(me.controlPosition.getX() + pickDist, me.controlPosition.getY() + pickDist);
147 util.controlToCanvas(p1, p1);
148 util.controlToCanvas(p2, p2);
149 rect.setFrameFromDiagonal(p1, p2);
151 if (infoDisabled() || !infoEvent(me)) {
161 private void createMessage(TerminalInfo terminal, final Consumer<String> callback) {
162 Simantics.getSession().asyncRequest(new TerminalInfoMessage(terminal, terminalNamingStrategy), new ProcedureAdapter<String>() {
164 public void exception(Throwable t) {
165 ErrorLogger.defaultLogError(t);
168 public void execute(String result) {
169 callback.accept(result);
174 private void pickRect(Rectangle2D rect) {
175 TerminalInfo terminal = TerminalUtil.pickTerminal(getContext(), diagram, rect);
176 if (terminal != null) {
177 createMessage(terminal, message -> setMessage(null, message));
183 private void setMessage(String message) {
184 setMessage(null, message);
187 private void setMessage(final ImageDescriptor imageDescriptor, String _message) {
188 // Empty message equals no message.
189 if (_message != null && _message.isEmpty())
191 final String message = _message;
193 if (viewingMessage == null && message == null)
195 if (ObjectUtils.objectEquals(viewingMessage, message))
198 this.viewingMessage = message;
200 SWTUtils.asyncExec(control, new Runnable() {
203 if (control.isDisposed())
205 display = control.getDisplay();
208 ResourceManager rm = JFaceResources.getResources();
209 if (imageDescriptor != null) {
210 if (imageDescriptor.equals(TerminalInformer.this.currentImage)) {
211 img = (Image) rm.find(imageDescriptor);
213 img = (Image) rm.createImage(imageDescriptor);
214 currentImage = imageDescriptor;
217 if (currentImage != null) {
218 rm.destroyImage(currentImage);
223 IStatusLineManager statusLine = getStatusLine();
224 if (statusLine != null) {
225 statusLine.setMessage(img, message);
226 statusLine.setErrorMessage(null);
232 static class TerminalInfoMessage extends BinaryRead<TerminalInfo, TerminalNamingStrategy, String> {
233 public TerminalInfoMessage(TerminalInfo info, TerminalNamingStrategy strategy) {
234 super(info, strategy);
237 public String perform(ReadGraph graph) throws DatabaseException {
238 return parameter2.getName(graph, parameter);
242 protected IStatusLineManager getStatusLine() {
243 IWorkbenchPart activePart = WorkbenchUtils.getActiveWorkbenchPart();
244 if (activePart != null) {
245 TerminalInformer.this.statusLine = statusLine = WorkbenchUtils.getStatusLine(activePart);