Bladeren bron

Added time scaling clocks and scale widget for simulation

Andreas Mülder 13 jaren geleden
bovenliggende
commit
a463a463b3

+ 5 - 0
plugins/org.yakindu.sct.simulation.core/src/org/yakindu/sct/simulation/core/runtime/IExecutionContext.java

@@ -17,6 +17,7 @@ import org.yakindu.sct.model.sexec.ExecutionState;
 import org.yakindu.sct.model.sgraph.RegularState;
 import org.yakindu.sct.simulation.core.runtime.impl.ExecutionEvent;
 import org.yakindu.sct.simulation.core.runtime.impl.ExecutionVariable;
+import org.yakindu.sct.simulation.core.runtime.timer.VirtualClock;
 
 /**
  * 
@@ -116,4 +117,8 @@ public interface IExecutionContext {
 	public double getTimeScaleFactor();
 
 	public void setTimeScaleFactor(double factor);
+	
+	public VirtualClock getVirtualClock();
+	
+	
 }

+ 1 - 0
plugins/org.yakindu.sct.simulation.core/src/org/yakindu/sct/simulation/core/runtime/IExecutionFacade.java

@@ -31,5 +31,6 @@ public interface IExecutionFacade {
 	public void removeTraceListener(IExecutionTraceListener listener);
 
 	public IExecutionContext getExecutionContext();
+	
 
 }

+ 7 - 0
plugins/org.yakindu.sct.simulation.core/src/org/yakindu/sct/simulation/core/runtime/impl/ExecutionContextImpl.java

@@ -23,6 +23,7 @@ import org.yakindu.sct.model.sgraph.RegularState;
 import org.yakindu.sct.model.sgraph.State;
 import org.yakindu.sct.simulation.core.runtime.ExecutionException;
 import org.yakindu.sct.simulation.core.runtime.IExecutionContext;
+import org.yakindu.sct.simulation.core.runtime.timer.VirtualClock;
 
 /**
  * 
@@ -37,12 +38,14 @@ public class ExecutionContextImpl extends AbstractExecutionContext implements
 	private List<ExecutionEvent> raisedEvents;
 	private ExecutionState[] activeStateConfig;
 	private double timeScaleFactor;
+	private VirtualClock virtualClock;
 
 	public ExecutionContextImpl() {
 		variables = new ArrayList<ExecutionVariable>();
 		declaredEvents = new ArrayList<ExecutionEvent>();
 		raisedEvents = new ArrayList<ExecutionEvent>();
 		timeScaleFactor = 1.0d;
+		virtualClock = new VirtualClock();
 		activeStateConfig = null;
 	}
 
@@ -193,4 +196,8 @@ public class ExecutionContextImpl extends AbstractExecutionContext implements
 		timeScaleFactor = factor;
 		notifyTimeScaleFactorChanged(oldFactor, factor);
 	}
+
+	public VirtualClock getVirtualClock() {
+		return virtualClock;
+	}
 }

+ 18 - 1
plugins/org.yakindu.sct.simulation.core/src/org/yakindu/sct/simulation/core/runtime/timer/VirtualClock.java

@@ -19,13 +19,18 @@ package org.yakindu.sct.simulation.core.runtime.timer;
  */
 public class VirtualClock {
 
+	//real time in ms since start of the clock
+	private long startTime;
+	//real time in ms since last factor change
+	private long realTime;
+	//virtual time in ms since last factor change
 	private long virtualTime;
 
-	private long realTime;
 
 	private double factor = 1.0d;
 
 	public void start() {
+		startTime = System.currentTimeMillis();
 		virtualTime = System.currentTimeMillis();
 		realTime = System.currentTimeMillis();
 	}
@@ -46,4 +51,16 @@ public class VirtualClock {
 		return factor;
 	}
 
+	public long getStartTime() {
+		return startTime;
+	}
+
+	public long getRealTime() {
+		return realTime;
+	}
+
+	public long getVirtualTime() {
+		return virtualTime;
+	}
+
 }

