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