MPROMEditor now calls its columns "Opcode" and "muPC"
[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 = 0;
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 double getSpeedFactor()
55         {
56                 return speedFactor;
57         }
58
59         public void setSpeedFactor(double factor)
60         {
61                 if (factor <= 0)
62                         throw new IllegalArgumentException("time factor can't be less than or equal to 0");
63                 if (!paused)
64                 {
65                         pause();
66                         unpause();
67                 }
68                 this.speedFactor = factor;
69                 callSimulTimeToRealTimeFactorChangedListeners(getSimulTimeToRealTimeFactor());
70         }
71
72         //@formatter:off
73         public void    addSimulTimeToRealTimeFactorChangedListener(Consumer<Double> listener)
74                 {simulTimeToRealTimeFactorChangedListeners.add   (listener);}
75         public void removeSimulTimeToRealTimeFactorChangedListener(Consumer<Double> listener)
76                 {simulTimeToRealTimeFactorChangedListeners.remove(listener);}
77         private void  callSimulTimeToRealTimeFactorChangedListeners(double f)
78                 {simulTimeToRealTimeFactorChangedListeners.forEach(l -> l.accept(f));}
79         //@formatter:on
80
81         public boolean isPaused()
82         {
83                 return paused;
84         }
85
86         public void toggle()
87         {
88                 if (paused)
89                         unpause();
90                 else
91                         pause();
92         }
93 }