1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.simulation.ui.handlers;
\r
14 import java.util.concurrent.ScheduledFuture;
\r
15 import java.util.concurrent.TimeUnit;
\r
17 import org.eclipse.jface.action.IContributionItem;
\r
18 import org.eclipse.jface.resource.ColorDescriptor;
\r
19 import org.eclipse.jface.resource.JFaceResources;
\r
20 import org.eclipse.jface.resource.LocalResourceManager;
\r
21 import org.eclipse.jface.resource.ResourceManager;
\r
22 import org.eclipse.swt.SWT;
\r
23 import org.eclipse.swt.graphics.Color;
\r
24 import org.eclipse.swt.graphics.Point;
\r
25 import org.eclipse.swt.graphics.RGB;
\r
26 import org.eclipse.swt.widgets.Event;
\r
27 import org.eclipse.swt.widgets.Listener;
\r
28 import org.eclipse.swt.widgets.Text;
\r
29 import org.eclipse.swt.widgets.ToolBar;
\r
30 import org.eclipse.swt.widgets.ToolItem;
\r
31 import org.eclipse.ui.PlatformUI;
\r
32 import org.eclipse.ui.actions.CompoundContributionItem;
\r
33 import org.simantics.project.IProject;
\r
34 import org.simantics.simulation.experiment.ExperimentState;
\r
35 import org.simantics.simulation.experiment.IDynamicExperiment;
\r
36 import org.simantics.simulation.experiment.IDynamicExperimentListener;
\r
37 import org.simantics.simulation.experiment.IExperiment;
\r
38 import org.simantics.simulation.experiment.IExperimentListener;
\r
39 import org.simantics.simulation.experiment.SimulationTimeUtil;
\r
40 import org.simantics.simulation.project.IExperimentManager;
\r
41 import org.simantics.simulation.project.IExperimentManagerListener;
\r
42 import org.simantics.ui.SimanticsUI;
\r
43 import org.simantics.utils.threads.ThreadUtils;
\r
46 public class TimerContribution extends CompoundContributionItem {
\r
48 private static final long LABEL_UPDATE_MIN_PERIOD_MS = 100;
\r
55 case HMS: return SECONDS;
\r
56 case SECONDS: return HMS;
\r
57 default: return HMS;
\r
62 boolean disposed = false;
\r
66 private Mode mode = Mode.HMS;
\r
67 private ToolItem ti;
\r
68 private IExperimentManager experimentManager;
\r
69 private IExperimentManagerListener experimentManagerListener;
\r
70 private ExperimentState currentState;
\r
72 private ResourceManager resourceManager;
\r
74 private static ColorDescriptor RUNNING_BG = ColorDescriptor.createFrom(new RGB(0, 128, 0));
\r
75 private static ColorDescriptor RUNNING_FG = ColorDescriptor.createFrom(new RGB(255, 255, 255));
\r
77 public TimerContribution() {
\r
78 super("org.simantics.simulation.ui.timer");
\r
82 protected IContributionItem[] getContributionItems() {
\r
83 return new IContributionItem[0];
\r
87 if (mode == Mode.SECONDS)
\r
88 return SimulationTimeUtil.formatSeconds(time);
\r
89 return SimulationTimeUtil.formatHMSS(time);
\r
93 public void fill(final ToolBar parent, final int index) {
\r
94 //System.out.println(this + "(" + System.identityHashCode(this) + ") FILL");
\r
96 IProject project = SimanticsUI.peekProject();
\r
97 if (project == null)
\r
100 IExperimentManager manager = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);
\r
101 if(manager == null)
\r
104 IExperiment active = manager.getActiveExperiment();
\r
105 if (!(active instanceof IDynamicExperiment))
\r
108 //System.out.println(this + "(" + System.identityHashCode(this) + ") got DynamicExperiment: " + active);
\r
110 ti = new ToolItem(parent, SWT.SEPARATOR, index);
\r
111 ti.setText("Simulation Timer");
\r
112 ti.setToolTipText("Simulation Timer");
\r
113 label = new Text(parent, SWT.BORDER | SWT.CENTER | SWT.READ_ONLY);
\r
114 label.setText(getTime());
\r
116 this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), label);
\r
120 Listener labelListener = new Listener() {
\r
121 boolean pressed = false;
\r
122 boolean inside = false;
\r
124 public void handleEvent(Event event) {
\r
125 switch (event.type) {
\r
126 case SWT.MouseDown:
\r
127 if (inside && (event.button == 1 || event.button == 2))
\r
131 if (pressed && inside) {
\r
136 case SWT.MouseEnter:
\r
139 case SWT.MouseExit:
\r
145 label.addListener(SWT.MouseDown, labelListener);
\r
146 label.addListener(SWT.MouseEnter, labelListener);
\r
147 label.addListener(SWT.MouseExit, labelListener);
\r
148 label.addListener(SWT.MouseUp, labelListener);
\r
150 width = label.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x;
\r
151 ti.setWidth(width);
\r
152 ti.setControl(label);
\r
154 if (currentState != null)
\r
155 setLabelVisualsByState(currentState);
\r
157 attachToExperimentManager(manager);
\r
160 private void attachToExperimentManager(final IExperimentManager manager) {
\r
161 if (experimentManager != null) {
\r
162 if (experimentManager.equals(manager))
\r
164 experimentManager.removeListener(experimentManagerListener);
\r
166 if (manager == null)
\r
169 //System.out.println(this + "(" + System.identityHashCode(this) + ") ATTACH TO EXPERIMENT MANAGER " + manager);
\r
171 experimentManagerListener = new IExperimentManagerListener() {
\r
172 IDynamicExperiment currentExperiment;
\r
173 IExperimentListener currentListener;
\r
176 public void managerDisposed() {
\r
177 manager.removeListener(this);
\r
180 public void activeExperimentUnloaded() {
\r
181 attachToExperiment(null);
\r
184 public void activeExperimentLoaded(IExperiment experiment) {
\r
185 attachToExperiment(experiment);
\r
187 synchronized void attachToExperiment(final IExperiment experiment) {
\r
188 if (currentExperiment != null) {
\r
189 currentExperiment.removeListener(currentListener);
\r
190 currentExperiment = null;
\r
191 currentListener = null;
\r
194 if (experiment == null)
\r
196 if (!(experiment instanceof IDynamicExperiment))
\r
199 IDynamicExperiment dynExp = (IDynamicExperiment) experiment;
\r
200 //System.out.println(TimerContribution.this + "(" + System.identityHashCode(TimerContribution.this) + ") ATTACH TO EXPERIMENT " + dynExp);
\r
202 IDynamicExperimentListener listener = new IDynamicExperimentListener() {
\r
203 final IExperimentListener _this = this;
\r
204 long lastUpdateTime = 0;
\r
205 ScheduledFuture<?> timedUpdate = null;
\r
206 ExperimentState lastState = null;
\r
208 public void timeChanged(double newTime) {
\r
209 //System.out.println(this + ".timeChanged: " + newTime);
\r
212 ScheduledFuture<?> f = timedUpdate;
\r
213 if (f != null && !f.isDone())
\r
216 long timeSinceLastUpdate = System.currentTimeMillis() - lastUpdateTime;
\r
218 if (timeSinceLastUpdate > LABEL_UPDATE_MIN_PERIOD_MS) {
\r
219 scheduleLabelUpdate();
\r
221 timedUpdate = ThreadUtils.getNonBlockingWorkExecutor().schedule(new Runnable() {
\r
223 public void run() {
\r
224 scheduleLabelUpdate();
\r
226 }, LABEL_UPDATE_MIN_PERIOD_MS - timeSinceLastUpdate, TimeUnit.MILLISECONDS);
\r
229 private void scheduleLabelUpdate() {
\r
230 lastUpdateTime = System.currentTimeMillis();
\r
231 timedUpdate = null;
\r
233 PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
\r
235 public void run() {
\r
236 //System.out.println("updating time label: " + time);
\r
237 //System.out.println("label isdisposed: " + label.isDisposed());
\r
238 if (!label.isDisposed())
\r
241 if (lastState != currentState) {
\r
242 setLabelVisualsByState(currentState);
\r
243 lastState = currentState;
\r
249 public void stateChanged(ExperimentState state) {
\r
250 //System.out.println("TimerContribution: state changed: " + state);
\r
251 currentState = state;
\r
252 if (state == ExperimentState.DISPOSED)
\r
253 experiment.removeListener(_this);
\r
255 scheduleLabelUpdate();
\r
258 experiment.addListener(listener);
\r
260 currentExperiment = dynExp;
\r
261 currentListener = listener;
\r
265 experimentManager = manager;
\r
266 manager.addListener(experimentManagerListener);
\r
269 private void toggleMode() {
\r
270 mode = mode.next();
\r
271 if (label.isDisposed())
\r
277 private void updateTooltip() {
\r
278 if (label.isDisposed())
\r
282 label.setToolTipText("Shows simulation time in HMS");
\r
285 label.setToolTipText("Shows simulation time in seconds");
\r
290 private void updateLabel() {
\r
291 // Try to keep selection.
\r
292 Point selection = label.getSelection();
\r
293 String oldText = label.getText();
\r
294 String newText = getTime();
\r
295 if (selection.y == oldText.length())
\r
296 selection.y = newText.length();
\r
298 selection.y = Math.min(selection.y, newText.length());
\r
300 label.setText(newText);
\r
301 label.setSelection(selection);
\r
302 int newWidth = label.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x;
\r
303 if (newWidth != width) {
\r
306 if (!ti.isDisposed()) {
\r
307 ti.setWidth(width);
\r
308 if (!ti.getParent().isDisposed())
\r
309 ti.getParent().pack();
\r
315 public void dispose() {
\r
317 //System.out.println(this + "(" + System.identityHashCode(this) + ") DISPOSE");
\r
318 attachToExperimentManager(null);
\r
322 public boolean isDynamic() {
\r
327 * @param currentState
\r
330 private void setLabelVisualsByState(ExperimentState currentState) {
\r
331 if (label.isDisposed())
\r
333 switch (currentState) {
\r
335 label.setBackground((Color) resourceManager.get(RUNNING_BG));
\r
336 label.setForeground((Color) resourceManager.get(RUNNING_FG));
\r
337 //label.setFont((Font) resourceManager.get(FontDescriptor.createFrom(label.getFont()).setStyle(SWT.BOLD)));
\r
338 label.setEnabled(true);
\r
341 label.setBackground(null);
\r
342 label.setForeground(null);
\r
343 label.setFont(null);
\r
344 label.setEnabled(true);
\r
347 label.setBackground(null);
\r
348 label.setForeground(null);
\r
349 label.setFont(null);
\r
350 label.setEnabled(false);
\r