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 Slider simSpeedSlider;
56 private Composite canvasParent;
57 private LogicUICanvas canvas;
58 private InstructionTable instPreview;
59 private Label noMachineLabel;
61 private ActiveMachineListener activeMNachineListener;
62 private MemoryCellModifiedListener memCellListener;
63 private LogicObserver clockObserver;
65 public SimulationViewEditor()
67 activeMNachineListener = m -> recreateContextDependentControls();
68 memCellListener = a -> instPreview.refresh();
71 if (((CoreClock) o).isOn())
73 exec.pauseLiveExecution();
74 if (!pauseButton.isDisposed())
75 Display.getDefault().asyncExec(() ->
77 if (!pauseButton.isDisposed())
78 pauseButton.setSelection(false);
79 setPauseText(pauseButton, false);
86 public void createPartControl(Composite parent)
90 parent.setLayout(new GridLayout());
92 noMachineLabel = new Label(parent, SWT.NONE);
93 noMachineLabel.setText("No machine present...");// TODO internationalize?
94 addSimulationControlWidgets(parent);
95 canvasParent = new Composite(parent, SWT.NONE);
96 canvasParent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
97 canvasParent.setLayout(new FillLayout());
98 addInstructionPreviewControlWidgets(parent);
99 recreateContextDependentControls();
102 private void recreateContextDependentControls()
105 // createPartControls has not been called yet
111 stopExecAndDeregisterContextDependentListeners();
114 offX = canvas.getOffX();
115 offY = canvas.getOffY();
116 zoom = canvas.getZoom();
125 Optional<Machine> machineOptional;
126 if (context != null && (machineOptional = context.getActiveMachine()).isPresent())
128 noMachineLabel.setVisible(false);
129 resetButton.setEnabled(true);
130 sbseButton.setEnabled(true);
131 pauseButton.setEnabled(true);
132 simSpeedSlider.setEnabled(true);
134 machine = machineOptional.get();
135 canvas = new LogicUICanvas(canvasParent, SWT.NONE, machine.getModel());
136 ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(canvas);
137 userInput.buttonDrag = 3;
138 userInput.buttonZoom = 2;
139 userInput.enableUserInput();
142 canvas.moveTo(offX, offY, zoom);
143 canvas.commitTransform();
146 AssignableMicroInstructionMemory mIMemory = machine.getMicroInstructionMemory();
147 instPreview.bindMicroInstructionMemory(mIMemory);
148 mIMemory.registerCellModifiedListener(memCellListener);
150 canvasParent.layout();
152 // initialize executer
153 exec = new LogicExecuter(machine.getTimeline());
154 exec.startLiveExecution();
157 noMachineLabel.setVisible(true);
158 resetButton.setEnabled(false);
159 sbseButton.setEnabled(false);
160 pauseButton.setEnabled(false);
161 simSpeedSlider.setEnabled(false);
165 private void stopExecAndDeregisterContextDependentListeners()
168 exec.stopLiveExecution();
171 machine.getMicroInstructionMemory().deregisterCellModifiedListener(memCellListener);
172 machine.getClock().deregisterObserver(clockObserver);
176 private void addSimulationControlWidgets(Composite parent)
178 Composite c = new Composite(parent, SWT.NONE);
179 c.setLayout(new GridLayout(7, false));
181 resetButton = new Button(c, SWT.PUSH);
182 resetButton.setText("Reset machine");
183 resetButton.addListener(SWT.Selection, e -> context.getActiveMachine().get().reset());
185 sbseButton = new Button(c, SWT.CHECK);
186 pauseButton = new Button(c, SWT.TOGGLE);
188 sbseButton.setText("Step by step execution");
189 sbseButton.addListener(SWT.Selection, e ->
191 CoreClock cl = machine.getClock();
192 if (sbseButton.getSelection())
193 cl.registerObserver(clockObserver);
195 cl.deregisterObserver(clockObserver);
197 sbseButton.setSelection(false);
199 pauseButton.setSelection(true);
200 setPauseText(pauseButton, false);
202 pauseButton.addListener(SWT.Selection, e ->
204 setPauseText(pauseButton, false);
205 if (pauseButton.getSelection())
207 exec.unpauseLiveExecution();
210 exec.pauseLiveExecution();
213 pauseButton.addMouseTrackListener(new MouseTrackListener()
216 public void mouseHover(MouseEvent e)
222 public void mouseExit(MouseEvent e)
224 setPauseText(pauseButton, false);
228 public void mouseEnter(MouseEvent e)
230 setPauseText(pauseButton, true);
234 Label speedLabel = new Label(c, SWT.NONE);
235 speedLabel.setText("Simulation Speed: ");
237 simSpeedSlider = new Slider(c, SWT.NONE);
238 simSpeedSlider.setMinimum(1);
239 simSpeedSlider.setMaximum(100 + simSpeedSlider.getThumb());
240 simSpeedSlider.setIncrement(1);
242 Label speedPercentageLabel = new Label(c, SWT.NONE);
243 speedPercentageLabel.setText("100%");
245 simSpeedSlider.addListener(SWT.Selection, e ->
247 int selection = simSpeedSlider.getSelection();
248 speedPercentageLabel.setText(selection + "%");
250 exec.setSpeedPercentage(simSpeedSlider.getSelection());
252 simSpeedSlider.setSelection(100);
254 c.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL));
258 private void addInstructionPreviewControlWidgets(Composite parent)
260 instPreview = new InstructionTable(parent, new DisplaySettings());
261 instPreview.getTableViewer().getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
262 instPreview.setContentProvider(new ActiveInstructionPreviewContentProvider(instPreview.getTableViewer()));
265 private static void setPauseText(Button pauseButton, boolean hovered)
268 if (pauseButton.getSelection())
269 pauseButton.setText("Pause?");
271 pauseButton.setText("Resume?");
272 else if (pauseButton.getSelection())
273 pauseButton.setText("Running");
275 pauseButton.setText("Paused");
279 public void init(IEditorSite site, IEditorInput input) throws PartInitException
281 if (input instanceof IFileEditorInput)
283 IFileEditorInput fileInput = (IFileEditorInput) input;
284 context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
285 context.activateMachine();
286 context.addActiveMachineListener(activeMNachineListener);
287 recreateContextDependentControls();
289 setPartName(fileInput.getName());
290 open(fileInput.getFile());
292 throw new IllegalArgumentException("SimulationViewEditor can only be used with Files");
299 public void doSave(IProgressMonitor monitor)
301 IEditorInput input = getEditorInput();
302 if (input instanceof IFileEditorInput)
303 SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
305 throw new IllegalArgumentException("SimulationViewEditor can only be used with Files");
308 private void save(IFile file, IProgressMonitor monitor) throws CoreException
310 file.setContents(new ByteArrayInputStream("actual contents will go here".getBytes()), 0, monitor);
313 private void open(IFile file)
319 public void doSaveAs()
321 throw new UnsupportedOperationException();
325 public boolean isDirty()
331 public boolean isSaveAsAllowed()
337 public void setFocus()
343 public void dispose()
345 stopExecAndDeregisterContextDependentListeners();
346 context.removeActiveMachineListener(activeMNachineListener);