]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/console/SCLConsoleView.java
Fixed SCL Console Clear Console active-state when imports are erroneous
[simantics/platform.git] / bundles / org.simantics.scl.ui / src / org / simantics / scl / ui / console / SCLConsoleView.java
old mode 100755 (executable)
new mode 100644 (file)
index 6385fe9..67de0b2
-package org.simantics.scl.ui.console;\r
-\r
-import java.nio.file.Files;\r
-import java.nio.file.Path;\r
-import java.nio.file.Paths;\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.List;\r
-\r
-import org.eclipse.core.runtime.Platform;\r
-import org.eclipse.core.runtime.preferences.InstanceScope;\r
-import org.eclipse.jface.action.Action;\r
-import org.eclipse.jface.action.IToolBarManager;\r
-import org.eclipse.jface.dialogs.Dialog;\r
-import org.eclipse.jface.preference.IPersistentPreferenceStore;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.dnd.DND;\r
-import org.eclipse.swt.dnd.DropTarget;\r
-import org.eclipse.swt.dnd.DropTargetAdapter;\r
-import org.eclipse.swt.dnd.DropTargetEvent;\r
-import org.eclipse.swt.dnd.FileTransfer;\r
-import org.eclipse.swt.dnd.Transfer;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.ui.part.ViewPart;\r
-import org.eclipse.ui.preferences.ScopedPreferenceStore;\r
-import org.simantics.scl.compiler.commands.CommandSessionImportEntry;\r
-import org.simantics.scl.compiler.commands.SCLConsoleListener;\r
-import org.simantics.scl.compiler.testing.TestRunnable;\r
-import org.simantics.scl.osgi.internal.TestUtils;\r
-import org.simantics.scl.ui.Activator;\r
-import org.simantics.scl.ui.imports.internal.ManageImportsDialog;\r
-import org.simantics.scl.ui.tests.SCLTestsDialog;\r
-\r
-public class SCLConsoleView extends ViewPart {\r
-\r
-    public static final String PLUGIN_ID = "org.simantics.scl.ui";\r
-    public static final String IMPORTS = "imports";\r
-    public static final String SEPARATOR = ";";\r
-    public static final String DISABLED_TAG = "[DISABLED]";\r
-    \r
-    SCLConsole console;\r
-    \r
-    private ArrayList<CommandSessionImportEntry> readImportPreferences() {\r
-        IPersistentPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, PLUGIN_ID);\r
-        String importsString = store.getString(IMPORTS);\r
-        \r
-        String[] splitted = importsString.split(SEPARATOR);\r
-        ArrayList<CommandSessionImportEntry> result = new ArrayList<CommandSessionImportEntry>(splitted.length);\r
-        for(String entryString : splitted) {\r
-            if(entryString.isEmpty())\r
-                continue;\r
-            boolean disabled = false;\r
-            if(entryString.startsWith(DISABLED_TAG)) {\r
-                disabled = true;\r
-                entryString = entryString.substring(DISABLED_TAG.length());\r
-            }\r
-            String[] parts = entryString.split("=");\r
-            CommandSessionImportEntry entry;\r
-            if(parts.length == 1)\r
-                entry = new CommandSessionImportEntry(parts[0], "", true);\r
-            else\r
-                entry = new CommandSessionImportEntry(parts[1], parts[0], true);\r
-            entry.disabled = disabled;\r
-            result.add(entry);\r
-        }\r
-        return result;\r
-    }\r
-    \r
-    private void writeImportPreferences(ArrayList<CommandSessionImportEntry> entries) {\r
-        StringBuilder b = new StringBuilder();\r
-        \r
-        boolean first = true;\r
-        for(CommandSessionImportEntry entry : entries)\r
-            if(entry.persistent) {\r
-                if(first)\r
-                    first = false;\r
-                else\r
-                    b.append(SEPARATOR);\r
-                if(entry.disabled)\r
-                    b.append(DISABLED_TAG);\r
-                if(!entry.localName.isEmpty()) {\r
-                    b.append(entry.localName);\r
-                    b.append("=");\r
-                }\r
-                b.append(entry.moduleName);\r
-            }\r
-        \r
-        IPersistentPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, PLUGIN_ID);\r
-        store.putValue(IMPORTS, b.toString());\r
-    }\r
-    \r
-    private ArrayList<CommandSessionImportEntry> getCurrentImports() {\r
-        return console.getSession().getImportEntries();\r
-    }\r
-    \r
-    private void setCurrentImports(ArrayList<CommandSessionImportEntry> entries) {\r
-        console.getSession().setImportEntries(entries);\r
-    }\r
-    \r
-    private void manageImports() {\r
-        ManageImportsDialog dialog = new ManageImportsDialog(\r
-                getSite().getShell(),\r
-                getCurrentImports());\r
-        if(dialog.open() == Dialog.OK) {\r
-            writeImportPreferences(dialog.getImports());\r
-            setCurrentImports(dialog.getImports());\r
-        }\r
-    }\r
-    \r
-    private void sclTestDialog() {\r
-        List<TestRunnable> tests = TestUtils.getTests();\r
-        SCLTestsDialog dialog = new SCLTestsDialog(\r
-                getSite().getShell(),\r
-                tests, true);\r
-        if(dialog.open() == Dialog.OK) {\r
-            for(Object result : dialog.getResult()) {\r
-                TestRunnable test = (TestRunnable) result;\r
-                try {\r
-                    // Bit of a haxx solution to get around a deadlock caused by simply\r
-                    // running the test with test.run()\r
-                    console.execute("import \"Commands/Tests\"");\r
-                    console.execute("runByName \"" + test.getName() + "\"");\r
-//                    test.run();\r
-                } catch (Exception e) {\r
-                    e.printStackTrace();\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public void createPartControl(Composite parent) {\r
-        this.console = new SCLConsole(parent, SWT.NONE);\r
-        setCurrentImports(readImportPreferences());\r
-\r
-        addScriptDropSupport(console);\r
-\r
-        IToolBarManager toolBarManager = getViewSite().getActionBars().getToolBarManager();\r
-        \r
-        // Interrupt action\r
-        final Action interruptAction = new Action("Interrupt current command",\r
-                Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/stop.png")) {\r
-            @Override\r
-            public void run() {\r
-                console.interruptCurrentCommands();\r
-            }\r
-        };\r
-        interruptAction.setDisabledImageDescriptor(\r
-                Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/stop_disabled.png"));\r
-        interruptAction.setEnabled(false);\r
-        toolBarManager.add(interruptAction);\r
-        \r
-        // Clear console action\r
-        final Action clearAction = new Action("Clear console",\r
-                Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/clear_console.png")) {\r
-            @Override\r
-            public void run() {\r
-                setEnabled(false);\r
-                console.clear();\r
-            }\r
-        };\r
-        clearAction.setDisabledImageDescriptor(\r
-                Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/clear_console_disabled.png"));\r
-        clearAction.setEnabled(false);\r
-        toolBarManager.add(clearAction);\r
-        console.addListener(new SCLConsoleListener() {\r
-            @Override\r
-            public void startedExecution() {\r
-                interruptAction.setEnabled(true);\r
-            }\r
-            @Override\r
-            public void finishedExecution() {\r
-                interruptAction.setEnabled(false);\r
-            }\r
-            @Override\r
-            public void consoleIsNotEmptyAnymore() {\r
-                clearAction.setEnabled(true);\r
-            }\r
-        });\r
-        \r
-        // Refresh action\r
-        toolBarManager.add(new Action("Refresh modules",\r
-                Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/arrow_refresh.png")) {\r
-            @Override\r
-            public void run() {\r
-                console.getSession().getModuleRepository().getSourceRepository().checkUpdates();\r
-                console.getSession().updateRuntimeEnvironment(true);\r
-                console.appendOutput("refresh completed\n", console.greenColor, null);\r
-            }\r
-        });\r
-        toolBarManager.add(new Action("Manage imports",\r
-                Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/configure_imports.png")) {\r
-            @Override\r
-            public void run() {\r
-                manageImports();\r
-            }\r
-        });\r
-        \r
-        // Show action for running SCL tests if in development mode\r
-        if (Platform.inDevelopmentMode()) {\r
-            toolBarManager.add(new Action("Run tests",\r
-                    Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/run_tests.png")) {\r
-                @Override\r
-                public void run() {\r
-                    sclTestDialog();\r
-                }\r
-            });\r
-        }\r
-        \r
-        toolBarManager.update(true);\r
-    }\r
-\r
-    private class ScriptRunningDropTarget extends DropTargetAdapter {\r
-        public void drop(DropTargetEvent event) {\r
-            if (FileTransfer.getInstance().isSupportedType(event.currentDataType)) {\r
-                String[] files = ((String[]) event.data).clone();\r
-                // Sort files by name to allow deterministic multi-file drop\r
-                Arrays.sort(files);\r
-                for (String file : files) {\r
-                    Path p = Paths.get(file).toAbsolutePath();\r
-                    if (isScriptFile(p)) {\r
-                        console.execute("runFromFile \"" + p.toString().replace('\\', '/') + "\"");\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        private boolean isScriptFile(Path p) {\r
-            return Files.isRegularFile(p)\r
-                    //&& p.toString().toLowerCase().endsWith(".scl")\r
-                    ;\r
-        }\r
-    }\r
-\r
-    private void addScriptDropSupport(SCLConsole console) {\r
-        DropTarget target = new DropTarget(console.getOutputWidget(), DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT);\r
-        target.setTransfer(new Transfer[] { FileTransfer.getInstance() });\r
-        target.addDropListener(new ScriptRunningDropTarget());\r
-    }\r
-\r
-    @Override\r
-    public void setFocus() {\r
-        console.setFocus();\r
-    }\r
-    \r
-    @Override\r
-    public void dispose() {\r
-        super.dispose();\r
-        console.dispose();\r
-    }\r
-\r
-}\r
+package org.simantics.scl.ui.console;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.IPersistentPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTarget;
+import org.eclipse.swt.dnd.DropTargetAdapter;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.ui.part.ViewPart;
+import org.eclipse.ui.preferences.ScopedPreferenceStore;
+import org.simantics.scl.compiler.commands.CommandSession;
+import org.simantics.scl.compiler.commands.CommandSessionImportEntry;
+import org.simantics.scl.compiler.commands.SCLConsoleListener;
+import org.simantics.scl.compiler.module.repository.UpdateListener;
+import org.simantics.scl.compiler.testing.TestRunnable;
+import org.simantics.scl.osgi.internal.TestUtils;
+import org.simantics.scl.runtime.reporting.SCLReportingHandler;
+import org.simantics.scl.ui.Activator;
+import org.simantics.scl.ui.imports.internal.ManageImportsDialog;
+import org.simantics.scl.ui.tests.SCLTestsDialog;
+
+public class SCLConsoleView extends ViewPart {
+
+    public static final String PLUGIN_ID = "org.simantics.scl.ui";
+    public static final String IMPORTS = "imports";
+    public static final String REFRESH_AUTOMATICALLY = "refresh-automatically";
+    public static final String SEPARATOR = ";";
+    public static final String DISABLED_TAG = "[DISABLED]";
+    
+    IPersistentPreferenceStore store;
+    SCLConsole console;
+    boolean refreshAutomatically = false;
+    MenuItem refreshAutomaticallyItem;
+    
+    private ArrayList<CommandSessionImportEntry> readImportPreferences() {
+        String importsString = store.getString(IMPORTS);
+        
+        String[] splitted = importsString.split(SEPARATOR);
+        ArrayList<CommandSessionImportEntry> result = new ArrayList<CommandSessionImportEntry>(splitted.length);
+        for(String entryString : splitted) {
+            if(entryString.isEmpty())
+                continue;
+            boolean disabled = false;
+            if(entryString.startsWith(DISABLED_TAG)) {
+                disabled = true;
+                entryString = entryString.substring(DISABLED_TAG.length());
+            }
+            String[] parts = entryString.split("=");
+            CommandSessionImportEntry entry;
+            if(parts.length == 1)
+                entry = new CommandSessionImportEntry(parts[0], "", true);
+            else
+                entry = new CommandSessionImportEntry(parts[1], parts[0], true);
+            entry.disabled = disabled;
+            result.add(entry);
+        }
+        return result;
+    }
+    
+    private void writeImportPreferences(ArrayList<CommandSessionImportEntry> entries) {
+        StringBuilder b = new StringBuilder();
+        
+        boolean first = true;
+        for(CommandSessionImportEntry entry : entries)
+            if(entry.persistent) {
+                if(first)
+                    first = false;
+                else
+                    b.append(SEPARATOR);
+                if(entry.disabled)
+                    b.append(DISABLED_TAG);
+                if(!entry.localName.isEmpty()) {
+                    b.append(entry.localName);
+                    b.append("=");
+                }
+                b.append(entry.moduleName);
+            }
+        
+        IPersistentPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, PLUGIN_ID);
+        store.setValue(IMPORTS, b.toString());
+    }
+    
+    private ArrayList<CommandSessionImportEntry> getCurrentImports() {
+        return console.getSession().getImportEntries();
+    }
+    
+    private void setCurrentImports(ArrayList<CommandSessionImportEntry> entries) {
+        console.getSession().setImportEntries(entries);
+    }
+    
+    private void manageImports() {
+        ManageImportsDialog dialog = new ManageImportsDialog(
+                getSite().getShell(),
+                getCurrentImports());
+        if(dialog.open() == Dialog.OK) {
+            writeImportPreferences(dialog.getImports());
+            setCurrentImports(dialog.getImports());
+        }
+    }
+    
+    private void sclTestDialog() {
+        List<TestRunnable> tests = TestUtils.getTests();
+        SCLTestsDialog dialog = new SCLTestsDialog(
+                getSite().getShell(),
+                tests, true);
+        if(dialog.open() == Dialog.OK) {
+            for(Object result : dialog.getResult()) {
+                TestRunnable test = (TestRunnable) result;
+                try {
+                    // Bit of a haxx solution to get around a deadlock caused by simply
+                    // running the test with test.run()
+                    console.execute("import \"Commands/Tests\"");
+                    console.execute("runByName \"" + test.getName() + "\"");
+//                    test.run();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+    
+    private UpdateListener dependencyListener = new UpdateListener() {
+        @Override
+        public void notifyAboutUpdate() {
+            if(refreshAutomatically)
+                console.getSession().updateRuntimeEnvironment(true);
+        }
+    };
+
+    private void setRefreshAutomatically(boolean refreshAutomatically, boolean refreshAlso) {
+        this.refreshAutomatically = refreshAutomatically;
+        if(refreshAutomaticallyItem != null)
+            refreshAutomaticallyItem.setSelection(refreshAutomatically);
+        
+        store.setValue(REFRESH_AUTOMATICALLY, refreshAutomatically);
+        
+        if(refreshAutomatically) {
+            console.getSession().setDependenciesListener(dependencyListener);
+            if(refreshAlso)
+                console.getSession().updateRuntimeEnvironment(true);
+        }
+        else {
+            console.getSession().setDependenciesListener(null);
+            dependencyListener.stopListening();
+        }
+    }
+    
+    @Override
+    public void createPartControl(Composite parent) {
+        store = new ScopedPreferenceStore(InstanceScope.INSTANCE, PLUGIN_ID);
+        store.setDefault(REFRESH_AUTOMATICALLY, true);
+        
+        this.console = new SCLConsole(parent, SWT.NONE);
+
+        IToolBarManager toolBarManager = getViewSite().getActionBars().getToolBarManager();
+        
+        // Interrupt action
+        Action interruptAction = ConsoleActions.createInterruptAction(console);
+        toolBarManager.add(interruptAction);
+        
+        // Clear console action
+        Action clearAction = ConsoleActions.createClearAction(console);
+        toolBarManager.add(clearAction);
+        
+        console.addListener(new SCLConsoleListener() {
+            @Override
+            public void startedExecution() {
+                interruptAction.setEnabled(true);
+            }
+            @Override
+            public void finishedExecution() {
+                interruptAction.setEnabled(false);
+            }
+            @Override
+            public void consoleIsNotEmptyAnymore() {
+                clearAction.setEnabled(true);
+            }
+        });
+        
+        // Refresh action
+        toolBarManager.add(new Action("Refresh modules", IAction.AS_DROP_DOWN_MENU) {
+            {
+                setImageDescriptor(Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/arrow_refresh.png"));
+                setMenuCreator(new IMenuCreator() {
+                    Menu menu;
+                    @Override
+                    public Menu getMenu(Menu parent) {
+                        throw new UnsupportedOperationException();
+                    }
+                    
+                    @Override
+                    public Menu getMenu(Control parent) {
+                        if(menu == null) {
+                            menu = new Menu(parent);
+                            refreshAutomaticallyItem = new MenuItem(menu, SWT.CHECK);
+                            refreshAutomaticallyItem.setText("Refresh automatically");
+                            refreshAutomaticallyItem.setSelection(refreshAutomatically);
+                            refreshAutomaticallyItem.addSelectionListener(new SelectionAdapter() {
+                                @Override
+                                public void widgetSelected(SelectionEvent e) {
+                                    setRefreshAutomatically(!refreshAutomatically, true);
+                                }
+                            });
+                        }
+                        return menu;
+                    }
+                    
+                    @Override
+                    public void dispose() {
+                        if(menu != null)
+                            menu.dispose();
+                    }
+                });
+            }
+            @Override
+            public void run() {
+                console.getSession().getModuleRepository().getSourceRepository().checkUpdates();
+                console.getSession().updateRuntimeEnvironment(true);
+                console.appendOutput("refresh completed\n", console.greenColor, null);
+            }
+        });
+        toolBarManager.add(new Action("Manage imports",
+                Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/configure_imports.png")) {
+            @Override
+            public void run() {
+                manageImports();
+            }
+        });
+
+        // Show action for running SCL tests if in development mode
+        if (Platform.inDevelopmentMode()) {
+            toolBarManager.add(new Action("Run tests",
+                    Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/run_tests.png")) {
+                @Override
+                public void run() {
+                    sclTestDialog();
+                }
+            });
+        }
+        
+        toolBarManager.update(true);
+
+        setRefreshAutomatically(store.getBoolean(REFRESH_AUTOMATICALLY), false);
+        // Do this after the actions and SCLConsoleListener are
+        // registered because it can cause output to the console.
+        setCurrentImports(readImportPreferences());
+        addScriptDropSupport(console);
+    }
+
+    private class ScriptRunningDropTarget extends DropTargetAdapter {
+        @Override
+        public void dragEnter(DropTargetEvent event) {
+            if (event.detail == DND.DROP_DEFAULT) {
+                event.detail = DND.DROP_LINK;
+            }
+        }
+
+        @Override
+        public void dragOperationChanged(DropTargetEvent event) {
+            if (event.detail == DND.DROP_DEFAULT) {
+                event.detail = DND.DROP_LINK;
+            }
+        }
+
+        public void drop(DropTargetEvent event) {
+            if (FileTransfer.getInstance().isSupportedType(event.currentDataType)) {
+                String[] files = ((String[]) event.data).clone();
+                // Sort files by name to allow deterministic multi-file drop
+                Arrays.sort(files);
+                for (String file : files) {
+                    Path p = Paths.get(file).toAbsolutePath();
+                    if (isScriptFile(p)) {
+                        console.execute("runFromFile \"" + p.toString().replace('\\', '/') + "\"");
+                    }
+                }
+            }
+        }
+
+        private boolean isScriptFile(Path p) {
+            return Files.isRegularFile(p)
+                    //&& p.toString().toLowerCase().endsWith(".scl")
+                    ;
+        }
+    }
+
+    private void addScriptDropSupport(SCLConsole console) {
+        DropTarget target = new DropTarget(console.getOutputWidget(), DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK | DND.DROP_DEFAULT);
+        target.setTransfer(new Transfer[] { FileTransfer.getInstance() });
+        target.addDropListener(new ScriptRunningDropTarget());
+    }
+
+    @Override
+    public void setFocus() {
+        console.setFocus();
+    }
+    
+    @Override
+    public void dispose() {
+        super.dispose();
+        console.dispose();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getAdapter(Class<T> adapter) {
+        if (adapter == CommandSession.class)
+            return (T) console.getSession();
+        if (adapter == SCLReportingHandler.class)
+            return (T) console.getHandler();
+        return super.getAdapter(adapter);
+    }
+
+}