c50af4ae51ef6a9d0732c7879fe4f1dcd290b617
[Mograsim.git] / LogicUI / src / era / mi / gui / LogicUIStandalone.java
1 package era.mi.gui;\r
2 \r
3 import java.util.concurrent.atomic.AtomicBoolean;\r
4 \r
5 import org.eclipse.swt.SWT;\r
6 import org.eclipse.swt.layout.FillLayout;\r
7 import org.eclipse.swt.widgets.Display;\r
8 import org.eclipse.swt.widgets.Shell;\r
9 \r
10 import era.mi.logic.timeline.Timeline;\r
11 import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasOverlay;\r
12 import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasUserInput;\r
13 \r
14 /**\r
15  * Standalone simulation visualizer.\r
16  * \r
17  * @author Daniel Kirschten\r
18  */\r
19 public class LogicUIStandalone\r
20 {\r
21         private final Display display;\r
22         private final Shell shell;\r
23         private final LogicUICanvas ui;\r
24         private Timeline timeline;\r
25 \r
26         public LogicUIStandalone(Timeline timeline)\r
27         {\r
28                 this.timeline = timeline;\r
29                 display = new Display();\r
30                 shell = new Shell(display);\r
31                 shell.setLayout(new FillLayout());\r
32                 ui = new LogicUICanvas(shell, SWT.NONE);\r
33 \r
34                 ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(ui);\r
35                 userInput.buttonDrag = 3;\r
36                 userInput.buttonZoom = 2;\r
37                 userInput.enableUserInput();\r
38                 new ZoomableCanvasOverlay(ui, null).enableScale();\r
39         }\r
40 \r
41         public LogicUICanvas getLogicUICanvas()\r
42         {\r
43                 return ui;\r
44         }\r
45 \r
46         /**\r
47          * Start the simulation timeline, and open the UI shell. Returns when the shell is closed.\r
48          */\r
49         public void run()\r
50         {\r
51                 AtomicBoolean running = new AtomicBoolean(true);\r
52                 Thread simulationThread = new Thread(() ->\r
53                 {\r
54                         while (running.get())\r
55                         {\r
56                                 // always execute to keep timeline from "hanging behind" for too long\r
57                                 timeline.executeUpTo(System.currentTimeMillis(), System.currentTimeMillis() + 10);\r
58                                 long sleepTime;\r
59                                 if (timeline.hasNext())\r
60                                         sleepTime = timeline.nextEventTime() - System.currentTimeMillis();\r
61                                 else\r
62                                         sleepTime = 10;\r
63                                 try\r
64                                 {\r
65                                         if (sleepTime > 0)\r
66                                                 Thread.sleep(sleepTime);\r
67                                 }\r
68                                 catch (InterruptedException e)\r
69                                 {\r
70                                 } // it is normal execution flow to be interrupted\r
71                         }\r
72                 });\r
73                 simulationThread.start();\r
74                 timeline.addEventAddedListener(event ->\r
75                 {\r
76                         if (event.getTiming() <= System.currentTimeMillis())\r
77                                 simulationThread.interrupt();\r
78                 });\r
79 \r
80                 shell.open();\r
81                 while (!shell.isDisposed())\r
82                         if (!display.readAndDispatch())\r
83                                 display.sleep();\r
84                 running.set(false);\r
85                 simulationThread.interrupt();\r
86         }\r
87 }