]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Controls for simulation playback
authorlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Thu, 20 Oct 2011 09:10:22 +0000 (09:10 +0000)
committerlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Thu, 20 Oct 2011 09:10:22 +0000 (09:10 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@22888 ac1ea38d-2e2b-0410-8846-a27921b304fc

22 files changed:
org.simantics.sysdyn.ui/icons/control_fastforward.png [new file with mode: 0644]
org.simantics.sysdyn.ui/icons/control_fastforward_blue.png [new file with mode: 0644]
org.simantics.sysdyn.ui/icons/control_pause.png [new file with mode: 0644]
org.simantics.sysdyn.ui/icons/control_pause_blue.png [new file with mode: 0644]
org.simantics.sysdyn.ui/icons/control_play.png [new file with mode: 0644]
org.simantics.sysdyn.ui/icons/control_play_blue.png [new file with mode: 0644]
org.simantics.sysdyn.ui/icons/control_step.png [new file with mode: 0644]
org.simantics.sysdyn.ui/icons/control_step_blue.png [new file with mode: 0644]
org.simantics.sysdyn.ui/plugin.xml
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements2/profiles/SimulationPlaybackStyle.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/FastSpeedHandler.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/NormalSpeedHandler.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/PlaybackExperimentHandler.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/PlaybackResetHandler.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/SlowSpeedHandler.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/SpeedHandler.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/listeners/SysdynExperimentListener.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/listeners/SysdynPlaybackExperimentListener.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/menu/PlaybackSliderContribution.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/ValidationUtils.java
org.simantics.sysdyn.ui/sysdyn.product
org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynPlaybackExperiment.java

diff --git a/org.simantics.sysdyn.ui/icons/control_fastforward.png b/org.simantics.sysdyn.ui/icons/control_fastforward.png
new file mode 100644 (file)
index 0000000..31f7fd3
Binary files /dev/null and b/org.simantics.sysdyn.ui/icons/control_fastforward.png differ
diff --git a/org.simantics.sysdyn.ui/icons/control_fastforward_blue.png b/org.simantics.sysdyn.ui/icons/control_fastforward_blue.png
new file mode 100644 (file)
index 0000000..4a2f9d4
Binary files /dev/null and b/org.simantics.sysdyn.ui/icons/control_fastforward_blue.png differ
diff --git a/org.simantics.sysdyn.ui/icons/control_pause.png b/org.simantics.sysdyn.ui/icons/control_pause.png
new file mode 100644 (file)
index 0000000..2d9ce9c
Binary files /dev/null and b/org.simantics.sysdyn.ui/icons/control_pause.png differ
diff --git a/org.simantics.sysdyn.ui/icons/control_pause_blue.png b/org.simantics.sysdyn.ui/icons/control_pause_blue.png
new file mode 100644 (file)
index 0000000..ec61099
Binary files /dev/null and b/org.simantics.sysdyn.ui/icons/control_pause_blue.png differ
diff --git a/org.simantics.sysdyn.ui/icons/control_play.png b/org.simantics.sysdyn.ui/icons/control_play.png
new file mode 100644 (file)
index 0000000..0846555
Binary files /dev/null and b/org.simantics.sysdyn.ui/icons/control_play.png differ
diff --git a/org.simantics.sysdyn.ui/icons/control_play_blue.png b/org.simantics.sysdyn.ui/icons/control_play_blue.png
new file mode 100644 (file)
index 0000000..f8c8ec6
Binary files /dev/null and b/org.simantics.sysdyn.ui/icons/control_play_blue.png differ
diff --git a/org.simantics.sysdyn.ui/icons/control_step.png b/org.simantics.sysdyn.ui/icons/control_step.png
new file mode 100644 (file)
index 0000000..820b020
Binary files /dev/null and b/org.simantics.sysdyn.ui/icons/control_step.png differ
diff --git a/org.simantics.sysdyn.ui/icons/control_step_blue.png b/org.simantics.sysdyn.ui/icons/control_step_blue.png
new file mode 100644 (file)
index 0000000..98071cc
Binary files /dev/null and b/org.simantics.sysdyn.ui/icons/control_step_blue.png differ
index a9237d571dbaaa166b179cec62599fa713a8c670..0f62b29906a9e6b0c49872441f296389e3542d06 100644 (file)
          </toolbar>\r
          <toolbar\r
                id="org.simantics.sysdyn.ui.playbackControlToolbar">\r
+            <command\r
+                  commandId="org.simantics.sysdyn.ui.playbackReset"\r
+                  hoverIcon="platform:/plugin/com.famfamfam.silk/icons/control_start_blue.png"\r
+                  icon="platform:/plugin/com.famfamfam.silk/icons/control_start.png"\r
+                  id="org.simantics.sysdyn.ui.playbackReset.button"\r
+                  label="Reset"\r
+                  style="push">\r
+               <visibleWhen>\r
+                  <with\r
+                        variable="activeContexts">\r
+                     <iterate\r
+                           ifEmpty="false"\r
+                           operator="or">\r
+                        <equals\r
+                              value="org.simantics.sysdyn.ui.playbackExperiment">\r
+                        </equals>\r
+                     </iterate>\r
+                  </with>\r
+               </visibleWhen>\r
+            </command>\r
+            <command\r
+                  commandId="org.simantics.sysdyn.ui.playback"\r
+                  hoverIcon="platform:/plugin/com.famfamfam.silk/icons/control_play_blue.png"\r
+                  icon="platform:/plugin/com.famfamfam.silk/icons/control_play.png"\r
+                  id="org.simantics.sysdyn.ui.playback.button"\r
+                  label="Start playback"\r
+                  style="pulldown">\r
+               <visibleWhen>\r
+                  <with\r
+                        variable="activeContexts">\r
+                     <iterate\r
+                           ifEmpty="false"\r
+                           operator="or">\r
+                        <equals\r
+                              value="org.simantics.sysdyn.ui.playbackExperiment">\r
+                        </equals>\r
+                     </iterate>\r
+                  </with>\r
+               </visibleWhen>\r
+            </command>\r
             <dynamic\r
                   class="org.simantics.sysdyn.ui.menu.PlaybackSliderContribution"\r
                   id="org.simantics.sysdyn.ui.playbackSlider">\r
                   </with>\r
                </visibleWhen>\r
             </dynamic>\r
+            <command\r
+                  commandId="org.simantics.sysdyn.ui.dispose"\r
+                  hoverIcon="platform:/plugin/com.famfamfam.silk/icons/control_eject_blue.png"\r
+                  icon="platform:/plugin/com.famfamfam.silk/icons/control_eject.png"\r
+                  id="org.simantics.sysdyn.ui.dispose.button"\r
+                  label="Quit Experiment">\r
+               <visibleWhen>\r
+                  <with\r
+                        variable="activeContexts">\r
+                     <iterate\r
+                           ifEmpty="false"\r
+                           operator="or">\r
+                        <equals\r
+                              value="org.simantics.sysdyn.ui.playbackExperiment">\r
+                        </equals>\r
+                     </iterate>\r
+                  </with>\r
+               </visibleWhen>\r
+            </command>\r
          </toolbar>\r
       </menuContribution>\r
       <menuContribution\r
                style="push">\r
          </command>\r
       </menuContribution>\r
+      <menuContribution\r
+            allPopups="false"\r
+            locationURI="menu:org.simantics.sysdyn.ui.playback.button">\r
+         <command\r
+               commandId="org.simantics.sysdyn.ui.playbackSlow"\r
+               icon="icons/control_step.png"\r
+               label="Slow"\r
+               style="push">\r
+         </command>\r
+         <command\r
+               commandId="org.simantics.sysdyn.ui.playbackNormal"\r
+               icon="platform:/plugin/com.famfamfam.silk/icons/control_play.png"\r
+               label="Normal"\r
+               style="push">\r
+         </command>\r
+         <command\r
+               commandId="org.simantics.sysdyn.ui.playbackFast"\r
+               icon="platform:/plugin/com.famfamfam.silk/icons/control_fastforward.png"\r
+               label="Fast"\r
+               style="push">\r
+         </command>\r
+      </menuContribution>\r
    </extension>\r
    <extension\r
          point="org.eclipse.ui.commands">\r
             id="org.simantics.sysdyn.ui.newPlaybackExperiment"\r
             name="New Playback Experiment">\r
       </command>\r
+      <command\r
+            defaultHandler="org.simantics.sysdyn.ui.handlers.simulationPlayback.PlaybackExperimentHandler"\r
+            id="org.simantics.sysdyn.ui.playback"\r
+            name="Playback experiment">\r
+      </command>\r
+      <command\r
+            defaultHandler="org.simantics.sysdyn.ui.handlers.simulationPlayback.SlowSpeedHandler"\r
+            id="org.simantics.sysdyn.ui.playbackSlow"\r
+            name="Slow Playback">\r
+      </command>\r
+      <command\r
+            defaultHandler="org.simantics.sysdyn.ui.handlers.simulationPlayback.NormalSpeedHandler"\r
+            id="org.simantics.sysdyn.ui.playbackNormal"\r
+            name="Normal Playback">\r
+      </command>\r
+      <command\r
+            defaultHandler="org.simantics.sysdyn.ui.handlers.simulationPlayback.FastSpeedHandler"\r
+            id="org.simantics.sysdyn.ui.playbackFast"\r
+            name="Fast Playback">\r
+      </command>\r
+      <command\r
+            defaultHandler="org.simantics.sysdyn.ui.handlers.simulationPlayback.PlaybackResetHandler"\r
+            id="org.simantics.sysdyn.ui.playbackReset"\r
+            name="Reset Playback">\r
+      </command>\r
    </extension>\r
    <extension\r
          point="org.eclipse.ui.handlers">\r
index 1dd871655a7030452472778eb7b16076f7c92231..8a68153acbff8c2c1c01ec2213eb6919fbaa22cf 100644 (file)
@@ -100,10 +100,10 @@ public class SimulationPlaybackStyle extends StyleBase<Pair<AffineTransform, Dou
             int index = 0;\r
             if(ta[ta.length - 1] - time > ta[ta.length / 2] ) {\r
                 index = ta.length - 1;\r
-                while(ta[index] > time)\r
+                while(ta[index] > time && index > 0)\r
                     index--;\r
             } else {\r
-                while(ta[index] < time)\r
+                while(ta[index] < time && index < ta.length - 1)\r
                     index++;\r
             }\r
             \r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/FastSpeedHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/FastSpeedHandler.java
new file mode 100644 (file)
index 0000000..d98a44e
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.handlers.simulationPlayback;\r
+\r
+import org.eclipse.core.commands.ExecutionEvent;\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.simantics.sysdyn.manager.SysdynPlaybackExperiment;\r
+\r
+public class FastSpeedHandler extends SpeedHandler {\r
+\r
+    @Override\r
+    public Object execute(ExecutionEvent event) throws ExecutionException {\r
+        setPlaybackSpeed(SysdynPlaybackExperiment.DURATION_FAST);\r
+        return null;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/NormalSpeedHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/NormalSpeedHandler.java
new file mode 100644 (file)
index 0000000..b2ece4d
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.handlers.simulationPlayback;\r
+\r
+import org.eclipse.core.commands.ExecutionEvent;\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.simantics.sysdyn.manager.SysdynPlaybackExperiment;\r
+\r
+public class NormalSpeedHandler extends SpeedHandler {\r
+\r
+    @Override\r
+    public Object execute(ExecutionEvent event) throws ExecutionException {\r
+        setPlaybackSpeed(SysdynPlaybackExperiment.DURATION_NORMAL);\r
+        return null;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/PlaybackExperimentHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/PlaybackExperimentHandler.java
new file mode 100644 (file)
index 0000000..72ae6ec
--- /dev/null
@@ -0,0 +1,82 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.handlers.simulationPlayback;\r
+\r
+import java.util.Map;\r
+\r
+import org.eclipse.core.commands.AbstractHandler;\r
+import org.eclipse.core.commands.ExecutionEvent;\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
+import org.eclipse.ui.commands.IElementUpdater;\r
+import org.eclipse.ui.menus.UIElement;\r
+import org.simantics.simulation.experiment.ExperimentState;\r
+import org.simantics.simulation.experiment.IExperiment;\r
+import org.simantics.simulation.project.IExperimentManager;\r
+import org.simantics.sysdyn.manager.SysdynPlaybackExperiment;\r
+import org.simantics.sysdyn.ui.Activator;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class PlaybackExperimentHandler extends AbstractHandler implements IElementUpdater {\r
+    \r
+    public static final String COMMAND = "org.simantics.sysdyn.ui.playback";\r
+\r
+    @Override\r
+    public Object execute(ExecutionEvent event) throws ExecutionException {\r
+        IExperimentManager manager = SimanticsUI.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);\r
+        IExperiment experiment = manager.getActiveExperiment();\r
+        if(experiment == null || !(experiment instanceof SysdynPlaybackExperiment)) \r
+            return null;\r
+        SysdynPlaybackExperiment spe = (SysdynPlaybackExperiment)experiment;\r
+        if(!spe.isPlaybackRunning())\r
+            spe.startPlayback();\r
+        else\r
+            spe.stopPlayback();\r
+        return null;\r
+    }\r
+\r
+    @SuppressWarnings("rawtypes")\r
+    @Override\r
+    public void updateElement(UIElement element, Map parameters) {\r
+        IExperimentManager manager = \r
+            SimanticsUI.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);\r
+        IExperiment experiment = manager.getActiveExperiment();\r
+        if(experiment == null || !(experiment instanceof SysdynPlaybackExperiment)) \r
+            return;\r
+        SysdynPlaybackExperiment spe = (SysdynPlaybackExperiment)experiment;      \r
+        \r
+        ExperimentState state = experiment.getState();\r
+        if(state == ExperimentState.RUNNING && !spe.isPlaybackRunning()) {\r
+            // RUNNING == simulation, not playback\r
+            this.setBaseEnabled(false);\r
+        } else {\r
+            this.setBaseEnabled(true);\r
+        }\r
+\r
+        if(spe.isPlaybackRunning()) {\r
+            element.setIcon(ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/control_pause.png")));\r
+            element.setHoverIcon(ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/control_pause_blue.png")));\r
+        } else {\r
+            long duration = spe.getPlaybackDuration();\r
+            if(duration == SysdynPlaybackExperiment.DURATION_SLOW) {\r
+                element.setIcon(ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/control_step.png")));\r
+                element.setHoverIcon(ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/control_step_blue.png")));\r
+            } else if(duration == SysdynPlaybackExperiment.DURATION_FAST) {\r
+                element.setIcon(ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/control_fastforward.png")));\r
+                element.setHoverIcon(ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/control_fastforward_blue.png")));\r
+            } else {\r
+                element.setIcon(ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/control_play.png")));\r
+                element.setHoverIcon(ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/control_play_blue.png")));\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/PlaybackResetHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/PlaybackResetHandler.java
new file mode 100644 (file)
index 0000000..e4155b6
--- /dev/null
@@ -0,0 +1,63 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.handlers.simulationPlayback;\r
+\r
+import java.util.Map;\r
+\r
+import org.eclipse.core.commands.AbstractHandler;\r
+import org.eclipse.core.commands.ExecutionEvent;\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.eclipse.ui.commands.IElementUpdater;\r
+import org.eclipse.ui.menus.UIElement;\r
+import org.simantics.simulation.experiment.ExperimentState;\r
+import org.simantics.simulation.experiment.IExperiment;\r
+import org.simantics.simulation.project.IExperimentManager;\r
+import org.simantics.sysdyn.manager.SysdynPlaybackExperiment;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class PlaybackResetHandler extends AbstractHandler implements IElementUpdater {\r
+\r
+    public static final String COMMAND = "org.simantics.sysdyn.ui.playbackReset";\r
+\r
+    \r
+    @Override\r
+    public Object execute(ExecutionEvent event) throws ExecutionException {\r
+        IExperimentManager manager = SimanticsUI.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);\r
+        IExperiment experiment = manager.getActiveExperiment();\r
+        if(experiment == null || !(experiment instanceof SysdynPlaybackExperiment)) \r
+            return null;\r
+        SysdynPlaybackExperiment spe = (SysdynPlaybackExperiment)experiment;\r
+        spe.resetPlayback();\r
+        return null;\r
+    }\r
+\r
+    @SuppressWarnings("rawtypes")\r
+    @Override\r
+    public void updateElement(UIElement element, Map parameters) {\r
+        IExperimentManager manager = \r
+                SimanticsUI.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);\r
+        IExperiment experiment = manager.getActiveExperiment();\r
+        if(experiment == null || !(experiment instanceof SysdynPlaybackExperiment)) \r
+            return;\r
+        SysdynPlaybackExperiment spe = (SysdynPlaybackExperiment)experiment;      \r
+\r
+        ExperimentState state = experiment.getState();\r
+        if(state == ExperimentState.RUNNING && !spe.isPlaybackRunning()) {\r
+            // RUNNING == simulation, not playback\r
+            this.setBaseEnabled(false);\r
+        } else {\r
+            this.setBaseEnabled(true);\r
+        }\r
+\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/SlowSpeedHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/SlowSpeedHandler.java
new file mode 100644 (file)
index 0000000..6ebeba3
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.handlers.simulationPlayback;\r
+\r
+import org.eclipse.core.commands.ExecutionEvent;\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.simantics.sysdyn.manager.SysdynPlaybackExperiment;\r
+\r
+public class SlowSpeedHandler extends SpeedHandler {\r
+\r
+    @Override\r
+    public Object execute(ExecutionEvent event) throws ExecutionException {\r
+        setPlaybackSpeed(SysdynPlaybackExperiment.DURATION_SLOW);\r
+        return null;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/SpeedHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/simulationPlayback/SpeedHandler.java
new file mode 100644 (file)
index 0000000..4fe9691
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.handlers.simulationPlayback;\r
+\r
+import org.eclipse.core.commands.AbstractHandler;\r
+import org.eclipse.ui.PlatformUI;\r
+import org.eclipse.ui.commands.ICommandService;\r
+import org.simantics.simulation.experiment.IExperiment;\r
+import org.simantics.simulation.project.IExperimentManager;\r
+import org.simantics.sysdyn.manager.SysdynPlaybackExperiment;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+abstract class SpeedHandler extends AbstractHandler {\r
+    \r
+    protected void setPlaybackSpeed(long duration) {\r
+        \r
+        \r
+        IExperimentManager manager = SimanticsUI.getProject().getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);\r
+        IExperiment experiment = manager.getActiveExperiment();\r
+        if(experiment == null || !(experiment instanceof SysdynPlaybackExperiment)) \r
+            return;\r
+        final SysdynPlaybackExperiment spe = (SysdynPlaybackExperiment)experiment;\r
+        \r
+        if(spe.getPlaybackDuration() == duration)\r
+            return;\r
+        \r
+        \r
+        spe.setPlaybackDuration(duration);\r
+        \r
+        PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {\r
+\r
+            @Override\r
+            public void run() {\r
+                ICommandService commandService =\r
+                    (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class);\r
+                commandService.refreshElements(PlaybackExperimentHandler.COMMAND, null);\r
+            }\r
+        });\r
+    }\r
+\r
+}\r
index 44406261491ec91f7d2d3f4c9978e3e3ea99d57f..04507781daca121ff3b2156ef1399653e5a8d7a1 100644 (file)
@@ -20,6 +20,8 @@ import org.simantics.simulation.experiment.ExperimentState;
 import org.simantics.simulation.experiment.IExperimentListener;\r
 import org.simantics.sysdyn.ui.handlers.RunBasicExperiment;\r
 import org.simantics.sysdyn.ui.handlers.ToggleSimulation;\r
+import org.simantics.sysdyn.ui.handlers.simulationPlayback.PlaybackExperimentHandler;\r
+import org.simantics.sysdyn.ui.handlers.simulationPlayback.PlaybackResetHandler;\r
 \r
 public class SysdynExperimentListener  implements IExperimentListener {\r
 \r
@@ -43,6 +45,8 @@ public class SysdynExperimentListener  implements IExperimentListener {
                 }\r
                 commandService.refreshElements(command.getId(), null); \r
                 commandService.refreshElements(RunBasicExperiment.COMMAND, null);\r
+                commandService.refreshElements(PlaybackExperimentHandler.COMMAND, null);\r
+                commandService.refreshElements(PlaybackResetHandler.COMMAND, null);\r
             }\r
             \r
         });\r
index cb859cccb7556fc40b0ce8babd2717a1954d342b..50bd04806a37d1a8fc479d3e04166be93d284490 100644 (file)
@@ -1,6 +1,16 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
 package org.simantics.sysdyn.ui.listeners;\r
 \r
-import java.util.Collection;\r
 import java.util.HashMap;\r
 \r
 import org.eclipse.ui.IEditorPart;\r
@@ -11,18 +21,19 @@ import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.PlatformUI;\r
 import org.simantics.db.Resource;\r
 import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.request.ObjectsWithType;\r
 import org.simantics.db.common.request.PossibleObjectWithType;\r
 import org.simantics.db.common.request.WriteRequest;\r
 import org.simantics.db.exception.DatabaseException;\r
 import org.simantics.db.layer0.util.Simantics;\r
 import org.simantics.db.service.VirtualGraphSupport;\r
+import org.simantics.diagram.profile.Profiles;\r
 import org.simantics.diagram.stubs.DiagramResource;\r
 import org.simantics.layer0.Layer0;\r
 import org.simantics.project.IProject;\r
 import org.simantics.simulation.experiment.ExperimentState;\r
 import org.simantics.simulation.experiment.IExperiment;\r
 import org.simantics.simulation.experiment.IExperimentListener;\r
+import org.simantics.simulation.ontology.SimulationResource;\r
 import org.simantics.simulation.project.IExperimentManager;\r
 import org.simantics.sysdyn.SysdynResource;\r
 import org.simantics.sysdyn.manager.SysdynPlaybackExperiment;\r
@@ -32,6 +43,7 @@ import org.simantics.ui.SimanticsUI;
 public class SysdynPlaybackExperimentListener implements IExperimentListener {\r
 \r
     private Resource model;\r
+    private Resource previousProfile;\r
 \r
     public SysdynPlaybackExperimentListener(SysdynPlaybackExperiment experiment) {\r
         this.model = experiment.getModel();\r
@@ -96,11 +108,11 @@ public class SysdynPlaybackExperimentListener implements IExperimentListener {
                         Layer0 l0 = Layer0.getInstance(graph);\r
                         SysdynResource sr = SysdynResource.getInstance(graph);\r
                         \r
-                        Collection<Resource> profiles = graph.syncRequest(new ObjectsWithType(model, l0.ConsistsOf, sr.SimulationPlaybackProfile));\r
-                        if(profiles.isEmpty())\r
+                        Resource defaultProfile = graph.syncRequest(new PossibleObjectWithType(model, l0.ConsistsOf, sr.DefaultProfile));\r
+                        if(defaultProfile == null)\r
                             return;\r
                         \r
-                        Resource defaultProfile = profiles.iterator().next();\r
+                        setProfileForModel(graph, model, previousProfile == null ? defaultProfile : previousProfile);\r
                         \r
                         HashMap<Resource, DiagramInfo> infos = getRuntimesForModel(graph, runtimeDiagramsAndModelUris, model);\r
                         for(Resource runtimeDiagram : infos.keySet()) {\r
@@ -108,7 +120,7 @@ public class SysdynPlaybackExperimentListener implements IExperimentListener {
                             if(previousRuntimeDiagramsAndModelUris.containsKey(runtimeDiagram)) {\r
                                 previous = previousRuntimeDiagramsAndModelUris.get(runtimeDiagram).previousProfile;\r
                             }\r
-                            setProfile(graph, model, runtimeDiagram, previous == null ? defaultProfile : previous);\r
+                            setProfileForDiagram(graph, runtimeDiagram, previous == null ? defaultProfile : previous);\r
                         }\r
                     }\r
                 });\r
@@ -170,30 +182,34 @@ public class SysdynPlaybackExperimentListener implements IExperimentListener {
                 if(model == null)\r
                     return;\r
                 \r
-                Layer0 l0 = Layer0.getInstance(graph);\r
-                SysdynResource sr = SysdynResource.getInstance(graph);\r
-                \r
-                Resource profile = graph.syncRequest(new PossibleObjectWithType(model, l0.ConsistsOf, sr.SimulationPlaybackProfile));\r
+                Resource profile = getSimulationPlaybackProfile(graph, model);\r
                 if(profile == null)\r
                     return;\r
                 \r
                 DiagramResource DIA = DiagramResource.getInstance(graph);\r
 \r
+                Resource current = graph.getPossibleObject(model, DIA.HasActiveProfile);\r
+                previousProfile = current;\r
+\r
+                if(!profile.equals(current)) {\r
+                    setProfileForModel(graph, model, profile);\r
+                }\r
+                \r
                 HashMap<Resource, DiagramInfo> infos = getRuntimesForModel(graph, allDiagramInfos, model);\r
                 for(Resource runtimeDiagram : infos.keySet()) {\r
                     DiagramInfo di = infos.get(runtimeDiagram);\r
-                    Resource current = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile);\r
+                    current = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile);\r
+                    di.previousProfile = current;\r
                     if(profile.equals(current)) \r
                         continue;\r
-                    di.previousProfile = current;\r
-                    setProfile(graph, model, runtimeDiagram, profile);\r
+                    setProfileForDiagram(graph, runtimeDiagram, profile);\r
                 }\r
             }\r
         });\r
     }\r
     \r
     \r
-    private void setProfile(WriteGraph graph, Resource model, Resource runtimeDiagram, Resource profile) throws DatabaseException {\r
+    private void setProfileForDiagram(WriteGraph graph, Resource runtimeDiagram, Resource profile) throws DatabaseException {\r
         DiagramResource DIA = DiagramResource.getInstance(graph);\r
 \r
         Resource current = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile);\r
@@ -202,14 +218,38 @@ public class SysdynPlaybackExperimentListener implements IExperimentListener {
         graph.deny(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile, null, current);\r
         graph.claim(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile, null, profile);\r
 \r
-        // Set this profile as the default profile for this model\r
-        graph.deny(model, DIA.HasActiveProfile);\r
-        graph.claim(model, DIA.HasActiveProfile, profile);\r
-        \r
         // Set this profile as the default profile for this diagram\r
         Resource configuration = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration);\r
         graph.deny(configuration, DIA.HasActiveProfile);\r
         graph.claim(configuration, DIA.HasActiveProfile, profile);\r
     }\r
     \r
+    private void setProfileForModel(WriteGraph graph, Resource model, Resource profile) throws DatabaseException {\r
+        DiagramResource DIA = DiagramResource.getInstance(graph);\r
+\r
+        // Set this profile as the default profile for this model\r
+        graph.deny(model, DIA.HasActiveProfile);\r
+        graph.claim(model, DIA.HasActiveProfile, profile);\r
+    }\r
+    \r
+    private Resource getSimulationPlaybackProfile(WriteGraph graph, Resource model) throws DatabaseException {\r
+        Layer0 l0 = Layer0.getInstance(graph);\r
+        SysdynResource sr = SysdynResource.getInstance(graph);\r
+        SimulationResource SIMU = SimulationResource.getInstance(graph);\r
+        \r
+        Resource profile = graph.syncRequest(new PossibleObjectWithType(model, l0.ConsistsOf, sr.SimulationPlaybackProfile));\r
+        if(profile == null) {\r
+            profile = Profiles.createProfile(graph, "Simulation Playback", sr.Profiles_SimulationPlaybackColours);\r
+            graph.deny(profile, l0.InstanceOf);\r
+            graph.claim(profile, l0.InstanceOf, null, sr.SimulationPlaybackProfile);\r
+            graph.claim(model, l0.ConsistsOf, profile);\r
+        }\r
+\r
+        if(!graph.hasStatement(profile, SIMU.IsActive)) {\r
+            graph.claim(profile, SIMU.IsActive, sr.Profiles_SimulationPlaybackColours);\r
+        }\r
+        \r
+        return profile;\r
+    }\r
+    \r
 }\r
index 04596c12611a9574231187a6113dcaa4e1006e82..e589c31dd250a1863417066930cf597e1af34461 100644 (file)
@@ -23,6 +23,11 @@ import org.simantics.ui.SimanticsUI;
 \r
 public class PlaybackSliderContribution extends ToolBarContributionItem {\r
 \r
+    Runnable timeListener;\r
+    SysdynPlaybackExperiment spe;\r
+    Slider s;\r
+    Double startTime, endTime;\r
+    boolean ignoreChange = false;\r
 \r
     @Override\r
     public void fill(ToolBar parent, int index)\r
@@ -33,8 +38,8 @@ public class PlaybackSliderContribution extends ToolBarContributionItem {
             IExperiment experiment = manager.getActiveExperiment();\r
             if(experiment == null || !(experiment instanceof SysdynPlaybackExperiment)) \r
                 return;\r
-            final SysdynPlaybackExperiment spe = (SysdynPlaybackExperiment)experiment;\r
-            \r
+            spe = (SysdynPlaybackExperiment)experiment;\r
+\r
             Double[] numbers = new Double[3];\r
             try {\r
                 numbers = SimanticsUI.getSession().syncRequest(new Read<Double[]>() {\r
@@ -52,38 +57,37 @@ public class PlaybackSliderContribution extends ToolBarContributionItem {
             } catch (DatabaseException e1) {\r
                 e1.printStackTrace();\r
             }\r
-            \r
+\r
             ToolItem ti = new ToolItem(parent, SWT.SEPARATOR);\r
-            \r
+\r
             Composite composite = new Composite(parent, SWT.NONE);\r
-            GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite);\r
+            GridLayoutFactory.fillDefaults().margins(3, SWT.DEFAULT).numColumns(2).applyTo(composite);\r
             GridDataFactory.fillDefaults().applyTo(composite);\r
 \r
-            Slider s = new Slider(composite, SWT.NONE);\r
+            s = new Slider(composite, SWT.NONE);\r
             s.setMinimum(0);\r
             s.setMaximum(100);\r
             s.setIncrement(1);\r
             s.setPageIncrement(1);\r
             s.setThumb(1);\r
-            \r
+\r
             final Label label = new Label(composite, SWT.NONE);\r
             GridDataFactory.fillDefaults().hint(50, SWT.DEFAULT).applyTo(label);\r
             label.setText("0.0");\r
 \r
             ti.setWidth(250);\r
             ti.setControl(composite);\r
-            \r
-            final Double startTime = numbers[0];\r
-            final Double endTime = numbers[1];\r
-            \r
 \r
+            startTime = numbers[0];\r
+            endTime = numbers[1];\r
+            \r
             s.addSelectionListener(new SelectionListener() {\r
 \r
                 @Override\r
                 public void widgetSelected(SelectionEvent e) {\r
                     Slider s = (Slider)e.widget;\r
                     Double time = s.getSelection() / 99.0 * (endTime - startTime) + startTime;\r
-                    spe.setTime(time);\r
+                    spe.setTimeAndContinue(time);\r
                     if(!label.isDisposed()) {\r
                         label.setText(time.toString());\r
                     }\r
@@ -93,6 +97,39 @@ public class PlaybackSliderContribution extends ToolBarContributionItem {
                 public void widgetDefaultSelected(SelectionEvent e) {\r
                 }\r
             });\r
+\r
+            if(timeListener != null) {\r
+                spe.removeTimeListener(timeListener);\r
+            }\r
+\r
+            timeListener = new Runnable() {\r
+\r
+                @Override\r
+                public void run() {\r
+                    s.getDisplay().asyncExec(new Runnable() {\r
+\r
+                        @Override\r
+                        public void run() {\r
+                            int value = (int) ((spe.getTime() - startTime) / (endTime - startTime) * 99);\r
+                            s.setSelection(value);\r
+                            label.setText("" + spe.getTime());\r
+                        }\r
+                    });\r
+\r
+                }\r
+\r
+            };\r
+            spe.addTimeListener(timeListener);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void dispose() {\r
+        if(this.timeListener != null && spe != null) {\r
+            spe.removeTimeListener(timeListener);\r
+            this.timeListener = null;\r
         }\r
+        super.dispose();\r
+\r
     }\r
 }\r
index 7659e3d5824b063520464475d40c09d8199d590a..d81d186e4324d98b6205f1c28b2e867298e1bd25 100644 (file)
@@ -27,6 +27,7 @@ import org.simantics.db.WriteGraph;
 import org.simantics.db.common.request.ObjectsWithType;\r
 import org.simantics.db.common.utils.OrderedSetUtils;\r
 import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.util.RemoverUtil;\r
 import org.simantics.issues.ontology.IssueResource;\r
 import org.simantics.layer0.Layer0;\r
 import org.simantics.sysdyn.SysdynResource;\r
@@ -39,6 +40,7 @@ public class ValidationUtils {
     public static void removeIssue(WriteGraph graph, Resource model, Resource source, Resource variable, Resource issue, Collection<Resource> existing) throws DatabaseException {\r
         graph.deny(issue, Layer0.getInstance(graph).PartOf);\r
         graph.deny(source, IssueResource.getInstance(graph).Manages, issue);\r
+        RemoverUtil.remove(graph, issue);\r
         existing.remove(issue);\r
     }\r
     \r
index 540ebbc53f43222efaa60cfff8fe06e84a75af1a..8ab825b021d3a490c4b02644d1a4147c3bd49ac3 100644 (file)
@@ -7,7 +7,9 @@
    </configIni>\r
 \r
    <launcherArgs>\r
-      <programArgs>-fixerrors</programArgs>\r
+      <programArgs>-fixerrors\r
+--launcher.XXMaxPermSize\r
+256m</programArgs>\r
       <vmArgs>-ea  -Xmx768M -Xshare:off</vmArgs>\r
       <vmArgsMac>-XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts</vmArgsMac>\r
    </launcherArgs>\r
index 870418ea0dea1229f2e0443d322d66497a52bc9d..615c7020bd6176829f12803329e3941f57711d3e 100644 (file)
@@ -1,28 +1,81 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
 package org.simantics.sysdyn.manager;\r
 \r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.concurrent.Executors;\r
+import java.util.concurrent.ScheduledExecutorService;\r
+import java.util.concurrent.ScheduledFuture;\r
+import java.util.concurrent.TimeUnit;\r
+\r
 import org.simantics.db.ReadGraph;\r
 import org.simantics.db.Resource;\r
 import org.simantics.db.common.request.ReadRequest;\r
 import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.util.Simantics;\r
+import org.simantics.db.request.Read;\r
 import org.simantics.simulation.experiment.ExperimentState;\r
 import org.simantics.simulation.experiment.IDynamicExperiment;\r
 import org.simantics.simulation.ontology.SimulationResource;\r
+import org.simantics.sysdyn.SysdynResource;\r
 \r
 public class SysdynPlaybackExperiment extends SysdynExperiment implements IDynamicExperiment {\r
-\r
+    \r
+    public static long DURATION_SLOW = 20000;\r
+    public static long DURATION_NORMAL = 10000;\r
+    public static long DURATION_FAST = 5000;\r
+    \r
     double time;\r
     public static final long VARIABLE_UPDATE_INTERVAL = 500000000;\r
+    private static final double UPDATES_PER_TIME_UNIT = 0.015;\r
+    private long playbackDuration = DURATION_NORMAL;\r
+    private Collection<Runnable> timeListeners = new ArrayList<Runnable>();\r
     \r
+    ScheduledExecutorService playbackExecutionService;\r
+    PlaybackConfiguration playbackConfiguration;\r
 \r
     public SysdynPlaybackExperiment(Resource experiment, Resource model) {\r
         super(experiment, model);\r
         this.time = 0;\r
     }\r
     \r
-    volatile boolean updating = false;\r
-\r
     \r
-    public void setTime(double time) {\r
+    /**\r
+     * Interrupts a possible ongoing playback\r
+     * \r
+     * @param time\r
+     */\r
+    public void setTimeInterrupting(double time) {\r
+        stopPlayback();\r
+        setTime(time);\r
+    }\r
+    \r
+    /**\r
+     * Sets a new time and continues playback from that point if \r
+     * playback was running  \r
+     * @param time\r
+     */\r
+    public void setTimeAndContinue(double time) {\r
+        if(isPlaybackRunning()) {\r
+            stopPlayback();\r
+            setTime(time);\r
+            startPlayback(500);\r
+        } else {\r
+            setTime(time);\r
+        }\r
+    }\r
+    \r
+    private void setTime(double time) {\r
         this.time = time;\r
         fireValuesChanged(); \r
     }\r
@@ -31,6 +84,18 @@ public class SysdynPlaybackExperiment extends SysdynExperiment implements IDynam
         return this.time;\r
     }\r
     \r
+    public void setPlaybackDuration(long duration) {\r
+        this.playbackDuration = duration;\r
+        if(isPlaybackRunning()) {\r
+            //Restart playback with different time settings\r
+            startPlayback();\r
+        }\r
+    }\r
+    \r
+    public long getPlaybackDuration() {\r
+        return this.playbackDuration;\r
+    }\r
+    \r
     @Override\r
     public void init(ReadGraph g) {\r
         this.session = g.getSession();\r
@@ -46,4 +111,160 @@ public class SysdynPlaybackExperiment extends SysdynExperiment implements IDynam
             }\r
         });\r
     }\r
+    \r
+    \r
+    // PLAYBACK CONTROLS\r
+    public void startPlayback() {\r
+        startPlayback(0);\r
+    }\r
+    public void startPlayback(long initialDelay) {\r
+        if(isPlaybackRunning()) {\r
+            stopPlayback();\r
+        }\r
+        playbackConfiguration = getPlaybackConfiguration();\r
+        playbackExecutionService = Executors.newScheduledThreadPool(1); \r
+\r
+        if(time >= playbackConfiguration.endTime) {\r
+            setTime(playbackConfiguration.startTime);\r
+            playbackConfiguration = getPlaybackConfiguration();\r
+        }\r
+        \r
+        Runnable playbackSimulationTask = new PlaybackSimulationTask(time, playbackConfiguration.simulationStepLength);\r
+        \r
+        long delay = (long) (playbackConfiguration.playbackDuration / playbackConfiguration.intervals);\r
+        ScheduledFuture<?> stepper = playbackExecutionService.scheduleWithFixedDelay(\r
+                playbackSimulationTask, initialDelay, delay, TimeUnit.MILLISECONDS\r
+        );\r
+        \r
+        Runnable stopSimulationTask = new StopSimulationTask(stepper, playbackConfiguration.endTime);\r
+        playbackExecutionService.schedule(stopSimulationTask, playbackConfiguration.playbackDuration + initialDelay, TimeUnit.MILLISECONDS);\r
+        \r
+        changeState(ExperimentState.RUNNING);\r
+    }\r
+    \r
+    public boolean isPlaybackRunning() {\r
+        return playbackExecutionService != null && !playbackExecutionService.isShutdown();\r
+    }\r
+    \r
+    public void resetPlayback() {\r
+        double startTime = 0.0;\r
+        if(isPlaybackRunning() && playbackConfiguration != null) {\r
+            startTime = playbackConfiguration.startTime;\r
+        } else {\r
+            startTime = getPlaybackConfiguration().startTime;\r
+        }\r
+        setTimeInterrupting(startTime);\r
+    }\r
+    \r
+    public void stopPlayback() {\r
+        if(isPlaybackRunning()) {\r
+            playbackExecutionService.shutdownNow();\r
+            playbackExecutionService.shutdown();\r
+            if(playbackConfiguration != null)\r
+                playbackConfiguration = null;\r
+            changeState(ExperimentState.STOPPED);\r
+        }\r
+    }\r
+    \r
+   \r
+    private class PlaybackSimulationTask implements Runnable {\r
+        private int stepCount;\r
+        private double startTime, stepLength;\r
+        \r
+        public PlaybackSimulationTask(double startTime, double stepLength) {\r
+            this.startTime = startTime;\r
+            this.stepLength = stepLength;\r
+        }\r
+        \r
+        public void run() {\r
+          ++stepCount;\r
+          setTime(startTime + stepCount * stepLength);\r
+//          System.out.println("Playback step at time: " + (startTime + stepCount * stepLength) + " (step: " + stepCount + ")");\r
+        }\r
+      }\r
+\r
+    private class StopSimulationTask implements Runnable {\r
+\r
+        private ScheduledFuture<?> scheduledFuture;\r
+        private double endTime;\r
+        \r
+        public StopSimulationTask(ScheduledFuture<?> aSchedFuture, double endTime){\r
+            scheduledFuture = aSchedFuture;\r
+            this.endTime = endTime;\r
+        }\r
+        public void run() {\r
+//            System.out.println("Stopping playback");\r
+            scheduledFuture.cancel(false);\r
+            stopPlayback();\r
+            setTime(endTime);\r
+        }\r
+\r
+    }\r
+    \r
+    private PlaybackConfiguration getPlaybackConfiguration() {\r
+        Double[] numbers = new Double[3];\r
+        try {\r
+            numbers = Simantics.getSession().syncRequest(new Read<Double[]>() {\r
+                @Override\r
+                public Double[] perform(ReadGraph graph) throws DatabaseException {\r
+                    Double[] numbers = new Double[3];\r
+                    Resource model = getModel();\r
+                    SysdynResource sr = SysdynResource.getInstance(graph);\r
+                    numbers[0] = graph.getRelatedValue(model, sr.HasStartTime);\r
+                    numbers[1] = graph.getRelatedValue(model, sr.HasStopTime);\r
+                    numbers[2] = graph.getPossibleRelatedValue(model, sr.HasOutputInterval);\r
+                    return numbers;\r
+                }\r
+            });\r
+        } catch (DatabaseException e1) {\r
+            e1.printStackTrace();\r
+        }\r
+        \r
+        PlaybackConfiguration config = new PlaybackConfiguration();\r
+        config.simulationDuration = numbers[1] - numbers[0] - time;\r
+        config.playbackDuration = (long) (config.simulationDuration / (config.simulationDuration + time) * playbackDuration);\r
+        config.intervals = config.playbackDuration * UPDATES_PER_TIME_UNIT;\r
+        config.simulationStepLength = config.simulationDuration / config.intervals;\r
+        config.endTime = numbers[1];\r
+        config.startTime = numbers[0];\r
+        return config;\r
+    }\r
+    \r
+    private class PlaybackConfiguration {\r
+        public double simulationDuration, simulationStepLength, intervals, endTime, startTime;\r
+        public long playbackDuration;\r
+    }\r
+    \r
+    protected void localStateChange() {\r
+        super.localStateChange();\r
+        \r
+        ExperimentState state = getState();\r
+        if(ExperimentState.DISPOSED.equals(state)) {\r
+            stopPlayback();\r
+        }\r
+    }\r
+    \r
+    // TIME LISTENERS\r
+    public void addTimeListener(Runnable timeListener) {\r
+        if(!this.timeListeners.contains(timeListener))\r
+            this.timeListeners.add(timeListener);\r
+    }\r
+    \r
+    public Collection<Runnable> getTimeListeners() {\r
+        return this.timeListeners;\r
+    }\r
+    \r
+    public void removeTimeListener(Runnable timeListener) {\r
+        this.timeListeners.remove(timeListener);\r
+    }\r
+    \r
+    @Override\r
+    public void fireValuesChanged() {\r
+        for(Runnable listener : timeListeners) {\r
+            listener.run();\r
+        }\r
+        super.fireValuesChanged();\r
+\r
+    }\r
+    \r
 }\r