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