235e3e533b27c6353a210de40b1298b7662c1098
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / tables / mi / InstructionView.java
1 package net.mograsim.plugin.tables.mi;
2
3 import java.io.IOException;
4 import java.io.InputStream;
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.swt.SWT;
10 import org.eclipse.swt.layout.GridData;
11 import org.eclipse.swt.layout.GridLayout;
12 import org.eclipse.swt.widgets.Button;
13 import org.eclipse.swt.widgets.Composite;
14 import org.eclipse.swt.widgets.Display;
15 import org.eclipse.ui.IEditorInput;
16 import org.eclipse.ui.IEditorSite;
17 import org.eclipse.ui.IFileEditorInput;
18 import org.eclipse.ui.PartInitException;
19 import org.eclipse.ui.part.EditorPart;
20
21 import net.mograsim.machine.Memory.MemoryCellModifiedListener;
22 import net.mograsim.machine.mi.AssignableMicroInstructionMemory.MIMemoryReassignedListener;
23 import net.mograsim.machine.mi.MicroInstructionMemory;
24 import net.mograsim.machine.mi.MicroInstructionMemory.ActiveMicroInstructionChangedListener;
25 import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
26 import net.mograsim.machine.mi.MicroInstructionMemoryParser;
27 import net.mograsim.plugin.nature.MachineContext;
28 import net.mograsim.plugin.nature.ProjectMachineContext;
29 import net.mograsim.plugin.tables.DisplaySettings;
30 import net.mograsim.plugin.tables.LazyTableViewer;
31 import net.mograsim.plugin.tables.RadixSelector;
32
33 public class InstructionView extends EditorPart implements MemoryCellModifiedListener, ActiveMicroInstructionChangedListener
34 {
35         private InstructionTableContentProvider provider;
36         private int highlighted = 0;
37         private boolean dirty = false;
38         private MicroInstructionMemory memory;
39         private InstructionTable table;
40         private MachineContext context;
41
42         @SuppressWarnings("unused")
43         @Override
44         public void createPartControl(Composite parent)
45         {
46                 provider = new InstructionTableLazyContentProvider();
47                 GridLayout layout = new GridLayout(3, false);
48                 parent.setLayout(layout);
49
50                 DisplaySettings displaySettings = new DisplaySettings();
51                 new RadixSelector(parent, displaySettings);
52
53                 addActivationButton(parent);
54
55                 table = new InstructionTable(parent, displaySettings);
56                 table.setContentProvider(provider);
57                 table.bindMicroInstructionMemory(memory);
58
59                 GridData viewerData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
60                 viewerData.horizontalSpan = 3;
61                 table.getTableViewer().getTable().setLayoutData(viewerData);
62         }
63
64         public void highlight(int index)
65         {
66                 Display.getDefault().asyncExec(() ->
67                 {
68                         LazyTableViewer viewer = table.getTableViewer();
69                         viewer.highlightRow(highlighted, false);
70                         highlighted = index;
71                         if (index != -1)
72                         {
73                                 viewer.highlightRow(index, true);
74                                 viewer.getTable()
75                                                 .showItem(viewer.getTable().getItem(Math.min((int) memory.getDefinition().getMaximalAddress(), index + 2)));
76                                 viewer.getTable().showItem(viewer.getTable().getItem(index));
77                         }
78                 });
79         }
80
81         private void addActivationButton(Composite parent)
82         {
83                 Button activationButton = new Button(parent, SWT.PUSH);
84                 activationButton.setText("Set Active");
85                 activationButton.addListener(SWT.Selection, e -> context.getActiveMachine().ifPresent(m ->
86                 {
87                         // clear highlighting if the memory is reassigned
88                         MIMemoryReassignedListener memReassignedListener = n ->
89                         {
90                                 if (n != memory)
91                                         highlight(-1);
92                         };
93                         m.getMicroInstructionMemory().registerMemoryReassignedListener(memReassignedListener);
94                         // clear highlighting if the active machine changes
95                         context.addActiveMachineListener(n ->
96                         {
97                                 if (n.isEmpty() || n.get() != m)
98                                 {
99                                         highlight(-1);
100                                         m.getMicroInstructionMemory().deregisterMemoryReassignedListener(memReassignedListener);
101                                 }
102                         });
103                         m.getMicroInstructionMemory().bind(memory);
104                 }));
105         }
106
107         public void bindMicroInstructionMemory(MicroInstructionMemory memory)
108         {
109                 if (this.memory != null)
110                 {
111                         this.memory.deregisterCellModifiedListener(this);
112                         this.memory.deregisterActiveMicroInstructionChangedListener(this);
113                 }
114                 this.memory = memory;
115                 if (memory != null)
116                 {
117                         this.memory.registerCellModifiedListener(this);
118                         this.memory.registerActiveMicroInstructionChangedListener(this);
119                 }
120                 if (table != null)
121                         table.bindMicroInstructionMemory(memory);
122         }
123
124         private void open(IFile file) throws IOException, MicroInstructionMemoryParseException, CoreException
125         {
126                 bindMicroInstructionMemory(MicroInstructionMemoryParser.parseMemory(
127                                 context.getMachineDefinition().orElseThrow(() -> new MicroInstructionMemoryParseException("No MachineDefinition assigned!"))
128                                                 .getMicroInstructionMemoryDefinition(),
129                                 file.getContents()));
130         }
131
132         private void save(IFile file, IProgressMonitor progressMonitor) throws IOException, CoreException, MicroInstructionMemoryParseException
133         {
134                 if (memory == null)
135                 {
136                         throw new MicroInstructionMemoryParseException(
137                                         "Failed to write MicroprogrammingMemory to File. No MicroprogrammingMemory assigned.");
138                 }
139                 try (InputStream toWrite = MicroInstructionMemoryParser.write(memory))
140                 {
141                         file.setContents(toWrite, 0, progressMonitor);
142                 }
143         }
144
145         @Override
146         public void setFocus()
147         {
148                 table.getTableViewer().getControl().setFocus();
149         }
150
151         @Override
152         public void doSave(IProgressMonitor progressMonitor)
153         {
154                 IEditorInput input = getEditorInput();
155                 if (input instanceof IFileEditorInput)
156                 {
157                         IFileEditorInput pathInput = (IFileEditorInput) input;
158                         try
159                         {
160                                 save(pathInput.getFile(), progressMonitor);
161                                 setDirty(false);
162                         }
163                         catch (Exception e)
164                         {
165                                 e.printStackTrace();
166                                 progressMonitor.setCanceled(true);
167                         }
168                 } else
169                         progressMonitor.setCanceled(true);
170         }
171
172         @Override
173         public void doSaveAs()
174         {
175 //              openSaveAsDialog();
176         }
177
178 //      private void openSaveAsDialog()
179 //      {
180 //              FileDialog d = new FileDialog(table.getTableViewer().getTable().getShell(), SWT.SAVE);
181 //              d.open();
182 //              String filename = d.getFileName();
183 //              if (!filename.equals(""))
184 //              {
185 //                      save(d.getFilterPath() + File.separator + filename);
186 //                      setDirty(false);
187 //              }
188 //      }
189
190         @Override
191         public void init(IEditorSite site, IEditorInput input) throws PartInitException
192         {
193                 setSite(site);
194                 setInput(input);
195                 try
196                 {
197                         if (input instanceof IFileEditorInput)
198                         {
199                                 IFileEditorInput fileInput = (IFileEditorInput) input;
200                                 context = ProjectMachineContext.getMachineContextOf(fileInput.getFile().getProject());
201                                 context.activateMachine();
202                                 setPartName(fileInput.getName());
203                                 open(fileInput.getFile());
204                         }
205                 }
206                 catch (Exception e)
207                 {
208                         throw new PartInitException("Failed to read input!", e);
209                 }
210
211         }
212
213         @Override
214         public boolean isDirty()
215         {
216                 return dirty;
217         }
218
219         @Override
220         public boolean isSaveAsAllowed()
221         {
222                 return false;
223         }
224
225         @Override
226         public void update(long address)
227         {
228                 setDirty(true);
229                 table.refresh();
230         }
231
232         private void setDirty(boolean value)
233         {
234                 dirty = value;
235                 firePropertyChange(PROP_DIRTY);
236         }
237
238         @Override
239         public void activeMicroInstructionChanged(long address)
240         {
241                 highlight((int) (address - memory.getDefinition().getMinimalAddress()));
242         }
243 }