Made simulation view / LogicUIPart to an Editor
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / editors / SimulationViewEditor.java
1 package net.mograsim.plugin.editors;
2
3 import java.io.ByteArrayInputStream;
4 import java.util.Optional;
5
6 import org.eclipse.core.resources.IFile;
7 import org.eclipse.core.runtime.CoreException;
8 import org.eclipse.core.runtime.IProgressMonitor;
9 import org.eclipse.jface.util.SafeRunnable;
10 import org.eclipse.swt.SWT;
11 import org.eclipse.swt.events.MouseEvent;
12 import org.eclipse.swt.events.MouseTrackListener;
13 import org.eclipse.swt.layout.GridData;
14 import org.eclipse.swt.layout.GridLayout;
15 import org.eclipse.swt.widgets.Button;
16 import org.eclipse.swt.widgets.Composite;
17 import org.eclipse.swt.widgets.Label;
18 import org.eclipse.swt.widgets.Slider;
19 import org.eclipse.ui.IEditorInput;
20 import org.eclipse.ui.IEditorSite;
21 import org.eclipse.ui.IFileEditorInput;
22 import org.eclipse.ui.PartInitException;
23 import org.eclipse.ui.part.EditorPart;
24
25 import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasUserInput;
26 import net.mograsim.logic.model.LogicExecuter;
27 import net.mograsim.logic.model.LogicUICanvas;
28 import net.mograsim.machine.Machine;
29 import net.mograsim.plugin.nature.MachineContext;
30 import net.mograsim.plugin.nature.ProjectMachineContext;
31
32 //TODO what if we open multiple editors?
33 //TODO actually save / load register and latch states
34 public class SimulationViewEditor extends EditorPart
35 {
36         private MachineContext context;
37
38         private LogicExecuter exec;
39
40         private Composite parent;
41         private LogicUICanvas canvas;
42         private Label noMachineLabel;
43
44         @Override
45         public void createPartControl(Composite parent)
46         {
47                 this.parent = parent;
48                 // initialize UI
49                 parent.setLayout(new GridLayout());
50
51                 noMachineLabel = new Label(parent, SWT.NONE);
52                 noMachineLabel.setText("No machine present...");// TODO internationalize?
53                 addSimulationControlWidgets(parent);
54                 recreateContextDependentControls();
55         }
56
57         private void recreateContextDependentControls()
58         {
59                 if (parent == null)
60                         // createPartControls has not been called yet
61                         return;
62
63                 if (canvas != null)
64                         canvas.dispose();
65                 if (exec != null)
66                         exec.stopLiveExecution();
67
68                 Optional<Machine> machineOptional;
69                 if (context != null && (machineOptional = context.getActiveMachine()).isPresent())
70                 {
71                         noMachineLabel.setVisible(false);
72                         Machine machine = machineOptional.get();
73                         canvas = new LogicUICanvas(parent, SWT.NONE, machine.getModel());
74                         ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(canvas);
75                         userInput.buttonDrag = 3;
76                         userInput.buttonZoom = 2;
77                         userInput.enableUserInput();
78
79                         GridData uiData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
80                         canvas.setLayoutData(uiData);
81
82                         // initialize executer
83                         exec = new LogicExecuter(machine.getTimeline());
84                         exec.startLiveExecution();
85                 } else
86                         noMachineLabel.setVisible(true);
87         }
88
89         private void addSimulationControlWidgets(Composite parent)
90         {
91                 Composite c = new Composite(parent, SWT.NONE);
92                 c.setLayout(new GridLayout(6, false));
93
94                 Button pauseButton = new Button(c, SWT.TOGGLE);
95                 pauseButton.setSelection(true);
96                 setPauseText(pauseButton, false);
97
98                 pauseButton.addListener(SWT.Selection, e ->
99                 {
100                         setPauseText(pauseButton, false);
101                         if (pauseButton.getSelection())
102                         {
103                                 exec.unpauseLiveExecution();
104                         } else
105                         {
106                                 exec.pauseLiveExecution();
107                         }
108                 });
109                 pauseButton.addMouseTrackListener(new MouseTrackListener()
110                 {
111                         @Override
112                         public void mouseHover(MouseEvent e)
113                         {
114                                 // nothing
115                         }
116
117                         @Override
118                         public void mouseExit(MouseEvent e)
119                         {
120                                 setPauseText(pauseButton, false);
121                         }
122
123                         @Override
124                         public void mouseEnter(MouseEvent e)
125                         {
126                                 setPauseText(pauseButton, true);
127                         }
128                 });
129
130                 Label speedLabel = new Label(c, SWT.NONE);
131                 speedLabel.setText("Simulation Speed: ");
132
133                 Slider slider = new Slider(c, SWT.NONE);
134                 slider.setMinimum(1);
135                 slider.setMaximum(100 + slider.getThumb());
136                 slider.setIncrement(1);
137
138                 Label speedPercentageLabel = new Label(c, SWT.NONE);
139                 speedPercentageLabel.setText("100%");
140
141                 slider.addListener(SWT.Selection, e ->
142                 {
143                         int selection = slider.getSelection();
144                         speedPercentageLabel.setText(selection + "%");
145
146                         exec.setSpeedPercentage(slider.getSelection());
147                 });
148                 slider.setSelection(100);
149
150                 c.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL));
151                 c.pack();
152                 c.setVisible(true);
153         }
154
155         private static void setPauseText(Button pauseButton, boolean hovered)
156         {
157                 if (hovered)
158                         if (pauseButton.getSelection())
159                                 pauseButton.setText("Pause?");
160                         else
161                                 pauseButton.setText("Resume?");
162                 else if (pauseButton.getSelection())
163                         pauseButton.setText("Running");
164                 else
165                         pauseButton.setText("Paused");
166         }
167
168         @Override
169         public void init(IEditorSite site, IEditorInput input) throws PartInitException
170         {
171                 if (input instanceof IFileEditorInput)
172                 {
173                         IFileEditorInput fileInput = (IFileEditorInput) input;
174                         context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
175                         recreateContextDependentControls();
176
177                         setPartName(fileInput.getName());
178                         open(fileInput.getFile());
179                 } else
180                         throw new IllegalArgumentException("SimulationViewEditor can only be used with Files");
181
182                 setSite(site);
183                 setInput(input);
184         }
185
186         @Override
187         public void doSave(IProgressMonitor monitor)
188         {
189                 IEditorInput input = getEditorInput();
190                 if (input instanceof IFileEditorInput)
191                         SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
192                 else
193                         throw new IllegalArgumentException("SimulationViewEditor can only be used with Files");
194         }
195
196         private void save(IFile file, IProgressMonitor monitor) throws CoreException
197         {
198                 file.setContents(new ByteArrayInputStream("actual contents will go here".getBytes()), 0, monitor);
199         }
200
201         private void open(IFile file)
202         {
203                 // do nothing yet
204         }
205
206         @Override
207         public void doSaveAs()
208         {
209                 throw new UnsupportedOperationException();
210         }
211
212         @Override
213         public boolean isDirty()
214         {
215                 return false;
216         }
217
218         @Override
219         public boolean isSaveAsAllowed()
220         {
221                 return false;
222         }
223
224         @Override
225         public void setFocus()
226         {
227                 canvas.setFocus();
228         }
229
230         @Override
231         public void dispose()
232         {
233                 exec.stopLiveExecution();
234                 super.dispose();
235         }
236 }