+ 12 - 12
plugins/org.yakindu.sct.simulation.core/src/org/yakindu/sct/simulation/core/runtime/timer/VirtualTimer.java

@@ -44,16 +44,13 @@ public class VirtualTimer {
 	 * The timer thread.
 	 */
 
-	private VirtualClock clock = new VirtualClock();
-	{
-		clock.start();
-	}
+	private VirtualClock clock;
 
 	public VirtualClock getClock() {
 		return clock;
 	}
 
-	private TimerThread thread = new TimerThread(queue, clock);
+	private TimerThread thread;
 	/**
 	 * This object causes the timer's task execution thread to exit gracefully
 	 * when there are no live references to the Timer object and no tasks in the
@@ -88,8 +85,8 @@ public class VirtualTimer {
 	 * @see Thread
 	 * @see #cancel()
 	 */
-	public VirtualTimer() {
-		this("Timer-" + serialNumber());
+	public VirtualTimer(VirtualClock clock) {
+		this("Timer-" + serialNumber(), clock);
 	}
 
 	/**
@@ -105,8 +102,8 @@ public class VirtualTimer {
 	 * @see Thread
 	 * @see #cancel()
 	 */
-	public VirtualTimer(boolean isDaemon) {
-		this("Timer-" + serialNumber(), isDaemon);
+	public VirtualTimer(VirtualClock clock, boolean isDaemon) {
+		this("Timer-" + serialNumber(), isDaemon, clock);
 	}
 
 	/**
@@ -121,7 +118,9 @@ public class VirtualTimer {
 	 * @see Thread#isDaemon()
 	 * @since 1.5
 	 */
-	public VirtualTimer(String name) {
+	public VirtualTimer(String name, VirtualClock clock) {
+		this.clock = clock;
+		thread = new TimerThread(queue, clock);
 		thread.setName(name);
 		thread.start();
 	}
@@ -140,7 +139,8 @@ public class VirtualTimer {
 	 * @see Thread#isDaemon()
 	 * @since 1.5
 	 */
-	public VirtualTimer(String name, boolean isDaemon) {
+	public VirtualTimer(String name, boolean isDaemon, VirtualClock clock) {
+		this.clock = clock;
 		thread.setName(name);
 		thread.setDaemon(isDaemon);
 		thread.start();
@@ -392,7 +392,7 @@ class TimerThread extends Thread {
 						}
 					}
 					if (!taskFired) {
-						//CHANGED
+						// CHANGED
 						// Task hasn't yet fired; wait
 						// queue.wait((long)((executionTime - currentTime) /
 						// clock.getFactor()));

+ 2 - 1
plugins/org.yakindu.sct.simulation.ui/META-INF/MANIFEST.MF

@@ -24,7 +24,8 @@ Require-Bundle: org.eclipse.ui,
  org.yakindu.sct.model.sexec,
  com.google.inject,
  org.eclipse.xtext.xbase.lib,
- org.eclipse.xtext.xtend2.lib
+ org.eclipse.xtext.xtend2.lib,
+ org.apache.commons.lang;bundle-version="2.4.0"
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Bundle-ActivationPolicy: lazy
 Import-Package: org.eclipse.ui.dialogs

+ 129 - 13
plugins/org.yakindu.sct.simulation.ui/src/org/yakindu/sct/simulation/ui/view/SimulationView.java

@@ -10,6 +10,7 @@
  */
 package org.yakindu.sct.simulation.ui.view;
 
+import org.apache.commons.lang.time.DurationFormatUtils;
 import org.eclipse.core.runtime.PlatformObject;
 import org.eclipse.debug.core.DebugEvent;
 import org.eclipse.debug.core.DebugPlugin;
@@ -30,12 +31,15 @@ import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Scale;
 import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.forms.widgets.FormToolkit;
 import org.eclipse.ui.forms.widgets.Section;
@@ -44,6 +48,7 @@ import org.yakindu.sct.simulation.core.debugmodel.SCTDebugTarget;
 import org.yakindu.sct.simulation.core.runtime.IExecutionContext;
 import org.yakindu.sct.simulation.core.runtime.IExecutionFacade;
 import org.yakindu.sct.simulation.core.runtime.impl.ExecutionEvent;
+import org.yakindu.sct.simulation.core.runtime.timer.VirtualClock;
 import org.yakindu.sct.simulation.ui.view.actions.CollapseAllAction;
 import org.yakindu.sct.simulation.ui.view.actions.ExpandAllAction;
 import org.yakindu.sct.simulation.ui.view.actions.HideTimeEventsAction;
@@ -62,24 +67,36 @@ public class SimulationView extends ViewPart implements IDebugContextListener,
 
 	private TreeViewer viewer;
 	private SCTDebugTarget debugTarget;
+	private Text scaleFactor;
+	private FormToolkit kit;
+	private Font font;
+	private Label lblVirtualTime;
+	private Label lblRealTime;
+	private ClockUpdater clockUpdater;
 
 	public SimulationView() {
 		DebugUITools.getDebugContextManager().addDebugContextListener(this);
 		DebugPlugin.getDefault().addDebugEventListener(this);
+		kit = new FormToolkit(Display.getDefault());
+		font = new Font(Display.getDefault(), new FontData("Courier", 10,
+				SWT.BOLD));
+		clockUpdater = new ClockUpdater();
 	}
 
 	@Override
 	public void dispose() {
+		clockUpdater.setTerminated(true);
 		super.dispose();
 		DebugUITools.getDebugContextManager().removeDebugContextListener(this);
 		DebugPlugin.getDefault().removeDebugEventListener(this);
+		font.dispose();
 	}
 
 	@Override
 	public void createPartControl(Composite parent) {
 		parent.setLayout(new FillLayout(SWT.VERTICAL));
 		createViewer(parent);
-		createTimeScalingControls(parent);
+		createTimeScalingSection(parent);
 		hookActions();
 	}
 
@@ -88,32 +105,82 @@ public class SimulationView extends ViewPart implements IDebugContextListener,
 		viewer.getTree().setFocus();
 	}
 
-	private void createTimeScalingControls(Composite parent) {
-		FormToolkit kit = new FormToolkit(Display.getDefault());
+	private void createTimeScalingSection(Composite parent) {
 		Section section = kit.createSection(parent, Section.TITLE_BAR);
-		section.setText("scaled real-time");
+		section.setText("time scaling");
 		Composite client = kit.createComposite(section);
 		client.setLayout(new GridLayout(3, false));
 		section.setClient(client);
+		createClocks(client);
+		createScalingControls(client);
+	}
+
+	private void createScalingControls(Composite client) {
+		final Scale scale = new Scale(client, SWT.NONE);
+		scale.setMinimum(1);
+		scale.setMaximum(100);
+		scale.setSelection(50);
+		scale.setPageIncrement(5);
+		scale.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				int selection = scale.getSelection();
+				if (selection > 50) {
+					selection = selection - 50;
+					scaleFactor.setText(String.valueOf(1.0d * selection));
+				} else if (selection == 50) {
+					scaleFactor.setText(String.valueOf(1.0d));
+				} else {
+					selection = 50 - selection;
+					scaleFactor.setText(String.valueOf(1.0d / selection));
+				}
+				applyScaleFactor();
+			}
+		});
+		GridDataFactory.fillDefaults().span(3, 0).applyTo(scale);
 		Label label = kit.createLabel(client, "scale factor: ");
 		GridDataFactory.fillDefaults().grab(true, false).applyTo(label);
-		final Text scaleFactor = kit.createText(client, "1.0");
+		scaleFactor = kit.createText(client, "1.0");
 		GridDataFactory.fillDefaults().grab(true, false).applyTo(scaleFactor);
-		Button setScale = kit.createButton(client, "apply", SWT.PUSH);
+		final Button setScale = kit.createButton(client, "apply", SWT.PUSH);
 		setScale.addSelectionListener(new SelectionAdapter() {
 			public void widgetSelected(SelectionEvent e) {
-				try {
-					double factor = Double.parseDouble(scaleFactor.getText());
-					IExecutionFacade facade = (IExecutionFacade) debugTarget
-							.getAdapter(IExecutionFacade.class);
-					facade.getExecutionContext().setTimeScaleFactor(factor);
-				} catch (NumberFormatException ex) {
-				}
+				applyScaleFactor();
 			}
 		});
 		GridDataFactory.fillDefaults().applyTo(setScale);
 	}
 
+	private void createClocks(Composite parent) {
+		// Virtual Clock
+		Label label = kit.createLabel(parent, "virtual time:");
+		GridDataFactory.fillDefaults().applyTo(label);
+		lblVirtualTime = new Label(parent, SWT.NONE);
+		lblVirtualTime.setFont(font);
+		lblVirtualTime.setText("00:00:00:00");
+
+		GridDataFactory.fillDefaults().grab(true, false).span(2, 0)
+				.applyTo(lblVirtualTime);
+		// Real time clock
+		Label label2 = kit.createLabel(parent, "real time:");
+		GridDataFactory.fillDefaults().applyTo(label2);
+		lblRealTime = new Label(parent, SWT.NONE);
+		lblRealTime.setFont(font);
+		lblRealTime.setText("00:00:00:00");
+		GridDataFactory.fillDefaults().grab(true, false).span(2, 0)
+				.applyTo(lblRealTime);
+
+	}
+
+	private void applyScaleFactor() {
+		try {
+			double factor = Double.parseDouble(scaleFactor.getText());
+			IExecutionFacade facade = (IExecutionFacade) debugTarget
+					.getAdapter(IExecutionFacade.class);
+			facade.getExecutionContext().setTimeScaleFactor(factor);
+		} catch (NumberFormatException ex) {
+		}
+	}
+
 	protected Viewer createViewer(Composite parent) {
 		viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL
 				| SWT.FULL_SELECTION);
@@ -163,6 +230,7 @@ public class SimulationView extends ViewPart implements IDebugContextListener,
 					&& !newTarget.isTerminated()) {
 				refreshInput(newTarget);
 				debugTarget = newTarget;
+				new Thread(clockUpdater).start();
 			}
 		}
 
@@ -180,6 +248,7 @@ public class SimulationView extends ViewPart implements IDebugContextListener,
 			Display.getDefault().asyncExec(new Runnable() {
 				public void run() {
 					viewer.setInput(null);
+					clockUpdater.setTerminated(true);
 				}
 			});
 			break;
@@ -204,4 +273,51 @@ public class SimulationView extends ViewPart implements IDebugContextListener,
 		mgr.add(hideTimeEvent);
 	}
 
+	public class ClockUpdater implements Runnable {
+
+		private static final String PATTERN = "HH:mm:ss:SS";
+		private boolean terminated = false;
+
+		public void run() {
+			while (!terminated) {
+				Display.getDefault().asyncExec(new Runnable() {
+					public void run() {
+						IExecutionFacade facade = (IExecutionFacade) debugTarget
+								.getAdapter(IExecutionFacade.class);
+						VirtualClock virtualClock = facade
+								.getExecutionContext().getVirtualClock();
+						if (lblVirtualTime != null
+								&& !lblVirtualTime.isDisposed()) {
+							String text = DurationFormatUtils.formatDuration(
+									virtualClock.getTime()
+											- virtualClock.getStartTime(),
+									PATTERN);
+							lblVirtualTime.setText(text);
+						}
+						if (lblRealTime != null && !lblRealTime.isDisposed()) {
+							String text = DurationFormatUtils.formatDuration(
+									System.currentTimeMillis()
+											- virtualClock.getStartTime(),
+									PATTERN);
+							lblRealTime.setText(text);
+						}
+					}
+				});
+				try {
+					Thread.sleep(100);
+				} catch (InterruptedException e) {
+					e.printStackTrace();
+				}
+			}
+		}
+
+		public boolean isTerminated() {
+			return terminated;
+		}
+
+		public void setTerminated(boolean terminated) {
+			this.terminated = terminated;
+		}
+	}
+
 }