]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/TerminalInformer.java
Debug logging through SLF4J Logger for Expressions
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / diagramEditor / TerminalInformer.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.modeling.ui.diagramEditor;
13
14 import java.awt.geom.Point2D;
15 import java.awt.geom.Rectangle2D;
16 import java.util.function.Consumer;
17
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.databoard.util.ObjectUtils;
27 import org.simantics.db.ReadGraph;
28 import org.simantics.db.common.procedure.adapter.ProcedureAdapter;
29 import org.simantics.db.common.request.BinaryRead;
30 import org.simantics.db.exception.DatabaseException;
31 import org.simantics.g2d.canvas.ICanvasContext;
32 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
33 import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
34 import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;
35 import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil;
36 import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo;
37 import org.simantics.g2d.participant.TransformUtil;
38 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
39 import org.simantics.scenegraph.g2d.events.KeyEvent;
40 import org.simantics.scenegraph.g2d.events.KeyEvent.KeyPressedEvent;
41 import org.simantics.scenegraph.g2d.events.MouseEvent;
42 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
43 import org.simantics.ui.SimanticsUI;
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;
49
50 /**
51  * Shows information about the terminal under the mouse in the Workbench status
52  * line.
53  * 
54  * @author Tuukka Lehtonen
55  */
56 public class TerminalInformer extends AbstractDiagramParticipant {
57
58     public static interface TerminalNamingStrategy {
59         String getName(ReadGraph graph, TerminalInfo info) throws DatabaseException;
60     }
61
62     /**
63      * If this hint is not set or set to <code>false</code>, this participant
64      * will show terminal information in the status bar.
65      */
66     public static final Key TERMINAL_INFO_DISABLED = new KeyOf(Boolean.class);
67
68     @Dependency
69     protected PointerInteractor pointerInteractor;
70
71     Control                 control;
72     transient Display       display;
73     IStatusLineManager      statusLine;
74     ImageDescriptor         currentImage;
75
76     @Dependency
77     TransformUtil           util;
78
79     Point2D                 p1                     = new Point2D.Double();
80     Point2D                 p2                     = new Point2D.Double();
81     Rectangle2D             rect                   = new Rectangle2D.Double();
82     String                  viewingMessage;
83
84     final TerminalNamingStrategy terminalNamingStrategy;
85
86     /**
87      * @param parentControl
88      * @param resourceManager deprecated argument, use <code>null</code>
89      * @param statusLine
90      * @param terminalNamingStrategy
91      */
92     public TerminalInformer(Control parentControl, ResourceManager resourceManager, IStatusLineManager statusLine, TerminalNamingStrategy terminalNamingStrategy) {
93         this.control = parentControl;
94         this.statusLine = statusLine;
95         this.terminalNamingStrategy = terminalNamingStrategy;
96     }
97
98     @Override
99     public void removedFromContext(ICanvasContext ctx) {
100         super.removedFromContext(ctx);
101
102         final IStatusLineManager statusLine = this.statusLine;
103         if (display != null && statusLine != null) {
104             SWTUtils.asyncExec(display, new Runnable() {
105                 @Override
106                 public void run() {
107                     if (statusLine != null) {
108                         statusLine.setMessage(null, null);
109                         statusLine.setErrorMessage(null, null);
110                     }
111                     if (currentImage != null) {
112                         JFaceResources.getResources().destroyImage(currentImage);
113                     }
114                 }
115             });
116         }
117     }
118
119     public boolean infoDisabled() {
120         return Boolean.TRUE.equals(getHint(TERMINAL_INFO_DISABLED));
121     }
122
123     private boolean infoEvent(MouseMovedEvent me) {
124         return (me.stateMask & MouseEvent.CTRL_MASK) != 0;
125     }
126
127     private boolean infoEvent(KeyEvent ke) {
128         return ke.keyCode == java.awt.event.KeyEvent.VK_CONTROL && (ke instanceof KeyPressedEvent);
129     }
130
131     @EventHandler(priority = 0)
132     public boolean handleKeys(KeyEvent ke) {
133         if (infoDisabled() || !infoEvent(ke)) {
134             setMessage(null);
135             return false;
136         }
137
138         pickRect(rect);
139         return false;
140     }
141
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);
150
151         if (infoDisabled() || !infoEvent(me)) {
152             setMessage(null);
153             return false;
154         }
155
156         pickRect(rect);
157
158         return false;
159     }
160
161     private void createMessage(TerminalInfo terminal, final Consumer<String> callback) {
162         SimanticsUI.getSession().asyncRequest(new TerminalInfoMessage(terminal, terminalNamingStrategy), new ProcedureAdapter<String>() {
163             @Override
164             public void exception(Throwable t) {
165                 ErrorLogger.defaultLogError(t);
166             }
167             @Override
168             public void execute(String result) {
169                 callback.accept(result);
170             }
171         });
172     }
173
174     private void pickRect(Rectangle2D rect) {
175         TerminalInfo terminal = TerminalUtil.pickTerminal(diagram, rect);
176         if (terminal != null) {
177             createMessage(terminal, message -> setMessage(null, message));
178         } else {
179             setMessage(null);
180         }
181     }
182
183     private void setMessage(String message) {
184         setMessage(null, message);
185     }
186
187     private void setMessage(final ImageDescriptor imageDescriptor, String _message) {
188         // Empty message equals no message.
189         if (_message != null && _message.isEmpty())
190             _message = null;
191         final String message = _message;
192
193         if (viewingMessage == null && message == null)
194             return;
195         if (ObjectUtils.objectEquals(viewingMessage, message))
196             return;
197
198         this.viewingMessage = message;
199
200         SWTUtils.asyncExec(control, new Runnable() {
201             @Override
202             public void run() {
203                 if (control.isDisposed())
204                     return;
205                 display = control.getDisplay();
206
207                 Image img = null;
208                 ResourceManager rm = JFaceResources.getResources();
209                 if (imageDescriptor != null) {
210                     if (imageDescriptor.equals(TerminalInformer.this.currentImage)) {
211                         img = (Image) rm.find(imageDescriptor);
212                     } else {
213                         img = (Image) rm.createImage(imageDescriptor);
214                         currentImage = imageDescriptor;
215                     }
216                 } else {
217                     if (currentImage != null) {
218                         rm.destroyImage(currentImage);
219                         currentImage = null;
220                     }
221                 }
222
223                 IStatusLineManager statusLine = getStatusLine();
224                 if (statusLine != null) {
225                     statusLine.setMessage(img, message);
226                     statusLine.setErrorMessage(null);
227                 }
228             }
229         });
230     }
231
232     static class TerminalInfoMessage extends BinaryRead<TerminalInfo, TerminalNamingStrategy, String> {
233         public TerminalInfoMessage(TerminalInfo info, TerminalNamingStrategy strategy) {
234             super(info, strategy);
235         }
236         @Override
237         public String perform(ReadGraph graph) throws DatabaseException {
238             return parameter2.getName(graph, parameter);
239         }
240     }
241
242     protected IStatusLineManager getStatusLine() {
243         IWorkbenchPart activePart = WorkbenchUtils.getActiveWorkbenchPart();
244         if (activePart != null) {
245             TerminalInformer.this.statusLine = statusLine = WorkbenchUtils.getStatusLine(activePart);
246             return statusLine;
247         }
248         return null;
249     }
250
251 }