X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.ui%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fui%2Fconsole%2FSCLConsoleView.java;h=67de0b2ffe9e02571d75ec114c22416498e51274;hp=6385fe9ca16b9806a966056070ff0208966a5af1;hb=dbe0a77f0869111219b69d412d0bb90d17c391c1;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/console/SCLConsoleView.java b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/console/SCLConsoleView.java old mode 100755 new mode 100644 index 6385fe9ca..67de0b2ff --- a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/console/SCLConsoleView.java +++ b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/console/SCLConsoleView.java @@ -1,252 +1,335 @@ -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.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.widgets.Composite; -import org.eclipse.ui.part.ViewPart; -import org.eclipse.ui.preferences.ScopedPreferenceStore; -import org.simantics.scl.compiler.commands.CommandSessionImportEntry; -import org.simantics.scl.compiler.commands.SCLConsoleListener; -import org.simantics.scl.compiler.testing.TestRunnable; -import org.simantics.scl.osgi.internal.TestUtils; -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 SEPARATOR = ";"; - public static final String DISABLED_TAG = "[DISABLED]"; - - SCLConsole console; - - private ArrayList readImportPreferences() { - IPersistentPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, PLUGIN_ID); - String importsString = store.getString(IMPORTS); - - String[] splitted = importsString.split(SEPARATOR); - ArrayList result = new ArrayList(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 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.putValue(IMPORTS, b.toString()); - } - - private ArrayList getCurrentImports() { - return console.getSession().getImportEntries(); - } - - private void setCurrentImports(ArrayList 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 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(); - } - } - } - } - - @Override - public void createPartControl(Composite parent) { - this.console = new SCLConsole(parent, SWT.NONE); - setCurrentImports(readImportPreferences()); - - addScriptDropSupport(console); - - IToolBarManager toolBarManager = getViewSite().getActionBars().getToolBarManager(); - - // Interrupt action - final Action interruptAction = new Action("Interrupt current command", - Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/stop.png")) { - @Override - public void run() { - console.interruptCurrentCommands(); - } - }; - interruptAction.setDisabledImageDescriptor( - Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/stop_disabled.png")); - interruptAction.setEnabled(false); - toolBarManager.add(interruptAction); - - // Clear console action - final Action clearAction = new Action("Clear console", - Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/clear_console.png")) { - @Override - public void run() { - setEnabled(false); - console.clear(); - } - }; - clearAction.setDisabledImageDescriptor( - Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/clear_console_disabled.png")); - clearAction.setEnabled(false); - 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", - Activator.imageDescriptorFromPlugin("org.simantics.scl.ui", "icons/arrow_refresh.png")) { - @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); - } - - private class ScriptRunningDropTarget extends DropTargetAdapter { - 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_MOVE | DND.DROP_COPY | 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(); - } - -} +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 readImportPreferences() { + String importsString = store.getString(IMPORTS); + + String[] splitted = importsString.split(SEPARATOR); + ArrayList result = new ArrayList(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 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 getCurrentImports() { + return console.getSession().getImportEntries(); + } + + private void setCurrentImports(ArrayList 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 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 getAdapter(Class adapter) { + if (adapter == CommandSession.class) + return (T) console.getSession(); + if (adapter == SCLReportingHandler.class) + return (T) console.getHandler(); + return super.getAdapter(adapter); + } + +}