1 package net.mograsim.plugin.editors;
3 import java.io.ByteArrayInputStream;
4 import java.util.Optional;
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.FillLayout;
14 import org.eclipse.swt.layout.GridData;
15 import org.eclipse.swt.layout.GridLayout;
16 import org.eclipse.swt.widgets.Button;
17 import org.eclipse.swt.widgets.Composite;
18 import org.eclipse.swt.widgets.Display;
19 import org.eclipse.swt.widgets.Label;
20 import org.eclipse.swt.widgets.Slider;
21 import org.eclipse.ui.IEditorInput;
22 import org.eclipse.ui.IEditorSite;
23 import org.eclipse.ui.IFileEditorInput;
24 import org.eclipse.ui.PartInitException;
25 import org.eclipse.ui.part.EditorPart;
27 import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasUserInput;
28 import net.mograsim.logic.core.LogicObserver;
29 import net.mograsim.logic.core.components.CoreClock;
30 import net.mograsim.logic.model.LogicExecuter;
31 import net.mograsim.logic.model.LogicUICanvas;
32 import net.mograsim.machine.Machine;
33 import net.mograsim.machine.Memory.MemoryCellModifiedListener;
34 import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
35 import net.mograsim.plugin.nature.MachineContext;
36 import net.mograsim.plugin.nature.MachineContext.ActiveMachineListener;
37 import net.mograsim.plugin.nature.ProjectMachineContext;
38 import net.mograsim.plugin.tables.DisplaySettings;
39 import net.mograsim.plugin.tables.mi.ActiveInstructionPreviewContentProvider;
40 import net.mograsim.plugin.tables.mi.InstructionTable;
42 //TODO what if we open multiple editors?
43 //TODO actually save / load register and latch states
44 public class SimulationViewEditor extends EditorPart
46 private MachineContext context;
48 private LogicExecuter exec;
49 private Machine machine;
51 private Composite parent;
52 private Button resetButton;
53 private Button sbseButton;
54 private Button pauseButton;
55 private Label speedFactorLabel;
56 private Slider simSpeedSlider;
57 private Composite canvasParent;
58 private LogicUICanvas canvas;
59 private InstructionTable instPreview;
60 private Label noMachineLabel;
62 private ActiveMachineListener activeMNachineListener;
63 private MemoryCellModifiedListener memCellListener;
64 private LogicObserver clockObserver;
66 public SimulationViewEditor()
68 activeMNachineListener = m -> recreateContextDependentControls();
69 memCellListener = a -> instPreview.refresh();
72 if (((CoreClock) o).isOn())
74 exec.pauseLiveExecution();
75 if (!pauseButton.isDisposed())
76 Display.getDefault().asyncExec(() ->
78 if (!pauseButton.isDisposed())
79 pauseButton.setSelection(false);
80 setPauseText(pauseButton, false);
87 public void createPartControl(Composite parent)
91 parent.setLayout(new GridLayout());
93 noMachineLabel = new Label(parent, SWT.NONE);
94 noMachineLabel.setText("No machine present...");// TODO internationalize?
95 addSimulationControlWidgets(parent);
96 canvasParent = new Composite(parent, SWT.NONE);
97 canvasParent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
98 canvasParent.setLayout(new FillLayout());
99 addInstructionPreviewControlWidgets(parent);
100 recreateContextDependentControls();
103 private void recreateContextDependentControls()
106 // createPartControls has not been called yet
112 stopExecAndDeregisterContextDependentListeners();
115 offX = canvas.getOffX();
116 offY = canvas.getOffY();
117 zoom = canvas.getZoom();
126 Optional<Machine> machineOptional;
127 if (context != null && (machineOptional = context.getActiveMachine()).isPresent())
129 noMachineLabel.setVisible(false);
130 resetButton.setEnabled(true);
131 sbseButton.setEnabled(true);
132 pauseButton.setEnabled(true);
133 simSpeedSlider.setEnabled(true);
135 machine = machineOptional.get();
136 canvas = new LogicUICanvas(canvasParent, SWT.NONE, machine.getModel());
137 ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(canvas);
138 userInput.buttonDrag = 3;
139 userInput.buttonZoom = 2;
140 userInput.enableUserInput();
143 canvas.moveTo(offX, offY, zoom);
144 canvas.commitTransform();
147 AssignableMicroInstructionMemory mIMemory = machine.getMicroInstructionMemory();
148 instPreview.bindMicroInstructionMemory(mIMemory);
149 mIMemory.registerCellModifiedListener(memCellListener);
151 canvasParent.layout();
153 // initialize executer
154 exec = new LogicExecuter(machine.getTimeline());
157 exec.startLiveExecution();
160 noMachineLabel.setVisible(true);
161 resetButton.setEnabled(false);
162 sbseButton.setEnabled(false);
163 pauseButton.setEnabled(false);
164 simSpeedSlider.setEnabled(false);
168 private void stopExecAndDeregisterContextDependentListeners()
171 exec.stopLiveExecution();
174 machine.getMicroInstructionMemory().deregisterCellModifiedListener(memCellListener);
175 machine.getClock().deregisterObserver(clockObserver);
179 private void addSimulationControlWidgets(Composite parent)
181 Composite c = new Composite(parent, SWT.NONE);
182 c.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
183 c.setLayout(new GridLayout(7, false));
185 resetButton = new Button(c, SWT.PUSH);
186 resetButton.setText("Reset machine");
187 resetButton.addListener(SWT.Selection, e -> context.getActiveMachine().get().reset());
189 sbseButton = new Button(c, SWT.CHECK);
190 pauseButton = new Button(c, SWT.TOGGLE);
192 sbseButton.setText("Step by step execution");
193 sbseButton.addListener(SWT.Selection, e ->
195 CoreClock cl = machine.getClock();
196 if (sbseButton.getSelection())
197 cl.registerObserver(clockObserver);
199 cl.deregisterObserver(clockObserver);
201 sbseButton.setSelection(false);
203 pauseButton.setSelection(true);
204 setPauseText(pauseButton, false);
206 pauseButton.addListener(SWT.Selection, e -> updatePausedState());
207 pauseButton.addMouseTrackListener(new MouseTrackListener()
210 public void mouseHover(MouseEvent e)
216 public void mouseExit(MouseEvent e)
218 setPauseText(pauseButton, false);
222 public void mouseEnter(MouseEvent e)
224 setPauseText(pauseButton, true);
228 new Label(c, SWT.NONE).setText("Simulation Speed: ");
230 simSpeedSlider = new Slider(c, SWT.NONE);
231 simSpeedSlider.setMinimum(0);
232 simSpeedSlider.setMaximum(50 + simSpeedSlider.getThumb());
233 simSpeedSlider.setIncrement(1);
234 simSpeedSlider.setSelection(0);
236 speedFactorLabel = new Label(c, SWT.NONE);
237 speedFactorLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
239 simSpeedSlider.addListener(SWT.Selection, e -> updateSpeedFactor());
245 private void updatePausedState()
247 setPauseText(pauseButton, false);
249 if (pauseButton.getSelection())
250 exec.unpauseLiveExecution();
252 exec.pauseLiveExecution();
255 private void updateSpeedFactor()
257 double factor = Math.pow(1.32, simSpeedSlider.getSelection() - 50);
258 speedFactorLabel.setText(String.format("%f", factor));
260 exec.setSpeedFactor(factor);
263 private void addInstructionPreviewControlWidgets(Composite parent)
265 instPreview = new InstructionTable(parent, new DisplaySettings());
266 instPreview.getTableViewer().getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
267 instPreview.setContentProvider(new ActiveInstructionPreviewContentProvider(instPreview.getTableViewer()));
270 private static void setPauseText(Button pauseButton, boolean hovered)
273 if (pauseButton.getSelection())
274 pauseButton.setText("Pause?");
276 pauseButton.setText("Resume?");
277 else if (pauseButton.getSelection())
278 pauseButton.setText("Running");
280 pauseButton.setText("Paused");
284 public void init(IEditorSite site, IEditorInput input) throws PartInitException
286 if (input instanceof IFileEditorInput)
288 IFileEditorInput fileInput = (IFileEditorInput) input;
289 context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
290 context.activateMachine();
291 context.addActiveMachineListener(activeMNachineListener);
292 recreateContextDependentControls();
294 setPartName(fileInput.getName());
295 open(fileInput.getFile());
297 throw new IllegalArgumentException("SimulationViewEditor can only be used with Files");
304 public void doSave(IProgressMonitor monitor)
306 IEditorInput input = getEditorInput();
307 if (input instanceof IFileEditorInput)
308 SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
310 throw new IllegalArgumentException("SimulationViewEditor can only be used with Files");
313 private void save(IFile file, IProgressMonitor monitor) throws CoreException
315 file.setContents(new ByteArrayInputStream("actual contents will go here".getBytes()), 0, monitor);
318 private void open(IFile file)
324 public void doSaveAs()
326 throw new UnsupportedOperationException();
330 public boolean isDirty()
336 public boolean isSaveAsAllowed()
342 public void setFocus()
348 public void dispose()
350 stopExecAndDeregisterContextDependentListeners();
351 context.removeActiveMachineListener(activeMNachineListener);