1 package net.mograsim.plugin.tables.mi;
3 import java.io.BufferedReader;
5 import java.io.FileReader;
6 import java.io.IOException;
7 import java.util.Arrays;
9 import org.eclipse.core.runtime.IProgressMonitor;
10 import org.eclipse.jface.viewers.ColumnLabelProvider;
11 import org.eclipse.jface.viewers.EditingSupport;
12 import org.eclipse.jface.viewers.TableViewerColumn;
13 import org.eclipse.swt.SWT;
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.FileDialog;
19 import org.eclipse.swt.widgets.Table;
20 import org.eclipse.swt.widgets.TableColumn;
21 import org.eclipse.ui.IEditorInput;
22 import org.eclipse.ui.IEditorSite;
23 import org.eclipse.ui.IPathEditorInput;
24 import org.eclipse.ui.PartInitException;
25 import org.eclipse.ui.part.EditorPart;
27 import net.mograsim.machine.MemoryObserver;
28 import net.mograsim.machine.mi.MicroInstructionDefinition;
29 import net.mograsim.machine.mi.MicroInstructionMemory;
30 import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
31 import net.mograsim.machine.mi.MicroInstructionMemoryParser;
32 import net.mograsim.machine.mi.parameters.MnemonicFamily;
33 import net.mograsim.machine.mi.parameters.ParameterClassification;
34 import net.mograsim.plugin.MachineContext;
35 import net.mograsim.plugin.tables.AddressLabelProvider;
36 import net.mograsim.plugin.tables.DisplaySettings;
37 import net.mograsim.plugin.tables.LazyTableViewer;
38 import net.mograsim.plugin.tables.RadixSelector;
40 public class InstructionView extends EditorPart implements MemoryObserver
42 private LazyTableViewer viewer;
43 private TableViewerColumn[] columns = new TableViewerColumn[0];
44 private MicroInstructionDefinition miDef;
45 private MicroInstructionMemory memory;
46 private DisplaySettings displaySettings;
47 private InstructionTableContentProvider provider;
48 private int highlighted = 0;
49 private boolean dirty = false;
50 private String machineName;
52 @SuppressWarnings("unused")
54 public void createPartControl(Composite parent)
56 provider = new InstructionTableContentProvider();
57 GridLayout layout = new GridLayout(3, false);
58 parent.setLayout(layout);
60 displaySettings = new DisplaySettings();
61 new RadixSelector(parent, displaySettings);
63 addActivationButton(parent);
64 viewer = new LazyTableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
66 Table table = viewer.getTable();
67 table.setHeaderVisible(true);
68 table.setLinesVisible(true);
69 viewer.setUseHashlookup(true);
70 viewer.setContentProvider(provider);
71 setViewerInput(memory);
72 getSite().setSelectionProvider(viewer);
74 GridData viewerData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
75 viewerData.horizontalSpan = 3;
76 viewer.getTable().setLayoutData(viewerData);
78 displaySettings.addObserver(() -> viewer.refresh());
81 private void addActivationButton(Composite parent)
83 Button activationButton = new Button(parent, SWT.PUSH);
84 activationButton.setText("Set Active");
85 activationButton.addListener(SWT.Selection,
86 e -> MachineContext.getInstance().getMachine().getMicroInstructionMemory().bind(memory));
89 public void highlight(int index)
91 viewer.highlightRow(highlighted, false);
92 viewer.highlightRow(index, true);
93 viewer.getTable().setTopIndex(index);
96 public void bindMicroInstructionMemory(MicroInstructionMemory memory)
99 this.miDef = memory.getDefinition().getMicroInstructionDefinition();
100 this.memory.registerObserver(this);
101 setViewerInput(memory);
104 private void setViewerInput(MicroInstructionMemory memory)
109 viewer.setInput(memory);
114 private void deleteColumns()
116 for (TableViewerColumn col : columns)
117 col.getColumn().dispose();
120 private void createColumns()
122 int size = miDef.size();
123 columns = new TableViewerColumn[size + 1];
125 TableViewerColumn col = createTableViewerColumn("Address", generateLongestHexStrings(12));
127 col.setLabelProvider(new AddressLabelProvider());
129 int bit = miDef.sizeInBits();
130 ParameterClassification[] classes = miDef.getParameterClassifications();
132 for (int i = 0; i < size; i++)
134 int startBit = bit - 1;
135 int endBit = bit = bit - classes[i].getExpectedBits();
136 String name = startBit == endBit ? Integer.toString(startBit) : startBit + "..." + endBit;
138 String[] longestPossibleContents;
139 switch (classes[i].getExpectedType())
141 case INTEGER_IMMEDIATE:
142 longestPossibleContents = generateLongestHexStrings(classes[i].getExpectedBits());
144 case BOOLEAN_IMMEDIATE:
146 longestPossibleContents = ((MnemonicFamily) classes[i]).getStringValues();
149 longestPossibleContents = new String[0];
153 col = createTableViewerColumn(name, longestPossibleContents);
154 columns[i + 1] = col;
155 createEditingAndLabel(col, miDef, i);
159 private static final String[] HEX_DIGITS = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" };
161 private static String[] generateLongestHexStrings(int bitWidth)
163 return Arrays.stream(HEX_DIGITS).map(s -> "0x" + s.repeat((bitWidth + 3) / 4)).toArray(String[]::new);
166 private void createEditingAndLabel(TableViewerColumn col, MicroInstructionDefinition miDef, int index)
168 ParameterClassification parameterClassification = miDef.getParameterClassifications()[index];
169 EditingSupport support;
170 ColumnLabelProvider provider;
171 switch (parameterClassification.getExpectedType())
173 case BOOLEAN_IMMEDIATE:
174 support = new BooleanEditingSupport(viewer, miDef, index);
175 provider = new ParameterLabelProvider(index);
177 case INTEGER_IMMEDIATE:
178 support = new IntegerEditingSupport(viewer, miDef, index, displaySettings, this.provider);
179 provider = new IntegerColumnLabelProvider(displaySettings, index);
182 support = new MnemonicEditingSupport(viewer, miDef, index, this.provider);
183 provider = new ParameterLabelProvider(index);
186 throw new IllegalStateException(
187 "Unable to create EditingSupport for unknown ParameterType " + parameterClassification.getExpectedType());
189 col.setEditingSupport(support);
190 col.setLabelProvider(provider);
191 col.getColumn().setToolTipText(miDef.getParameterDescription(index).orElse(""));
194 private TableViewerColumn createTableViewerColumn(String title, String... longestPossibleContents)
196 TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
197 TableColumn column = viewerColumn.getColumn();
199 for (String s : longestPossibleContents)
203 if (column.getWidth() > maxWidth)
204 maxWidth = column.getWidth();
206 column.setText(title);
208 if (column.getWidth() < maxWidth)
209 column.setWidth(maxWidth);
210 column.setResizable(true);
211 column.setMoveable(false);
215 private void open(String file)
217 try (BufferedReader bf = new BufferedReader(new FileReader(file)))
219 machineName = bf.readLine();
220 bindMicroInstructionMemory(MicroInstructionMemoryParser.parseMemory(machineName, bf));
222 catch (IOException | MicroInstructionMemoryParseException e)
228 private void save(String file)
232 System.err.println("Failed to write MicroprogrammingMemory to File. No MicroprogrammingMemory assigned.");
237 MicroInstructionMemoryParser.write(memory, machineName, file);
239 catch (IOException e)
246 public void setFocus()
248 viewer.getControl().setFocus();
252 public void doSave(IProgressMonitor progressMonitor)
254 IEditorInput input = getEditorInput();
255 if (input instanceof IPathEditorInput)
257 IPathEditorInput pathInput = (IPathEditorInput) input;
258 save(pathInput.getPath().toOSString());
264 public void doSaveAs()
269 private void openSaveAsDialog()
271 FileDialog d = new FileDialog(viewer.getTable().getShell(), SWT.SAVE);
273 String filename = d.getFileName();
274 if (!filename.equals(""))
276 save(d.getFilterPath() + File.separator + filename);
282 public void init(IEditorSite site, IEditorInput input) throws PartInitException
286 if (input instanceof IPathEditorInput)
288 IPathEditorInput pathInput = (IPathEditorInput) input;
289 setPartName(pathInput.getName());
290 open(pathInput.getPath().toOSString());
295 public boolean isDirty()
301 public boolean isSaveAsAllowed()
307 public void update(long address)
312 private void setDirty(boolean value)
315 firePropertyChange(PROP_DIRTY);