Made MemoryView to an Editor
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / editors / MemoryEditor.java
1 package net.mograsim.plugin.editors;
2
3 import java.io.ByteArrayInputStream;
4 import java.math.BigInteger;
5
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.jface.viewers.TableViewerColumn;
11 import org.eclipse.swt.SWT;
12 import org.eclipse.swt.layout.GridData;
13 import org.eclipse.swt.layout.GridLayout;
14 import org.eclipse.swt.widgets.Button;
15 import org.eclipse.swt.widgets.Composite;
16 import org.eclipse.swt.widgets.Label;
17 import org.eclipse.swt.widgets.Table;
18 import org.eclipse.swt.widgets.TableColumn;
19 import org.eclipse.swt.widgets.Text;
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;
25
26 import net.mograsim.machine.MainMemory;
27 import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
28 import net.mograsim.machine.standard.memory.WordAddressableMemory;
29 import net.mograsim.plugin.asm.AsmNumberUtil;
30 import net.mograsim.plugin.nature.MachineContext;
31 import net.mograsim.plugin.nature.ProjectMachineContext;
32 import net.mograsim.plugin.tables.AddressLabelProvider;
33 import net.mograsim.plugin.tables.DisplaySettings;
34 import net.mograsim.plugin.tables.LazyTableViewer;
35 import net.mograsim.plugin.tables.NumberColumnLabelProvider;
36 import net.mograsim.plugin.tables.RadixSelector;
37 import net.mograsim.plugin.tables.memory.MemoryCellEditingSupport;
38 import net.mograsim.plugin.tables.memory.MemoryTableContentProvider;
39 import net.mograsim.plugin.tables.memory.MemoryTableRow;
40 import net.mograsim.plugin.tables.memory.NumberVerifyListener;
41
42 public class MemoryEditor extends EditorPart
43 {
44         private MachineContext context;
45
46         private MainMemory memory;
47
48         private LazyTableViewer viewer;
49         private MemoryTableContentProvider provider;
50         private DisplaySettings displaySettings;
51
52         @Override
53         public void createPartControl(Composite parent)
54         {
55                 provider = new MemoryTableContentProvider();
56                 displaySettings = new DisplaySettings();
57
58                 parent.setLayout(new GridLayout(7, false));
59
60                 createHeader(parent);
61                 createViewer(parent);
62
63                 displaySettings.addObserver(() -> viewer.refresh());
64         }
65
66         @SuppressWarnings("unused") // RadixSelector and exceptions
67         private void createHeader(Composite parent)
68         {
69                 Label fromLabel = new Label(parent, SWT.NONE);
70                 fromLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
71                 fromLabel.setText("Address: ");
72
73                 Text fromText = new Text(parent, SWT.BORDER);
74                 fromText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
75                 NumberVerifyListener vl = new NumberVerifyListener();
76                 fromText.addVerifyListener(vl);
77                 fromText.setText("0");
78                 fromText.addModifyListener(e ->
79                 {
80                         try
81                         {
82                                 provider.setLowerBound(AsmNumberUtil.valueOf(fromText.getText()).longValue());
83                                 viewer.refresh();
84                         }
85                         catch (NumberFormatException x)
86                         {
87                                 // Nothing to do here
88                         }
89                 });
90                 Label amountLabel = new Label(parent, SWT.NONE);
91                 amountLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
92                 amountLabel.setText("Number of cells: ");
93                 Text amountText = new Text(parent, SWT.BORDER);
94                 amountText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
95                 amountText.addVerifyListener(vl);
96                 amountText.setText("0");
97                 amountText.addModifyListener(e ->
98                 {
99                         try
100                         {
101                                 provider.setAmount(AsmNumberUtil.valueOf(amountText.getText()).intValue());
102                                 viewer.refresh();
103                         }
104                         catch (NumberFormatException x)
105                         {
106                                 // Nothing to do here
107                         }
108                 });
109                 new RadixSelector(parent, displaySettings);
110
111                 addActivationButton(parent);
112         }
113
114         private void addActivationButton(Composite parent)
115         {
116                 Button activationButton = new Button(parent, SWT.PUSH);
117                 activationButton.setText("Set Active");
118                 activationButton.addListener(SWT.Selection, e -> context.getActiveMachine().ifPresent(m -> m.getMainMemory().bind(memory)));
119         }
120
121         private void createViewer(Composite parent)
122         {
123                 viewer = new LazyTableViewer(parent, SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
124                 createColumns();
125                 Table table = viewer.getTable();
126                 table.setHeaderVisible(true);
127                 table.setLinesVisible(true);
128                 viewer.setUseHashlookup(true);
129                 viewer.setContentProvider(provider);
130                 getSite().setSelectionProvider(viewer);// TODO what does this?
131                 viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 7, 1));
132                 if (memory != null)
133                         viewer.setInput(memory);
134         }
135
136         private void createColumns()
137         {
138                 TableViewerColumn addrCol = createTableViewerColumn("Address", 100);
139                 addrCol.setLabelProvider(new AddressLabelProvider());
140
141                 TableViewerColumn dataCol = createTableViewerColumn("Data", 100);
142                 dataCol.setLabelProvider(new NumberColumnLabelProvider(displaySettings)
143                 {
144                         @Override
145                         public BigInteger getAsBigInteger(Object element)
146                         {
147                                 MemoryTableRow row = (MemoryTableRow) element;
148                                 return row.getMemory().getCellAsBigInteger(row.address);
149                         }
150
151                         @Override
152                         public int getBitLength(Object element)
153                         {
154                                 return ((MemoryTableRow) element).getMemory().getDefinition().getCellWidth();
155                         }
156                 });
157                 dataCol.setEditingSupport(new MemoryCellEditingSupport(viewer, displaySettings));
158         }
159
160         private TableViewerColumn createTableViewerColumn(String title, int width)
161         {
162                 TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
163                 TableColumn column = viewerColumn.getColumn();
164                 column.setText(title);
165                 column.setWidth(width);
166                 column.setResizable(true);
167                 column.setMoveable(false);
168                 return viewerColumn;
169         }
170
171         @Override
172         public void init(IEditorSite site, IEditorInput input) throws PartInitException
173         {
174                 if (input instanceof IFileEditorInput)
175                 {
176                         IFileEditorInput fileInput = (IFileEditorInput) input;
177                         context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
178                         context.activateMachine();
179
180                         setPartName(fileInput.getName());
181                         open(fileInput.getFile());
182                 } else
183                         throw new IllegalArgumentException("MemoryEditor can only be used with Files");
184
185                 setSite(site);
186                 setInput(input);
187         }
188
189         @Override
190         public void doSave(IProgressMonitor monitor)
191         {
192                 IEditorInput input = getEditorInput();
193                 if (input instanceof IFileEditorInput)
194                         SafeRunnable.getRunner().run(() -> save(((IFileEditorInput) input).getFile(), monitor));
195         }
196
197         private void save(IFile file, IProgressMonitor monitor) throws CoreException
198         {
199                 file.setContents(new ByteArrayInputStream("actual contents will go here".getBytes()), 0, monitor);
200         }
201
202         private void open(IFile file)
203         {
204                 // TODO actually parse the file
205                 memory = new WordAddressableMemory(context.getMachineDefinition()
206                                 .orElseThrow(() -> new MicroInstructionMemoryParseException("No MachineDefinition assigned!")).getMainMemoryDefinition());
207                 if (viewer != null)
208                         viewer.setInput(memory);
209         }
210
211         @Override
212         public void doSaveAs()
213         {
214                 throw new UnsupportedOperationException();
215         }
216
217         @Override
218         public boolean isDirty()
219         {
220                 // TODO
221                 return false;
222         }
223
224         @Override
225         public boolean isSaveAsAllowed()
226         {
227                 return false;
228         }
229
230         @Override
231         public void setFocus()
232         {
233                 viewer.getTable().setFocus();
234         }
235
236         @Override
237         public void dispose()
238         {
239                 // TODO Auto-generated method stub
240                 super.dispose();
241         }
242 }