Added null check in dispose() of InstructionView
[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 import java.util.Optional;
6
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.debug.ui.DebugUITools;
11 import org.eclipse.debug.ui.contexts.IDebugContextManager;
12 import org.eclipse.debug.ui.contexts.IDebugContextService;
13 import org.eclipse.swt.layout.GridData;
14 import org.eclipse.swt.layout.GridLayout;
15 import org.eclipse.swt.widgets.Composite;
16 import org.eclipse.ui.IEditorInput;
17 import org.eclipse.ui.IEditorSite;
18 import org.eclipse.ui.IFileEditorInput;
19 import org.eclipse.ui.PartInitException;
20 import org.eclipse.ui.PlatformUI;
21 import org.eclipse.ui.part.EditorPart;
22
23 import net.mograsim.machine.Machine;
24 import net.mograsim.machine.Machine.ActiveMicroInstructionChangedListener;
25 import net.mograsim.machine.Memory.MemoryCellModifiedListener;
26 import net.mograsim.machine.mi.MicroInstructionMemory;
27 import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
28 import net.mograsim.machine.mi.MicroInstructionMemoryParser;
29 import net.mograsim.plugin.launch.MachineDebugContextListener;
30 import net.mograsim.plugin.launch.MachineDebugTarget;
31 import net.mograsim.plugin.nature.MachineContext;
32 import net.mograsim.plugin.nature.ProjectMachineContext;
33 import net.mograsim.plugin.tables.DisplaySettings;
34 import net.mograsim.plugin.tables.RadixSelector;
35
36 public class InstructionView extends EditorPart
37 {
38         private InstructionTableContentProvider provider;
39         private boolean dirty = false;
40         private MicroInstructionMemory memory;
41         private InstructionTable table;
42         private MachineContext context;
43
44         private IFile file;
45
46         // Listeners
47         private MemoryCellModifiedListener cellModifiedListener = address ->
48         {
49                 setDirty(true);
50                 table.refresh();
51         };
52
53         private ActiveMicroInstructionChangedListener instChangeListener = (oldAddress, newAddress) ->
54         {
55                 highlight((int) (newAddress - memory.getDefinition().getMinimalAddress()));
56         };
57
58         private MachineDebugContextListener debugContextListener = new MachineDebugContextListener()
59         {
60                 @Override
61                 public void machineDebugContextChanged(Optional<MachineDebugTarget> oldTarget, Optional<MachineDebugTarget> newTarget)
62                 {
63                         instChangeListener.instructionChanged(-1, -1);
64                         oldTarget.ifPresent(target -> target.getMachine().removeActiveMicroInstructionChangedListener(instChangeListener));
65
66                         newTarget.ifPresent(target ->
67                         {
68                                 if (file.equals(target.getMPMFile()))
69                                 {
70                                         Machine m = target.getMachine();
71                                         target.getMachine().addActiveMicroInstructionChangedListener(instChangeListener);
72                                         instChangeListener.instructionChanged(-1, m.getActiveMicroInstructionAddress());
73                                 }
74                         });
75                 }
76         };
77
78         @SuppressWarnings("unused")
79         @Override
80         public void createPartControl(Composite parent)
81         {
82                 provider = new InstructionTableLazyContentProvider();
83                 GridLayout layout = new GridLayout(3, false);
84                 parent.setLayout(layout);
85
86                 DisplaySettings displaySettings = new DisplaySettings();
87                 new RadixSelector(parent, displaySettings);
88
89                 table = new InstructionTable(parent, displaySettings, getSite().getWorkbenchWindow().getWorkbench().getThemeManager());
90                 table.setContentProvider(provider);
91                 table.bindMicroInstructionMemory(memory);
92
93                 GridData viewerData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
94                 viewerData.horizontalSpan = 3;
95                 table.getTableViewer().getTable().setLayoutData(viewerData);
96
97                 IDebugContextManager debugCManager = DebugUITools.getDebugContextManager();
98                 IDebugContextService contextService = debugCManager.getContextService(PlatformUI.getWorkbench().getActiveWorkbenchWindow());
99                 contextService.addDebugContextListener(debugContextListener);
100                 debugContextListener.debugContextChanged(contextService.getActiveContext());
101                 parent.addDisposeListener(e -> contextService.removeDebugContextListener(debugContextListener));
102         }
103
104         public void highlight(int row)
105         {
106                 table.highlight(row);
107         }
108
109         public void bindMicroInstructionMemory(MicroInstructionMemory memory)
110         {
111                 if (this.memory != null)
112                 {
113                         this.memory.deregisterCellModifiedListener(cellModifiedListener);
114                 }
115                 this.memory = memory;
116                 if (memory != null)
117                 {
118                         this.memory.registerCellModifiedListener(cellModifiedListener);
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                                 file = fileInput.getFile();
201                                 context = ProjectMachineContext.getMachineContextOf(file.getProject());
202
203                                 setPartName(fileInput.getName());
204                                 open(file);
205                         } else
206                                 throw new IllegalArgumentException("Expected IFileEditorInput!");
207                 }
208                 catch (Exception e)
209                 {
210                         throw new PartInitException("Failed to read input!", e);
211                 }
212         }
213
214         @Override
215         public boolean isDirty()
216         {
217                 return dirty;
218         }
219
220         @Override
221         public boolean isSaveAsAllowed()
222         {
223                 return false;
224         }
225
226         private void setDirty(boolean value)
227         {
228                 dirty = value;
229                 firePropertyChange(PROP_DIRTY);
230         }
231
232         @Override
233         public void dispose()
234         {
235                 if (memory != null)
236                         memory.deregisterCellModifiedListener(cellModifiedListener);
237                 super.dispose();
238         }
239
240         public IFile getFile()
241         {
242                 return file;
243         }
244 }