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