Simulation speed now can be edited via a text field
[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 import java.util.function.LongSupplier;
7
8 public class PauseableTimeFunction implements LongSupplier
9 {
10         private boolean paused = false;
11         private long unpausedSysTime = 0, lastPausedInternalTime = 0;
12         private double speedFactor = 1;
13
14         private final List<Consumer<Double>> simulTimeToRealTimeFactorChangedListeners = new ArrayList<>();
15
16         public void pause()
17         {
18                 if (!paused)
19                 {
20                         lastPausedInternalTime = getAsLong();
21                         paused = true;
22                 }
23         }
24
25         public void unpause()
26         {
27                 if (paused)
28                 {
29                         paused = false;
30                         unpausedSysTime = System.nanoTime() / 1000;
31                 }
32         }
33
34         @Override
35         public long getAsLong()
36         {
37                 return (long) (paused ? lastPausedInternalTime
38                                 : lastPausedInternalTime + (System.nanoTime() / 1000 - unpausedSysTime) * speedFactor);
39         }
40
41         public double getSimulTimeToRealTimeFactor()
42         {
43                 return 1 / 1000d / speedFactor;
44         }
45
46         public void setSpeedFactor(double factor)
47         {
48                 if (factor <= 0)
49                         throw new IllegalArgumentException("time factor can't be less than or equal to 0");
50                 if (!paused)
51                 {
52                         pause();
53                         unpause();
54                 }
55                 this.speedFactor = factor;
56                 callSimulTimeToRealTimeFactorChangedListeners(getSimulTimeToRealTimeFactor());
57         }
58
59         //@formatter:off
60         public void    addSimulTimeToRealTimeFactorChangedListener(Consumer<Double> listener)
61                 {simulTimeToRealTimeFactorChangedListeners.add   (listener);}
62         public void removeSimulTimeToRealTimeFactorChangedListener(Consumer<Double> listener)
63                 {simulTimeToRealTimeFactorChangedListeners.remove(listener);}
64         private void  callSimulTimeToRealTimeFactorChangedListeners(double f)
65                 {simulTimeToRealTimeFactorChangedListeners.forEach(l -> l.accept(f));}
66         //@formatter:on
67
68         public boolean isPaused()
69         {
70                 return paused;
71         }
72
73         public void toggle()
74         {
75                 if (paused)
76                         unpause();
77                 else
78                         pause();
79         }
80 }