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.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;
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.machine.Memory.MemoryCellModifiedListener;
33 import net.mograsim.machine.mi.AssignableMicroInstructionMemory;
34 import net.mograsim.plugin.nature.MachineContext;
35 import net.mograsim.plugin.nature.ProjectMachineContext;
36 import net.mograsim.plugin.tables.DisplaySettings;
37 import net.mograsim.plugin.tables.mi.ActiveInstructionPreviewContentProvider;
38 import net.mograsim.plugin.tables.mi.InstructionTable;
40 //TODO what if we open multiple editors?
41 //TODO actually save / load register and latch states
42 public class SimulationViewEditor extends EditorPart
44 private MachineContext context;
46 private LogicExecuter exec;
47 private Machine machine;
49 private Composite parent;
50 private Button sbseButton;
51 private Button pauseButton;
52 private Slider simSpeedSlider;
53 private LogicUICanvas canvas;
54 private Label noMachineLabel;
56 private MemoryCellModifiedListener currentRegisteredCellListener;
57 private LogicObserver currentClockObserver;
60 public void createPartControl(Composite parent)
64 parent.setLayout(new GridLayout());
66 noMachineLabel = new Label(parent, SWT.NONE);
67 noMachineLabel.setText("No machine present...");// TODO internationalize?
68 addSimulationControlWidgets(parent);
69 recreateContextDependentControls();
72 private void recreateContextDependentControls()
75 // createPartControls has not been called yet
81 exec.stopLiveExecution();
83 Optional<Machine> machineOptional;
84 if (context != null && (machineOptional = context.getActiveMachine()).isPresent())
86 noMachineLabel.setVisible(false);
87 sbseButton.setEnabled(true);
88 pauseButton.setEnabled(true);
89 simSpeedSlider.setEnabled(true);
93 machine.getMicroInstructionMemory().deregisterCellModifiedListener(currentRegisteredCellListener);
94 machine.getClock().deregisterObserver(currentClockObserver);
97 machine = machineOptional.get();
98 canvas = new LogicUICanvas(parent, SWT.NONE, machine.getModel());
99 canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
100 ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(canvas);
101 userInput.buttonDrag = 3;
102 userInput.buttonZoom = 2;
103 userInput.enableUserInput();
105 // initialize Instruction preview
106 InstructionTable instPreview = new InstructionTable(parent, new DisplaySettings());
107 instPreview.getTableViewer().getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
108 instPreview.setContentProvider(new ActiveInstructionPreviewContentProvider(instPreview.getTableViewer()));
109 AssignableMicroInstructionMemory mIMemory = machine.getMicroInstructionMemory();
110 instPreview.bindMicroInstructionMemory(mIMemory);
111 currentRegisteredCellListener = a -> instPreview.refresh();
112 mIMemory.registerCellModifiedListener(currentRegisteredCellListener);
114 GridData uiData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
115 canvas.setLayoutData(uiData);
117 // initialize executer
118 exec = new LogicExecuter(machine.getTimeline());
119 exec.startLiveExecution();
122 noMachineLabel.setVisible(true);
123 sbseButton.setEnabled(false);
124 pauseButton.setEnabled(false);
125 simSpeedSlider.setEnabled(false);
129 private void addSimulationControlWidgets(Composite parent)
131 Composite c = new Composite(parent, SWT.NONE);
132 c.setLayout(new GridLayout(7, false));
134 sbseButton = new Button(c, SWT.CHECK);
135 pauseButton = new Button(c, SWT.TOGGLE);
136 currentClockObserver = o ->
138 if (((CoreClock) o).isOn())
140 exec.pauseLiveExecution();
141 if (!pauseButton.isDisposed())
142 Display.getDefault().asyncExec(() ->
144 if (!pauseButton.isDisposed())
145 pauseButton.setSelection(false);
146 setPauseText(pauseButton, false);
151 sbseButton.setText("Step by step execution");
152 sbseButton.addListener(SWT.Selection, e ->
154 CoreClock cl = machine.getClock();
155 if (sbseButton.getSelection())
156 cl.registerObserver(currentClockObserver);
158 cl.deregisterObserver(currentClockObserver);
160 sbseButton.setSelection(false);
162 pauseButton.setSelection(true);
163 setPauseText(pauseButton, false);
165 pauseButton.addListener(SWT.Selection, e ->
167 setPauseText(pauseButton, false);
168 if (pauseButton.getSelection())
170 exec.unpauseLiveExecution();
173 exec.pauseLiveExecution();
176 pauseButton.addMouseTrackListener(new MouseTrackListener()
179 public void mouseHover(MouseEvent e)
185 public void mouseExit(MouseEvent e)
187 setPauseText(pauseButton, false);
191 public void mouseEnter(MouseEvent e)
193 setPauseText(pauseButton, true);
197 Label speedLabel = new Label(c, SWT.NONE);
198 speedLabel.setText("Simulation Speed: ");
200 simSpeedSlider = new Slider(c, SWT.NONE);
201 simSpeedSlider.setMinimum(1);
202 simSpeedSlider.setMaximum(100 + simSpeedSlider.getThumb());
203 simSpeedSlider.setIncrement(1);
205 Label speedPercentageLabel = new Label(c, SWT.NONE);
206 speedPercentageLabel.setText("100%");
208 simSpeedSlider.addListener(SWT.Selection, e ->
210 int selection = simSpeedSlider.getSelection();
211 speedPercentageLabel.setText(selection + "%");
213 exec.setSpeedPercentage(simSpeedSlider.getSelection());
215 simSpeedSlider.setSelection(100);
217 c.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL));
221 private static void setPauseText(Button pauseButton, boolean hovered)
224 if (pauseButton.getSelection())
225 pauseButton.setText("Pause?");
227 pauseButton.setText("Resume?");
228 else if (pauseButton.getSelection())
229 pauseButton.setText("Running");
231 pauseButton.setText("Paused");
235 public void init(IEditorSite site, IEditorInput input) throws PartInitException
237 if (input instanceof IFileEditorInput)
239 IFileEditorInput fileInput = (IFileEditorInput) input;
240 context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
241 recreateContextDependentControls();
243 setPartName(fileInput.getName());
244 open(fileInput.getFile());
246 throw new IllegalArgumentException("SimulationViewEditor can only be used with Files");
253 public void doSave(IProgressMonitor monitor)
255 IEditorInput input = getEditorInput();
256 if (input instanceof IFileEditorInput)
257 SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
259 throw new IllegalArgumentException("SimulationViewEditor can only be used with Files");
262 private void save(IFile file, IProgressMonitor monitor) throws CoreException
264 file.setContents(new ByteArrayInputStream("actual contents will go here".getBytes()), 0, monitor);
267 private void open(IFile file)
273 public void doSaveAs()
275 throw new UnsupportedOperationException();
279 public boolean isDirty()
285 public boolean isSaveAsAllowed()
291 public void setFocus()
297 public void dispose()
299 exec.stopLiveExecution();