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