]> gerrit.simantics Code Review - simantics/platform.git/blob
076c97f8747ca38ed04f772698bb0ef24b0f7c57
[simantics/platform.git] /
1 /*******************************************************************************
2  * Copyright (c) 2012 Association for Decentralized Information Management in
3  * 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.diagram.monitor;
13
14 import java.util.Map;
15 import java.util.concurrent.atomic.AtomicBoolean;
16 import java.util.concurrent.atomic.AtomicReference;
17
18 import org.simantics.db.Disposable;
19 import org.simantics.db.Resource;
20 import org.simantics.db.procedure.Listener;
21 import org.simantics.diagram.elements.MonitorClass;
22 import org.simantics.g2d.canvas.Hints;
23 import org.simantics.g2d.canvas.ICanvasContext;
24 import org.simantics.g2d.diagram.IDiagram;
25 import org.simantics.g2d.element.ElementUtils;
26 import org.simantics.g2d.element.IElement;
27 import org.simantics.utils.threads.ThreadUtils;
28 import org.simantics.utils.ui.ErrorLogger;
29
30 /**
31  * @author Tuukka Lehtonen
32  */
33 public class MonitorListener implements Listener<MonitorVariableValue>, Runnable, Disposable {
34
35     private final Resource                                  element;
36     private ICanvasContext                                  canvas;
37     private IDiagram                                        diagram;
38     private final Map<String, String>                       substitutions;
39
40     private transient AtomicReference<MonitorVariableValue> lastScheduledUpdate   = null;
41     private transient AtomicBoolean                         inUpdate = null;
42
43     public MonitorListener(Resource element, ICanvasContext canvas, IDiagram diagram, Map<String, String> substitutions) {
44         if (element == null)
45             throw new NullPointerException("null element");
46         if (canvas == null)
47             throw new NullPointerException("null canvas");
48         if (diagram == null)
49             throw new NullPointerException("null diagram");
50         if (substitutions == null)
51             throw new NullPointerException("null substitutions");
52         this.element = element;
53         this.canvas = canvas;
54         this.diagram = diagram;
55         this.substitutions = substitutions;
56     }
57
58     @Override
59     public void dispose() {
60         canvas = null;
61         diagram = null;
62     }
63
64     @Override
65     public void execute(MonitorVariableValue result) {
66         // Implement some kind of throttling for AWT thread element
67         // update scheduling to keep the amount of AWT scheduling
68         // down to a minimum.
69         if (inUpdate == null)
70             inUpdate = new AtomicBoolean(false);
71         if (lastScheduledUpdate == null)
72             lastScheduledUpdate = new AtomicReference<MonitorVariableValue>();
73
74         lastScheduledUpdate.set(result);
75
76         // Don't schedule update if there was already one in the pipe.
77         synchronized (inUpdate) {
78             if (!inUpdate.compareAndSet(false, true))
79                 return;
80         }
81
82         //System.out.println(this + ".execute(" + result + "+")");
83         scheduleUpdate();
84     }
85
86     @Override
87     public void run() {
88         if (isDisposed())
89             return;
90
91         IElement el = ElementUtils.getByData(diagram, element);
92         if (el == null)
93             return;
94
95         try {
96             performUpdate(el);
97         } finally {
98             // Mark null to allow new update scheduling to commence.
99             synchronized (inUpdate) {
100                 if (lastScheduledUpdate.get() != null)
101                     scheduleUpdate();
102                 else
103                     inUpdate.set(false);
104             }
105         }
106     }
107
108     private void scheduleUpdate() {
109         ICanvasContext canvas = this.canvas;
110         if (!isDisposed())
111             ThreadUtils.asyncExec(canvas.getThreadAccess(), this);
112     }
113
114     private void performUpdate(IElement el) {
115         // Get the last updated monitor value but don't yet
116         // mark the container null to keep the outer code
117         // from scheduling new updates until this one is
118         // finished.
119         MonitorVariableValue result = lastScheduledUpdate.getAndSet(null);
120
121         String value = "<no variable>";
122         if (result != null) {
123             if (result.getValue() != null) {
124                 value = result.getValue();//ValueFormatUtil.valueStr(result.getValue(), format);
125             } else {
126                 value = "<no value>";
127             }
128             el.setHint(MonitorClass.KEY_MONITOR_COMPONENT, result.getMonitorVariable().getMonitorComponent());
129             ElementUtils.setOrRemoveHint(el, MonitorClass.KEY_MONITOR_IS_EXTERNAL, result.getMonitorVariable().isExternal());
130         } else {
131             el.removeHint(MonitorClass.KEY_MONITOR_COMPONENT);
132             el.removeHint(MonitorClass.KEY_MONITOR_IS_EXTERNAL);
133         }
134
135         substitutions.put("#v1", value);
136
137         final Map<String, String> subs = el.getHint(MonitorClass.KEY_MONITOR_SUBSTITUTIONS);
138         if (substitutions != subs)
139             el.setHint(MonitorClass.KEY_MONITOR_SUBSTITUTIONS, substitutions);
140
141         //System.out.println("REPLACING #v1: " + substitutions.get("#v1"));
142
143         el.setHint(Hints.KEY_DIRTY, Hints.VALUE_SG_DELAYED_UPDATE);
144     }
145
146     @Override
147     public void exception(Throwable t) {
148         ErrorLogger.defaultLogError(t);
149     }
150
151     @Override
152     public boolean isDisposed() {
153         return canvas == null || diagram == null || canvas.isDisposed();
154     }
155
156     @Override
157     public int hashCode() {
158         return element.hashCode();
159     }
160
161     @Override
162     public boolean equals(Object obj) {
163         if (this == obj)
164             return true;
165         if (obj == null)
166             return false;
167         if (getClass() != obj.getClass())
168             return false;
169         MonitorListener other = (MonitorListener) obj;
170         return element.equals(other.element);
171     }
172
173 }