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.events.SelectionEvent;
15 import org.eclipse.swt.events.SelectionListener;
16 import org.eclipse.swt.layout.GridData;
17 import org.eclipse.swt.layout.GridLayout;
18 import org.eclipse.swt.widgets.Button;
19 import org.eclipse.swt.widgets.Composite;
20 import org.eclipse.swt.widgets.FileDialog;
21 import org.eclipse.swt.widgets.Table;
22 import org.eclipse.swt.widgets.TableColumn;
23 import org.eclipse.ui.IEditorInput;
24 import org.eclipse.ui.IEditorSite;
25 import org.eclipse.ui.IPathEditorInput;
26 import org.eclipse.ui.PartInitException;
27 import org.eclipse.ui.part.EditorPart;
29 import net.mograsim.machine.MemoryObserver;
30 import net.mograsim.machine.mi.MicroInstructionDefinition;
31 import net.mograsim.machine.mi.MicroInstructionMemory;
32 import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
33 import net.mograsim.machine.mi.MicroInstructionMemoryParser;
34 import net.mograsim.machine.mi.parameters.MnemonicFamily;
35 import net.mograsim.machine.mi.parameters.ParameterClassification;
36 import net.mograsim.plugin.MachineContext;
37 import net.mograsim.plugin.tables.AddressLabelProvider;
38 import net.mograsim.plugin.tables.DisplaySettings;
39 import net.mograsim.plugin.tables.LazyTableViewer;
40 import net.mograsim.plugin.tables.RadixSelector;
42 public class InstructionView extends EditorPart implements MemoryObserver
44 private LazyTableViewer viewer;
45 private TableViewerColumn[] columns = new TableViewerColumn[0];
46 private MicroInstructionDefinition miDef;
47 private MicroInstructionMemory memory;
48 private DisplaySettings displaySettings;
49 private InstructionTableContentProvider provider;
50 private int highlighted = 0;
51 private boolean dirty = false;
52 private String machineName;
54 @SuppressWarnings("unused")
56 public void createPartControl(Composite parent)
58 provider = new InstructionTableContentProvider();
59 GridLayout layout = new GridLayout(3, false);
60 parent.setLayout(layout);
62 displaySettings = new DisplaySettings();
63 new RadixSelector(parent, displaySettings);
65 addActivationButton(parent);
66 viewer = new LazyTableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
68 Table table = viewer.getTable();
69 table.setHeaderVisible(true);
70 table.setLinesVisible(true);
71 viewer.setUseHashlookup(true);
72 viewer.setContentProvider(provider);
73 setViewerInput(memory);
74 getSite().setSelectionProvider(viewer);
76 GridData viewerData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
77 viewerData.horizontalSpan = 3;
78 viewer.getTable().setLayoutData(viewerData);
80 displaySettings.addObserver(() -> viewer.refresh());
83 private void addActivationButton(Composite parent)
85 Button activationButton = new Button(parent, SWT.PUSH);
86 activationButton.setText("Set Active");
87 activationButton.addSelectionListener(new SelectionListener()
91 public void widgetSelected(SelectionEvent e)
93 if (e.detail == SWT.PUSH)
94 MachineContext.getInstance().getMachine().getMicroInstructionMemory().bind(memory);
95 // TODO register this in project context
99 public void widgetDefaultSelected(SelectionEvent e)
106 public void highlight(int index)
108 viewer.highlightRow(highlighted, false);
109 viewer.highlightRow(index, true);
110 viewer.getTable().setTopIndex(index);
113 public void bindMicroInstructionMemory(MicroInstructionMemory memory)
115 this.memory = memory;
116 this.miDef = memory.getDefinition().getMicroInstructionDefinition();
117 this.memory.registerObserver(this);
118 setViewerInput(memory);
121 private void setViewerInput(MicroInstructionMemory memory)
126 viewer.setInput(memory);
131 private void deleteColumns()
133 for (TableViewerColumn col : columns)
134 col.getColumn().dispose();
137 private void createColumns()
139 int size = miDef.size();
140 columns = new TableViewerColumn[size + 1];
142 TableViewerColumn col = createTableViewerColumn("Address", generateLongestHexStrings(12));
144 col.setLabelProvider(new AddressLabelProvider());
146 int bit = miDef.sizeInBits();
147 ParameterClassification[] classes = miDef.getParameterClassifications();
149 for (int i = 0; i < size; i++)
151 int startBit = bit - 1;
152 int endBit = bit = bit - classes[i].getExpectedBits();
153 String name = startBit == endBit ? Integer.toString(startBit) : startBit + "..." + endBit;
155 String[] longestPossibleContents;
156 switch (classes[i].getExpectedType())
158 case INTEGER_IMMEDIATE:
159 longestPossibleContents = generateLongestHexStrings(classes[i].getExpectedBits());
161 case BOOLEAN_IMMEDIATE:
163 longestPossibleContents = ((MnemonicFamily) classes[i]).getStringValues();
166 longestPossibleContents = new String[0];
170 col = createTableViewerColumn(name, longestPossibleContents);
171 columns[i + 1] = col;
172 createEditingAndLabel(col, miDef, i);
176 private static final String[] HEX_DIGITS = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" };
178 private static String[] generateLongestHexStrings(int bitWidth)
180 return Arrays.stream(HEX_DIGITS).map(s -> "0x" + s.repeat((bitWidth + 3) / 4)).toArray(String[]::new);
183 private void createEditingAndLabel(TableViewerColumn col, MicroInstructionDefinition miDef, int index)
185 ParameterClassification parameterClassification = miDef.getParameterClassifications()[index];
186 EditingSupport support;
187 ColumnLabelProvider provider;
188 switch (parameterClassification.getExpectedType())
190 case BOOLEAN_IMMEDIATE:
191 support = new BooleanEditingSupport(viewer, miDef, index);
192 provider = new ParameterLabelProvider(index);
194 case INTEGER_IMMEDIATE:
195 support = new IntegerEditingSupport(viewer, miDef, index, displaySettings, this.provider);
196 provider = new IntegerColumnLabelProvider(displaySettings, index);
199 support = new MnemonicEditingSupport(viewer, miDef, index, this.provider);
200 provider = new ParameterLabelProvider(index);
203 throw new IllegalStateException(
204 "Unable to create EditingSupport for unknown ParameterType " + parameterClassification.getExpectedType());
206 col.setEditingSupport(support);
207 col.setLabelProvider(provider);
208 col.getColumn().setToolTipText(miDef.getParameterDescription(index).orElse(""));
211 private TableViewerColumn createTableViewerColumn(String title, String... longestPossibleContents)
213 TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
214 TableColumn column = viewerColumn.getColumn();
216 for (String s : longestPossibleContents)
220 if (column.getWidth() > maxWidth)
221 maxWidth = column.getWidth();
223 column.setText(title);
225 if (column.getWidth() < maxWidth)
226 column.setWidth(maxWidth);
227 column.setResizable(true);
228 column.setMoveable(false);
232 private void open(String file)
234 try (BufferedReader bf = new BufferedReader(new FileReader(file)))
236 machineName = bf.readLine();
237 bindMicroInstructionMemory(MicroInstructionMemoryParser.parseMemory(machineName, bf));
239 catch (IOException | MicroInstructionMemoryParseException e)
245 private void save(String file)
249 System.err.println("Failed to write MicroprogrammingMemory to File. No MicroprogrammingMemory assigned.");
254 MicroInstructionMemoryParser.write(memory, machineName, file);
256 catch (IOException e)
263 public void setFocus()
265 viewer.getControl().setFocus();
269 public void doSave(IProgressMonitor progressMonitor)
271 IEditorInput input = getEditorInput();
272 if (input instanceof IPathEditorInput)
274 IPathEditorInput pathInput = (IPathEditorInput) input;
275 save(pathInput.getPath().toOSString());
281 public void doSaveAs()
286 private void openSaveAsDialog()
288 FileDialog d = new FileDialog(viewer.getTable().getShell(), SWT.SAVE);
290 String filename = d.getFileName();
291 if (!filename.equals(""))
293 save(d.getFilterPath() + File.separator + filename);
299 public void init(IEditorSite site, IEditorInput input) throws PartInitException
303 if (input instanceof IPathEditorInput)
305 IPathEditorInput pathInput = (IPathEditorInput) input;
306 setPartName(pathInput.getName());
307 open(pathInput.getPath().toOSString());
312 public boolean isDirty()
318 public boolean isSaveAsAllowed()
324 public void update(long address)
329 private void setDirty(boolean value)
332 firePropertyChange(PROP_DIRTY);