1 package net.mograsim.plugin.editors;
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.math.BigInteger;
7 import org.eclipse.core.resources.IFile;
8 import org.eclipse.core.runtime.CoreException;
9 import org.eclipse.core.runtime.IProgressMonitor;
10 import org.eclipse.jface.util.IPropertyChangeListener;
11 import org.eclipse.jface.util.SafeRunnable;
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.Label;
19 import org.eclipse.swt.widgets.Table;
20 import org.eclipse.swt.widgets.TableColumn;
21 import org.eclipse.swt.widgets.Text;
22 import org.eclipse.ui.IEditorInput;
23 import org.eclipse.ui.IEditorSite;
24 import org.eclipse.ui.IFileEditorInput;
25 import org.eclipse.ui.PartInitException;
26 import org.eclipse.ui.part.EditorPart;
27 import org.eclipse.ui.themes.ITheme;
28 import org.eclipse.ui.themes.IThemeManager;
30 import net.mograsim.machine.MainMemory;
31 import net.mograsim.machine.MainMemoryDefinition;
32 import net.mograsim.machine.Memory.MemoryCellModifiedListener;
33 import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
34 import net.mograsim.machine.standard.memory.MainMemoryParser;
35 import net.mograsim.plugin.asm.AsmNumberUtil;
36 import net.mograsim.plugin.nature.MachineContext;
37 import net.mograsim.plugin.nature.ProjectMachineContext;
38 import net.mograsim.plugin.tables.AddressLabelProvider;
39 import net.mograsim.plugin.tables.DisplaySettings;
40 import net.mograsim.plugin.tables.LazyTableViewer;
41 import net.mograsim.plugin.tables.NumberColumnLabelProvider;
42 import net.mograsim.plugin.tables.RadixSelector;
43 import net.mograsim.plugin.tables.memory.MemoryCellEditingSupport;
44 import net.mograsim.plugin.tables.memory.MemoryTableContentProvider;
45 import net.mograsim.plugin.tables.memory.MemoryTableRow;
46 import net.mograsim.plugin.tables.memory.NumberVerifyListener;
48 public class MemoryEditor extends EditorPart
50 private MachineContext context;
52 private MainMemory memory;
54 private LazyTableViewer viewer;
55 private MemoryTableContentProvider provider;
56 private DisplaySettings displaySettings;
58 private boolean dirty;
60 private final MemoryCellModifiedListener memListener;
62 private final static String font = "net.mograsim.plugin.memory.table_font";
63 private IPropertyChangeListener fontChangeListener;
67 memListener = this::cellModified;
71 public void createPartControl(Composite parent)
73 provider = new MemoryTableContentProvider();
74 displaySettings = new DisplaySettings();
76 parent.setLayout(new GridLayout(7, false));
81 displaySettings.addObserver(() -> viewer.refresh());
84 @SuppressWarnings("unused") // RadixSelector and exceptions
85 private void createHeader(Composite parent)
87 Label fromLabel = new Label(parent, SWT.NONE);
88 fromLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
89 fromLabel.setText("Address: ");
91 Text fromText = new Text(parent, SWT.BORDER);
92 fromText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
93 NumberVerifyListener vl = new NumberVerifyListener();
94 fromText.addVerifyListener(vl);
95 fromText.setText("0");
96 fromText.addModifyListener(e ->
100 provider.setLowerBound(AsmNumberUtil.valueOf(fromText.getText()).longValue());
103 catch (NumberFormatException x)
105 // Nothing to do here
108 Label amountLabel = new Label(parent, SWT.NONE);
109 amountLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
110 amountLabel.setText("Number of cells: ");
111 Text amountText = new Text(parent, SWT.BORDER);
112 amountText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
113 amountText.addVerifyListener(vl);
114 amountText.setText("0");
115 amountText.addModifyListener(e ->
119 provider.setAmount(AsmNumberUtil.valueOf(amountText.getText()).intValue());
122 catch (NumberFormatException x)
124 // Nothing to do here
127 new RadixSelector(parent, displaySettings);
129 addActivationButton(parent);
132 private void addActivationButton(Composite parent)
134 Button activationButton = new Button(parent, SWT.PUSH);
135 activationButton.setText("Set Active");
136 activationButton.addListener(SWT.Selection, e -> context.getActiveMachine().ifPresent(m -> m.getMainMemory().bind(memory)));
139 private void createViewer(Composite parent)
141 viewer = new LazyTableViewer(parent, SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
143 Table table = viewer.getTable();
144 table.setHeaderVisible(true);
145 table.setLinesVisible(true);
146 viewer.setUseHashlookup(true);
147 viewer.setContentProvider(provider);
148 getSite().setSelectionProvider(viewer);// TODO what does this do?
149 viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 7, 1));
151 IThemeManager themeManager = getSite().getWorkbenchWindow().getWorkbench().getThemeManager();
152 themeManager.addPropertyChangeListener(fontChangeListener = (e) ->
154 if (IThemeManager.CHANGE_CURRENT_THEME.equals(e.getProperty()) || font.equals(e.getProperty()))
156 updateFont(themeManager.getCurrentTheme());
160 updateFont(themeManager.getCurrentTheme());
163 viewer.setInput(memory);
166 private void updateFont(ITheme theme)
168 viewer.getTable().setFont(theme.getFontRegistry().get(font));
171 private void createColumns()
173 TableViewerColumn addrCol = createTableViewerColumn("Address", 100);
174 addrCol.setLabelProvider(new AddressLabelProvider());
176 TableViewerColumn dataCol = createTableViewerColumn("Data", 100);
177 dataCol.setLabelProvider(new NumberColumnLabelProvider(displaySettings)
180 public BigInteger getAsBigInteger(Object element)
182 MemoryTableRow row = (MemoryTableRow) element;
183 return row.getMemory().getCellAsBigInteger(row.address);
187 public int getBitLength(Object element)
189 return ((MemoryTableRow) element).getMemory().getDefinition().getCellWidth();
192 dataCol.setEditingSupport(new MemoryCellEditingSupport(viewer, displaySettings));
195 private TableViewerColumn createTableViewerColumn(String title, int width)
197 TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
198 TableColumn column = viewerColumn.getColumn();
199 column.setText(title);
200 column.setWidth(width);
201 column.setResizable(true);
202 column.setMoveable(false);
207 public void init(IEditorSite site, IEditorInput input) throws PartInitException
209 if (input instanceof IFileEditorInput)
211 IFileEditorInput fileInput = (IFileEditorInput) input;
212 context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
213 context.activateMachine();
215 setPartName(fileInput.getName());
218 open(fileInput.getFile());
222 throw new PartInitException("Failed to read input!", e);
225 throw new IllegalArgumentException("MemoryEditor can only be used with Files");
232 public void doSave(IProgressMonitor monitor)
234 IEditorInput input = getEditorInput();
235 if (input instanceof IFileEditorInput)
236 SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
239 private void save(IFile file, IProgressMonitor monitor) throws CoreException, IOException
243 throw new MicroInstructionMemoryParseException("Failed to write MainMemory to File. No MainMemory assigned.");
245 try (InputStream toWrite = MainMemoryParser.write(memory))
247 file.setContents(toWrite, 0, monitor);
252 private void open(IFile file) throws IOException, CoreException
254 MainMemoryDefinition memDef = context.getMachineDefinition()
255 .orElseThrow(() -> new MicroInstructionMemoryParseException("No MachineDefinition assigned!")).getMainMemoryDefinition();
256 memory = MainMemoryParser.parseMemory(memDef, file.getContents());
257 memory.registerCellModifiedListener(memListener);
259 viewer.setInput(memory);
262 private void cellModified(@SuppressWarnings("unused") long address)
267 private void setDirty(boolean newDirty)
270 firePropertyChange(PROP_DIRTY);
274 public void doSaveAs()
276 throw new UnsupportedOperationException();
280 public boolean isDirty()
286 public boolean isSaveAsAllowed()
292 public void setFocus()
294 viewer.getTable().setFocus();
298 public void dispose()
300 getSite().getWorkbenchWindow().getWorkbench().getThemeManager().removePropertyChangeListener(fontChangeListener);
302 memory.deregisterCellModifiedListener(memListener);