Highlighting Instructions is now based on the selected DebugTarget
[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.resources.IProject;
9 import org.eclipse.core.resources.ResourcesPlugin;
10 import org.eclipse.core.runtime.CoreException;
11 import org.eclipse.core.runtime.IProgressMonitor;
12 import org.eclipse.debug.ui.DebugUITools;
13 import org.eclipse.debug.ui.contexts.IDebugContextManager;
14 import org.eclipse.debug.ui.contexts.IDebugContextService;
15 import org.eclipse.swt.layout.GridData;
16 import org.eclipse.swt.layout.GridLayout;
17 import org.eclipse.swt.widgets.Composite;
18 import org.eclipse.ui.IEditorInput;
19 import org.eclipse.ui.IEditorSite;
20 import org.eclipse.ui.IFileEditorInput;
21 import org.eclipse.ui.PartInitException;
22 import org.eclipse.ui.PlatformUI;
23 import org.eclipse.ui.part.EditorPart;
24
25 import net.mograsim.machine.Machine;
26 import net.mograsim.machine.Machine.ActiveMicroInstructionChangedListener;
27 import net.mograsim.machine.Memory.MemoryCellModifiedListener;
28 import net.mograsim.machine.mi.MicroInstructionMemory;
29 import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
30 import net.mograsim.machine.mi.MicroInstructionMemoryParser;
31 import net.mograsim.plugin.launch.MachineDebugContextListener;
32 import net.mograsim.plugin.launch.MachineDebugTarget;
33 import net.mograsim.plugin.launch.MachineLaunchConfigType.MachineLaunchParams;
34 import net.mograsim.plugin.nature.MachineContext;
35 import net.mograsim.plugin.nature.ProjectMachineContext;
36 import net.mograsim.plugin.tables.DisplaySettings;
37 import net.mograsim.plugin.tables.RadixSelector;
38
39 public class InstructionView extends EditorPart
40 {
41         private InstructionTableContentProvider provider;
42         private boolean dirty = false;
43         private MicroInstructionMemory memory;
44         private InstructionTable table;
45         private MachineContext context;
46
47         private IFile file;
48
49         // Listeners
50         private MemoryCellModifiedListener cellModifiedListener = address ->
51         {
52                 setDirty(true);
53                 table.refresh();
54         };
55
56         private ActiveMicroInstructionChangedListener instChangeListener = (oldAddress, newAddress) ->
57         {
58                 highlight((int) (newAddress - memory.getDefinition().getMinimalAddress()));
59         };
60
61         private MachineDebugContextListener debugContextListener = new MachineDebugContextListener()
62         {
63                 @Override
64                 public void machineDebugContextChanged(Optional<MachineDebugTarget> oldTarget, Optional<MachineDebugTarget> newTarget)
65                 {
66                         instChangeListener.instructionChanged(-1, -1);
67                         oldTarget.ifPresent(target -> target.getMachine().removeActiveMicroInstructionChangedListener(instChangeListener));
68
69                         newTarget.ifPresent(target ->
70                         {
71                                 MachineLaunchParams params = target.getLaunchParams();
72                                 IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(params.getProjectPath());
73
74                                 if (file.equals(project.getFile(params.getMpmPath())))
75                                 {
76                                         Machine m = target.getMachine();
77                                         target.getMachine().addActiveMicroInstructionChangedListener(instChangeListener);
78                                         instChangeListener.instructionChanged(-1, m.getActiveMicroInstructionAddress());
79                                 }
80                         });
81                 }
82         };
83
84         @SuppressWarnings("unused")
85         @Override
86         public void createPartControl(Composite parent)
87         {
88                 provider = new InstructionTableLazyContentProvider();
89                 GridLayout layout = new GridLayout(3, false);
90                 parent.setLayout(layout);
91
92                 DisplaySettings displaySettings = new DisplaySettings();
93                 new RadixSelector(parent, displaySettings);
94
95                 table = new InstructionTable(parent, displaySettings, getSite().getWorkbenchWindow().getWorkbench().getThemeManager());
96                 table.setContentProvider(provider);
97                 table.bindMicroInstructionMemory(memory);
98
99                 GridData viewerData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
100                 viewerData.horizontalSpan = 3;
101                 table.getTableViewer().getTable().setLayoutData(viewerData);
102
103                 IDebugContextManager debugCManager = DebugUITools.getDebugContextManager();
104                 IDebugContextService contextService = debugCManager.getContextService(PlatformUI.getWorkbench().getActiveWorkbenchWindow());
105                 contextService.addDebugContextListener(debugContextListener);
106                 debugContextListener.debugContextChanged(contextService.getActiveContext());
107                 parent.addDisposeListener(e -> contextService.removeDebugContextListener(debugContextListener));
108         }
109
110         public void highlight(int row)
111         {
112                 table.highlight(row);
113         }
114
115         public void bindMicroInstructionMemory(MicroInstructionMemory memory)
116         {
117                 if (this.memory != null)
118                 {
119                         this.memory.deregisterCellModifiedListener(cellModifiedListener);
120                 }
121                 this.memory = memory;
122                 if (memory != null)
123                 {
124                         this.memory.registerCellModifiedListener(cellModifiedListener);
125                 }
126                 if (table != null)
127                         table.bindMicroInstructionMemory(memory);
128         }
129
130         private void open(IFile file) throws IOException, MicroInstructionMemoryParseException, CoreException
131         {
132                 bindMicroInstructionMemory(MicroInstructionMemoryParser.parseMemory(
133                                 context.getMachineDefinition().orElseThrow(() -> new MicroInstructionMemoryParseException("No MachineDefinition assigned!"))
134                                                 .getMicroInstructionMemoryDefinition(),
135                                 file.getContents()));
136         }
137
138         private void save(IFile file, IProgressMonitor progressMonitor) throws IOException, CoreException, MicroInstructionMemoryParseException
139         {
140                 if (memory == null)
141                 {
142                         throw new MicroInstructionMemoryParseException(
143                                         "Failed to write MicroprogrammingMemory to File. No MicroprogrammingMemory assigned.");
144                 }
145                 try (InputStream toWrite = MicroInstructionMemoryParser.write(memory))
146                 {
147                         file.setContents(toWrite, 0, progressMonitor);
148                 }
149         }
150
151         @Override
152         public void setFocus()
153         {
154                 table.getTableViewer().getControl().setFocus();
155         }
156
157         @Override
158         public void doSave(IProgressMonitor progressMonitor)
159         {
160                 IEditorInput input = getEditorInput();
161                 if (input instanceof IFileEditorInput)
162                 {
163                         IFileEditorInput pathInput = (IFileEditorInput) input;
164                         try
165                         {
166                                 save(pathInput.getFile(), progressMonitor);
167                                 setDirty(false);
168                         }
169                         catch (Exception e)
170                         {
171                                 e.printStackTrace();
172                                 progressMonitor.setCanceled(true);
173                         }
174                 } else
175                         progressMonitor.setCanceled(true);
176         }
177
178         @Override
179         public void doSaveAs()
180         {
181 //              openSaveAsDialog();
182         }
183
184 //      private void openSaveAsDialog()
185 //      {
186 //              FileDialog d = new FileDialog(table.getTableViewer().getTable().getShell(), SWT.SAVE);
187 //              d.open();
188 //              String filename = d.getFileName();
189 //              if (!filename.equals(""))
190 //              {
191 //                      save(d.getFilterPath() + File.separator + filename);
192 //                      setDirty(false);
193 //              }
194 //      }
195
196         @Override
197         public void init(IEditorSite site, IEditorInput input) throws PartInitException
198         {
199                 setSite(site);
200                 setInput(input);
201                 try
202                 {
203                         if (input instanceof IFileEditorInput)
204                         {
205                                 IFileEditorInput fileInput = (IFileEditorInput) input;
206                                 file = fileInput.getFile();
207                                 context = ProjectMachineContext.getMachineContextOf(file.getProject());
208
209                                 setPartName(fileInput.getName());
210                                 open(file);
211                         } else
212                                 throw new IllegalArgumentException("Expected IFileEditorInput!");
213                 }
214                 catch (Exception e)
215                 {
216                         throw new PartInitException("Failed to read input!", e);
217                 }
218         }
219
220         @Override
221         public boolean isDirty()
222         {
223                 return dirty;
224         }
225
226         @Override
227         public boolean isSaveAsAllowed()
228         {
229                 return false;
230         }
231
232         private void setDirty(boolean value)
233         {
234                 dirty = value;
235                 firePropertyChange(PROP_DIRTY);
236         }
237
238         @Override
239         public void dispose()
240         {
241                 memory.deregisterCellModifiedListener(cellModifiedListener);
242                 super.dispose();
243         }
244 }