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.ProjectMachineContext;
37 import net.mograsim.plugin.tables.DisplaySettings;
38 import net.mograsim.plugin.tables.mi.ActiveInstructionPreviewContentProvider;
39 import net.mograsim.plugin.tables.mi.InstructionTable;
41 //TODO what if we open multiple editors?
42 //TODO actually save / load register and latch states
43 public class SimulationViewEditor extends EditorPart
45 private MachineContext context;
47 private LogicExecuter exec;
48 private Machine machine;
50 private Composite parent;
51 private Button sbseButton;
52 private Button pauseButton;
53 private Slider simSpeedSlider;
54 private Composite canvasParent;
55 private LogicUICanvas canvas;
56 private InstructionTable instPreview;
57 private Label noMachineLabel;
59 private MemoryCellModifiedListener currentRegisteredCellListener;
60 private LogicObserver currentClockObserver;
63 public void createPartControl(Composite parent)
67 parent.setLayout(new GridLayout());
69 noMachineLabel = new Label(parent, SWT.NONE);
70 noMachineLabel.setText("No machine present...");// TODO internationalize?
71 addSimulationControlWidgets(parent);
72 canvasParent = new Composite(parent, SWT.NONE);
73 canvasParent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
74 canvasParent.setLayout(new FillLayout());
75 addInstructionPreviewControlWidgets(parent);
76 recreateContextDependentControls();
79 private void recreateContextDependentControls()
82 // createPartControls has not been called yet
90 offX = canvas.getOffX();
91 offY = canvas.getOffY();
92 zoom = canvas.getZoom();
101 exec.stopLiveExecution();
105 machine.getMicroInstructionMemory().deregisterCellModifiedListener(currentRegisteredCellListener);
106 machine.getClock().deregisterObserver(currentClockObserver);
109 Optional<Machine> machineOptional;
110 if (context != null && (machineOptional = context.getActiveMachine()).isPresent())
112 noMachineLabel.setVisible(false);
113 sbseButton.setEnabled(true);
114 pauseButton.setEnabled(true);
115 simSpeedSlider.setEnabled(true);
117 machine = machineOptional.get();
118 canvas = new LogicUICanvas(canvasParent, SWT.NONE, machine.getModel());
119 ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(canvas);
120 userInput.buttonDrag = 3;
121 userInput.buttonZoom = 2;
122 userInput.enableUserInput();
125 canvas.moveTo(offX, offY, zoom);
126 canvas.commitTransform();
129 AssignableMicroInstructionMemory mIMemory = machine.getMicroInstructionMemory();
130 instPreview.bindMicroInstructionMemory(mIMemory);
131 currentRegisteredCellListener = a -> instPreview.refresh();
132 mIMemory.registerCellModifiedListener(currentRegisteredCellListener);
134 canvasParent.layout();
136 // initialize executer
137 exec = new LogicExecuter(machine.getTimeline());
138 exec.startLiveExecution();
141 noMachineLabel.setVisible(true);
142 sbseButton.setEnabled(false);
143 pauseButton.setEnabled(false);
144 simSpeedSlider.setEnabled(false);
148 private void addSimulationControlWidgets(Composite parent)
150 Composite c = new Composite(parent, SWT.NONE);
151 c.setLayout(new GridLayout(7, false));
153 sbseButton = new Button(c, SWT.CHECK);
154 pauseButton = new Button(c, SWT.TOGGLE);
155 currentClockObserver = o ->
157 if (((CoreClock) o).isOn())
159 exec.pauseLiveExecution();
160 if (!pauseButton.isDisposed())
161 Display.getDefault().asyncExec(() ->
163 if (!pauseButton.isDisposed())
164 pauseButton.setSelection(false);
165 setPauseText(pauseButton, false);
170 sbseButton.setText("Step by step execution");
171 sbseButton.addListener(SWT.Selection, e ->
173 CoreClock cl = machine.getClock();
174 if (sbseButton.getSelection())
175 cl.registerObserver(currentClockObserver);
177 cl.deregisterObserver(currentClockObserver);
179 sbseButton.setSelection(false);
181 pauseButton.setSelection(true);
182 setPauseText(pauseButton, false);
184 pauseButton.addListener(SWT.Selection, e ->
186 setPauseText(pauseButton, false);
187 if (pauseButton.getSelection())
189 exec.unpauseLiveExecution();
192 exec.pauseLiveExecution();
195 pauseButton.addMouseTrackListener(new MouseTrackListener()
198 public void mouseHover(MouseEvent e)
204 public void mouseExit(MouseEvent e)
206 setPauseText(pauseButton, false);
210 public void mouseEnter(MouseEvent e)
212 setPauseText(pauseButton, true);
216 Label speedLabel = new Label(c, SWT.NONE);
217 speedLabel.setText("Simulation Speed: ");
219 simSpeedSlider = new Slider(c, SWT.NONE);
220 simSpeedSlider.setMinimum(1);
221 simSpeedSlider.setMaximum(100 + simSpeedSlider.getThumb());
222 simSpeedSlider.setIncrement(1);
224 Label speedPercentageLabel = new Label(c, SWT.NONE);
225 speedPercentageLabel.setText("100%");
227 simSpeedSlider.addListener(SWT.Selection, e ->
229 int selection = simSpeedSlider.getSelection();
230 speedPercentageLabel.setText(selection + "%");
232 exec.setSpeedPercentage(simSpeedSlider.getSelection());
234 simSpeedSlider.setSelection(100);
236 c.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL));
240 private void addInstructionPreviewControlWidgets(Composite parent)
242 instPreview = new InstructionTable(parent, new DisplaySettings());
243 instPreview.getTableViewer().getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
244 instPreview.setContentProvider(new ActiveInstructionPreviewContentProvider(instPreview.getTableViewer()));
247 private static void setPauseText(Button pauseButton, boolean hovered)
250 if (pauseButton.getSelection())
251 pauseButton.setText("Pause?");
253 pauseButton.setText("Resume?");
254 else if (pauseButton.getSelection())
255 pauseButton.setText("Running");
257 pauseButton.setText("Paused");
261 public void init(IEditorSite site, IEditorInput input) throws PartInitException
263 if (input instanceof IFileEditorInput)
265 IFileEditorInput fileInput = (IFileEditorInput) input;
266 context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
267 context.registerObserver(m -> recreateContextDependentControls());
268 recreateContextDependentControls();
270 setPartName(fileInput.getName());
271 open(fileInput.getFile());
273 throw new IllegalArgumentException("SimulationViewEditor can only be used with Files");
280 public void doSave(IProgressMonitor monitor)
282 IEditorInput input = getEditorInput();
283 if (input instanceof IFileEditorInput)
284 SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
286 throw new IllegalArgumentException("SimulationViewEditor can only be used with Files");
289 private void save(IFile file, IProgressMonitor monitor) throws CoreException
291 file.setContents(new ByteArrayInputStream("actual contents will go here".getBytes()), 0, monitor);
294 private void open(IFile file)
300 public void doSaveAs()
302 throw new UnsupportedOperationException();
306 public boolean isDirty()
312 public boolean isSaveAsAllowed()
318 public void setFocus()
324 public void dispose()
326 exec.stopLiveExecution();