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