]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/console/SCLConsoleView.java
(refs #7524) Set Refresh automatically as default in SCLConsole
[simantics/platform.git] / bundles / org.simantics.scl.ui / src / org / simantics / scl / ui / console / SCLConsoleView.java
1 package org.simantics.scl.ui.console;
2
3 import java.nio.file.Files;
4 import java.nio.file.Path;
5 import java.nio.file.Paths;
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.List;
9
10 import org.eclipse.core.runtime.Platform;
11 import org.eclipse.core.runtime.preferences.InstanceScope;
12 import org.eclipse.jface.action.Action;
13 import org.eclipse.jface.action.IAction;
14 import org.eclipse.jface.action.IMenuCreator;
15 import org.eclipse.jface.action.IToolBarManager;
16 import org.eclipse.jface.dialogs.Dialog;
17 import org.eclipse.jface.preference.IPersistentPreferenceStore;
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.dnd.DND;
20 import org.eclipse.swt.dnd.DropTarget;
21 import org.eclipse.swt.dnd.DropTargetAdapter;
22 import org.eclipse.swt.dnd.DropTargetEvent;
23 import org.eclipse.swt.dnd.FileTransfer;
24 import org.eclipse.swt.dnd.Transfer;
25 import org.eclipse.swt.events.SelectionAdapter;
26 import org.eclipse.swt.events.SelectionEvent;
27 import org.eclipse.swt.widgets.Composite;
28 import org.eclipse.swt.widgets.Control;
29 import org.eclipse.swt.widgets.Menu;
30 import org.eclipse.swt.widgets.MenuItem;
31 import org.eclipse.ui.part.ViewPart;
32 import org.eclipse.ui.preferences.ScopedPreferenceStore;
33 import org.simantics.scl.compiler.commands.CommandSession;
34 import org.simantics.scl.compiler.commands.CommandSessionImportEntry;
35 import org.simantics.scl.compiler.commands.SCLConsoleListener;
36 import org.simantics.scl.compiler.module.repository.UpdateListener;
37 import org.simantics.scl.compiler.testing.TestRunnable;
38 import org.simantics.scl.osgi.internal.TestUtils;
39 import org.simantics.scl.runtime.reporting.SCLReportingHandler;
40 import org.simantics.scl.ui.Activator;
41 import org.simantics.scl.ui.imports.internal.ManageImportsDialog;
42 import org.simantics.scl.ui.tests.SCLTestsDialog;
43
44 public class SCLConsoleView extends ViewPart {
45
46     public static final String PLUGIN_ID = "org.simantics.scl.ui";
47     public static final String IMPORTS = "imports";
48     public static final String REFRESH_AUTOMATICALLY = "refresh-automatically";
49     public static final String SEPARATOR = ";";
50     public static final String DISABLED_TAG = "[DISABLED]";
51     
52     IPersistentPreferenceStore store;
53     SCLConsole console;
54     boolean refreshAutomatically = false;
55     MenuItem refreshAutomaticallyItem;
56     
57     private ArrayList<CommandSessionImportEntry> readImportPreferences() {
58         String importsString = store.getString(IMPORTS);
59         
60         String[] splitted = importsString.split(SEPARATOR);
61         ArrayList<CommandSessionImportEntry> result = new ArrayList<CommandSessionImportEntry>(splitted.length);
62         for(String entryString : splitted) {
63             if(entryString.isEmpty())
64                 continue;
65             boolean disabled = false;
66             if(entryString.startsWith(DISABLED_TAG)) {
67                 disabled = true;
68                 entryString = entryString.substring(DISABLED_TAG.length());
69             }
70             String[] parts = entryString.split("=");
71             CommandSessionImportEntry entry;
72             if(parts.length == 1)
73                 entry = new CommandSessionImportEntry(parts[0], "", true);
74             else
75                 entry = new CommandSessionImportEntry(parts[1], parts[0], true);
76             entry.disabled = disabled;
77             result.add(entry);
78         }
79         return result;
80     }
81     
82     private void writeImportPreferences(ArrayList<CommandSessionImportEntry> entries) {
83         StringBuilder b = new StringBuilder();
84         
85         boolean first = true;
86         for(CommandSessionImportEntry entry : entries)
87             if(entry.persistent) {
88                 if(first)
89                     first = false;
90                 else
91                     b.append(SEPARATOR);
92                 if(entry.disabled)
93                     b.append(DISABLED_TAG);
94                 if(!entry.localName.isEmpty()) {
95                     b.append(entry.localName);
96                     b.append("=");
97                 }
98                 b.append(entry.moduleName);
99             }
100         
101         IPersistentPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, PLUGIN_ID);
102         store.setValue(IMPORTS, b.toString());
103     }
104     
105     private ArrayList<CommandSessionImportEntry> getCurrentImports() {
106         return console.getSession().getImportEntries();
107     }
108     
109     private void setCurrentImports(ArrayList<CommandSessionImportEntry> entries) {
110         console.getSession().setImportEntries(entries);
111     }
112     
113     private void manageImports() {
114         ManageImportsDialog dialog = new ManageImportsDialog(
115                 getSite().getShell(),
116                 getCurrentImports());
117         if(dialog.open() == Dialog.OK) {
118             writeImportPreferences(dialog.getImports());
119             setCurrentImports(dialog.getImports());
120         }
121     }
122     
123     private void sclTestDialog() {
124         List<TestRunnable> tests = TestUtils.getTests();
125         SCLTestsDialog dialog = new SCLTestsDialog(
126                 getSite().getShell(),
127                 tests, true);
128         if(dialog.open() == Dialog.OK) {
129             for(Object result : dialog.getResult()) {
130                 TestRunnable test = (TestRunnable) result;
131                 try {
132                     // Bit of a haxx solution to get around a deadlock caused by simply
133                     // running the test with test.run()
134                     console.execute("import \"Commands/Tests\"");
135                     console.execute("runByName \"" + test.getName() + "\"");
136 //                    test.run();
137                 } catch (Exception e) {
138                     e.printStackTrace();
139                 }
140             }
141         }
142     }
143     
144     private UpdateListener dependencyListener = new UpdateListener() {
145         @Override
146         public void notifyAboutUpdate() {
147             if(refreshAutomatically)
148                 console.getSession().updateRuntimeEnvironment(true);
149         }
150     };
151
152     private void setRefreshAutomatically(boolean refreshAutomatically, boolean refreshAlso) {
153         this.refreshAutomatically = refreshAutomatically;
154         if(refreshAutomaticallyItem != null)
155             refreshAutomaticallyItem.setSelection(refreshAutomatically);
156         
157         store.setValue(REFRESH_AUTOMATICALLY, refreshAutomatically);
158         
159         if(refreshAutomatically) {
160             console.getSession().setDependenciesListener(dependencyListener);
161             if(refreshAlso)
162                 console.getSession().updateRuntimeEnvironment(true);
163         }
164         else {
165             console.getSession().setDependenciesListener(null);
166             dependencyListener.stopListening();
167         }
168     }
169     
170     @Override
171     public void createPartControl(Composite parent) {
172         store = new ScopedPreferenceStore(InstanceScope.INSTANCE, PLUGIN_ID);
173         store.setDefault(REFRESH_AUTOMATICALLY, true);
174         
175         this.console = new SCLConsole(parent, SWT.NONE);
176         
177         setRefreshAutomatically(store.getBoolean(REFRESH_AUTOMATICALLY), false);
178         setCurrentImports(readImportPreferences());
179
180         addScriptDropSupport(console);
181
182         IToolBarManager toolBarManager = getViewSite().getActionBars().getToolBarManager();
183         
184         // Interrupt action
185         final Action interruptAction = new Action("Interrupt current command",
186                 Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/stop.png")) {
187             @Override
188             public void run() {
189                 console.interruptCurrentCommands();
190             }
191         };
192         interruptAction.setDisabledImageDescriptor(
193                 Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/stop_disabled.png"));
194         interruptAction.setEnabled(false);
195         toolBarManager.add(interruptAction);
196         
197         // Clear console action
198         final Action clearAction = new Action("Clear console",
199                 Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/clear_console.png")) {
200             @Override
201             public void run() {
202                 setEnabled(false);
203                 console.clear();
204             }
205         };
206         clearAction.setDisabledImageDescriptor(
207                 Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/clear_console_disabled.png"));
208         clearAction.setEnabled(false);
209         toolBarManager.add(clearAction);
210         console.addListener(new SCLConsoleListener() {
211             @Override
212             public void startedExecution() {
213                 interruptAction.setEnabled(true);
214             }
215             @Override
216             public void finishedExecution() {
217                 interruptAction.setEnabled(false);
218             }
219             @Override
220             public void consoleIsNotEmptyAnymore() {
221                 clearAction.setEnabled(true);
222             }
223         });
224         
225         // Refresh action
226         toolBarManager.add(new Action("Refresh modules", IAction.AS_DROP_DOWN_MENU) {
227             {
228                 setImageDescriptor(Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/arrow_refresh.png"));
229                 setMenuCreator(new IMenuCreator() {
230                     Menu menu;
231                     @Override
232                     public Menu getMenu(Menu parent) {
233                         throw new UnsupportedOperationException();
234                     }
235                     
236                     @Override
237                     public Menu getMenu(Control parent) {
238                         if(menu == null) {
239                             menu = new Menu(parent);
240                             refreshAutomaticallyItem = new MenuItem(menu, SWT.CHECK);
241                             refreshAutomaticallyItem.setText("Refresh automatically");
242                             refreshAutomaticallyItem.setSelection(refreshAutomatically);
243                             refreshAutomaticallyItem.addSelectionListener(new SelectionAdapter() {
244                                 @Override
245                                 public void widgetSelected(SelectionEvent e) {
246                                     setRefreshAutomatically(!refreshAutomatically, true);
247                                 }
248                             });
249                         }
250                         return menu;
251                     }
252                     
253                     @Override
254                     public void dispose() {
255                         if(menu != null)
256                             menu.dispose();
257                     }
258                 });
259             }
260             @Override
261             public void run() {
262                 console.getSession().getModuleRepository().getSourceRepository().checkUpdates();
263                 console.getSession().updateRuntimeEnvironment(true);
264                 console.appendOutput("refresh completed\n", console.greenColor, null);
265             }
266         });
267         toolBarManager.add(new Action("Manage imports",
268                 Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/configure_imports.png")) {
269             @Override
270             public void run() {
271                 manageImports();
272             }
273         });
274         
275         // Show action for running SCL tests if in development mode
276         if (Platform.inDevelopmentMode()) {
277             toolBarManager.add(new Action("Run tests",
278                     Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/run_tests.png")) {
279                 @Override
280                 public void run() {
281                     sclTestDialog();
282                 }
283             });
284         }
285         
286         toolBarManager.update(true);
287     }
288
289     private class ScriptRunningDropTarget extends DropTargetAdapter {
290         @Override
291         public void dragEnter(DropTargetEvent event) {
292             if (event.detail == DND.DROP_DEFAULT) {
293                 event.detail = DND.DROP_LINK;
294             }
295         }
296
297         @Override
298         public void dragOperationChanged(DropTargetEvent event) {
299             if (event.detail == DND.DROP_DEFAULT) {
300                 event.detail = DND.DROP_LINK;
301             }
302         }
303
304         public void drop(DropTargetEvent event) {
305             if (FileTransfer.getInstance().isSupportedType(event.currentDataType)) {
306                 String[] files = ((String[]) event.data).clone();
307                 // Sort files by name to allow deterministic multi-file drop
308                 Arrays.sort(files);
309                 for (String file : files) {
310                     Path p = Paths.get(file).toAbsolutePath();
311                     if (isScriptFile(p)) {
312                         console.execute("runFromFile \"" + p.toString().replace('\\', '/') + "\"");
313                     }
314                 }
315             }
316         }
317
318         private boolean isScriptFile(Path p) {
319             return Files.isRegularFile(p)
320                     //&& p.toString().toLowerCase().endsWith(".scl")
321                     ;
322         }
323     }
324
325     private void addScriptDropSupport(SCLConsole console) {
326         DropTarget target = new DropTarget(console.getOutputWidget(), DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK | DND.DROP_DEFAULT);
327         target.setTransfer(new Transfer[] { FileTransfer.getInstance() });
328         target.addDropListener(new ScriptRunningDropTarget());
329     }
330
331     @Override
332     public void setFocus() {
333         console.setFocus();
334     }
335     
336     @Override
337     public void dispose() {
338         super.dispose();
339         console.dispose();
340     }
341
342     @SuppressWarnings("unchecked")
343     @Override
344     public <T> T getAdapter(Class<T> adapter) {
345         if (adapter == CommandSession.class)
346             return (T) console.getSession();
347         if (adapter == SCLReportingHandler.class)
348             return (T) console.getHandler();
349         return super.getAdapter(adapter);
350     }
351
352 }