Merge branch 'development' of https://gitlab.lrz.de/lrr-tum/students/eragp-misim...
[Mograsim.git] / plugins / net.mograsim.logic.core / src / net / mograsim / logic / core / timeline / PauseableTimeFunction.java
1 package net.mograsim.logic.core.timeline;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.function.Consumer;
6
7 import net.mograsim.logic.core.timeline.Timeline.TimeFunction;
8
9 public class PauseableTimeFunction implements TimeFunction
10 {
11         private boolean paused = false;
12         private long unpausedSysTime = 0, lastPausedInternalTime = 0;
13         private double speedFactor = 1;
14
15         private final List<Consumer<Double>> simulTimeToRealTimeFactorChangedListeners = new ArrayList<>();
16
17         public void pause()
18         {
19                 if (!paused)
20                 {
21                         lastPausedInternalTime = getTime();
22                         paused = true;
23                 }
24         }
25
26         public void unpause()
27         {
28                 if (paused)
29                 {
30                         paused = false;
31                         unpausedSysTime = System.nanoTime() / 1000;
32                 }
33         }
34
35         @Override
36         public long getTime()
37         {
38                 return (long) (paused ? lastPausedInternalTime
39                                 : lastPausedInternalTime + (System.nanoTime() / 1000 - unpausedSysTime) * speedFactor);
40         }
41
42         @Override
43         public void setTime(long time)
44         {
45                 lastPausedInternalTime = time;
46                 unpausedSysTime = System.nanoTime() / 1000;
47         }
48
49         public double getSimulTimeToRealTimeFactor()
50         {
51                 return 1 / 1000d / speedFactor;
52         }
53
54         public void setSpeedFactor(double factor)
55         {
56                 if (factor <= 0)
57                         throw new IllegalArgumentException("time factor can't be less than or equal to 0");
58                 if (!paused)
59                 {
60                         pause();
61                         unpause();
62                 }
63                 this.speedFactor = factor;
64                 callSimulTimeToRealTimeFactorChangedListeners(getSimulTimeToRealTimeFactor());
65         }
66
67         //@formatter:off
68         public void    addSimulTimeToRealTimeFactorChangedListener(Consumer<Double> listener)
69                 {simulTimeToRealTimeFactorChangedListeners.add   (listener);}
70         public void removeSimulTimeToRealTimeFactorChangedListener(Consumer<Double> listener)
71                 {simulTimeToRealTimeFactorChangedListeners.remove(listener);}
72         private void  callSimulTimeToRealTimeFactorChangedListeners(double f)
73                 {simulTimeToRealTimeFactorChangedListeners.forEach(l -> l.accept(f));}
74         //@formatter:on
75
76         public boolean isPaused()
77         {
78                 return paused;
79         }
80
81         public void toggle()
82         {
83                 if (paused)
84                         unpause();
85                 else
86                         pause();
87         }
88 }