package org.simantics.scl.ui.console;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import org.eclipse.core.runtime.IProgressMonitor;
import org.simantics.scl.ui.assist.SCLContentProposalProvider;
import org.simantics.scl.ui.assist.StyledTextContentAdapter;
+import gnu.trove.set.hash.THashSet;
+
/**
* An SCL console with input and output area that can be embedded
* into any editor or view.
* @author Hannu Niemistö
*/
public class SCLConsole extends AbstractCommandConsole {
+
+ /**
+ * Use this option mask to exclude {@link SCLConsoleListener}s contributed as
+ * OSGi services from listening to this console.
+ */
+ public static final int EXCLUDE_CONTRIBUTED_LISTENERS = 1 << 10;
+
public static final String JOB_NAME = "org.simantics.scl.console.job";
+ public static final long TERMINATE_GRACE_PERIOD = 1000L;
private THashSet<Job> currentJobs = new THashSet<Job>();
- private Thread currentThread;
private final IdentitySchedulingRule schedulingRule = new IdentitySchedulingRule();
private ArrayList<SCLConsoleListener> listeners = new ArrayList<SCLConsoleListener>(2);
private boolean consoleIsEmpty = true;
CommandSession session = new CommandSession(SCLOsgi.MODULE_REPOSITORY, handler);
ContentProposalAdapter contentProposalAdapter;
-
+
public SCLConsole(Composite parent, int style) {
- super(parent, style);
-
+ this(parent, style, 0);
+ }
+
+ public SCLConsole(Composite parent, int style, int options) {
+ super(parent, style, options);
+ createContentProposalAdapter();
+ if (!hasOption(EXCLUDE_CONTRIBUTED_LISTENERS))
+ addContributedListeners();
+ }
+
+ protected void createContentProposalAdapter() {
+ if (input == null)
+ return;
+
StyledTextContentAdapter styledTextContentAdapter = new StyledTextContentAdapter();
SCLContentProposalProvider contentProvider = new SCLContentProposalProvider(session);
-
try {
contentProposalAdapter = new ContentProposalAdapter(
input,
} catch (ParseException e) {
// No content assist then.
}
-
- addContributedListeners();
}
@Override
protected boolean canExecuteCommand() {
- return !contentProposalAdapter.isProposalPopupOpen();
+ return contentProposalAdapter == null || !contentProposalAdapter.isProposalPopupOpen();
}
-
+
@Override
public ErrorAnnotation[] validate(String command) {
if(command.isEmpty())
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
- synchronized(currentJobs) {
- currentJobs.remove(this);
- currentThread = Thread.currentThread();
- }
session.execute(command, handler);
} finally {
synchronized(currentJobs) {
- currentThread = null;
+ currentJobs.remove(this);
if(currentJobs.isEmpty())
for(SCLConsoleListener listener : listeners)
listener.finishedExecution();
}
return Status.OK_STATUS;
}
+
+ @Override
+ protected void canceling() {
+ Thread thread = getThread();
+ if(thread != null)
+ thread.interrupt();
+
+ try {
+ Thread.sleep(TERMINATE_GRACE_PERIOD);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ return;
+ }
+
+ thread = getThread();
+ if(thread != null)
+ thread.stop();
+ }
};
job.setRule(schedulingRule);
synchronized(currentJobs) {
public CommandSession getSession() {
return session;
}
+
+ public SCLReportingHandler getHandler() {
+ return handler;
+ }
+
public void interruptCurrentCommands() {
synchronized(currentJobs) {
for(Job job : currentJobs)
job.cancel();
currentJobs.clear();
- if(currentThread != null)
- currentThread.interrupt();
}
}
consoleIsEmpty = true;
}
- private void addContributedListeners() {
+ protected void addContributedListeners() {
final BundleContext context = Activator.getInstance().getBundle().getBundleContext();
new ServiceTracker<SCLConsoleListener, SCLConsoleListener>(context,
SCLConsoleListener.class, null) {