Bug 540010: Add tools for R apps
- Add launch config type R App and actions to start/stop/restart apps
- Add app browser view R App Viewer
- Add app variables view R App Variables
Also:
- Replace IToolProvider / ToolRetargetableHandler by ecommons.ts
- Replace ToolRetargetableHandler by AbstractToolHandler
- Add Section to Queue to improve handling of stacked queues
- Extract RElementInput utilities and handlers from object browser
- CleanUp QueueView and HistoryView
Change-Id: Ifee5b79578719a19c97a5bc676c96a629c5ab259
diff --git a/r/_build/org.eclipse.statet.r-feature/feature.xml b/r/_build/org.eclipse.statet.r-feature/feature.xml
index 6ab035b..26c6f80 100644
--- a/r/_build/org.eclipse.statet.r-feature/feature.xml
+++ b/r/_build/org.eclipse.statet.r-feature/feature.xml
@@ -143,6 +143,13 @@
unpack="false"/-->
<plugin
+ id="org.eclipse.statet.r.apps"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
id="org.eclipse.statet.r.doc"
download-size="0"
install-size="0"
diff --git a/r/org.eclipse.statet.ide.ui/src/org/eclipse/statet/internal/ide/ui/StatetPerspectiveFactory.java b/r/org.eclipse.statet.ide.ui/src/org/eclipse/statet/internal/ide/ui/StatetPerspectiveFactory.java
index a067e8d..fce06fe 100644
--- a/r/org.eclipse.statet.ide.ui/src/org/eclipse/statet/internal/ide/ui/StatetPerspectiveFactory.java
+++ b/r/org.eclipse.statet.ide.ui/src/org/eclipse/statet/internal/ide/ui/StatetPerspectiveFactory.java
@@ -59,8 +59,7 @@
"console-additions", IPageLayout.BOTTOM, 0.60f, "left"); //$NON-NLS-1$ //$NON-NLS-2$
consoleAddFolder.addView(NICO_OBJECTBROWSER_VIEW);
consoleAddFolder.addView(NICO_CMDHISTORY_VIEW);
-
-// layout.createPlaceholderFolder("console-additions", IPageLayout.BOTTOM, 0.80f, "left"); //$NON-NLS-1$
+ consoleAddFolder.addPlaceholder("org.eclipse.statet.r.apps.views.VariableViewer"); //$NON-NLS-1$
layout.addActionSet(LAUNCH_ACTION_SET);
layout.addActionSet(BREAKPOINT_ACTION_SET);
diff --git a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/internal/nico/core/Messages.java b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/internal/nico/core/Messages.java
index bfa3700..f5cdc62 100644
--- a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/internal/nico/core/Messages.java
+++ b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/internal/nico/core/Messages.java
@@ -16,7 +16,11 @@
import org.eclipse.osgi.util.NLS;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+@NonNullByDefault
+@SuppressWarnings("null")
public class Messages extends NLS {
@@ -40,6 +44,7 @@
public static String ToolController_FileOperation_error_CannotResolve_message;
public static String ToolController_SubmitCancelled_message;
public static String ToolController_ToolTerminated_message;
+ public static String ToolController_QueueSectionTerminated_message;
public static String Progress_Starting_label;
public static String Progress_Terminating_label;
diff --git a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/internal/nico/core/Messages.properties b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/internal/nico/core/Messages.properties
index e145d30..e530158 100644
--- a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/internal/nico/core/Messages.properties
+++ b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/internal/nico/core/Messages.properties
@@ -29,10 +29,11 @@
Runtime_error_CriticalError_message = Critical runtime error occurred.
Runtime_error_UnexpectedTermination_message = An error occurred while running {0}. {1} terminates unexpected.
-ToolController_CommonStartTask_label = Start Tool
-ToolController_FileOperation_error_CannotResolve_message = Filename ''{0}'' cannot be resolved.
-ToolController_SubmitCancelled_message = Submit cancelled
-ToolController_ToolTerminated_message = {0} is terminated.
+ToolController_CommonStartTask_label= Start Tool
+ToolController_FileOperation_error_CannotResolve_message= Filename ''{0}'' cannot be resolved.
+ToolController_SubmitCancelled_message= Submit cancelled
+ToolController_ToolTerminated_message= {0} is terminated.
+ToolController_QueueSectionTerminated_message= Requested position in queue of {0} is not available.
Progress_Starting_label = Starting
Progress_Terminating_label = Terminating
diff --git a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/Queue.java b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/Queue.java
index 1d6fcc5..ef3cd91 100644
--- a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/Queue.java
+++ b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/Queue.java
@@ -29,6 +29,9 @@
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
+import org.eclipse.statet.jcommons.lang.NonNull;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ecommons.ts.core.SystemRunnable;
import org.eclipse.statet.ecommons.ts.core.ToolQueue;
@@ -39,7 +42,7 @@
/**
- * Queue with IToolRunnable waiting to be processed by the tool/controller.
+ * Queue with ToolRunnable waiting to be processed by the tool/controller.
*
* Usage: You get your queue via accessor of the ToolProcess.
*
@@ -60,6 +63,7 @@
* The events of this type are sended by the queue (source element).
*
*/
+@NonNullByDefault
public final class Queue implements ToolQueue {
@@ -74,7 +78,7 @@
* Constant for detail of a DebugEvent, sending the complete queue.
* This does not signalising, that the queue has changed.
* <p>
- * The queue entries (<code>IToolRunnable[]</code>) are attached as
+ * The queue entries (<code>List<ToolRunnable></code>) are attached as
* data to this event. The source of the event is the ToolProcess.
* <p>
* Usage: Events of this type are sended by the ToolProcess/its queue.
@@ -83,19 +87,6 @@
*/
public static final int QUEUE_INFO= 1;
-// /**
-// * Constant for detail of a DebugEvent, signalising that
-// * queue has changed e.g. reordered, cleared,... .
-// * <p>
-// * The queue entries (<code>IToolRunnable[]</code>) are attached as
-// * data to this event. The source of the event is the ToolProcess.
-// * <p>
-// * Usage: Events of this type are sended by the ToolProcess/its queue.
-// * The constant is applicable for DebugEvents of kind
-// * <code>MODEL_SPECIFIC</code>.</p>
-// */
-// public static final int QUEUE_MAJOR_CHANGE= 2;
-
public static final int STATE_REQUEST= 5;
@@ -148,6 +139,116 @@
}
+ public static final int IF_ABSENT= 1 << 0;
+
+
+ public static class RunnableStatus implements IStatus {
+
+
+ private static final IStatus[] NO_CHILDREN= new IStatus[0];
+
+
+ private final int severity;
+
+ private final int code;
+
+ private final String message;
+
+ private final ToolRunnable runnable;
+
+
+ public RunnableStatus(final int severity, final int code, final String message,
+ final ToolRunnable runnable) {
+ this.severity= severity;
+ this.code= code;
+ this.message= message;
+ this.runnable= runnable;
+ }
+
+
+ @Override
+ public int getSeverity() {
+ return this.severity;
+ }
+
+ @Override
+ public boolean isOK() {
+ return (this.severity == OK);
+ }
+
+ @Override
+ public boolean matches(final int severityMask) {
+ return (this.severity & severityMask) != 0;
+ }
+
+ @Override
+ public String getPlugin() {
+ return "Tool.Queue";
+ }
+
+ @Override
+ public int getCode() {
+ return this.code;
+ }
+
+ @Override
+ public String getMessage() {
+ return this.message;
+ }
+
+ public ToolRunnable getRunnable() {
+ return this.runnable;
+ }
+
+ @Override
+ public @Nullable Throwable getException() {
+ return null;
+ }
+
+ @Override
+ public boolean isMultiStatus() {
+ return false;
+ }
+
+ @Override
+ public IStatus[] getChildren() {
+ return NO_CHILDREN;
+ }
+
+ }
+
+ public static final IStatus ADDED_STATUS= Status.OK_STATUS;
+
+ public static final IStatus ALREADY_PRESENT_STATUS= new Status(IStatus.INFO, ADDED_STATUS.getPlugin(), "Already " + ADDED_STATUS.getMessage());
+
+
+ private static ToolRunnable checkRunnable(final @Nullable ToolRunnable runnable) {
+ if (runnable == null) {
+ throw new NullPointerException("runnable"); //$NON-NLS-1$
+ }
+ return runnable;
+ }
+
+ private static ImList<ToolRunnable> checkRunnableList(final @Nullable ToolRunnable runnable) {
+ if (runnable == null) {
+ throw new NullPointerException("runnable"); //$NON-NLS-1$
+ }
+ return ImCollections.newList(runnable);
+ }
+
+ private static ImList<ToolRunnable> checkRunnableList(final @Nullable List<ToolRunnable> runnables) {
+ if (runnables == null) {
+ throw new NullPointerException("runnables"); //$NON-NLS-1$
+ }
+ final ImList<ToolRunnable> finalRunnables= ImCollections.toList(runnables);
+ final int i= finalRunnables.indexOf(null);
+ if (i >= 0) {
+ throw new NullPointerException("runnable[" + i + ']'); //$NON-NLS-1$
+ }
+ return finalRunnables;
+ }
+
+
static final int RUN_NONE= -2;
static final int RUN_SUSPEND= -1;
static final int RUN_CONTROL= 1;
@@ -155,6 +256,7 @@
static final int RUN_OTHER= 3;
static final int RUN_DEFAULT= 4;
+
private static class RankedItem {
final ToolRunnable runnable;
@@ -182,19 +284,126 @@
}
- private final LinkedList<ToolRunnable> list= new LinkedList<>();
- private ImList<ToolRunnable> singleIOCache= null;
- private ToolRunnable insertRunnable= null;
- private final List<ToolRunnable> insertRunnableStack= new ArrayList<>();
- private int insertIndex= -1;
+
+ public static interface Section {
+
+ }
+
+ private static abstract class SubQueue implements Section {
+
+ protected final LinkedList<ToolRunnable> list= new LinkedList<>();
+
+ private @Nullable SubQueue next;
+
+ private boolean state;
+
+
+ public abstract int getAllSize();
+
+ public abstract int getAll(final ToolRunnable[] array, final int i);
+
+ public int getStartIdx() {
+ int idx= 0;
+ SubQueue next= this.next;
+ while (next != null) {
+ idx+= next.getAllSize();
+ next= next.next;
+ }
+ return idx;
+ }
+
+ public int getAppendIdx() {
+ return getStartIdx() + this.list.size();
+ }
+
+ public void append(final ImList<ToolRunnable> runnables) {
+ if (runnables.size() == 1) {
+ this.list.add(runnables.get(0));
+ }
+ else {
+ this.list.addAll(runnables);
+ }
+ }
+
+ public void append(final ToolRunnable runnable) {
+ this.list.add(runnable);
+ }
+
+ public void dispose() {
+ this.state= true;
+
+ this.list.clear();
+
+ this.next= null;
+ }
+
+ public boolean isDispose() {
+ return this.state;
+ }
+
+ }
+
+ private static final class TopLevelQueue extends SubQueue {
+
+
+ public TopLevelQueue() {
+ }
+
+
+ @Override
+ public int getAllSize() {
+ return this.list.size();
+ }
+
+ @Override
+ public int getAll(final ToolRunnable[] array, int i) {
+ for (final ToolRunnable runnable : this.list) {
+ array[i++]= runnable;
+ }
+ return i;
+ }
+
+ }
+
+ private static final class InsertQueue extends SubQueue {
+
+ protected final ToolRunnable insertRunnable;
+
+
+ public InsertQueue(final ToolRunnable insertRunnable) {
+ this.insertRunnable= insertRunnable;
+ }
+
+
+ @Override
+ public int getAllSize() {
+ return this.list.size() + 1;
+ }
+
+ @Override
+ public int getAll(final ToolRunnable[] array, int i) {
+ for (final ToolRunnable runnable : this.list) {
+ array[i++]= runnable;
+ }
+ array[i++]= this.insertRunnable;
+ return i;
+ }
+
+ }
+
+ private final List<SubQueue> sectionStack= new ArrayList<>();
+ private final SubQueue topLevelSection; // sectionStack.first
+ private SubQueue currentSection; // sectionStack.last
+ private @Nullable ImList<ToolRunnable> singleIOCache= null;
+
private final Deque<ImList<ToolRunnable>> finishedExpected= new ArrayDeque<>();
private final List<DebugEvent> eventList= new ArrayList<>(5);
private final ToolProcess process;
- private boolean resetOnIdle= false;
+ private boolean resetOnIdle= true;
private final List<RankedItem> onIdleList= new ArrayList<>();
- private final LinkedList<ToolRunnable> nextIdleList= new LinkedList<>();
+ private final LinkedList<ToolRunnable> currentIdleList= new LinkedList<>();
private final LinkedList<ToolRunnable> hotList= new LinkedList<>();
@@ -204,31 +413,59 @@
Queue(final ToolProcess process) {
this.process= process;
+
+ this.topLevelSection= new TopLevelQueue();
+ this.sectionStack.add(this.topLevelSection);
+ this.currentSection= this.topLevelSection;
}
private final IStatus acceptSubmit(final ToolStatus toolStatus) {
if (toolStatus == ToolStatus.TERMINATED) {
return new Status(IStatus.ERROR, NicoCore.BUNDLE_ID, -1,
- NLS.bind(Messages.ToolController_ToolTerminated_message, this.process.getLabel(0)), null);
+ NLS.bind(Messages.ToolController_ToolTerminated_message, this.process.getLabel(0)),
+ null );
}
- return Status.OK_STATUS;
+ return ADDED_STATUS;
+ }
+
+ private final IStatus acceptSubmit(final ToolStatus toolStatus, final SubQueue section) {
+ if (toolStatus == ToolStatus.TERMINATED) {
+ return new Status(IStatus.ERROR, NicoCore.BUNDLE_ID, -1,
+ NLS.bind(Messages.ToolController_ToolTerminated_message, this.process.getLabel(0)),
+ null );
+ }
+ if (section.isDispose()) {
+ return new Status(IStatus.ERROR, NicoCore.BUNDLE_ID, -1,
+ NLS.bind(Messages.ToolController_QueueSectionTerminated_message, this.process.getLabel(0)),
+ null );
+ }
+ return ADDED_STATUS;
}
public synchronized void sendElements() {
checkIOCache();
- final ToolRunnable[] queueElements= this.list.toArray(new ToolRunnable[this.list.size()]);
+ final ImList<ToolRunnable> runnables= internal_createCompleteList();
final DebugEvent event= new DebugEvent(this, DebugEvent.MODEL_SPECIFIC, QUEUE_INFO);
- event.setData(queueElements);
+ event.setData(runnables);
this.eventList.add(event);
- internalFireEvents();
+ internal_fireEvents();
}
- public synchronized int size() {
+ public Section getTopLevelSection() {
+ return this.topLevelSection;
+ }
+
+ public synchronized Section getCurrentSection() {
+ return this.currentSection;
+ }
+
+
+ public synchronized int getCurrentSize() {
if (this.singleIOCache != null) {
return 1;
}
- return this.list.size();
+ return this.currentSection.list.size();
}
/**
@@ -241,10 +478,9 @@
*/
@Override
public IStatus add(final ToolRunnable runnable) {
- if (runnable == null) {
- throw new NullPointerException("runnable"); //$NON-NLS-1$
- }
- return doAdd(ImCollections.newList(runnable));
+ final ImList<ToolRunnable> checkedRunnables= checkRunnableList(runnable);
+
+ return doAdd(checkedRunnables, null);
}
/**
@@ -256,128 +492,131 @@
* @return the status of the queue operation.
*/
public IStatus add(final List<ToolRunnable> runnables) {
- if (runnables == null) {
- throw new NullPointerException("runnables"); //$NON-NLS-1$
- }
- final ImList<ToolRunnable> finalRunnables= ImCollections.toList(runnables);
- for (int i= 0; i < finalRunnables.size(); i++) {
- if (runnables.get(i) == null) {
- throw new NullPointerException("runnable["+i+']'); //$NON-NLS-1$
- }
- }
- return doAdd(finalRunnables);
+ final ImList<ToolRunnable> checkedRunnables= checkRunnableList(runnables);
+
+ return doAdd(checkedRunnables, null);
}
- private synchronized IStatus doAdd(final ImList<ToolRunnable> runnables) {
+ /**
+ * Submits the runnable for the tool.
+ * <p>
+ * The runnable will be added to the queue in the specified section
+ * and will be run, if it's its turn.
+ *
+ * @param runnable the runnable to add
+ * @param section where to add the runnable, <code>null</code> for current section
+ * @param strategy flags {@link #IF_ABSENT}
+ * @return the status of the queue operation.
+ */
+ public IStatus add(final ToolRunnable runnable,
+ final @Nullable Section section, final int strategy) {
+ final ToolRunnable checkedRunnable= checkRunnable(runnable);
+
+ return doAdd(checkedRunnable, (SubQueue) section, strategy);
+ }
+
+ /**
+ * Submits the runnables for the tool.
+ * <p>
+ * The runnables will be added en block to the queue in the specified section
+ * and will be runned, if it's its turn.
+ *
+ * @param runnables the runnables to add.
+ * @param section where to add the runnabler, <code>null</code> for current section
+ * @return the status of the queue operation.
+ */
+ public IStatus add(final List<ToolRunnable> runnables,
+ final @Nullable Section section) {
+ final ImList<ToolRunnable> checkedRunnables= checkRunnableList(runnables);
+
+ return doAdd(checkedRunnables, (SubQueue) section);
+ }
+
+ private synchronized IStatus doAdd(final ImList<ToolRunnable> runnables,
+ @Nullable SubQueue section) {
+ if (section == null) {
+ section= this.currentSection;
+ }
+
final ToolStatus toolStatus= this.process.getToolStatus();
- final IStatus status= acceptSubmit(toolStatus);
+ final IStatus status= acceptSubmit(toolStatus, section);
if (status.getSeverity() < IStatus.ERROR) {
if (toolStatus.isWaiting()) {
- internalAdd(runnables, true);
+ internal_add(runnables, section, true);
notifyAll();
}
else {
- internalAdd(runnables, false);
+ internal_add(runnables, section, false);
}
}
return status;
}
+ private synchronized IStatus doAdd(final ToolRunnable runnable,
+ @Nullable SubQueue section, final int strategy) {
+ if (section == null) {
+ section= this.currentSection;
+ }
+
+ final ToolStatus toolStatus= this.process.getToolStatus();
+ final IStatus status= acceptSubmit(toolStatus, section);
+ if (status.getSeverity() < IStatus.ERROR) {
+ if (strategy != 0) {
+ checkIOCache();
+
+ int idx;
+ if ((strategy & IF_ABSENT) != 0 && (idx= section.list.indexOf(runnable)) >= 0) {
+ return new RunnableStatus(IStatus.INFO, IF_ABSENT, "OK", section.list.get(idx)); //$NON-NLS-1$
+ }
+ }
+
+ if (toolStatus.isWaiting()) {
+ internal_add(ImCollections.newList(runnable), section, true);
+ notifyAll();
+ }
+ else {
+ internal_add(ImCollections.newList(runnable), section, false);
+ }
+ return new RunnableStatus(IStatus.OK, 0, "OK", runnable); //$NON-NLS-1$
+ }
+ return status;
+ }
+
@Override
public void remove(final ToolRunnable runnable) {
- if (runnable == null) {
- throw new NullPointerException("runnable"); //$NON-NLS-1$
- }
- doRemove(new ToolRunnable[] { runnable });
- }
-
- public void remove(final ToolRunnable[] runnables) {
- if (runnables == null) {
- throw new NullPointerException("runnables"); //$NON-NLS-1$
- }
- for (int i= 0; i < runnables.length; i++) {
- if (runnables[i] == null) {
- throw new NullPointerException("runnable["+i+']'); //$NON-NLS-1$
- }
- }
- doRemove(runnables);
- }
-
- private void doRemove(final ToolRunnable[] runnables) {
+ final ImList<ToolRunnable> checkedRunnables= checkRunnableList(runnable);
+
synchronized (this) {
- checkIOCache();
- final List<ToolRunnable> removed= new ArrayList<>(runnables.length);
- boolean checkInsert= false;
- for (final ToolRunnable runnable : runnables) {
- final int index= this.list.indexOf(runnable);
- if (index >= 0 && runnable.changed(ToolRunnable.REMOVING_FROM, this.process)) {
- this.list.remove(index);
- removed.add(runnable);
- if (!checkInsert && index < this.insertIndex) {
- checkInsert= true;
- }
- }
- }
- if (checkInsert) {
- this.insertIndex= this.list.indexOf(this.insertRunnable);
- }
- // IToolRunnable[] queueElements= fList.toArray(new IToolRunnable[fList.size()]);
- // addDebugEvent(COMPLETE_CHANGE, queueElements);
- final ImList<ToolRunnable> finalRunnables= ImCollections.toList(removed);
- addChangeEvent(ToolRunnable.REMOVING_FROM, finalRunnables);
- internalFireEvents();
+ internal_remove(checkedRunnables);
+
+ internal_fireEvents();
}
}
- public void move(final ToolRunnable[] runnables, final Queue to) {
- if (runnables == null) {
- throw new NullPointerException("runnables"); //$NON-NLS-1$
+ public void remove(final List<ToolRunnable> runnables) {
+ final ImList<ToolRunnable> checkedRunnables= checkRunnableList(runnables);
+
+ synchronized (this) {
+ internal_remove(checkedRunnables);
+
+ internal_fireEvents();
}
+ }
+
+ public void move(final ImList<ToolRunnable> runnables, final Queue to) {
+ final ImList<ToolRunnable> checkedRunnables= checkRunnableList(runnables);
if (to == null) {
throw new NullPointerException("to"); //$NON-NLS-1$
}
+
final ImList<ToolRunnable> finalRunnables;
synchronized (this) {
- checkIOCache();
- final List<ToolRunnable> removed= new ArrayList<>(runnables.length);
- boolean checkInsert= false;
- for (final ToolRunnable runnable : runnables) {
- final int index= this.list.indexOf(runnable);
- if (index >= 0 && runnable.changed(ToolRunnable.MOVING_FROM, this.process)) {
- this.list.remove(index);
- removed.add(runnable);
- if (!checkInsert && index < this.insertIndex) {
- checkInsert= true;
- }
- }
- }
- if (checkInsert) {
- this.insertIndex= this.list.indexOf(this.insertRunnable);
- }
- finalRunnables= ImCollections.toList(removed);
- addChangeEvent(ToolRunnable.MOVING_FROM, finalRunnables);
- internalFireEvents();
+ finalRunnables= internal_moveFrom(checkedRunnables);
}
synchronized (to) {
- to.checkIOCache();
- if (to == this && this.insertIndex >= 0) {
- this.list.addAll(this.insertIndex, finalRunnables);
- for (final ToolRunnable runnable : finalRunnables) {
- runnable.changed(ToolRunnable.MOVING_TO, to.process);
- }
- addContentEvent(DebugEvent.CHANGE, DebugEvent.CONTENT,
- new TaskDelta(ToolRunnable.MOVING_TO, this.insertIndex, finalRunnables));
- this.insertIndex+= finalRunnables.size();
- }
- else {
- to.list.addAll(finalRunnables);
- for (final ToolRunnable runnable : finalRunnables) {
- runnable.changed(ToolRunnable.MOVING_TO, to.process);
- }
- to.addChangeEvent(ToolRunnable.MOVING_TO, finalRunnables);
- }
- to.internalFireEvents();
+ to.internal_moveTo(finalRunnables, to.currentSection);
+
to.notifyAll();
}
}
@@ -389,49 +628,44 @@
final ImList<ToolRunnable> finalRunnables;
synchronized (this) {
checkIOCache();
- final List<ToolRunnable> removed= new ArrayList<>(this.list.size());
- for (final Iterator<ToolRunnable> iter= this.list.iterator(); iter.hasNext();) {
- final ToolRunnable runnable= iter.next();
- if (runnable.changed(ToolRunnable.MOVING_FROM, this.process)) {
- iter.remove();
- removed.add(runnable);
+
+ { final List<ToolRunnable> removed= new ArrayList<>(internal_getCompleteSize());
+ for (final Iterator<ToolRunnable> iter= this.topLevelSection.list.iterator(); iter.hasNext();) {
+ final ToolRunnable runnable= iter.next();
+ if (runnable.changed(ToolRunnable.MOVING_FROM, this.process)) {
+ iter.remove();
+ removed.add(runnable);
+ }
}
+ finalRunnables= ImCollections.toList(removed);
}
- if (this.insertIndex >= 0) {
- this.insertIndex= this.list.indexOf(this.insertRunnable);
- }
- finalRunnables= ImCollections.toList(removed);
- addChangeEvent(ToolRunnable.MOVING_FROM, finalRunnables);
- internalFireEvents();
+
+ addContentChangeEvent(new TaskDelta(ToolRunnable.MOVING_FROM, -1, finalRunnables));
+
+ internal_fireEvents();
}
synchronized (to) {
- to.checkIOCache();
- to.list.addAll(finalRunnables);
- for (final ToolRunnable runnable : finalRunnables) {
- runnable.changed(ToolRunnable.MOVING_TO, to.process);
- }
- to.addChangeEvent(ToolRunnable.MOVING_TO, finalRunnables);
- to.internalFireEvents();
+ to.internal_moveTo(finalRunnables, to.topLevelSection);
+
to.notifyAll();
}
}
public IStatus addOnIdle(final SystemRunnable runnable, final int rank) {
- if (runnable == null) {
- throw new NullPointerException("runnable"); //$NON-NLS-1$
- }
+ final ToolRunnable checkedRunnable= checkRunnable(runnable);
+
synchronized (this) {
final ToolStatus toolStatus= this.process.getToolStatus();
final IStatus status= acceptSubmit(toolStatus);
if (status.getSeverity() < IStatus.ERROR) {
- final RankedItem item= new RankedItem(runnable, rank);
+ final RankedItem item= new RankedItem(checkedRunnable, rank);
int idx= this.onIdleList.indexOf(item);
if (idx >= 0 && this.onIdleList.get(idx).rank != rank) {
this.onIdleList.remove(idx);
if (!this.resetOnIdle) {
- this.nextIdleList.remove(item.runnable);
+ this.currentIdleList.remove(item.runnable);
}
idx= -1;
}
@@ -445,14 +679,14 @@
this.onIdleList.add(idx, item);
if (!this.resetOnIdle) {
- if (idx == this.onIdleList.size()-1) { // last
- this.nextIdleList.add(item.runnable);
+ if (idx == this.onIdleList.size() - 1) { // last
+ this.currentIdleList.add(item.runnable);
}
else {
- final RankedItem next= this.onIdleList.get(idx+1);
- final int nextIdx= this.nextIdleList.indexOf(next.runnable);
+ final RankedItem next= this.onIdleList.get(idx + 1);
+ final int nextIdx= this.currentIdleList.indexOf(next.runnable);
if (nextIdx >= 0) {
- this.nextIdleList.add(nextIdx, item.runnable);
+ this.currentIdleList.add(nextIdx, item.runnable);
}
}
}
@@ -464,12 +698,11 @@
}
public void removeOnIdle(final ToolRunnable runnable) {
- if (runnable == null) {
- throw new NullPointerException("runnable"); //$NON-NLS-1$
- }
+ final ToolRunnable checkedRunnable= checkRunnable(runnable);
+
synchronized (this) {
- this.onIdleList.remove(new RankedItem(runnable, 0));
- this.nextIdleList.remove(runnable);
+ this.onIdleList.remove(new RankedItem(checkedRunnable, 0));
+ this.currentIdleList.remove(runnable);
}
}
@@ -484,19 +717,18 @@
}
public IStatus addHot(final ToolRunnable runnable, final int strategy) {
- if (runnable == null) {
- throw new NullPointerException("runnable"); //$NON-NLS-1$
- }
+ final ToolRunnable checkedRunnable= checkRunnable(runnable);
+
synchronized (this) {
final ToolStatus toolStatus= this.process.getToolStatus();
final IStatus status= acceptSubmit(toolStatus);
if (status.getSeverity() < IStatus.ERROR) {
- if ((strategy & 1) != 0) {
- if (this.hotList.contains(runnable)) {
- return Status.OK_STATUS;
+ if ((strategy & IF_ABSENT) != 0) {
+ if (this.hotList.contains(checkedRunnable)) {
+ return ALREADY_PRESENT_STATUS;
}
}
- this.hotList.add(runnable);
+ this.hotList.add(checkedRunnable);
if (this.hotList.size() > 0) {
notifyAll();
final ToolController controller= this.process.getController();
@@ -511,120 +743,191 @@
@Override
public void removeHot(final ToolRunnable runnable) {
- if (runnable == null) {
- throw new NullPointerException("runnable"); //$NON-NLS-1$
- }
+ final ToolRunnable checkedRunnable= checkRunnable(runnable);
synchronized (this) {
- if (this.hotList.remove(runnable)) {
+ if (this.hotList.remove(checkedRunnable)) {
runnable.changed(ToolRunnable.REMOVING_FROM, this.process);
}
}
}
- void internalAdd(final ImList<ToolRunnable> runnables, final boolean allowCache) {
- if (allowCache && this.singleIOCache == null && this.list.isEmpty()
- && runnables.size() == 1) {
+ private void internal_add(final ImList<ToolRunnable> runnables, final SubQueue section,
+ final boolean allowCache) {
+ if (allowCache && this.singleIOCache == null
+ && runnables.size() == 1
+ && section == this.currentSection && this.currentSection.list.isEmpty() ) {
this.singleIOCache= runnables;
return;
}
checkIOCache();
- if (this.insertIndex >= 0) {
- if (runnables.size() == 1) {
- this.list.add(this.insertIndex, runnables.get(0));
- }
- else {
- this.list.addAll(this.insertIndex, runnables);
- }
- addContentEvent(DebugEvent.CHANGE, DebugEvent.CONTENT,
- new TaskDelta(ToolRunnable.ADDING_TO, this.insertIndex, runnables) );
- this.insertIndex += runnables.size();
- }
- else {
- if (runnables.size() == 1) {
- this.list.add(runnables.get(0));
- }
- else {
- this.list.addAll(runnables);
- }
- addContentEvent(DebugEvent.CHANGE, DebugEvent.CONTENT,
- new TaskDelta(ToolRunnable.ADDING_TO, -1, runnables) );
- }
- internalFireEvents();
+
+ final int idx= section.getAppendIdx();
+ section.append(runnables);
+ addContentChangeEvent(new TaskDelta(ToolRunnable.ADDING_TO, idx, runnables));
+
+ internal_fireEvents();
}
- void internalAddInsert(final ToolRunnable runnable) {
+ private void internal_remove(final ImList<ToolRunnable> runnables) {
checkIOCache();
- this.insertRunnableStack.add(runnable);
- this.insertRunnable= runnable;
- this.insertIndex= 0;
- this.list.add(0, runnable);
- addContentEvent(DebugEvent.CHANGE, DebugEvent.CONTENT,
- new TaskDelta(ToolRunnable.ADDING_TO, 0, ImCollections.newList(runnable)) );
- internalFireEvents();
- }
-
- void internalRemoveInsert(final ToolRunnable runnable) {
- checkIOCache();
-
- final List<ToolRunnable> removed= new ArrayList<>(this.insertIndex+1);
- final int insertStackIdx= this.insertRunnableStack.indexOf(runnable);
- if (insertStackIdx < 0) {
- return;
- }
- final Iterator<ToolRunnable> iter= this.list.iterator();
- if (insertStackIdx < this.insertRunnableStack.size()-1) {
- final ToolRunnable start= this.insertRunnableStack.get(insertStackIdx+1);
- while (iter.hasNext()) {
- if (iter.next() == start) {
- break;
+ final ImList<ToolRunnable> finalRunnables;
+ { final List<ToolRunnable> removed= new ArrayList<>(runnables.size());
+
+ ITER_RUNNABLE: for (final ToolRunnable runnable : runnables) {
+ for (int iSection= this.sectionStack.size() - 1; iSection >= 0; iSection--) {
+ final SubQueue section= this.sectionStack.get(iSection);
+ final int idx= section.list.indexOf(runnable);
+ if (idx >= 0) {
+ if (runnable.changed(ToolRunnable.REMOVING_FROM, this.process)) {
+ section.list.remove(idx);
+ removed.add(runnable);
+ }
+ continue ITER_RUNNABLE;
+ }
}
}
+ finalRunnables= ImCollections.toList(removed);
}
- while (iter.hasNext()) {
- final ToolRunnable toRemove= iter.next();
- if (toRemove == runnable) {
- iter.remove();
- removed.add(toRemove);
- break;
+
+ addContentChangeEvent(new TaskDelta(ToolRunnable.REMOVING_FROM, -1, finalRunnables));
+
+ internal_fireEvents();
+ }
+
+ private ImList<ToolRunnable> internal_moveFrom(final ImList<ToolRunnable> runnables) {
+ checkIOCache();
+
+ final ImList<ToolRunnable> finalRunnables;
+ { final List<ToolRunnable> removed= new ArrayList<>(runnables.size());
+
+ ITER_RUNNABLE: for (final ToolRunnable runnable : runnables) {
+ for (int iSection= this.sectionStack.size() - 1; iSection >= 0; iSection--) {
+ final SubQueue section= this.sectionStack.get(iSection);
+ final int idx= section.list.indexOf(runnable);
+ if (idx >= 0) {
+ if (runnable.changed(ToolRunnable.MOVING_FROM, this.process)) {
+ section.list.remove(idx);
+ removed.add(runnable);
+ }
+ continue ITER_RUNNABLE;
+ }
+ }
}
- if (toRemove.changed(ToolRunnable.REMOVING_FROM, this.process)) {
- iter.remove();
- removed.add(toRemove);
+ finalRunnables= ImCollections.toList(removed);
+ }
+
+ addContentChangeEvent(new TaskDelta(ToolRunnable.MOVING_FROM, -1, finalRunnables));
+
+ internal_fireEvents();
+
+ return finalRunnables;
+ }
+
+ private void internal_moveTo(final ImList<ToolRunnable> runnables, final SubQueue section) {
+ checkIOCache();
+
+ final int idx= section.getAppendIdx();
+ section.append(runnables);
+ addContentChangeEvent(new TaskDelta(ToolRunnable.MOVING_TO, idx, runnables));
+
+ internal_fireEvents();
+ }
+
+
+ Section internal_addInsert(final ToolRunnable runnable) {
+ assert (runnable != null);
+
+ checkIOCache();
+
+ final SubQueue section= new InsertQueue(runnable);
+ this.sectionStack.add(section);
+ this.currentSection.next= section;
+ this.currentSection= section;
+ addContentChangeEvent(new TaskDelta(ToolRunnable.ADDING_TO, 0, ImCollections.newList(runnable)));
+
+ internal_resetOnIdle();
+
+ internal_fireEvents();
+
+ return section;
+ }
+
+ void internal_removeInsert(final Section section) {
+ assert (section != null);
+
+ checkIOCache();
+
+ final int sectionIdx= this.sectionStack.indexOf(section);
+ if (sectionIdx < 0) {
+ return;
+ }
+ if (sectionIdx == 0) {
+ throw new IllegalArgumentException();
+ }
+
+ final ImList<ToolRunnable> finalRunnables;
+ { final ToolRunnable[] runnables= new @NonNull ToolRunnable[
+ internal_getSize(sectionIdx, this.sectionStack.size()) ];
+ int i= 0;
+ for (int iSection= this.sectionStack.size() - 1; iSection >= sectionIdx; iSection--) {
+ final SubQueue removedSection= this.sectionStack.remove(iSection);
+ i= removedSection.getAll(runnables, i);
+ removedSection.dispose();
+ }
+ this.currentSection= this.sectionStack.get(this.sectionStack.size() - 1);
+ this.currentSection.next= null;
+
+ finalRunnables= ImCollections.newList(runnables);
+ }
+ for (final ToolRunnable runnable : finalRunnables) {
+// runnable.changed(ToolRunnable.BEING_ABANDONED, this.process);
+ if (!runnable.changed(ToolRunnable.REMOVING_FROM, this.process)) {
+ runnable.changed(ToolRunnable.BEING_ABANDONED, this.process);
}
}
- final ImList<ToolRunnable> finalRunnables= ImCollections.toList(removed);
- addChangeEvent(ToolRunnable.REMOVING_FROM, finalRunnables);
- this.insertRunnableStack.remove(runnable);
- if (this.insertRunnableStack.isEmpty()) {
- this.insertRunnable= null;
- this.insertIndex= -1;
- }
- else {
- this.insertRunnable= this.insertRunnableStack.get(this.insertRunnableStack.size()-1);
- this.insertIndex= this.list.indexOf(this.insertRunnable);
- }
- internalFireEvents();
- }
-
- void internalScheduleIdle(final ToolRunnable runnable) {
- if (runnable == null) {
- throw new NullPointerException();
- }
- this.nextIdleList.add(runnable);
- }
-
- void internalRemoveIdle(final ToolRunnable runnable) {
- if (runnable == null) {
- throw new NullPointerException();
- }
- this.nextIdleList.remove(runnable);
+
+ addContentChangeEvent(new TaskDelta(ToolRunnable.REMOVING_FROM, -1, finalRunnables));
+
+ internal_resetOnIdle();
+
+ internal_fireEvents();
}
- int internalNext() {
+ void internal_scheduleIdle(final ToolRunnable runnable) {
+ final ToolRunnable checkedRunnable= checkRunnable(runnable);
+
+ this.currentIdleList.add(checkedRunnable);
+ }
+
+ void internal_removeIdle(final ToolRunnable runnable) {
+ final ToolRunnable checkedRunnable= checkRunnable(runnable);
+
+ this.currentIdleList.remove(checkedRunnable);
+ }
+
+
+ void internal_check() {
+ checkIOCache();
+ internal_fireEvents();
+ }
+
+ void internal_resetOnIdle() {
+ this.resetOnIdle= true;
+ }
+
+ private void internal_resetIdleList() {
+ this.resetOnIdle= false;
+ this.currentIdleList.clear();
+ for (int i= 0; i < this.onIdleList.size(); i++) {
+ this.currentIdleList.add(this.onIdleList.get(i).runnable);
+ }
+ }
+
+ int internal_next() {
if (!this.hotList.isEmpty()) {
return RUN_HOT;
}
@@ -632,104 +935,99 @@
if (this.singleIOCache != null) {
runnable= this.singleIOCache.get(0);
}
- else if (!this.list.isEmpty() && this.insertIndex != 0) {
- runnable= this.list.get(0);
- }
- else if (!this.nextIdleList.isEmpty()) {
- runnable= this.nextIdleList.get(0);
+ else if (!this.currentSection.list.isEmpty()) {
+ runnable= this.currentSection.list.peekFirst();
}
else {
- return RUN_NONE;
+ if (this.resetOnIdle) {
+ internal_resetIdleList();
+ }
+ if (!this.currentIdleList.isEmpty()) {
+ runnable= this.currentIdleList.peekFirst();
+ }
+ else {
+ return RUN_NONE;
+ }
}
return (runnable instanceof SystemRunnable) ?
RUN_OTHER : RUN_DEFAULT;
}
- boolean internalNextHot() {
- return !this.hotList.isEmpty();
- }
-
- void internalCheck() {
- checkIOCache();
- internalFireEvents();
- }
-
- void internalResetIdle() {
- this.resetOnIdle= false;
- for (int i= this.onIdleList.size()-1; i >= 0; i--) {
- if (!this.nextIdleList.remove(this.onIdleList.get(i).runnable)) {
- break;
- }
- }
- for (int i= 0; i < this.onIdleList.size(); i++) {
- this.nextIdleList.add(this.onIdleList.get(i).runnable);
- }
- }
-
-
- ToolRunnable internalPoll() {
- final ImList<ToolRunnable> finalRunnable;
+ /** After check with {@link #internal_next()} */
+ ToolRunnable internal_poll() {
+ final @NonNull ImList<ToolRunnable> finalRunnable;
if (this.singleIOCache != null) {
finalRunnable= this.singleIOCache;
- if (this.insertIndex >= 0) {
- addContentEvent(DebugEvent.CHANGE, DebugEvent.CONTENT,
- new TaskDelta(ToolRunnable.ADDING_TO, this.insertIndex, this.singleIOCache));
- }
- else {
- addContentEvent(DebugEvent.CHANGE, DebugEvent.CONTENT,
- new TaskDelta(ToolRunnable.ADDING_TO, -1, this.singleIOCache));
- }
+ final int idx= this.currentSection.getAppendIdx();
+ addContentChangeEvent(new TaskDelta(ToolRunnable.ADDING_TO, idx, finalRunnable));
this.singleIOCache= null;
- if (this.resetOnIdle) {
- internalResetIdle();
- }
+ internal_resetOnIdle();
}
- else if (!this.list.isEmpty() && this.insertIndex != 0) {
- finalRunnable= ImCollections.newList(this.list.poll());
- if (this.insertIndex >= 0) {
- this.insertIndex--;
- }
- if (this.resetOnIdle) {
- internalResetIdle();
- }
+ else if (!this.currentSection.list.isEmpty()) {
+ finalRunnable= ImCollections.newList(this.currentSection.list.pollFirst());
+ internal_resetOnIdle();
}
else {
- finalRunnable= ImCollections.newList(this.nextIdleList.poll());
- this.resetOnIdle= true;
+ finalRunnable= ImCollections.newList(this.currentIdleList.pollFirst());
}
- addChangeEvent(ToolRunnable.STARTING, finalRunnable);
+ addContentChangeEvent(new TaskDelta(ToolRunnable.STARTING, -1, finalRunnable));
- internalFireEvents();
+ internal_fireEvents();
this.finishedExpected.push(finalRunnable);
return finalRunnable.get(0);
}
- ToolRunnable internalPollHot() {
- return this.hotList.poll();
+ boolean internal_nextHot() {
+ return !this.hotList.isEmpty();
+ }
+
+ @Nullable ToolRunnable internal_pollHot() {
+ return this.hotList.pollFirst();
}
/**
* Not necessary in synchronized block
*/
- void internalFinished(final ToolRunnable runnable, final int detail) {
+ void internal_onFinished(final ToolRunnable runnable, final int detail) {
assert (runnable == this.finishedExpected.peek().get(0));
- addChangeEvent(detail, this.finishedExpected.poll());
+ addContentChangeEvent(new TaskDelta(detail, -1, this.finishedExpected.poll()));
}
- List<ToolRunnable> internalGetList() {
- internalCheck();
- return this.list;
+ private int internal_getCompleteSize() {
+ int size= 0;
+ for (int iSection= this.sectionStack.size() - 1; iSection >= 0; iSection--) {
+ size+= this.sectionStack.get(iSection).getAllSize();
+ }
+ return size;
}
- List<ToolRunnable> internalGetCurrentList() {
- internalCheck();
- if (this.insertIndex >= 0) {
- return this.list.subList(0, this.insertIndex);
+ private int internal_getSize(final int startSection, final int endSection) {
+ int size= 0;
+ for (int iSection= endSection - 1; iSection >= startSection; iSection--) {
+ size+= this.sectionStack.get(iSection).getAllSize();
}
- else {
- return this.list;
+ return size;
+ }
+
+ private ImList<ToolRunnable> internal_createCompleteList() {
+ final ToolRunnable[] runnables= new @NonNull ToolRunnable[
+ internal_getCompleteSize() ];
+ int i= 0;
+ for (int iSection= this.sectionStack.size() - 1; iSection >= 0; iSection--) {
+ i= this.sectionStack.get(iSection).getAll(runnables, i);
}
+ return ImCollections.newList(runnables);
+ }
+
+ List<ToolRunnable> internal_getList() {
+ internal_check();
+ return internal_createCompleteList();
+ }
+
+ List<ToolRunnable> internal_getCurrentList() {
+ internal_check();
+ return this.currentSection.list;
}
@@ -746,7 +1044,7 @@
this.stateRequest= PAUSED_STATE;
addStateEvent(DebugEvent.MODEL_SPECIFIC, STATE_REQUEST,
new StateDelta(oldState, PAUSED_STATE));
- internalFireEvents();
+ internal_fireEvents();
notifyAll();
}
return true;
@@ -761,13 +1059,13 @@
this.stateRequest= PROCESSING_STATE;
addStateEvent(DebugEvent.MODEL_SPECIFIC, STATE_REQUEST,
new StateDelta(oldState, PROCESSING_STATE) );
- internalFireEvents();
+ internal_fireEvents();
notifyAll();
}
return true;
}
- void internalStatusChanged(final ToolStatus newStatus) {
+ void internal_onStatusChanged(final ToolStatus newStatus) {
final byte oldState= this.state;
switch (newStatus) {
case STARTED_IDLING:
@@ -800,12 +1098,12 @@
}
}
- boolean internalIsPauseRequested() {
+ boolean internal_isPauseRequested() {
return (this.stateRequest == PAUSED_STATE);
}
- void dispose() {
+ void internal_dispose() {
checkIOCache();
final byte oldState= this.state;
@@ -815,57 +1113,62 @@
new StateDelta(oldState, TERMINATED_STATE) );
}
- if (!this.list.isEmpty()) {
- final ImList<ToolRunnable> finalRunnables= ImCollections.toList(this.list);
- for (final ToolRunnable runnable : finalRunnables) {
+ final ImList<ToolRunnable> finalRunnables;
+ { final ToolRunnable[] runnables= new @NonNull ToolRunnable[
+ internal_getCompleteSize() ];
+ int i= 0;
+ for (int iSection= this.sectionStack.size() - 1; iSection >= 1; iSection--) {
+ final SubQueue removedSection= this.sectionStack.remove(iSection);
+ i= removedSection.getAll(runnables, i);
+ removedSection.dispose();
+ }
+ { // iSection == 0
+ i= this.topLevelSection.getAll(runnables, i);
+ this.topLevelSection.dispose();
+ }
+ this.currentSection= this.topLevelSection;
+ this.currentSection.next= null;
+
+ finalRunnables= ImCollections.newList(runnables);
+ }
+ for (final ToolRunnable runnable : finalRunnables) {
+ runnable.changed(ToolRunnable.BEING_ABANDONED, this.process);
+ }
+ addTerminateEvent(new TaskDelta(ToolRunnable.BEING_ABANDONED, -1, finalRunnables));
+
+ if (!this.hotList.isEmpty()){
+ final ImList<ToolRunnable> leftRunnable= ImCollections.toList(this.hotList);
+ this.hotList.clear();
+
+ for (final ToolRunnable runnable : leftRunnable) {
runnable.changed(ToolRunnable.BEING_ABANDONED, this.process);
}
- addContentEvent(DebugEvent.TERMINATE, DebugEvent.UNSPECIFIED,
- new TaskDelta(ToolRunnable.BEING_ABANDONED, -1, finalRunnables) );
- this.list.clear();
- }
- if (!this.hotList.isEmpty()){
- final ToolRunnable[] array= this.hotList.toArray(new ToolRunnable[this.hotList.size()]);
- for (int i= 0; i < array.length; i++) {
- array[i].changed(ToolRunnable.BEING_ABANDONED, this.process);
- }
- this.hotList.clear();
}
if (!this.onIdleList.isEmpty()){
- final RankedItem[] array= this.onIdleList.toArray(new RankedItem[this.onIdleList.size()]);
- for (int i= 0; i < array.length; i++) {
- array[i].runnable.changed(ToolRunnable.BEING_ABANDONED, this.process);
- }
+ final ImList<RankedItem> leftRunnable= ImCollections.toList(this.onIdleList);
this.onIdleList.clear();
+
+ for (final RankedItem item : leftRunnable) {
+ item.runnable.changed(ToolRunnable.BEING_ABANDONED, this.process);
+ }
}
- internalFireEvents();
+ internal_fireEvents();
}
private void checkIOCache() {
if (this.singleIOCache != null) {
- if (this.insertIndex >= 0) {
- addContentEvent(DebugEvent.CHANGE, DebugEvent.CONTENT,
- new TaskDelta(ToolRunnable.ADDING_TO, this.insertIndex, this.singleIOCache) );
- this.list.add(this.insertIndex, this.singleIOCache.get(0));
- this.insertIndex++;
- }
- else {
- addContentEvent(DebugEvent.CHANGE, DebugEvent.CONTENT,
- new TaskDelta(ToolRunnable.ADDING_TO, -1, this.singleIOCache) );
- this.list.add(this.singleIOCache.get(0));
- }
+ final int idx= this.currentSection.getAppendIdx();
+ this.currentSection.append(this.singleIOCache.get(0));
+ addContentChangeEvent(new TaskDelta(ToolRunnable.ADDING_TO, idx, this.singleIOCache));
this.singleIOCache= null;
}
}
- private void addChangeEvent(final int deltaType, final ImList<ToolRunnable> deltaData) {
- addContentEvent(DebugEvent.CHANGE, DebugEvent.CONTENT, new TaskDelta(deltaType, -1, deltaData));
- }
- private void addContentEvent(final int code, final int detail, final TaskDelta delta) {
- final DebugEvent event= new DebugEvent(this, code, detail);
+ private void addContentChangeEvent(final TaskDelta delta) {
+ final DebugEvent event= new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT);
event.setData(delta);
this.eventList.add(event);
}
@@ -876,11 +1179,17 @@
this.eventList.add(event);
}
- List<DebugEvent> internalGetEventList() {
+ private void addTerminateEvent(final TaskDelta delta) {
+ final DebugEvent event= new DebugEvent(this, DebugEvent.TERMINATE, DebugEvent.UNSPECIFIED);
+ event.setData(delta);
+ this.eventList.add(event);
+ }
+
+ List<DebugEvent> internal_getEventList() {
return this.eventList;
}
- void internalFireEvents() {
+ void internal_fireEvents() {
if (this.eventList.isEmpty()) {
return;
}
diff --git a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolController.java b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolController.java
index 484a63d..6f53571 100644
--- a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolController.java
+++ b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolController.java
@@ -56,6 +56,7 @@
import org.eclipse.statet.internal.nico.core.RunnableProgressMonitor;
import org.eclipse.statet.nico.core.NicoCore;
import org.eclipse.statet.nico.core.NicoCoreMessages;
+import org.eclipse.statet.nico.core.runtime.Queue.Section;
/**
@@ -360,14 +361,13 @@
protected void submitToConsole(final String print, final String send,
final IProgressMonitor monitor) throws CoreException {
- final ToolRunnable savedCurrentRunnable= ToolController.this.currentRunnable;
- setCurrentRunnable(this);
+ ToolController.this.currentSubmitType= getSubmitTypeL(this);
try {
ToolController.this.fCurrentInput= print;
doBeforeSubmitL();
}
finally {
- setCurrentRunnable(savedCurrentRunnable);
+ ToolController.this.currentSubmitType= ToolController.this.currentRunnable.submitType;
}
if (send != null) {
ToolController.this.fCurrentInput= send;
@@ -409,6 +409,21 @@
}
+ protected static class RunnableData {
+
+ private final ToolRunnable runnable;
+ private final SubmitType submitType;
+ private final Section queueSection;
+
+ public RunnableData(final ToolRunnable runnable, final SubmitType submitType, final Section queueSection) {
+ this.runnable= runnable;
+ this.submitType= submitType;
+ this.queueSection= queueSection;
+ }
+
+ }
+
+
public static final String START_TYPE_ID= "common/start"; //$NON-NLS-1$
public static final String QUIT_TYPE_ID= "common/quit"; //$NON-NLS-1$
@@ -427,6 +442,10 @@
protected static final int SUSPENDED_TOPLEVEL= 0x1;
protected static final int SUSPENDED_DEEPLEVEL= 0x2;
+ private static final byte REGULAR= 0;
+ private static final byte HOT_REGULAR= 1;
+ private static final byte HOT_NESTED= 2;
+
private ToolStreamProxy streams;
@@ -435,7 +454,7 @@
private int counter= 0;
- private ToolRunnable currentRunnable;
+ private RunnableData currentRunnable;
private SubmitType currentSubmitType;
private final List<SystemRunnable> controllerRunnables= new ArrayList<>();
private SystemRunnable postControllerRunnable;
@@ -450,8 +469,8 @@
private volatile boolean isTerminated;
private boolean hotModeDeferred;
- private boolean hotMode;
private boolean hotModeNested= true;
+ private byte hotMode= REGULAR;
private final IProgressMonitor hotModeMonitor= new NullProgressMonitor();
private boolean isDebugEnabled;
@@ -468,7 +487,9 @@
private ToolWorkspace workspaceData;
- private volatile int changeStamp;
+ private volatile int currentStamp;
+ private int changeStamp;
+ private int hotStamp;
private final Map<String, ToolCommandHandler> actionHandlers= new HashMap<>();
@@ -481,9 +502,9 @@
private final CopyOnWriteIdentityListSet<Disposable> disposables= new CopyOnWriteIdentityListSet<>();
- protected ToolController(final ToolProcess process, final Map<String, Object> initData) {
+ protected ToolController(final ToolProcess process, final Map<String, Object> connectionInfo) {
this.process= process;
- this.process.fInitData= initData;
+ this.process.connectionInfo= connectionInfo;
this.streams= new ToolStreamProxy();
@@ -573,11 +594,6 @@
}
- protected Map<String, Object> getInitData() {
- return this.process.fInitData;
- }
-
-
/**
* Runs the tool.
*
@@ -587,15 +603,17 @@
public final void run() throws CoreException {
assert (this.status == ToolStatus.STARTING);
try {
+ final Section queueSection= this.queue.getTopLevelSection();
+
this.controllerThread= Thread.currentThread();
- setCurrentRunnable(createStartRunnable());
+ setCurrentRunnable(createRunnableData(createStartRunnable(), queueSection));
startToolL(this.runnableProgressMonitor);
- setCurrentRunnable(null);
+ setCurrentRunnable(new RunnableData(null, SubmitType.CONSOLE, queueSection));
synchronized (this.queue) {
loopChangeStatus((this.controllerRunnables.isEmpty()) ?
ToolStatus.STARTED_IDLING : ToolStatus.STARTED_PROCESSING, null);
}
- loop();
+ loopTopLevel(queueSection);
}
finally {
synchronized (this.queue) {
@@ -612,15 +630,12 @@
public final int getHotTasksState() {
synchronized (this.queue) {
- if (this.hotMode) {
- return (this.hotModeNested) ? 2 : 1;
- }
- return 0;
+ return this.hotMode;
}
}
protected final boolean isInHotModeL() {
- return this.hotMode;
+ return (this.hotMode != 0);
}
/**
@@ -657,7 +672,7 @@
/**
* Tries to apply "cancel".
*
- * The return value signalises if the command was applicable and/or
+ * The return value signals if the command was applicable and/or
* was succesful (depends on implementation).
*
* @return hint about success.
@@ -665,8 +680,8 @@
public final boolean cancelTask(final int options) {
synchronized (this.queue) {
if ((options & CANCEL_ALL) != 0) {
- final List<ToolRunnable> list= this.queue.internalGetList();
- this.queue.remove(list.toArray(new ToolRunnable[list.size()]));
+ final List<ToolRunnable> list= this.queue.internal_getCurrentList();
+ list.clear();
}
if ((options & CANCEL_PAUSE) != 0) {
this.queue.pause();
@@ -719,7 +734,7 @@
final ToolCommandHandler handler= this.actionHandlers.get(SCHEDULE_QUIT_EVENT_ID);
if (handler != null) {
final Map<String, Object> data= new HashMap<>();
- data.put("scheduledQuitTasks", getQuitTasks()); //$NON-NLS-1$
+ data.put("scheduledQuitRunnables", getQuitRunnables()); //$NON-NLS-1$
final IStatus status= executeHandler(SCHEDULE_QUIT_EVENT_ID, handler, data, new NullProgressMonitor());
if (status != null && !status.isOK()) {
schedule= false;
@@ -774,7 +789,7 @@
*/
public final void cancelQuit() {
synchronized(this.queue) {
- this.queue.remove(getQuitTasks());
+ this.queue.remove(getQuitRunnables());
if (this.status == ToolStatus.TERMINATED) {
return;
@@ -782,25 +797,29 @@
}
// cancel task should not be synch
- final ToolRunnable current= this.currentRunnable;
+ final ToolRunnable current= this.currentRunnable.runnable;
if (current != null && current.getTypeId() == QUIT_TYPE_ID) {
cancelTask(0);
}
}
- private final ToolRunnable[] getQuitTasks() {
- final List<ToolRunnable> quit= new ArrayList<>();
- final ToolRunnable current= this.currentRunnable;
- if (current != null && current.getTypeId() == QUIT_TYPE_ID) {
- quit.add(current);
+ private final List<ToolRunnable> getQuitRunnables() {
+ final ToolRunnable current;
+ final List<ToolRunnable> waiting;
+ synchronized (this.queue) {
+ current= this.currentRunnable.runnable;
+ waiting= this.queue.internal_getCurrentList();
}
- final List<ToolRunnable> list= this.queue.internalGetCurrentList();
- for (final ToolRunnable runnable : list) {
+ final List<ToolRunnable> quitRunnables= new ArrayList<>();
+ if (current != null && current.getTypeId() == QUIT_TYPE_ID) {
+ quitRunnables.add(current);
+ }
+ for (final ToolRunnable runnable : waiting) {
if (runnable.getTypeId() == QUIT_TYPE_ID) {
- quit.add(runnable);
+ quitRunnables.add(runnable);
}
}
- return quit.toArray(new ToolRunnable[quit.size()]);
+ return quitRunnables;
}
public final void kill(final IProgressMonitor monitor) throws CoreException {
@@ -845,7 +864,7 @@
if (newStatus == ToolStatus.STARTED_PROCESSING && this.loopCurrentLevel > 0) {
// for changed resume detail
final ImIdentityList<IToolStatusListener> listeners= this.toolStatusListeners.toList();
- final List<DebugEvent> eventList= this.queue.internalGetEventList();
+ final List<DebugEvent> eventList= this.queue.internal_getEventList();
for (final IToolStatusListener listener : listeners) {
if (listener instanceof IThread) {
listener.controllerStatusChanged(this.statusPrevious, newStatus, eventList);
@@ -862,16 +881,16 @@
}
if (newStatus == ToolStatus.STARTED_PROCESSING
&& (this.status != ToolStatus.STARTED_PAUSED || this.statusPrevious != ToolStatus.STARTED_PROCESSING)) {
- this.queue.internalResetIdle();
+ this.queue.internal_resetOnIdle();
}
- this.queue.internalStatusChanged(newStatus);
+ this.queue.internal_onStatusChanged(newStatus);
this.statusPrevious= this.status;
this.status= newStatus;
final ImIdentityList<IToolStatusListener> listeners= this.toolStatusListeners.toList();
- final List<DebugEvent> eventList= this.queue.internalGetEventList();
+ final List<DebugEvent> eventList= this.queue.internal_getEventList();
for (final IToolStatusListener listener : listeners) {
listener.controllerStatusChanged(this.statusPrevious, newStatus, eventList);
}
@@ -881,7 +900,7 @@
logEvents("loopChangeStatus", newStatus); //$NON-NLS-1$
}
- this.queue.internalFireEvents();
+ this.queue.internal_fireEvents();
}
// protected final void loopBusyChanged(final boolean isBusy) {
@@ -1009,7 +1028,7 @@
public abstract ToolRunnable createCommandRunnable(final String command, final SubmitType type);
- private final void loop() {
+ private final void loopTopLevel(final Section queueSection) {
if (this.hotModeDeferred) {
this.hotModeDeferred= false;
scheduleHotMode();
@@ -1022,11 +1041,11 @@
runSuspendedLoopL(SUSPENDED_TOPLEVEL);
}
else {
- loopRunTask();
+ loopRunTask(queueSection);
}
synchronized (this.queue) { // if interrupted run loop, all states are checked
- this.queue.internalCheck();
+ this.queue.internal_check();
if (this.internalTask > 0) {
try {
@@ -1047,7 +1066,7 @@
enterSuspended= true;
continue;
}
- if (this.queue.internalIsPauseRequested()) {
+ if (this.queue.internal_isPauseRequested()) {
loopChangeStatus(ToolStatus.STARTED_PAUSED, null);
try {
this.queue.wait();
@@ -1055,7 +1074,7 @@
catch (final InterruptedException e) {}
continue;
}
- if (this.queue.internalNext() < 0) {
+ if (this.queue.internal_next() < 0) {
loopChangeStatus(ToolStatus.STARTED_IDLING, null);
try {
this.queue.wait();
@@ -1067,7 +1086,7 @@
}
}
- private final void loopSuspended(final int level) {
+ private final void loopSuspended(final int level, final Section queueSection) {
boolean enterSuspended= false;
while (true) {
@@ -1076,11 +1095,11 @@
runSuspendedLoopL(SUSPENDED_TOPLEVEL);
}
else {
- loopRunTask();
+ loopRunTask(queueSection);
}
synchronized (this.queue) { // if interrupted run loop, all states are checked
- this.queue.internalCheck();
+ this.queue.internal_check();
if (this.internalTask > 0) {
try {
@@ -1102,7 +1121,7 @@
enterSuspended= true;
continue;
}
- if (this.queue.internalIsPauseRequested()) {
+ if (this.queue.internal_isPauseRequested()) {
loopChangeStatus(ToolStatus.STARTED_PAUSED, null);
try {
this.queue.wait();
@@ -1110,7 +1129,7 @@
catch (final InterruptedException e) {}
continue;
}
- if (this.queue.internalNext() < 0) {
+ if (this.queue.internal_next() < 0) {
loopChangeStatus(ToolStatus.STARTED_SUSPENDED, null);
try {
this.queue.wait();
@@ -1122,27 +1141,29 @@
}
}
- private final void loopRunTask() {
+ private final void loopRunTask(final Section queueSection) {
while (true) {
final int type;
- final ToolRunnable savedCurrentRunnable= this.currentRunnable;
+ final RunnableData savedCurrentRunnable= this.currentRunnable;
+ final ToolRunnable runnable;
synchronized (this.queue) {
if (this.controllerRunnables.size() > 0) {
type= Queue.RUN_CONTROL;
- setCurrentRunnable(this.controllerRunnables.remove(0));
+ runnable= this.controllerRunnables.remove(0);
}
else if (this.loopCurrentLevel != this.suspendedRequestLevel || this.isTerminated
- || this.internalTask > 0 || this.queue.internalIsPauseRequested()) {
+ || this.internalTask > 0 || this.queue.internal_isPauseRequested()) {
return;
}
else {
- type= this.queue.internalNext();
+ type= this.queue.internal_next();
switch (type) {
case Queue.RUN_HOT:
+ runnable= null;
break;
case Queue.RUN_OTHER:
case Queue.RUN_DEFAULT:
- setCurrentRunnable(this.queue.internalPoll());
+ runnable= this.queue.internal_poll();
break;
default:
return;
@@ -1151,49 +1172,50 @@
if (type != Queue.RUN_HOT) {
if (this.loopCurrentLevel > 0) {
if (type != Queue.RUN_CONTROL
- && (this.currentRunnable instanceof ConsoleCommandRunnable)
- && !runConsoleCommandInSuspend(((ConsoleCommandRunnable) this.currentRunnable).fText) ) {
+ && (runnable instanceof ConsoleCommandRunnable)
+ && !runConsoleCommandInSuspend(((ConsoleCommandRunnable) runnable).fText) ) {
try {
- this.queue.internalFinished(this.currentRunnable, ToolRunnable.FINISHING_CANCEL);
+ this.queue.internal_onFinished(runnable, ToolRunnable.FINISHING_CANCEL);
}
finally {
setCurrentRunnable(savedCurrentRunnable);
}
return;
}
- if (this.currentRunnable instanceof ToolController.SuspendResumeRunnable) {
- this.suspendExitDetail= ((ToolController.SuspendResumeRunnable) this.currentRunnable).detail;
+ if (runnable instanceof ToolController.SuspendResumeRunnable) {
+ this.suspendExitDetail= ((ToolController.SuspendResumeRunnable) runnable).detail;
}
else {
- final int detail= getDebugResumeDetailL(this.currentRunnable);
+ final int detail= getDebugResumeDetailL(runnable);
if (this.status == ToolStatus.STARTED_SUSPENDED
|| getDebugResumeDetailPriority(detail) >= getDebugResumeDetailPriority(this.suspendExitDetail)) {
this.suspendExitDetail= detail;
}
}
}
+ setCurrentRunnable(createRunnableData(runnable, queueSection));
loopChangeStatus(ToolStatus.STARTED_PROCESSING,
- new RunnableProgressMonitor(this.currentRunnable));
+ new RunnableProgressMonitor(runnable));
}
}
switch (type) {
case Queue.RUN_CONTROL:
try {
- this.currentRunnable.run(this, this.runnableProgressMonitor);
- safeRunnableChanged(this.currentRunnable, ToolRunnable.FINISHING_OK);
+ runnable.run(this, this.runnableProgressMonitor);
+ safeRunnableChanged(runnable, ToolRunnable.FINISHING_OK);
continue;
}
catch (final Throwable e) {
final IStatus status= (e instanceof CoreException) ? ((CoreException) e).getStatus() : null;
if (status != null && (status.getSeverity() == IStatus.CANCEL || status.getSeverity() <= IStatus.INFO)) {
- safeRunnableChanged(this.currentRunnable, ToolRunnable.FINISHING_CANCEL);
+ safeRunnableChanged(runnable, ToolRunnable.FINISHING_CANCEL);
// ignore
}
else {
NicoCorePlugin.logError(-1, NLS.bind(
"An Error occurred when running internal controller task ''{0}''.", //$NON-NLS-1$
- this.currentRunnable.getLabel() ), e);
- safeRunnableChanged(this.currentRunnable, ToolRunnable.FINISHING_ERROR);
+ runnable.getLabel() ), e);
+ safeRunnableChanged(runnable, ToolRunnable.FINISHING_ERROR);
}
if (!isToolAlive()) {
@@ -1203,7 +1225,6 @@
}
finally {
setCurrentRunnable(savedCurrentRunnable);
- this.currentSubmitType= null;
this.runnableProgressMonitor.done();
}
case Queue.RUN_HOT:
@@ -1223,7 +1244,7 @@
case Queue.RUN_DEFAULT:
try {
this.counter++;
- this.currentRunnable.run(this, this.runnableProgressMonitor);
+ runnable.run(this, this.runnableProgressMonitor);
onTaskFinished(this.currentRunnable, ToolRunnable.FINISHING_OK,
this.runnableProgressMonitor );
continue;
@@ -1241,7 +1262,7 @@
status= new Status(IStatus.ERROR, NicoCore.BUNDLE_ID, NicoCorePlugin.EXTERNAL_ERROR,
NLS.bind(Messages.ToolRunnable_error_RuntimeError_message,
this.process.getLabel(Tool.LONG_LABEL),
- this.currentRunnable.getLabel() ),
+ runnable.getLabel() ),
e);
if (type == Queue.RUN_DEFAULT) {
handleStatus(status, this.runnableProgressMonitor);
@@ -1271,10 +1292,10 @@
}
/** Only called for regular tasks */
- protected void onTaskFinished(final ToolRunnable runnable, final int event,
+ protected void onTaskFinished(final RunnableData runnableData, final int event,
final IProgressMonitor monitor) {
- this.queue.internalFinished(runnable, event);
- safeRunnableChanged(runnable, event);
+ this.queue.internal_onFinished(runnableData.runnable, event);
+ safeRunnableChanged(runnableData.runnable, event);
}
private void safeRunnableChanged(final ToolRunnable runnable, final int event) {
@@ -1317,7 +1338,7 @@
private final ToolRunnable pollHotRunnable() {
ToolRunnable runnable= null;
if (!this.isTerminated) {
- runnable= this.queue.internalPollHot();
+ runnable= this.queue.internal_pollHot();
if (runnable == null && !this.hotModeNested) {
try {
this.queue.wait(100);
@@ -1325,7 +1346,7 @@
catch (final InterruptedException e) {
}
if (!this.isTerminated) {
- runnable= this.queue.internalPollHot();
+ runnable= this.queue.internal_pollHot();
}
}
}
@@ -1333,21 +1354,20 @@
}
protected final void runHotModeLoop() {
- final SubmitType savedSubmitType= this.currentSubmitType;
while (true) {
final ToolRunnable runnable;
synchronized (this.queue) {
runnable= pollHotRunnable();
if (runnable == null) {
- if (this.hotMode) {
+ if (this.hotMode != 0) {
onHotModeExit(this.hotModeMonitor);
- this.hotMode= false;
- this.currentSubmitType= savedSubmitType;
+ this.hotMode= 0;
+ this.currentSubmitType= this.currentRunnable.submitType;
}
return;
}
- if (!this.hotMode) {
- this.hotMode= true;
+ if (this.hotMode == 0) {
+ this.hotMode= (this.hotModeNested) ? HOT_NESTED : HOT_REGULAR;
this.currentSubmitType= SubmitType.OTHER;
onHotModeEnter(this.hotModeMonitor);
}
@@ -1377,9 +1397,13 @@
}
protected void onHotModeEnter(final IProgressMonitor monitor) {
+ if (this.hotMode > HOT_REGULAR) {
+ enableHotStamp();
+ }
}
protected void onHotModeExit(final IProgressMonitor monitor) {
+ disableHotStamp();
}
@@ -1463,10 +1487,10 @@
}
protected void runSuspendedLoopL(final int o) {
- ToolRunnable insertMarker= null;
+ Queue.Section queueSection= null;
SystemRunnable updater= null;
- final ToolRunnable savedCurrentRunnable= this.currentRunnable;
+ final RunnableData savedCurrentRunnable= this.currentRunnable;
final RunnableProgressMonitor savedProgressMonitor= this.runnableProgressMonitor;
final ToolStatus savedStatus= this.status;
@@ -1481,11 +1505,11 @@
setSuspended(this.suspendedRequestLevel, 0, null);
return;
}
- if (this.loopCurrentLevel != thisLevel || insertMarker == null) {
+ if (this.loopCurrentLevel != thisLevel || queueSection == null) {
this.loopCurrentLevel= this.suspendedRunLevel= thisLevel;
- insertMarker= new SuspendedInsertRunnable(thisLevel);
- this.queue.internalAddInsert(insertMarker);
+ queueSection= this.queue.internal_addInsert(
+ new SuspendedInsertRunnable(thisLevel) );
if (savedLevel == 0 && updater == null) {
updater= new SuspendedUpdateRunnable();
this.queue.addOnIdle(updater, 6000);
@@ -1495,7 +1519,7 @@
}
// run suspended loop
- doRunSuspendedLoopL(o, thisLevel);
+ doRunSuspendedLoopL(o, thisLevel, queueSection);
// resume main runnable
final SuspendResumeRunnable runnable;
@@ -1508,8 +1532,8 @@
this.loopCurrentLevel= savedLevel;
this.suspendEnterDetail= DebugEvent.UNSPECIFIED;
- this.queue.internalRemoveInsert(insertMarker);
- insertMarker= null;
+ this.queue.internal_removeInsert(queueSection);
+ queueSection= null;
if (thisLevel <= this.suspendedRequestLevel) {
continue;
@@ -1525,7 +1549,8 @@
if (runnable != null) { // resume with runnable
try {
setCurrentRunnable((savedCurrentRunnable != null) ?
- savedCurrentRunnable : runnable);
+ savedCurrentRunnable :
+ createRunnableData(runnable, this.queue.getCurrentSection()) );
if (runnable.canExec(savedProgressMonitor)) { // exec resume
synchronized (this.queue) {
this.suspendExitDetail= runnable.detail;
@@ -1570,8 +1595,8 @@
if (updater != null) {
this.queue.removeOnIdle(updater);
}
- if (insertMarker != null) {
- this.queue.internalRemoveInsert(insertMarker);
+ if (queueSection != null) {
+ this.queue.internal_removeInsert(queueSection);
}
this.suspendExitRunnable= null;
@@ -1580,8 +1605,8 @@
}
}
- protected void doRunSuspendedLoopL(final int o, final int level) {
- loopSuspended(level);
+ protected void doRunSuspendedLoopL(final int o, final int level, final Section queueSection) {
+ loopSuspended(level, queueSection);
}
protected int getCurrentLevelL() {
@@ -1679,7 +1704,9 @@
disposable.dispose();
}
catch (final Exception e) {
- NicoCorePlugin.log(new Status(IStatus.ERROR, NicoCore.BUNDLE_ID, -1, "An unexepected exception is thrown when disposing a controller extension.", e));
+ NicoCorePlugin.log(new Status(IStatus.ERROR, NicoCore.BUNDLE_ID, -1,
+ "An unexepected exception is thrown when disposing a controller extension.",
+ e ));
}
}
}
@@ -1709,7 +1736,8 @@
}
catch (final Exception e) {
NicoCorePlugin.log(new Status(IStatus.ERROR, NicoCore.BUNDLE_ID,
- NLS.bind("An error occurred when executing tool command ''{0}''.", commandID)));
+ NLS.bind("An error occurred when executing tool command ''{0}''.", commandID),
+ e ));
return null;
}
}
@@ -1729,9 +1757,13 @@
}
- private void setCurrentRunnable(final ToolRunnable runnable) {
+ private RunnableData createRunnableData(final ToolRunnable runnable, final Section queueSection) {
+ return new RunnableData(runnable, getSubmitTypeL(runnable), queueSection);
+ }
+
+ private void setCurrentRunnable(final RunnableData runnable) {
this.currentRunnable= runnable;
- this.currentSubmitType= getSubmitTypeL(runnable);
+ this.currentSubmitType= runnable.submitType;
}
protected SubmitType getSubmitTypeL(final ToolRunnable runnable) {
@@ -1748,7 +1780,11 @@
@Override
public ToolRunnable getCurrentRunnable() {
- return this.currentRunnable;
+ return this.currentRunnable.runnable;
+ }
+
+ public Queue.Section getCurrentQueueSection() {
+ return this.currentRunnable.queueSection;
}
public SubmitType getCurrentSubmitType() {
@@ -1808,8 +1844,24 @@
}
+ public final int getChangeStamp() {
+ return this.currentStamp;
+ }
+
+ private void touchChangeStamp() {
+ this.currentStamp= this.changeStamp= ((this.changeStamp + 1) & ~(1 << 31));
+ }
+
+ private void enableHotStamp() {
+ this.currentStamp= this.hotStamp= ((this.hotStamp + 1) | (1 << 31));
+ }
+
+ private void disableHotStamp() {
+ this.currentStamp= this.changeStamp;
+ }
+
public void briefAboutToChange() {
- this.changeStamp++;
+ touchChangeStamp();
}
public void briefChanged(final int flags) {
@@ -1817,23 +1869,19 @@
}
public void briefChanged(final Object obj, final int flags) {
- this.changeStamp++;
+ touchChangeStamp();
this.workspaceData.controlBriefChanged(obj, flags);
if (DEBUG_LOG_STATE) {
logChanged();
}
}
- public final int getChangeStamp() {
- return this.changeStamp;
- }
-
private void logEvents(final String label, final ToolStatus status) {
final ToStringBuilder sb= new ObjectUtils.ToStringBuilder(label);
sb.addProp("status", this.status); //$NON-NLS-1$
sb.addProp("changeStamp", this.changeStamp); //$NON-NLS-1$
- sb.addProp("events", this.queue.internalGetEventList()); //$NON-NLS-1$
+ sb.addProp("events", this.queue.internal_getEventList()); //$NON-NLS-1$
NicoCorePlugin.log(new Status(IStatus.INFO, NicoCore.BUNDLE_ID, sb.toString()));
}
diff --git a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolProcess.java b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolProcess.java
index 9bb13b3..89797f8 100644
--- a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolProcess.java
+++ b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolProcess.java
@@ -63,7 +63,7 @@
private final long fConnectionTimestamp;
private long fStartupTimestamp;
private String fStartupWD;
- Map<String, Object> fInitData;
+ Map<String, Object> connectionInfo;
private ToolController fController;
private final Queue fQueue;
@@ -341,6 +341,10 @@
doDispose();
}
+ public Map<String, Object> getConnectionInfo() {
+ return this.connectionInfo;
+ }
+
public void prepareRestart(final Map<String, Object> data) {
if (fStatus != ToolStatus.TERMINATED) {
throw new IllegalStateException();
@@ -351,7 +355,7 @@
data.put("process", this);
data.put("processDispose", poseponeDispose());
data.put("address", fAddress);
- data.put("initData", fInitData);
+ data.put("connectionInfo", this.connectionInfo);
}
public void restartCompleted(final Map<String, Object> data) {
@@ -398,7 +402,9 @@
protected void doDispose() {
if (fQueue != null) {
- fQueue.dispose();
+ synchronized (fQueue) {
+ fQueue.internal_dispose();
+ }
}
if (fHistory != null) {
fHistory.dispose();
diff --git a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolStreamProxy.java b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolStreamProxy.java
index 0650fbb..06a8426 100644
--- a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolStreamProxy.java
+++ b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolStreamProxy.java
@@ -18,18 +18,21 @@
import org.eclipse.debug.core.model.IStreamsProxy;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
/**
* None buffered streams
*/
+@NonNullByDefault
public class ToolStreamProxy implements IStreamsProxy {
- private final ToolStreamMonitor inputMonitor = new ToolStreamMonitor();
- private final ToolStreamMonitor infoMonitor = new ToolStreamMonitor();
- private final ToolStreamMonitor standardOutputMonitor = new ToolStreamMonitor();
- private final ToolStreamMonitor standardErrorMonitor = new ToolStreamMonitor();
- private final ToolStreamMonitor systemOutputMonitor = new ToolStreamMonitor();
+ private final ToolStreamMonitor inputMonitor= new ToolStreamMonitor();
+ private final ToolStreamMonitor infoMonitor= new ToolStreamMonitor();
+ private final ToolStreamMonitor standardOutputMonitor= new ToolStreamMonitor();
+ private final ToolStreamMonitor standardErrorMonitor= new ToolStreamMonitor();
+ private final ToolStreamMonitor systemOutputMonitor= new ToolStreamMonitor();
public ToolStreamProxy() {
@@ -65,11 +68,11 @@
public void dispose() {
- inputMonitor.dispose();
- infoMonitor.dispose();
- standardOutputMonitor.dispose();
- standardErrorMonitor.dispose();
- systemOutputMonitor.dispose();
+ this.inputMonitor.dispose();
+ this.infoMonitor.dispose();
+ this.standardOutputMonitor.dispose();
+ this.standardErrorMonitor.dispose();
+ this.systemOutputMonitor.dispose();
}
}
diff --git a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolWorkspace.java b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolWorkspace.java
index 2950ae2..69a0fec 100644
--- a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolWorkspace.java
+++ b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/runtime/ToolWorkspace.java
@@ -228,7 +228,7 @@
final ToolStatus status= this.process.getToolStatus();
if (status != ToolStatus.TERMINATED) {
if (enable && status.isWaiting()) {
- this.process.getQueue().internalResetIdle();
+ this.process.getQueue().internal_resetOnIdle();
this.process.getQueue().notifyAll();
}
addPropertyChanged("AutoRefresh.enabled", enable);
diff --git a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/util/IToolProvider.java b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/util/IToolProvider.java
deleted file mode 100644
index e273eb3..0000000
--- a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/util/IToolProvider.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*=============================================================================#
- # Copyright (c) 2006, 2018 Stephan Wahlbrink and others.
- #
- # This program and the accompanying materials are made available under the
- # terms of the Eclipse Public License 2.0 which is available at
- # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
- # which is available at https://www.apache.org/licenses/LICENSE-2.0.
- #
- # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
- #
- # Contributors:
- # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
- #=============================================================================*/
-
-package org.eclipse.statet.nico.core.util;
-
-import org.eclipse.statet.nico.core.runtime.ToolProcess;
-
-
-/**
- * Provides access to a selected (the active) tool instance.
- * Counterpart of {@link IToolRetargetable}.
- */
-public interface IToolProvider {
-
-
- public ToolProcess getTool();
-
- public void addToolRetargetable(IToolRetargetable action);
-
- public void removeToolRetargetable(IToolRetargetable action);
-
-}
diff --git a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/util/IToolRetargetable.java b/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/util/IToolRetargetable.java
deleted file mode 100644
index 1a7cff6..0000000
--- a/r/org.eclipse.statet.nico.core/src/org/eclipse/statet/nico/core/util/IToolRetargetable.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*=============================================================================#
- # Copyright (c) 2006, 2018 Stephan Wahlbrink and others.
- #
- # This program and the accompanying materials are made available under the
- # terms of the Eclipse Public License 2.0 which is available at
- # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
- # which is available at https://www.apache.org/licenses/LICENSE-2.0.
- #
- # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
- #
- # Contributors:
- # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
- #=============================================================================*/
-
-package org.eclipse.statet.nico.core.util;
-
-import org.eclipse.statet.nico.core.runtime.ToolProcess;
-
-
-/**
- * Objects accepts tool instances. Can be connected to a {@link IToolProvider}.
- */
-public interface IToolRetargetable {
-
- /**
- * Is called when the tool changed
- *
- * @param tool the new tool
- */
- void setTool(ToolProcess tool);
-
- /**
- * Is called when the set tool is terminated
- */
- void toolTerminated();
-
-}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/LocalTaskTransfer.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/LocalTaskTransfer.java
index e762d8e..4b32d0c 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/LocalTaskTransfer.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/LocalTaskTransfer.java
@@ -21,6 +21,10 @@
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.ui.statushandlers.StatusManager;
+import org.eclipse.statet.jcommons.collections.ImList;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
import org.eclipse.statet.ecommons.ts.core.ToolRunnable;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
@@ -30,16 +34,17 @@
/**
* Transfer type for {@link ToolRunnable}
*/
+@NonNullByDefault
public final class LocalTaskTransfer extends ByteArrayTransfer {
// First attempt to create a UUID for the type name to make sure that
// different Eclipse applications use different "types" of
// <code>LocalTaskTransfer</code>
- private static final String TYPE_NAME = "org.eclipse.statet.nico-task-transfer-format" + (new Long(System.currentTimeMillis())).toString(); //$NON-NLS-1$;
+ private static final String TYPE_NAME= "org.eclipse.statet.nico-task-transfer-format" + (new Long(System.currentTimeMillis())).toString(); //$NON-NLS-1$;
- private static final int TYPEID = registerType(TYPE_NAME);
+ private static final int TYPEID= registerType(TYPE_NAME);
- private static final LocalTaskTransfer INSTANCE = new LocalTaskTransfer();
+ private static final LocalTaskTransfer INSTANCE= new LocalTaskTransfer();
/**
@@ -48,10 +53,10 @@
public static class Data {
public final ToolProcess process;
- public ToolRunnable[] runnables;
+ public @Nullable ImList<ToolRunnable> runnables;
private Data(final ToolProcess process) {
- this.process = process;
+ this.process= process;
}
}
@@ -66,12 +71,12 @@
}
- private ToolProcess fProcess;
- private Data fData;
+ private @Nullable ToolProcess process;
+ private @Nullable Data data;
/**
- * Only the singleton instance of this class may be used.
+ * Only the singleton instance of this class may be used.
*/
protected LocalTaskTransfer() {
// do nothing
@@ -119,10 +124,8 @@
*/
@Override
public void javaToNative(final Object object, final TransferData transferData) {
- if (object instanceof Data) {
- fData = (Data) object;
- }
- final byte[] check = TYPE_NAME.getBytes();
+ this.data= (Data) object;
+ final byte[] check= TYPE_NAME.getBytes();
super.javaToNative(check, transferData);
}
@@ -133,13 +136,13 @@
* @see org.eclipse.swt.dnd.ByteArrayTransfer#nativeToJava(TransferData)
*/
@Override
- public Object nativeToJava(final TransferData transferData) {
- final Object result = super.nativeToJava(transferData);
+ public @Nullable Object nativeToJava(final TransferData transferData) {
+ final Object result= super.nativeToJava(transferData);
if (isInvalidNativeType(result)) {
StatusManager.getManager().handle(new Status(IStatus.ERROR, NicoUI.BUNDLE_ID, 0,
"invalid transfer type", null)); //$NON-NLS-1$
}
- return fData;
+ return this.data;
}
@@ -149,7 +152,7 @@
* @param process
*/
public void init(final ToolProcess process) {
- fProcess = process;
+ this.process= process;
}
/**
@@ -158,9 +161,9 @@
*
* @return new data object or <code>null</code> if no current dnd
*/
- public Data createData() {
- if (fProcess != null) {
- return new Data(fProcess);
+ public @Nullable Data createData() {
+ if (this.process != null) {
+ return new Data(this.process);
}
return null;
}
@@ -170,8 +173,8 @@
* (usually in {@link DragSourceListener#dragFinished(org.eclipse.swt.dnd.DragSourceEvent)})
*/
public void finished() {
- fProcess = null;
- fData = null;
+ this.process= null;
+ this.data= null;
}
/**
@@ -179,9 +182,9 @@
* so the drop adapter can check the type
* @return main type or <code>null</code> if no current dnd
*/
- public String getMainType() {
- if (fProcess != null) {
- return fProcess.getMainType();
+ public @Nullable String getMainType() {
+ if (this.process != null) {
+ return this.process.getMainType();
}
return null;
}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/DisconnectEngineHandler.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/DisconnectEngineHandler.java
index 862257f..327939d 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/DisconnectEngineHandler.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/DisconnectEngineHandler.java
@@ -14,6 +14,8 @@
package org.eclipse.statet.internal.nico.ui.actions;
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
+
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -24,16 +26,22 @@
import org.eclipse.ui.services.IServiceLocator;
import org.eclipse.ui.statushandlers.StatusManager;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
+import org.eclipse.statet.ecommons.ui.workbench.WorkbenchUIUtils;
+
import org.eclipse.statet.nico.core.runtime.IRemoteEngineController;
import org.eclipse.statet.nico.core.runtime.ToolController;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
import org.eclipse.statet.nico.ui.NicoUI;
import org.eclipse.statet.nico.ui.NicoUITools;
-import org.eclipse.statet.nico.ui.actions.ToolRetargetableHandler;
+import org.eclipse.statet.nico.ui.actions.AbstractToolHandler;
-public class DisconnectEngineHandler extends ToolRetargetableHandler {
+@NonNullByDefault
+public class DisconnectEngineHandler extends AbstractToolHandler<ToolProcess> {
private static class DisconnectJob extends Job {
@@ -43,7 +51,7 @@
}
- private final ToolController fController;
+ private final ToolController controller;
DisconnectJob(final ToolProcess process, final ToolController controller) {
@@ -52,13 +60,13 @@
setUser(true);
setPriority(INTERACTIVE);
- fController = controller;
+ this.controller= controller;
}
@Override
protected IStatus run(final IProgressMonitor monitor) {
try {
- ((IRemoteEngineController) fController).disconnect(monitor);
+ ((IRemoteEngineController) this.controller).disconnect(monitor);
return Status.OK_STATUS;
}
catch (final CoreException e) {
@@ -72,36 +80,31 @@
}
- public DisconnectEngineHandler(final IToolProvider toolProvider, final IServiceLocator serviceLocator) {
- super(toolProvider, serviceLocator);
+ public DisconnectEngineHandler(final ToolProvider toolProvider, final IServiceLocator serviceLocator) {
+ super(null, IRemoteEngineController.FEATURE_SET_ID,
+ toolProvider, serviceLocator );
init();
}
@Override
- protected boolean evaluateEnabled() {
- final ToolProcess tool = getTool();
- return ((tool != null)
- && tool.isProvidingFeatureSet(IRemoteEngineController.FEATURE_SET_ID)
- && !tool.isTerminated() );
- }
-
- @Override
- protected Object doExecute(final ExecutionEvent event) {
- final ToolProcess tool = getCheckedTool();
+ protected @Nullable Object execute(final ToolProcess tool, final ExecutionEvent event) {
final ToolController controller;
try {
- controller = NicoUITools.accessController(null, tool);
+ controller= NicoUITools.accessController(null, tool);
}
catch (final CoreException e) {
StatusManager.getManager().handle(e.getStatus(), StatusManager.SHOW | StatusManager.LOG);
return null;
}
- final IProgressService progressService = getProgressService();
- final Job job = new DisconnectJob(tool, controller);
+ final IServiceLocator serviceLocator= getServiceLocator(event.getApplicationContext());
+ final IProgressService progressService= nonNullAssert(
+ serviceLocator.getService(IProgressService.class) );
+ final Job job= new DisconnectJob(tool, controller);
job.schedule();
- progressService.showInDialog(getShell(), job);
+ progressService.showInDialog(WorkbenchUIUtils.getShell(event.getApplicationContext()), job);
+
return null;
}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/PauseHandler.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/PauseHandler.java
index 2cf0933..a4b94e4 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/PauseHandler.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/PauseHandler.java
@@ -24,29 +24,32 @@
import org.eclipse.ui.menus.UIElement;
import org.eclipse.ui.services.IServiceLocator;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
+import org.eclipse.statet.ecommons.ui.util.UIAccess;
import org.eclipse.statet.ecommons.ui.workbench.WorkbenchUIUtils;
import org.eclipse.statet.nico.core.runtime.Queue;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
import org.eclipse.statet.nico.ui.NicoUI;
-import org.eclipse.statet.nico.ui.actions.ToolRetargetableHandler;
+import org.eclipse.statet.nico.ui.actions.AbstractToolHandler;
/**
* Handler to toggle pause state of engine
*/
-public class PauseHandler extends ToolRetargetableHandler implements IElementUpdater,
+@NonNullByDefault
+public class PauseHandler extends AbstractToolHandler<ToolProcess> implements IElementUpdater,
IDebugEventSetListener {
- private boolean fIsChecked;
-
- private final ElementUpdater fUpdater = new ElementUpdater(NicoUI.PAUSE_COMMAND_ID);
+ private boolean isChecked;
- public PauseHandler(final IToolProvider toolProvider, final IServiceLocator serviceLocator) {
- super(toolProvider, serviceLocator);
+ public PauseHandler(final ToolProvider toolProvider, final IServiceLocator serviceLocator) {
+ super(null, null, toolProvider, serviceLocator);
init();
}
@@ -67,118 +70,99 @@
}
- @Override
- protected void doRefresh() {
- if (getState() == S_ONAIR) {
- fUpdater.schedule();
+ private void setChecked(final boolean isChecked) {
+ if (isChecked != this.isChecked) {
+ this.isChecked= isChecked;
+ refreshUI();
}
}
@Override
+ public void setEnabled(@Nullable Object evaluationContext) {
+ super.setEnabled(evaluationContext);
+
+ final ToolProcess enabledTool= getActiveTool();
+ setChecked((enabledTool != null) ?
+ enabledTool.getQueue().isRequested(Queue.PAUSED_STATE) :
+ false );
+ }
+
+ protected void refreshUI() {
+ WorkbenchUIUtils.refreshCommandElements(NicoUI.PAUSE_COMMAND_ID, this, null);
+ }
+
+ @Override
public void updateElement(final UIElement element, final Map parameters) {
WorkbenchUIUtils.aboutToUpdateCommandsElements(this, element);
try {
- element.setChecked(fIsChecked);
+ element.setChecked(this.isChecked);
}
finally {
WorkbenchUIUtils.finalizeUpdateCommandsElements(this);
}
}
- @Override
- public boolean handleToolChanged() {
- final ToolProcess tool = getTool();
- final boolean wasChecked = fIsChecked;
- fIsChecked = (tool != null) ?
- tool.getQueue().isRequested(Queue.PAUSED_STATE) :
- false;
-
- setBaseEnabled(evaluateEnabled());
- return (wasChecked != fIsChecked);
- }
@Override
public void handleDebugEvents(final DebugEvent[] events) {
- if (getState() != S_ONAIR) {
- return;
- }
- boolean update = false;
- final ToolProcess tool = getTool();
+ final ToolProcess tool= getActiveTool();
if (tool == null) {
return;
}
ITER_EVENTS: for (final DebugEvent event : events) {
if (event.getSource() == tool) {
if (event.getKind() == DebugEvent.TERMINATE) {
- synchronized (this) {
- if (getTool() != tool) {
- return;
- }
- setBaseEnabled(false);
- }
- break;
+ update(tool);
}
continue ITER_EVENTS;
}
if (event.getSource() == tool.getQueue()) {
- Boolean checked= null;
if (Queue.isStateRequest(event)) {
final Queue.StateDelta delta= (Queue.StateDelta) event.getData();
if (delta.newState == Queue.PAUSED_STATE) {
- checked= Boolean.TRUE;
+ updateChecked(tool, true);
}
else {
- checked= Boolean.FALSE;
+ updateChecked(tool, false);
}
}
else if (Queue.isStateChange(event)) {
final Queue.StateDelta delta= (Queue.StateDelta) event.getData();
if (delta.newState == Queue.PAUSED_STATE) {
- checked= Boolean.TRUE;
- }
- }
- if (checked != null) {
- synchronized (this) {
- if (getState() != S_ONAIR || getTool() != tool) {
- return;
- }
- final boolean wasChecked = fIsChecked;
- fIsChecked = checked;
-
- update = (wasChecked != fIsChecked);
+ updateChecked(tool, true);
}
}
continue ITER_EVENTS;
}
}
-
- if (update) {
- doRefresh();
- }
}
+ private void update(final ToolProcess tool) {
+ UIAccess.getDisplay().asyncExec(() -> {
+ if (getState() != S_INITIALIZED || getActiveTool() != tool) {
+ return;
+ }
+ setEnabled(null);
+ });
+ }
+
+ private void updateChecked(final ToolProcess tool, final boolean isChecked) {
+ UIAccess.getDisplay().asyncExec(() -> {
+ if (getState() != S_INITIALIZED || getActiveTool() != tool) {
+ return;
+ }
+ setChecked(isChecked);
+ });
+ }
+
+
@Override
- protected Object doExecute(final ExecutionEvent event) {
- boolean update = false;
- synchronized (this) {
- final ToolProcess tool = getCheckedTool();
- final boolean wasChecked= fIsChecked;
- if (tool != null) {
- final boolean success= (!wasChecked) ?
- tool.getQueue().pause() : tool.getQueue().resume();
- if (success) {
- fIsChecked= !wasChecked;
- }
- }
- else {
- fIsChecked= false;
- }
- update = (wasChecked != fIsChecked);
- }
+ protected @Nullable Object execute(final ToolProcess tool, final ExecutionEvent event) {
+ final boolean wasChecked= this.isChecked;
+ final boolean success= (!wasChecked) ?
+ tool.getQueue().pause() : tool.getQueue().resume();
+ setChecked((success) ? !wasChecked : false);
- if (update) {
- doRefresh();
- }
return null;
}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/ReconnectEngineHandler.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/ReconnectEngineHandler.java
index dcef072..471d94e 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/ReconnectEngineHandler.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/internal/nico/ui/actions/ReconnectEngineHandler.java
@@ -14,6 +14,8 @@
package org.eclipse.statet.internal.nico.ui.actions;
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
+
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
@@ -31,31 +33,33 @@
import org.eclipse.ui.services.IServiceLocator;
import org.eclipse.ui.statushandlers.StatusManager;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
import org.eclipse.statet.ecommons.debug.core.util.OverlayLaunchConfiguration;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
import org.eclipse.statet.nico.core.runtime.IRemoteEngineController;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
import org.eclipse.statet.nico.ui.NicoUI;
-import org.eclipse.statet.nico.ui.actions.ToolRetargetableHandler;
+import org.eclipse.statet.nico.ui.actions.AbstractToolHandler;
-public class ReconnectEngineHandler extends ToolRetargetableHandler {
+@NonNullByDefault
+public class ReconnectEngineHandler extends AbstractToolHandler<ToolProcess> {
- public ReconnectEngineHandler(final IToolProvider toolProvider, final IServiceLocator serviceLocator) {
- super(toolProvider, serviceLocator);
+ public ReconnectEngineHandler(final ToolProvider toolProvider, final IServiceLocator serviceLocator) {
+ super(null, IRemoteEngineController.FEATURE_SET_ID,
+ toolProvider, serviceLocator );
init();
}
@Override
- protected boolean evaluateEnabled() {
- final ToolProcess tool = getTool();
+ protected boolean evaluateIsEnabled(final ToolProcess tool, final @Nullable Object evaluationContext) {
try {
- return ((tool != null)
- && tool.isProvidingFeatureSet(IRemoteEngineController.FEATURE_SET_ID)
- && tool.isTerminated()
+ return (tool.isTerminated()
&& (tool.getExitValue() == ToolProcess.EXITCODE_DISCONNECTED) );
}
catch (final DebugException e) {
@@ -63,17 +67,20 @@
}
}
+
@Override
- protected Object doExecute(final ExecutionEvent event) {
- final ToolProcess tool = getCheckedTool();
-
- final IProgressService progressService = getProgressService();
+ protected @Nullable Object execute(final ToolProcess tool, final ExecutionEvent event) {
+ final IServiceLocator serviceLocator= getServiceLocator(event.getApplicationContext());
+ final IProgressService progressService= nonNullAssert(
+ serviceLocator.getService(IProgressService.class) );
try {
progressService.busyCursorWhile(createRunnable(tool));
}
catch (final InvocationTargetException e) {
StatusManager.getManager().handle(new Status(IStatus.ERROR, NicoUI.BUNDLE_ID, -1,
- "Reconnecting failed.", e.getCause()), StatusManager.SHOW | StatusManager.LOG);
+ "Reconnecting failed.",
+ e.getCause() ),
+ StatusManager.SHOW | StatusManager.LOG );
}
catch (final InterruptedException e) {
}
@@ -84,10 +91,10 @@
return new IRunnableWithProgress() {
@Override
public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
- final ILaunch originallaunch = process.getLaunch();
- ILaunchConfiguration originalConfig = originallaunch.getLaunchConfiguration();
+ final ILaunch originallaunch= process.getLaunch();
+ ILaunchConfiguration originalConfig= originallaunch.getLaunchConfiguration();
if (originalConfig instanceof OverlayLaunchConfiguration) {
- originalConfig = ((OverlayLaunchConfiguration) originalConfig).getOriginal();
+ originalConfig= ((OverlayLaunchConfiguration) originalConfig).getOriginal();
}
final Map<String, Object> reconnect= new HashMap<>();
@@ -95,13 +102,14 @@
final Map<String, Object> add= new HashMap<>();
add.put(IRemoteEngineController.LAUNCH_RECONNECT_ATTRIBUTE, reconnect);
- final ILaunchConfiguration reconnectConfig = new OverlayLaunchConfiguration(originalConfig, add);
+ final ILaunchConfiguration reconnectConfig= new OverlayLaunchConfiguration(originalConfig, add);
try {
- final ILaunch reconnectLaunch = reconnectConfig.launch(originallaunch.getLaunchMode(), monitor, false);
+ final ILaunch reconnectLaunch= reconnectConfig.launch(
+ originallaunch.getLaunchMode(), monitor, false );
// if (dispose != null) {
-// final ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
-// final ILaunchesListener2 launchListener = new ILaunchesListener2() {
+// final ILaunchManager launchManager= DebugPlugin.getDefault().getLaunchManager();
+// final ILaunchesListener2 launchListener= new ILaunchesListener2() {
// public void launchesAdded(final ILaunch[] launches) {
// }
// public void launchesChanged(final ILaunch[] launches) {
@@ -133,18 +141,17 @@
}
throw new InvocationTargetException(e);
}
-
}
};
}
- private boolean contains(final ILaunch[] launches, final ILaunch search) {
- for (final ILaunch launch : launches) {
- if (search == launch) {
- return true;
- }
- }
- return false;
- }
+// private boolean contains(final ILaunch[] launches, final ILaunch search) {
+// for (final ILaunch launch : launches) {
+// if (search == launch) {
+// return true;
+// }
+// }
+// return false;
+// }
}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/AbstractToolHandler.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/AbstractToolHandler.java
index 9bbb5fc..1273cfd 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/AbstractToolHandler.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/AbstractToolHandler.java
@@ -18,61 +18,155 @@
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.services.IServiceLocator;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ecommons.ts.core.Tool;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
+import org.eclipse.statet.ecommons.ui.workbench.WorkbenchUIUtils;
import org.eclipse.statet.internal.nico.ui.ToolSourceProvider;
-public abstract class AbstractToolHandler extends AbstractHandler {
+@NonNullByDefault
+public abstract class AbstractToolHandler<TTool extends Tool> extends AbstractHandler
+ implements ActiveToolListener {
- private final String requiredMainType;
- private final String requiredFeatureSet;
+ protected static final byte S_INITIALIZING= 0;
+ protected static final byte S_INITIALIZED= 1;
+ protected static final byte S_DISPOSED= -1;
- protected AbstractToolHandler(final String mainType) {
- this(mainType, null);
- }
+ /** internal state of this handler */
+ private byte state;
- protected AbstractToolHandler(final String mainType, final String featureSet) {
+ private final @Nullable String requiredMainType;
+ private final @Nullable String requiredFeatureSet;
+
+ private final @Nullable ToolProvider toolProvider;
+
+ private final @Nullable IServiceLocator serviceLocator;
+
+ private @Nullable TTool activeTool;
+
+
+ protected AbstractToolHandler(final @Nullable String mainType, final @Nullable String featureSet,
+ final @Nullable ToolProvider toolProvider, final @Nullable IServiceLocator serviceLocator) {
this.requiredMainType= mainType;
this.requiredFeatureSet= featureSet;
+
+ this.toolProvider= toolProvider;
+ this.serviceLocator= serviceLocator;
+
+ this.state= S_INITIALIZING;
+ }
+
+ protected AbstractToolHandler(final @Nullable String mainType, final @Nullable String featureSet) {
+ this(mainType, featureSet, null, null);
+ }
+
+ protected AbstractToolHandler(final @Nullable String mainType) {
+ this(mainType, null, null, null);
}
- protected Tool getTool(final Object evaluationContext) {
+ protected final int getState() {
+ return this.state;
+ }
+
+ /**
+ * Must be call at the end of the constructor to finish initialization.
+ */
+ protected void init() {
+ if (this.toolProvider != null) {
+ this.toolProvider.addToolListener(this);
+ }
+ this.state= S_INITIALIZED;
+ }
+
+ @Override
+ public void dispose() {
+ if (this.state == S_DISPOSED) {
+ return;
+ }
+ synchronized (this) {
+ this.state= S_DISPOSED;
+ }
+
+ if (this.toolProvider != null) {
+ this.toolProvider.removeToolListener(this);
+ }
+
+ super.dispose();
+ }
+
+
+ protected @Nullable Tool getTool(final @Nullable Object evaluationContext) {
+ if (this.toolProvider != null) {
+ return this.toolProvider.getTool();
+ }
return (Tool) HandlerUtil.getVariable(evaluationContext, ToolSourceProvider.ACTIVE_TOOL_NAME);
}
- protected boolean isValid(final Tool tool) {
- return (tool != null
- && (this.requiredMainType == null || tool.getMainType() == this.requiredMainType)
- && (this.requiredFeatureSet == null || tool.isProvidingFeatureSet(this.requiredFeatureSet))
- && isSupported(tool) );
+ @Override
+ public void onToolChanged(final ActiveToolEvent event) {
+ if (this.state == S_DISPOSED) {
+ return;
+ }
+
+ setEnabled(null);
}
- protected boolean isSupported(final Tool tool) {
+
+ protected boolean isValid(final @Nullable Tool tool) {
+ return (tool != null
+ && (this.requiredMainType == null || tool.getMainType() == this.requiredMainType)
+ && (this.requiredFeatureSet == null || tool.isProvidingFeatureSet(this.requiredFeatureSet)));
+ }
+
+
+ protected boolean evaluateIsEnabled(final TTool tool, final @Nullable Object evaluationContext) {
return (!tool.isTerminated());
}
-
@Override
- public void setEnabled(final Object evaluationContext) {
+ public void setEnabled(final @Nullable Object evaluationContext) {
final Tool tool= getTool(evaluationContext);
- setBaseEnabled(isValid(tool));
+ this.activeTool= isValid(tool) ? (TTool) tool : null;
+ setBaseEnabled(this.activeTool != null
+ && evaluateIsEnabled(this.activeTool, evaluationContext) );
}
+ protected @Nullable TTool getActiveTool() {
+ return this.activeTool;
+ }
+
+
+ protected IServiceLocator getServiceLocator(final @Nullable Object evaluationContext) {
+ if (this.serviceLocator != null) {
+ return this.serviceLocator;
+ }
+ return WorkbenchUIUtils.getServiceLocator(evaluationContext);
+ }
+
+
@Override
- public Object execute(final ExecutionEvent event) throws ExecutionException {
+ public @Nullable Object execute(final ExecutionEvent event) throws ExecutionException {
final Tool tool= getTool(event.getApplicationContext());
- if (!isValid(tool)) {
- return null;
+ final TTool execTool;
+ if ((tool == this.activeTool || isValid(tool))
+ && evaluateIsEnabled(execTool= (TTool) tool, event.getApplicationContext()) ) {
+ return execute(execTool, event);
}
- return execute(tool, event);
+ return null;
}
- protected abstract Object execute(Tool tool, ExecutionEvent event) throws ExecutionException;
+ protected abstract @Nullable Object execute(TTool tool,
+ ExecutionEvent event) throws ExecutionException;
}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/CancelHandler.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/CancelHandler.java
index 08adda3..ec36ca5 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/CancelHandler.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/CancelHandler.java
@@ -17,52 +17,55 @@
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
+
import org.eclipse.statet.nico.core.runtime.ToolController;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
/**
* Handler to cancel tool tasks.
*/
-public class CancelHandler extends ToolRetargetableHandler {
+@NonNullByDefault
+public class CancelHandler extends AbstractToolHandler<ToolProcess> {
- public static final String MENU_ID = "org.eclipse.statet.nico.menus.Cancel"; //$NON-NLS-1$
+ public static final String MENU_ID= "org.eclipse.statet.nico.menus.Cancel"; //$NON-NLS-1$
- public static final String PAR_OPTIONS = "options"; //$NON-NLS-1$
+ public static final String PAR_OPTIONS= "options"; //$NON-NLS-1$
- private final int fOptions;
+ private final int options;
- public CancelHandler(final IToolProvider toolProvider) {
- super(toolProvider, null);
- fOptions = 0;
+ public CancelHandler(final ToolProvider toolProvider, final int options) {
+ super(null, null, toolProvider, null);
+
+ this.options= options;
init();
}
- public CancelHandler(final IToolProvider toolProvider, final int options) {
- super(toolProvider, null);
- fOptions = options;
- init();
+ public CancelHandler(final ToolProvider toolProvider) {
+ this(toolProvider, 0);
}
@Override
- protected Object doExecute(final ExecutionEvent event) {
- final String optionsParameter = event.getParameter(PAR_OPTIONS);
- int options = fOptions;
+ protected @Nullable Object execute(final ToolProcess tool, final ExecutionEvent event) {
+ final String optionsParameter= event.getParameter(PAR_OPTIONS);
+ int options= this.options;
if (optionsParameter != null) {
try {
- options = Integer.decode(optionsParameter);
+ options= Integer.decode(optionsParameter);
}
catch (final NumberFormatException e) {
}
}
- final ToolProcess tool = getCheckedTool();
- final ToolController controller = (tool != null) ? tool.getController() : null;
+ final ToolController controller= (tool != null) ? tool.getController() : null;
if (controller == null) {
return null;
}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/LoadHistoryAction.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/LoadHistoryAction.java
index a5f1510..802d27d 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/LoadHistoryAction.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/LoadHistoryAction.java
@@ -16,20 +16,17 @@
import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
import org.eclipse.statet.nico.ui.NicoUIMessages;
-/**
- *
- */
public class LoadHistoryAction extends ToolAction {
- public LoadHistoryAction(final IToolProvider support) {
+ public LoadHistoryAction(final ToolProvider support) {
super(support, false);
setText(NicoUIMessages.LoadHistoryAction_name);
@@ -37,13 +34,12 @@
// setImageDescriptor();
// setDisabledImageDescriptor();
- handleToolChanged();
+ update();
}
@Override
public void run() {
-
final ToolProcess tool = getTool();
if (tool == null) {
return;
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/SaveHistoryAction.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/SaveHistoryAction.java
index e63fab4..be1ccdc 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/SaveHistoryAction.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/SaveHistoryAction.java
@@ -16,20 +16,17 @@
import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
import org.eclipse.statet.nico.ui.NicoUIMessages;
-/**
- *
- */
public class SaveHistoryAction extends ToolAction {
- public SaveHistoryAction(final IToolProvider support) {
+ public SaveHistoryAction(final ToolProvider support) {
super(support, false);
setText(NicoUIMessages.SaveHistoryAction_name);
@@ -37,7 +34,7 @@
// setImageDescriptor();
// setDisabledImageDescriptor();
- handleToolChanged();
+ update();
}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/ToolAction.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/ToolAction.java
index db2dd69..9fb82da 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/ToolAction.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/ToolAction.java
@@ -17,58 +17,55 @@
import org.eclipse.jface.action.Action;
import org.eclipse.swt.SWT;
+import org.eclipse.statet.ecommons.ts.core.Tool;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
+
import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
-import org.eclipse.statet.nico.core.util.IToolRetargetable;
/**
* Can be used for actions for tools.
* <p>
- * Same as {@link ToolRetargetableHandler} for actions
+ * Same as {@link AbstractLocalToolHandler} for actions
*/
-public class ToolAction extends Action implements IToolRetargetable {
+@Deprecated
+public class ToolAction extends Action implements ActiveToolListener {
private ToolProcess fTool;
private final boolean fDisableOnTermination;
- public ToolAction(final IToolProvider support, final boolean disableOnTermination) {
+ public ToolAction(final ToolProvider support, final boolean disableOnTermination) {
this(support, SWT.NONE, disableOnTermination);
}
- public ToolAction(final IToolProvider support, final int style, final boolean disableOnTermination) {
+ public ToolAction(final ToolProvider support, final int style, final boolean disableOnTermination) {
super(null, style);
- support.addToolRetargetable(this);
- fTool = support.getTool();
- fDisableOnTermination = disableOnTermination;
+ support.addToolListener(this);
+ setTool(support.getTool());
+ this.fDisableOnTermination = disableOnTermination;
}
+ private void setTool(final Tool tool) {
+ this.fTool = (tool instanceof ToolProcess) ? (ToolProcess) tool : null;
+ }
@Override
- public void setTool(final ToolProcess tool) {
- fTool = tool;
- handleToolChanged();
- }
-
- public void handleToolChanged() {
- update();
- }
-
- @Override
- public void toolTerminated() {
+ public void onToolChanged(final ActiveToolEvent event) {
+ setTool(event.getTool());
update();
}
public void update() {
- setEnabled(fTool != null
- && (!fDisableOnTermination || !fTool.isTerminated()));
+ setEnabled(this.fTool != null
+ && (!this.fDisableOnTermination || !this.fTool.isTerminated()));
}
public ToolProcess getTool() {
- return fTool;
+ return this.fTool;
}
}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/ToolRetargetableHandler.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/ToolRetargetableHandler.java
deleted file mode 100644
index 6ca2ffa..0000000
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/ToolRetargetableHandler.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*=============================================================================#
- # Copyright (c) 2007, 2018 Stephan Wahlbrink and others.
- #
- # This program and the accompanying materials are made available under the
- # terms of the Eclipse Public License 2.0 which is available at
- # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
- # which is available at https://www.apache.org/licenses/LICENSE-2.0.
- #
- # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
- #
- # Contributors:
- # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
- #=============================================================================*/
-
-package org.eclipse.statet.nico.ui.actions;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.window.IShellProvider;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.progress.IProgressService;
-import org.eclipse.ui.services.IServiceLocator;
-
-import org.eclipse.statet.ecommons.ui.util.UIAccess;
-import org.eclipse.statet.ecommons.ui.workbench.WorkbenchUIUtils;
-
-import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
-import org.eclipse.statet.nico.core.util.IToolRetargetable;
-
-
-/**
- * Abstract command handler (not tool event handler)
- * supporting tool assignment by the {@link IToolRetargetable} interface
- */
-public abstract class ToolRetargetableHandler extends AbstractHandler implements IToolRetargetable {
-
-
- protected static final int S_INIT = 1;
- protected static final int S_ONAIR = 2;
- protected static final int S_DISPOSED = 3;
-
- protected static class ChangedStateException extends IllegalStateException {
- private static final long serialVersionUID = 1L;
- }
-
-
- protected class ElementUpdater implements Runnable {
-
- private final String fCommandId;
-
- public ElementUpdater(final String commandId) {
- fCommandId = commandId;
- assert (getServiceLocator() != null);
- }
-
- @Override
- public void run() {
- WorkbenchUIUtils.refreshCommandElements(fCommandId, ToolRetargetableHandler.this, null);
- }
-
- public void schedule() {
- final Display display = UIAccess.getDisplay(getShell());
- if (display != null) {
- if (display.getThread() == Thread.currentThread()) {
- run();
- }
- else {
- display.asyncExec(this);
- }
- }
- }
- }
-
-
- /** providing the active tool */
- private final IToolProvider fToolProvider;
-
- /** optional service locator */
- private final IServiceLocator fServiceLocator;
-
- /** internal state of this handler */
- private int fState;
-
- private ToolProcess fTool;
-
-
- public ToolRetargetableHandler(final IToolProvider toolProvider, final IServiceLocator serviceLocator) {
- super();
- fState = S_INIT;
- fServiceLocator = serviceLocator;
- fToolProvider = toolProvider;
- if (fToolProvider != null) {
- fToolProvider.addToolRetargetable(this);
- }
- }
-
- /**
- * Must be call at the end of the constructor to finish initialization.
- */
- protected void init() {
- setTool(fToolProvider.getTool());
- fState = S_ONAIR;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void dispose() {
- if (fState >= S_DISPOSED) {
- return;
- }
- fState = S_DISPOSED;
-
- if (fToolProvider != null) {
- fToolProvider.removeToolRetargetable(this);
- }
-
- synchronized (this) {
- fTool = null;
- }
-
- super.dispose();
- }
-
-
- @Override
- public final void setTool(final ToolProcess tool) {
- boolean update = false;
-
- synchronized (this) {
- if (fState == S_DISPOSED) {
- return;
- }
- if ((fTool == null) ?
- (tool == null && getState() == S_ONAIR) :
- (tool == fTool) ) {
- return;
- }
-
- fTool = tool;
- update = handleToolChanged();
- }
-
- if (update) {
- doRefresh();
- }
- }
-
- @Override
- public void toolTerminated() {
- boolean update = false;
- synchronized (this) {
- update = handleToolChanged();
- }
-
- if (update) {
- doRefresh();
- }
- }
-
-
- protected final int getState() {
- return fState;
- }
-
- /**
- * @return current associated tool
- */
- public final ToolProcess getTool() {
- return fTool;
- }
-
- /**
- * Checks if action is enabled for the current tool and returns it
- *
- * @return current associated tool
- */
- protected final ToolProcess getCheckedTool() {
- synchronized (this) {
- if (fState != S_ONAIR || !isEnabled()) {
- throw new ChangedStateException();
- }
- return fTool;
- }
- }
-
- /**
- * Optional service locator (window, view, page,...)
- *
- * @return the service locator or <code>null</code>
- */
- protected IServiceLocator getServiceLocator() {
- return fServiceLocator;
- }
-
- protected IProgressService getProgressService() {
- return getServiceLocator().getService(IProgressService.class);
- }
-
-
- protected Shell getShell() {
- if (fServiceLocator instanceof IShellProvider) {
- return ((IShellProvider) fServiceLocator).getShell();
- }
- return null;
- }
-
-
- /**
- * Is called when the tool changed. Can be overwritten to
- * update the handler state.
- *
- * @return if {@link #doRefresh()} should be called
- */
- public boolean handleToolChanged() {
- final boolean isEnabled = evaluateEnabled();
- if (isEnabled != isEnabled()) {
- setBaseEnabled(isEnabled);
- return true;
- }
- return false;
- }
-
- /**
- * Is called when the tool was terminated. Can be overwritten to
- * update the handler state or do nothing.
- *
- * @return if {@link #doRefresh()} should be called
- */
- public boolean handleToolTerminated() {
- return handleToolChanged();
- }
-
- /**
- * Computes the enablement state of the handler. Can be overwritten
- * to change the criteria.
- *
- * @return if handler should set to enabled
- */
- protected boolean evaluateEnabled() {
- final ToolProcess tool = getTool();
- return (tool != null
- && !tool.isTerminated());
- }
-
- @Override
- public final Object execute(final ExecutionEvent event) throws ExecutionException {
- if (fToolProvider != null) {
- final ToolProcess tool = fToolProvider.getTool();
- if (tool != fTool) {
- setTool(tool);
- }
- }
-
- try {
- doExecute(event);
- }
- catch (final ChangedStateException e) {
- }
- return null;
- }
-
- protected void doRefresh() {
- }
-
- protected abstract Object doExecute(final ExecutionEvent event);
-
-}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/WindowToolProvider.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/WindowToolProvider.java
index 5df11a4..6155e5c 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/WindowToolProvider.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/actions/WindowToolProvider.java
@@ -17,55 +17,60 @@
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener.ActiveToolEvent;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
+
import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
-import org.eclipse.statet.nico.core.util.IToolRetargetable;
import org.eclipse.statet.nico.ui.IToolRegistryListener;
import org.eclipse.statet.nico.ui.NicoUI;
import org.eclipse.statet.nico.ui.ToolSessionUIData;
-public class WindowToolProvider implements IToolProvider, IToolRegistryListener {
+@Deprecated
+public class WindowToolProvider implements ToolProvider, IToolRegistryListener {
- private final IWorkbenchPage fPage;
+ private final IWorkbenchPage page;
- private IToolRetargetable fListener;
+ private ActiveToolListener listener;
public WindowToolProvider(final IWorkbenchWindow window) {
- fPage = window.getActivePage();
- assert (fPage != null);
+ this.page= window.getActivePage();
+ assert (this.page != null);
}
@Override
- public void addToolRetargetable(final IToolRetargetable listener) {
- assert (fListener == null);
- fListener = listener;
- NicoUI.getToolRegistry().addListener(this, fPage);
+ public void addToolListener(final ActiveToolListener listener) {
+ assert (this.listener == null);
+ this.listener= listener;
+ NicoUI.getToolRegistry().addListener(this, this.page);
}
@Override
- public void removeToolRetargetable(final IToolRetargetable listener) {
- assert (fListener == listener || fListener == null);
- fListener = null;
+ public void removeToolListener(final ActiveToolListener listener) {
+ assert (this.listener == listener || this.listener == null);
+ this.listener= null;
NicoUI.getToolRegistry().removeListener(this);
}
@Override
public ToolProcess getTool() {
- return NicoUI.getToolRegistry().getActiveToolSession(fPage).getProcess();
+ return NicoUI.getToolRegistry().getActiveToolSession(this.page).getProcess();
}
@Override
- public void toolSessionActivated(final ToolSessionUIData informations) {
- fListener.setTool(informations.getProcess());
+ public void toolSessionActivated(final ToolSessionUIData sessionData) {
+ this.listener.onToolChanged(
+ new ActiveToolEvent(ActiveToolEvent.TOOL_ACTIVATED, sessionData.getProcess()) );
}
@Override
public void toolTerminated(final ToolSessionUIData sessionData) {
- fListener.toolTerminated();
+ this.listener.onToolChanged(
+ new ActiveToolEvent(ActiveToolEvent.TOOL_TERMINATED, sessionData.getProcess()) );
}
-}
\ No newline at end of file
+}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/console/NIConsolePage.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/console/NIConsolePage.java
index 79f6d9f..94ef4c9 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/console/NIConsolePage.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/console/NIConsolePage.java
@@ -26,7 +26,6 @@
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler2;
import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.ListenerList;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
@@ -98,10 +97,15 @@
import org.eclipse.ui.services.IServiceLocator;
import org.eclipse.ui.texteditor.FindReplaceAction;
+import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet;
+
import org.eclipse.statet.ecommons.preferences.PreferencesUtil;
import org.eclipse.statet.ecommons.preferences.SettingsChangeNotifier.ChangeListener;
import org.eclipse.statet.ecommons.text.ui.TextViewerAction;
import org.eclipse.statet.ecommons.text.ui.TextViewerEditorColorUpdater;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener.ActiveToolEvent;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
import org.eclipse.statet.ecommons.ui.ISettingsChangedHandler;
import org.eclipse.statet.ecommons.ui.SharedMessages;
import org.eclipse.statet.ecommons.ui.actions.HandlerCollection;
@@ -126,8 +130,6 @@
import org.eclipse.statet.nico.core.runtime.ToolProcess;
import org.eclipse.statet.nico.core.runtime.ToolStatus;
import org.eclipse.statet.nico.core.runtime.ToolWorkspace;
-import org.eclipse.statet.nico.core.util.IToolProvider;
-import org.eclipse.statet.nico.core.util.IToolRetargetable;
import org.eclipse.statet.nico.ui.NicoUI;
import org.eclipse.statet.nico.ui.actions.CancelHandler;
import org.eclipse.statet.nico.ui.util.ExportConsoleOutputWizard;
@@ -143,7 +145,7 @@
*/
public abstract class NIConsolePage implements IPageBookViewPage,
IAdaptable, IShowInSource, IShowInTargetList,
- IPropertyChangeListener, ScrollLockAction.Receiver, IToolProvider, ChangeListener {
+ IPropertyChangeListener, ScrollLockAction.Receiver, ToolProvider, ChangeListener {
private static final String DIALOG_ID= "Console"; //$NON-NLS-1$
@@ -400,7 +402,7 @@
// Actions
private MultiActionHandler multiActionHandler;
- private final ListenerList toolActions= new ListenerList();
+ private final CopyOnWriteIdentityListSet<ActiveToolListener> toolListeners= new CopyOnWriteIdentityListSet<>();
NestedServices inputServices;
private FindReplaceUpdater findReplaceUpdater;
@@ -980,13 +982,13 @@
}
@Override
- public void addToolRetargetable(final IToolRetargetable listener) {
- this.toolActions.add(listener);
+ public void addToolListener(final ActiveToolListener listener) {
+ this.toolListeners.add(listener);
}
@Override
- public void removeToolRetargetable(final IToolRetargetable listener) {
- this.toolActions.remove(listener);
+ public void removeToolListener(final ActiveToolListener listener) {
+ this.toolListeners.remove(listener);
}
public TextConsoleViewer getOutputViewer() {
@@ -1088,8 +1090,9 @@
protected void onToolTerminated() {
if (this.isCreated) {
this.terminateAction.update();
- for (final Object action : this.toolActions.getListeners()) {
- ((IToolRetargetable) action).toolTerminated();
+ final ActiveToolEvent event= new ActiveToolEvent(ActiveToolEvent.TOOL_TERMINATED, getTool());
+ for (final ActiveToolListener listener : this.toolListeners) {
+ listener.onToolChanged(event);
}
this.outputPasteAction.setEnabled(false);
final Button button= this.inputGroup.getSubmitButton();
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/console/SubmitDropAdapter.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/console/SubmitDropAdapter.java
index 3ec2b9b..cbce93d 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/console/SubmitDropAdapter.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/console/SubmitDropAdapter.java
@@ -72,7 +72,8 @@
if (LocalTaskTransfer.getTransfer().isSupportedType(event.currentDataType)) {
final LocalTaskTransfer.Data data= (Data) event.data;
final ToolProcess process= this.page.getConsole().getProcess();
- if (data == null || process.isTerminated()) {
+ if (data == null || data.process == null || data.runnables == null
+ || process.isTerminated()) {
return;
}
data.process.getQueue().move(data.runnables, process.getQueue());
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/util/QuitHandler.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/util/QuitHandler.java
index 54b0f66..7c5515a 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/util/QuitHandler.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/util/QuitHandler.java
@@ -15,6 +15,7 @@
package org.eclipse.statet.nico.ui.util;
import java.lang.reflect.InvocationTargetException;
+import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
@@ -50,26 +51,26 @@
private static class UIRunnable implements Runnable {
- private ToolController fController;
- private String fDialogTitle;
- private String fDialogMessage;
- private String[] fDialogOptions;
- private volatile int fResult;
+ private ToolController controller;
+ private String dialogTitle;
+ private String dialogMessage;
+ private String[] dialogOptions;
+ private volatile int result;
@Override
public void run() {
- final IWorkbenchWindow window = UIAccess.getActiveWorkbenchWindow(true);
- final MessageDialog dialog = new MessageDialog(window.getShell(), fDialogTitle, null,
- fDialogMessage, MessageDialog.QUESTION, fDialogOptions, 0 );
- fResult = dialog.open();
+ final IWorkbenchWindow window= UIAccess.getActiveWorkbenchWindow(true);
+ final MessageDialog dialog= new MessageDialog(window.getShell(), this.dialogTitle, null,
+ this.dialogMessage, MessageDialog.QUESTION, this.dialogOptions, 0 );
+ this.result= dialog.open();
- if (fResult == 1) {
+ if (this.result == 1) {
try {
window.run(true, true, new IRunnableWithProgress() {
@Override
public void run(final IProgressMonitor monitor) throws InvocationTargetException {
try {
- fController.kill(monitor);
+ UIRunnable.this.controller.kill(monitor);
} catch (final CoreException e) {
throw new InvocationTargetException(e);
}
@@ -91,9 +92,9 @@
@Override
public IStatus execute(final String id, final ToolService service, final Map<String, Object> data,
final IProgressMonitor monitor) {
- final IConsoleService console = (IConsoleService) service;
+ final IConsoleService console= (IConsoleService) service;
if (PlatformUI.getWorkbench().isClosing()) {
- final ToolController controller = console.getController();
+ final ToolController controller= console.getController();
if (controller != null) {
if (console.getTool().isProvidingFeatureSet(IRemoteEngineController.FEATURE_SET_ID)) {
try {
@@ -111,25 +112,25 @@
return Status.CANCEL_STATUS;
}
- final ToolRunnable[] quitRunnables = (ToolRunnable[]) data.get("scheduledQuitTasks");
- if (quitRunnables.length == 0) {
- return Status.OK_STATUS; // run default = schedule quit
+ final List<ToolRunnable> quitRunnables= (List<ToolRunnable>) data.get("scheduledQuitRunnables");
+ if (quitRunnables.isEmpty()) {
+ return Status.OK_STATUS; // run default= schedule quit
}
- final UIRunnable runner = new UIRunnable();
- runner.fController = console.getController();
- final ToolProcess process = runner.fController.getTool();
- runner.fDialogTitle = NLS.bind(Messages.TerminatingMonitor_title, process.getLabel(Tool.DEFAULT_LABEL));
- runner.fDialogMessage = NLS.bind(Messages.TerminatingMonitor_message, process.getLabel(Tool.LONG_LABEL));
- runner.fDialogOptions = new String[] {
+ final UIRunnable runner= new UIRunnable();
+ runner.controller= console.getController();
+ final ToolProcess process= runner.controller.getTool();
+ runner.dialogTitle= NLS.bind(Messages.TerminatingMonitor_title, process.getLabel(Tool.DEFAULT_LABEL));
+ runner.dialogMessage= NLS.bind(Messages.TerminatingMonitor_message, process.getLabel(Tool.LONG_LABEL));
+ runner.dialogOptions= new String[] {
Messages.TerminatingMonitor_WaitButton_label,
Messages.TerminatingMonitor_ForceButton_label,
Messages.TerminatingMonitor_CancelButton_label
};
UIAccess.getDisplay().syncExec(runner);
- if (runner.fResult == 2) {
- runner.fController.cancelQuit();
+ if (runner.result == 2) {
+ runner.controller.cancelQuit();
}
return Status.CANCEL_STATUS; // do nothing
}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/views/HistoryView.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/views/HistoryView.java
index aaf715d..8b83ebb 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/views/HistoryView.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/views/HistoryView.java
@@ -49,7 +49,6 @@
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
@@ -72,11 +71,15 @@
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
+import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.ecommons.collections.FastList;
import org.eclipse.statet.ecommons.preferences.core.Preference.EnumSetPref;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener.ActiveToolEvent;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
import org.eclipse.statet.ecommons.ui.SharedMessages;
import org.eclipse.statet.ecommons.ui.SharedUIResources;
import org.eclipse.statet.ecommons.ui.actions.HandlerContributionItem;
@@ -95,8 +98,6 @@
import org.eclipse.statet.nico.core.runtime.IHistoryListener;
import org.eclipse.statet.nico.core.runtime.SubmitType;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
-import org.eclipse.statet.nico.core.util.IToolRetargetable;
import org.eclipse.statet.nico.ui.IToolRegistry;
import org.eclipse.statet.nico.ui.IToolRegistryListener;
import org.eclipse.statet.nico.ui.NicoUI;
@@ -112,7 +113,7 @@
*
* Usage: This class is not intend to be subclassed.
*/
-public class HistoryView extends ViewPart implements IToolProvider {
+public class HistoryView extends ViewPart implements ToolProvider {
public static interface EntryFilter {
@@ -162,15 +163,15 @@
private final EnumSet<SubmitType> fSubmitTypes;
public SubmitTypeFilter(final EnumSet<SubmitType> types) {
- fSubmitTypes = types;
+ this.fSubmitTypes = types;
}
@Override
public boolean select(final Entry e) {
final SubmitType type = e.getSubmitType();
return (type == null
- || fSubmitTypes.contains(type));
- }
+ || this.fSubmitTypes.contains(type));
+ }
}
@@ -187,12 +188,12 @@
@Override
protected IStatus run(final IProgressMonitor monitor) {
- final ToolProcess process = fProcess;
+ final ToolProcess process = HistoryView.this.fProcess;
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
if (process == null) {
- fContentProvider.setNewSource(null, new Entry[0]);
+ HistoryView.this.fContentProvider.setNewSource(null, new Entry[0]);
return Status.OK_STATUS;
}
final History history = process.getHistory();
@@ -207,7 +208,7 @@
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
- fContentProvider.setNewSource(history, entries);
+ HistoryView.this.fContentProvider.setNewSource(history, entries);
return Status.OK_STATUS;
}
@@ -224,55 +225,55 @@
private Entry[] fNewEntrys;
public synchronized void setNewSource(final History source, final Entry[] es) {
- fCurrentSource = source;
+ this.fCurrentSource = source;
- fNewEntrys = es;
- fToAdd.clear();
- fToRemove.clear();
+ this.fNewEntrys = es;
+ this.fToAdd.clear();
+ this.fToRemove.clear();
- if (!fIsScheduled) {
- fIsScheduled = true;
+ if (!this.fIsScheduled) {
+ this.fIsScheduled = true;
UIAccess.getDisplay().asyncExec(this);
}
}
@Override
public synchronized void completeChange(final History source, final Entry[] es) {
- if (fCurrentSource != source) {
+ if (this.fCurrentSource != source) {
return;
}
- fNewEntrys = es;
- fToAdd.clear();
- fToRemove.clear();
+ this.fNewEntrys = es;
+ this.fToAdd.clear();
+ this.fToRemove.clear();
- if (!fIsScheduled) {
- fIsScheduled = true;
+ if (!this.fIsScheduled) {
+ this.fIsScheduled = true;
UIAccess.getDisplay().asyncExec(this);
}
}
@Override
public synchronized void entryAdded(final History source, final Entry e) {
- if (fCurrentSource != source) {
+ if (this.fCurrentSource != source) {
return;
}
- fToAdd.add(e);
+ this.fToAdd.add(e);
- if (!fIsScheduled) {
- fIsScheduled = true;
+ if (!this.fIsScheduled) {
+ this.fIsScheduled = true;
UIAccess.getDisplay().asyncExec(this);
}
}
@Override
public synchronized void entryRemoved(final History source, final Entry e) {
- if (fCurrentSource != source) {
+ if (this.fCurrentSource != source) {
return;
}
- fToRemove.add(e);
+ this.fToRemove.add(e);
- if (!fIsScheduled) {
- fIsScheduled = true;
+ if (!this.fIsScheduled) {
+ this.fIsScheduled = true;
UIAccess.getDisplay().asyncExec(this);
}
}
@@ -286,30 +287,30 @@
final ImList<Entry> toRemoveEntries;
final EntryFilter[] filter;
synchronized (this) {
- fIsScheduled = false;
- if (!UIAccess.isOkToUse(fTable)) {
+ this.fIsScheduled = false;
+ if (!UIAccess.isOkToUse(HistoryView.this.fTable)) {
return;
}
- if ((fProcess != null && fCurrentSource != fProcess.getHistory())
- || (fProcess == null && fCurrentSource != null)) {
+ if ((HistoryView.this.fProcess != null && this.fCurrentSource != HistoryView.this.fProcess.getHistory())
+ || (HistoryView.this.fProcess == null && this.fCurrentSource != null)) {
return;
}
- newEntries = fNewEntrys;
- fNewEntrys = null;
- toAdd = fToAdd.size();
- toAddEntries = (toAdd > 0) ? ImCollections.clearToList(fToAdd) : null;
- toRemove = fToRemove.size();
- toRemoveEntries = (toRemove > REMOVE_THRESHOLD) ? ImCollections.clearToList(fToRemove) : null;
- filter = fFilter.toArray();
+ newEntries = this.fNewEntrys;
+ this.fNewEntrys = null;
+ toAdd = this.fToAdd.size();
+ toAddEntries = (toAdd > 0) ? ImCollections.clearToList(this.fToAdd) : null;
+ toRemove = this.fToRemove.size();
+ toRemoveEntries = (toRemove > REMOVE_THRESHOLD) ? ImCollections.clearToList(this.fToRemove) : null;
+ filter = HistoryView.this.fFilter.toArray();
}
- fTable.setRedraw(false);
+ HistoryView.this.fTable.setRedraw(false);
TableItem addedItem = null;
if (newEntries != null) {
- fTable.deselectAll();
+ HistoryView.this.fTable.deselectAll();
- final int reusableItemCount = fTable.getItemCount();
+ final int reusableItemCount = HistoryView.this.fTable.getItemCount();
int reuseItemIdx = 0;
final int n = newEntries.length;
ITER_ENTRY : for (int i = 0; i < n; i++) {
@@ -320,20 +321,20 @@
}
}
if (reuseItemIdx < reusableItemCount) {
- addedItem = fTable.getItem(reuseItemIdx++);
+ addedItem = HistoryView.this.fTable.getItem(reuseItemIdx++);
}
else {
- addedItem = new TableItem(fTable, SWT.NONE);
+ addedItem = new TableItem(HistoryView.this.fTable, SWT.NONE);
}
addedItem.setData(e);
updateItem(addedItem);
}
if (reuseItemIdx < reusableItemCount) {
- fTable.remove(reuseItemIdx, reusableItemCount-1);
+ HistoryView.this.fTable.remove(reuseItemIdx, reusableItemCount-1);
}
if (addedItem != null) {
- fTable.showItem(addedItem);
+ HistoryView.this.fTable.showItem(addedItem);
}
}
@@ -345,18 +346,18 @@
continue ITER_ENTRY;
}
}
- addedItem = new TableItem(fTable, SWT.NONE);
+ addedItem = new TableItem(HistoryView.this.fTable, SWT.NONE);
addedItem.setData(e);
updateItem(addedItem);
}
}
if (toRemove > REMOVE_THRESHOLD) {
- final int itemCount = fTable.getItemCount();
+ final int itemCount = HistoryView.this.fTable.getItemCount();
int[] removeIdxs = new int[toRemove];
int count = 0;
for (int i = 0; i < toRemove; i++) {
for (int j = 0; j < itemCount; j++) {
- final TableItem removedItem = fTable.getItem(j);
+ final TableItem removedItem = HistoryView.this.fTable.getItem(j);
if (removedItem.getData() == toRemoveEntries.get(i)) {
removedItem.setData(null);
removeIdxs[count++] = j;
@@ -367,14 +368,14 @@
if (count < removeIdxs.length) {
System.arraycopy(removeIdxs, 0, removeIdxs = new int[count], 0, count);
}
- fTable.remove(removeIdxs);
+ HistoryView.this.fTable.remove(removeIdxs);
}
}
- if (fDoAutoscroll && addedItem != null) {
- fTable.showItem(addedItem);
+ if (HistoryView.this.fDoAutoscroll && addedItem != null) {
+ HistoryView.this.fTable.showItem(addedItem);
}
- fTable.setRedraw(true);
+ HistoryView.this.fTable.setRedraw(true);
}
}
@@ -386,15 +387,15 @@
setToolTipText(Messages.FilterEmptyAction_tooltip);
setImageDescriptor(SharedUIResources.getImages().getDescriptor(SharedUIResources.LOCTOOL_FILTER_IMAGE_ID));
- setChecked(fDoFilterEmpty);
+ setChecked(HistoryView.this.fDoFilterEmpty);
}
@Override
public void run() {
final boolean switchOn = isChecked();
- fDoFilterEmpty = switchOn;
+ HistoryView.this.fDoFilterEmpty = switchOn;
if (switchOn) {
- addFilter(EMPTY_FILTER);
+ addFilter(EMPTY_FILTER);
}
else {
removeFilter(EMPTY_FILTER);
@@ -409,24 +410,24 @@
public FilterBySourceAction(final SubmitType type) {
super(type.getLabel(), null, SimpleContributionItem.STYLE_CHECK);
- fType = type;
- setChecked(fFilterBySource.fSubmitTypes.contains(type));
+ this.fType = type;
+ setChecked(HistoryView.this.fFilterBySource.fSubmitTypes.contains(type));
}
@Override
protected void execute() throws ExecutionException {
- final SubmitTypeFilter currentFilter = fFilterBySource;
+ final SubmitTypeFilter currentFilter = HistoryView.this.fFilterBySource;
final EnumSet<SubmitType> types = EnumSet.copyOf(currentFilter.fSubmitTypes);
- if (types.contains(fType)) {
- types.remove(fType);
+ if (types.contains(this.fType)) {
+ types.remove(this.fType);
setChecked(false);
}
else {
- types.add(fType);
+ types.add(this.fType);
setChecked(true);
}
final SubmitTypeFilter newFilter = new SubmitTypeFilter(types);
- fFilterBySource = newFilter;
+ HistoryView.this.fFilterBySource = newFilter;
replaceFilter(currentFilter, newFilter);
}
@@ -452,7 +453,7 @@
private static final String M_FILTER_BY_SOURCE = "FilterBySource.include"; //$NON-NLS-1$
private SubmitTypeFilter fFilterBySource;
- private final FastList<IToolRetargetable> fToolListenerList= new FastList<>(IToolRetargetable.class);
+ private final CopyOnWriteIdentityListSet<ActiveToolListener> fToolListeners= new CopyOnWriteIdentityListSet<>();
private Action fSelectAllAction;
private Action fCopyAction;
@@ -476,8 +477,8 @@
* The constructor.
*/
public HistoryView() {
- fReloadJob = new ViewReloadJob();
- fContentProvider = new ViewContentProvider();
+ this.fReloadJob = new ViewReloadJob();
+ this.fContentProvider = new ViewContentProvider();
}
@@ -487,28 +488,28 @@
final String autoscroll = (memento != null) ? memento.getString(M_AUTOSCROLL) : null;
if (autoscroll == null || autoscroll.equals("on")) { // default //$NON-NLS-1$
- fDoAutoscroll = true;
+ this.fDoAutoscroll = true;
}
else {
- fDoAutoscroll = false;
+ this.fDoAutoscroll = false;
}
final String filterBySource = (memento != null) ? memento.getString(M_FILTER_BY_SOURCE) : null;
if (filterBySource == null) {
- fFilterBySource = new SubmitTypeFilter(EnumSet.range(SubmitType.CONSOLE, SubmitType.TOOLS));
+ this.fFilterBySource = new SubmitTypeFilter(EnumSet.range(SubmitType.CONSOLE, SubmitType.TOOLS));
}
else {
- fFilterBySource = new SubmitTypeFilter(SOURCE_ENCODER.store2Usage(filterBySource));
+ this.fFilterBySource = new SubmitTypeFilter(SOURCE_ENCODER.store2Usage(filterBySource));
}
- fFilter.add(fFilterBySource);
+ this.fFilter.add(this.fFilterBySource);
final String filterEmpty = (memento != null) ? memento.getString(M_FILTER_EMPTY) : null;
if (filterEmpty == null || filterEmpty.equals("off")) { // default //$NON-NLS-1$
- fDoFilterEmpty = false;
+ this.fDoFilterEmpty = false;
}
else {
- fDoFilterEmpty = true;
- fFilter.add(EMPTY_FILTER);
+ this.fDoFilterEmpty = true;
+ this.fFilter.add(EMPTY_FILTER);
}
}
@@ -516,64 +517,64 @@
public void saveState(final IMemento memento) {
super.saveState(memento);
- memento.putString(M_AUTOSCROLL, (fDoAutoscroll) ? "on" : "off"); //$NON-NLS-1$ //$NON-NLS-2$
- memento.putString(M_FILTER_BY_SOURCE, SOURCE_ENCODER.usage2Store(fFilterBySource.fSubmitTypes));
- memento.putString(M_FILTER_EMPTY, (fDoFilterEmpty) ? "on" : "off"); //$NON-NLS-1$ //$NON-NLS-2$
+ memento.putString(M_AUTOSCROLL, (this.fDoAutoscroll) ? "on" : "off"); //$NON-NLS-1$ //$NON-NLS-2$
+ memento.putString(M_FILTER_BY_SOURCE, SOURCE_ENCODER.usage2Store(this.fFilterBySource.fSubmitTypes));
+ memento.putString(M_FILTER_EMPTY, (this.fDoFilterEmpty) ? "on" : "off"); //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public void createPartControl(final Composite parent) {
parent.setLayout(LayoutUtils.newSashGrid());
- fTable = new Table(parent, SWT.MULTI | SWT.V_SCROLL | SWT.FULL_SELECTION);
- fTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- fTable.setLinesVisible(false);
- fTable.setHeaderVisible(false);
- new DefaultToolTip(fTable) {
+ this.fTable = new Table(parent, SWT.MULTI | SWT.V_SCROLL | SWT.FULL_SELECTION);
+ this.fTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ this.fTable.setLinesVisible(false);
+ this.fTable.setHeaderVisible(false);
+ new DefaultToolTip(this.fTable) {
private final DateFormat fFormat = DateFormat.getDateTimeInstance();
@Override
protected boolean shouldCreateToolTip(final Event event) {
return (super.shouldCreateToolTip(event)
- && fTable.getItem(new Point(event.x, event.y)) != null );
+ && HistoryView.this.fTable.getItem(new Point(event.x, event.y)) != null );
}
@Override
protected String getText(final Event event) {
- final TableItem item = fTable.getItem(new Point(event.x, event.y));
+ final TableItem item = HistoryView.this.fTable.getItem(new Point(event.x, event.y));
if (item != null) {
final Entry e = (Entry) item.getData();
if (e.getTimeStamp() < 0) {
return "[-]\n"+e.getCommand(); //$NON-NLS-1$
}
else {
- return "["+fFormat.format(new Date(e.getTimeStamp()))+"]\n" + e.getCommand(); //$NON-NLS-1$ //$NON-NLS-2$
+ return "["+this.fFormat.format(new Date(e.getTimeStamp()))+"]\n" + e.getCommand(); //$NON-NLS-1$ //$NON-NLS-2$
}
}
return null;
}
};
- final TableColumn column = new TableColumn(fTable, SWT.DEFAULT);
- fTable.addListener(SWT.Resize, new Listener() {
+ final TableColumn column = new TableColumn(this.fTable, SWT.DEFAULT);
+ this.fTable.addListener(SWT.Resize, new Listener() {
@Override
public void handleEvent(final Event event) {
// adapt the column width to the width of the table
- final int tableWidth = fTable.getClientArea().width;
+ final int tableWidth = HistoryView.this.fTable.getClientArea().width;
if (tableWidth == 0) {
return;
}
column.setWidth(tableWidth);
}
});
- fTable.addKeyListener(new KeyListener() {
+ this.fTable.addKeyListener(new KeyListener() {
@Override
public void keyPressed(final KeyEvent e) {
- if (e.keyCode == SWT.ARROW_UP &&
- fTable.getSelectionCount() == 1 && fTable.getSelectionIndex() == 0) {
- fSearchTextItem.show();
- fTable.deselectAll();
+ if (e.keyCode == SWT.ARROW_UP &&
+ HistoryView.this.fTable.getSelectionCount() == 1 && HistoryView.this.fTable.getSelectionIndex() == 0) {
+ HistoryView.this.fSearchTextItem.show();
+ HistoryView.this.fTable.deselectAll();
e.doit = false;
}
}
@@ -586,13 +587,13 @@
hookContextMenu();
contributeToActionBars();
- final DragSource dragSource = new DragSource(fTable, DND.DROP_COPY);
+ final DragSource dragSource = new DragSource(this.fTable, DND.DROP_COPY);
dragSource.setTransfer(new Transfer[] { TextTransfer.getInstance() });
dragSource.addDragListener(new HistoryDragAdapter(this));
// listen on console changes
final IToolRegistry toolRegistry = NicoUI.getToolRegistry();
- fToolRegistryListener = new IToolRegistryListener() {
+ this.fToolRegistryListener = new IToolRegistryListener() {
@Override
public void toolSessionActivated(final ToolSessionUIData sessionData) {
final ToolProcess process = sessionData.getProcess();
@@ -609,14 +610,14 @@
UIAccess.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
- if (fProcess != null && fProcess == process) {
+ if (HistoryView.this.fProcess != null && HistoryView.this.fProcess == process) {
connect(null);
}
}
});
}
};
- toolRegistry.addListener(fToolRegistryListener, getViewSite().getPage());
+ toolRegistry.addListener(this.fToolRegistryListener, getViewSite().getPage());
connect(toolRegistry.getActiveToolSession(getViewSite().getPage()).getProcess());
PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "org.eclipse.statet.nico.ui.cmd_history_view"); //$NON-NLS-1$
@@ -631,28 +632,28 @@
private void createActions() {
final IHandlerService handlerService = getSite().getService(IHandlerService.class);
- fFilterEmptyAction = new FilterEmptyAction();
- fScrollLockAction = new ScrollLockAction(new Receiver() {
+ this.fFilterEmptyAction = new FilterEmptyAction();
+ this.fScrollLockAction = new ScrollLockAction(new Receiver() {
@Override
public void setAutoScroll(final boolean enabled) {
- fDoAutoscroll = enabled;
+ HistoryView.this.fDoAutoscroll = enabled;
}
- }, !fDoAutoscroll);
- fSelectAllAction = new Action() {
+ }, !this.fDoAutoscroll);
+ this.fSelectAllAction = new Action() {
@Override
public void run() {
- fTable.selectAll();
+ HistoryView.this.fTable.selectAll();
}
};
- fCopyAction = new HistoryCopyAction(this);
- fSubmitAction = new HistorySubmitAction(this);
+ this.fCopyAction = new HistoryCopyAction(this);
+ this.fSubmitAction = new HistorySubmitAction(this);
enabledSelectionActions(false);
- fTable.addSelectionListener(new SelectionListener() {
+ this.fTable.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(final SelectionEvent e) {
- if (fTable.getSelectionCount() > 0) {
+ if (HistoryView.this.fTable.getSelectionCount() > 0) {
enabledSelectionActions(true);
}
else {
@@ -661,46 +662,46 @@
};
@Override
public void widgetDefaultSelected(final SelectionEvent e) {
- fSubmitAction.run();
+ HistoryView.this.fSubmitAction.run();
}
} );
- fLoadHistoryAction = new LoadHistoryAction(this);
- fSaveHistoryAction = new SaveHistoryAction(this);
+ this.fLoadHistoryAction = new LoadHistoryAction(this);
+ this.fSaveHistoryAction = new SaveHistoryAction(this);
- fSearchStartHandler = new AbstractHandler() {
+ this.fSearchStartHandler = new AbstractHandler() {
@Override
public Object execute(final ExecutionEvent arg0) {
- fSearchTextItem.show();
+ HistoryView.this.fSearchTextItem.show();
return null;
}
};
- handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_FIND_AND_REPLACE, fSearchStartHandler);
+ handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_FIND_AND_REPLACE, this.fSearchStartHandler);
- fSearchNextHandler = new AbstractHandler() {
+ this.fSearchNextHandler = new AbstractHandler() {
@Override
public Object execute(final ExecutionEvent arg0) {
search(true, -1);
return null;
}
};
- handlerService.activateHandler(SharedUIResources.FIND_NEXT_COMMAND_ID, fSearchNextHandler);
- handlerService.activateHandler("org.eclipse.ui.navigate.next", fSearchNextHandler); //$NON-NLS-1$
+ handlerService.activateHandler(SharedUIResources.FIND_NEXT_COMMAND_ID, this.fSearchNextHandler);
+ handlerService.activateHandler("org.eclipse.ui.navigate.next", this.fSearchNextHandler); //$NON-NLS-1$
- fSearchPrevHandler = new AbstractHandler() {
+ this.fSearchPrevHandler = new AbstractHandler() {
@Override
public Object execute(final ExecutionEvent arg0) {
search(false, -1);
return null;
}
};
- handlerService.activateHandler(SharedUIResources.FIND_PREVIOUS_COMMAND_ID, fSearchPrevHandler);
- handlerService.activateHandler("org.eclipse.ui.navigate.previous", fSearchPrevHandler); //$NON-NLS-1$
+ handlerService.activateHandler(SharedUIResources.FIND_PREVIOUS_COMMAND_ID, this.fSearchPrevHandler);
+ handlerService.activateHandler("org.eclipse.ui.navigate.previous", this.fSearchPrevHandler); //$NON-NLS-1$
}
protected void enabledSelectionActions(final boolean enable) {
- fCopyAction.setEnabled(enable);
- fSubmitAction.setEnabled(enable);
+ this.fCopyAction.setEnabled(enable);
+ this.fSubmitAction.setEnabled(enable);
}
@@ -713,24 +714,24 @@
HistoryView.this.fillContextMenu(manager);
}
});
- final Menu menu = menuMgr.createContextMenu(fTable);
- fTable.setMenu(menu);
+ final Menu menu = menuMgr.createContextMenu(this.fTable);
+ this.fTable.setMenu(menu);
// getSite().registerContextMenu(menuMgr, fTableViewer);
}
private void contributeToActionBars() {
final IActionBars bars = getViewSite().getActionBars();
- bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), fSelectAllAction);
- bars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyAction);
+ bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), this.fSelectAllAction);
+ bars.setGlobalActionHandler(ActionFactory.COPY.getId(), this.fCopyAction);
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
}
private void fillLocalPullDown(final IMenuManager manager) {
- manager.add(fLoadHistoryAction);
- manager.add(fSaveHistoryAction);
+ manager.add(this.fLoadHistoryAction);
+ manager.add(this.fSaveHistoryAction);
manager.add(new Separator());
final IMenuManager filterBySourceMenu = new MenuManager("Include Commands &From", SharedUIResources.getImages().getDescriptor(SharedUIResources.LOCTOOL_FILTER_IMAGE_ID), null);
@@ -740,108 +741,110 @@
filterBySourceMenu.add(new FilterBySourceAction(submitType));
}
manager.add(filterBySourceMenu);
- manager.add(fFilterEmptyAction);
+ manager.add(this.fFilterEmptyAction);
manager.add(new Separator());
- manager.add(fScrollLockAction);
+ manager.add(this.fScrollLockAction);
manager.add(new Separator());
}
private void fillContextMenu(final IMenuManager manager) {
- manager.add(fCopyAction);
- manager.add(fSubmitAction);
+ manager.add(this.fCopyAction);
+ manager.add(this.fSubmitAction);
// Other plug-ins can contribute there actions here
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
private void fillLocalToolBar(final IToolBarManager manager) {
- fSearchTextItem = new SearchContributionItem("search.text", //$NON-NLS-1$
+ this.fSearchTextItem = new SearchContributionItem("search.text", //$NON-NLS-1$
SearchContributionItem.VIEW_TOOLBAR ) {
@Override
protected void search() {
HistoryView.this.search(true, -1);
}
};
- fSearchTextItem.setToolTip(Messages.HistorySearch_Pattern_tooltip);
- fSearchTextItem.setSizeControl(fTable.getParent());
- fSearchTextItem.setResultControl(fTable);
+ this.fSearchTextItem.setToolTip(Messages.HistorySearch_Pattern_tooltip);
+ this.fSearchTextItem.setSizeControl(this.fTable.getParent());
+ this.fSearchTextItem.setResultControl(this.fTable);
- manager.add(fSearchTextItem);
+ manager.add(this.fSearchTextItem);
final ImageRegistry ecommonsImages = SharedUIResources.getImages();
manager.add(new HandlerContributionItem(new CommandContributionItemParameter(
getSite(), "search.next", SharedUIResources.FIND_NEXT_COMMAND_ID, null, //$NON-NLS-1$
ecommonsImages.getDescriptor(SharedUIResources.LOCTOOL_DOWN_IMAGE_ID), null, ecommonsImages.getDescriptor(SharedUIResources.LOCTOOL_DOWN_H_IMAGE_ID),
- SharedMessages.FindNext_tooltip, null, null, SWT.PUSH, null, false), fSearchNextHandler));
+ SharedMessages.FindNext_tooltip, null, null, SWT.PUSH, null, false), this.fSearchNextHandler));
manager.add(new HandlerContributionItem(new CommandContributionItemParameter(
getSite(), "search.previous", SharedUIResources.FIND_PREVIOUS_COMMAND_ID, null, //$NON-NLS-1$
ecommonsImages.getDescriptor(SharedUIResources.LOCTOOL_UP_IMAGE_ID), null, ecommonsImages.getDescriptor(SharedUIResources.LOCTOOL_UP_H_IMAGE_ID),
- SharedMessages.FindPrevious_tooltip, null, null, SWT.PUSH, null, false), fSearchPrevHandler));
+ SharedMessages.FindPrevious_tooltip, null, null, SWT.PUSH, null, false), this.fSearchPrevHandler));
manager.add(new Separator());
- manager.add(fScrollLockAction);
+ manager.add(this.fScrollLockAction);
}
/** May only be called in UI thread */
public void connect(final ToolProcess process) {
- if (fProcess == process) {
+ if (this.fProcess == process) {
return;
}
- if (fProcess != null) {
- fProcess.getHistory().removeListener(fContentProvider);
+ if (this.fProcess != null) {
+ this.fProcess.getHistory().removeListener(this.fContentProvider);
}
- fProcess = process;
- if (fProcess != null) {
- fProcess.getHistory().addListener(fContentProvider);
+ this.fProcess = process;
+ if (this.fProcess != null) {
+ this.fProcess.getHistory().addListener(this.fContentProvider);
}
scheduleRefresh(true);
- for (final IToolRetargetable action : fToolListenerList.toArray()) {
- action.setTool(fProcess);
+
+ final ActiveToolEvent event= new ActiveToolEvent(ActiveToolEvent.TOOL_ACTIVATED, this.fProcess);
+ for (final ActiveToolListener listener : this.fToolListeners) {
+ listener.onToolChanged(event);
}
}
private void scheduleRefresh(final boolean change) {
final IWorkbenchSiteProgressService context = getSite().getAdapter(IWorkbenchSiteProgressService.class);
if (change) {
- fReloadJob.cancel();
- context.schedule(fReloadJob, 200);
+ this.fReloadJob.cancel();
+ context.schedule(this.fReloadJob, 200);
}
else {
- context.schedule(fReloadJob, 0);
+ context.schedule(this.fReloadJob, 0);
}
}
@Override
- public void addToolRetargetable(final IToolRetargetable action) {
- fToolListenerList.add(action);
+ public void addToolListener(final ActiveToolListener action) {
+ this.fToolListeners.add(action);
}
@Override
- public void removeToolRetargetable(final IToolRetargetable action) {
- fToolListenerList.remove(action);
+ public void removeToolListener(final ActiveToolListener action) {
+ this.fToolListeners.remove(action);
}
public void addFilter(final EntryFilter filter) {
- fFilter.add(filter);
+ this.fFilter.add(filter);
scheduleRefresh(false);
}
public void removeFilter(final EntryFilter filter) {
- fFilter.remove(filter);
+ this.fFilter.remove(filter);
scheduleRefresh(false);
}
public void replaceFilter(final EntryFilter oldFilter, final EntryFilter newFilter) {
- fFilter.replace(oldFilter, newFilter);
+ this.fFilter.replace(oldFilter, newFilter);
scheduleRefresh(false);
}
public void search(final String pattern, final boolean forward) {
- fSearchTextItem.getSearchText().setText(pattern);
- search(forward, forward ? 0 : fTable.getItemCount()-1);
+ this.fSearchTextItem.getSearchText().setText(pattern);
+ search(forward, forward ? 0 : this.fTable.getItemCount()-1);
}
@@ -852,7 +855,7 @@
*/
@Override
public ToolProcess getTool() {
- return fProcess;
+ return this.fProcess;
}
/**
@@ -861,15 +864,15 @@
* @return a clipboard object.
*/
public Clipboard getClipboard() {
- if (fClipboard == null) {
- fClipboard = new Clipboard(Display.getCurrent());
+ if (this.fClipboard == null) {
+ this.fClipboard = new Clipboard(Display.getCurrent());
}
- return fClipboard;
+ return this.fClipboard;
}
public Entry[] getSelection() {
- final TableItem[] items = fTable.getSelection();
+ final TableItem[] items = this.fTable.getSelection();
final int n = items.length;
final Entry[] selection = new Entry[n];
for (int i = 0; i < n; i++) {
@@ -881,16 +884,16 @@
@Override
public void setFocus() {
// Passing the focus request to the viewer's control.
- fTable.setFocus();
+ this.fTable.setFocus();
}
private void search(final boolean forward, final int startIdx) {
- if (!UIAccess.isOkToUse(fTable)) {
+ if (!UIAccess.isOkToUse(this.fTable)) {
return;
}
- final int itemCount = fTable.getItemCount();
- final String text = fSearchTextItem.getText();
+ final int itemCount = this.fTable.getItemCount();
+ final String text = this.fSearchTextItem.getText();
if (itemCount == 0 || text.isEmpty()) {
return;
}
@@ -905,11 +908,11 @@
break;
}
} while (start < text.length());
- fSearchPattern.setPattern(text.substring(start));
+ this.fSearchPattern.setPattern(text.substring(start));
int idx;
if (startIdx < 0) {
- idx = fTable.getSelectionIndex();
+ idx = this.fTable.getSelectionIndex();
}
else {
idx = (forward) ? startIdx-1 : startIdx+1;
@@ -917,11 +920,11 @@
if (forward) {
idx++;
while (idx < itemCount) {
- final Entry e = (Entry) fTable.getItem(idx).getData();
+ final Entry e = (Entry) this.fTable.getItem(idx).getData();
final int offset = e.getCommandMarker();
- if (fSearchPattern.matches(e.getCommand().substring(
+ if (this.fSearchPattern.matches(e.getCommand().substring(
offset >= 0 ? offset : -1-offset))) {
- fTable.setSelection(idx);
+ this.fTable.setSelection(idx);
return;
}
idx++;
@@ -930,11 +933,11 @@
else {
idx--;
while (idx >= 0) {
- final Entry e = (Entry) fTable.getItem(idx).getData();
+ final Entry e = (Entry) this.fTable.getItem(idx).getData();
final int offset = e.getCommandMarker();
- if (fSearchPattern.matches(e.getCommand().substring(
+ if (this.fSearchPattern.matches(e.getCommand().substring(
offset >= 0 ? offset : -1-offset))) {
- fTable.setSelection(idx);
+ this.fTable.setSelection(idx);
return;
}
idx--;
@@ -945,42 +948,42 @@
@Override
public void dispose() {
- if (fToolRegistryListener != null) {
- NicoUI.getToolRegistry().removeListener(fToolRegistryListener);
- fToolRegistryListener = null;
+ if (this.fToolRegistryListener != null) {
+ NicoUI.getToolRegistry().removeListener(this.fToolRegistryListener);
+ this.fToolRegistryListener = null;
}
- fReloadJob.cancel();
- final ToolProcess process = fProcess;
+ this.fReloadJob.cancel();
+ final ToolProcess process = this.fProcess;
if (process != null) {
- process.getHistory().removeListener(fContentProvider);
+ process.getHistory().removeListener(this.fContentProvider);
}
- fToolListenerList.clear();
- fProcess = null;
- fCopyAction = null;
- fSubmitAction = null;
- fLoadHistoryAction = null;
- fSaveHistoryAction = null;
- if (fSearchStartHandler != null) {
- fSearchStartHandler.dispose();
- fSearchStartHandler = null;
+ this.fToolListeners.clear();
+ this.fProcess = null;
+ this.fCopyAction = null;
+ this.fSubmitAction = null;
+ this.fLoadHistoryAction = null;
+ this.fSaveHistoryAction = null;
+ if (this.fSearchStartHandler != null) {
+ this.fSearchStartHandler.dispose();
+ this.fSearchStartHandler = null;
}
- if (fSearchPrevHandler != null) {
- fSearchPrevHandler.dispose();
- fSearchPrevHandler = null;
+ if (this.fSearchPrevHandler != null) {
+ this.fSearchPrevHandler.dispose();
+ this.fSearchPrevHandler = null;
}
- if (fSearchNextHandler != null) {
- fSearchNextHandler.dispose();
- fSearchNextHandler = null;
+ if (this.fSearchNextHandler != null) {
+ this.fSearchNextHandler.dispose();
+ this.fSearchNextHandler = null;
}
super.dispose();
- if (fClipboard != null) {
- fClipboard.dispose();
- fClipboard = null;
+ if (this.fClipboard != null) {
+ this.fClipboard.dispose();
+ this.fClipboard = null;
}
- fTable = null;
+ this.fTable = null;
}
}
diff --git a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/views/QueueView.java b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/views/QueueView.java
index ec4d265..f3b3b60 100644
--- a/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/views/QueueView.java
+++ b/r/org.eclipse.statet.nico.ui/src/org/eclipse/statet/nico/ui/views/QueueView.java
@@ -14,8 +14,6 @@
package org.eclipse.statet.nico.ui.views;
-import java.util.List;
-
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
@@ -52,6 +50,9 @@
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.part.ViewPart;
+import org.eclipse.statet.jcommons.collections.ImCollections;
+import org.eclipse.statet.jcommons.collections.ImList;
+
import org.eclipse.statet.ecommons.ts.core.ToolRunnable;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
@@ -75,16 +76,10 @@
public class QueueView extends ViewPart {
- private static ToolRunnable[] toArray(final IStructuredSelection selection) {
- final List<?> list = selection.toList();
- return list.toArray(new ToolRunnable[list.size()]);
- }
-
-
private class ViewContentProvider implements IStructuredContentProvider, IDebugEventSetListener {
- private volatile boolean fExpectInfoEvent = false;
- private ToolRunnable[] fRefreshData;
+ private volatile boolean expectInfoEvent= false;
+ private ImList<ToolRunnable> refreshData;
@Override
public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
@@ -92,9 +87,9 @@
unregister();
}
if (newInput != null) {
- final ToolProcess newProcess = (ToolProcess) newInput;
+ final ToolProcess newProcess= (ToolProcess) newInput;
- final DebugPlugin manager = DebugPlugin.getDefault();
+ final DebugPlugin manager= DebugPlugin.getDefault();
if (manager != null) {
manager.addDebugEventListener(this);
}
@@ -104,15 +99,15 @@
@Override
public Object[] getElements(final Object inputElement) {
ToolRunnable[] elements;
- if (fRefreshData != null) {
- elements = fRefreshData;
- fRefreshData = null;
+ if (this.refreshData != null) {
+ elements= this.refreshData.toArray(new ToolRunnable[this.refreshData.size()]);
+ this.refreshData= null;
}
else {
- elements = new ToolRunnable[0];
- final Queue queue = getQueue();
+ elements= new ToolRunnable[0];
+ final Queue queue= getQueue();
if (queue != null) {
- fExpectInfoEvent = true;
+ this.expectInfoEvent= true;
queue.sendElements();
}
}
@@ -120,7 +115,7 @@
}
private void unregister() {
- final DebugPlugin manager = DebugPlugin.getDefault();
+ final DebugPlugin manager= DebugPlugin.getDefault();
if (manager != null) {
manager.removeDebugEventListener(this);
}
@@ -131,30 +126,30 @@
unregister();
}
- private void setElements(final ToolRunnable[] elements) {
+ private void setElements(final ImList<ToolRunnable> elements) {
UIAccess.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
- if (!UIAccess.isOkToUse(fTableViewer)) {
+ if (!UIAccess.isOkToUse(QueueView.this.tableViewer)) {
return;
}
- fRefreshData = elements;
- fTableViewer.refresh();
+ ViewContentProvider.this.refreshData= elements;
+ QueueView.this.tableViewer.refresh();
}
});
}
@Override
public void handleDebugEvents(final DebugEvent[] events) {
- final ToolProcess process = fProcess;
+ final ToolProcess process= QueueView.this.process;
if (process == null) {
return;
}
- boolean updateProgress = false;
- final Queue queue = process.getQueue();
- EVENT: for (int i = 0; i < events.length; i++) {
- final DebugEvent event = events[i];
- final Object source = event.getSource();
+ boolean updateProgress= false;
+ final Queue queue= process.getQueue();
+ EVENT: for (int i= 0; i < events.length; i++) {
+ final DebugEvent event= events[i];
+ final Object source= event.getSource();
if (source == queue) {
switch (event.getKind()) {
@@ -162,21 +157,21 @@
if (event.getDetail() != DebugEvent.CONTENT) {
continue EVENT;
}
- final Queue.TaskDelta taskDelta = (Queue.TaskDelta) event.getData();
+ final Queue.TaskDelta taskDelta= (Queue.TaskDelta) event.getData();
switch (taskDelta.type) {
case ToolRunnable.ADDING_TO:
case ToolRunnable.MOVING_TO:
- if (!fExpectInfoEvent) {
+ if (!this.expectInfoEvent) {
if (events.length > i + 1 && taskDelta.data.size() == 1) {
// Added and removed in same set
- final DebugEvent next = events[i + 1];
+ final DebugEvent next= events[i + 1];
if (next.getSource() == queue
&& next.getKind() == DebugEvent.CHANGE
&& next.getDetail() == DebugEvent.CONTENT) {
- final Queue.TaskDelta nextDelta = (Queue.TaskDelta) next.getData();
+ final Queue.TaskDelta nextDelta= (Queue.TaskDelta) next.getData();
if (nextDelta.type == ToolRunnable.STARTING
&& taskDelta.data.get(0) == nextDelta.data.get(0)) {
- updateProgress = true;
+ updateProgress= true;
i++;
continue EVENT;
}
@@ -185,16 +180,16 @@
UIAccess.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
- if (!UIAccess.isOkToUse(fTableViewer)) {
+ if (!UIAccess.isOkToUse(QueueView.this.tableViewer)) {
return;
}
if (taskDelta.position >= 0) {
- for (int j = 0; j < taskDelta.data.size(); j++) {
- fTableViewer.insert(taskDelta.data.get(j), taskDelta.position + j);
+ for (int j= 0; j < taskDelta.data.size(); j++) {
+ QueueView.this.tableViewer.insert(taskDelta.data.get(j), taskDelta.position + j);
}
}
else {
- fTableViewer.add(taskDelta.data.toArray());
+ QueueView.this.tableViewer.add(taskDelta.data.toArray());
}
}
});
@@ -202,18 +197,18 @@
continue EVENT;
case ToolRunnable.STARTING:
- updateProgress = true;
+ updateProgress= true;
//$FALL-THROUGH$ continue with delete
case ToolRunnable.REMOVING_FROM:
case ToolRunnable.MOVING_FROM:
- if (!fExpectInfoEvent) {
+ if (!this.expectInfoEvent) {
UIAccess.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
- if (!UIAccess.isOkToUse(fTableViewer)) {
+ if (!UIAccess.isOkToUse(QueueView.this.tableViewer)) {
return;
}
- fTableViewer.remove(taskDelta.data.toArray());
+ QueueView.this.tableViewer.remove(taskDelta.data.toArray());
}
});
}
@@ -228,9 +223,9 @@
continue EVENT;
case DebugEvent.MODEL_SPECIFIC:
- if (event.getDetail() == Queue.QUEUE_INFO && fExpectInfoEvent) {
- fExpectInfoEvent = false;
- setElements((ToolRunnable[]) event.getData());
+ if (event.getDetail() == Queue.QUEUE_INFO && this.expectInfoEvent) {
+ this.expectInfoEvent= false;
+ setElements((ImList<ToolRunnable>) event.getData());
}
continue EVENT;
@@ -243,8 +238,8 @@
}
}
}
- if (updateProgress && fShowProgress) {
- final ToolProgressGroup progress = fProgressControl;
+ if (updateProgress && QueueView.this.showProgress) {
+ final ToolProgressGroup progress= QueueView.this.progressControl;
if (progress != null) {
progress.refresh(false);
}
@@ -277,7 +272,7 @@
@Override
public String getText(final Object element) {
- final ToolRunnable runnable = (ToolRunnable) element;
+ final ToolRunnable runnable= (ToolRunnable) element;
return runnable.getLabel();
}
}
@@ -287,13 +282,13 @@
public ShowDescriptionAction() {
setText(Messages.ShowToolDescription_name);
setToolTipText(Messages.ShowToolDescription_tooltip);
- setChecked(fShowDescription);
+ setChecked(QueueView.this.showDescription);
}
@Override
public void run() {
- fShowDescription = isChecked();
- updateContentDescription(fProcess);
+ QueueView.this.showDescription= isChecked();
+ updateContentDescription(QueueView.this.process);
}
}
@@ -302,45 +297,45 @@
public ShowProgressAction() {
setText(Messages.ShowProgress_name);
setToolTipText(Messages.ShowProgress_tooltip);
- setChecked(fShowProgress);
+ setChecked(QueueView.this.showProgress);
}
@Override
public void run() {
- fShowProgress = isChecked();
- if (fShowProgress) {
+ QueueView.this.showProgress= isChecked();
+ if (QueueView.this.showProgress) {
createProgressControl();
- fProgressControl.setTool(fProcess, true);
- fProgressControl.getControl().moveAbove(fTableViewer.getControl());
+ QueueView.this.progressControl.setTool(QueueView.this.process, true);
+ QueueView.this.progressControl.getControl().moveAbove(QueueView.this.tableViewer.getControl());
}
else {
- if (fProgressControl != null) {
- fProgressControl.getControl().dispose();
- fProgressControl = null;
+ if (QueueView.this.progressControl != null) {
+ QueueView.this.progressControl.getControl().dispose();
+ QueueView.this.progressControl= null;
}
}
- fComposite.layout(true);
+ QueueView.this.composite.layout(true);
}
}
- private Composite fComposite;
- private ToolProgressGroup fProgressControl;
- private TableViewer fTableViewer;
+ private Composite composite;
+ private ToolProgressGroup progressControl;
+ private TableViewer tableViewer;
- private ToolProcess fProcess;
- private IToolRegistryListener fToolRegistryListener;
+ private ToolProcess process;
+ private IToolRegistryListener toolRegistryListener;
- private static final String M_SHOW_DESCRIPTION = "QueueView.ShowDescription"; //$NON-NLS-1$
- private boolean fShowDescription;
- private Action fShowDescriptionAction;
+ private static final String M_SHOW_DESCRIPTION= "QueueView.ShowDescription"; //$NON-NLS-1$
+ private boolean showDescription;
+ private Action showDescriptionAction;
- private static final String M_SHOW_PROGRESS = "QueueView.ShowProgress"; //$NON-NLS-1$
- private boolean fShowProgress;
- private Action fShowProgressAction;
+ private static final String M_SHOW_PROGRESS= "QueueView.ShowProgress"; //$NON-NLS-1$
+ private boolean showProgress;
+ private Action showProgressAction;
- private Action fSelectAllAction;
- private Action fDeleteAction;
+ private Action selectAllAction;
+ private Action deleteAction;
public QueueView() {
@@ -351,18 +346,18 @@
public void init(final IViewSite site, final IMemento memento) throws PartInitException {
super.init(site, memento);
- final String showDescription = (memento != null) ? memento.getString(M_SHOW_DESCRIPTION) : null;
+ final String showDescription= (memento != null) ? memento.getString(M_SHOW_DESCRIPTION) : null;
if (showDescription == null || showDescription.equals("off")) { // default //$NON-NLS-1$
- fShowDescription = false;
+ this.showDescription= false;
} else {
- fShowDescription = true;
+ this.showDescription= true;
}
- final String showProgress = (memento != null) ? memento.getString(M_SHOW_PROGRESS) : null;
+ final String showProgress= (memento != null) ? memento.getString(M_SHOW_PROGRESS) : null;
if (showProgress== null || showProgress.equals("on")) { // default //$NON-NLS-1$
- fShowProgress = true;
+ this.showProgress= true;
} else {
- fShowProgress = false;
+ this.showProgress= false;
}
}
@@ -370,55 +365,55 @@
public void saveState(final IMemento memento) {
super.saveState(memento);
- memento.putString(M_SHOW_DESCRIPTION, (fShowDescription) ? "on" : "off"); //$NON-NLS-1$ //$NON-NLS-2$
- memento.putString(M_SHOW_PROGRESS, (fShowProgress) ? "on" : "off"); //$NON-NLS-1$ //$NON-NLS-2$
+ memento.putString(M_SHOW_DESCRIPTION, (this.showDescription) ? "on" : "off"); //$NON-NLS-1$ //$NON-NLS-2$
+ memento.putString(M_SHOW_PROGRESS, (this.showProgress) ? "on" : "off"); //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public void createPartControl(final Composite parent) {
updateContentDescription(null);
- fComposite = parent;
- final GridLayout layout = new GridLayout();
- layout.marginHeight = 0;
- layout.marginWidth = 0;
- layout.verticalSpacing = 0;
+ this.composite= parent;
+ final GridLayout layout= new GridLayout();
+ layout.marginHeight= 0;
+ layout.marginWidth= 0;
+ layout.verticalSpacing= 0;
parent.setLayout(layout);
- if (fShowProgress) {
+ if (this.showProgress) {
createProgressControl();
}
- fTableViewer = new TableViewer(parent, SWT.MULTI | SWT.V_SCROLL);
- fTableViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- fTableViewer.getTable().setLinesVisible(false);
- fTableViewer.getTable().setHeaderVisible(false);
- new TableColumn(fTableViewer.getTable(), SWT.DEFAULT);
- fTableViewer.getTable().addControlListener(new ControlAdapter() {
+ this.tableViewer= new TableViewer(parent, SWT.MULTI | SWT.V_SCROLL);
+ this.tableViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ this.tableViewer.getTable().setLinesVisible(false);
+ this.tableViewer.getTable().setHeaderVisible(false);
+ new TableColumn(this.tableViewer.getTable(), SWT.DEFAULT);
+ this.tableViewer.getTable().addControlListener(new ControlAdapter() {
@Override
public void controlResized(final ControlEvent e) {
// adapt the column width to the width of the table
- final Table table = fTableViewer.getTable();
- final Rectangle area = table.getClientArea();
- final TableColumn column = table.getColumn(0);
+ final Table table= QueueView.this.tableViewer.getTable();
+ final Rectangle area= table.getClientArea();
+ final TableColumn column= table.getColumn(0);
column.setWidth(area.width-3); // it looks better with a small gap
}
});
- fTableViewer.setContentProvider(new ViewContentProvider());
- fTableViewer.setLabelProvider(new TableLabelProvider());
+ this.tableViewer.setContentProvider(new ViewContentProvider());
+ this.tableViewer.setLabelProvider(new TableLabelProvider());
createActions();
contributeToActionBars();
hookDND();
// listen on console changes
- final IToolRegistry toolRegistry = NicoUI.getToolRegistry();
+ final IToolRegistry toolRegistry= NicoUI.getToolRegistry();
connect(toolRegistry.getActiveToolSession(getViewSite().getPage()).getProcess());
- fToolRegistryListener = new IToolRegistryListener() {
+ this.toolRegistryListener= new IToolRegistryListener() {
@Override
public void toolSessionActivated(final ToolSessionUIData sessionData) {
- final ToolProcess process = sessionData.getProcess();
+ final ToolProcess process= sessionData.getProcess();
UIAccess.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
@@ -431,18 +426,18 @@
// handled by debug events
}
};
- toolRegistry.addListener(fToolRegistryListener, getViewSite().getPage());
+ toolRegistry.addListener(this.toolRegistryListener, getViewSite().getPage());
}
private void createProgressControl() {
- fProgressControl = new ToolProgressGroup(fComposite);
- fProgressControl.getControl().setLayoutData(
+ this.progressControl= new ToolProgressGroup(this.composite);
+ this.progressControl.getControl().setLayoutData(
new GridData(SWT.FILL, SWT.FILL, true, false));
}
protected void updateContentDescription(final ToolProcess process) {
- if (fShowDescription) {
+ if (this.showDescription) {
setContentDescription(process != null ? process.getLabel(0) : " "); //$NON-NLS-1$
}
else {
@@ -451,40 +446,40 @@
}
private void createActions() {
- fShowDescriptionAction = new ShowDescriptionAction();
- fShowProgressAction = new ShowProgressAction();
+ this.showDescriptionAction= new ShowDescriptionAction();
+ this.showProgressAction= new ShowProgressAction();
- fSelectAllAction = new Action() {
+ this.selectAllAction= new Action() {
@Override
public void run() {
- fTableViewer.getTable().selectAll();
+ QueueView.this.tableViewer.getTable().selectAll();
}
};
- fDeleteAction = new Action() {
+ this.deleteAction= new Action() {
@Override
public void run() {
- final Queue queue = getQueue();
+ final Queue queue= getQueue();
if (queue != null) {
- final IStructuredSelection selection = (IStructuredSelection) fTableViewer.getSelection();
- queue.remove(toArray(selection));
+ final IStructuredSelection selection= (IStructuredSelection) QueueView.this.tableViewer.getSelection();
+ queue.remove(ImCollections.toList(selection.toList()));
}
}
};
}
private void contributeToActionBars() {
- final IActionBars bars = getViewSite().getActionBars();
+ final IActionBars bars= getViewSite().getActionBars();
- bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), fSelectAllAction);
- bars.setGlobalActionHandler(ActionFactory.DELETE.getId(), fDeleteAction);
+ bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), this.selectAllAction);
+ bars.setGlobalActionHandler(ActionFactory.DELETE.getId(), this.deleteAction);
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
}
private void fillLocalPullDown(final IMenuManager manager) {
- manager.add(fShowDescriptionAction);
- manager.add(fShowProgressAction);
+ manager.add(this.showDescriptionAction);
+ manager.add(this.showProgressAction);
}
private void fillLocalToolBar(final IToolBarManager manager) {
@@ -496,29 +491,30 @@
}
private void hookDND() {
- fTableViewer.addDragSupport(DND.DROP_MOVE,
- new Transfer[] { LocalTaskTransfer.getTransfer() },
- new TableDragSourceEffect(fTableViewer.getTable()) {
+ this.tableViewer.addDragSupport(DND.DROP_MOVE,
+ new Transfer[] { LocalTaskTransfer.getTransfer() },
+ new TableDragSourceEffect(this.tableViewer.getTable()) {
@Override
public void dragStart(final DragSourceEvent event) {
- if (fTableViewer.getTable().getSelectionCount() > 0) {
- event.doit = true;
+ if (QueueView.this.tableViewer.getTable().getSelectionCount() > 0) {
+ event.doit= true;
} else {
- event.doit = false;
+ event.doit= false;
}
- LocalTaskTransfer.getTransfer().init(fProcess);
+ LocalTaskTransfer.getTransfer().init(QueueView.this.process);
super.dragStart(event);
}
@Override
public void dragSetData(final DragSourceEvent event) {
super.dragSetData(event);
- final LocalTaskTransfer.Data data = LocalTaskTransfer.getTransfer().createData();
- if (data.process != fProcess) {
- event.doit = false;
+ final LocalTaskTransfer.Data data= LocalTaskTransfer.getTransfer().createData();
+ if (data.process != QueueView.this.process) {
+ event.doit= false;
return;
}
- data.runnables = toArray((IStructuredSelection) fTableViewer.getSelection());
- event.data = data;
+ data.runnables= ImCollections.toList(
+ ((IStructuredSelection) QueueView.this.tableViewer.getSelection()).toList() );
+ event.data= data;
}
@Override
public void dragFinished(final DragSourceEvent event) {
@@ -532,7 +528,7 @@
UIAccess.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
- if (fProcess != null && fProcess == process) {
+ if (QueueView.this.process != null && QueueView.this.process == process) {
connect(null);
}
}
@@ -541,18 +537,18 @@
/** May only be called in UI thread */
public void connect(final ToolProcess process) {
- final Runnable runnable = new Runnable() {
+ final Runnable runnable= new Runnable() {
@Override
public void run() {
- if (!UIAccess.isOkToUse(fTableViewer)) {
+ if (!UIAccess.isOkToUse(QueueView.this.tableViewer)) {
return;
}
- fProcess = process;
+ QueueView.this.process= process;
updateContentDescription(process);
- if (fProgressControl != null) {
- fProgressControl.setTool(process, true);
+ if (QueueView.this.progressControl != null) {
+ QueueView.this.progressControl.setTool(process, true);
}
- fTableViewer.setInput(process);
+ QueueView.this.tableViewer.setInput(process);
}
};
BusyIndicator.showWhile(UIAccess.getDisplay(), runnable);
@@ -564,12 +560,12 @@
* @return a tool process or <code>null</code>, if no process is connected.
*/
public ToolProcess getProcess() {
- return fProcess;
+ return this.process;
}
public Queue getQueue() {
- if (fProcess != null) {
- return fProcess.getQueue();
+ if (this.process != null) {
+ return this.process.getQueue();
}
return null;
}
@@ -578,7 +574,7 @@
@Override
public void setFocus() {
// Passing the focus request to the viewer's control.
- fTableViewer.getControl().setFocus();
+ this.tableViewer.getControl().setFocus();
}
@Override
diff --git a/r/org.eclipse.statet.r.apps/.classpath b/r/org.eclipse.statet.r.apps/.classpath
new file mode 100644
index 0000000..7728a88
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/.classpath
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+ <attributes>
+ <attribute name="annotationpath" value="/org.eclipse.statet/eea/"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
+ <attributes>
+ <attribute name="annotationpath" value="/org.eclipse.statet/eea/"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/r/org.eclipse.statet.r.apps/.gitignore b/r/org.eclipse.statet.r.apps/.gitignore
new file mode 100644
index 0000000..5e56e04
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/r/org.eclipse.statet.r.apps/.project b/r/org.eclipse.statet.r.apps/.project
new file mode 100644
index 0000000..90e3c6b
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.statet.r.apps</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
diff --git a/r/org.eclipse.statet.r.apps/.settings/org.eclipse.core.resources.prefs b/r/org.eclipse.statet.r.apps/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..99f26c0
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/r/org.eclipse.statet.r.apps/.settings/org.eclipse.core.runtime.prefs b/r/org.eclipse.statet.r.apps/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..5a0ad22
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/r/org.eclipse.statet.r.apps/.settings/org.eclipse.jdt.core.prefs b/r/org.eclipse.statet.r.apps/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..ccb1eaa
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,325 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=85
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0
+org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=2
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=2
+org.eclipse.jdt.core.formatter.blank_lines_before_package=1
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=100
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=false
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=100
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=false
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/r/org.eclipse.statet.r.apps/.settings/org.eclipse.jdt.ui.prefs b/r/org.eclipse.statet.r.apps/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..e62a4f5
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,131 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=true
+cleanup.always_use_this_for_non_static_field_access=true
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_functional_interfaces=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.insert_inferred_type_arguments=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=true
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=true
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=false
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=false
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_redundant_type_arguments=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_anonymous_class_creation=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_lambda=true
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=true
+cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+cleanup.use_this_for_non_static_method_access=true
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup.use_type_arguments=false
+cleanup_profile=_StatET
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_StatET
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=\#;java;javax;com.ibm.icu;org.osgi;org.eclipse;;org.eclipse.statet.jcommons;org.eclipse.statet.ecommons;org.eclipse.statet;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=true
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\#\n \# Copyright (c) ${year} ${user} and others.\n # \n # This program and the accompanying materials are made available under the\n # terms of the Eclipse Public License 2.0 which is available at\n # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0\n # which is available at https://www.apache.org/licenses/LICENSE-2.0.\n # \n # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0\n # \n \# Contributors\:\n \# ${user} - initial API and implementation\n \#\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=*/</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * \n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment"/><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="false" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=true
+sp_cleanup.always_use_this_for_non_static_field_access=true
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=false
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_trailing_whitespaces=false
+sp_cleanup.remove_trailing_whitespaces_all=false
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=true
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=false
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=false
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=true
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false
+sp_cleanup.use_this_for_non_static_method_access=true
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
diff --git a/r/org.eclipse.statet.r.apps/META-INF/MANIFEST.MF b/r/org.eclipse.statet.r.apps/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..2edec13
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/META-INF/MANIFEST.MF
@@ -0,0 +1,26 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.statet.r.apps;singleton:=true
+Bundle-Version: 3.6.0.qualifier
+Bundle-Vendor: Eclipse.org
+Bundle-Name: StatET R - Add-on for R Apps
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.statet.internal.r.apps.ui.RAppUIPlugin
+Bundle-Localization: plugin
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.eclipse.statet.ide.ui;bundle-version="[4.0.0,4.1.0)",
+ org.eclipse.core.variables,
+ org.eclipse.ui.browser,
+ org.eclipse.statet.ecommons.debug.ui,
+ org.eclipse.statet.ltk.ui,
+ org.eclipse.statet.r.ui,
+ org.eclipse.statet.ecommons.coremisc,
+ org.eclipse.statet.ecommons.debug.core,
+ org.eclipse.statet.r.console.core,
+ org.eclipse.statet.nico.core,
+ org.eclipse.statet.nico.ui
+Import-Package: com.jcraft.jsch,
+ org.eclipse.statet.ecommons.databinding.core.validation;version="4.0.0",
+ org.eclipse.statet.jcommons.collections;version="4.0.0",
+ org.eclipse.statet.jcommons.lang;version="4.0.0"
+Export-Package: org.eclipse.statet.r.apps.ui
diff --git a/r/org.eclipse.statet.r.apps/about.html b/r/org.eclipse.statet.r.apps/about.html
new file mode 100644
index 0000000..e71ae66
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/about.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>December 1, 2017</p>
+<h3>License</h3>
+
+<p>
+ The Eclipse Foundation makes available all content in this plug-in
+ ("Content"). Unless otherwise indicated below, the Content
+ is provided to you under the terms and conditions of the Eclipse
+ Public License Version 2.0 ("EPL"), or the Apache License,
+ Version 2.0 (AL). A copy of the EPL is available at <a href="https://www.eclipse.org/legal/epl-2.0">https://www.eclipse.org/legal/epl-2.0</a>.
+ For purposes of the EPL, "Program" will mean the Content.
+ A copy of the AL is available at <a href="https://www.apache.org/licenses/LICENSE-2.0">https://www.apache.org/licenses/LICENSE-2.0</a>.
+</p>
+
+<p>
+ If you did not receive this Content directly from the Eclipse
+ Foundation, the Content is being redistributed by another party
+ ("Redistributor") and different terms and conditions may
+ apply to your use of any object code in the Content. Check the
+ Redistributor's license that was provided with the Content. If no such
+ license exists, contact the Redistributor. Unless otherwise indicated
+ below, the terms and conditions of the EPL or AL still apply to any
+ source code in the Content and such source code may be obtained at <a
+ href="https://www.eclipse.org/">https://www.eclipse.org</a>.
+</p>
+
+</body>
+</html>
diff --git a/r/org.eclipse.statet.r.apps/build.properties b/r/org.eclipse.statet.r.apps/build.properties
new file mode 100644
index 0000000..976d098
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/build.properties
@@ -0,0 +1,11 @@
+source..= src/
+output..= bin/
+javacDefaultEncoding..= UTF-8
+
+bin.includes= META-INF/,\
+ plugin.xml,\
+ plugin.properties,\
+ .,\
+ icons/,\
+ about.html
+src.includes= .settings/org.eclipse.core.resources.prefs
diff --git a/r/org.eclipse.statet.r.apps/icons/obj_16/r_app.png b/r/org.eclipse.statet.r.apps/icons/obj_16/r_app.png
new file mode 100644
index 0000000..a40d16b
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/icons/obj_16/r_app.png
Binary files differ
diff --git a/r/org.eclipse.statet.r.apps/icons/tool_16/run-r_app.png b/r/org.eclipse.statet.r.apps/icons/tool_16/run-r_app.png
new file mode 100644
index 0000000..d607896
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/icons/tool_16/run-r_app.png
Binary files differ
diff --git a/r/org.eclipse.statet.r.apps/icons/tool_16/view-app.png b/r/org.eclipse.statet.r.apps/icons/tool_16/view-app.png
new file mode 100644
index 0000000..b7dcb79
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/icons/tool_16/view-app.png
Binary files differ
diff --git a/r/org.eclipse.statet.r.apps/icons/view_16/r_app_var_browser.png b/r/org.eclipse.statet.r.apps/icons/view_16/r_app_var_browser.png
new file mode 100644
index 0000000..270cc7a
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/icons/view_16/r_app_var_browser.png
Binary files differ
diff --git a/r/org.eclipse.statet.r.apps/plugin.properties b/r/org.eclipse.statet.r.apps/plugin.properties
new file mode 100644
index 0000000..1b598fd
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/plugin.properties
@@ -0,0 +1,23 @@
+ #=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================#
+
+launchConfigurations_RApp_name= R App
+
+launchShortcuts_RShinyApp_name= R Shiny App
+commands_RunApp_name= Run R App
+commands_RunApp_description= Runs the R app of the active editor (active configuration)
+toolbars_AppTools_label= R App Tools\u2002[StatET]
+
+views_AppViewer_name= R App Viewer
+views_AppVarBrowser_name= R App Variables
diff --git a/r/org.eclipse.statet.r.apps/plugin.xml b/r/org.eclipse.statet.r.apps/plugin.xml
new file mode 100644
index 0000000..0238068
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/plugin.xml
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<!--
+ #=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================#
+-->
+
+<plugin>
+
+ <extension
+ point="org.eclipse.core.resources.natures"
+ id="org.eclipse.statet.r.apps.resourceProjects.RApp"
+ name="R App [StatET]">
+ <requires-nature
+ id="org.eclipse.statet.r.resourceProjects.R"/>
+ <runtime>
+ <run
+ class="org.eclipse.statet.intern.r.apps.core.RAppProject"/>
+ </runtime>
+ </extension>
+
+ <extension
+ point="org.eclipse.core.expressions.propertyTesters">
+ <propertyTester
+ id="org.eclipse.statet.r.apps.expressionProperties.RShinyResources"
+ namespace="org.eclipse.statet.r.apps"
+ properties="isRShinyAppResource"
+ type="org.eclipse.core.resources.IResource"
+ class="org.eclipse.statet.internal.r.apps.core.shiny.RShinyResourceTester">
+ </propertyTester>
+ </extension>
+ <extension
+ point="org.eclipse.core.expressions.definitions">
+ <definition
+ id="org.eclipse.statet.r.apps.expressions.isEditorInputActive.RShinyResource">
+ <with
+ variable="activeEditorInput">
+ <adapt
+ type="org.eclipse.core.resources.IResource">
+ <test
+ property="org.eclipse.core.resources.projectNature"
+ value="org.eclipse.statet.r.resourceProjects.R"/>
+ <or>
+ <test
+ property="org.eclipse.core.resources.projectNature"
+ value="org.eclipse.statet.r.apps.resourceProjects.RApp"/>
+ <test
+ property="org.eclipse.statet.r.apps.isRShinyAppResource"
+ forcePluginActivation="true"/>
+ </or>
+ </adapt>
+ </with>
+ </definition>
+ <definition
+ id="org.eclipse.statet.r.apps.expressions.isSelectionActive.RShinyResource">
+ <with
+ variable="selection">
+ <count
+ value="1"/>
+ <iterate>
+ <adapt
+ type="org.eclipse.core.resources.IResource">
+ <test
+ property="org.eclipse.core.resources.projectNature"
+ value="org.eclipse.statet.r.resourceProjects.R"/>
+ <or>
+ <test
+ property="org.eclipse.core.resources.projectNature"
+ value="org.eclipse.statet.r.apps.resourceProjects.RApp"/>
+ <test
+ property="org.eclipse.statet.r.apps.isRShinyAppResource"
+ forcePluginActivation="true"/>
+ </or>
+ </adapt>
+ </iterate>
+ </with>
+ </definition>
+ </extension>
+
+ <extension
+ point="org.eclipse.statet.ecommons.ts.UIDecorators">
+ <runnable
+ typeId="org.eclipse.statet.r.apps/RunApp"
+ icon="icons/obj_16/r_app.png">
+ </runnable>
+
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.core.launchConfigurationTypes">
+ <launchConfigurationType
+ id="org.eclipse.statet.r.apps.launchConfigurations.RAppControl"
+ name="%launchConfigurations_RApp_name"
+ modes="run"
+ delegate="org.eclipse.statet.internal.r.apps.ui.launching.AppControlLaunchDelegate">
+ </launchConfigurationType>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.ui.launchConfigurationTypeImages">
+ <launchConfigurationTypeImage
+ id="org.eclipse.statet.r.images.RApp"
+ configTypeID="org.eclipse.statet.r.apps.launchConfigurations.RAppControl"
+ icon="icons/obj_16/r_app.png">
+ </launchConfigurationTypeImage>
+ </extension>
+ <extension
+ point="org.eclipse.debug.ui.launchConfigurationTabGroups">
+ <launchConfigurationTabGroup
+ id="org.eclipse.statet.r.apps.launchConfigurationTabGroups.RAppControl"
+ type="org.eclipse.statet.r.apps.launchConfigurations.RAppControl"
+ class="org.eclipse.statet.internal.r.apps.ui.launching.AppControlConfigTabGroup">
+ </launchConfigurationTabGroup>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.ui.launchShortcuts">
+ <shortcut
+ id="org.eclipse.statet.r.launchShortcuts.RShinyApp"
+ label="%launchShortcuts_RShinyApp_name"
+ icon="icons/tool_16/run-r_app.png"
+ class="org.eclipse.statet.internal.r.apps.ui.shiny.actions.AppLaunchShortcut"
+ modes="run">
+ <configurationType
+ id="org.eclipse.statet.r.apps.launchConfigurations.RAppControl"/>
+ <contextualLaunch>
+ <enablement>
+ <reference
+ definitionId="org.eclipse.statet.r.apps.expressions.isSelectionActive.RShinyResource"/>
+ </enablement>
+ </contextualLaunch>
+ </shortcut>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.commands">
+ <command
+ id="org.eclipse.statet.r.apps.commands.RunAppDefault"
+ categoryId="org.eclipse.debug.ui.category.run"
+ name="%commands_RunApp_name"
+ description="%commands_RunApp_description">
+ </command>
+ </extension>
+ <extension
+ point="org.eclipse.ui.commandImages">
+ <image
+ commandId="org.eclipse.statet.r.apps.commands.RunAppDefault"
+ icon="icons/tool_16/run-r_app.png">
+ </image>
+ </extension>
+ <extension
+ point="org.eclipse.ui.handlers">
+ <handler
+ commandId="org.eclipse.statet.r.apps.commands.RunAppDefault"
+ class="org.eclipse.statet.internal.r.apps.ui.shiny.actions.RunActiveAppConfigWorkbenchHandler">
+ <activeWhen>
+ <reference
+ definitionId="org.eclipse.statet.r.apps.expressions.isEditorInputActive.RShinyResource"/>
+ </activeWhen>
+ </handler>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.bindings">
+ <key
+ commandId="org.eclipse.statet.r.apps.commands.RunAppDefault"
+ contextId="org.eclipse.ui.contexts.window"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="M1+R A">
+ </key>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.menus">
+ <menuContribution
+ locationURI="toolbar:org.eclipse.ui.main.toolbar?before=org.eclipse.ui.workbench.navigate">
+ <toolbar
+ id="org.eclipse.statet.r.apps.menus.AppTools"
+ label="%toolbars_AppTools_label">
+ <separator
+ name="run_app"
+ visible="false">
+ </separator>
+ <command
+ id="org.eclipse.statet.r.apps.menus.RunApp"
+ commandId="org.eclipse.statet.r.apps.commands.RunAppDefault"
+ style="pulldown">
+ <visibleWhen>
+ <reference
+ definitionId="org.eclipse.statet.r.apps.expressions.isEditorInputActive.RShinyResource"/>
+ </visibleWhen>
+ </command>
+ <separator
+ name="additions"
+ visible="false">
+ </separator>
+ </toolbar>
+ </menuContribution>
+ <menuContribution
+ locationURI="menu:org.eclipse.statet.r.apps.menus.RunApp">
+ <dynamic
+ id="org.eclipse.statet.r.apps.menus.RunAppItems"
+ class="org.eclipse.statet.internal.r.apps.ui.shiny.actions.RunAppConfigsDropdownContribution">
+ </dynamic>
+ <separator
+ name="additions"
+ visible="true">
+ </separator>
+ </menuContribution>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.views">
+ <view
+ id="org.eclipse.statet.r.apps.views.AppViewer"
+ category="org.eclipse.statet.workbench.views.StatetCategory"
+ name="%views_AppViewer_name"
+ icon="icons/obj_16/r_app.png"
+ class="org.eclipse.statet.internal.r.apps.ui.viewer.AppBrowserView"
+ restorable="true">
+ </view>
+ </extension>
+ <extension
+ point="org.eclipse.ui.views">
+ <view
+ id="org.eclipse.statet.r.apps.views.VariableViewer"
+ category="org.eclipse.statet.workbench.views.StatetCategory"
+ name="%views_AppVarBrowser_name"
+ icon="icons/view_16/r_app_var_browser.png"
+ class="org.eclipse.statet.internal.r.apps.ui.variables.AppVarView"
+ restorable="true">
+ </view>
+ </extension>
+
+</plugin>
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/intern/r/apps/core/RAppProject.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/intern/r/apps/core/RAppProject.java
new file mode 100644
index 0000000..22cac35
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/intern/r/apps/core/RAppProject.java
@@ -0,0 +1,55 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.intern.r.apps.core;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectNature;
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+
+@NonNullByDefault
+public class RAppProject implements IProjectNature {
+
+
+ private IProject project;
+
+
+ /** plugin.xml */
+ @SuppressWarnings("null")
+ public RAppProject() {
+ }
+
+
+ @Override
+ public void setProject(final IProject project) {
+ this.project= project;
+ }
+
+ @Override
+ public final IProject getProject() {
+ return this.project;
+ }
+
+ @Override
+ public void configure() throws CoreException {
+ }
+
+ @Override
+ public void deconfigure() throws CoreException {
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/core/shiny/RShinyResourceTester.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/core/shiny/RShinyResourceTester.java
new file mode 100644
index 0000000..8591350
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/core/shiny/RShinyResourceTester.java
@@ -0,0 +1,121 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.core.shiny;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+
+@NonNullByDefault
+public class RShinyResourceTester extends PropertyTester {
+
+
+ private static final IPath APP_FILE_PATH= new Path("app.R"); //$NON-NLS-1$
+
+ private static final IPath UI_FILE_PATH= new Path("ui.R"); //$NON-NLS-1$
+ private static final IPath SERVER_FILE_PATH= new Path("server.R"); //$NON-NLS-1$
+
+
+ @SuppressWarnings("null")
+ private static final IContainer getContainer(final IResource resource) {
+ return (resource instanceof IContainer) ?
+ (IContainer) resource :
+ resource.getParent();
+ }
+
+ public static final boolean isAppContainer(final IContainer container) {
+ return (((container.getFile(SERVER_FILE_PATH).exists()
+ && container.getFile(UI_FILE_PATH).exists() )
+ || (container.getFile(APP_FILE_PATH).exists()) ));
+ }
+
+ public static final @Nullable IContainer getAppContainer(IContainer container) {
+ while (true) {
+ if (isAppContainer(container)) {
+ return container;
+ }
+ if (container.getType() == IResource.FOLDER) {
+ container= container.getParent();
+ continue;
+ }
+ return null;
+ }
+ }
+
+// public static final IContainer getContainingShinyContainer(IContainer container) {
+// try {
+// container.accept(new IResourceVisitor() {
+// IContainer appContainer;
+// @Override
+// public boolean visit(final IResource resource) throws CoreException {
+// if (resource.getType() == IResource.FOLDER
+// || resource.getType() == IResource.PROJECT) {
+// if (isShinyContainer((IContainer) resource)) {
+// if (this.appContainer != null) {
+//
+// }
+// this.appContainer= (IContainer) resource;
+// return false;
+// }
+// return true;
+// }
+// return false;
+// }
+// });
+// }
+// catch (final CoreException e) {
+// return null;
+// }
+// }
+
+ public static final boolean isInsideAppContainer(final IResource resource) {
+ return (getAppContainer(getContainer(resource)) != null);
+ }
+
+ public static final @Nullable IContainer getAppContainer(final IResource resource) {
+ return getAppContainer(getContainer(resource));
+ }
+
+
+ /** plugin.xml */
+ public RShinyResourceTester() {
+ }
+
+
+ @Override
+ public boolean test(final Object receiver,
+ final String property, final Object[] args, final @Nullable Object expectedValue) {
+ if (receiver instanceof IResource) {
+ final IResource resource= (IResource) receiver;
+ switch (property) {
+ case "isAppResource": //$NON-NLS-1$
+// System.out.println("isAppResource" + resource.getFullPath() + "= " + isInsideAppContainer(resource));
+ return (isInsideAppContainer(resource));
+// case "containsApp": //$NON-NLS-1$
+ default:
+ break;
+ }
+ }
+ return false;
+ }
+
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/Messages.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/Messages.java
new file mode 100644
index 0000000..d3ad6ca
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/Messages.java
@@ -0,0 +1,71 @@
+/*=============================================================================#
+ # Copyright (c) 2007, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui;
+
+import org.eclipse.osgi.util.NLS;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+
+@NonNullByDefault
+@SuppressWarnings("null")
+public class Messages extends NLS {
+
+
+ public static String Variable_AppHost_description;
+ public static String Variable_AppPort_description;
+
+ public static String RunAction_RunApp_label;
+
+ public static String Operation_MainTab_name;
+
+ public static String Operation_MainTab_AppFolder_label;
+ public static String Operation_AppFolder_info;
+
+ public static String Operation_MainTab_AppAddress_group;
+ public static String Operation_MainTab_AppHost_label;
+ public static String Operation_AppHost_info;
+ public static String Operation_MainTab_AppPort_label;
+ public static String Operation_AppPort_error_SpecInvalid_message;
+ public static String Operation_AppPort_info;
+
+ public static String Operation_MainTab_Start_group;
+ public static String Operation_StartApp_RCode_label;
+ public static String Operation_StartApp_RCode_error_SpecMissing_message;
+ public static String Operation_StartApp_RCode_error_SpecInvalid_message;
+ public static String Operation_StopApp_RCode_label;
+ public static String Operation_StartApp_StopRunningApp_label;
+
+ public static String Operation_ViewTab_name;
+ public static String Operation_ViewTab_label;
+ public static String Operation_ViewTab_Operation_label;
+ public static String Operation_Viewer_None_label;
+ public static String Operation_Viewer_WorkbenchExternal_label;
+ public static String Operation_Viewer_WorkbenchView_label;
+ public static String Operation_Viewer_error_Run_message;
+ public static String Operation_Variables_label;
+ public static String Operation_Variables_ShowView_label;
+ public static String Operation_Variables_error_Run_message;
+
+ public static String Action_RestartApp_label;
+ public static String Action_StopApp_label;
+
+
+ static {
+ NLS.initializeMessages(Messages.class.getName(), Messages.class);
+ }
+ private Messages() {}
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/Messages.properties b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/Messages.properties
new file mode 100644
index 0000000..2be577a
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/Messages.properties
@@ -0,0 +1,51 @@
+ #=============================================================================#
+ # Copyright (c) 2007, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================#
+
+Variable_AppHost_description= Returns the specific host of the app address.
+Variable_AppPort_description= Returns the specific port of the app address.
+
+RunAction_RunApp_label= &Run App
+
+Operation_MainTab_name= &Main
+
+Operation_MainTab_AppFolder_label= App &folder
+Operation_AppFolder_info= (empty= selected resource)
+
+Operation_MainTab_AppAddress_group= Network Address:
+Operation_MainTab_AppHost_label= &Host
+Operation_AppHost_info= (empty= automatic)
+Operation_MainTab_AppPort_label= &Port
+Operation_AppPort_error_SpecInvalid_message= Invalid port number specified (0-65535).
+Operation_AppPort_info= (empty= automatic)
+
+Operation_MainTab_Start_group= App Start:
+Operation_StartApp_RCode_label= R code to r&un the app
+Operation_StartApp_RCode_error_SpecMissing_message= The spec of R code snippet is missing.
+Operation_StartApp_RCode_error_SpecInvalid_message= In spec of R code snippet, {0}
+Operation_StartApp_StopRunningApp_label= S&top app already running in R
+Operation_StopApp_RCode_label= R code to st&op the app
+
+Operation_ViewTab_name= &View
+Operation_ViewTab_label= Show app when started
+Operation_ViewTab_Operation_label= View &Operation
+Operation_Viewer_None_label=
+Operation_Viewer_WorkbenchExternal_label= Open app in external web browser
+Operation_Viewer_WorkbenchView_label= Open app in Eclipse view
+Operation_Viewer_error_Run_message= An error occurred when opening viewer to show the app.
+Operation_Variables_label= R App Variables (Reactive Variables)
+Operation_Variables_ShowView_label= &Show view
+Operation_Variables_error_Run_message= An error occurred when opening the R App Variables view.
+
+Action_RestartApp_label= Restart App
+Action_StopApp_label= Stop App
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/RAppUIPlugin.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/RAppUIPlugin.java
new file mode 100644
index 0000000..7d5dd46
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/RAppUIPlugin.java
@@ -0,0 +1,131 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.framework.BundleContext;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+import org.eclipse.statet.jcommons.lang.Disposable;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ui.util.ImageRegistryUtil;
+
+import org.eclipse.statet.internal.r.apps.ui.launching.AppControlManager;
+import org.eclipse.statet.internal.r.apps.ui.launching.AppType;
+import org.eclipse.statet.r.apps.ui.RAppUIResources;
+
+
+@NonNullByDefault
+public class RAppUIPlugin extends AbstractUIPlugin {
+
+
+ public static final String BUNDLE_ID= "org.eclipse.statet.r.apps"; //$NON-NLS-1$
+
+
+ private static RAppUIPlugin instance;
+
+ /**
+ * Returns the shared plug-in instance
+ *
+ * @return the shared instance
+ */
+ public static RAppUIPlugin getInstance() {
+ return RAppUIPlugin.instance;
+ }
+
+
+ public static void log(final IStatus status) {
+ final Plugin plugin= getInstance();
+ if (plugin != null) {
+ plugin.getLog().log(status);
+ }
+ }
+
+
+ private boolean started;
+
+ private List<Disposable> disposables;
+
+ private @Nullable AppControlManager launchConfigManager;
+
+
+ @SuppressWarnings("null")
+ public RAppUIPlugin() {
+ }
+
+ @Override
+ public void start(final BundleContext context) throws Exception {
+ super.start(context);
+ instance= this;
+
+ this.disposables= new ArrayList<>();
+
+ this.started= true;
+ }
+
+ @Override
+ public void stop(final BundleContext context) throws Exception {
+ try {
+ synchronized (this) {
+ this.started= false;
+ }
+
+ for (final Disposable listener : this.disposables) {
+ try {
+ listener.dispose();
+ }
+ catch (final Throwable e) {
+ getLog().log(new Status(IStatus.ERROR, BUNDLE_ID, 0,
+ "Error occured while dispose module", e ));
+ }
+ }
+ this.disposables= null;
+ }
+ finally {
+ instance= null;
+ super.stop(context);
+ }
+ }
+
+
+ @Override
+ protected void initializeImageRegistry(final ImageRegistry reg) {
+ if (!this.started) {
+ throw new IllegalStateException("Plug-in is not started.");
+ }
+ final ImageRegistryUtil util= new ImageRegistryUtil(this);
+
+ util.register(RAppUIResources.TOOL_VIEW_IMAGE_ID, ImageRegistryUtil.T_TOOL, "view-app.png"); //$NON-NLS-1$
+ }
+
+
+ public synchronized AppControlManager getRunAppConfigManager(final AppType appType) {
+ if (this.launchConfigManager == null) {
+ this.launchConfigManager= new AppControlManager(appType);
+ this.disposables.add(this.launchConfigManager);
+ }
+ return this.launchConfigManager;
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigMainTab.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigMainTab.java
new file mode 100644
index 0000000..66475b1
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigMainTab.java
@@ -0,0 +1,403 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.launching;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.databinding.DataBindingContext;
+import org.eclipse.core.databinding.UpdateValueStrategy;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.core.databinding.observable.value.WritableValue;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.variables.IStringVariable;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.jface.databinding.swt.WidgetProperties;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import org.eclipse.statet.ecommons.databinding.IntegerValidator;
+import org.eclipse.statet.ecommons.databinding.core.validation.UpdateableErrorValidator;
+import org.eclipse.statet.ecommons.debug.ui.config.LaunchConfigPresets;
+import org.eclipse.statet.ecommons.debug.ui.config.LaunchConfigTabWithPresets;
+import org.eclipse.statet.ecommons.templates.TemplateVariableProcessor;
+import org.eclipse.statet.ecommons.ui.SharedMessages;
+import org.eclipse.statet.ecommons.ui.SharedUIResources;
+import org.eclipse.statet.ecommons.ui.components.CustomizableVariableSelectionDialog;
+import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
+import org.eclipse.statet.ecommons.ui.util.VariableFilterUtils;
+import org.eclipse.statet.ecommons.variables.core.VariableText2;
+import org.eclipse.statet.ecommons.variables.core.VariableTextValidator;
+import org.eclipse.statet.ecommons.variables.core.VariableUtils;
+
+import org.eclipse.statet.internal.r.apps.ui.Messages;
+import org.eclipse.statet.ltk.ui.sourceediting.SnippetEditor;
+import org.eclipse.statet.ltk.ui.sourceediting.SnippetEditor1;
+import org.eclipse.statet.r.core.RCore;
+import org.eclipse.statet.r.launching.ui.RLaunchingUI;
+import org.eclipse.statet.r.ui.sourceediting.RSourceViewerConfigurator;
+import org.eclipse.statet.r.ui.sourceediting.RTemplateSourceViewerConfigurator;
+
+
+public class AppControlConfigMainTab extends LaunchConfigTabWithPresets {
+
+
+ static void initDefaults(final ILaunchConfigurationWorkingCopy config) {
+ config.setAttribute(AppControlConfigs.START_STOP_BLOCKING_TASKS_MODE_ATTR_NAME, 1);
+ }
+
+
+ private final IObservableValue<String> appPathValue;
+
+ private final IObservableValue<String> appHostValue;
+ private final IObservableValue<Integer> appPortValue;
+
+ private final IObservableValue<Boolean> startStopRunningValue;
+ private final IObservableValue<String> startRSnippetValue;
+ private final IObservableValue<String> stopRSnippetValue;
+
+// private ResourceInputComposite appPathControl;
+
+ private Text sHostControl;
+ private Text sPortControl;
+
+ private Button startStopRunningControl;
+ private VariableText2 rSnippetVariableResolver;
+ private SnippetEditor startRSnippetEditor;
+ private SnippetEditor stopRSnippetEditor;
+
+
+ public AppControlConfigMainTab(final LaunchConfigPresets presets) {
+
+ final Realm realm= getRealm();
+ this.appHostValue= new WritableValue<>(realm, null, String.class);
+ this.appPortValue= new WritableValue<>(realm, null, Integer.class);
+ this.appPathValue= new WritableValue<>(realm, null, String.class);
+ this.startRSnippetValue= new WritableValue<>(realm, null, String.class);
+ this.startStopRunningValue= new WritableValue<>(realm, null, Boolean.class);
+ this.stopRSnippetValue= new WritableValue<>(realm, null, String.class);
+
+ setPresets(presets);
+ }
+
+
+ @Override
+ public Image getImage() {
+ return SharedUIResources.getImages().get(SharedUIResources.OBJ_MAIN_TAB_ID);
+ }
+
+ @Override
+ public String getName() {
+ return Messages.Operation_MainTab_name;
+ }
+
+
+ @Override
+ public void createControl(final Composite parent) {
+ final Composite mainComposite= new Composite(parent, SWT.NONE);
+ setControl(mainComposite);
+ mainComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ mainComposite.setLayout(LayoutUtils.newTabGrid(1));
+
+ addPresetsButton(mainComposite);
+
+ { final Composite composite= createAddressSettings(mainComposite);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ }
+ { final Composite composite= createSnippetSettings(mainComposite);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ }
+ Dialog.applyDialogFont(parent);
+
+ initBindings();
+ }
+
+ private Composite createAddressSettings(final Composite parent) {
+ final Group composite= new Group(parent, SWT.NONE);
+ composite.setText(Messages.Operation_MainTab_AppAddress_group);
+ composite.setLayout(LayoutUtils.newGroupGrid(4));
+
+ { // Address
+ final Label label= new Label(composite, SWT.LEFT);
+ label.setText(Messages.Operation_MainTab_AppHost_label + ':');
+ label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+
+ final Text text= new Text(composite, SWT.BORDER | SWT.SINGLE | SWT.LEFT);
+ text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ this.sHostControl= text;
+
+ final Label info= new Label(composite, SWT.LEFT);
+ info.setText(Messages.Operation_AppHost_info);
+ info.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ }
+ { // Port
+ final Label label= new Label(composite, SWT.LEFT);
+ label.setText(Messages.Operation_MainTab_AppPort_label + ':');
+ label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+
+ final Text number= new Text(composite, SWT.BORDER | SWT.SINGLE | SWT.LEFT);
+ final GridData gd= new GridData(SWT.LEFT, SWT.CENTER, false, false);
+ gd.widthHint= LayoutUtils.hintWidth(number, 5);
+ number.setLayoutData(gd);
+ this.sPortControl= number;
+
+ final Label info= new Label(composite, SWT.LEFT);
+ info.setText(Messages.Operation_AppPort_info);
+ info.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
+ }
+
+ return composite;
+ }
+
+ private Map<String, IStringVariable> createSnippetVariables() {
+ final Map<String, IStringVariable> variables= new HashMap<>();
+ VariableUtils.add(variables, AppControlConfigs.APP_HOST_VAR);
+ VariableUtils.add(variables, AppControlConfigs.APP_PORT_VAR);
+ return variables;
+ }
+
+ private Composite createSnippetSettings(final Composite parent) {
+ final Group composite= new Group(parent, SWT.NONE);
+ composite.setText(Messages.Operation_MainTab_Start_group);
+ composite.setLayout(LayoutUtils.newGroupGrid(1));
+
+// { final Label label= new Label(composite, SWT.NONE);
+// label.setText(Messages.Operation_MainTab_AppFolder_label + ' ' +
+// Messages.Operation_AppFolder_info + ':' );
+// label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+//
+// final ResourceInputComposite input= new ResourceInputComposite(composite,
+// ResourceInputComposite.STYLE_TEXT,
+// ResourceInputComposite.MODE_DIRECTORY | ResourceInputComposite.MODE_OPEN
+// | ResourceInputComposite.MODE_WS_ONLY,
+// Messages.Operation_MainTab_AppFolder_label );
+// input.getValidator().setOnEmpty(IStatus.OK);
+// input.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+// this.appPathControl= input;
+// }
+
+ this.rSnippetVariableResolver= new VariableText2(createSnippetVariables());
+
+ { final Label label= new Label(composite, SWT.NONE);
+ label.setText(Messages.Operation_StartApp_RCode_label + ':');
+ label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+
+ final TemplateVariableProcessor templateVariableProcessor= new TemplateVariableProcessor();
+ final RSourceViewerConfigurator configurator= new RTemplateSourceViewerConfigurator(
+ RCore.getWorkbenchAccess(),
+ templateVariableProcessor );
+ final SnippetEditor1 editor= new SnippetEditor1(configurator, null,
+ PlatformUI.getWorkbench(), RLaunchingUI.LAUNCH_CONFIG_QUALIFIER, true ) {
+ @Override
+ protected void fillToolMenu(final Menu menu) {
+ { final MenuItem item= new MenuItem(menu, SWT.PUSH);
+ item.setText(SharedMessages.InsertVariable_label);
+ item.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ final CustomizableVariableSelectionDialog dialog= new CustomizableVariableSelectionDialog(getTextControl().getShell());
+ dialog.addVariableFilter(VariableFilterUtils.EXCLUDE_JAVA_FILTER);
+ dialog.setAdditionals(AppControlConfigMainTab
+ .this.rSnippetVariableResolver.getExtraVariables().values() );
+ if (dialog.open() != Dialog.OK) {
+ return;
+ }
+ final String variable= dialog.getVariableExpression();
+ if (variable == null) {
+ return;
+ }
+ getTextControl().insert(variable);
+ getTextControl().setFocus();
+ }
+ });
+ }
+ }
+ };
+ editor.create(composite, SnippetEditor.DEFAULT_MULTI_LINE_STYLE);
+ final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
+ gd.heightHint= LayoutUtils.hintHeight(editor.getSourceViewer().getTextWidget(), 8);
+ editor.getControl().setLayoutData(gd);
+ this.startRSnippetEditor= editor;
+ }
+ { final Button button= new Button(composite, SWT.CHECK);
+ button.setText(Messages.Operation_StartApp_StopRunningApp_label);
+ button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ this.startStopRunningControl= button;
+ }
+ LayoutUtils.addSmallFiller(composite, false);
+ { final Label label= new Label(composite, SWT.NONE);
+ label.setText(Messages.Operation_StopApp_RCode_label + ':');
+ label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+
+ final TemplateVariableProcessor templateVariableProcessor= new TemplateVariableProcessor();
+ final RSourceViewerConfigurator configurator= new RTemplateSourceViewerConfigurator(
+ RCore.getWorkbenchAccess(),
+ templateVariableProcessor );
+ final SnippetEditor1 editor= new SnippetEditor1(configurator, null,
+ PlatformUI.getWorkbench(), RLaunchingUI.LAUNCH_CONFIG_QUALIFIER );
+ editor.create(composite, SnippetEditor.DEFAULT_SINGLE_LINE_STYLE);
+ final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false);
+ gd.heightHint= LayoutUtils.hintHeight(editor.getSourceViewer().getTextWidget(), 1);
+ editor.getControl().setLayoutData(gd);
+ this.stopRSnippetEditor= editor;
+ }
+ return composite;
+ }
+
+
+ @Override
+ protected void addBindings(final DataBindingContext dbc) {
+// dbc.bindValue(
+// this.appPathControl.getObservable(),
+// this.appPathValue,
+// new UpdateValueStrategy().setAfterGetValidator(this.appPathControl.getValidator()),
+// null );
+
+ dbc.bindValue(
+ WidgetProperties.text(SWT.Modify).observe(this.sHostControl),
+ this.appHostValue );
+ dbc.bindValue(
+ WidgetProperties.text(SWT.Modify).observe(this.sPortControl),
+ this.appPortValue,
+ new UpdateValueStrategy().setAfterGetValidator(new IntegerValidator(0, 65535, true,
+ Messages.Operation_AppPort_error_SpecInvalid_message )),
+ null );
+
+ dbc.bindValue(
+ WidgetProperties.text(SWT.Modify).observe(this.startRSnippetEditor.getTextControl()),
+ this.startRSnippetValue,
+ new UpdateValueStrategy().setAfterGetValidator(
+ new UpdateableErrorValidator(new VariableTextValidator(
+ this.rSnippetVariableResolver,
+ Messages.Operation_StartApp_RCode_error_SpecInvalid_message ))),
+ null );
+ dbc.bindValue(
+ WidgetProperties.selection().observe(this.startStopRunningControl),
+ this.startStopRunningValue );
+ dbc.bindValue(
+ WidgetProperties.text(SWT.Modify).observe(this.stopRSnippetEditor.getTextControl()),
+ this.stopRSnippetValue );
+ }
+
+
+ @Override
+ public void setDefaults(final ILaunchConfigurationWorkingCopy configuration) {
+ initDefaults(configuration);
+ }
+
+ @Override
+ protected void doInitialize(final ILaunchConfiguration configuration) {
+// { String path= ""; //$NON-NLS-1$
+// try {
+// path= configuration.getAttribute(AppControlConfig.EXPL_SOURCE_PATH_ATTR_NAME, path);
+// }
+// catch (final CoreException e) {
+// logReadingError(e);
+// }
+// this.appPathValue.setValue(path);
+// }
+
+ { String text= ""; //$NON-NLS-1$
+ try {
+ text= configuration.getAttribute(AppControlConfigs.APP_HOST_ATTR_NAME, text);
+ }
+ catch (final CoreException e) {
+ logReadingError(e);
+ }
+ this.appHostValue.setValue(text);
+ }
+ { int port= 0;
+ try {
+ port= configuration.getAttribute(AppControlConfigs.APP_PORT_ATTR_NAME, port);
+ }
+ catch (final CoreException e) {
+ logReadingError(e);
+ }
+ this.appPortValue.setValue((port != 0) ? Integer.valueOf(port) : null);
+ }
+
+ { int mode= 0;
+ try {
+ mode= configuration.getAttribute(AppControlConfigs.START_STOP_BLOCKING_TASKS_MODE_ATTR_NAME, mode);
+ }
+ catch (final CoreException e) {
+ logReadingError(e);
+ }
+ this.startStopRunningValue.setValue(mode > 0);
+ }
+ { String code= ""; //$NON-NLS-1$
+ try {
+ code= configuration.getAttribute(AppControlConfigs.START_R_SNIPPET_CODE_ATTR_NAME, code);
+ }
+ catch (final CoreException e) {
+ logReadingError(e);
+ }
+ this.startRSnippetValue.setValue(code);
+ }
+ { String code= ""; //$NON-NLS-1$
+ try {
+ code= configuration.getAttribute(AppControlConfigs.STOP_R_SNIPPET_CODE_ATTR_NAME, code);
+ }
+ catch (final CoreException e) {
+ logReadingError(e);
+ }
+ this.stopRSnippetValue.setValue(code);
+ }
+ }
+
+ @Override
+ protected void doSave(final ILaunchConfigurationWorkingCopy configuration) {
+// { final String path= this.appPathValue.getValue();
+// configuration.setAttribute(AppControlConfig.EXPL_SOURCE_PATH_ATTR_NAME, path);
+// }
+
+ { final String text= this.appHostValue.getValue();
+ configuration.setAttribute(AppControlConfigs.APP_HOST_ATTR_NAME, text);
+ }
+ { final Integer port= this.appPortValue.getValue();
+ if (port != null) {
+ configuration.setAttribute(AppControlConfigs.APP_PORT_ATTR_NAME, port.intValue());
+ }
+ else {
+ configuration.removeAttribute(AppControlConfigs.APP_PORT_ATTR_NAME);
+ }
+ }
+
+ { final int mode= (this.startStopRunningValue.getValue()) ? 1 : 0;
+ configuration.setAttribute(AppControlConfigs.START_STOP_BLOCKING_TASKS_MODE_ATTR_NAME, mode);
+ }
+ { final String code= this.startRSnippetValue.getValue();
+ configuration.setAttribute(AppControlConfigs.START_R_SNIPPET_CODE_ATTR_NAME, code);
+ }
+ { final String code= this.stopRSnippetValue.getValue();
+ configuration.setAttribute(AppControlConfigs.STOP_R_SNIPPET_CODE_ATTR_NAME, code);
+ }
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigTabGroup.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigTabGroup.java
new file mode 100644
index 0000000..cc48137
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigTabGroup.java
@@ -0,0 +1,76 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.launching;
+
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.CommonTab;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.ecommons.debug.ui.config.LaunchConfigPresets;
+
+
+@NonNullByDefault
+public class AppControlConfigTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+
+ private static final LaunchConfigPresets PRESETS;
+ static {
+ final LaunchConfigPresets presets= new LaunchConfigPresets(
+ AppControlConfigs.TYPE_ID );
+
+ final ILaunchConfigurationWorkingCopy config= presets.add("R Shiny App");
+ config.setAttribute(AppControlConfigs.START_R_SNIPPET_CODE_ATTR_NAME,
+ "library(shiny);\n" + //$NON-NLS-1$
+ "shiny::runApp(\"${resource_loc}\", " + //$NON-NLS-1$
+ "host= \"${" + AppControlConfigs.APP_HOST_VAR_NAME + "}\", " +
+ "port= ${" + AppControlConfigs.APP_PORT_VAR_NAME + "}, " + //$NON-NLS-1$
+ "launch.browser= FALSE)" ); //$NON-NLS-1$
+ config.setAttribute(AppControlConfigs.STOP_R_SNIPPET_CODE_ATTR_NAME,
+ "shiny::stopApp()");
+ config.setAttribute(AppControlConfigs.VARIABLES_CODE_ATTR_NAME,
+ ".rj.tmp$appDomains" );
+
+ PRESETS= presets;
+ }
+
+ public static LaunchConfigPresets getPresets() {
+ return PRESETS;
+ }
+
+ public static void initDefaults(final ILaunchConfigurationWorkingCopy config) {
+ AppControlConfigMainTab.initDefaults(config);
+ AppControlConfigViewTab.initDefaults(config);
+ }
+
+
+ public AppControlConfigTabGroup() {
+ }
+
+
+ @Override
+ public void createTabs(final ILaunchConfigurationDialog dialog, final String mode) {
+ final ILaunchConfigurationTab[] tabs= new ILaunchConfigurationTab[] {
+ new AppControlConfigMainTab(PRESETS),
+ new AppControlConfigViewTab(),
+ new CommonTab()
+ };
+ setTabs(tabs);
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigViewTab.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigViewTab.java
new file mode 100644
index 0000000..33e3e30
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigViewTab.java
@@ -0,0 +1,376 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.launching;
+
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
+
+import org.eclipse.core.databinding.DataBindingContext;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.core.databinding.observable.value.IValueChangeListener;
+import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
+import org.eclipse.core.databinding.observable.value.WritableValue;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.jface.databinding.swt.WidgetProperties;
+import org.eclipse.jface.databinding.viewers.ViewerProperties;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.ComboViewer;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.ui.PlatformUI;
+
+import org.eclipse.statet.jcommons.collections.ImCollections;
+import org.eclipse.statet.jcommons.collections.ImList;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.debug.ui.config.LaunchConfigTabWithDbc;
+import org.eclipse.statet.ecommons.templates.TemplateVariableProcessor;
+import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
+
+import org.eclipse.statet.internal.r.apps.ui.Messages;
+import org.eclipse.statet.ltk.ui.sourceediting.SnippetEditor;
+import org.eclipse.statet.ltk.ui.sourceediting.SnippetEditor1;
+import org.eclipse.statet.r.apps.ui.RAppUIResources;
+import org.eclipse.statet.r.core.RCore;
+import org.eclipse.statet.r.launching.ui.RLaunchingUI;
+import org.eclipse.statet.r.ui.sourceediting.RSourceViewerConfigurator;
+import org.eclipse.statet.r.ui.sourceediting.RTemplateSourceViewerConfigurator;
+
+
+@NonNullByDefault
+public class AppControlConfigViewTab extends LaunchConfigTabWithDbc
+ implements IValueChangeListener<Object> {
+
+
+ static void initDefaults(final ILaunchConfigurationWorkingCopy config) {
+ config.setAttribute(AppControlConfigs.VIEWER_ID_ATTR_NAME, AppControlConfigs.WORKBENCH_VIEW_BROWSER_ID);
+ config.setAttribute(AppControlConfigs.VARIABLES_VIEWER_ACTION_ATTR_NAME, AppControlConfigs.SHOW_ACTION_ID);
+ }
+
+
+ private class ViewerItem {
+
+
+ private final @Nullable String id;
+
+ private final String label;
+
+ private @Nullable Composite detailControl;
+
+
+ public ViewerItem(final @Nullable String id, final String label) {
+ this.id= id;
+ this.label= label;
+ }
+
+
+ public @Nullable String getId() {
+ return this.id;
+ }
+
+ @Override // for LabelProvider
+ public String toString() {
+ return this.label;
+ }
+
+ public Composite enable() {
+ if (this.id != null) {
+ if (this.detailControl == null) {
+ this.detailControl= createControl(AppControlConfigViewTab.this.viewerDetailControl);
+ }
+ }
+ return this.detailControl;
+ }
+
+ public void disable() {
+ }
+
+ protected Composite createControl(final Composite parent) {
+ final Composite composite= new Composite(parent, SWT.NONE);
+ return composite;
+ }
+
+ }
+
+
+ private ImList<ViewerItem> viewers;
+
+ private IObservableValue<ViewerItem> viewerValue;
+
+ private IObservableValue<String> variablesCodeValue;
+ private IObservableValue<Boolean> variablesActionValue;
+
+ private ComboViewer viewerSelectionViewer;
+ private StackLayout viewerDetailLayout;
+ private Composite viewerDetailControl;
+
+ private SnippetEditor variablesCodeEditor;
+ private Button variablesActionControl;
+
+
+ public AppControlConfigViewTab() {
+
+ final Realm realm= getRealm();
+ this.viewerValue= new WritableValue<>(realm, null, String.class);
+ this.viewerValue.addValueChangeListener(this);
+
+ this.viewers= ImCollections.newList(
+ new ViewerItem(null, Messages.Operation_Viewer_None_label),
+ new ViewerItem(AppControlConfigs.WORKBENCH_VIEW_BROWSER_ID,
+ Messages.Operation_Viewer_WorkbenchView_label),
+ new ViewerItem(AppControlConfigs.WORKBENCH_EXTERNAL_BROWSER_ID,
+ Messages.Operation_Viewer_WorkbenchExternal_label) {
+ @Override
+ protected Composite createControl(final Composite parent) {
+ final Composite composite= super.createControl(parent);
+
+ composite.setLayout(LayoutUtils.newCompositeGrid(1));
+
+ LayoutUtils.addSmallFiller(composite, true);
+
+ final Link link= new Link(composite, SWT.NONE);
+ link.setText("Global preferences: "
+ + "<a href=\"org.eclipse.ui.browser.preferencePage\">Web Browser</a>.");
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false));
+ link.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ final PreferenceDialog dialog= org.eclipse.ui.dialogs.PreferencesUtil.createPreferenceDialogOn(null, e.text, null, null);
+ if (dialog != null) {
+ dialog.open();
+ }
+ }
+ });
+
+ return composite;
+ }
+ });
+
+ this.variablesCodeValue= new WritableValue<>(realm, "", String.class); //$NON-NLS-1$
+ this.variablesActionValue= new WritableValue<>(realm, true, Boolean.TYPE);
+ }
+
+
+ @Override
+ public Image getImage() {
+ return nonNullAssert(RAppUIResources.INSTANCE.getImage(RAppUIResources.TOOL_VIEW_IMAGE_ID));
+ }
+
+ @Override
+ public String getName() {
+ return Messages.Operation_ViewTab_name;
+ }
+
+ public String getLabel() {
+ return Messages.Operation_ViewTab_label;
+ }
+
+
+ @Override
+ public void createControl(final Composite parent) {
+ final Composite mainComposite= new Composite(parent, SWT.NONE);
+ setControl(mainComposite);
+ mainComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ mainComposite.setLayout(new GridLayout());
+
+ { final Label label= new Label(mainComposite, SWT.NONE);
+ label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ label.setText(getLabel() + ':');
+ }
+ { final Composite composite= createViewerSettings(mainComposite);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ }
+ { final Composite composite= createVariablesSettings(mainComposite);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ }
+ Dialog.applyDialogFont(parent);
+
+ initBindings();
+ }
+
+
+ private ViewerItem getViewerItem(final String id) {
+ for (final ViewerItem item : this.viewers) {
+ if (item.getId() == id) {
+ return item;
+ }
+ }
+ return this.viewers.get(0);
+ }
+
+ private Composite createViewerSettings(final Composite parent) {
+ final Group composite= new Group(parent, SWT.NONE);
+ composite.setText(Messages.Operation_ViewTab_Operation_label + ':');
+ composite.setLayout(LayoutUtils.newGroupGrid(1));
+
+ { final ComboViewer viewer= new ComboViewer(composite);
+
+ viewer.setLabelProvider(new LabelProvider());
+ viewer.setContentProvider(new ArrayContentProvider());
+ viewer.setInput(this.viewers);
+
+ viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ this.viewerSelectionViewer= viewer;
+ }
+ { final Composite detailControl= new Composite(composite, SWT.NONE);
+
+ this.viewerDetailLayout= new StackLayout();
+ detailControl.setLayout(this.viewerDetailLayout);
+
+ detailControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ this.viewerDetailControl= detailControl;
+ }
+
+ return composite;
+ }
+
+ private Composite createVariablesSettings(final Composite parent) {
+ final Group composite= new Group(parent, SWT.NONE);
+ composite.setText(Messages.Operation_Variables_label + ':');
+ composite.setLayout(LayoutUtils.newGroupGrid(2));
+
+ { final Label label= new Label(composite, SWT.NONE);
+ label.setText(Messages.Operation_StartApp_RCode_label + ':');
+ label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+
+ final TemplateVariableProcessor templateVariableProcessor= new TemplateVariableProcessor();
+ final RSourceViewerConfigurator configurator= new RTemplateSourceViewerConfigurator(
+ RCore.getWorkbenchAccess(),
+ templateVariableProcessor );
+ final SnippetEditor1 editor= new SnippetEditor1(configurator, null,
+ PlatformUI.getWorkbench(), RLaunchingUI.LAUNCH_CONFIG_QUALIFIER );
+ editor.create(composite, SnippetEditor.DEFAULT_SINGLE_LINE_STYLE);
+ final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false);
+ gd.heightHint= LayoutUtils.hintHeight(editor.getSourceViewer().getTextWidget(), 1);
+ editor.getControl().setLayoutData(gd);
+ this.variablesCodeEditor= editor;
+ }
+
+ { final Button button= new Button(composite, SWT.CHECK);
+ button.setText(Messages.Operation_Variables_ShowView_label);
+
+ button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ this.variablesActionControl= button;
+ }
+
+ return composite;
+ }
+
+
+ @Override
+ protected void addBindings(final DataBindingContext dbc) {
+ dbc.bindValue(
+ ViewerProperties.singleSelection().observe(this.viewerSelectionViewer),
+ this.viewerValue );
+
+ dbc.bindValue(
+ WidgetProperties.text(SWT.Modify).observe(this.variablesCodeEditor.getTextControl()),
+ this.variablesCodeValue );
+ dbc.bindValue(
+ WidgetProperties.selection().observe(this.variablesActionControl),
+ this.variablesActionValue );
+ }
+
+ @Override
+ public void handleValueChange(final ValueChangeEvent<?> event) {
+ if (event.getObservable() == this.viewerValue) {
+ final ViewerItem oldItem= (ViewerItem) event.diff.getOldValue();
+ if (oldItem != null) {
+ oldItem.disable();
+ }
+
+ final ViewerItem newItem= (ViewerItem) event.diff.getNewValue();
+ if (newItem != null) {
+ this.viewerDetailLayout.topControl= newItem.enable();
+ }
+ else {
+ this.viewerDetailLayout.topControl= null;
+ }
+ this.viewerDetailControl.layout();
+ }
+ }
+
+
+ @Override
+ public void setDefaults(final ILaunchConfigurationWorkingCopy configuration) {
+ initDefaults(configuration);
+ }
+
+ @Override
+ protected void doInitialize(final ILaunchConfiguration configuration) {
+ { String id= ""; //$NON-NLS-1$
+ try {
+ id= configuration.getAttribute(AppControlConfigs.VIEWER_ID_ATTR_NAME, id);
+ }
+ catch (final CoreException e) {
+ logReadingError(e);
+ }
+ id= id.intern();
+ final ViewerItem item= getViewerItem(id);
+ this.viewerValue.setValue(item);
+ }
+
+ { String code= ""; //$NON-NLS-1$
+ try {
+ code= configuration.getAttribute(AppControlConfigs.VARIABLES_CODE_ATTR_NAME, code);
+ }
+ catch (final CoreException e) {
+ logReadingError(e);
+ }
+ this.variablesCodeValue.setValue(code);
+ }
+ { String action= ""; //$NON-NLS-1$
+ try {
+ action= configuration.getAttribute(AppControlConfigs.VARIABLES_VIEWER_ACTION_ATTR_NAME, action);
+ }
+ catch (final CoreException e) {
+ logReadingError(e);
+ }
+ this.variablesActionValue.setValue(action.equals(AppControlConfigs.SHOW_ACTION_ID));
+ }
+ }
+
+ @Override
+ protected void doSave(final ILaunchConfigurationWorkingCopy configuration) {
+ { final ViewerItem item= this.viewerValue.getValue();
+ configuration.setAttribute(AppControlConfigs.VIEWER_ID_ATTR_NAME, item.getId());
+ }
+
+ { final String code= this.variablesCodeValue.getValue();
+ configuration.setAttribute(AppControlConfigs.VARIABLES_CODE_ATTR_NAME, code);
+ }
+ { final Boolean enabled= this.variablesActionValue.getValue();
+ configuration.setAttribute(AppControlConfigs.VARIABLES_VIEWER_ACTION_ATTR_NAME,
+ (enabled) ? AppControlConfigs.SHOW_ACTION_ID : null );
+ }
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigs.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigs.java
new file mode 100644
index 0000000..61f0cae
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlConfigs.java
@@ -0,0 +1,66 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.launching;
+
+import org.eclipse.core.variables.IStringVariable;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.ecommons.variables.core.DynamicVariable;
+
+import org.eclipse.statet.internal.r.apps.ui.Messages;
+
+
+@NonNullByDefault
+public class AppControlConfigs {
+
+
+ public static final String TYPE_ID= "org.eclipse.statet.r.apps.launchConfigurations.RAppControl"; //$NON-NLS-1$
+
+
+ static final String ATTR_ROOT= "org.eclipse.statet.r.apps/"; //$NON-NLS-1$
+
+ public static final String SOURCE_PATH_ATTR_NAME= ATTR_ROOT + "AppSource.path"; //$NON-NLS-1$
+
+ public static final String APP_HOST_ATTR_NAME= ATTR_ROOT + "App.host"; //$NON-NLS-1$
+ public static final String APP_PORT_ATTR_NAME= ATTR_ROOT + "App.port"; //$NON-NLS-1$
+
+ public static final String START_STOP_BLOCKING_TASKS_MODE_ATTR_NAME= ATTR_ROOT + "Start.StopBlockingTasks.mode"; //$NON-NLS-1$
+
+ public static final String START_R_SNIPPET_CODE_ATTR_NAME= ATTR_ROOT + "Start.RSnippet.code"; //$NON-NLS-1$
+
+ public static final String STOP_R_SNIPPET_CODE_ATTR_NAME= ATTR_ROOT + "Stop.RSnippet.code"; //$NON-NLS-1$
+
+ public static final String VIEWER_ID_ATTR_NAME= ATTR_ROOT + "Viewer.id"; //$NON-NLS-1$
+
+ public static final String VARIABLES_CODE_ATTR_NAME= ATTR_ROOT + "Variables.code"; //$NON-NLS-1$
+ public static final String VARIABLES_VIEWER_ACTION_ATTR_NAME= ATTR_ROOT + "Variables.Viewer.action"; //$NON-NLS-1$
+
+
+ public static final String APP_HOST_VAR_NAME= "host"; //$NON-NLS-1$
+ public static final String APP_PORT_VAR_NAME= "port"; //$NON-NLS-1$
+
+ public static final IStringVariable APP_HOST_VAR= new DynamicVariable(
+ APP_HOST_VAR_NAME, Messages.Variable_AppHost_description, false );
+ public static final IStringVariable APP_PORT_VAR= new DynamicVariable(
+ APP_PORT_VAR_NAME, Messages.Variable_AppPort_description, false );
+
+ public static final String WORKBENCH_EXTERNAL_BROWSER_ID= "workbench-external"; //$NON-NLS-1$
+ public static final String WORKBENCH_VIEW_BROWSER_ID= "workbench-view"; //$NON-NLS-1$
+
+ public static final String SHOW_ACTION_ID= "show"; //$NON-NLS-1$
+
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlLaunchConfig.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlLaunchConfig.java
new file mode 100644
index 0000000..63ee3c9
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlLaunchConfig.java
@@ -0,0 +1,272 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.launching;
+
+import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.PARAMETER;
+import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.RETURN_TYPE;
+import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.TYPE_ARGUMENT;
+import static org.eclipse.statet.jcommons.lang.NullDefaultLocation.TYPE_BOUND;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.variables.IStringVariable;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.IWorkbenchPage;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.io.FileValidator;
+import org.eclipse.statet.ecommons.resources.core.variables.ResourceVariableResolver;
+import org.eclipse.statet.ecommons.resources.core.variables.ResourceVariables;
+import org.eclipse.statet.ecommons.ui.util.UIAccess;
+import org.eclipse.statet.ecommons.ui.workbench.workspace.ResourceVariableUtil;
+import org.eclipse.statet.ecommons.variables.core.VariableText2;
+import org.eclipse.statet.ecommons.variables.core.VariableText2.Severities;
+import org.eclipse.statet.ecommons.variables.core.VariableUtils;
+
+import org.eclipse.statet.internal.r.apps.core.shiny.RShinyResourceTester;
+import org.eclipse.statet.internal.r.apps.ui.Messages;
+import org.eclipse.statet.internal.r.apps.ui.RAppUIPlugin;
+
+
+@NonNullByDefault({ PARAMETER, RETURN_TYPE, TYPE_BOUND, TYPE_ARGUMENT })
+public class AppControlLaunchConfig {
+
+
+ protected static CoreException createMissingConfigAttr(final String attrName) {
+ return new CoreException(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ NLS.bind("Invalid configuration: configuration attribute ''{0}'' is missing.", attrName) ));
+ }
+
+ protected static CoreException createValidationFailed(final FileValidator validator) {
+ final IStatus status= validator.getStatus();
+ return new CoreException(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ status.getMessage() ));
+ }
+
+
+ private ResourceVariableUtil selectedResourceUtil;
+
+ private IResource appFolder;
+ private ResourceVariableUtil appFolderrUtil;
+
+ private Map<String, IStringVariable> globalVariables;
+
+ private String appHost;
+ private int appPort;
+
+ private String startCode;
+ private String stopCode;
+
+ private String viewerId;
+
+ private String variablesCode;
+ private int variablesViewAction;
+
+ private int stopBlocking;
+
+
+ public AppControlLaunchConfig() {
+ }
+
+
+ public Map<String, IStringVariable> getVariables() {
+ if (this.globalVariables == null) {
+ this.globalVariables= new HashMap<>();
+ }
+ return this.globalVariables;
+ }
+
+ public void initSource(final ILaunchConfiguration configuration,
+ final SubMonitor m) throws CoreException {
+ final FileValidator validator= new FileValidator(true);
+ validator.setResourceLabel("app resource");
+ validator.setRequireWorkspace(true, true);
+
+ IPath explicitePath= null;
+ { final String path= configuration.getAttribute(AppControlConfigs.SOURCE_PATH_ATTR_NAME,
+ (String) null );
+ if (path != null) {
+ explicitePath= Path.fromPortableString(path);
+ }
+ }
+
+ if (explicitePath != null) {
+ validator.setExplicit(explicitePath);
+ }
+ else {
+ UIAccess.getDisplay().syncExec(() -> {
+ final ResourceVariableUtil util= new ResourceVariableUtil();
+ util.getResource();
+ AppControlLaunchConfig.this.selectedResourceUtil= util;
+ });
+ if (this.selectedResourceUtil.getResource() == null) {
+ throw new CoreException(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ "No resource selected in the active Workbench window." ));
+ }
+ validator.setExplicit(this.selectedResourceUtil.getResource());
+ }
+
+ if (validator.getStatus().getSeverity() == IStatus.ERROR) {
+ throw createValidationFailed(validator);
+ }
+
+ setSelectedResource(validator.getWorkspaceResource());
+
+ final IResource appFolder;
+ if (explicitePath != null) {
+ appFolder= this.selectedResourceUtil.getResource();
+ }
+ else {
+ appFolder= RShinyResourceTester.getAppContainer(
+ this.selectedResourceUtil.getResource() );
+ if (appFolder == null) {
+ throw new CoreException(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ NLS.bind("Could not find app folder for ''{0}''.",
+ this.selectedResourceUtil.getResource() )));
+ }
+ }
+ initAppFolder(appFolder);
+ }
+
+ protected void setSelectedResource(final IResource resource) {
+ if (this.selectedResourceUtil == null) {
+ UIAccess.getDisplay().syncExec(() -> {
+ final ResourceVariableUtil util= new ResourceVariableUtil(resource);
+ AppControlLaunchConfig.this.selectedResourceUtil= util;
+ });
+ }
+ }
+
+ private void initAppFolder(final IResource resource) {
+ this.appFolder= resource;
+ this.appFolderrUtil= new ResourceVariableUtil(this.selectedResourceUtil, resource);
+
+ { final Map<String, IStringVariable> variables= getVariables();
+ VariableUtils.add(variables,
+ ResourceVariables.getSingleResourceVariables(),
+ new ResourceVariableResolver(this.appFolderrUtil) );
+ }
+ }
+
+ public IResource getAppFolder() {
+ return this.appFolder;
+ }
+
+ public IWorkbenchPage getWorkbenchPage() {
+ return this.appFolderrUtil.getWorkbenchPage();
+ }
+
+
+ public void initAddress(final ILaunchConfiguration configuration,
+ final SubMonitor m) throws CoreException {
+ this.appHost= configuration.getAttribute(AppControlConfigs.APP_HOST_ATTR_NAME, ""); //$NON-NLS-1$
+ this.appPort= configuration.getAttribute(AppControlConfigs.APP_PORT_ATTR_NAME, 0);
+
+ final Map<String, IStringVariable> variables= getVariables();
+ VariableUtils.add(variables, AppControlConfigs.APP_HOST_VAR);
+ VariableUtils.add(variables, AppControlConfigs.APP_PORT_VAR);
+ }
+
+ public String getAppHost() {
+ return this.appHost;
+ }
+
+ public int getAppPort() {
+ return this.appPort;
+ }
+
+
+ public void initOperation(final ILaunchConfiguration configuration,
+ final SubMonitor m) throws CoreException {
+ this.stopBlocking= configuration.getAttribute(AppControlConfigs.START_STOP_BLOCKING_TASKS_MODE_ATTR_NAME, 0);
+
+ { final String code= configuration.getAttribute(AppControlConfigs.START_R_SNIPPET_CODE_ATTR_NAME, ""); //$NON-NLS-1$
+ if (code.isEmpty()) {
+ throw new CoreException(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ Messages.Operation_StartApp_RCode_error_SpecMissing_message ));
+ }
+
+ try {
+ final VariableText2 variableResolver= new VariableText2(getVariables());
+ variableResolver.validate(code, Severities.CHECK_SYNTAX, null);
+ this.startCode= code;
+ }
+ catch (final CoreException e) {
+ throw new CoreException(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ NLS.bind(Messages.Operation_StartApp_RCode_error_SpecInvalid_message,
+ e.getMessage() )));
+ }
+ }
+
+ { final String code= configuration.getAttribute(AppControlConfigs.STOP_R_SNIPPET_CODE_ATTR_NAME, ""); //$NON-NLS-1$
+ this.stopCode= (!code.isEmpty()) ? code : null;
+ }
+
+ this.viewerId= configuration.getAttribute(AppControlConfigs.VIEWER_ID_ATTR_NAME, (String) null);
+
+ { String code= configuration.getAttribute(AppControlConfigs.VARIABLES_CODE_ATTR_NAME, ""); //$NON-NLS-1$
+ if (code.isEmpty()) {
+ code= null;
+ }
+ this.variablesCode= code;
+
+ final String viewAction= configuration.getAttribute(AppControlConfigs.VARIABLES_VIEWER_ACTION_ATTR_NAME, ""); //$NON-NLS-1$
+ int viewActionMode= 0;
+ if (viewAction.equals(AppControlConfigs.SHOW_ACTION_ID)) {
+ viewActionMode= IWorkbenchPage.VIEW_VISIBLE;
+ }
+ this.variablesViewAction= viewActionMode;
+ }
+ }
+
+
+ public int getStopBlocking() {
+ return this.stopBlocking;
+ }
+
+ public String getStartCode() {
+ return this.startCode;
+ }
+
+ public String getStopCode() {
+ return this.stopCode;
+ }
+
+
+ public @Nullable String getViewerId() {
+ return this.viewerId;
+ }
+
+
+ public @Nullable String getVariablesCode() {
+ return this.variablesCode;
+ }
+
+ public int getVariablesViewAction() {
+ return this.variablesViewAction;
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlLaunchDelegate.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlLaunchDelegate.java
new file mode 100644
index 0000000..2257eab
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlLaunchDelegate.java
@@ -0,0 +1,66 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.launching;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
+import org.eclipse.debug.ui.DebugUITools;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+
+@NonNullByDefault
+public class AppControlLaunchDelegate extends LaunchConfigurationDelegate {
+
+
+ public AppControlLaunchDelegate() {
+ }
+
+
+ @Override
+ protected IProject @Nullable [] getBuildOrder(final ILaunchConfiguration configuration,
+ final String mode) throws CoreException {
+ final IResource resource= DebugUITools.getSelectedResource();
+ final IProject project;
+ if (resource != null && (project= resource.getProject()) != null) {
+ return computeReferencedBuildOrder(new IProject[] { project });
+ }
+ return null;
+ }
+
+
+ @Override
+ public void launch(final ILaunchConfiguration configuration,
+ final String mode, final @Nullable ILaunch launch,
+ final @Nullable IProgressMonitor monitor) throws CoreException {
+ final SubMonitor m= SubMonitor.convert(monitor, "Configuring App Operation...", 3 + 3);
+
+ final AppControlLaunchConfig config= new AppControlLaunchConfig();
+ config.initSource(configuration, m.newChild(1));
+ config.initAddress(configuration, m.newChild(1));
+ config.initOperation(configuration, m.newChild(1));
+
+ final AppRunner runner= new AppRunner(config);
+ runner.startApp(config.getWorkbenchPage());
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlManager.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlManager.java
new file mode 100644
index 0000000..a494894
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppControlManager.java
@@ -0,0 +1,93 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.launching;
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.osgi.util.NLS;
+
+import org.eclipse.statet.jcommons.collections.IdentitySet;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.ecommons.debug.ui.config.LaunchConfigManager;
+import org.eclipse.statet.ecommons.debug.ui.config.LaunchConfigPresets;
+
+import org.eclipse.statet.internal.r.apps.ui.Messages;
+
+
+/**
+ *
+ * element= app container
+ */
+@NonNullByDefault
+public class AppControlManager extends LaunchConfigManager<IContainer> {
+
+
+ private final AppType appType;
+
+
+ public AppControlManager(final AppType appType) {
+ super(appType.getId(), AppControlConfigs.TYPE_ID );
+
+ this.appType= appType;
+ }
+
+
+ @Override
+ protected Map<String, Object> createRunAttributes(final IContainer element,
+ final IdentitySet<String> flags) {
+ final Map<String, Object> map= new IdentityHashMap<>(4);
+ if (element != null) {
+ map.put(AppControlConfigs.SOURCE_PATH_ATTR_NAME, element.getFullPath().toPortableString());
+ }
+ return map;
+ }
+
+
+ @Override
+ protected String getActionLabel(final byte bits) {
+ switch (bits) {
+ case 0:
+ return Messages.RunAction_RunApp_label;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+
+ @Override
+ protected String getAutogenConfigName() {
+ String name= this.appType.getName();
+ if (name.startsWith("R ")) { //$NON-NLS-1$
+ name= name.substring(2);
+ }
+ return NLS.bind("Run {0} and Show in Eclipse", name);
+ }
+
+ @Override
+ protected void initAutogenConfig(final ILaunchConfigurationWorkingCopy config) {
+ AppControlConfigTabGroup.initDefaults(config);
+ final ILaunchConfiguration preset= AppControlConfigTabGroup.getPresets().get(
+ this.appType.getName() );
+ if (preset != null) {
+ LaunchConfigPresets.apply(preset, config);
+ }
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppRCommandHandler.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppRCommandHandler.java
new file mode 100644
index 0000000..898f91f
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppRCommandHandler.java
@@ -0,0 +1,92 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.launching;
+
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ts.core.util.ToolCommandHandlerUtil;
+
+import org.eclipse.statet.nico.core.runtime.ToolController;
+import org.eclipse.statet.r.console.core.RProcess;
+import org.eclipse.statet.rj.eclient.core.AbstractRToolCommandHandler;
+import org.eclipse.statet.rj.eclient.core.RToolService;
+
+
+@NonNullByDefault
+class AppRCommandHandler extends AbstractRToolCommandHandler {
+
+
+ private static final String ON_APP_STARTED_ID= "org.eclipse.statet.r.apps.onAppStarted"; //$NON-NLS-1$
+
+ private static final String ON_APP_STOPPED_ID= "org.eclipse.statet.r.apps.onAppStopped"; //$NON-NLS-1$
+
+
+ static AppRCommandHandler connect(final AppRunner runner,
+ final RToolService r, final IProgressMonitor monitor) throws CoreException {
+ final ToolController controller= ((RProcess) r.getTool()).getController();
+ AppRCommandHandler handler= (AppRCommandHandler) controller.getCommandHandler(ON_APP_STARTED_ID);
+ if (handler == null) {
+ handler= new AppRCommandHandler();
+ controller.addCommandHandler(ON_APP_STARTED_ID, handler);
+ controller.addCommandHandler(ON_APP_STOPPED_ID, handler);
+ }
+ handler.currentRunner= runner;
+
+ return handler;
+ }
+
+
+ private @Nullable AppRunner currentRunner;
+
+
+ private AppRCommandHandler() {
+ }
+
+
+ @Override
+ protected IStatus execute(final String id, final RToolService r,
+ final Map<String, Object> data,
+ final IProgressMonitor monitor) throws CoreException {
+ if (id.equals(ON_APP_STARTED_ID)) {
+ if (this.currentRunner != null) {
+ this.currentRunner.onAppStarted(
+ ToolCommandHandlerUtil.getCheckedData(data, "url", String.class, false), //$NON-NLS-1$
+ ToolCommandHandlerUtil.getCheckedData(data, "typeId", String.class, false) ); //$NON-NLS-1$
+ }
+ }
+ if (id.equals(ON_APP_STOPPED_ID)) {
+ if (this.currentRunner != null) {
+ this.currentRunner.onAppStopped(
+ ToolCommandHandlerUtil.getCheckedData(data, "url", String.class, false) ); //$NON-NLS-1$
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ void disconnect(final AppRunner runner) {
+ if (this.currentRunner == runner) {
+ this.currentRunner= null;
+ }
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppRunner.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppRunner.java
new file mode 100644
index 0000000..445bf0e
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppRunner.java
@@ -0,0 +1,764 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.launching;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+import java.util.Objects;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.variables.IStringVariable;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IViewReference;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.browser.IWebBrowser;
+import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
+import org.eclipse.ui.statushandlers.StatusManager;
+
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+
+import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ts.core.Tool;
+import org.eclipse.statet.ecommons.ts.core.ToolRunnable;
+import org.eclipse.statet.ecommons.ui.mpbv.BrowserSession;
+import org.eclipse.statet.ecommons.ui.util.UIAccess;
+import org.eclipse.statet.ecommons.variables.core.StaticVariable;
+import org.eclipse.statet.ecommons.variables.core.VariableText2;
+import org.eclipse.statet.ecommons.variables.core.VariableUtils;
+
+import org.eclipse.statet.internal.r.apps.ui.Messages;
+import org.eclipse.statet.internal.r.apps.ui.RAppUIPlugin;
+import org.eclipse.statet.internal.r.apps.ui.variables.AppVarView;
+import org.eclipse.statet.internal.r.apps.ui.viewer.AppBrowserSession;
+import org.eclipse.statet.internal.r.apps.ui.viewer.AppBrowserView;
+import org.eclipse.statet.nico.core.runtime.Queue;
+import org.eclipse.statet.nico.core.runtime.Queue.RunnableStatus;
+import org.eclipse.statet.nico.core.runtime.ToolController;
+import org.eclipse.statet.nico.core.runtime.ToolProcess;
+import org.eclipse.statet.nico.ui.NicoUI;
+import org.eclipse.statet.nico.ui.NicoUITools;
+import org.eclipse.statet.r.apps.ui.AppRegistry;
+import org.eclipse.statet.r.apps.ui.RApp;
+import org.eclipse.statet.r.apps.ui.VariablesData;
+import org.eclipse.statet.r.console.core.RConsoleTool;
+import org.eclipse.statet.r.console.core.RProcess;
+import org.eclipse.statet.r.console.core.RWorkspace;
+import org.eclipse.statet.r.console.core.util.RCodeVariableText;
+import org.eclipse.statet.r.core.tool.AbstractStatetRRunnable;
+import org.eclipse.statet.r.core.tool.IRConsoleService;
+import org.eclipse.statet.r.nico.impl.RjsUtil;
+import org.eclipse.statet.rj.eclient.core.AbstractRToolRunnable;
+import org.eclipse.statet.rj.eclient.core.RToolService;
+
+
+@NonNullByDefault
+public class AppRunner extends AbstractStatetRRunnable implements RApp {
+
+
+ public static final String RUN_TASK_ID= "org.eclipse.statet.r.apps/RunApp"; //$NON-NLS-1$
+ public static final String STOP_TASK_ID= "org.eclipse.statet.r.apps/StopApp"; //$NON-NLS-1$
+
+ private static final String LOCALHOST= "127.0.0.1"; //$NON-NLS-1$
+
+ private static final IStatus NOT_RUNNING_DATA_STATUS= new Status(IStatus.INFO, RAppUIPlugin.BUNDLE_ID,
+ "The app is not running." );
+ private static final IStatus NOT_LOADED_DATA_STATUS= new Status(IStatus.INFO, RAppUIPlugin.BUNDLE_ID,
+ "Variabes are not yet available." );
+
+
+ public static RProcess fetchRProcess(final IWorkbenchPage page) throws CoreException {
+ final ToolProcess process= NicoUI.getToolRegistry().getActiveToolSession(page).getProcess();
+ NicoUITools.accessTool(RConsoleTool.TYPE, process);
+ return (RProcess) process;
+ }
+
+
+ private class AppSession {
+
+ private final RProcess rProcess;
+
+ private Queue.Section queueSection;
+
+ private String host;
+ private String remoteHost;
+ private int remotePort;
+ private @Nullable Session sshSession;
+ private int sshLocalPort= -1;
+
+ private @Nullable URL localUrl;
+ private @Nullable URL idUrl;
+
+ private boolean isRunning;
+
+
+ public AppSession(final RProcess tool) {
+ this.rProcess= tool;
+ }
+
+
+ public RProcess getTool() {
+ return this.rProcess;
+ }
+
+ public boolean isRunning() {
+ return this.isRunning;
+ }
+
+ public void init(final IProgressMonitor monitor) throws CoreException {
+ { this.queueSection= this.rProcess.getController().getCurrentQueueSection();
+ }
+ { final String host= AppRunner.this.config.getAppHost();
+ if (host.isEmpty()) {
+ final RWorkspace workspaceData= this.rProcess.getWorkspaceData();
+ if (workspaceData.isRemote()) {
+ this.host= workspaceData.getRemoteAddress();
+ final Map<String, Object> connectionInfo= this.rProcess.getConnectionInfo();
+ if (connectionInfo != null && Objects.equals(connectionInfo.get("protocol"), "ssh")) {
+ this.remoteHost= LOCALHOST;
+ this.sshSession= RjsUtil.getSession(connectionInfo, monitor);
+ }
+ }
+ else {
+ this.host= LOCALHOST;
+ }
+ }
+ else {
+ this.host= host;
+ }
+ if (this.remoteHost == null) {
+ this.remoteHost= this.host;
+ }
+ this.remotePort= AppRunner.this.config.getAppPort();
+ }
+ }
+
+ public String getStartCode() throws CoreException {
+ { final String code= AppRunner.this.config.getStartCode();
+
+ final Map<String, IStringVariable> variables= AppRunner.this.config.getVariables();
+ VariableUtils.add(variables, new StaticVariable(
+ AppControlConfigs.APP_HOST_VAR,
+ this.remoteHost ));
+ VariableUtils.add(variables, new StaticVariable(
+ AppControlConfigs.APP_PORT_VAR,
+ (this.remotePort > 0) ? Integer.toString(this.remotePort) : "NULL" )); //$NON-NLS-1$
+
+ final VariableText2 variableText= new RCodeVariableText(
+ this.rProcess.getWorkspaceData(), variables );
+ try {
+ return variableText.performStringSubstitution(code, null);
+ }
+ catch (final CoreException e) {
+ throw new CoreException(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ NLS.bind(Messages.Operation_StartApp_RCode_error_SpecInvalid_message,
+ e.getMessage() )));
+ }
+ }
+ }
+
+ public boolean onStarted(final String url) {
+ try {
+ final URL rUrl;
+ try {
+ rUrl= new URL(url);
+ }
+ catch (final MalformedURLException e) {
+ throw new CoreException(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ NLS.bind("Invalid URL of the R app from R= ''{0}''.", url),
+ e ));
+ }
+
+ if (this.sshSession != null) {
+ try {
+ this.sshLocalPort= this.sshSession.setPortForwardingL(0, LOCALHOST,
+ (rUrl.getPort() != -1) ? rUrl.getPort() : 80 );
+ this.localUrl= new URL(rUrl.getProtocol(), LOCALHOST, this.sshLocalPort,
+ rUrl.getFile() );
+ this.idUrl= new URL(rUrl.getProtocol(), this.host, rUrl.getPort(),
+ rUrl.getFile() );
+ }
+ catch (final JSchException e) {
+ throw new CoreException(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ "Failed create SSH tunnel for http connection of the R app.",
+ e ));
+ }
+ }
+ else if (!this.host.equals(rUrl.getHost())) {
+ this.localUrl= new URL(rUrl.getProtocol(), this.host, rUrl.getPort(),
+ rUrl.getFile() );
+ this.idUrl= this.localUrl;
+ }
+ else {
+ this.localUrl= rUrl;
+ this.idUrl= this.localUrl;
+ }
+ }
+ catch (final Exception e) {
+ StatusManager.getManager().handle(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ "An error occurred when preparing to show the R app.", e ),
+ (AppRunner.this.config.getViewerId() != null) ?
+ StatusManager.LOG | StatusManager.SHOW :
+ StatusManager.LOG );
+ return false;
+ }
+
+ synchronized (AppRunner.this) {
+ this.isRunning= true;
+ return true;
+ }
+ }
+
+ public URL getLocalUrl() {
+ return this.localUrl;
+ }
+
+ public URL getIdUrl() {
+ return this.idUrl;
+ }
+
+ public void onAppStop() {
+ synchronized (AppRunner.this) {
+ this.isRunning= false;
+ }
+
+ this.queueSection= null;
+
+ if (this.sshSession != null && this.sshLocalPort > 0) {
+ try {
+ this.sshSession.delPortForwardingL(this.sshLocalPort);
+ }
+ catch (final JSchException e) {
+ RAppUIPlugin.log(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ "Failed delete SSH tunnel for http connection of the R app.",
+ e ));
+ }
+ this.sshLocalPort= -1;
+ }
+ }
+
+ }
+
+ public class StopRunnable extends AbstractRToolRunnable {
+
+
+ public StopRunnable() {
+ super(STOP_TASK_ID, "Stop R App"); //$NON-NLS-1$
+ }
+
+
+ @Override
+ public boolean changed(final int event, final Tool tool) {
+ switch (event) {
+ case MOVING_FROM:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ @Override
+ protected void run(final RToolService r,
+ final IProgressMonitor monitor) throws CoreException {
+ AppSession session;
+ synchronized (AppRunner.this) {
+ session= AppRunner.this.session;
+ if (session == null || !session.isRunning()) {
+ return;
+ }
+ }
+
+ final String code= AppRunner.this.config.getStopCode();
+ r.evalVoid(code, monitor);
+ }
+
+ }
+
+
+ private final AppControlLaunchConfig config;
+
+ private final CopyOnWriteIdentityListSet<Listener> listeners= new CopyOnWriteIdentityListSet<>();
+
+ private @Nullable AppSession session;
+
+ private @Nullable RProcess tool;
+ private @Nullable IWorkbenchPage workbenchPage;
+
+ private @Nullable DataLoader variablesLoader;
+ private @Nullable volatile VariablesData variablesData;
+
+
+ public AppRunner(final AppControlLaunchConfig config) {
+ super(RUN_TASK_ID, NLS.bind("Run R App ''{0}''",
+ config.getAppFolder().getFullPath().toString() ));
+
+ this.config= config;
+ initVars();
+ }
+
+
+ @Override
+ public IResource getResource() {
+ return this.config.getAppFolder();
+ }
+
+
+ @Override
+ protected void run(final IRConsoleService r,
+ final IProgressMonitor monitor) throws CoreException {
+ final AppSession session;
+ AppRCommandHandler listener= null;
+ try {
+ synchronized (this) {
+ this.tool= (RProcess) r.getTool();
+ session= new AppSession(this.tool);
+ this.session= session;
+ }
+
+ session.init(monitor);
+
+ listener= AppRCommandHandler.connect(this, r, monitor);
+
+ r.briefAboutToChange();
+
+ r.submitToConsole(session.getStartCode(), monitor);
+
+ }
+ finally {
+ r.briefChanged(IRConsoleService.AUTO_CHANGE);
+
+ onAppStopped(null);
+
+ if (listener != null) {
+ listener.disconnect(this);
+ }
+ }
+ }
+
+ protected void onAppStarted(final String url, final String typeId) {
+ final AppSession session;
+ synchronized (this) {
+ session= this.session;
+ if (session == null) {
+ return;
+ }
+ }
+
+ final boolean isRunning= session.onStarted(url);
+ updateVarsOnStarted();
+
+ if (isRunning) {
+ AppRegistry.getInstance().onAppStarted(session.getIdUrl(), this);
+
+ if (this.config.getViewerId() != null) {
+ showViewer(session, this.config.getViewerId());
+ }
+ if (this.config.getVariablesViewAction() != 0 && this.variablesData != null) {
+ showVariablesView(session, this.config.getVariablesViewAction());
+ }
+ refreshVariables();
+ }
+ }
+
+ protected void onAppStopped(final @Nullable String url) {
+ final AppSession session;
+ synchronized (this) {
+ session= this.session;
+ if (session == null) {
+ return;
+ }
+
+ this.session= null;
+ }
+
+ session.onAppStop();
+
+ if (session.getIdUrl() != null) {
+ AppRegistry.getInstance().onAppStopped(session.getIdUrl(), this);
+ }
+
+ updateVarsOnStopped();
+ }
+
+
+ @Override
+ public @Nullable RProcess getTool() {
+ return this.tool;
+ }
+
+ protected IWorkbenchPage getWorkbenchPage() {
+ IWorkbenchPage page= this.workbenchPage;
+ if (page == null) {
+ page= this.config.getWorkbenchPage();
+ }
+ if (page != null && page.getWorkbenchWindow().getActivePage() == page) {
+ return page;
+ }
+ page= UIAccess.getActiveWorkbenchPage(true);
+ this.workbenchPage= page;
+ return page;
+ }
+
+ @Override
+ public boolean isRunning() {
+ final AppSession session;
+ synchronized (this) {
+ session= this.session;
+
+ return (session != null && session.isRunning());
+ }
+ }
+
+ @Override
+ public void startApp(final IWorkbenchPage page) throws CoreException {
+ final RProcess tool= fetchRProcess(page);
+
+ final IStatus status= tryStart(tool);
+ if (status.getSeverity() < IStatus.ERROR) {
+ return;
+ }
+
+ throw new CoreException(status);
+ }
+
+ @Override
+ public boolean canRestartApp() { // (!isRunning() || canStopApp())
+ final AppSession session;
+ synchronized (this) {
+ session= this.session;
+ if (session == null || !session.isRunning()) {
+ return true;
+ }
+ }
+
+ return (this.config.getStopCode() != null);
+ }
+
+ @Override
+ public void restartApp(final IWorkbenchPage page) throws CoreException {
+ final AppSession session;
+ RProcess tool;
+ Queue.Section queueSection;
+ synchronized (this) {
+ tool= this.tool;
+ session= this.session;
+
+ queueSection= (session != null && session.isRunning()) ? session.queueSection : null;
+ }
+
+ final AppRunner runner= new AppRunner(this.config);
+ runner.workbenchPage= this.workbenchPage;
+
+ IStatus status= null;
+ if (tool != null) {
+ if (queueSection != null && queueSection != tool.getQueue().getTopLevelSection()) {
+ final IStatus status0= runner.tryRestart(tool, queueSection);
+ if (status0.getSeverity() < IStatus.ERROR) {
+ return;
+ }
+ }
+ { final IStatus status0= runner.tryRestart(tool, tool.getQueue().getTopLevelSection());
+ if (status0.getSeverity() < IStatus.ERROR) {
+ return;
+ }
+ if (status == null) {
+ status= status0;
+ }
+ }
+ }
+
+ { tool= fetchRProcess(page);
+ final IStatus status0= runner.tryRestart(tool, tool.getQueue().getTopLevelSection());
+ if (status0.getSeverity() < IStatus.ERROR) {
+ return;
+ }
+ if (status == null) {
+ status= status0;
+ }
+ }
+
+ throw new CoreException(status);
+ }
+
+ private IStatus tryStart(final RProcess tool) {
+ final Queue queue= tool.getQueue();
+ final IStatus status= queue.add(this);
+
+ if (status.getSeverity() < IStatus.ERROR) {
+ stopBlocking(tool, this.config.getStopBlocking());
+ }
+
+ return status;
+ }
+
+ private IStatus tryRestart(final RProcess tool, final Queue.Section queueSection) {
+ final Queue queue= tool.getQueue();
+ final IStatus status= queue.add(this, queueSection, Queue.IF_ABSENT);
+
+ if (status.getSeverity() < IStatus.ERROR) {
+ final AppRunner runner= (AppRunner) ((RunnableStatus) status).getRunnable();
+
+ runner.stopBlocking(tool, this.config.getStopBlocking() | 2);
+ }
+
+ return status;
+ }
+
+ private void stopBlocking(final RProcess tool, final int mode) {
+ if (mode == 0) {
+ return;
+ }
+ final ToolController controller= tool.getController();
+ if (controller != null) {
+ final ToolRunnable currentRunnable= controller.getCurrentRunnable();
+ if (currentRunnable != this && currentRunnable instanceof AppRunner) {
+ final AppRunner runner= (AppRunner) currentRunnable;
+ if ((mode & 1) != 0
+ || ((mode & 2) != 0 && runner.config == this.config) ) {
+ runner.stopApp();
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean canStopApp() {
+ final AppSession session;
+ synchronized (this) {
+ session= this.session;
+ if (session == null || !session.isRunning()) {
+ return false;
+ }
+ }
+
+ return (this.config.getStopCode() != null);
+ }
+
+ @Override
+ public void stopApp() {
+ final AppSession session;
+ synchronized (this) {
+ session= this.session;
+ if (session == null) {
+ return;
+ }
+ }
+
+ if (this.config.getStopCode() != null) {
+ session.getTool().getQueue().addHot(new StopRunnable());
+ }
+ }
+
+
+ private void showViewer(final AppSession session, final String viewerId) {
+ if (session.getLocalUrl() == null) {
+ StatusManager.getManager().handle(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ "Cannot open viewer to show the R app: URL is missing." ),
+ StatusManager.SHOW );
+ return;
+ }
+
+ UIAccess.getDisplay().asyncExec(() -> {
+ synchronized (AppRunner.this) {
+ if (session != this.session || !session.isRunning()) {
+ return;
+ }
+ }
+ try {
+ switch (viewerId) {
+ case AppControlConfigs.WORKBENCH_EXTERNAL_BROWSER_ID:
+ openExternalBrowser(session);
+ return;
+ case AppControlConfigs.WORKBENCH_VIEW_BROWSER_ID:
+ openViewBrowser(getWorkbenchPage(), session);
+ return;
+ default:
+ throw new UnsupportedOperationException("viewerId= " + viewerId); //$NON-NLS-1$
+ }
+ }
+ catch (final Exception e) {
+ StatusManager.getManager().handle(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ Messages.Operation_Viewer_error_Run_message, e ),
+ StatusManager.LOG | StatusManager.SHOW );
+ }
+ });
+ }
+
+ private void openExternalBrowser(final AppSession session) throws PartInitException {
+ final IWorkbenchBrowserSupport browserSupport= PlatformUI.getWorkbench().getBrowserSupport();
+ final IWebBrowser webBrowser= browserSupport.getExternalBrowser();
+ webBrowser.openURL(session.getLocalUrl());
+ }
+
+ private AppBrowserView getView(final IWorkbenchPage page) throws PartInitException {
+ return (AppBrowserView) page.showView(AppBrowserView.VIEW_ID, null,
+ IWorkbenchPage.VIEW_VISIBLE );
+ }
+
+ private void openViewBrowser(final IWorkbenchPage page, final AppSession session) throws PartInitException {
+ final AppBrowserView view= getView(page);
+ AppBrowserSession viewSession= (AppBrowserSession) BrowserSession.findSessionById(
+ view.getSessions(), session.getIdUrl() );
+ if (viewSession == null) {
+ viewSession= new AppBrowserSession(session.getIdUrl());
+ }
+ view.openUrl(session.getLocalUrl().toExternalForm(), viewSession);
+ }
+
+
+ private void showVariablesView(final AppSession session, final int viewActionMode) {
+ UIAccess.getDisplay().asyncExec(() -> {
+ synchronized (AppRunner.this) {
+ if (session != this.session || !session.isRunning()) {
+ return;
+ }
+ }
+ try {
+ final IWorkbenchPage page= getWorkbenchPage();
+ final IViewReference viewRef= page.findViewReference(AppVarView.VIEW_ID);
+ if (viewRef != null) {
+ if (viewRef.isFastView()) {
+ return;
+ }
+ final IViewPart view= viewRef.getView(false);
+ if (view != null && page.isPartVisible(view)) {
+ return;
+ }
+ }
+ final AppVarView view= (AppVarView) page.showView(AppVarView.VIEW_ID, null,
+ viewActionMode );
+ view.setShownByLauncher(this);
+ }
+ catch (final PartInitException e) {
+ StatusManager.getManager().handle(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID,
+ Messages.Operation_Variables_error_Run_message, e ));
+ }
+ });
+ }
+
+
+ @Override
+ public void addListener(final Listener listener) {
+ boolean refresh;
+ synchronized (this.listeners) {
+ refresh= (this.listeners.isEmpty() && this.variablesLoader == null);
+
+ this.listeners.add(listener);
+ }
+ if (refresh) {
+ refreshVariables();
+ }
+ }
+
+ @Override
+ public void removeListener(final Listener listener) {
+ this.listeners.remove(listener);
+ }
+
+ @Override
+ public @Nullable VariablesData getVariables() {
+ return this.variablesData;
+ }
+
+ private void initVars() {
+ final String code= this.config.getVariablesCode();
+ if (code == null) {
+ return;
+ }
+ this.variablesData= new VariablesData(code, NOT_RUNNING_DATA_STATUS);
+ }
+
+ private void updateVarsOnStarted() {
+ final VariablesData data= this.variablesData;
+ if (data == null || data.getStatus() != NOT_RUNNING_DATA_STATUS) {
+ return;
+ }
+ setData(new VariablesData(data.getExpression(), NOT_LOADED_DATA_STATUS));
+ }
+
+ @Override
+ public void refreshVariables() {
+ final VariablesData data= this.variablesData;
+ if (data == null) {
+ return;
+ }
+ DataLoader loader;
+ synchronized (this.listeners) {
+ loader= this.variablesLoader;
+ if (loader == null) {
+ if (this.listeners.isEmpty() || !isRunning()) {
+ return;
+ }
+ loader= new DataLoader(this, data.getExpression());
+ this.variablesLoader= loader;
+ }
+ }
+ loader.schedule();
+ }
+
+ private void updateVarsOnStopped() {
+ final VariablesData data= this.variablesData;
+ if (data == null) {
+ return;
+ }
+ DataLoader loader;
+ synchronized (this.listeners) {
+ loader= this.variablesLoader;
+ this.variablesLoader= null;
+ }
+ if (loader != null) {
+ loader.stop();
+ }
+ setData(new VariablesData(data.getExpression(), NOT_RUNNING_DATA_STATUS));
+ }
+
+ void setData(final VariablesData variables) {
+ this.variablesData= variables;
+
+ final AppEvent event= new AppEvent(this);
+ for (final Listener listener : this.listeners) {
+ listener.onVariablesChanged(event);
+ }
+ }
+
+
+ @Override
+ public int hashCode() {
+ return this.config.hashCode();
+ }
+
+ @Override
+ public boolean equals(final @Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof AppRunner) {
+ return (this.config == ((AppRunner) obj).config);
+ }
+ return false;
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppType.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppType.java
new file mode 100644
index 0000000..e7cd3ec
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/AppType.java
@@ -0,0 +1,49 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.launching;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+
+@NonNullByDefault
+public class AppType {
+
+
+ private final String id;
+
+ private final String name;
+
+
+ public AppType(final String id, final String name) {
+ this.id= id;
+ this.name= name;
+ }
+
+
+ public String getId() {
+ return this.id;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+
+ @Override
+ public String toString() {
+ return this.id;
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/DataLoader.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/DataLoader.java
new file mode 100644
index 0000000..ef0c30c
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/launching/DataLoader.java
@@ -0,0 +1,274 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.launching;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+
+import org.eclipse.statet.jcommons.collections.ImCollections;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.ObjectUtils;
+import org.eclipse.statet.jcommons.lang.ObjectUtils.ToStringBuilder;
+
+import org.eclipse.statet.ecommons.ts.core.SystemRunnable;
+import org.eclipse.statet.ecommons.ts.core.Tool;
+
+import org.eclipse.statet.internal.r.apps.ui.RAppUIPlugin;
+import org.eclipse.statet.nico.core.runtime.Queue;
+import org.eclipse.statet.r.apps.ui.VariablesData;
+import org.eclipse.statet.r.console.core.RProcess;
+import org.eclipse.statet.r.console.core.RWorkspace;
+import org.eclipse.statet.r.core.data.CombinedRElement;
+import org.eclipse.statet.r.core.model.RElementName;
+import org.eclipse.statet.r.core.tool.TmpUtils;
+import org.eclipse.statet.r.nico.ICombinedRDataAdapter;
+import org.eclipse.statet.rj.data.RDataUtils;
+import org.eclipse.statet.rj.data.RReference;
+import org.eclipse.statet.rj.data.UnexpectedRDataException;
+import org.eclipse.statet.rj.eclient.core.AbstractRToolRunnable;
+import org.eclipse.statet.rj.eclient.core.RToolService;
+import org.eclipse.statet.rj.services.RService;
+
+
+@NonNullByDefault
+public class DataLoader extends AbstractRToolRunnable implements SystemRunnable {
+
+
+ public static final String TASK_ID= "org.eclipse.statet.r.apps/LoadVariables"; //$NON-NLS-1$
+
+
+ private final AppRunner app;
+
+ private final String expression;
+
+ private boolean isScheduled;
+
+ private RWorkspace workspace;
+
+ private final Set<Long> envs= new HashSet<>();
+
+
+ @SuppressWarnings("null")
+ public DataLoader(final AppRunner app, final String expression) {
+ super(TASK_ID, "Load elements of R app variables");
+
+ this.app= app;
+ this.expression= expression;
+
+ final Queue queue= getTool().getQueue();
+ queue.addOnIdle(this, 5100);
+ }
+
+
+ @SuppressWarnings("null")
+ private RProcess getTool() {
+ return this.app.getTool();
+ }
+
+ public void schedule() {
+ synchronized (this) {
+ final Queue queue= getTool().getQueue();
+ if (!this.isScheduled) {
+ queue.addHot(this);
+ }
+ }
+ }
+
+ public void stop() {
+ synchronized (this) {
+ final Queue queue= getTool().getQueue();
+ if (this.isScheduled) {
+ queue.removeHot(this);
+ this.isScheduled= false;
+ }
+ queue.removeOnIdle(this);
+ }
+ }
+
+
+ @Override
+ public boolean canRunIn(final Tool tool) {
+ return (tool == this.app.getTool());
+ }
+
+ @Override
+ protected void run(final RToolService r, final IProgressMonitor monitor) throws CoreException {
+ if (!this.app.isRunning()) {
+ return;
+ }
+
+ final SubMonitor m= SubMonitor.convert(monitor);
+ try {
+ final TmpUtils.Item tmpItem= TmpUtils.newItem("appvars", r, m); //$NON-NLS-1$
+ try {
+ evalExpression(tmpItem, (ICombinedRDataAdapter) r, m);
+ }
+ finally {
+ tmpItem.disposeChecked(m);
+ }
+ }
+ catch (final CoreException | UnexpectedRDataException e) {
+ final ToStringBuilder sb= new ObjectUtils.ToStringBuilder(
+ "An error occurred when evaluating the app variables expression." );
+ sb.addProp("expression", this.expression); //$NON-NLS-1$
+ RAppUIPlugin.log(new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID, 0,
+ sb.toString(), e ));
+ this.app.setData(new VariablesData(this.expression,
+ new Status(IStatus.ERROR, RAppUIPlugin.BUNDLE_ID, 0,
+ "Evaluation failed (internal error).", e )));
+ }
+ finally {
+ this.envs.clear();
+
+ synchronized (this) {
+ final Queue queue= getTool().getQueue();
+ if (this.isScheduled) {
+ queue.removeHot(this);
+ this.isScheduled= false;
+ }
+ }
+ }
+ }
+
+ private void evalExpression(final TmpUtils.Item tmpItem, final ICombinedRDataAdapter r,
+ final SubMonitor m) throws UnexpectedRDataException, CoreException {
+ final String valueName= tmpItem.createSub("value"); //$NON-NLS-1$
+ final RElementName valueElementName= RElementName.create(RElementName.MAIN_DEFAULT,
+ valueName );
+ final RElementName fqElementName= TmpUtils.createFQElementName(valueElementName);
+
+ CombinedRElement element= null;
+ try {
+// System.out.println("App Data Update= " + r.getChangeStamp());
+// int nframes= RDataUtil.checkSingleIntValue(r.evalData("sys.nframe()", m));
+// System.out.println("nframes= " + nframes);
+// for (int i= 0; i < nframes + 1; i++) {
+// String s= "evalq(shiny::getDefaultReactiveDomain(), envir=sys.frame(" + i + "L))";
+// System.out.println("expr= " + s);
+//
+// element= r.evalCombinedStruct(s,
+// 0, RService.DEPTH_REFERENCE, fqElementName, m );
+//
+// System.out.println(((RReference)element).getRClassName());
+// }
+ element= r.evalCombinedStruct(this.expression,
+ 0, RService.DEPTH_REFERENCE, fqElementName, m );
+ }
+ catch (final CoreException e) {
+ final IStatus status= e.getStatus();
+ this.app.setData(new VariablesData(this.expression,
+ new Status(status.getSeverity(), RAppUIPlugin.BUNDLE_ID, 0,
+ "Evaluation failed: " + e.getLocalizedMessage(), e )));
+ return;
+ }
+ final RReference ref= RDataUtils.checkRReference(element);
+
+ tmpItem.set(valueName, ref, m);
+
+ element= r.getWorkspaceData().resolve(ref,
+ RWorkspace.RESOLVE_UPTODATE | RWorkspace.RESOLVE_RECURSIVE, 0, m);
+ if (element == null) {
+ element= r.findCombinedStruct(valueElementName, TmpUtils.ENV_FQ_ELEMENT_NAME, false,
+ 0, RService.DEPTH_INFINITE, m );
+ if (element == null) {
+ throw new UnexpectedRDataException("null"); //$NON-NLS-1$
+ }
+ }
+ RElementName name= RElementName.parseDefault(this.expression);
+ if (name == null) {
+ name= RElementName.create(RElementName.MAIN_OTHER, "variables");
+ }
+ element= ICombinedRDataAdapter.createReference(element, name);
+
+ this.app.setData(new VariablesData(this.expression,
+ ImCollections.newList(element) ));
+ }
+
+// private void check(final ICombinedRElement element,
+// final SubMonitor m) throws CoreException {
+// if (element instanceof ICombinedRList) {
+// check((ICombinedRList) element, m);
+// }
+// }
+//
+// private void resolve(final RReference ref, final @Nullable RElementName fullName,
+// final int loadOptions, final SubMonitor m) throws CoreException {
+// if (!this.envs.add(ref.getHandle())) {
+// return;
+// }
+// final ICombinedRElement element= this.workspace.resolve(ref,
+// RWorkspace.RESOLVE_UPTODATE, loadOptions, m );
+// check(element, m);
+// }
+//
+// private void check(final ICombinedRList list,
+// final SubMonitor m) throws CoreException {
+// if (list.hasModelChildren(null)) {
+// final long length= list.getLength();
+// if (length <= Integer.MAX_VALUE) {
+// final int l= (int) length;
+// ITER_CHILDREN : for (int i= 0; i < l; i++) {
+// final RObject object= list.get(i);
+// if (object != null) {
+// switch (object.getRObjectType()) {
+// case RObject.TYPE_REFERENCE:
+// if (((RReference) object).getReferencedRObjectType() == RObject.TYPE_ENV) {
+// resolve((RReference) object, null, 0, m);
+// }
+// else {
+// }
+// continue ITER_CHILDREN;
+// case RObject.TYPE_LIST:
+// case RObject.TYPE_S4OBJECT:
+// check((ICombinedRList) object, m);
+// continue ITER_CHILDREN;
+// default:
+// continue ITER_CHILDREN;
+// }
+// }
+// }
+// }
+// else {
+// ITER_CHILDREN : for (long i= 0; i < length; i++) {
+// final RObject object= list.get(i);
+// if (object != null) {
+// switch (object.getRObjectType()) {
+// case RObject.TYPE_REFERENCE:
+// if (((RReference) object).getReferencedRObjectType() == RObject.TYPE_ENV) {
+// resolve((RReference) object, null, 0, m);
+// }
+// else {
+// }
+// continue ITER_CHILDREN;
+// case RObject.TYPE_LIST:
+// case RObject.TYPE_S4OBJECT:
+// check((ICombinedRList) object, m);
+// continue ITER_CHILDREN;
+// default:
+// continue ITER_CHILDREN;
+// }
+// }
+// }
+// }
+// }
+// }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/AppActionUtil.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/AppActionUtil.java
new file mode 100644
index 0000000..f4767f7
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/AppActionUtil.java
@@ -0,0 +1,76 @@
+/*=============================================================================#
+ # Copyright (c) 2015, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.shiny.actions;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchWindow;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.debug.ui.config.LaunchConfigManager;
+import org.eclipse.statet.ecommons.debug.ui.config.actions.ActionUtil;
+
+import org.eclipse.statet.internal.r.apps.core.shiny.RShinyResourceTester;
+import org.eclipse.statet.internal.r.apps.ui.RAppUIPlugin;
+import org.eclipse.statet.internal.r.apps.ui.launching.AppType;
+
+
+/**
+ *
+ * element= app container
+ */
+@NonNullByDefault
+public class AppActionUtil extends ActionUtil<IContainer> {
+
+
+ private static final AppType APP_TYPE= new AppType("org.eclipse.statet.r.apps.appTypes.RShiny", //$NON-NLS-1$
+ "R Shiny App" );
+
+
+ public AppActionUtil(final byte initialMode) {
+ super(initialMode);
+ }
+
+
+ @Override
+ public @Nullable IContainer getLaunchElement(final @Nullable IEditorPart editor) {
+ IResource resource= null;
+ if (editor != null) {
+ resource= getSingleResource(editor.getEditorInput());
+ }
+ return (resource != null) ? RShinyResourceTester.getAppContainer(resource) : null;
+ }
+
+ @Override
+ public @Nullable IContainer getLaunchElement(final @Nullable ISelection selection) {
+ IResource resource= null;
+ if (selection instanceof IStructuredSelection) {
+ resource= getSingleResource((IStructuredSelection) selection);
+ }
+ return (resource != null) ? RShinyResourceTester.getAppContainer(resource) : null;
+ }
+
+ @Override
+ public @Nullable LaunchConfigManager<IContainer> getManager(final IWorkbenchWindow window,
+ final IContainer element) {
+ return RAppUIPlugin.getInstance().getRunAppConfigManager(APP_TYPE);
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/AppLaunchShortcut.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/AppLaunchShortcut.java
new file mode 100644
index 0000000..c40ec90
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/AppLaunchShortcut.java
@@ -0,0 +1,34 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.shiny.actions;
+
+import org.eclipse.core.resources.IContainer;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.ecommons.debug.ui.config.actions.ActionUtil;
+import org.eclipse.statet.ecommons.debug.ui.config.actions.RunActiveConfigLaunchShortcut;
+
+
+@NonNullByDefault
+public class AppLaunchShortcut extends RunActiveConfigLaunchShortcut<IContainer> {
+
+
+ public AppLaunchShortcut() {
+ super(new AppActionUtil(ActionUtil.ACTIVE_MENU_SELECTION_MODE));
+ }
+
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/RunActiveAppConfigWorkbenchHandler.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/RunActiveAppConfigWorkbenchHandler.java
new file mode 100644
index 0000000..9106b56
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/RunActiveAppConfigWorkbenchHandler.java
@@ -0,0 +1,70 @@
+/*=============================================================================#
+ # Copyright (c) 2008, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.shiny.actions;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.ui.commands.IElementUpdater;
+
+import org.eclipse.statet.jcommons.collections.ImCollections;
+import org.eclipse.statet.jcommons.collections.ImIdentitySet;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.debug.ui.config.actions.ActionUtil;
+import org.eclipse.statet.ecommons.debug.ui.config.actions.RunActiveConfigScopeHandler;
+import org.eclipse.statet.ecommons.ui.actions.WorkbenchScopingHandler;
+
+
+/**
+ * Handlers for document output creation toolchain running with the active configuration.
+ */
+@NonNullByDefault
+public class RunActiveAppConfigWorkbenchHandler extends WorkbenchScopingHandler
+ implements IElementUpdater, IExecutableExtension {
+
+
+ private ImIdentitySet<String> launchFlags;
+
+
+ /** For instantiation via plugin.xml */
+ @SuppressWarnings("null")
+ public RunActiveAppConfigWorkbenchHandler() {
+ }
+
+
+ protected ImIdentitySet<String> getLaunchFlags() {
+ return this.launchFlags;
+ }
+
+
+ @Override
+ public void setInitializationData(final IConfigurationElement config,
+ final String propertyName, final @Nullable Object data) throws CoreException {
+ super.setInitializationData(config, propertyName, data);
+
+ this.launchFlags= ImCollections.newIdentitySet();
+ }
+
+ @Override
+ protected RunActiveConfigScopeHandler<IContainer> createScopeHandler(final Object scope) {
+ return new RunActiveConfigScopeHandler<>(scope, getCommandId(),
+ new AppActionUtil(ActionUtil.ACTIVE_EDITOR_MODE), getLaunchFlags() );
+ }
+
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/RunAppConfigsDropdownContribution.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/RunAppConfigsDropdownContribution.java
new file mode 100644
index 0000000..c617577
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/RunAppConfigsDropdownContribution.java
@@ -0,0 +1,43 @@
+/*=============================================================================#
+ # Copyright (c) 2007, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.shiny.actions;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.ui.menus.IWorkbenchContribution;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.ecommons.debug.ui.config.actions.RunConfigsDropdownContribution;
+
+
+@NonNullByDefault
+public class RunAppConfigsDropdownContribution extends RunConfigsDropdownContribution<IContainer>
+ implements IWorkbenchContribution, IExecutableExtension {
+
+
+ /** For instantiation via plugin.xml */
+ public RunAppConfigsDropdownContribution() {
+ super(new AppActionUtil(AppActionUtil.ACTIVE_EDITOR_MODE));
+ }
+
+
+ @Override
+ protected AppActionUtil getUtil() {
+ return (AppActionUtil) super.getUtil();
+ }
+
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/RunAppConfigsMenuContribution.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/RunAppConfigsMenuContribution.java
new file mode 100644
index 0000000..4b08fc0
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/shiny/actions/RunAppConfigsMenuContribution.java
@@ -0,0 +1,89 @@
+/*=============================================================================#
+ # Copyright (c) 2007, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.shiny.actions;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.ui.menus.IWorkbenchContribution;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.ecommons.debug.ui.config.actions.ActionUtil;
+import org.eclipse.statet.ecommons.debug.ui.config.actions.RunConfigsMenuContribution;
+
+
+@NonNullByDefault
+public class RunAppConfigsMenuContribution extends RunConfigsMenuContribution<IContainer>
+ implements IWorkbenchContribution, IExecutableExtension {
+
+
+// protected class AppConfigContribution extends ConfigContribution {
+//
+//
+// public AppConfigContribution(final Image icon, final String label,
+// final ILaunchConfiguration configuration) {
+// super(icon, label, configuration);
+// }
+//
+//
+// @Override
+// protected void fillMenu(final Menu menu) {
+// addLaunchItems(menu);
+//
+// new MenuItem(menu, SWT.SEPARATOR);
+// addActivateItem(menu, DocProcessingUI.ACTIONS_ACTIVATE_CONFIG_HELP_CONTEXT_ID);
+// addEditItem(menu, DocProcessingUI.ACTIONS_EDIT_CONFIG_HELP_CONTEXT_ID);
+// }
+//
+// protected void addLaunchItems(final Menu menu) {
+// }
+//
+//
+// protected String createDetail(final String inputExt, final String outputExt) {
+// if (inputExt == null || outputExt == null) {
+// return null;
+// }
+// final StringBuilder sb= getStringBuilder();
+// sb.append("\u2002["); //$NON-NLS-1$
+// sb.append(inputExt);
+// sb.append("\u2002\u2192\u2002"); //$NON-NLS-1$
+// sb.append(outputExt);
+// sb.append("]"); //$NON-NLS-1$
+//
+// return sb.toString();
+// }
+//
+// }
+
+
+ /** For instantiation via plugin.xml */
+ public RunAppConfigsMenuContribution() {
+ super(new AppActionUtil(ActionUtil.ACTIVE_MENU_SELECTION_MODE));
+ }
+
+
+ @Override
+ protected AppActionUtil getUtil() {
+ return (AppActionUtil) super.getUtil();
+ }
+
+
+// @Override
+// protected ConfigContribution createConfigContribution(
+// Image icon, StringBuilder label, ILaunchConfiguration configuration) {
+// return new AppConfigContribution(icon, label.toString(), configuration);
+// }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/variables/AppVarInput.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/variables/AppVarInput.java
new file mode 100644
index 0000000..4aa539d
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/variables/AppVarInput.java
@@ -0,0 +1,35 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.variables;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ltk.model.core.elements.IModelElement.Filter;
+import org.eclipse.statet.r.apps.ui.RApp;
+import org.eclipse.statet.r.ui.util.RElementInput;
+
+
+@NonNullByDefault
+public class AppVarInput extends RElementInput<RApp> {
+
+
+ public AppVarInput(final RApp app,
+ final @Nullable Filter envFilter, final @Nullable Filter otherFilter) {
+ super(app, envFilter, otherFilter);
+ }
+
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/variables/AppVarView.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/variables/AppVarView.java
new file mode 100644
index 0000000..fcc9650
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/variables/AppVarView.java
@@ -0,0 +1,661 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.variables;
+
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
+import static org.eclipse.ui.IWorkbenchCommandConstants.NAVIGATE_COLLAPSE_ALL;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ITreeSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbenchCommandConstants;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.commands.IElementUpdater;
+import org.eclipse.ui.handlers.CollapseAllHandler;
+import org.eclipse.ui.handlers.IHandlerService;
+import org.eclipse.ui.menus.CommandContributionItemParameter;
+import org.eclipse.ui.menus.UIElement;
+import org.eclipse.ui.part.ViewPart;
+import org.eclipse.ui.services.IServiceLocator;
+
+import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ts.core.Tool;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener.ActiveToolEvent;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
+import org.eclipse.statet.ecommons.ui.actions.HandlerCollection;
+import org.eclipse.statet.ecommons.ui.actions.HandlerContributionItem;
+import org.eclipse.statet.ecommons.ui.actions.UIActions;
+import org.eclipse.statet.ecommons.ui.components.StatusInfo;
+import org.eclipse.statet.ecommons.ui.dialogs.DialogUtils;
+import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
+import org.eclipse.statet.ecommons.ui.util.UIAccess;
+import org.eclipse.statet.ecommons.ui.util.ViewActionUtil;
+import org.eclipse.statet.ecommons.ui.workbench.ContextHandlers;
+import org.eclipse.statet.ecommons.ui.workbench.WorkbenchUIUtils;
+
+import org.eclipse.statet.base.ui.StatetImages;
+import org.eclipse.statet.internal.r.apps.ui.RAppUIPlugin;
+import org.eclipse.statet.ltk.ui.sourceediting.ISourceEditorCommandIds;
+import org.eclipse.statet.ltk.ui.util.ViewerDragSupport;
+import org.eclipse.statet.nico.core.runtime.ToolProcess;
+import org.eclipse.statet.nico.ui.IToolRegistry;
+import org.eclipse.statet.nico.ui.IToolRegistryListener;
+import org.eclipse.statet.nico.ui.NicoUI;
+import org.eclipse.statet.nico.ui.ToolSessionUIData;
+import org.eclipse.statet.nico.ui.actions.AbstractToolHandler;
+import org.eclipse.statet.r.apps.ui.AppRegistry;
+import org.eclipse.statet.r.apps.ui.AppRegistry.AppStateEvent;
+import org.eclipse.statet.r.apps.ui.RApp;
+import org.eclipse.statet.r.apps.ui.VariablesData;
+import org.eclipse.statet.r.console.core.RConsoleTool;
+import org.eclipse.statet.r.console.core.RProcess;
+import org.eclipse.statet.r.console.core.RProcessREnvironment;
+import org.eclipse.statet.r.ui.rtool.CopyRElementHandler;
+import org.eclipse.statet.r.ui.rtool.PrintRElementHandler;
+import org.eclipse.statet.r.ui.rtool.RElementViewerDragSourceListener;
+import org.eclipse.statet.r.ui.util.CopyRElementNameHandler;
+import org.eclipse.statet.r.ui.util.RElementInputContentProvider;
+import org.eclipse.statet.r.ui.util.RElementInputLabelProvider;
+import org.eclipse.statet.r.ui.util.RElementInputUtils;
+import org.eclipse.statet.rj.data.RReference;
+
+
+@NonNullByDefault
+public class AppVarView extends ViewPart implements ToolProvider {
+
+
+ public static final String VIEW_ID= "org.eclipse.statet.r.apps.views.VariableViewer"; //$NON-NLS-1$
+
+
+ private static final String REFRESH_COMMAND_ID= IWorkbenchCommandConstants.FILE_REFRESH;
+
+ private static final String FILTER_INCLUDE_INTERNAL_COMMAND_ID= "Filter.IncludeInternal"; //$NON-NLS-1$
+
+ private static final String PRINT_COMMAND_ID= "org.eclipse.statet.r.commands.RunPrintInR"; //$NON-NLS-1$
+
+
+ private static final String FILTER_INCLUDE_INTERNAL_SETTINGS_KEY= "Filter.IncludeInternal.enabled"; //$NON-NLS-1$
+
+
+ private class RefreshHandler extends AbstractToolHandler<RProcess> {
+
+ public RefreshHandler() {
+ super(RConsoleTool.TYPE, null, AppVarView.this, getSite());
+ init();
+ }
+
+
+ @Override
+ protected boolean evaluateIsEnabled(final RProcess tool, final @Nullable Object evaluationContext) {
+ return (super.evaluateIsEnabled(tool, evaluationContext)
+ && getApp() != null );
+ }
+
+ protected void refreshElements() {
+ WorkbenchUIUtils.refreshCommandElements(REFRESH_COMMAND_ID, this, null);
+ }
+
+ @Override
+ protected @Nullable Object execute(final RProcess tool, final ExecutionEvent event) {
+ final RApp app= getApp();
+ if (app != null) {
+ app.refreshVariables();
+ }
+ return null;
+ }
+
+ }
+
+ private class FilterInternalHandler extends AbstractHandler implements IElementUpdater {
+
+ @Override
+ public @Nullable Object execute(final ExecutionEvent event) throws ExecutionException {
+ AppVarView.this.filterIncludeInternal= !AppVarView.this.filterIncludeInternal;
+ AppVarView.this.settings.put(FILTER_INCLUDE_INTERNAL_SETTINGS_KEY, AppVarView.this.filterIncludeInternal);
+ updateFilter();
+ return null;
+ }
+
+ @Override
+ public void updateElement(final UIElement element, final Map parameters) {
+ WorkbenchUIUtils.aboutToUpdateCommandsElements(this, element);
+ try {
+ element.setChecked(AppVarView.this.filterIncludeInternal);
+ }
+ finally {
+ WorkbenchUIUtils.finalizeUpdateCommandsElements(this);
+ }
+ }
+
+ }
+
+
+ private IDialogSettings settings;
+
+ final Object sourceLock= new Object();
+ private IToolRegistryListener toolRegistryListener;
+ private @Nullable RProcess process;
+ private final CopyOnWriteIdentityListSet<ActiveToolListener> toolListeners= new CopyOnWriteIdentityListSet<>();
+
+ private AppRegistry.Listener appRegistryListener;
+ private @Nullable RApp app;
+
+
+ private TreeViewer treeViewer;
+
+ private final ContentJob inputUpdater= new ContentJob(this);
+ private boolean isUpdating;
+
+ private boolean filterIncludeInternal;
+ private String filterText;
+
+ private RElementInputContentProvider<AppVarInput> inputContentProvider;
+
+
+ private ViewActionUtil actionUtil;
+ private ContextHandlers handlers;
+
+ private @Nullable Object currentInfoObject;
+
+
+ private @Nullable RApp shownByLauncher;
+
+
+ @SuppressWarnings("null")
+ public AppVarView() {
+ }
+
+ @Override
+ public void dispose() {
+ if (this.appRegistryListener != null) {
+ AppRegistry.getInstance().removeListener(this.appRegistryListener);
+ this.appRegistryListener= null;
+ }
+ if (this.toolRegistryListener != null) {
+ NicoUI.getToolRegistry().removeListener(this.toolRegistryListener);
+ this.toolRegistryListener= null;
+ }
+ setTool(null, false);
+
+ if (this.handlers != null) {
+ this.handlers.dispose();
+ this.handlers= null;
+ }
+
+ super.dispose();
+ }
+
+
+ @Override
+ public void init(final IViewSite site, final @Nullable IMemento memento) throws PartInitException {
+ super.init(site, memento);
+
+ this.settings= DialogUtils.getDialogSettings(RAppUIPlugin.getInstance(), "AppVarBrowser");
+
+ this.filterIncludeInternal= this.settings.getBoolean(FILTER_INCLUDE_INTERNAL_SETTINGS_KEY);
+ }
+
+ @Override
+ public void createPartControl(final Composite parent) {
+ parent.setLayout(LayoutUtils.newSashGrid());
+
+ this.treeViewer= createTreeViewer(parent);
+ this.treeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ final IPostSelectionProvider treeSelectionProvider= this.treeViewer;
+ treeSelectionProvider.addPostSelectionChangedListener(new ISelectionChangedListener() {
+ @Override
+ public void selectionChanged(final SelectionChangedEvent event) {
+ updateSelectionInfo((ITreeSelection) event.getSelection());
+ }
+ });
+
+ final IViewSite site= getViewSite();
+ site.setSelectionProvider(treeSelectionProvider);
+ this.actionUtil= new ViewActionUtil(this);
+ this.handlers= new ContextHandlers(site.getService(IHandlerService.class));
+ initActions(site, this.handlers);
+ contributeToActionBars(site, site.getActionBars(), this.handlers);
+ hookContextMenu();
+
+ // listen on console changes
+ final IToolRegistry toolRegistry= NicoUI.getToolRegistry();
+ this.toolRegistryListener= new IToolRegistryListener() {
+ @Override
+ public void toolSessionActivated(final ToolSessionUIData sessionData) {
+ final ToolProcess process= sessionData.getProcess();
+ UIAccess.getDisplay().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ setTool(process, true);
+ }
+ });
+ }
+ @Override
+ public void toolTerminated(final ToolSessionUIData sessionData) {
+ final ToolProcess process= sessionData.getProcess();
+ UIAccess.getDisplay().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (process == getTool()) {
+ setTool(null, true);
+ }
+ }
+ });
+ }
+ };
+ toolRegistry.addListener(this.toolRegistryListener, getViewSite().getPage());
+
+ this.appRegistryListener= new AppRegistry.Listener() {
+ @Override
+ public void onAppStateChanged(final AppStateEvent event) {
+ UIAccess.getDisplay(getSite().getShell()).asyncExec(() -> {
+ switch (event.getType()) {
+ case AppRegistry.APP_STARTED:
+ if (event.getApp().getTool() == getTool()) {
+ setApp(event.getApp(), true);
+ }
+ break;
+ case AppRegistry.APP_STOPPED:
+ if (event.getApp() == getApp()) {
+ setApp(null, true);
+ }
+ break;
+ default:
+ break;
+ }
+ });
+ }
+ };
+ AppRegistry.getInstance().addListener(this.appRegistryListener);
+
+ setTool(toolRegistry.getActiveToolSession(getViewSite().getPage()).getProcess(), true);
+ }
+
+ private TreeViewer createTreeViewer(final Composite parent) {
+ final TreeViewer viewer= new TreeViewer(parent, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
+
+ viewer.setLabelProvider(new RElementInputLabelProvider());
+
+ viewer.setUseHashlookup(true);
+ this.inputContentProvider= new RElementInputContentProvider();
+ viewer.setContentProvider(this.inputContentProvider);
+ viewer.setInput(this);
+
+ return viewer;
+ }
+
+ protected void initActions(final IServiceLocator serviceLocator, final ContextHandlers handlers) {
+ handlers.addActivate(REFRESH_COMMAND_ID, new RefreshHandler());
+
+ final CopyRElementHandler copyHandler= new CopyRElementHandler(this.actionUtil,
+ (ILabelProvider) this.treeViewer.getLabelProvider() );
+ handlers.addActivate(IWorkbenchCommandConstants.EDIT_COPY, copyHandler);
+ handlers.addActivate(ISourceEditorCommandIds.COPY_ELEMENT_NAME,
+ new CopyRElementNameHandler(this.actionUtil) );
+
+ final ViewerDragSupport dragSupport= new ViewerDragSupport(this.treeViewer);
+ dragSupport.addDragSourceListener(new RElementViewerDragSourceListener(
+ copyHandler, this.treeViewer ));
+ dragSupport.init();
+
+ handlers.addActivate(PRINT_COMMAND_ID,
+ new PrintRElementHandler(this.actionUtil) );
+
+ handlers.add(FILTER_INCLUDE_INTERNAL_COMMAND_ID,
+ new FilterInternalHandler() );
+
+ handlers.addActivate(NAVIGATE_COLLAPSE_ALL,
+ new CollapseAllHandler(this.treeViewer) );
+ RElementInputUtils.addDoubleClickExpansion(this.treeViewer);
+ }
+
+ protected void contributeToActionBars(final IServiceLocator serviceLocator,
+ final IActionBars actionBars, final HandlerCollection handlers) {
+ final IMenuManager menuManager= actionBars.getMenuManager();
+ final IToolBarManager toolbarManager= actionBars.getToolBarManager();
+
+ menuManager.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ null, HandlerContributionItem.NO_COMMAND_ID, null,
+ null, null, null,
+ "Show &Internal Variables ('.*')", null, null,
+ HandlerContributionItem.STYLE_CHECK, null, false ),
+ nonNullAssert(handlers.get(FILTER_INCLUDE_INTERNAL_COMMAND_ID)) ));
+
+ menuManager.add(new Separator());
+ menuManager.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ "Refresh", REFRESH_COMMAND_ID, null, //$NON-NLS-1$
+ StatetImages.getDescriptor(StatetImages.TOOL_REFRESH), StatetImages.getDescriptor(StatetImages.TOOLD_REFRESH), null,
+ "&Refresh", null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ handlers ));
+
+ toolbarManager.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ null, CollapseAllHandler.COMMAND_ID, null,
+ null, null, null,
+ null, null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ nonNullAssert(handlers.get(NAVIGATE_COLLAPSE_ALL)) ));
+ }
+
+ private void hookContextMenu() {
+ final MenuManager menuManager= new MenuManager("ContextMenu", //$NON-NLS-1$
+ "org.eclipse.statet.r.apps.menus.VariablesViewContextMenu" ); //$NON-NLS-1$
+ menuManager.setRemoveAllWhenShown(true);
+ menuManager.addMenuListener(this::fillContextMenu);
+ final Menu contextMenu= menuManager.createContextMenu(this.treeViewer.getTree());
+ this.treeViewer.getTree().setMenu(contextMenu);
+ getSite().registerContextMenu(menuManager, this.treeViewer);
+ }
+
+ private void fillContextMenu(final IMenuManager m) {
+ final IServiceLocator serviceLocator= getSite();
+ final ContextHandlers handlers= this.handlers;
+
+ m.add(new Separator(UIActions.EDIT_GROUP_ID));
+ m.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ "Copy", IWorkbenchCommandConstants.EDIT_COPY, null, //$NON-NLS-1$
+ null, null, null,
+ null, null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ handlers ));
+ m.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ "Copy.ElementName", ISourceEditorCommandIds.COPY_ELEMENT_NAME, null, //$NON-NLS-1$
+ null, null, null,
+ null, null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ handlers ));
+ m.add(new Separator());
+ m.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ null, PRINT_COMMAND_ID, null,
+ null, null, null,
+ null, null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ handlers ));
+
+ m.add(new Separator(UIActions.ADDITIONS_GROUP_ID));
+ }
+
+ @Override
+ public void setFocus() {
+ this.treeViewer.getControl().setFocus();
+ }
+
+
+ /** UI thread only (called by update job) */
+ void updateView(final @Nullable AppVarInput input,
+ final @Nullable List<RProcessREnvironment> updateEnvirs) {
+ if (!UIAccess.isOkToUse(this.treeViewer)) {
+ return;
+ }
+ this.isUpdating= true;
+
+// this.hoveringController.stop();
+
+ this.inputContentProvider.setInput(input);
+
+ final Set<RReference> previousReferences= this.inputContentProvider.resetUsedReferences();
+ if (input != null && updateEnvirs != null) {
+ for (final RProcessREnvironment entry : updateEnvirs) {
+ this.treeViewer.refresh(entry, true);
+ }
+ if (!previousReferences.isEmpty()) {
+ final Set<RReference> usedReferences= this.inputContentProvider.getUsedReferences();
+ ITER_REFS: for (final RReference reference : previousReferences) {
+ if (!usedReferences.contains(reference)) {
+ // Update the envir copy in the viewer, if it refers to an updated envir
+ for (final RProcessREnvironment entry : updateEnvirs) {
+ if (entry.getHandle() == reference.getHandle()) {
+ this.treeViewer.refresh(reference, true);
+ // reference is readded automatically to new set, if necessary
+ continue ITER_REFS;
+ }
+ }
+ // Keep/readd the reference, if it refers to an envir in the search path
+// for (final ICombinedREnvironment entry : input.searchEnvirs) {
+// if (entry.getHandle() == reference.getHandle()) {
+// usedReferences.add(reference);
+// continue ITER_REFS;
+// }
+// }
+ }
+ }
+ }
+ }
+ else {
+ this.treeViewer.refresh(true);
+ }
+
+ updateSelectionInfo((ITreeSelection) this.actionUtil.getSelectionProvider().getSelection());
+ }
+
+ private void updateFilter() {
+ this.inputUpdater.schedule();
+ }
+
+ private void clearActionInfo() {
+ this.actionUtil.getStatusLine().clearAll();
+ }
+
+ private void updateSelectionInfo(final ITreeSelection selection) {
+ if (this.isUpdating) {
+ return;
+ }
+ final Object infoObject= null;
+ final String message= null;
+
+// if (tool != null && !selection.isEmpty()) {
+// if (selection.size() == 1) {
+// final TreePath treePath= selection.getPaths()[0];
+// final IElementName elementName= getFQElementName(treePath);
+// final String name= (elementName != null) ? elementName.getDisplayName() : null;
+// if (name != null) {
+// infoObject= selection.getFirstElement();
+// message= name;
+// }
+// }
+// else {
+// message= NLS.bind("{0} items selected", selection.size());
+// }
+// if (message != null) {
+// message= NLS.bind("{0} \u2012 {1}", message, tool.getLabel(ITool.DEFAULT_LABEL)); //$NON-NLS-1$
+// }
+// }
+
+ if (infoObject == null || !infoObject.equals(this.currentInfoObject)) {
+ clearActionInfo();
+ }
+ this.currentInfoObject= infoObject;
+ this.actionUtil.getStatusLine().setSelectionMessage(
+ (message != null) ? new StatusInfo(IStatus.OK, message) : null );
+ }
+
+
+ @Override
+ public @Nullable RProcess getTool() {
+ return this.process;
+ }
+
+ @Override
+ public void addToolListener(final ActiveToolListener action) {
+ this.toolListeners.add(action);
+ }
+
+ @Override
+ public void removeToolListener(final ActiveToolListener action) {
+ this.toolListeners.remove(action);
+ }
+
+ /** UI thread only */
+ private void setTool(final @Nullable ToolProcess tool, final boolean update) {
+ final RProcess process= (tool != null
+ && tool.isProvidingFeatureSet(RConsoleTool.R_DATA_FEATURESET_ID)
+ && !tool.isTerminated() ) ?
+ (RProcess) tool : null;
+ if (this.process == tool) {
+ return;
+ }
+ final RProcess oldProcess= process;
+ synchronized (this.sourceLock) {
+ this.process= process;
+ }
+
+ final ActiveToolEvent event= new ActiveToolEvent(ActiveToolEvent.TOOL_ACTIVATED, process);
+ for (final ActiveToolListener listener : this.toolListeners) {
+ listener.onToolChanged(event);
+ }
+
+ setApp((process != null) ? AppRegistry.getInstance().getApp(process) : null, update);
+ }
+
+ public @Nullable RApp getApp() {
+ return this.app;
+ }
+
+ /** UI thread only */
+ private void setApp(@Nullable RApp app, final boolean update) {
+ if (app != null && app.getVariables() == null) {
+ app= null;
+ }
+ if (this.app == app) {
+ return;
+ }
+
+ final RApp oldApp= this.app;
+ if (oldApp != null) {
+ oldApp.removeListener(this.inputUpdater);
+ }
+ synchronized (this.sourceLock) {
+ this.app= app;
+ }
+ clearActionInfo();
+
+ this.inputUpdater.forceUpdate(app);
+ if (app != null) {
+ setContentDescription(computeContentDescription(app));
+ app.addListener(this.inputUpdater);
+ }
+ else {
+ setContentDescription("No app at this time.");
+ }
+ if (update) {
+ this.inputUpdater.schedule();
+
+ if (app == null && oldApp == this.shownByLauncher) {
+ Display.getCurrent().timerExec(200, () -> {
+ showPreviousView(oldApp);
+ });
+ }
+ }
+ }
+
+ private String computeContentDescription(final RApp app) {
+ final StringBuilder sb= new StringBuilder();
+
+ final VariablesData vars= app.getVariables();
+ if (vars != null) {
+ sb.append(vars.getExpression());
+ }
+ else {
+ sb.append("<no available>");
+ }
+
+ final IResource resource= app.getResource();
+ if (resource != null) {
+ if (sb.length() > 0) {
+ sb.append("\u2002\u2013\u2002"); //$NON-NLS-1$
+ }
+ sb.append(resource.getFullPath().toString());
+ }
+
+ return sb.toString();
+ }
+
+
+ public boolean getFilterIncludeInternal() {
+ return this.filterIncludeInternal;
+ }
+
+ public String getFilterSearchText() {
+ return this.filterText;
+ }
+
+
+ public void setShownByLauncher(final RApp app) {
+ this.shownByLauncher= app;
+ }
+
+ private void showPreviousView(final RApp oldApp) {
+ if (this.app == null && oldApp == this.shownByLauncher) {
+ final IWorkbenchPage page= getSite().getPage();
+ final IViewPart[] viewStack= page.getViewStack(this);
+ if (viewStack != null && viewStack.length >= 2 && viewStack[0] == this) {
+ page.bringToTop(viewStack[1]);
+ }
+ }
+ }
+
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getAdapter(final Class<T> adapterType) {
+ if (adapterType == Control.class) {
+ return (T) this.treeViewer.getTree();
+ }
+ if (adapterType == Tool.class) {
+ return (T) this.process;
+ }
+ return super.getAdapter(adapterType);
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/variables/ContentJob.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/variables/ContentJob.java
new file mode 100644
index 0000000..3386438
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/variables/ContentJob.java
@@ -0,0 +1,265 @@
+/*=============================================================================#
+ # Copyright (c) 2009, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.variables;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.ui.dialogs.SearchPattern;
+import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
+
+import org.eclipse.statet.jcommons.lang.NonNull;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ui.util.UIAccess;
+
+import org.eclipse.statet.ltk.model.core.elements.IModelElement;
+import org.eclipse.statet.r.apps.ui.RApp;
+import org.eclipse.statet.r.apps.ui.RApp.AppEvent;
+import org.eclipse.statet.r.apps.ui.VariablesData;
+import org.eclipse.statet.r.console.core.RProcessREnvironment;
+import org.eclipse.statet.r.core.data.CombinedRElement;
+import org.eclipse.statet.r.ui.util.RNameSearchPattern;
+
+
+@NonNullByDefault
+class ContentJob extends Job implements RApp.Listener {
+
+
+ static class ContentFilter implements IModelElement.Filter {
+
+ private final boolean filterInternal;
+ private final @Nullable SearchPattern searchPattern;
+
+
+ public ContentFilter(final boolean filterInternal, final @Nullable SearchPattern pattern) {
+ this.filterInternal= filterInternal;
+ this.searchPattern= pattern;
+ }
+
+
+ @Override
+ public boolean include(final IModelElement element) {
+ final String name= element.getElementName().getSegmentName();
+ if (name != null) {
+ if (this.filterInternal && name.length() > 0 && name.charAt(0) == '.') {
+ return false;
+ }
+ return (this.searchPattern == null || this.searchPattern.matches(name));
+ }
+ else {
+ return true;
+ }
+ }
+
+ }
+
+
+ private final AppVarView view;
+
+ /** the app to update */
+ private @Nullable RApp updateSource;
+ /** the app of last update */
+ private @Nullable RApp lastSource;
+ /** update all environment */
+ private boolean force;
+
+ private @Nullable VariablesData rawInput;
+
+ private volatile boolean isScheduled;
+
+
+ public ContentJob(final AppVarView view) {
+ super("R Object Browser Update");
+ this.view= view;
+ setSystem(true);
+ setUser(false);
+ }
+
+
+ @Override
+ public void onVariablesChanged(final AppEvent event) {
+ schedule(event.getApp());
+ }
+
+ public void forceUpdate(final @Nullable RApp app) {
+ synchronized (this.view.sourceLock) {
+ if (app != this.view.getApp()) {
+ return;
+ }
+ this.updateSource= app;
+ this.force= true;
+ }
+ }
+
+ public void schedule(final RApp app) {
+ if (app != null) {
+ synchronized (this.view.sourceLock) {
+ if (app != this.view.getApp()) {
+ return;
+ }
+ this.updateSource= app;
+ }
+ }
+ schedule();
+ }
+
+ @Override
+ public boolean shouldSchedule() {
+ this.isScheduled= true;
+ return true;
+ }
+
+ @Override
+ protected IStatus run(final IProgressMonitor monitor) {
+ if (!this.isScheduled) {
+ return Status.CANCEL_STATUS;
+ }
+
+ final IWorkbenchSiteProgressService progressService= this.view.getViewSite().getService(IWorkbenchSiteProgressService.class);
+ if (progressService != null) {
+ progressService.incrementBusy();
+ }
+
+ try {
+ final RApp app;
+ final boolean sourceChanged;
+ final boolean updateInput;
+ synchronized (this.view.sourceLock) {
+ this.isScheduled= false;
+
+ app= this.view.getApp();
+ sourceChanged= (app != this.lastSource);
+ updateInput= (sourceChanged || this.updateSource != null);
+ this.lastSource= app;
+ this.updateSource= null;
+ this.force= false;
+ }
+
+ final AppVarInput input= (app != null) ? createInput(app) : null;
+
+ // Update input and refresh
+ final List<RProcessREnvironment> toUpdate;
+ if (updateInput) {
+ toUpdate= updateFromSource(input);
+ }
+ else {
+ toUpdate= null;
+ }
+
+ prepare(input);
+
+ synchronized (this.view.sourceLock) {
+ if (app != this.view.getApp()) {
+ this.lastSource= null;
+ return Status.CANCEL_STATUS;
+ }
+ if ((!sourceChanged && this.isScheduled) || monitor.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+ }
+ UIAccess.getDisplay().syncExec(() -> {
+ if (app != ContentJob.this.view.getApp()) {
+ return;
+ }
+ ContentJob.this.view.updateView(input, toUpdate);
+ });
+
+ return Status.OK_STATUS;
+ }
+ finally {
+ if (progressService != null) {
+ progressService.decrementBusy();
+ }
+ }
+ }
+
+ private AppVarInput createInput(final RApp source) {
+ final boolean filterInternal= !this.view.getFilterIncludeInternal();
+ final String filterText= this.view.getFilterSearchText();
+ IModelElement.Filter envFilter;
+ IModelElement.Filter otherFilter;
+ if (filterText != null && filterText.length() > 0) {
+ final SearchPattern filterPattern= new RNameSearchPattern();
+ filterPattern.setPattern(filterText);
+ envFilter= new ContentFilter(filterInternal, filterPattern);
+ otherFilter= (filterInternal) ? new ContentFilter(filterInternal, null) : null;
+ }
+ else if (filterInternal) {
+ envFilter= new ContentFilter(filterInternal, null);
+ otherFilter= new ContentFilter(filterInternal, null);
+ }
+ else {
+ envFilter= null;
+ otherFilter= null;
+ }
+ return new AppVarInput(source, envFilter, otherFilter);
+ }
+
+ private @Nullable List<RProcessREnvironment> updateFromSource(final @Nullable AppVarInput input) {
+ if (input == null) {
+ this.rawInput= null;
+ return null;
+ }
+
+ final RApp app= input.getSource();
+ final VariablesData oldInput= this.rawInput;
+ final VariablesData data= app.getVariables();
+ this.rawInput= data;
+ if (data != null) {
+ // If search path (environments) is not changed and not in force mode, refresh only the updated entries
+ final List<RProcessREnvironment> updateEntries= null;
+
+ return updateEntries;
+ }
+ else {
+ return null;
+ }
+ }
+
+ private void prepare(final @Nullable AppVarInput input) {
+ final VariablesData rawInput= this.rawInput;
+ if (input == null || rawInput == null) {
+ return;
+ }
+
+ @NonNull CombinedRElement[] array;
+
+ final List<? extends CombinedRElement> elements= rawInput.getElements();
+ if (elements != null) {
+// if (elements.size() == 1) {
+// ICombinedRElement single= elements.get(0);
+// }
+
+ array= elements.toArray(new @NonNull CombinedRElement[elements.size()]);
+
+ if (input.hasEnvFilter()) { // prepare env filter
+ for (int i= 0; i < array.length; i++) {
+ input.getEnvChildren(array[i]);
+ }
+ }
+ }
+ else {
+ array= null;
+ }
+
+ input.setRootElements(array);
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/viewer/AppBrowserPage.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/viewer/AppBrowserPage.java
new file mode 100644
index 0000000..bf3c63c
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/viewer/AppBrowserPage.java
@@ -0,0 +1,153 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.viewer;
+
+import static org.eclipse.statet.ecommons.debug.ui.ECommonsDebugUI.TERMINATE_COMMAND_ID;
+import static org.eclipse.statet.ecommons.debug.ui.ECommonsDebugUI.TERMINATE_RELAUNCH_COMMAND_ID;
+import static org.eclipse.statet.internal.r.apps.ui.viewer.AppBrowserView.APP_CONTROL_GROUP_ID;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.menus.CommandContributionItemParameter;
+import org.eclipse.ui.services.IServiceLocator;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ui.actions.HandlerCollection;
+import org.eclipse.statet.ecommons.ui.actions.HandlerContributionItem;
+import org.eclipse.statet.ecommons.ui.mpbv.PageBookBrowserPage;
+import org.eclipse.statet.ecommons.ui.workbench.ContextHandlers;
+
+import org.eclipse.statet.internal.r.apps.ui.Messages;
+import org.eclipse.statet.r.apps.ui.RApp;
+
+
+@NonNullByDefault
+public class AppBrowserPage extends PageBookBrowserPage {
+
+
+ private class StopAppHandler extends AbstractHandler {
+
+ @Override
+ public void setEnabled(final @Nullable Object evaluationContext) {
+ final AppBrowserSession session= getSession();
+ final RApp app= session.getLatestApp();
+ setBaseEnabled(app != null && app.canStopApp());
+ }
+
+ @Override
+ public @Nullable Object execute(final ExecutionEvent event) throws ExecutionException {
+ final AppBrowserSession session= getSession();
+ final RApp app= session.getLatestApp();
+ if (app != null) {
+ app.stopApp();
+ }
+ return null;
+ }
+
+ }
+
+ private class RestartAppHandler extends AbstractHandler {
+
+ @Override
+ public void setEnabled(final @Nullable Object evaluationContext) {
+ final AppBrowserSession session= getSession();
+ final RApp app= session.getLatestApp();
+ setBaseEnabled(app != null && app.canRestartApp());
+ }
+
+ @Override
+ public @Nullable Object execute(final ExecutionEvent event) throws ExecutionException {
+ try {
+ final AppBrowserSession session= getSession();
+ final RApp app= session.getLatestApp();
+ if (app != null) {
+ app.restartApp(getSite().getPage());
+ }
+ return null;
+ }
+ catch (final CoreException e) {
+ // show message?
+ return null;
+ }
+ }
+
+ }
+
+
+ public AppBrowserPage(final AppBrowserView view, final AppBrowserSession session) {
+ super(view, session);
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ }
+
+
+ @Override
+ public AppBrowserSession getSession() {
+ return (AppBrowserSession) super.getSession();
+ }
+
+
+ @Override
+ protected @Nullable Control createAddressBar(final Composite parent) {
+ return null;
+ }
+
+ @Override
+ protected void initActions(final IServiceLocator serviceLocator, final ContextHandlers handlers) {
+ super.initActions(serviceLocator, handlers);
+
+ handlers.addActivate(TERMINATE_COMMAND_ID, new StopAppHandler());
+ handlers.addActivate(TERMINATE_RELAUNCH_COMMAND_ID, new RestartAppHandler());
+ }
+
+ @Override
+ protected void contributeToActionBars(final IServiceLocator serviceLocator,
+ final IActionBars actionBars, final HandlerCollection handlers) {
+ super.contributeToActionBars(serviceLocator, actionBars, handlers);
+
+ final IToolBarManager toolBarManager= actionBars.getToolBarManager();
+
+ toolBarManager.appendToGroup(APP_CONTROL_GROUP_ID, new HandlerContributionItem(
+ new CommandContributionItemParameter(
+ serviceLocator, TERMINATE_RELAUNCH_COMMAND_ID,
+ TERMINATE_RELAUNCH_COMMAND_ID, null,
+ null, null, null,
+ Messages.Action_RestartApp_label, null, Messages.Action_RestartApp_label,
+ HandlerContributionItem.STYLE_PUSH,
+ null, false ),
+ handlers ));
+ toolBarManager.appendToGroup(APP_CONTROL_GROUP_ID, new HandlerContributionItem(
+ new CommandContributionItemParameter(
+ serviceLocator, TERMINATE_COMMAND_ID,
+ TERMINATE_COMMAND_ID, null,
+ null, null, null,
+ Messages.Action_StopApp_label, null, Messages.Action_StopApp_label,
+ HandlerContributionItem.STYLE_PUSH,
+ null, false ),
+ handlers ));
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/viewer/AppBrowserSession.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/viewer/AppBrowserSession.java
new file mode 100644
index 0000000..f4695b5
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/viewer/AppBrowserSession.java
@@ -0,0 +1,77 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.viewer;
+
+import java.net.URL;
+
+import org.eclipse.core.resources.IResource;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ts.core.Tool;
+import org.eclipse.statet.ecommons.ui.mpbv.BrowserSession;
+
+import org.eclipse.statet.r.apps.ui.AppRegistry;
+import org.eclipse.statet.r.apps.ui.RApp;
+
+
+@NonNullByDefault
+public class AppBrowserSession extends BrowserSession {
+
+
+ private final URL id;
+
+
+ public AppBrowserSession(final URL id) {
+ this.id= id;
+ }
+
+
+ @Override
+ public URL getId() {
+ return this.id;
+ }
+
+ @Override
+ public String getLabel() {
+ final StringBuilder sb= new StringBuilder();
+ sb.append(super.getLabel());
+
+ final RApp app= getLatestApp();
+ if (app != null) {
+ final IResource resource= app.getResource();
+ if (resource != null) {
+ if (sb.length() > 0) {
+ sb.append("\u2002\u2013\u2002"); //$NON-NLS-1$
+ }
+ sb.append(resource.getFullPath().toString());
+ }
+
+ final Tool tool= app.getTool();
+ if (tool != null) {
+ sb.append(" │ "); //$NON-NLS-1$
+ sb.append(tool.getLabel(Tool.DEFAULT_LABEL));
+ }
+ }
+
+ return sb.toString();
+ }
+
+ public @Nullable RApp getLatestApp() {
+ return AppRegistry.getInstance().getApp(this.id);
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/viewer/AppBrowserView.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/viewer/AppBrowserView.java
new file mode 100644
index 0000000..3fb628c
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/internal/r/apps/ui/viewer/AppBrowserView.java
@@ -0,0 +1,109 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.internal.r.apps.ui.viewer;
+
+import java.net.URL;
+
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.services.IServiceLocator;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.ecommons.ui.actions.HandlerCollection;
+import org.eclipse.statet.ecommons.ui.actions.UIActions;
+import org.eclipse.statet.ecommons.ui.mpbv.BrowserSession;
+import org.eclipse.statet.ecommons.ui.mpbv.PageBookBrowserPage;
+import org.eclipse.statet.ecommons.ui.mpbv.PageBookBrowserView;
+import org.eclipse.statet.ecommons.ui.util.UIAccess;
+
+import org.eclipse.statet.r.apps.ui.AppRegistry;
+import org.eclipse.statet.r.apps.ui.AppRegistry.AppStateEvent;
+
+
+@NonNullByDefault
+public class AppBrowserView extends PageBookBrowserView {
+
+
+ public static final String VIEW_ID= "org.eclipse.statet.r.apps.views.AppViewer"; //$NON-NLS-1$
+
+ public static final String APP_CONTROL_GROUP_ID= "app.Control"; //$NON-NLS-1$
+
+
+ private AppRegistry.Listener appRegistryListener;
+
+
+ /** plugin.xml */
+ public AppBrowserView() {
+ super();
+ }
+
+ @Override
+ public void dispose() {
+ if (this.appRegistryListener != null) {
+ AppRegistry.getInstance().removeListener(this.appRegistryListener);
+ this.appRegistryListener= null;
+ }
+
+ super.dispose();
+ }
+
+
+ @Override
+ public void createPartControl(final Composite parent) {
+ super.createPartControl(parent);
+
+ this.appRegistryListener= new AppRegistry.Listener() {
+ @Override
+ public void onAppStateChanged(final AppStateEvent event) {
+ UIAccess.getDisplay(getSite().getShell()).asyncExec(() -> {
+ if (isCurrent(event.getId())) {
+ updateTitle();
+ updateState();
+ }
+ });
+ }
+ };
+ AppRegistry.getInstance().addListener(this.appRegistryListener);
+ }
+
+ @Override
+ protected void contributeToActionBars(final IServiceLocator serviceLocator,
+ final IActionBars actionBars, final HandlerCollection handlers) {
+ super.contributeToActionBars(serviceLocator, actionBars, handlers);
+
+ final IToolBarManager toolBarManager= actionBars.getToolBarManager();
+ toolBarManager.insertBefore(UIActions.ADDITIONS_GROUP_ID,
+ new Separator(APP_CONTROL_GROUP_ID) );
+ }
+
+ @Override
+ protected PageBookBrowserPage doCreatePage(final BrowserSession session) {
+ if (session instanceof AppBrowserSession) {
+ return new AppBrowserPage(this, (AppBrowserSession) session);
+ }
+ return super.doCreatePage(session);
+ }
+
+
+ private boolean isCurrent(final URL id) {
+ final BrowserSession session= getCurrentSession();
+ return (session != null && id.equals(session.getId())
+ && UIAccess.isOkToUse(getPageBook()) );
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/AppRegistry.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/AppRegistry.java
new file mode 100644
index 0000000..ed42ca5
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/AppRegistry.java
@@ -0,0 +1,150 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.apps.ui;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ts.core.Tool;
+
+
+@NonNullByDefault
+public class AppRegistry {
+
+
+ public static final byte APP_STARTED= 1;
+ public static final byte APP_STOPPED= 2;
+
+
+ public static class AppStateEvent extends RApp.AppEvent {
+
+
+ private final byte type;
+
+ private final URL id;
+
+
+ public AppStateEvent(final byte type, final URL id, final RApp app) {
+ super(app);
+ this.type= type;
+ this.id= id;
+ }
+
+
+ public byte getType() {
+ return this.type;
+ }
+
+ public URL getId() {
+ return this.id;
+ }
+
+ }
+
+ public static interface Listener {
+
+
+ void onAppStateChanged(AppStateEvent event);
+
+ }
+
+
+ private static class AppEntry {
+
+
+ private final URL id;
+
+ private RApp app;
+ private boolean isRunning;
+
+
+ public AppEntry(final URL id) {
+ this.id= id;
+ }
+
+ }
+
+
+ private static final AppRegistry INSTANCE= new AppRegistry();
+
+ public static AppRegistry getInstance() {
+ return INSTANCE;
+ }
+
+
+ private final Map<URL, AppEntry> sessions= new HashMap<>();
+
+ private final CopyOnWriteIdentityListSet<Listener> listeners= new CopyOnWriteIdentityListSet<>();
+
+
+ public AppRegistry() {
+ }
+
+
+ public void addListener(final Listener listener) {
+ this.listeners.add(listener);
+ }
+
+ public void removeListener(final Listener listener) {
+ this.listeners.remove(listener);
+ }
+
+ private void notifyListeners(final AppStateEvent event) {
+ for (final Listener listener : this.listeners) {
+ listener.onAppStateChanged(event);
+ }
+ }
+
+
+ public synchronized void onAppStarted(final URL id, final RApp app) {
+ final AppEntry entry= this.sessions.computeIfAbsent(id, AppEntry::new);
+
+ if (entry.isRunning) {
+ notifyListeners(new AppStateEvent(APP_STOPPED, id, entry.app));
+ }
+
+ entry.app= app;
+ entry.isRunning= true;
+ notifyListeners(new AppStateEvent(APP_STARTED, id, app));
+ }
+
+ public synchronized void onAppStopped(final URL id, final RApp app) {
+ final AppEntry entry= this.sessions.get(id);
+ if (entry != null && entry.app == app) {
+ entry.isRunning= false;
+ notifyListeners(new AppStateEvent(APP_STOPPED, id, app));
+ }
+ }
+
+ public synchronized @Nullable RApp getApp(final URL id) {
+ final AppEntry entry= this.sessions.get(id);
+ return (entry != null) ? entry.app : null;
+ }
+
+ public synchronized @Nullable RApp getApp(final Tool tool) {
+ for (final AppEntry entry : this.sessions.values()) {
+ if (entry.isRunning && entry.app.getTool() == tool) {
+ return entry.app;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/RApp.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/RApp.java
new file mode 100644
index 0000000..ab08bc5
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/RApp.java
@@ -0,0 +1,75 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.apps.ui;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.ui.IWorkbenchPage;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.ts.core.Tool;
+
+
+@NonNullByDefault
+public interface RApp {
+
+
+ class AppEvent {
+
+ private final RApp app;
+
+
+ public AppEvent(final RApp app) {
+ this.app= app;
+ }
+
+
+ public RApp getApp() {
+ return this.app;
+ }
+
+ }
+
+ interface Listener {
+
+
+ void onVariablesChanged(AppEvent event);
+
+ }
+
+
+ IResource getResource();
+
+ @Nullable Tool getTool();
+
+ boolean isRunning();
+
+ void startApp(IWorkbenchPage page) throws CoreException;
+ boolean canRestartApp();
+ void restartApp(IWorkbenchPage page) throws CoreException;
+
+ boolean canStopApp();
+ void stopApp();
+
+
+ void addListener(Listener listener);
+ void removeListener(Listener listener);
+
+ @Nullable VariablesData getVariables();
+ void refreshVariables();
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/RAppUIResources.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/RAppUIResources.java
new file mode 100644
index 0000000..bff8066
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/RAppUIResources.java
@@ -0,0 +1,56 @@
+/*=============================================================================#
+ # Copyright (c) 2009, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.apps.ui;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.internal.r.apps.ui.RAppUIPlugin;
+
+
+@NonNullByDefault
+public class RAppUIResources {
+
+
+ private static final String NS= "org.eclipse.statet.r.apps"; //$NON-NLS-1$
+
+
+ public static final String TOOL_VIEW_IMAGE_ID= NS + "/image/tool/View"; //$NON-NLS-1$
+
+
+ public static final RAppUIResources INSTANCE= new RAppUIResources();
+
+
+ private final ImageRegistry registry;
+
+
+ private RAppUIResources() {
+ this.registry= RAppUIPlugin.getInstance().getImageRegistry();
+ }
+
+
+ public @Nullable ImageDescriptor getImageDescriptor(final String id) {
+ return this.registry.getDescriptor(id);
+ }
+
+ public @Nullable Image getImage(final String id) {
+ return this.registry.get(id);
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/VariablesData.java b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/VariablesData.java
new file mode 100644
index 0000000..1d11a94
--- /dev/null
+++ b/r/org.eclipse.statet.r.apps/src/org/eclipse/statet/r/apps/ui/VariablesData.java
@@ -0,0 +1,76 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.apps.ui;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+import org.eclipse.statet.jcommons.collections.ImList;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+import org.eclipse.statet.jcommons.lang.ObjectUtils.ToStringBuilder;
+
+import org.eclipse.statet.r.core.data.CombinedRElement;
+
+
+@NonNullByDefault
+public class VariablesData {
+
+
+ private final String expression;
+
+ private final IStatus status;
+
+ private final @Nullable ImList<CombinedRElement> elements;
+
+
+ public VariablesData(final String expression,
+ final ImList<CombinedRElement> elements) {
+ this.expression= expression;
+ this.status= Status.OK_STATUS;
+ this.elements= elements;
+ }
+
+ public VariablesData(final String expression,
+ final IStatus status) {
+ this.expression= expression;
+ this.status= status;
+ this.elements= null;
+ }
+
+
+ public String getExpression() {
+ return this.expression;
+ }
+
+ public IStatus getStatus() {
+ return this.status;
+ }
+
+ public @Nullable ImList<CombinedRElement> getElements() {
+ return this.elements;
+ }
+
+
+ @Override
+ public String toString() {
+ final ToStringBuilder sb= new ToStringBuilder("VariablesData"); //$NON-NLS-1$
+ sb.addProp("expression", this.expression); //$NON-NLS-1$
+ sb.addProp("status", this.status); //$NON-NLS-1$
+ sb.addProp("elements", this.elements); //$NON-NLS-1$
+ return sb.toString();
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/AbstractRController.java b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/AbstractRController.java
index 1ca2a6c..4e8cd2f 100644
--- a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/AbstractRController.java
+++ b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/AbstractRController.java
@@ -30,6 +30,7 @@
import org.eclipse.statet.ltk.model.core.elements.ISourceUnit;
import org.eclipse.statet.nico.core.runtime.ITrack;
+import org.eclipse.statet.nico.core.runtime.Queue.Section;
import org.eclipse.statet.nico.core.runtime.SubmitType;
import org.eclipse.statet.nico.core.runtime.ToolController;
import org.eclipse.statet.nico.core.runtime.ToolStreamProxy;
@@ -87,8 +88,9 @@
private List<TrackingConfiguration> trackingConfigurations;
- public AbstractRController(final RProcess process, final Map<String, Object> initData) {
- super(process, initData);
+ public AbstractRController(final RProcess process,
+ final Map<String, Object> connectionInfo) {
+ super(process, connectionInfo);
process.registerFeatureSet(RConsoleTool.R_BASIC_FEATURESET_ID);
}
@@ -199,11 +201,11 @@
@Override
- protected void doRunSuspendedLoopL(final int o, final int level) {
+ protected void doRunSuspendedLoopL(final int o, final int level, final Section queueSection) {
briefChanged(RWorkspace.REFRESH_AUTO);
final Changes savedChanges= getWorkspaceData().saveChanges();
try {
- super.doRunSuspendedLoopL(o, level);
+ super.doRunSuspendedLoopL(o, level, queueSection);
}
finally {
getWorkspaceData().restoreChanges(savedChanges);
diff --git a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/RWorkspace.java b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/RWorkspace.java
index 62d463b..ead9cf9 100644
--- a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/RWorkspace.java
+++ b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/RWorkspace.java
@@ -363,7 +363,7 @@
RReferenceVar ref= null;
if (reference instanceof RReferenceVar) {
ref= (RReferenceVar) reference;
- if (ref.getHandle() == 0 || controller.getHotTasksState() > 1 || !isUptodate(ref)) {
+ if (ref.getHandle() == 0 || !isUptodate(ref)) {
ref= verifyVar(RModel.getFQElementName(ref),
(ICombinedRDataAdapter) controller, monitor );
}
diff --git a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/util/RCodeVariableText.java b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/util/RCodeVariableText.java
new file mode 100644
index 0000000..a9efaa5
--- /dev/null
+++ b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/util/RCodeVariableText.java
@@ -0,0 +1,59 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.console.core.util;
+
+import java.util.Map;
+
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.variables.IStringVariable;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+import org.eclipse.statet.ecommons.io.FileUtil;
+import org.eclipse.statet.ecommons.variables.core.VariableText2;
+
+import org.eclipse.statet.r.console.core.RWorkspace;
+import org.eclipse.statet.r.core.RUtil;
+
+
+@NonNullByDefault
+public class RCodeVariableText extends VariableText2 {
+
+
+ private final RWorkspace rWorkspace;
+
+
+ public RCodeVariableText(final RWorkspace rWorkspace,
+ final Map<String, IStringVariable> variables) {
+ super(variables);
+
+ this.rWorkspace= rWorkspace;
+ }
+
+
+ @Override
+ protected String checkValue(final IStringVariable variable, String value) throws CoreException {
+ if (variable.getName().endsWith("_loc")) { //$NON-NLS-1$
+ if (this.rWorkspace.isRemote()) {
+ final IFileStore store= FileUtil.getFileStore(value);
+ value= this.rWorkspace.toToolPath(store);
+ }
+ return RUtil.escapeBackslash(value);
+ }
+ return value;
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/AbstractRDbgController.java b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/AbstractRDbgController.java
index a0fedaf..110a59f 100644
--- a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/AbstractRDbgController.java
+++ b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/AbstractRDbgController.java
@@ -183,7 +183,7 @@
initTopLevelBrowser(monitor);
break;
case TOPLEVELBROWSER_CHECK_SUSPENDED:
- if (getQueue().size() > 0) {
+ if (getQueue().getCurrentSize() > 0) {
AbstractRDbgController.this.topLevelBrowserAction= TOPLEVELBROWSER_CHECK_SUBMIT;
break;
}
@@ -239,11 +239,12 @@
/**
*
* @param process the R process the controller belongs to
- * @param initData the initialization data
+ * @param connectionInfo the initialization data
* @param enableDebug if debug features should be enabled
*/
- public AbstractRDbgController(final RProcess process, final Map<String, Object> initData) {
- super(process, initData);
+ public AbstractRDbgController(final RProcess process,
+ final Map<String, Object> connectionInfo) {
+ super(process, connectionInfo);
}
diff --git a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/impl/RjsController.java b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/impl/RjsController.java
index b3f6f5d..1bb06eb 100644
--- a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/impl/RjsController.java
+++ b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/impl/RjsController.java
@@ -458,19 +458,19 @@
*
* @param process the R process the controller belongs to
* @param address the RMI address
- * @param initData the initialization data
+ * @param connectionInfo the initialization data
* @param rjsFlags controller mode flags
* @param startup flag to start R (otherwise connect only)
* @param rArgs R arguments (required only if startup is <code>true</code>)
* @param initialWD
*/
public RjsController(final RProcess process,
- final RMIAddress address, final RjsConnection connection, final Map<String, Object> initData,
+ final RMIAddress address, final RjsConnection connection, final Map<String, Object> connectionInfo,
final int rjsFlags, final String[] rArgs,
final Map<String, Object> rjsProperties, final IFileStore initialWD,
final RWorkspaceConfig workspaceConfig,
final List<TrackingConfiguration> trackingConfigurations) {
- super(process, initData);
+ super(process, connectionInfo);
if (address == null || connection == null) {
throw new IllegalArgumentException();
}
@@ -579,7 +579,7 @@
String msg= null;
boolean connected= false;
while (!connected) {
- final Map<String, Object> initData= getInitData();
+ final Map<String, Object> connectionInfo= getTool().getConnectionInfo();
final ServerLogin login= this.rjsConnection.getServer().createLogin(Server.C_CONSOLE_CONNECT);
try {
final Callback[] callbacks= login.getCallbacks();
@@ -595,8 +595,8 @@
}
}
- if (initData != null) {
- data.putAll(initData);
+ if (connectionInfo != null) {
+ data.putAll(connectionInfo);
}
data.put(LOGIN_ADDRESS_DATA_KEY, (fx != null) ? this.address.getHost() : this.address.getAddress());
data.put(LOGIN_MESSAGE_DATA_KEY, msg);
@@ -635,8 +635,8 @@
if (callbacks != null) {
loginHandler.execute(LOGIN_OK_EVENT_ID, this, data, monitor);
- if (initData != null) {
- initData.put(LOGIN_USERNAME_DATA_KEY, data.get(LOGIN_USERNAME_DATA_KEY));
+ if (connectionInfo != null) {
+ connectionInfo.put(LOGIN_USERNAME_DATA_KEY, data.get(LOGIN_USERNAME_DATA_KEY));
}
}
}
@@ -780,6 +780,7 @@
@Override
protected void onHotModeExit(final IProgressMonitor monitor) {
+ super.onHotModeExit(monitor);
try {
this.fRjs.finishTask(monitor);
}
@@ -787,14 +788,14 @@
}
@Override
- protected void onTaskFinished(final ToolRunnable runnable, final int event,
+ protected void onTaskFinished(final RunnableData runnableData, final int event,
final IProgressMonitor monitor) {
try {
this.fRjs.finishTask(monitor);
}
catch (final Throwable e) {}
- super.onTaskFinished(runnable, event, monitor);
+ super.onTaskFinished(runnableData, event, monitor);
}
diff --git a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/actions/REnvIndexUpdateHandler.java b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/actions/REnvIndexUpdateHandler.java
index 17b1c3e..045a176 100644
--- a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/actions/REnvIndexUpdateHandler.java
+++ b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/actions/REnvIndexUpdateHandler.java
@@ -17,6 +17,9 @@
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
import org.eclipse.statet.ecommons.ts.core.Tool;
import org.eclipse.statet.nico.ui.actions.AbstractToolHandler;
@@ -27,7 +30,8 @@
/**
* Command handler scheduling the update of an R environment index.
*/
-public class REnvIndexUpdateHandler extends AbstractToolHandler {
+@NonNullByDefault
+public class REnvIndexUpdateHandler extends AbstractToolHandler<Tool> {
public static final int INDEX_COMPLETELY= 0x0000_0001;
@@ -58,9 +62,11 @@
@Override
- protected Object execute(final Tool tool, final ExecutionEvent event) throws ExecutionException {
+ protected @Nullable Object execute(final Tool tool,
+ final ExecutionEvent event) throws ExecutionException {
tool.getQueue().add(new REnvIndexAutoUpdater.UpdateRunnable(
((this.mode & 0xf) == INDEX_COMPLETELY) ));
+
return null;
}
diff --git a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleLaunchDelegate.java b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleLaunchDelegate.java
index e5f0bed..2f61483 100644
--- a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleLaunchDelegate.java
+++ b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleLaunchDelegate.java
@@ -306,7 +306,7 @@
}
final boolean sshTunnel= configuration.getAttribute(RConsoleLaunching.ATTR_SSH_TUNNEL_ENABLED, false);
- final Map<String, Object> loginData= new HashMap<>();
+ final Map<String, Object> connectionInfo= new HashMap<>();
RMIAddress rmiAddress= null;
RMIClientSocketFactory socketFactory= null;
@@ -320,18 +320,19 @@
rmiAddress= new RMIAddress(address);
// init login data
- loginData.put(LOGIN_USERNAME_DATA_KEY, username);
+ connectionInfo.put(LOGIN_USERNAME_DATA_KEY, username);
if (type.equals(RConsoleLaunching.REMOTE_RJS_SSH)) {
- loginData.put(LOGIN_USERNAME_FORCE_DATA_KEY, true);
+ connectionInfo.put(LOGIN_USERNAME_FORCE_DATA_KEY, true);
}
final int sshPort= configuration.getAttribute(RConsoleLaunching.ATTR_SSH_PORT, DEFAULT_SSH_PORT);
- loginData.put(LOGIN_SSH_HOST_DATA_KEY, rmiAddress.getHostAddress().getHostAddress());
- loginData.put(LOGIN_SSH_PORT_DATA_KEY, Integer.valueOf(sshPort));
+ connectionInfo.put(LOGIN_SSH_HOST_DATA_KEY, rmiAddress.getHostAddress().getHostAddress());
+ connectionInfo.put(LOGIN_SSH_PORT_DATA_KEY, Integer.valueOf(sshPort));
final Remote remote;
if (sshTunnel) {
+ connectionInfo.put("protocol", "ssh");
if (sshSession == null) {
- sshSession= RjsUtil.getSession(loginData, m.newChild(5));
+ sshSession= RjsUtil.getSession(connectionInfo, m.newChild(5));
}
socketFactory= RjsUtil.createRMIOverSshClientSocketFactory(sshSession);
@@ -425,9 +426,9 @@
final String[] args= LaunchUtils.getProcessArguments(configuration, RConsoleLaunching.ATTR_OPTIONS);
if (reconnect != null) {
- final Map<String, String> reconnectData= (Map<String, String>) reconnect.get("initData"); //$NON-NLS-1$
+ final Map<String, String> reconnectData= (Map<String, String>) reconnect.get("connectionInfo"); //$NON-NLS-1$
if (reconnectData != null) {
- loginData.putAll(reconnectData);
+ connectionInfo.putAll(reconnectData);
}
}
@@ -472,7 +473,7 @@
envp.put("LC_ALL", "C"); //$NON-NLS-1$ //$NON-NLS-2$
envp.put("LANG", "C"); //$NON-NLS-1$ //$NON-NLS-2$
envp.put("LC_NUMERIC", "C"); //$NON-NLS-1$ //$NON-NLS-2$
- RjsUtil.startRemoteServerOverSsh(RjsUtil.getSession(loginData, m.newChild(5)), command, envp, m.newChild(5));
+ RjsUtil.startRemoteServerOverSsh(RjsUtil.getSession(connectionInfo, m.newChild(5)), command, envp, m.newChild(5));
m.subTask(Messages.LaunchDelegate_WaitForR_subtask);
final long t= System.nanoTime();
@@ -484,7 +485,7 @@
if (registry == null) {
if (sshTunnel) {
if (sshSession == null) {
- sshSession= RjsUtil.getSession(loginData, m.newChild(5));
+ sshSession= RjsUtil.getSession(connectionInfo, m.newChild(5));
}
if (socketFactory == null) {
socketFactory= RjsUtil.createRMIOverSshClientSocketFactory(sshSession);
@@ -566,7 +567,7 @@
rjsProperties.put(RjsComConfig.RJ_DATA_STRUCTS_ENVS_MAX_LENGTH_PROPERTY_ID,
configuration.getAttribute(RConsoleLaunching.ATTR_OBJECTDB_ENVS_MAX_LENGTH, 10000));
rjsProperties.put("rj.session.startup.time", timestamp); //$NON-NLS-1$
- final RjsController controller= new RjsController(process, rmiAddress, connection, loginData,
+ final RjsController controller= new RjsController(process, rmiAddress, connection, connectionInfo,
(startup) ? RjsController.RJS_SETUP_CONSOLE : 0, args, rjsProperties, null,
RConsoleRJLaunchDelegate.createWorkspaceConfig(configuration), trackingConfigs);
diff --git a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleMainTab.java b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleMainTab.java
index ffbb444..28d3193 100644
--- a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleMainTab.java
+++ b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleMainTab.java
@@ -23,6 +23,7 @@
import static org.eclipse.statet.r.console.ui.launching.RConsoleLaunching.REMOTE_RJS_SSH;
import java.net.MalformedURLException;
+import java.net.UnknownHostException;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.util.ArrayList;
@@ -55,7 +56,6 @@
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
@@ -110,7 +110,11 @@
final RMIAddress rmiAddress= new RMIAddress(this.address);
sb.append(rmiAddress.getHostAddress().getHostAddress());
}
- catch (final Exception e) {}
+ catch (final UnknownHostException e) {
+ sb.append("<unknown>");
+ }
+ catch (final Exception e) {
+ }
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
diff --git a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/page/RConsolePage.java b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/page/RConsolePage.java
index 8fefff9..e07e7de 100644
--- a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/page/RConsolePage.java
+++ b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/page/RConsolePage.java
@@ -39,7 +39,6 @@
import org.eclipse.statet.jcommons.collections.ImCollections;
-import org.eclipse.statet.ecommons.ts.core.Tool;
import org.eclipse.statet.ecommons.ui.actions.HandlerCollection;
import org.eclipse.statet.ecommons.ui.actions.HandlerContributionItem;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
@@ -174,8 +173,8 @@
CommandContributionItem.STYLE_PUSH, null, false ),
new OpenRPkgManagerHandler() {
@Override
- protected Object execute(final Tool tool, final ExecutionEvent event)
- throws ExecutionException {
+ protected Object execute(final RProcess tool,
+ final ExecutionEvent event) throws ExecutionException {
final IRPkgManager packageManager= RPkgManagerUI.getPackageManager(tool);
if (packageManager != null) {
packageManager.clear();
diff --git a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/r/console/ui/tools/ChangeWorkingDirectoryWizard.java b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/r/console/ui/tools/ChangeWorkingDirectoryWizard.java
index e3be97f..cd82d74 100644
--- a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/r/console/ui/tools/ChangeWorkingDirectoryWizard.java
+++ b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/r/console/ui/tools/ChangeWorkingDirectoryWizard.java
@@ -32,6 +32,7 @@
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
import org.eclipse.statet.ecommons.ui.dialogs.DialogUtils;
import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
@@ -40,7 +41,6 @@
import org.eclipse.statet.internal.r.console.ui.Messages;
import org.eclipse.statet.internal.r.console.ui.RConsoleUIPlugin;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
import org.eclipse.statet.nico.ui.actions.ToolAction;
import org.eclipse.statet.nico.ui.util.NicoWizardDialog;
import org.eclipse.statet.nico.ui.util.ToolInfoGroup;
@@ -54,7 +54,7 @@
public static class ChangeAction extends ToolAction {
- public ChangeAction(final IToolProvider support) {
+ public ChangeAction(final ToolProvider support) {
super(support, true);
setId("org.eclipse.statet.r.tools.ChangeWorkingDirectory"); //$NON-NLS-1$
diff --git a/r/org.eclipse.statet.r.ui/plugin.xml b/r/org.eclipse.statet.r.ui/plugin.xml
index 8e4a099..0661269 100644
--- a/r/org.eclipse.statet.r.ui/plugin.xml
+++ b/r/org.eclipse.statet.r.ui/plugin.xml
@@ -1162,11 +1162,11 @@
</commandParameter>
</command>
<command
- categoryId="org.eclipse.statet.workbench.commandCategorys.Source"
- defaultHandler="org.eclipse.statet.internal.r.ui.rtools.RunPrintInR"
- description="%commands.RunPrintInR.description"
id="org.eclipse.statet.r.commands.RunPrintInR"
- name="%commands.RunPrintInR.name">
+ categoryId="org.eclipse.statet.workbench.commandCategorys.Source"
+ name="%commands.RunPrintInR.name"
+ description="%commands.RunPrintInR.description"
+ defaultHandler="org.eclipse.statet.internal.r.ui.rtools.RunPrintInR">
<commandParameter
id="var"
name="Variable to Print"
@@ -1188,12 +1188,12 @@
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
sequence="M1+R M2+1">
</key>
- <!-- key
+ <key
commandId="org.eclipse.statet.r.commands.RunPrintInR"
contextId="org.eclipse.statet.r.contexts.REditor"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
- sequence="M1+R P">
- </key -->
+ sequence="M1+R 2">
+ </key>
</extension>
<extension
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/tools/LoadRImageHandler.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/tools/LoadRImageHandler.java
index cdc9d84..f1983bd 100644
--- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/tools/LoadRImageHandler.java
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/tools/LoadRImageHandler.java
@@ -18,16 +18,19 @@
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.wizard.WizardDialog;
-import org.eclipse.statet.ecommons.ts.core.Tool;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
import org.eclipse.statet.ecommons.ui.util.UIAccess;
-import org.eclipse.statet.nico.core.runtime.ToolProcess;
import org.eclipse.statet.nico.ui.actions.AbstractToolHandler;
import org.eclipse.statet.nico.ui.util.NicoWizardDialog;
import org.eclipse.statet.r.console.core.RConsoleTool;
+import org.eclipse.statet.r.console.core.RProcess;
-public class LoadRImageHandler extends AbstractToolHandler {
+@NonNullByDefault
+public class LoadRImageHandler extends AbstractToolHandler<RProcess> {
public LoadRImageHandler() {
@@ -36,8 +39,9 @@
@Override
- protected Object execute(final Tool tool, final ExecutionEvent event) throws ExecutionException {
- final LoadRImageWizard wizard = new LoadRImageWizard((ToolProcess) tool);
+ protected @Nullable Object execute(final RProcess tool,
+ final ExecutionEvent event) throws ExecutionException {
+ final LoadRImageWizard wizard = new LoadRImageWizard(tool);
final WizardDialog dialog = new NicoWizardDialog(UIAccess.getActiveWorkbenchShell(true), wizard);
dialog.setBlockOnOpen(false);
dialog.open();
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/RLabelProvider.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/RLabelProvider.java
index b883d89..4520da7 100644
--- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/RLabelProvider.java
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/RLabelProvider.java
@@ -38,8 +38,8 @@
import org.eclipse.statet.ltk.core.LTKUtils;
import org.eclipse.statet.ltk.model.core.elements.IModelElement;
import org.eclipse.statet.ltk.ui.IElementLabelProvider;
-import org.eclipse.statet.r.console.core.RProcessREnvironment;
import org.eclipse.statet.r.core.data.CombinedRElement;
+import org.eclipse.statet.r.core.data.CombinedRList;
import org.eclipse.statet.r.core.model.ArgsDefinition;
import org.eclipse.statet.r.core.model.ArgsDefinition.Arg;
import org.eclipse.statet.r.core.model.IRClass;
@@ -468,6 +468,16 @@
return text;
}
+ public String getText(final ElementPartition partition) {
+ final StringBuilder text= new StringBuilder();
+ text.append("["); //$NON-NLS-1$
+ text.append(Long.toString((partition.getPartitionStart() + 1)));
+ text.append(" ... "); //$NON-NLS-1$
+ text.append(Long.toString(partition.getPartitionStart() + partition.getPartitionLength()));
+ text.append("]"); //$NON-NLS-1$
+ return text.toString();
+ }
+
@Override
public Image getImage(final Object element) {
@@ -483,6 +493,9 @@
@Override
public String getText(final Object element) {
+ if (element instanceof ElementPartition) {
+ return getText((ElementPartition) element);
+ }
final IModelElement modelElement= LTKUtils.getModelElement(element);
if (modelElement != null) {
// if (modelElement instanceof ICombinedRElement) {
@@ -988,9 +1001,9 @@
}
protected void appendEnvDetail(final StyledString text, final CombinedRElement element, final RList elementAttr) {
- final RProcessREnvironment envir= (RProcessREnvironment) element;
+ final CombinedRList env= (CombinedRList) element;
if ((this.style & COUNT) != 0) { // count info
- final String countInfo= getEnvCountInfo(envir);
+ final String countInfo= getEnvCountInfo(env);
text.append(countInfo, StyledString.COUNTER_STYLER);
}
@@ -999,7 +1012,7 @@
}
}
- protected String getEnvCountInfo(final RProcessREnvironment envir) {
+ protected String getEnvCountInfo(final CombinedRList envir) {
final StringBuilder textBuilder= getTextBuilder();
textBuilder.append(" ("); //$NON-NLS-1$
textBuilder.append(envir.getLength());
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/dataeditor/ShowElementCommandHandler.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/dataeditor/ShowElementCommandHandler.java
index 89b6c56..6afe6b7 100644
--- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/dataeditor/ShowElementCommandHandler.java
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/dataeditor/ShowElementCommandHandler.java
@@ -77,7 +77,6 @@
public boolean changed(final int event, final Tool tool) {
switch (event) {
case MOVING_FROM:
- case MOVING_TO:
return false;
default:
return true;
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/pkgmanager/OpenRPkgManagerHandler.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/pkgmanager/OpenRPkgManagerHandler.java
index 71e1826..772a47c 100644
--- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/pkgmanager/OpenRPkgManagerHandler.java
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/pkgmanager/OpenRPkgManagerHandler.java
@@ -19,14 +19,16 @@
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.handlers.HandlerUtil;
-import org.eclipse.statet.ecommons.ts.core.Tool;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.nico.ui.actions.AbstractToolHandler;
import org.eclipse.statet.r.console.core.RConsoleTool;
import org.eclipse.statet.r.console.core.RProcess;
-public class OpenRPkgManagerHandler extends AbstractToolHandler {
+@NonNullByDefault
+public class OpenRPkgManagerHandler extends AbstractToolHandler<RProcess> {
public OpenRPkgManagerHandler() {
@@ -34,17 +36,19 @@
}
- protected StartAction getStartAction() {
+ protected @Nullable StartAction getStartAction() {
return null;
}
@Override
- protected Object execute(final Tool tool, final ExecutionEvent event) throws ExecutionException {
+ protected @Nullable Object execute(final RProcess tool,
+ final ExecutionEvent event) throws ExecutionException {
final IWorkbenchWindow window= HandlerUtil.getActiveWorkbenchWindow(event);
- RPkgManagerUI.openDialog((RProcess) tool, (window != null) ? window.getShell() : null,
+ RPkgManagerUI.openDialog(tool, (window != null) ? window.getShell() : null,
getStartAction() );
+
return null;
}
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/CopyRElementNameHandler.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/CopyRElementNameHandler.java
new file mode 100644
index 0000000..de35feb
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/CopyRElementNameHandler.java
@@ -0,0 +1,126 @@
+/*=============================================================================#
+ # Copyright (c) 2009, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.ui.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.ITreeSelection;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+
+import org.eclipse.statet.jcommons.collections.CollectionUtils;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.models.core.util.ElementPartition;
+import org.eclipse.statet.ecommons.ui.components.StatusInfo;
+import org.eclipse.statet.ecommons.ui.util.DNDUtils;
+import org.eclipse.statet.ecommons.ui.util.UIAccess;
+import org.eclipse.statet.ecommons.ui.util.ViewActionUtil;
+
+import org.eclipse.statet.r.core.model.RElementName;
+
+
+@NonNullByDefault
+public class CopyRElementNameHandler extends AbstractHandler {
+
+
+ private final ViewActionUtil actionUtil;
+
+
+ public CopyRElementNameHandler(final ViewActionUtil actionUtil) {
+ this.actionUtil= actionUtil;
+ }
+
+
+ private ITreeSelection getSelection() {
+ final ISelectionProvider selectionProvider= this.actionUtil.getSelectionProvider();
+ return (ITreeSelection) selectionProvider.getSelection();
+ }
+
+ protected boolean isValidSelection(final ITreeSelection selection) {
+ if (selection == null || selection.isEmpty()) {
+ return false;
+ }
+ for (final Object element : selection.toList()) {
+ if (element instanceof ElementPartition) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ protected @Nullable RElementName getRElementName(final TreePath treePath,
+ final ITreeSelection selection) {
+ return RElementInputUtils.getRElementName(treePath, selection);
+ }
+
+
+ @Override
+ public void setEnabled(final @Nullable Object evaluationContext) {
+ setBaseEnabled(isValidSelection(getSelection()));
+ }
+
+ @Override
+ public @Nullable Object execute(final ExecutionEvent event) throws ExecutionException {
+ if (!UIAccess.isOkToUse(this.actionUtil.getControl())) {
+ return null;
+ }
+ final ITreeSelection selection= getSelection();
+ if (!isValidSelection(selection)) {
+ return null;
+ }
+
+ final String text= createData(selection);
+ if (text != null) {
+ copy(text);
+ }
+
+ return null;
+ }
+
+ protected @Nullable String createData(final ITreeSelection selection) {
+ final TreePath[] treePaths= selection.getPaths();
+ final List<String> names= new ArrayList<>(selection.size());
+ for (int i= 0; i < treePaths.length; i++) {
+ final RElementName elementName= getRElementName(treePaths[i], selection);
+ final String name= (elementName != null) ? elementName.getDisplayName() : null;
+ if (name != null) {
+ names.add(name);
+ }
+ else {
+ this.actionUtil.getStatusLine().setMessage(new StatusInfo(IStatus.WARNING,
+ "Could not copy element name for the selected objects." ));
+ return null;
+ }
+ }
+ return (names.size() == 1) ?
+ names.get(0) : CollectionUtils.toString(names, ", "); //$NON-NLS-1$
+ }
+
+ private void copy(final String text) {
+ DNDUtils.setContent(this.actionUtil.getClipboard(),
+ new String[] { text },
+ new Transfer[] { TextTransfer.getInstance() } );
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInput.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInput.java
new file mode 100644
index 0000000..c29b48f
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInput.java
@@ -0,0 +1,106 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ # All rights reserved. This program and the accompanying materials
+ # are made available under the terms of the Eclipse Public License v1.0
+ # which accompanies this distribution, and is available at
+ # http://www.eclipse.org/legal/epl-v10.html
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.ui.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.statet.jcommons.lang.NonNull;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ltk.model.core.elements.IModelElement;
+import org.eclipse.statet.ltk.model.core.elements.IModelElement.Filter;
+import org.eclipse.statet.r.core.data.CombinedRElement;
+
+
+@NonNullByDefault
+public class RElementInput<TSource> {
+
+
+ private final TSource source;
+
+ private final @Nullable Filter envFilter;
+ private final @Nullable Filter otherFilter;
+
+ private final @Nullable Map<CombinedRElement, CombinedRElement[]> envFilteredChildren;
+
+
+ private CombinedRElement @Nullable [] rootElements;
+
+
+ public RElementInput(final TSource source,
+ final IModelElement. @Nullable Filter envFilter,
+ final IModelElement. @Nullable Filter otherFilter) {
+ this.source= source;
+
+ this.envFilter= envFilter;
+ this.otherFilter= otherFilter;
+
+ this.envFilteredChildren= (envFilter != null) ? new HashMap<>() : null;
+ }
+
+
+ public TSource getSource() {
+ return this.source;
+ }
+
+
+ public boolean hasEnvFilter() {
+ return (this.envFilter != null);
+ }
+
+ public IModelElement. @Nullable Filter getEnvFilter() {
+ return this.envFilter;
+ }
+
+ public CombinedRElement[] getEnvChildren(final CombinedRElement rElement) {
+ CombinedRElement[] children= this.envFilteredChildren.get(rElement);
+ if (children == null) {
+ final List<? extends CombinedRElement> list= rElement.getModelChildren(this.envFilter);
+ children= list.toArray(new @NonNull CombinedRElement[list.size()]);
+ this.envFilteredChildren.put(rElement, children);
+ }
+ return children;
+ }
+
+ public List<CombinedRElement> filterEnvChildren(final List<? extends CombinedRElement> children) {
+ final List<CombinedRElement> list= new ArrayList<>(children.size());
+ for (final CombinedRElement rElement : children) {
+ if (this.envFilter.include(rElement)) {
+ list.add(rElement);
+ }
+ }
+ return list;
+ }
+
+
+ public boolean hasOtherFilter() {
+ return (this.otherFilter != null);
+ }
+
+ public IModelElement. @Nullable Filter getOtherFilter() {
+ return this.otherFilter;
+ }
+
+
+ public void setRootElements(final CombinedRElement @Nullable [] elements) {
+ this.rootElements= elements;
+ }
+
+ public CombinedRElement @Nullable [] getRootElements() {
+ return this.rootElements;
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ContentProvider.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInputContentProvider.java
similarity index 71%
rename from r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ContentProvider.java
rename to r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInputContentProvider.java
index 0c18d01..72c60bf 100644
--- a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ContentProvider.java
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInputContentProvider.java
@@ -12,7 +12,7 @@
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
-package org.eclipse.statet.internal.r.objectbrowser;
+package org.eclipse.statet.r.ui.util;
import java.util.Collections;
import java.util.HashSet;
@@ -22,6 +22,10 @@
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.statet.jcommons.lang.NonNull;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
import org.eclipse.statet.ecommons.models.core.util.BasicElementProxy;
import org.eclipse.statet.ecommons.models.core.util.ElementPartition;
import org.eclipse.statet.ecommons.models.core.util.ElementPartitionFactory;
@@ -34,15 +38,16 @@
import org.eclipse.statet.rj.data.RReference;
-class ContentProvider implements ITreeContentProvider {
+@NonNullByDefault
+public class RElementInputContentProvider<TInput extends RElementInput<?>> implements ITreeContentProvider {
- static CombinedRElement getCombinedRElement(final Object object) {
+ public static @Nullable CombinedRElement getCombinedRElement(final Object object) {
if (object instanceof CombinedRElement) {
return (CombinedRElement) object;
}
if (object instanceof IAdaptable) {
- final IModelElement modelElement = ((IAdaptable) object).getAdapter(IModelElement.class);
+ final IModelElement modelElement= ((IAdaptable) object).getAdapter(IModelElement.class);
if (modelElement instanceof CombinedRElement) {
return (CombinedRElement) modelElement;
}
@@ -50,15 +55,17 @@
return null;
}
- private static final Object[] NO_CHILDREN = new Object[0];
+
+ private static final Object[] NO_CHILDREN= new Object[0];
static class RElementPartition extends BasicElementProxy implements ElementPartition {
- private final PartitionFactory.PartitionHandle partition;
+ private final RElementInputContentProvider<?>.PartitionFactory.PartitionHandle partition;
- public RElementPartition(final CombinedRElement value, final PartitionFactory.PartitionHandle partition) {
+ public RElementPartition(final CombinedRElement value,
+ final RElementInputContentProvider<?>.PartitionFactory.PartitionHandle partition) {
super(value);
- this.partition = partition;
+ this.partition= partition;
}
@@ -79,15 +86,15 @@
}
@Override
- public boolean equals(final Object obj) {
+ public boolean equals(final @Nullable Object obj) {
if (this == obj) {
return true;
}
- if (!(obj instanceof RElementPartition)) {
- return false;
+ if (obj instanceof RElementPartition) {
+ return (super.equals(obj)
+ && this.partition.equals(((RElementPartition) obj).partition) );
}
- return (super.equals(obj)
- && this.partition.equals(((RElementPartition) obj).partition) );
+ return false;
}
}
@@ -106,13 +113,13 @@
@Override
protected Object[] getChildren(final CombinedRList value, final long start, final int length) {
- if (ContentProvider.this.activeInput.hasEnvFilter()
+ if (RElementInputContentProvider.this.activeInput.hasEnvFilter()
&& value instanceof RProcessREnvironment) {
- final Object[] all = ContentProvider.this.activeInput.getEnvFilterChildren(value);
+ final Object[] all= RElementInputContentProvider.this.activeInput.getEnvChildren(value);
if (start == 0 && length == all.length) {
return all;
}
- final Object[] children = new Object[length];
+ final Object[] children= new @NonNull Object[length];
System.arraycopy(all, (int) start, children, 0, length);
return children;
}
@@ -120,9 +127,9 @@
if (start == 0 && length == value.getLength()) {
return value.getModelChildren(null).toArray();
}
- final Object[] children = new Object[length];
- for (int i = 0; i < length; i++) {
- children[i] = value.get(start + i);
+ final Object[] children= new @NonNull Object[length];
+ for (int i= 0; i < length; i++) {
+ children[i]= value.get(start + i);
}
return children;
}
@@ -130,15 +137,15 @@
}
- private final PartitionFactory partitionFactory = new PartitionFactory();
+ private final PartitionFactory partitionFactory= new PartitionFactory();
- private ContentInput activeInput;
+ private @Nullable TInput activeInput;
/** References used by the viewer. Use only in UI thread */
private Set<RReference> usedReferences= new HashSet<>();
- public ContentProvider() {
+ public RElementInputContentProvider() {
}
@@ -146,11 +153,11 @@
public void dispose() {
}
- public void setInput(final ContentInput input) {
- this.activeInput = input;
+ public void setInput(final @Nullable TInput input) {
+ this.activeInput= input;
}
- public ContentInput getInput() {
+ public @Nullable TInput getInput() {
return this.activeInput;
}
@@ -160,8 +167,9 @@
@Override
public Object[] getElements(final Object inputElement) {
- if (this.activeInput != null && this.activeInput.rootElements != null) {
- return this.activeInput.rootElements;
+ final Object[] elements;
+ if (this.activeInput != null && (elements= this.activeInput.getRootElements()) != null) {
+ return elements;
}
return NO_CHILDREN;
}
@@ -173,7 +181,7 @@
}
// if (element instanceof TreeElement) {
-// final TreeElement treeElement = (TreeElement) element;
+// final TreeElement treeElement= (TreeElement) element;
// if (treeElement.children != null) {
// return (treeElement.children.length > 0);
// }
@@ -200,18 +208,18 @@
return (rElement.getLength() > 0);
case RObject.TYPE_ENVIRONMENT:
if (this.activeInput.hasEnvFilter()) {
- return (this.activeInput.getEnvFilterChildren(rElement).length > 0);
+ return (this.activeInput.getEnvChildren(rElement).length > 0);
}
return (rElement.getLength() > 0);
case RObject.TYPE_REFERENCE: {
- final RObject realObject = ((RReference) rElement).getResolvedRObject();
+ final RObject realObject= ((RReference) rElement).getResolvedRObject();
if (realObject != null) {
this.usedReferences.add((RReference) rElement);
return hasChildren((CombinedRElement) realObject);
}
return false; }
case RObject.TYPE_S4OBJECT:
- return rElement.hasModelChildren(this.activeInput.otherFilter);
+ return rElement.hasModelChildren(this.activeInput.getOtherFilter());
default:
return false;
}
@@ -228,7 +236,7 @@
return NO_CHILDREN;
case RObject.TYPE_ENVIRONMENT:
if (this.activeInput.hasEnvFilter()) {
- final Object[] children = this.activeInput.getEnvFilterChildren(rElement);
+ final Object[] children= this.activeInput.getEnvChildren(rElement);
if (children.length > 5000) {
return this.partitionFactory.getElements((CombinedRList) rElement, children.length);
}
@@ -239,20 +247,20 @@
}
return rElement.getModelChildren(null).toArray();
case RObject.TYPE_REFERENCE: {
- final RObject realObject = ((RReference) rElement).getResolvedRObject();
+ final RObject realObject= ((RReference) rElement).getResolvedRObject();
if (realObject != null) {
return getChildren((CombinedRElement) realObject);
}
return NO_CHILDREN; }
case RObject.TYPE_S4OBJECT:
- return rElement.getModelChildren(this.activeInput.otherFilter).toArray();
+ return rElement.getModelChildren(this.activeInput.getOtherFilter()).toArray();
default:
return NO_CHILDREN;
}
}
@Override
- public Object getParent(final Object element) {
+ public @Nullable Object getParent(final Object element) {
return null;
}
@@ -261,7 +269,7 @@
if (this.usedReferences.isEmpty()) {
return Collections.emptySet();
}
- final Set<RReference> previousReferences = this.usedReferences;
+ final Set<RReference> previousReferences= this.usedReferences;
this.usedReferences= new HashSet<>();
return previousReferences;
}
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInputLabelProvider.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInputLabelProvider.java
new file mode 100644
index 0000000..c2d6832
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInputLabelProvider.java
@@ -0,0 +1,61 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.ui.util;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.r.core.data.CombinedRList;
+import org.eclipse.statet.r.ui.RLabelProvider;
+
+
+@NonNullByDefault
+public class RElementInputLabelProvider extends RLabelProvider {
+
+
+ public RElementInputLabelProvider(final int style) {
+ super(style);
+ }
+
+ public RElementInputLabelProvider() {
+ this(COUNT);
+ }
+
+
+ protected @Nullable RElementInput<?> getInput() {
+ return ((RElementInputContentProvider) getViewer().getContentProvider()).getInput();
+ }
+
+ @Override
+ protected String getEnvCountInfo(final CombinedRList envir) {
+ final StringBuilder textBuilder= getTextBuilder();
+ textBuilder.append(" ("); //$NON-NLS-1$
+ final RElementInput<?> input= getInput();
+ if (input != null && input.hasEnvFilter()) {
+ final Object[] children= input.getEnvChildren(envir);
+ if (children != null) {
+ textBuilder.append(children.length);
+ }
+ else {
+ textBuilder.append('-');
+ }
+ textBuilder.append('/');
+ }
+ textBuilder.append(envir.getLength());
+ textBuilder.append(')');
+ return textBuilder.toString();
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInputUtils.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInputUtils.java
new file mode 100644
index 0000000..048a224
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/r/ui/util/RElementInputUtils.java
@@ -0,0 +1,108 @@
+/*=============================================================================#
+ # Copyright (c) 2017, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.ui.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeSelection;
+import org.eclipse.jface.viewers.TreePath;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.models.core.util.ElementPartition;
+
+import org.eclipse.statet.ltk.ui.ElementNameProvider;
+import org.eclipse.statet.r.core.data.CombinedRElement;
+import org.eclipse.statet.r.core.model.RElementName;
+import org.eclipse.statet.rj.data.RObject;
+
+
+@NonNullByDefault
+public class RElementInputUtils {
+
+
+ public static class DoubleClickListener implements IDoubleClickListener {
+
+
+ private final AbstractTreeViewer viewer;
+
+
+ public DoubleClickListener(final AbstractTreeViewer viewer) {
+ this.viewer= viewer;
+ }
+
+
+ @Override
+ public void doubleClick(final DoubleClickEvent event) {
+ final IStructuredSelection selection= (IStructuredSelection) event.getSelection();
+ if (selection.size() != 1) {
+ return;
+ }
+ final Object element= selection.getFirstElement();
+ if (element instanceof RObject) {
+ final RObject object= (RObject) element;
+ switch (object.getRObjectType()) {
+ case RObject.TYPE_ENVIRONMENT:
+ case RObject.TYPE_LIST:
+ case RObject.TYPE_DATAFRAME:
+ case RObject.TYPE_S4OBJECT:
+ case RObject.TYPE_REFERENCE:
+ this.viewer.setExpandedState(element, !this.viewer.getExpandedState(element));
+ }
+ }
+ }
+
+ }
+
+
+ public static void addDoubleClickExpansion(final AbstractTreeViewer viewer) {
+ viewer.addDoubleClickListener(new DoubleClickListener(viewer));
+ }
+
+ public static @Nullable RElementName getRElementName(final TreePath treePath,
+ final ITreeSelection selection) {
+ if (selection instanceof ElementNameProvider) {
+ return (RElementName) ((ElementNameProvider) selection).getElementName(treePath);
+ }
+
+ if (treePath.getSegmentCount() == 0) {
+ return null;
+ }
+ final List<RElementName> names= new ArrayList<>(treePath.getSegmentCount() + 4);
+ int segmentIdx= 0;
+ while (segmentIdx < treePath.getSegmentCount()) {
+ final Object segment= treePath.getSegment(segmentIdx++);
+ if (segment instanceof ElementPartition) {
+ continue;
+ }
+ final CombinedRElement rElement= RElementInputContentProvider.getCombinedRElement(segment);
+ if (rElement == null) {
+ return null;
+ }
+ RElementName.addSegments(names, rElement.getElementName());
+ }
+ return RElementName.create(names);
+ }
+
+
+ private RElementInputUtils() {}
+
+}
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ContentInput.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ContentInput.java
index 1ec3d0b..3e5b3bc 100644
--- a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ContentInput.java
+++ b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ContentInput.java
@@ -14,67 +14,38 @@
package org.eclipse.statet.internal.r.objectbrowser;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ltk.model.core.elements.IModelElement;
+import org.eclipse.statet.r.console.core.RProcess;
import org.eclipse.statet.r.console.core.RProcessREnvironment;
-import org.eclipse.statet.r.core.data.CombinedRElement;
+import org.eclipse.statet.r.ui.util.RElementInput;
-class ContentInput {
+@NonNullByDefault
+class ContentInput extends RElementInput<RProcess> {
List<? extends RProcessREnvironment> searchEnvirs;
- boolean processChanged;
- boolean inputChanged;
- final boolean showCondensedUserspace;
- final IModelElement.Filter otherFilter;
-
- private final IModelElement.Filter envFilter;
- private final Map<CombinedRElement, Object[]> envFiltered;
-
- CombinedRElement[] rootElements;
+ private final boolean filterUserspace;
- public ContentInput(final boolean processChanged, final boolean inputChanged,
- final boolean showCondensedUserspace,
- final IModelElement.Filter envFilter, final IModelElement.Filter otherFilter) {
- this.processChanged = processChanged;
- this.inputChanged = inputChanged;
- this.showCondensedUserspace = showCondensedUserspace;
+ public ContentInput(final RProcess source,
+ final boolean filterUserspace,
+ final IModelElement. @Nullable Filter envFilter,
+ final IModelElement. @Nullable Filter otherFilter) {
+ super(source, envFilter, otherFilter);
- this.otherFilter = otherFilter;
-
- this.envFilter = envFilter;
- this.envFiltered = (envFilter != null) ? new HashMap<CombinedRElement, Object[]>() : null;
+ this.filterUserspace= filterUserspace;
}
- public boolean hasEnvFilter() {
- return (this.envFilter != null);
- }
-
- public Object[] getEnvFilterChildren(final CombinedRElement rElement) {
- Object[] children = this.envFiltered.get(rElement);
- if (children == null) {
- children = rElement.getModelChildren(this.envFilter).toArray();
- this.envFiltered.put(rElement, children);
- }
- return children;
- }
-
- public List<CombinedRElement> filterEnvChildren(final List<? extends CombinedRElement> children) {
- final List<CombinedRElement> list= new ArrayList<>(children.size());
- for (final CombinedRElement rElement : children) {
- if (this.envFilter.include(rElement)) {
- list.add(rElement);
- }
- }
- return list;
+ public boolean isFilterUserspace() {
+ return this.filterUserspace;
}
}
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ContentJob.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ContentJob.java
index d50186d..f675f32 100644
--- a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ContentJob.java
+++ b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ContentJob.java
@@ -14,8 +14,9 @@
package org.eclipse.statet.internal.r.objectbrowser;
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
+
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -29,6 +30,9 @@
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
import org.eclipse.statet.jcommons.collections.ImCollections;
+import org.eclipse.statet.jcommons.lang.NonNull;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
@@ -42,31 +46,30 @@
import org.eclipse.statet.rj.data.REnvironment;
+@NonNullByDefault
class ContentJob extends Job implements ToolWorkspace.Listener {
static class ContentFilter implements IModelElement.Filter {
private final boolean filterInternal;
- private final boolean filterNoPattern;
- private final SearchPattern searchPattern;
+ private final @Nullable SearchPattern searchPattern;
- public ContentFilter(final boolean filterInternal, final SearchPattern pattern) {
- this.filterInternal = filterInternal;
- this.filterNoPattern = (pattern == null);
- this.searchPattern = pattern;
+ public ContentFilter(final boolean filterInternal, final @Nullable SearchPattern pattern) {
+ this.filterInternal= filterInternal;
+ this.searchPattern= pattern;
}
@Override
public boolean include(final IModelElement element) {
- final String name = element.getElementName().getSegmentName();
+ final String name= element.getElementName().getSegmentName();
if (name != null) {
if (this.filterInternal && name.length() > 0 && name.charAt(0) == '.') {
return false;
}
- return (this.filterNoPattern || this.searchPattern.matches(name));
+ return (this.searchPattern == null || this.searchPattern.matches(name));
}
else {
return true;
@@ -78,26 +81,26 @@
private final ObjectBrowserView view;
+ private volatile boolean isScheduled;
+
/** true if RefreshR is running */
private boolean forceOnWorkspaceChange;
/** the process to update */
- private RProcess updateProcess;
+ private @Nullable RProcess updateSource;
/** the process of last update */
- private RProcess lastProcess;
+ private @Nullable RProcess lastSource;
/** update all environment */
private boolean force;
/** environments to update, if force is false*/
private final Set<RProcessREnvironment> updateSet= new HashSet<>();
- private List<? extends RProcessREnvironment> rawInput;
- private List<? extends CombinedRElement> userspaceInput;
-
- private volatile boolean isScheduled;
+ private @Nullable List<? extends RProcessREnvironment> rawInput;
+ private @Nullable List<? extends CombinedRElement> userspaceInput;
public ContentJob(final ObjectBrowserView view) {
super("R Object Browser Update");
- this.view = view;
+ this.view= view;
setSystem(true);
setUser(false);
}
@@ -105,21 +108,21 @@
@Override
public void propertyChanged(final ToolWorkspace workspace, final Map<String, Object> properties) {
- final RWorkspace rWorkspace = (RWorkspace) workspace;
+ final RWorkspace rWorkspace= (RWorkspace) workspace;
if (properties.containsKey("REnvironments")) {
if (this.forceOnWorkspaceChange) {
- this.forceOnWorkspaceChange = false;
- final RProcess process = rWorkspace.getProcess();
+ this.forceOnWorkspaceChange= false;
+ final RProcess process= rWorkspace.getProcess();
forceUpdate(process);
schedule();
}
else {
- final List<RProcessREnvironment> envirs = (List<RProcessREnvironment>) properties.get("REnvironments");
+ final List<RProcessREnvironment> envirs= (List<RProcessREnvironment>) properties.get("REnvironments");
schedule(rWorkspace.getProcess(), envirs);
}
}
- final Object autorefresh = properties.get("AutoRefresh.enabled");
+ final Object autorefresh= properties.get("AutoRefresh.enabled");
if (autorefresh instanceof Boolean) {
UIAccess.getDisplay().asyncExec(new Runnable() {
@Override
@@ -132,7 +135,7 @@
});
}
else { // autorefresh already updates dirty
- final Object dirty = properties.get("RObjectDB.dirty");
+ final Object dirty= properties.get("RObjectDB.dirty");
if (dirty instanceof Boolean) {
UIAccess.getDisplay().asyncExec(new Runnable() {
@Override
@@ -147,28 +150,28 @@
}
}
- public void forceUpdate(final RProcess process) {
- synchronized (this.view.processLock) {
+ public void forceUpdate(final @Nullable RProcess process) {
+ synchronized (this.view.sourceLock) {
if (process != this.view.getTool()) {
return;
}
- this.updateProcess = process;
- this.force = true;
+ this.updateSource= process;
+ this.force= true;
this.updateSet.clear();
}
}
public void forceOnWorkspaceChange() {
- this.forceOnWorkspaceChange = true;
+ this.forceOnWorkspaceChange= true;
}
public void schedule(final RProcess process, final List<RProcessREnvironment> envirs) {
if (envirs != null && process != null) {
- synchronized (this.view.processLock) {
+ synchronized (this.view.sourceLock) {
if (process != this.view.getTool()) {
return;
}
- this.updateProcess = process;
+ this.updateSource= process;
if (!this.force) {
this.updateSet.removeAll(envirs);
this.updateSet.addAll(envirs);
@@ -180,7 +183,7 @@
@Override
public boolean shouldSchedule() {
- this.isScheduled = true;
+ this.isScheduled= true;
return true;
}
@@ -189,79 +192,70 @@
if (!this.isScheduled) {
return Status.CANCEL_STATUS;
}
- this.isScheduled = false;
- final IWorkbenchSiteProgressService progressService = this.view.getViewSite().getService(IWorkbenchSiteProgressService.class);
+ final IWorkbenchSiteProgressService progressService= this.view.getViewSite().getService(IWorkbenchSiteProgressService.class);
if (progressService != null) {
progressService.incrementBusy();
}
try {
- final List<RProcessREnvironment> updateList;
- final boolean force;
- final boolean updateInput;
final RProcess process;
- synchronized (this.view.processLock) {
- force = this.force;
- updateInput = (force || this.updateProcess != null);
- process = (updateInput) ? this.updateProcess : this.view.getTool();
- if (process != this.view.getTool() || this.forceOnWorkspaceChange) {
+ final boolean sourceChanged;
+ final boolean updateInput;
+ List<RProcessREnvironment> updateList= null;
+ synchronized (this.view.sourceLock) {
+ this.isScheduled= false;
+
+ process= this.view.getTool();
+ sourceChanged= (process != this.lastSource);
+ updateInput= (sourceChanged || this.updateSource != null);
+ if (this.forceOnWorkspaceChange) {
return Status.OK_STATUS;
}
- updateList= new ArrayList<>(this.updateSet.size());
- updateList.addAll(this.updateSet);
+ if (!(sourceChanged || this.force)) {
+ updateList= new ArrayList<>(this.updateSet.size());
+ updateList.addAll(this.updateSet);
+ }
+ this.lastSource= process;
+ this.updateSource= null;
+ this.force= false;
this.updateSet.clear();
- this.updateProcess = null;
- this.force = false;
}
- final ContentInput input = createHandler(process, updateInput);
+ final ContentInput input= (process != null) ? createInput(process) : null;
// Update input and refresh
final List<RProcessREnvironment> toUpdate;
if (updateInput) {
- toUpdate = updateInput((!force) ? updateList : null, process, input);
+ toUpdate= updateFromSource(input, updateList);
}
else {
- toUpdate = null;
+ toUpdate= null;
}
- if (this.rawInput != null) {
- prescan(input);
- }
- else if (process != null) {
- input.processChanged = false;
- }
+ prepare(input);
- synchronized (this.view.processLock) {
+ synchronized (this.view.sourceLock) {
if (process != this.view.getTool()) {
+ this.lastSource= null;
return Status.CANCEL_STATUS;
}
- if ((!input.processChanged && this.isScheduled) || monitor.isCanceled()) {
- this.updateSet.addAll(updateList);
- this.force |= force;
- if (updateInput && this.updateProcess == null) {
- this.updateProcess = process;
+ if ((!sourceChanged && this.isScheduled) || monitor.isCanceled()) {
+ if (updateList != null
+ && (this.updateSource == process || this.updateSource == null) ) {
+ this.updateSource= process;
+ this.updateSet.addAll(updateList);
}
return Status.CANCEL_STATUS;
}
}
- UIAccess.getDisplay().syncExec(new Runnable() {
- @Override
- public void run() {
- if (process != ContentJob.this.view.getTool()) {
- return;
- }
- ContentJob.this.view.updateViewer(toUpdate, input);
+ UIAccess.getDisplay().syncExec(() -> {
+ if (process != ContentJob.this.view.getTool()) {
+ return;
}
+ ContentJob.this.view.updateView(input, toUpdate);
});
- if (this.rawInput != null) {
- this.lastProcess = process;
- }
- else {
- this.lastProcess = null;
- }
return Status.OK_STATUS;
}
finally {
@@ -271,119 +265,124 @@
}
}
- private ContentInput createHandler(final RProcess process, final boolean updateInput) {
- final boolean processChanged = ((process != null) ? process != this.lastProcess : this.lastProcess != null);
- final boolean filterInternal = !this.view.getShowInternal();
- final String filterText = this.view.getSearchText();
+ private ContentInput createInput(final RProcess source) {
+ final boolean filterInternal= !this.view.getFilterIncludeInternal();
+ final String filterText= this.view.getFilterSearchText();
IModelElement.Filter envFilter;
IModelElement.Filter otherFilter;
if (filterText != null && filterText.length() > 0) {
- final SearchPattern filterPattern = new RNameSearchPattern();
+ final SearchPattern filterPattern= new RNameSearchPattern();
filterPattern.setPattern(filterText);
- envFilter = new ContentFilter(filterInternal, filterPattern);
- otherFilter = (filterInternal) ? new ContentFilter(filterInternal, null) : null;
+ envFilter= new ContentFilter(filterInternal, filterPattern);
+ otherFilter= (filterInternal) ? new ContentFilter(filterInternal, null) : null;
}
else if (filterInternal) {
- envFilter = new ContentFilter(filterInternal, null);
- otherFilter = new ContentFilter(filterInternal, null);
+ envFilter= new ContentFilter(filterInternal, null);
+ otherFilter= new ContentFilter(filterInternal, null);
}
else {
- envFilter = null;
- otherFilter = null;
+ envFilter= null;
+ otherFilter= null;
}
- return new ContentInput(processChanged, updateInput, this.view.getShowConsenseUserspace(),
+ return new ContentInput(source,
+ this.view.getShowCondensedUserspace(),
envFilter, otherFilter );
}
- private List<RProcessREnvironment> updateInput(final List<RProcessREnvironment> updateList,
- final RProcess process, final ContentInput input) {
- if (process != null) {
- final List<? extends RProcessREnvironment> oldInput = this.rawInput;
- final RWorkspace workspaceData = process.getWorkspaceData();
- this.rawInput = workspaceData.getRSearchEnvironments();
- if (this.rawInput == null || this.rawInput.size() == 0) {
- this.rawInput = null;
- this.userspaceInput = null;
- return null;
- }
- input.searchEnvirs = this.rawInput;
- // If search path (environments) is not changed and not in force mode, refresh only the updated entries
- List<RProcessREnvironment> updateEntries = null;
- TRY_PARTIAL : if (!input.showCondensedUserspace
- && this.rawInput != null && oldInput != null && this.rawInput.size() == oldInput.size()
- && updateList != null && updateList.size() < this.rawInput.size() ) {
- updateEntries= new ArrayList<>(updateList.size());
- for (int i = 0; i < this.rawInput.size(); i++) {
- final RProcessREnvironment envir = this.rawInput.get(i);
- if (envir.equals(oldInput.get(i))) {
- if (updateList.remove(envir)) {
- updateEntries.add(envir);
- }
- }
- else { // search path is changed
- updateEntries = null;
- break TRY_PARTIAL;
+ private @Nullable List<RProcessREnvironment> updateFromSource(final @Nullable ContentInput input,
+ final @Nullable List<RProcessREnvironment> updateList) {
+ final List<? extends RProcessREnvironment> oldInput= this.rawInput;
+ this.rawInput= null;
+ this.userspaceInput= null;
+
+ if (input == null) {
+ return null;
+ }
+ final RProcess process= input.getSource();
+ final RWorkspace workspaceData= process.getWorkspaceData();
+ final List<? extends RProcessREnvironment> rawInput= workspaceData.getRSearchEnvironments();
+ if (rawInput == null || rawInput.size() == 0) {
+ return null;
+ }
+ this.rawInput= rawInput;
+ input.searchEnvirs= rawInput;
+ // If search path (environments) is not changed and not in force mode, refresh only the updated entries
+ List<RProcessREnvironment> updateEntries= null;
+ TRY_PARTIAL : if (!input.isFilterUserspace()
+ && oldInput != null && rawInput.size() == oldInput.size()
+ && updateList != null && updateList.size() < rawInput.size() ) {
+ updateEntries= new ArrayList<>(updateList.size());
+ for (int i= 0; i < rawInput.size(); i++) {
+ final RProcessREnvironment envir= rawInput.get(i);
+ if (envir.equals(oldInput.get(i))) {
+ if (updateList.remove(envir)) {
+ updateEntries.add(envir);
}
}
- if (!updateList.isEmpty()) {
- updateEntries = null;
+ else { // search path is changed
+ updateEntries= null;
break TRY_PARTIAL;
}
}
-
- // Prepare Userspace filter
- if (input.showCondensedUserspace) {
- int length = 0;
- final List<RProcessREnvironment> userEntries= new ArrayList<>(this.rawInput.size());
- for (final RProcessREnvironment env : this.rawInput) {
- if (env.getSpecialType() > 0 && env.getSpecialType() <= REnvironment.ENVTYPE_PACKAGE) {
- continue;
- }
- userEntries.add(env);
- length += env.getLength();
- }
- final List<IModelElement> elements= new ArrayList<>(length);
- for (final RProcessREnvironment entry : userEntries) {
- elements.addAll(entry.getModelChildren((IModelElement.Filter) null));
- }
-
- final CombinedRElement[] array = elements.toArray(new CombinedRElement[elements.size()]);
- Arrays.sort(array, ObjectBrowserView.ELEMENTNAME_COMPARATOR);
- this.userspaceInput= ImCollections.newList(array);
+ if (!updateList.isEmpty()) {
+ updateEntries= null;
+ break TRY_PARTIAL;
}
- else {
- this.userspaceInput = null;
- }
- return updateEntries;
}
- else {
- this.rawInput = null;
- this.userspaceInput = null;
- return null;
- }
+
+ return updateEntries;
}
- private void prescan(final ContentInput input) {
- // Prescan filter
- if (!input.showCondensedUserspace) {
- final CombinedRElement[] array = this.rawInput.toArray(new CombinedRElement[this.rawInput.size()]);
- if (input.hasEnvFilter()) {
- for (int i = 0; i < array.length; i++) {
- input.getEnvFilterChildren(array[i]);
+ private List<? extends CombinedRElement> getUserspaceInput() {
+ if (this.userspaceInput == null) {
+ final List<? extends RProcessREnvironment> rawInput= nonNullAssert(this.rawInput);
+ final List<RProcessREnvironment> userEntries= new ArrayList<>(rawInput.size());
+ int length= 0;
+ for (final RProcessREnvironment env : rawInput) {
+ if (env.getSpecialType() > 0 && env.getSpecialType() <= REnvironment.ENVTYPE_PACKAGE) {
+ continue;
}
+ userEntries.add(env);
+ length+= env.getLength();
}
- input.rootElements = array;
+ final List<CombinedRElement> elements= new ArrayList<>(length);
+ for (final RProcessREnvironment entry : userEntries) {
+ elements.addAll(entry.getModelChildren((IModelElement.Filter) null));
+ }
+
+ final CombinedRElement[] array= elements.toArray(new @NonNull CombinedRElement[elements.size()]);
+ this.userspaceInput= ImCollections.newList(array,
+ ObjectBrowserView.ELEMENTNAME_COMPARATOR );
+ }
+ return this.userspaceInput;
+ }
+
+ private void prepare(final @Nullable ContentInput input) {
+ final List<? extends RProcessREnvironment> rawInput= this.rawInput;
+ if (input == null || rawInput == null) {
+ return;
+ }
+
+ @NonNull CombinedRElement[] array;
+
+ if (input.isFilterUserspace()) {
+ // prepare userspace filter
+ List<? extends CombinedRElement> list= getUserspaceInput();
+ if (input.hasEnvFilter()) { // prepare env filter
+ list= input.filterEnvChildren(list);
+ }
+ array= list.toArray(new @NonNull CombinedRElement[list.size()]);
}
else {
- final List<? extends CombinedRElement> list;
- if (input.hasEnvFilter()) {
- list = input.filterEnvChildren(this.userspaceInput);
+ array= rawInput.toArray(new @NonNull CombinedRElement[rawInput.size()]);
+ if (input.hasEnvFilter()) { // prepare env filter
+ for (int i= 0; i < array.length; i++) {
+ input.getEnvChildren(array[i]);
+ }
}
- else {
- list = this.userspaceInput;
- }
- input.rootElements = list.toArray(new CombinedRElement[list.size()]);
}
+
+ input.setRootElements(array);
}
}
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/CopyElementNameHandler.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/CopyElementNameHandler.java
deleted file mode 100644
index 8a7c250..0000000
--- a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/CopyElementNameHandler.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*=============================================================================#
- # Copyright (c) 2009, 2018 Stephan Wahlbrink and others.
- #
- # This program and the accompanying materials are made available under the
- # terms of the Eclipse Public License 2.0 which is available at
- # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
- # which is available at https://www.apache.org/licenses/LICENSE-2.0.
- #
- # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
- #
- # Contributors:
- # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
- #=============================================================================*/
-
-package org.eclipse.statet.internal.r.objectbrowser;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.jface.viewers.ITreeSelection;
-import org.eclipse.jface.viewers.TreePath;
-import org.eclipse.swt.dnd.TextTransfer;
-import org.eclipse.swt.dnd.Transfer;
-
-import org.eclipse.statet.jcommons.collections.CollectionUtils;
-
-import org.eclipse.statet.ecommons.models.core.util.ElementPartition;
-import org.eclipse.statet.ecommons.ui.components.StatusInfo;
-import org.eclipse.statet.ecommons.ui.util.DNDUtils;
-import org.eclipse.statet.ecommons.ui.util.UIAccess;
-
-import org.eclipse.statet.ltk.core.ElementName;
-
-
-class CopyElementNameHandler extends AbstractHandler {
-
-
- private final ObjectBrowserView view;
-
-
- CopyElementNameHandler(final ObjectBrowserView objectBrowserView) {
- this.view = objectBrowserView;
- }
-
-
- private boolean isValidSelection(final ITreeSelection selection) {
- if (selection == null || selection.isEmpty()) {
- return false;
- }
- for (final Iterator<?> iter = selection.iterator(); iter.hasNext(); ) {
- final Object element = iter.next();
- if (element instanceof ElementPartition) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public void setEnabled(final Object evaluationContext) {
- setBaseEnabled(isValidSelection(this.view.getSelection()));
- }
-
- @Override
- public Object execute(final ExecutionEvent event) throws ExecutionException {
- if (!UIAccess.isOkToUse(this.view.getViewer())) {
- return null;
- }
- final ITreeSelection selection = this.view.getSelection();
- if (!isValidSelection(selection)) {
- return null;
- }
- final TreePath[] treePaths = selection.getPaths();
- if (treePaths.length == 0) {
- return null;
- }
- final List<String> names= new ArrayList<>();
- int failed = 0;
- for (int i = 0; i < treePaths.length; i++) {
- final ElementName elementName = this.view.getFQElementName(treePaths[i]);
- final String name = (elementName != null) ? elementName.getDisplayName() : null;
- if (name != null) {
- names.add(name);
- }
- else {
- failed++;
- }
- }
-
- if (names.size() == 1) {
- copy(names.get(0));
- }
- else if (names.size() > 1) {
- copy(CollectionUtils.toString(names, ", ")); //$NON-NLS-1$
- }
- else {
- copy(""); //$NON-NLS-1$
- }
- if (failed > 0) {
- this.view.getStatusLine().setMessage(new StatusInfo(IStatus.WARNING, "Could not copy element name for " + failed + " of " + treePaths.length + " objects."));
- }
-
- return null;
- }
-
- private void copy(final String text) {
- DNDUtils.setContent(this.view.getClipboard(),
- new String[] { text },
- new Transfer[] { TextTransfer.getInstance() } );
- }
-
-}
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/DeleteHandler.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/DeleteHandler.java
index c22e1cf..6ea22d3 100644
--- a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/DeleteHandler.java
+++ b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/DeleteHandler.java
@@ -36,6 +36,8 @@
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
import org.eclipse.statet.ecommons.models.core.util.ElementPartition;
import org.eclipse.statet.ecommons.ts.core.Tool;
import org.eclipse.statet.ecommons.ts.ui.ToolRunnableDecorator;
@@ -48,6 +50,7 @@
import org.eclipse.statet.r.console.core.IRDataAdapter;
import org.eclipse.statet.r.core.data.CombinedRElement;
import org.eclipse.statet.r.core.model.RElementName;
+import org.eclipse.statet.r.ui.util.RElementInputContentProvider;
import org.eclipse.statet.rj.data.RObject;
@@ -120,14 +123,14 @@
}
@Override
- public void setEnabled(final Object evaluationContext) {
+ public void setEnabled(final @Nullable Object evaluationContext) {
final ToolProcess process = this.view.getTool();
setBaseEnabled(process != null && !process.isTerminated()
&& isValidSelection(this.view.getSelection()) );
}
@Override
- public Object execute(final ExecutionEvent event) throws ExecutionException {
+ public @Nullable Object execute(final ExecutionEvent event) throws ExecutionException {
if (!UIAccess.isOkToUse(this.view.getViewer())) {
return null;
}
@@ -164,8 +167,8 @@
}
final TreePath treePath = treePaths[i];
- final CombinedRElement element = ContentProvider.getCombinedRElement(treePath.getLastSegment());
- final CombinedRElement parent = element.getModelParent();
+ final CombinedRElement element= RElementInputContentProvider.getCombinedRElement(treePath.getLastSegment());
+ final CombinedRElement parent= element.getModelParent();
final RElementName elementName = this.view.getFQElementName(treePath);
if (parent != null && elementName != null) {
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ObjectBrowserView.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ObjectBrowserView.java
index 50e34b1..4bfcb61 100644
--- a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ObjectBrowserView.java
+++ b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ObjectBrowserView.java
@@ -15,17 +15,18 @@
package org.eclipse.statet.internal.r.objectbrowser;
import static org.eclipse.statet.ecommons.ui.actions.UIActions.ADDITIONS_GROUP_ID;
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
+import static org.eclipse.ui.IWorkbenchCommandConstants.NAVIGATE_COLLAPSE_ALL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.commands.IHandler2;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@@ -37,11 +38,10 @@
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.viewers.DoubleClickEvent;
-import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreePath;
@@ -54,7 +54,7 @@
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
@@ -69,13 +69,22 @@
import org.eclipse.ui.menus.UIElement;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
+import org.eclipse.ui.services.IServiceLocator;
-import org.eclipse.statet.ecommons.collections.FastList;
+import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet;
+import org.eclipse.statet.jcommons.lang.NonNull;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
import org.eclipse.statet.ecommons.models.core.util.ElementPartition;
import org.eclipse.statet.ecommons.ts.core.Tool;
-import org.eclipse.statet.ecommons.ts.core.ToolRunnable;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener;
+import org.eclipse.statet.ecommons.ts.core.util.ActiveToolListener.ActiveToolEvent;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
+import org.eclipse.statet.ecommons.ui.actions.HandlerCollection;
import org.eclipse.statet.ecommons.ui.actions.HandlerContributionItem;
import org.eclipse.statet.ecommons.ui.actions.SearchContributionItem;
+import org.eclipse.statet.ecommons.ui.actions.UIActions;
import org.eclipse.statet.ecommons.ui.components.StatusInfo;
import org.eclipse.statet.ecommons.ui.dialogs.DialogUtils;
import org.eclipse.statet.ecommons.ui.util.ColumnHoverManager;
@@ -84,9 +93,10 @@
import org.eclipse.statet.ecommons.ui.util.InformationDispatchHandler;
import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
import org.eclipse.statet.ecommons.ui.util.PostSelectionProviderProxy;
-import org.eclipse.statet.ecommons.ui.util.StatusLineMessageManager;
import org.eclipse.statet.ecommons.ui.util.TreeSelectionProxy;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
+import org.eclipse.statet.ecommons.ui.util.ViewActionUtil;
+import org.eclipse.statet.ecommons.ui.workbench.ContextHandlers;
import org.eclipse.statet.ecommons.ui.workbench.WorkbenchUIUtils;
import org.eclipse.statet.base.ui.StatetImages;
@@ -98,13 +108,11 @@
import org.eclipse.statet.ltk.ui.sourceediting.assist.IInfoHover;
import org.eclipse.statet.ltk.ui.util.ViewerDragSupport;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.core.util.IToolProvider;
-import org.eclipse.statet.nico.core.util.IToolRetargetable;
import org.eclipse.statet.nico.ui.IToolRegistry;
import org.eclipse.statet.nico.ui.IToolRegistryListener;
import org.eclipse.statet.nico.ui.NicoUI;
import org.eclipse.statet.nico.ui.ToolSessionUIData;
-import org.eclipse.statet.nico.ui.actions.ToolRetargetableHandler;
+import org.eclipse.statet.nico.ui.actions.AbstractToolHandler;
import org.eclipse.statet.r.console.core.AbstractRDataRunnable;
import org.eclipse.statet.r.console.core.IRDataAdapter;
import org.eclipse.statet.r.console.core.RConsoleTool;
@@ -114,24 +122,38 @@
import org.eclipse.statet.r.core.data.CombinedRElement;
import org.eclipse.statet.r.core.model.RElementComparator;
import org.eclipse.statet.r.core.model.RElementName;
-import org.eclipse.statet.r.ui.RLabelProvider;
+import org.eclipse.statet.r.ui.rtool.CopyRElementHandler;
+import org.eclipse.statet.r.ui.rtool.PrintRElementHandler;
import org.eclipse.statet.r.ui.rtool.RElementInfoHoverCreator;
import org.eclipse.statet.r.ui.rtool.RElementInfoTask;
-import org.eclipse.statet.rj.data.RObject;
+import org.eclipse.statet.r.ui.rtool.RElementViewerDragSourceListener;
+import org.eclipse.statet.r.ui.util.CopyRElementNameHandler;
+import org.eclipse.statet.r.ui.util.RElementInputContentProvider;
+import org.eclipse.statet.r.ui.util.RElementInputLabelProvider;
+import org.eclipse.statet.r.ui.util.RElementInputUtils;
import org.eclipse.statet.rj.data.RReference;
-public class ObjectBrowserView extends ViewPart implements IToolProvider {
+@NonNullByDefault
+public class ObjectBrowserView extends ViewPart implements ToolProvider {
- private static final String FILTER_USERSPACEONLY_SETTINGS_KEY = "filter.only_userspace.enabled"; //$NON-NLS-1$
- private static final String FILTER_INTERNALINCLUDE_SETTINGS_KEY = "filter.include_internal.enabled"; //$NON-NLS-1$
- private static final String SORT_BYTYPE_SETTINGS_KEY = "sort.by_name.enabled"; //$NON-NLS-1$
+ private static final String REFRESH_COMMAND_ID= IWorkbenchCommandConstants.FILE_REFRESH;
- static final RElementComparator ELEMENTNAME_COMPARATOR = new RElementComparator();
- private static final ViewerComparator TYPE_COMPARATOR = new SortByTypeComparator();
+ private static final String OPEN_COMMAND_ID= "org.eclipse.jdt.ui.edit.text.java.open.editor"; //$NON-NLS-1$
+ private static final String PRINT_COMMAND_ID= RunPrintInR.COMMAND_ID;
- private static final String OPEN_COMMAND_ID = "org.eclipse.jdt.ui.edit.text.java.open.editor"; //$NON-NLS-1$
+ private static final String FILTER_ONLY_USERSPACE_COMMAND_ID= "Filter.OnlyUserspace";
+ private static final String FILTER_INCLUDE_INTERNAL_COMMAND_ID= "Filter.IncludeInternal";
+
+
+ private static final String FILTER_ONLY_USERSPACE_SETTINGS_KEY= "Filter.OnlyUserspace.enabled"; //$NON-NLS-1$
+ private static final String FILTER_INCLUDE_INTERNAL_SETTINGS_KEY= "Filter.IncludeInternal.enabled"; //$NON-NLS-1$
+ private static final String SORT_BY_TYPE_SETTINGS_KEY= "Sort.ByType.enabled"; //$NON-NLS-1$
+
+
+ static final RElementComparator ELEMENTNAME_COMPARATOR= new RElementComparator();
+ private static final ViewerComparator TYPE_COMPARATOR= new SortByTypeComparator();
private class RefreshWorkspaceR extends AbstractRDataRunnable {
@@ -152,15 +174,15 @@
protected void run(final IRDataAdapter r,
final IProgressMonitor monitor) throws CoreException {
boolean current;
- synchronized (ObjectBrowserView.this.processLock) {
- current = (r.getTool() != getTool());
+ synchronized (ObjectBrowserView.this.sourceLock) {
+ current= (r.getTool() != getTool());
}
- final IWorkbenchSiteProgressService progressService = getViewSite().getService(IWorkbenchSiteProgressService.class);
+ final IWorkbenchSiteProgressService progressService= getViewSite().getService(IWorkbenchSiteProgressService.class);
if (current && progressService != null) {
progressService.incrementBusy();
}
try {
- ObjectBrowserView.this.fInputUpdater.forceOnWorkspaceChange();
+ ObjectBrowserView.this.inputUpdater.forceOnWorkspaceChange();
r.refreshWorkspaceData(RWorkspace.REFRESH_COMPLETE, monitor);
}
finally {
@@ -172,25 +194,22 @@
}
- private class RefreshHandler extends ToolRetargetableHandler {
-
- private final ElementUpdater fUpdater = new ElementUpdater(IWorkbenchCommandConstants.FILE_REFRESH);
+ private class RefreshHandler extends AbstractToolHandler<RProcess> {
public RefreshHandler() {
- super(ObjectBrowserView.this, getSite());
+ super(RConsoleTool.TYPE, null, ObjectBrowserView.this, getSite());
init();
}
- @Override
- protected Object doExecute(final ExecutionEvent event) {
- scheduleUpdateAll();
- return null;
+
+ protected void refreshElements() {
+ WorkbenchUIUtils.refreshCommandElements(REFRESH_COMMAND_ID, this, null);
}
@Override
- protected void doRefresh() {
- super.doRefresh();
- this.fUpdater.schedule();
+ protected @Nullable Object execute(final RProcess tool, final ExecutionEvent event) {
+ scheduleUpdateAll();
+ return null;
}
}
@@ -198,71 +217,71 @@
private class FilterUserspaceHandler extends AbstractHandler implements IElementUpdater {
@Override
- public Object execute(final ExecutionEvent event) throws ExecutionException {
- ObjectBrowserView.this.fFilterUserspace = !ObjectBrowserView.this.fFilterUserspace;
- ObjectBrowserView.this.fSettings.put(FILTER_USERSPACEONLY_SETTINGS_KEY, ObjectBrowserView.this.fFilterUserspace);
- ObjectBrowserView.this.fInputUpdater.forceUpdate(ObjectBrowserView.this.process);
- ObjectBrowserView.this.fInputUpdater.schedule();
- return null;
- }
-
- @Override
public void updateElement(final UIElement element, final Map parameters) {
WorkbenchUIUtils.aboutToUpdateCommandsElements(this, element);
try {
- element.setChecked(ObjectBrowserView.this.fFilterUserspace);
+ element.setChecked(ObjectBrowserView.this.filterUserspace);
}
finally {
WorkbenchUIUtils.finalizeUpdateCommandsElements(this);
}
}
+ @Override
+ public @Nullable Object execute(final ExecutionEvent event) {
+ ObjectBrowserView.this.filterUserspace= !ObjectBrowserView.this.filterUserspace;
+ ObjectBrowserView.this.settings.put(FILTER_ONLY_USERSPACE_SETTINGS_KEY, ObjectBrowserView.this.filterUserspace);
+ ObjectBrowserView.this.inputUpdater.forceUpdate(ObjectBrowserView.this.process);
+ ObjectBrowserView.this.inputUpdater.schedule();
+ return null;
+ }
+
}
private class FilterInternalHandler extends AbstractHandler implements IElementUpdater {
@Override
- public Object execute(final ExecutionEvent event) throws ExecutionException {
- ObjectBrowserView.this.fFilterIncludeInternal = !ObjectBrowserView.this.fFilterIncludeInternal;
- ObjectBrowserView.this.fSettings.put(FILTER_INTERNALINCLUDE_SETTINGS_KEY, ObjectBrowserView.this.fFilterIncludeInternal);
- updateFilter();
- return null;
- }
-
- @Override
public void updateElement(final UIElement element, final Map parameters) {
WorkbenchUIUtils.aboutToUpdateCommandsElements(this, element);
try {
- element.setChecked(ObjectBrowserView.this.fFilterIncludeInternal);
+ element.setChecked(ObjectBrowserView.this.filterIncludeInternal);
}
finally {
WorkbenchUIUtils.finalizeUpdateCommandsElements(this);
}
}
+ @Override
+ public @Nullable Object execute(final ExecutionEvent event) {
+ ObjectBrowserView.this.filterIncludeInternal= !ObjectBrowserView.this.filterIncludeInternal;
+ ObjectBrowserView.this.settings.put(FILTER_INCLUDE_INTERNAL_SETTINGS_KEY, ObjectBrowserView.this.filterIncludeInternal);
+ updateFilter();
+ return null;
+ }
+
}
private class SortByTypeHandler extends AbstractHandler implements IElementUpdater {
@Override
- public Object execute(final ExecutionEvent event) throws ExecutionException {
- ObjectBrowserView.this.fSortByType = !ObjectBrowserView.this.fSortByType;
- ObjectBrowserView.this.fSettings.put(SORT_BYTYPE_SETTINGS_KEY, ObjectBrowserView.this.fSortByType);
- updateSorter();
- return null;
- }
-
- @Override
public void updateElement(final UIElement element, final Map parameters) {
WorkbenchUIUtils.aboutToUpdateCommandsElements(this, element);
try {
- element.setChecked(ObjectBrowserView.this.fSortByType);
+ element.setChecked(ObjectBrowserView.this.sortByType);
}
finally {
WorkbenchUIUtils.finalizeUpdateCommandsElements(this);
}
}
+ @Override
+ public @Nullable Object execute(final ExecutionEvent event) {
+ ObjectBrowserView.this.sortByType= !ObjectBrowserView.this.sortByType;
+ ObjectBrowserView.this.settings.put(SORT_BY_TYPE_SETTINGS_KEY, ObjectBrowserView.this.sortByType);
+ updateSorter();
+ return null;
+ }
+
}
private class TreeElementSelection extends TreeSelectionProxy implements ElementNameProvider {
@@ -272,8 +291,8 @@
}
@Override
- public ElementName getElementName(final Object selectionElement) {
- if (selectionElement instanceof TreePath) {
+ public @Nullable ElementName getElementName(final Object selectionElement) {
+ if (selectionElement instanceof TreePath) {
return getFQElementName((TreePath) selectionElement);
}
return null;
@@ -284,7 +303,7 @@
private class TreeSelectionProvider extends PostSelectionProviderProxy {
public TreeSelectionProvider() {
- super(ObjectBrowserView.this.fTreeViewer);
+ super(ObjectBrowserView.this.treeViewer);
}
@Override
@@ -297,16 +316,16 @@
private class HoverManager extends ColumnHoverManager {
HoverManager() {
- super(ObjectBrowserView.this.fTreeViewer, ObjectBrowserView.this.fTokenOwner, new RElementInfoHoverCreator(IInfoHover.MODE_TOOLTIP));
+ super(ObjectBrowserView.this.treeViewer, ObjectBrowserView.this.tokenOwner, new RElementInfoHoverCreator(IInfoHover.MODE_TOOLTIP));
- final ColumnHoverStickyManager stickyManager = new ColumnHoverStickyManager(ObjectBrowserView.this.fTokenOwner, this);
+ final ColumnHoverStickyManager stickyManager= new ColumnHoverStickyManager(ObjectBrowserView.this.tokenOwner, this);
getInternalAccessor().setInformationControlReplacer(stickyManager);
}
@Override
- protected Object prepareHoverInformation(final ViewerCell cell) {
- final TreePath treePath = cell.getViewerRow().getTreePath();
- final RElementName elementName = getFQElementName(treePath);
+ protected @Nullable Object prepareHoverInformation(final ViewerCell cell) {
+ final TreePath treePath= cell.getViewerRow().getTreePath();
+ final RElementName elementName= getFQElementName(treePath);
if (elementName != null && elementName.getScope() != null) {
return elementName;
}
@@ -314,9 +333,9 @@
}
@Override
- protected Object getHoverInformation(final Object element) {
+ protected @Nullable Object getHoverInformation(final Object element) {
if (element instanceof RElementName && ObjectBrowserView.this.process != null) {
- final RElementInfoTask updater = new RElementInfoTask((RElementName) element);
+ final RElementInfoTask updater= new RElementInfoTask((RElementName) element);
return updater.load(getTool(), getSubjectControl(), ObjectBrowserView.this);
}
return null;
@@ -325,72 +344,94 @@
}
- private TreeViewer fTreeViewer;
- private TreeSelectionProvider fTreeSelectionProvider;
- private ColumnWidgetTokenOwner fTokenOwner;
- private Clipboard fClipboard;
- private StatusLineMessageManager statusLine;
+ private IDialogSettings settings;
- private IDialogSettings fSettings;
+ final Object sourceLock= new Object();
+ private IToolRegistryListener toolRegistryListener;
+ private @Nullable RProcess process; // note: we write only in ui thread
+ private final CopyOnWriteIdentityListSet<ActiveToolListener> toolListeners= new CopyOnWriteIdentityListSet<>();
- final Object processLock = new Object();
- private RProcess process; // note: we write only in ui thread
- private IToolRegistryListener fToolRegistryListener;
- private final FastList<IToolRetargetable> fToolListenerList= new FastList<>(IToolRetargetable.class);
+ private TreeViewer treeViewer;
+ private ColumnWidgetTokenOwner tokenOwner;
+ private Clipboard clipboard;
- private final RefreshWorkspaceR fManualRefreshRunnable = new RefreshWorkspaceR();
- private final ContentJob fInputUpdater = new ContentJob(this);
+ private final ContentJob inputUpdater= new ContentJob(this);
+ private boolean isUpdating;
- private ContentProvider contentProvider;
+ private final RefreshWorkspaceR manualRefreshRunnable= new RefreshWorkspaceR();
- private boolean fFilterUserspace;
- private boolean fFilterIncludeInternal;
- private String fFilterText;
- private boolean fSortByType;
+ private boolean filterUserspace;
+ private boolean filterIncludeInternal;
+ private String filterText;
+ private boolean sortByType;
- private SearchContributionItem fSearchTextItem;
+ private SearchContributionItem searchTextItem;
- private boolean fFilterUserspaceActivated;
+ private RElementInputContentProvider<ContentInput> inputContentProvider;
- private CopyElementNameHandler fCopyElementNameHandler;
- private DeleteHandler fDeleteElementHandler;
- private PrintHandler fPrintElementHandler;
- private IHandler2 fOpenInEditorHandler;
+ private boolean filterUserspaceActivated;
- private Object fCurrentInfoObject;
- private ColumnHoverManager fHoveringController;
+ private ViewActionUtil actionUtil;
+ private ContextHandlers handlers;
- private AbstractHandler fSearchStartHandler;
+ private @Nullable Object currentInfoObject;
- private HandlerContributionItem fRefreshToolbarItem;
- private HandlerContributionItem fRefreshMenuItem;
- private boolean fRefreshDirtyIndicator;
+ private ColumnHoverManager hoveringController;
+
+ private HandlerContributionItem refreshToolbarItem;
+ private HandlerContributionItem refreshMenuItem;
+ private boolean refreshDirtyIndicator;
public ObjectBrowserView() {
}
@Override
+ public void dispose() {
+ if (this.toolRegistryListener != null) {
+ NicoUI.getToolRegistry().removeListener(this.toolRegistryListener);
+ this.toolRegistryListener= null;
+ }
+ setTool(null, false);
+ this.inputUpdater.cancel();
+
+ if (this.hoveringController != null) {
+ this.hoveringController.dispose();
+ this.hoveringController= null;
+ }
+ if (this.handlers != null) {
+ this.handlers.dispose();
+ this.handlers= null;
+ }
+
+ super.dispose();
+
+ if (this.clipboard != null) {
+ this.clipboard.dispose();
+ this.clipboard= null;
+ }
+ }
+
+
+ @Override
public void init(final IViewSite site, final IMemento memento) throws PartInitException {
super.init(site, memento);
- this.statusLine = new StatusLineMessageManager(site.getActionBars().getStatusLineManager());
+ this.settings= DialogUtils.getDialogSettings(RUIPlugin.getInstance(), "ObjectBrowser");
- this.fSettings = DialogUtils.getDialogSettings(RUIPlugin.getInstance(), "ObjectBrowser");
-
- this.fFilterUserspaceActivated = this.fFilterUserspace = this.fSettings.getBoolean(FILTER_USERSPACEONLY_SETTINGS_KEY);
- this.fFilterIncludeInternal = this.fSettings.getBoolean(FILTER_INTERNALINCLUDE_SETTINGS_KEY);
- this.fSortByType = this.fSettings.getBoolean(SORT_BYTYPE_SETTINGS_KEY);
+ this.filterUserspaceActivated= this.filterUserspace= this.settings.getBoolean(FILTER_ONLY_USERSPACE_SETTINGS_KEY);
+ this.filterIncludeInternal= this.settings.getBoolean(FILTER_INCLUDE_INTERNAL_SETTINGS_KEY);
+ this.sortByType= this.settings.getBoolean(SORT_BY_TYPE_SETTINGS_KEY);
}
@Override
public void saveState(final IMemento memento) {
super.saveState(memento);
- this.fSettings = DialogUtils.getDialogSettings(RUIPlugin.getInstance(), "ObjectBrowser");
+ this.settings= DialogUtils.getDialogSettings(RUIPlugin.getInstance(), "ObjectBrowser");
}
@@ -398,220 +439,200 @@
public void createPartControl(final Composite parent) {
parent.setLayout(LayoutUtils.newSashGrid());
- this.fTreeViewer = new TreeViewer(parent, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
- this.fTreeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 3));
- this.fTreeViewer.setUseHashlookup(true);
+ this.treeViewer= new TreeViewer(parent, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
+ this.treeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- this.fTreeSelectionProvider = new TreeSelectionProvider();
-
- this.fTreeViewer.setLabelProvider(new RLabelProvider(RLabelProvider.COUNT) {
- @Override
- protected String getEnvCountInfo(final RProcessREnvironment envir) {
- final StringBuilder textBuilder = getTextBuilder();
- textBuilder.append(" ("); //$NON-NLS-1$
- final ContentInput input = ObjectBrowserView.this.contentProvider.getInput();
- if (input != null && input.hasEnvFilter()) {
- final Object[] children = input.getEnvFilterChildren(envir);
- if (children != null) {
- textBuilder.append(children.length);
- }
- else {
- textBuilder.append('-');
- }
- textBuilder.append('/');
- }
- textBuilder.append(envir.getLength());
- textBuilder.append(')');
- return textBuilder.toString();
- }
- });
- this.fTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
- @Override
- public void doubleClick(final DoubleClickEvent event) {
- final IStructuredSelection selection = (IStructuredSelection) event.getSelection();
- if (selection.size() != 1) {
- return;
- }
- final Object element = selection.getFirstElement();
- if (element instanceof RObject) {
- final RObject object = (RObject) element;
- switch (object.getRObjectType()) {
- case RObject.TYPE_ENVIRONMENT:
- case RObject.TYPE_LIST:
- case RObject.TYPE_DATAFRAME:
- case RObject.TYPE_S4OBJECT:
- case RObject.TYPE_REFERENCE:
- ObjectBrowserView.this.fTreeViewer.setExpandedState(element, !ObjectBrowserView.this.fTreeViewer.getExpandedState(element));
- }
- }
- }
- });
- this.fTreeSelectionProvider.addPostSelectionChangedListener(new ISelectionChangedListener() {
+ final IPostSelectionProvider treeSelectionProvider= new TreeSelectionProvider();
+ treeSelectionProvider.addPostSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(final SelectionChangedEvent event) {
updateSelectionInfo((ITreeSelection) event.getSelection());
}
});
- this.contentProvider = new ContentProvider();
- this.fTreeViewer.setContentProvider(this.contentProvider);
+
+ this.treeViewer.setLabelProvider(new RElementInputLabelProvider());
+
+ this.treeViewer.setUseHashlookup(true);
+ this.inputContentProvider= new RElementInputContentProvider();
+ this.treeViewer.setContentProvider(this.inputContentProvider);
updateSorter();
- this.fTreeViewer.setInput(this);
+ this.treeViewer.setInput(this);
- this.fTokenOwner = new ColumnWidgetTokenOwner(this.fTreeViewer);
- this.fHoveringController = new HoverManager();
- this.fHoveringController.setSizeConstraints(100, 12, false, true);
- this.fHoveringController.install(this.fTreeViewer.getTree());
+ this.tokenOwner= new ColumnWidgetTokenOwner(this.treeViewer);
+ this.hoveringController= new HoverManager();
+ this.hoveringController.setSizeConstraints(100, 12, false, true);
+ this.hoveringController.install(this.treeViewer.getTree());
- createActions();
+ final IViewSite site= getViewSite();
+ site.setSelectionProvider(treeSelectionProvider);
+ this.actionUtil= new ViewActionUtil(this);
+ this.handlers= new ContextHandlers(site.getService(IHandlerService.class));
+ initActions(site, this.handlers);
+ contributeToActionBars(site, site.getActionBars(), this.handlers);
hookContextMenu();
- getSite().setSelectionProvider(this.fTreeSelectionProvider);
-
- final ViewerDragSupport dragSupport = new ViewerDragSupport(this.fTreeViewer);
- dragSupport.addDragSourceListener(new ViewerDragSupport.TextDragSourceListener(this.fTreeViewer));
- dragSupport.init();
// listen on console changes
- final IToolRegistry toolRegistry = NicoUI.getToolRegistry();
- this.fToolRegistryListener = new IToolRegistryListener() {
+ final IToolRegistry toolRegistry= NicoUI.getToolRegistry();
+ this.toolRegistryListener= new IToolRegistryListener() {
@Override
public void toolSessionActivated(final ToolSessionUIData sessionData) {
- final ToolProcess process = sessionData.getProcess();
+ final ToolProcess process= sessionData.getProcess();
UIAccess.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
- connect(process);
+ setTool(process, true);
}
});
}
@Override
public void toolTerminated(final ToolSessionUIData sessionData) {
- final ToolProcess process = sessionData.getProcess();
+ final ToolProcess process= sessionData.getProcess();
UIAccess.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
if (process == getTool()) {
- connect(null);
+ setTool(null, true);
}
}
});
}
};
- toolRegistry.addListener(this.fToolRegistryListener, getViewSite().getPage());
- connect(toolRegistry.getActiveToolSession(getViewSite().getPage()).getProcess());
+ toolRegistry.addListener(this.toolRegistryListener, getViewSite().getPage());
+ setTool(toolRegistry.getActiveToolSession(getViewSite().getPage()).getProcess(), true);
}
TreeViewer getViewer() {
- return this.fTreeViewer;
+ return this.treeViewer;
}
- private void createActions() {
- final IHandlerService handlerService = getSite().getService(IHandlerService.class);
- final IContextService contexts = getSite().getService(IContextService.class);
+ protected void initActions(final IServiceLocator serviceLocator, final ContextHandlers handlers) {
+ final IContextService contexts= serviceLocator.getService(IContextService.class);
contexts.activateContext("org.eclipse.statet.workbench.contexts.StructuredElementViewer"); //$NON-NLS-1$
- final RefreshHandler refreshHandler = new RefreshHandler();
- handlerService.activateHandler(IWorkbenchCommandConstants.FILE_REFRESH, refreshHandler);
- final CollapseAllHandler collapseAllHandler = new CollapseAllHandler(this.fTreeViewer);
- handlerService.activateHandler(CollapseAllHandler.COMMAND_ID, collapseAllHandler);
- this.fCopyElementNameHandler = new CopyElementNameHandler(this);
- handlerService.activateHandler(ISourceEditorCommandIds.COPY_ELEMENT_NAME, this.fCopyElementNameHandler);
- handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_COPY, this.fCopyElementNameHandler);
- this.fDeleteElementHandler = new DeleteHandler(this);
- handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_DELETE, this.fDeleteElementHandler);
- this.fPrintElementHandler = new PrintHandler(this);
- handlerService.activateHandler(RunPrintInR.COMMAND_ID, this.fPrintElementHandler);
- final InformationDispatchHandler infoHandler = new InformationDispatchHandler(this.fTokenOwner);
- handlerService.activateHandler(InformationDispatchHandler.COMMAND_ID, infoHandler);
- this.fOpenInEditorHandler = new OpenInEditorHandler();
- handlerService.activateHandler(OPEN_COMMAND_ID, this.fOpenInEditorHandler);
+ handlers.addActivate(REFRESH_COMMAND_ID, new RefreshHandler());
- this.fSearchTextItem = new SearchContributionItem("search.text", //$NON-NLS-1$
+ final CopyRElementHandler copyHandler= new CopyRElementHandler(this.actionUtil,
+ (ILabelProvider) this.treeViewer.getLabelProvider() );
+ handlers.addActivate(IWorkbenchCommandConstants.EDIT_COPY, copyHandler);
+ handlers.addActivate(ISourceEditorCommandIds.COPY_ELEMENT_NAME,
+ new CopyRElementNameHandler(this.actionUtil) );
+ handlers.addActivate(IWorkbenchCommandConstants.EDIT_DELETE,
+ new DeleteHandler(this) );
+
+ final ViewerDragSupport dragSupport= new ViewerDragSupport(this.treeViewer);
+ dragSupport.addDragSourceListener(new RElementViewerDragSourceListener(
+ copyHandler, this.treeViewer ));
+ dragSupport.init();
+
+ handlers.addActivate(OPEN_COMMAND_ID,
+ new OpenInEditorHandler() );
+ handlers.addActivate(PRINT_COMMAND_ID,
+ new PrintRElementHandler(this.actionUtil) );
+ handlers.addActivate(InformationDispatchHandler.COMMAND_ID,
+ new InformationDispatchHandler(this.tokenOwner) );
+
+ handlers.add(FILTER_INCLUDE_INTERNAL_COMMAND_ID, new FilterInternalHandler());
+ handlers.add(FILTER_ONLY_USERSPACE_COMMAND_ID, new FilterUserspaceHandler());
+
+ handlers.addActivate(NAVIGATE_COLLAPSE_ALL, new CollapseAllHandler(this.treeViewer));
+ RElementInputUtils.addDoubleClickExpansion(this.treeViewer);
+
+ this.searchTextItem= new SearchContributionItem("search.text", //$NON-NLS-1$
SearchContributionItem.VIEW_TOOLBAR, true ) {
@Override
protected void search() {
- ObjectBrowserView.this.fFilterText = getText();
+ ObjectBrowserView.this.filterText= getText();
updateFilter();
}
};
- this.fSearchTextItem.setToolTip("Filter Elements");
- this.fSearchTextItem.setSizeControl(this.fTreeViewer.getControl().getParent());
- this.fSearchTextItem.setResultControl(this.fTreeViewer.getTree());
+ this.searchTextItem.setToolTip("Filter Elements");
+ this.searchTextItem.setSizeControl(this.treeViewer.getControl().getParent());
+ this.searchTextItem.setResultControl(this.treeViewer.getTree());
- this.fSearchStartHandler = new AbstractHandler() {
- @Override
- public Object execute(final ExecutionEvent arg0) {
- ObjectBrowserView.this.fSearchTextItem.show();
- return null;
- }
- };
- handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_FIND_AND_REPLACE, this.fSearchStartHandler);
+ handlers.addActivate(IWorkbenchCommandConstants.EDIT_FIND_AND_REPLACE,
+ new AbstractHandler() {
+ @Override
+ public Object execute(final ExecutionEvent arg0) {
+ ObjectBrowserView.this.searchTextItem.show();
+ return null;
+ }
+ });
// add next/previous handler
+ }
+
+ protected void contributeToActionBars(final IServiceLocator serviceLocator,
+ final IActionBars actionBars, final HandlerCollection handlers) {
+ final IMenuManager menuManager= actionBars.getMenuManager();
+ final IToolBarManager toolbarManager= actionBars.getToolBarManager();
- final ToggleAutoRefreshHandler autoRefreshHandler = new ToggleAutoRefreshHandler(this);
+ final ToggleAutoRefreshHandler autoRefreshHandler= new ToggleAutoRefreshHandler(this);
- final IActionBars actionBars = getViewSite().getActionBars();
- final IMenuManager viewMenu = actionBars.getMenuManager();
- final IToolBarManager viewToolbar = actionBars.getToolBarManager();
-
- viewMenu.add(new HandlerContributionItem(new CommandContributionItemParameter(getSite(),
- "Filter.OnlyUserspace", HandlerContributionItem.NO_COMMAND_ID, null, //$NON-NLS-1$
- null, null, null,
- "Show non-&package Variables only", null, null,
- HandlerContributionItem.STYLE_CHECK, null, false),
- new FilterUserspaceHandler() ));
- viewMenu.add(new HandlerContributionItem(new CommandContributionItemParameter(getSite(),
- "Filter.IncludeInternal", HandlerContributionItem.NO_COMMAND_ID, null, //$NON-NLS-1$
- null, null, null,
- "Show &Internal Variables ('.*')", null, null,
- HandlerContributionItem.STYLE_CHECK, null, false),
- new FilterInternalHandler() ));
- viewMenu.add(new HandlerContributionItem(new CommandContributionItemParameter(getSite(),
- "Sort.ByType", HandlerContributionItem.NO_COMMAND_ID, null, //$NON-NLS-1$
- null, null, null,
- "Sort by &Type", null, null,
- HandlerContributionItem.STYLE_CHECK, null, false),
+ menuManager.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ "Filter.OnlyUserspace", HandlerContributionItem.NO_COMMAND_ID, null, //$NON-NLS-1$
+ null, null, null,
+ "Show non-&package Variables only", null, null,
+ HandlerContributionItem.STYLE_CHECK, null, false ),
+ nonNullAssert(handlers.get(FILTER_ONLY_USERSPACE_COMMAND_ID)) ));
+ menuManager.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ null, HandlerContributionItem.NO_COMMAND_ID, null, //$NON-NLS-1$
+ null, null, null,
+ "Show &Internal Variables ('.*')", null, null,
+ HandlerContributionItem.STYLE_CHECK, null, false ),
+ nonNullAssert(handlers.get(FILTER_INCLUDE_INTERNAL_COMMAND_ID)) ));
+ menuManager.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ "Sort.ByType", HandlerContributionItem.NO_COMMAND_ID, null, //$NON-NLS-1$
+ null, null, null,
+ "Sort by &Type", null, null,
+ HandlerContributionItem.STYLE_CHECK, null, false ),
new SortByTypeHandler() ));
- viewMenu.add(new Separator());
- final HandlerContributionItem autoRefreshItem = new HandlerContributionItem(new CommandContributionItemParameter(getSite(),
- null, HandlerContributionItem.NO_COMMAND_ID, null,
- null, null, null,
- "Refresh &automatically", null, null,
- HandlerContributionItem.STYLE_CHECK, null, false),
+ menuManager.add(new Separator());
+ final HandlerContributionItem autoRefreshItem= new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ null, HandlerContributionItem.NO_COMMAND_ID, null,
+ null, null, null,
+ "Refresh &automatically", null, null,
+ HandlerContributionItem.STYLE_CHECK, null, false ),
autoRefreshHandler );
- viewMenu.add(autoRefreshItem);
- this.fRefreshMenuItem = new HandlerContributionItem(new CommandContributionItemParameter(getSite(),
- null, IWorkbenchCommandConstants.FILE_REFRESH, null,
- StatetImages.getDescriptor(StatetImages.TOOL_REFRESH), StatetImages.getDescriptor(StatetImages.TOOLD_REFRESH), null,
- "&Refresh", null, null,
- HandlerContributionItem.STYLE_PUSH, null, false),
- refreshHandler );
- viewMenu.add(this.fRefreshMenuItem);
+ menuManager.add(autoRefreshItem);
+ this.refreshMenuItem= new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ "Refresh", REFRESH_COMMAND_ID, null, //$NON-NLS-1$
+ StatetImages.getDescriptor(StatetImages.TOOL_REFRESH), StatetImages.getDescriptor(StatetImages.TOOLD_REFRESH), null,
+ "&Refresh", null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ handlers );
+ menuManager.add(this.refreshMenuItem);
- viewMenu.addMenuListener(new IMenuListener() {
+ menuManager.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(final IMenuManager manager) {
autoRefreshItem.update();
}
});
- viewToolbar.add(this.fSearchTextItem);
- viewToolbar.add(new Separator());
- this.fRefreshToolbarItem = new HandlerContributionItem(new CommandContributionItemParameter(getSite(),
- "Refresh", IWorkbenchCommandConstants.FILE_REFRESH, null, //$NON-NLS-1$
- StatetImages.getDescriptor(StatetImages.TOOL_REFRESH), StatetImages.getDescriptor(StatetImages.TOOLD_REFRESH), null,
- null, null, null,
- HandlerContributionItem.STYLE_PUSH, null, false),
- refreshHandler);
- this.fRefreshToolbarItem.setVisible(false);
- viewToolbar.add(this.fRefreshToolbarItem);
- viewToolbar.add(new HandlerContributionItem(new CommandContributionItemParameter(getSite(),
- "Collapse.All", CollapseAllHandler.COMMAND_ID, null, //$NON-NLS-1$
- null, null, null,
- null, null, null,
- HandlerContributionItem.STYLE_PUSH, null, false),
- collapseAllHandler));
+ toolbarManager.add(this.searchTextItem);
+ toolbarManager.add(new Separator());
+ this.refreshToolbarItem= new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ "Refresh", REFRESH_COMMAND_ID, null, //$NON-NLS-1$
+ StatetImages.getDescriptor(StatetImages.TOOL_REFRESH), StatetImages.getDescriptor(StatetImages.TOOLD_REFRESH), null,
+ null, null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ handlers );
+ this.refreshToolbarItem.setVisible(false);
+ toolbarManager.add(this.refreshToolbarItem);
+ toolbarManager.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ null, NAVIGATE_COLLAPSE_ALL, null,
+ null, null, null,
+ null, null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ handlers ));
}
void updateAutoRefresh(final boolean enabled) {
@@ -626,190 +647,204 @@
updateDirty(this.process.getWorkspaceData().isRObjectDBDirty());
}
- if (this.fRefreshToolbarItem.isVisible() != enabled) {
+ if (this.refreshToolbarItem.isVisible() != enabled) {
return;
}
- this.fRefreshToolbarItem.setVisible(!enabled);
- final IContributionManager manager = this.fRefreshToolbarItem.getParent();
+ this.refreshToolbarItem.setVisible(!enabled);
+ final IContributionManager manager= this.refreshToolbarItem.getParent();
manager.update(true);
- this.fSearchTextItem.resize();
+ this.searchTextItem.resize();
}
void updateDirty(final boolean enabled) {
- if (this.fRefreshDirtyIndicator == enabled) {
+ if (this.refreshDirtyIndicator == enabled) {
return;
}
- final ImageDescriptor icon = (enabled) ?
+ final ImageDescriptor icon= nonNullAssert((enabled) ?
RUIPlugin.getInstance().getImageRegistry().getDescriptor(RUIPlugin.IMG_LOCTOOL_REFRESH_RECOMMENDED) :
- StatetImages.getDescriptor(StatetImages.TOOL_REFRESH);
- this.fRefreshToolbarItem.setIcon(icon);
- this.fRefreshMenuItem.setIcon(icon);
- this.fRefreshDirtyIndicator = enabled;
+ StatetImages.getDescriptor(StatetImages.TOOL_REFRESH) );
+ this.refreshToolbarItem.setIcon(icon);
+ this.refreshMenuItem.setIcon(icon);
+ this.refreshDirtyIndicator= enabled;
}
-
private void hookContextMenu() {
- final MenuManager menuManager = new MenuManager("ContextMenu", //$NON-NLS-1$
+ final MenuManager menuManager= new MenuManager("ContextMenu", //$NON-NLS-1$
"org.eclipse.statet.r.menus.RObjectBrowserContextMenu" ); //$NON-NLS-1$
menuManager.setRemoveAllWhenShown(true);
- menuManager.addMenuListener(new IMenuListener() {
- @Override
- public void menuAboutToShow(final IMenuManager m) {
- contextMenuAboutToShow(m);
- }
- });
- final Menu contextMenu = menuManager.createContextMenu(this.fTreeViewer.getTree());
- this.fTreeViewer.getTree().setMenu(contextMenu);
- getSite().registerContextMenu(menuManager, this.fTreeViewer);
+ menuManager.addMenuListener(this::fillContextMenu);
+ final Menu contextMenu= menuManager.createContextMenu(this.treeViewer.getTree());
+ this.treeViewer.getTree().setMenu(contextMenu);
+ getSite().registerContextMenu(menuManager, this.treeViewer);
}
- private void contextMenuAboutToShow(final IMenuManager m) {
- m.add(new HandlerContributionItem(new CommandContributionItemParameter(getSite(),
- null, OPEN_COMMAND_ID, null,
- null, null, null,
- "Open in Data &Viewer", null, null,
- HandlerContributionItem.STYLE_PUSH, null, true), this.fOpenInEditorHandler));
+ private void fillContextMenu(final IMenuManager m) {
+ final IServiceLocator serviceLocator= getSite();
+ final ContextHandlers handlers= this.handlers;
- m.add(new Separator("edit"));
- m.add(new HandlerContributionItem(new CommandContributionItemParameter(getSite(),
- "Copy.ElementName", ISourceEditorCommandIds.COPY_ELEMENT_NAME, null, //$NON-NLS-1$
- null, null, null,
- null, null, null,
- HandlerContributionItem.STYLE_PUSH, null, false),
- this.fCopyElementNameHandler));
- m.add(new HandlerContributionItem(new CommandContributionItemParameter(getSite(),
- "Delete", IWorkbenchCommandConstants.EDIT_DELETE, null, //$NON-NLS-1$
- null, null, null,
- null, null, null,
- HandlerContributionItem.STYLE_PUSH, null, false),
- this.fDeleteElementHandler));
+ m.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ null, OPEN_COMMAND_ID, null,
+ null, null, null,
+ "Open in Data &Viewer", null, null,
+ HandlerContributionItem.STYLE_PUSH, null, true ),
+ handlers ));
+
+ m.add(new Separator(UIActions.EDIT_GROUP_ID));
+ m.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ "Copy", IWorkbenchCommandConstants.EDIT_COPY, null, //$NON-NLS-1$
+ null, null, null,
+ null, null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ handlers ));
+ m.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ "Copy.ElementName", ISourceEditorCommandIds.COPY_ELEMENT_NAME, null, //$NON-NLS-1$
+ null, null, null,
+ null, null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ handlers ));
+ m.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ "Delete", IWorkbenchCommandConstants.EDIT_DELETE, null, //$NON-NLS-1$
+ null, null, null,
+ null, null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ handlers ));
m.add(new Separator());
- m.add(new HandlerContributionItem(new CommandContributionItemParameter(getSite(),
- null, RunPrintInR.COMMAND_ID, null,
- null, null, null,
- null, null, null,
- HandlerContributionItem.STYLE_PUSH, null, false),
- this.fPrintElementHandler));
+ m.add(new HandlerContributionItem(
+ new CommandContributionItemParameter(serviceLocator,
+ null, PRINT_COMMAND_ID, null,
+ null, null, null,
+ null, null, null,
+ HandlerContributionItem.STYLE_PUSH, null, false ),
+ handlers ));
m.add(new Separator(ADDITIONS_GROUP_ID));
}
- /** May only be called in UI thread */
- public void connect(final ToolProcess tool) {
- if (this.process == tool) {
- return;
- }
- final RProcess oldProcess = this.process;
- if (oldProcess != null) {
- oldProcess.getWorkspaceData().removePropertyListener(this.fInputUpdater);
- }
- synchronized (this.processLock) {
- this.process = (RProcess)
- ((tool != null && tool.isProvidingFeatureSet(RConsoleTool.R_DATA_FEATURESET_ID)) ?
- tool : null);
- }
- if (this.fHoveringController != null) {
- this.fHoveringController.stop();
- }
- if (oldProcess != null) {
- clearInfo();
- oldProcess.getQueue().remove(new ToolRunnable[] { this.fManualRefreshRunnable });
- }
- if (!UIAccess.isOkToUse(this.fTreeViewer)) {
- return;
- }
- for (final IToolRetargetable listener : this.fToolListenerList.toArray()) {
- listener.setTool(this.process);
- }
- this.fInputUpdater.forceUpdate(this.process);
- if (this.process != null) {
- this.process.getWorkspaceData().addPropertyListener(this.fInputUpdater);
- updateAutoRefresh(this.process.getWorkspaceData().isAutoRefreshEnabled());
- }
- this.fInputUpdater.schedule();
+ @Override
+ public void setFocus() {
+ this.treeViewer.getControl().setFocus();
}
+
@Override
- public RProcess getTool() {
+ public @Nullable RProcess getTool() {
return this.process;
}
- public ITreeSelection getSelection() {
- return (ITreeSelection) this.fTreeViewer.getSelection();
- }
-
-
- public boolean getShowInternal() {
- return this.fFilterIncludeInternal;
- }
-
- public boolean getShowConsenseUserspace() {
- return this.fFilterUserspace;
- }
-
- public String getSearchText() {
- return this.fFilterText;
- }
-
-
@Override
- public void addToolRetargetable(final IToolRetargetable action) {
- this.fToolListenerList.add(action);
+ public void addToolListener(final ActiveToolListener action) {
+ this.toolListeners.add(action);
}
@Override
- public void removeToolRetargetable(final IToolRetargetable action) {
- this.fToolListenerList.remove(action);
+ public void removeToolListener(final ActiveToolListener action) {
+ this.toolListeners.remove(action);
}
- @Override
- @SuppressWarnings("unchecked")
- public <T> T getAdapter(final Class<T> adapterType) {
- if (adapterType == Tool.class) {
- return (T) this.process;
+ /** UI thread only */
+ private void setTool(final @Nullable ToolProcess tool, final boolean update) {
+ final RProcess process= (tool != null
+ && tool.isProvidingFeatureSet(RConsoleTool.R_DATA_FEATURESET_ID)
+ && !tool.isTerminated() ) ?
+ (RProcess) tool : null;
+ if (this.process == tool) {
+ return;
}
- return super.getAdapter(adapterType);
+
+ final RProcess oldProcess= this.process;
+ if (oldProcess != null) {
+ oldProcess.getWorkspaceData().removePropertyListener(this.inputUpdater);
+ }
+ synchronized (this.sourceLock) {
+ this.process= process;
+ }
+ if (this.hoveringController != null) {
+ this.hoveringController.stop();
+ }
+ clearActionInfo();
+ if (oldProcess != null) {
+ oldProcess.getQueue().remove(this.manualRefreshRunnable);
+ }
+
+ final ActiveToolEvent event= new ActiveToolEvent(ActiveToolEvent.TOOL_ACTIVATED, process);
+ for (final ActiveToolListener listener : this.toolListeners) {
+ listener.onToolChanged(event);
+ }
+ this.inputUpdater.forceUpdate(process);
+ if (process != null) {
+ process.getWorkspaceData().addPropertyListener(this.inputUpdater);
+ updateAutoRefresh(process.getWorkspaceData().isAutoRefreshEnabled());
+ }
+
+ if (update) {
+ this.inputUpdater.schedule();
+ }
}
+ public ITreeSelection getSelection() {
+ return (ITreeSelection) this.treeViewer.getSelection();
+ }
+
+
+ public boolean getShowCondensedUserspace() {
+ return this.filterUserspace;
+ }
+
+ public boolean getFilterIncludeInternal() {
+ return this.filterIncludeInternal;
+ }
+
+ public String getFilterSearchText() {
+ return this.filterText;
+ }
+
+
private void scheduleUpdateAll() {
if (this.process != null) {
- this.process.getQueue().add(this.fManualRefreshRunnable);
+ this.process.getQueue().add(this.manualRefreshRunnable);
}
}
- /** May only be called in UI thread (called by update job) */
- void updateViewer(final List<RProcessREnvironment> updateEnvirs, final ContentInput input) {
- if (!UIAccess.isOkToUse(this.fTreeViewer)) {
+ /** UI thread only (called by update job) */
+ void updateView(final @Nullable ContentInput input,
+ final @Nullable List<RProcessREnvironment> updateEnvirs) {
+ if (!UIAccess.isOkToUse(this.treeViewer)) {
return;
}
- this.fHoveringController.stop();
+ this.isUpdating= true;
- this.contentProvider.setInput(input);
+ this.hoveringController.stop();
- final boolean changed = input.processChanged;
- ISelection selection = null;
- if (changed) {
- input.processChanged = false;
+ final ContentInput prevInput= this.inputContentProvider.getInput();
+ this.inputContentProvider.setInput(input);
+ final boolean processChanged= Objects.equals(
+ (input != null) ? input.getSource() : null,
+ (prevInput != null) ? prevInput.getSource() : null );
+
+ ISelection selection= null;
+ // If filter is changed, we have to retain the selection manually
+ if (input != null && !processChanged && input.isFilterUserspace() != this.filterUserspaceActivated) {
+ selection= this.treeViewer.getSelection();
}
- /*else*/ if (input.showCondensedUserspace != this.fFilterUserspaceActivated) {
- // If filter is changed, we have to retain the selection manually
- selection = this.fTreeViewer.getSelection();
- }
- this.fFilterUserspaceActivated = input.showCondensedUserspace;
+ this.filterUserspaceActivated= (input != null) ? input.isFilterUserspace() : false;
- final Set<RReference> previousReferences = this.contentProvider.resetUsedReferences();
- if (updateEnvirs != null) {
+ final Set<RReference> previousReferences= this.inputContentProvider.resetUsedReferences();
+ if (input != null && updateEnvirs != null) {
for (final RProcessREnvironment entry : updateEnvirs) {
- this.fTreeViewer.refresh(entry, true);
+ this.treeViewer.refresh(entry, true);
}
if (!previousReferences.isEmpty()) {
- final Set<RReference> usedReferences = this.contentProvider.getUsedReferences();
+ final Set<RReference> usedReferences= this.inputContentProvider.getUsedReferences();
ITER_REFS: for (final RReference reference : previousReferences) {
if (!usedReferences.contains(reference)) {
// Update the envir copy in the viewer, if it refers to an updated envir
for (final RProcessREnvironment entry : updateEnvirs) {
if (entry.getHandle() == reference.getHandle()) {
- this.fTreeViewer.refresh(reference, true);
+ this.treeViewer.refresh(reference, true);
// reference is readded automatically to new set, if necessary
continue ITER_REFS;
}
@@ -826,177 +861,139 @@
}
}
else {
- this.fTreeViewer.refresh(true);
+ this.treeViewer.refresh(true);
}
// Adapt and set selection
- if (selection != null && !selection.isEmpty()) {
- final ITreeSelection s = (ITreeSelection) selection;
- final TreePath[] paths = s.getPaths();
- int j = 0;
- for (int i = 0; i < paths.length; i++) {
- final TreePath oldPath = paths[i];
- final int count = oldPath.getSegmentCount();
- final int shift = (input.showCondensedUserspace) ? -1 : +1;
+ if (input != null && selection != null && !selection.isEmpty()) {
+ final ITreeSelection s= (ITreeSelection) selection;
+ final TreePath[] paths= s.getPaths();
+ int j= 0;
+ for (int i= 0; i < paths.length; i++) {
+ final TreePath oldPath= paths[i];
+ final int count= oldPath.getSegmentCount();
+ final int shift= (input.isFilterUserspace()) ? -1 : +1;
if (count + shift < 1) {
continue;
}
- final Object[] newPath = new Object[count + shift];
- for (int k = (shift == -1) ? +1 : 0; k < count; k++) {
- newPath[k + shift] = oldPath.getSegment(k);
+ final Object[] newPath= new @NonNull Object[count + shift];
+ for (int k= (shift == -1) ? +1 : 0; k < count; k++) {
+ newPath[k + shift]= oldPath.getSegment(k);
}
if (shift == +1) {
- newPath[0] = ContentProvider.getCombinedRElement(newPath[1]).getModelParent();
+ newPath[0]= RElementInputContentProvider.getCombinedRElement(newPath[1]).getModelParent();
}
- paths[j++] = new TreePath(newPath);
+ paths[j++]= new TreePath(newPath);
}
- this.fTreeViewer.setSelection(new TreeSelection(
+ this.treeViewer.setSelection(new TreeSelection(
(j < paths.length) ? Arrays.copyOf(paths, j) : paths),
true );
}
// Expand Global_Env, if it is a new process and has valid input
- EXPAND_GLOBALENV : if (changed && !input.showCondensedUserspace
- && input.rootElements != null && input.rootElements.length > 0) {
- for (final Object element : input.rootElements) {
- if (this.fTreeViewer.getExpandedState(element)) {
- break EXPAND_GLOBALENV;
+ EXPAND_GLOBALENV: if (input != null && processChanged && !input.isFilterUserspace()) {
+ final CombinedRElement[] rootElements= input.getRootElements();
+ if (rootElements != null && rootElements.length > 0) {
+ for (final Object element : rootElements) {
+ if (this.treeViewer.getExpandedState(element)) {
+ break EXPAND_GLOBALENV;
+ }
}
+ this.treeViewer.expandToLevel(new TreePath(new Object[] { rootElements[0] }), 1);
}
- this.fTreeViewer.expandToLevel(new TreePath(new Object[] { input.rootElements[0] }), 1);
}
+
+ this.isUpdating= false;
+
+ updateSelectionInfo((ITreeSelection) this.actionUtil.getSelectionProvider().getSelection());
}
private void updateFilter() {
- this.fInputUpdater.schedule();
+ this.inputUpdater.schedule();
}
private void updateSorter() {
- this.fTreeViewer.setComparator(this.fSortByType ? TYPE_COMPARATOR : null);
+ this.treeViewer.setComparator((this.sortByType) ? TYPE_COMPARATOR : null);
+ }
+
+ private void clearActionInfo() {
+ this.actionUtil.getStatusLine().clearAll();
}
private void updateSelectionInfo(final ITreeSelection selection) {
- final Object previousInfoObject = this.fCurrentInfoObject;
- this.fCurrentInfoObject = null;
-
- final RProcess tool = getTool();
- if (tool == null) {
+ if (this.isUpdating) {
return;
}
- if (selection.size() == 1) {
- this.fCurrentInfoObject = selection.getFirstElement();
- final TreePath treePath = selection.getPaths()[0];
- final ElementName elementName = getFQElementName(treePath);
- final String name = (elementName != null) ? elementName.getDisplayName() : null;
- if (name != null) {
- if (this.fCurrentInfoObject.equals(previousInfoObject)) {
- clearInfo();
+ Object infoObject= null;
+ String message= null;
+
+ final RProcess tool= getTool();
+ if (tool != null && !selection.isEmpty()) {
+ if (selection.size() == 1) {
+ final TreePath treePath= selection.getPaths()[0];
+ final ElementName elementName= getFQElementName(treePath);
+ final String name= (elementName != null) ? elementName.getDisplayName() : null;
+ if (name != null) {
+ infoObject= selection.getFirstElement();
+ message= name;
}
- this.statusLine.setSelectionMessage(new StatusInfo(IStatus.OK,
- NLS.bind("{0} \u2012 {1}", name, tool.getLabel(Tool.DEFAULT_LABEL)) )); //$NON-NLS-1$
- return;
+ }
+ else {
+ message= NLS.bind("{0} items selected", selection.size());
+ }
+ if (message != null) {
+ message= NLS.bind("{0} \u2012 {1}", message, tool.getLabel(Tool.DEFAULT_LABEL)); //$NON-NLS-1$
}
}
- clearInfo();
- if (selection.size() > 1) {
- this.statusLine.setSelectionMessage(new StatusInfo(IStatus.OK,
- NLS.bind("{0} items selected", selection.size()) ));
- return;
- }
- this.statusLine.setSelectionMessage(null);
- }
-
- private void clearInfo() {
- }
-
- /**
- * Returns a shared clipboard resource, which can be used by actions of this view.
- *
- * @return a clipboard object.
- */
- Clipboard getClipboard() {
- if (this.fClipboard == null) {
- this.fClipboard = new Clipboard(Display.getCurrent());
- }
- return this.fClipboard;
- }
-
- StatusLineMessageManager getStatusLine() {
- return this.statusLine;
- }
-
- @Override
- public void setFocus() {
- this.fTreeViewer.getControl().setFocus();
- }
-
- @Override
- public void dispose() {
- if (this.fToolRegistryListener != null) {
- NicoUI.getToolRegistry().removeListener(this.fToolRegistryListener);
- this.fToolRegistryListener = null;
- }
- if (this.process != null) {
- this.process.getWorkspaceData().removePropertyListener(this.fInputUpdater);
- this.process.getQueue().remove(new ToolRunnable[] { this.fManualRefreshRunnable });
- }
- this.fInputUpdater.cancel();
- if (this.fHoveringController != null) {
- this.fHoveringController.dispose();
- this.fHoveringController = null;
- }
- if (this.fSearchStartHandler != null) {
- this.fSearchStartHandler.dispose();
- this.fSearchStartHandler = null;
- }
- if (this.fCopyElementNameHandler != null) {
- this.fCopyElementNameHandler.dispose();
- this.fCopyElementNameHandler = null;
- }
- if (this.fPrintElementHandler != null) {
- this.fPrintElementHandler.dispose();
- this.fPrintElementHandler = null;
- }
- for (final IToolRetargetable listener : this.fToolListenerList.toArray()) {
- listener.setTool(null);
+ if (infoObject == null || !infoObject.equals(this.currentInfoObject)) {
+ clearActionInfo();
}
-
- super.dispose();
-
- if (this.fClipboard != null) {
- this.fClipboard.dispose();
- this.fClipboard = null;
- }
+ this.currentInfoObject= infoObject;
+ this.actionUtil.getStatusLine().setSelectionMessage(
+ (message != null) ? new StatusInfo(IStatus.OK, message) : null );
}
- public RElementName getFQElementName(final TreePath treePath) {
+ public @Nullable RElementName getFQElementName(final TreePath treePath) {
if (treePath.getSegmentCount() == 0) {
return null;
}
- int segmentIdx = 0;
- if (!this.fFilterUserspaceActivated) {
+ int segmentIdx= 0;
+ if (!this.filterUserspaceActivated) {
if (treePath.getSegmentCount() == 1) { // search path item
- return ContentProvider.getCombinedRElement(treePath.getFirstSegment()).getElementName();
+ return RElementInputContentProvider.getCombinedRElement(treePath.getFirstSegment()).getElementName();
}
else { // main name at 1
- segmentIdx = 1;
+ segmentIdx= 1;
}
}
final List<RElementName> names= new ArrayList<>(treePath.getSegmentCount() - segmentIdx + 1);
- final CombinedRElement first= ContentProvider.getCombinedRElement(treePath.getSegment(segmentIdx++));
+ final CombinedRElement first= RElementInputContentProvider.getCombinedRElement(treePath.getSegment(segmentIdx++));
names.add(first.getModelParent().getElementName());
names.add(first.getElementName());
while (segmentIdx < treePath.getSegmentCount()) {
- final Object object= treePath.getSegment(segmentIdx++);
- if (object instanceof ElementPartition) {
+ final Object segment= treePath.getSegment(segmentIdx++);
+ if (segment instanceof ElementPartition) {
continue;
}
- final CombinedRElement rElement= ContentProvider.getCombinedRElement(object);
+ final CombinedRElement rElement= RElementInputContentProvider.getCombinedRElement(segment);
names.add(rElement.getElementName());
}
return RElementName.create(names);
}
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getAdapter(final Class<T> adapterType) {
+ if (adapterType == Control.class) {
+ return (T) this.treeViewer.getControl();
+ }
+ if (adapterType == Tool.class) {
+ return (T) this.process;
+ }
+ return super.getAdapter(adapterType);
+ }
+
}
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/OpenInEditorHandler.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/OpenInEditorHandler.java
index 95aee4d..69d8c8c 100644
--- a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/OpenInEditorHandler.java
+++ b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/OpenInEditorHandler.java
@@ -20,6 +20,9 @@
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
import org.eclipse.statet.ecommons.ui.workbench.WorkbenchUIUtils;
import org.eclipse.statet.nico.core.runtime.ToolProcess;
@@ -27,8 +30,10 @@
import org.eclipse.statet.r.core.model.RElementName;
import org.eclipse.statet.r.ui.dataeditor.RDataEditor;
import org.eclipse.statet.r.ui.dataeditor.RLiveDataEditorInput;
+import org.eclipse.statet.r.ui.util.RElementInputContentProvider;
+@NonNullByDefault
public class OpenInEditorHandler extends AbstractHandler {
@@ -37,7 +42,7 @@
@Override
- public void setEnabled(final Object evaluationContext) {
+ public void setEnabled(final @Nullable Object evaluationContext) {
final IWorkbenchPart activePart= WorkbenchUIUtils.getActivePart(evaluationContext);
if (activePart instanceof ObjectBrowserView) {
final ObjectBrowserView browser= (ObjectBrowserView) activePart;
@@ -46,7 +51,7 @@
final ITreeSelection selection= browser.getSelection();
if (tool != null && !tool.isTerminated()
&& selection.size() == 1) {
- final CombinedRElement rElement= ContentProvider.getCombinedRElement(selection.getFirstElement());
+ final CombinedRElement rElement= RElementInputContentProvider.getCombinedRElement(selection.getFirstElement());
setBaseEnabled(rElement != null
&& RLiveDataEditorInput.isSupported(rElement) );
return;
@@ -56,7 +61,7 @@
}
@Override
- public Object execute(final ExecutionEvent event) throws ExecutionException {
+ public @Nullable Object execute(final ExecutionEvent event) throws ExecutionException {
final IWorkbenchPart activePart= WorkbenchUIUtils.getActivePart(event.getApplicationContext());
if (activePart instanceof ObjectBrowserView) {
final ObjectBrowserView browser= (ObjectBrowserView) activePart;
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/PrintHandler.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/PrintHandler.java
deleted file mode 100644
index bfc0fa6..0000000
--- a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/PrintHandler.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*=============================================================================#
- # Copyright (c) 2009, 2018 Stephan Wahlbrink and others.
- #
- # This program and the accompanying materials are made available under the
- # terms of the Eclipse Public License 2.0 which is available at
- # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
- # which is available at https://www.apache.org/licenses/LICENSE-2.0.
- #
- # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
- #
- # Contributors:
- # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
- #=============================================================================*/
-
-package org.eclipse.statet.internal.r.objectbrowser;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jface.viewers.ITreeSelection;
-import org.eclipse.jface.viewers.TreePath;
-
-import org.eclipse.statet.ecommons.models.core.util.ElementPartition;
-import org.eclipse.statet.ecommons.ui.util.UIAccess;
-
-import org.eclipse.statet.nico.core.runtime.SubmitType;
-import org.eclipse.statet.nico.core.runtime.ToolController;
-import org.eclipse.statet.nico.core.runtime.ToolProcess;
-import org.eclipse.statet.nico.ui.NicoUITools;
-import org.eclipse.statet.r.console.core.RConsoleTool;
-import org.eclipse.statet.r.core.data.CombinedRElement;
-import org.eclipse.statet.r.core.model.RElementName;
-import org.eclipse.statet.rj.data.RObject;
-
-
-class PrintHandler extends AbstractHandler {
-
-
- private final ObjectBrowserView view;
-
-
- public PrintHandler(final ObjectBrowserView objectBrowserView) {
- this.view = objectBrowserView;
- }
-
-
- private boolean isValidSelection(final ITreeSelection selection) {
- if (selection == null || selection.size() != 1) {
- return false;
- }
- final Object element = selection.getFirstElement();
- if (element instanceof ElementPartition) {
- final CombinedRElement rElement = ContentProvider.getCombinedRElement(element);
- if (rElement == null || rElement.getRObjectType() != RObject.TYPE_LIST) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public void setEnabled(final Object evaluationContext) {
- final ToolProcess process = this.view.getTool();
- setBaseEnabled(process != null && !process.isTerminated()
- && isValidSelection(this.view.getSelection()) );
- }
-
- @Override
- public Object execute(final ExecutionEvent event) throws ExecutionException {
- if (!UIAccess.isOkToUse(this.view.getViewer())) {
- return null;
- }
- final ITreeSelection selection = this.view.getSelection();
- if (!isValidSelection(selection)) {
- return null;
- }
- final TreePath treePath = selection.getPaths()[0];
- final RElementName elementName = this.view.getFQElementName(treePath);
- if (elementName != null) {
- String cmd = RElementName.createDisplayName(elementName, RElementName.DISPLAY_FQN | RElementName.DISPLAY_EXACT);
- if (treePath.getLastSegment() instanceof ElementPartition) {
- final ElementPartition partition = (ElementPartition) treePath.getLastSegment();
- cmd = cmd + '[' + (partition.getPartitionStart() + 1) + ':' + (partition.getPartitionStart() + partition.getPartitionLength()) + ']';
- }
-
- final ToolProcess process = this.view.getTool();
- try {
- final ToolController controller = NicoUITools.accessController(RConsoleTool.TYPE, process);
- controller.submit(cmd, SubmitType.TOOLS);
- }
- catch (final CoreException e) {
- }
- }
-
- return null;
- }
-
-}
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ToggleAutoRefreshHandler.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ToggleAutoRefreshHandler.java
index 78aff7b..315f96e 100644
--- a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ToggleAutoRefreshHandler.java
+++ b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/internal/r/objectbrowser/ToggleAutoRefreshHandler.java
@@ -20,14 +20,19 @@
import org.eclipse.ui.commands.IElementUpdater;
import org.eclipse.ui.menus.UIElement;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
import org.eclipse.statet.ecommons.ui.workbench.WorkbenchUIUtils;
-import org.eclipse.statet.nico.ui.actions.ToolRetargetableHandler;
+import org.eclipse.statet.nico.ui.actions.AbstractToolHandler;
+import org.eclipse.statet.r.console.core.RConsoleTool;
import org.eclipse.statet.r.console.core.RProcess;
import org.eclipse.statet.r.console.core.RWorkspace;
-class ToggleAutoRefreshHandler extends ToolRetargetableHandler implements IElementUpdater {
+@NonNullByDefault
+class ToggleAutoRefreshHandler extends AbstractToolHandler<RProcess> implements IElementUpdater {
private final ObjectBrowserView view;
@@ -36,21 +41,21 @@
public ToggleAutoRefreshHandler(final ObjectBrowserView view) {
- super(view, view.getSite());
+ super(RConsoleTool.TYPE, null, view, view.getSite());
- this.view = view;
+ this.view= view;
init();
}
@Override
public void updateElement(final UIElement element, final Map parameters) {
- this.currentState = false;
- final RProcess tool = this.view.getTool();
+ this.currentState= false;
+ final RProcess tool= getActiveTool();
if (tool != null) {
- final RWorkspace workspace = tool.getWorkspaceData();
+ final RWorkspace workspace= tool.getWorkspaceData();
if (workspace != null) {
- this.currentState = workspace.isAutoRefreshEnabled();
+ this.currentState= workspace.isAutoRefreshEnabled();
}
}
@@ -64,10 +69,10 @@
}
@Override
- protected Object doExecute(final ExecutionEvent event) {
- final RWorkspace workspace = (RWorkspace) getCheckedTool().getWorkspaceData();
+ protected @Nullable Object execute(final RProcess tool, final ExecutionEvent event) {
+ final RWorkspace workspace= tool.getWorkspaceData();
if (workspace != null) {
- this.currentState = !this.currentState;
+ this.currentState= !this.currentState;
workspace.setAutoRefresh(this.currentState);
}
return null;
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/ui/rtool/CopyRElementHandler.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/ui/rtool/CopyRElementHandler.java
new file mode 100644
index 0000000..95d09b5
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/ui/rtool/CopyRElementHandler.java
@@ -0,0 +1,115 @@
+/*=============================================================================#
+ # Copyright (c) 2009, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.ui.rtool;
+
+import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullElse;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+
+import org.eclipse.statet.jcommons.collections.CollectionUtils;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.models.core.util.ElementPartition;
+import org.eclipse.statet.ecommons.ui.util.DNDUtils;
+import org.eclipse.statet.ecommons.ui.util.UIAccess;
+import org.eclipse.statet.ecommons.ui.util.ViewActionUtil;
+
+
+@NonNullByDefault
+public class CopyRElementHandler extends AbstractHandler {
+
+
+ private final ViewActionUtil actionUtil;
+
+ private final ILabelProvider labelProvider;
+
+
+ public CopyRElementHandler(final ViewActionUtil actionUtil, final ILabelProvider labelProvider) {
+ this.actionUtil= actionUtil;
+ this.labelProvider= labelProvider;
+ }
+
+
+ private IStructuredSelection getSelection() {
+ final ISelectionProvider selectionProvider= this.actionUtil.getSelectionProvider();
+ return (IStructuredSelection) selectionProvider.getSelection();
+ }
+
+ protected boolean isValidSelection(final IStructuredSelection selection) {
+ if (selection == null || selection.isEmpty()) {
+ return false;
+ }
+ for (final Object element : selection.toList()) {
+ if (element instanceof ElementPartition) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private @Nullable String getText(final Object element) {
+ return this.labelProvider.getText(element);
+ }
+
+ @Override
+ public void setEnabled(final @Nullable Object evaluationContext) {
+ setBaseEnabled(isValidSelection(getSelection()));
+ }
+
+ @Override
+ public @Nullable Object execute(final ExecutionEvent event) throws ExecutionException {
+ if (!UIAccess.isOkToUse(this.actionUtil.getControl())) {
+ return null;
+ }
+ final IStructuredSelection selection= getSelection();
+ if (!isValidSelection(selection)) {
+ return null;
+ }
+
+ final String text= createData(selection);
+ if (text != null) {
+ copy(text);
+ }
+
+ return null;
+ }
+
+ protected @Nullable String createData(final IStructuredSelection selection) {
+ final List<String> texts= new ArrayList<>(selection.size());
+ for (final Object element : selection.toList()) {
+ texts.add(nonNullElse(getText(element), "-")); //$NON-NLS-1$
+ }
+ return (texts.size() == 1) ?
+ texts.get(0) : CollectionUtils.toString(texts, ", "); //$NON-NLS-1$
+ }
+
+ private void copy(final String text) {
+ DNDUtils.setContent(this.actionUtil.getClipboard(),
+ new String[] { text },
+ new Transfer[] { TextTransfer.getInstance() } );
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/ui/rtool/PrintRElementHandler.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/ui/rtool/PrintRElementHandler.java
new file mode 100644
index 0000000..c949746
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/ui/rtool/PrintRElementHandler.java
@@ -0,0 +1,113 @@
+/*=============================================================================#
+ # Copyright (c) 2009, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.ui.rtool;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.ITreeSelection;
+import org.eclipse.jface.viewers.TreePath;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+import org.eclipse.statet.ecommons.models.core.util.ElementPartition;
+import org.eclipse.statet.ecommons.ts.core.util.ToolProvider;
+import org.eclipse.statet.ecommons.ui.util.UIAccess;
+import org.eclipse.statet.ecommons.ui.util.ViewActionUtil;
+
+import org.eclipse.statet.nico.core.runtime.SubmitType;
+import org.eclipse.statet.nico.core.runtime.ToolController;
+import org.eclipse.statet.nico.ui.NicoUITools;
+import org.eclipse.statet.nico.ui.actions.AbstractToolHandler;
+import org.eclipse.statet.r.console.core.RConsoleTool;
+import org.eclipse.statet.r.console.core.RProcess;
+import org.eclipse.statet.r.core.data.CombinedRElement;
+import org.eclipse.statet.r.core.model.RElementName;
+import org.eclipse.statet.r.ui.util.RElementInputContentProvider;
+import org.eclipse.statet.r.ui.util.RElementInputUtils;
+import org.eclipse.statet.rj.data.RObject;
+
+
+@NonNullByDefault
+public class PrintRElementHandler extends AbstractToolHandler<RProcess> {
+
+
+ private final ViewActionUtil actionUtil;
+
+
+ public PrintRElementHandler(final ViewActionUtil actionUtil) {
+ super(RConsoleTool.TYPE, RConsoleTool.R_BASIC_FEATURESET_ID,
+ (ToolProvider) actionUtil.getWorkbenchPart(), actionUtil.getWorkbenchPart().getSite() );
+ this.actionUtil= actionUtil;
+ }
+
+
+ private ITreeSelection getSelection() {
+ final ISelectionProvider selectionProvider= this.actionUtil.getSelectionProvider();
+ return (ITreeSelection) selectionProvider.getSelection();
+ }
+
+ private boolean isValidSelection(final ITreeSelection selection) {
+ if (selection == null || selection.size() != 1) {
+ return false;
+ }
+ final Object element= selection.getFirstElement();
+ if (element instanceof ElementPartition) {
+ final CombinedRElement rElement= RElementInputContentProvider.getCombinedRElement(element);
+ if (rElement == null || rElement.getRObjectType() != RObject.TYPE_LIST) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ @Override
+ protected boolean evaluateIsEnabled(final RProcess tool, final @Nullable Object evaluationContext) {
+ return (super.evaluateIsEnabled(tool, evaluationContext)
+ && isValidSelection(getSelection()) );
+ }
+
+ @Override
+ protected @Nullable Object execute(final RProcess tool, final ExecutionEvent event) {
+ if (!UIAccess.isOkToUse(this.actionUtil.getControl())) {
+ return null;
+ }
+ final ITreeSelection selection= getSelection();
+ if (!isValidSelection(selection)) {
+ return null;
+ }
+ final TreePath treePath= selection.getPaths()[0];
+ final RElementName elementName= RElementInputUtils.getRElementName(treePath, selection);
+ if (elementName != null) {
+ String cmd= elementName.getDisplayName(RElementName.DISPLAY_FQN | RElementName.DISPLAY_EXACT);
+ if (treePath.getLastSegment() instanceof ElementPartition) {
+ final ElementPartition partition= (ElementPartition) treePath.getLastSegment();
+ cmd= cmd + '[' + (partition.getPartitionStart() + 1) + ':' + (partition.getPartitionStart() + partition.getPartitionLength()) + ']';
+ }
+
+ try {
+ final ToolController controller= NicoUITools.accessController(RConsoleTool.TYPE, tool);
+ controller.submit(cmd, SubmitType.TOOLS);
+ }
+ catch (final CoreException e) {
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/ui/rtool/RElementViewerDragSourceListener.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/ui/rtool/RElementViewerDragSourceListener.java
new file mode 100644
index 0000000..c4971dd
--- /dev/null
+++ b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/ui/rtool/RElementViewerDragSourceListener.java
@@ -0,0 +1,82 @@
+/*=============================================================================#
+ # Copyright (c) 2009, 2018 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.r.ui.rtool;
+
+import org.eclipse.jface.util.TransferDragSourceListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+
+
+@NonNullByDefault
+public class RElementViewerDragSourceListener implements TransferDragSourceListener {
+
+
+ private final CopyRElementHandler commandHandler;
+
+ private final StructuredViewer viewer;
+
+ private String text= ""; //$NON-NLS-1$
+
+
+ public RElementViewerDragSourceListener(final CopyRElementHandler commandHandler,
+ final StructuredViewer viewer) {
+ this.commandHandler= commandHandler;
+ this.viewer= viewer;
+ }
+
+
+ @Override
+ public Transfer getTransfer() {
+ return TextTransfer.getInstance();
+ }
+
+ private ITreeSelection getSelection() {
+ return (ITreeSelection) this.viewer.getSelection();
+ }
+
+ @Override
+ public void dragStart(final DragSourceEvent event) {
+ final IStructuredSelection selection= getSelection();
+ if (!this.commandHandler.isValidSelection(selection)) {
+ event.doit= false;
+ return;
+ }
+
+ final String text= this.commandHandler.createData(selection);
+ if (text != null) {
+ this.text= text;
+ }
+ else {
+ event.doit= false;
+ }
+ }
+
+ @Override
+ public void dragSetData(final DragSourceEvent event) {
+ event.data= this.text;
+ }
+
+ @Override
+ public void dragFinished(final DragSourceEvent event) {
+ this.text= ""; //$NON-NLS-1$
+ }
+
+}
diff --git a/redocs/org.eclipse.statet.redocs.r/META-INF/MANIFEST.MF b/redocs/org.eclipse.statet.redocs.r/META-INF/MANIFEST.MF
index a5ac451..42a7445 100644
--- a/redocs/org.eclipse.statet.redocs.r/META-INF/MANIFEST.MF
+++ b/redocs/org.eclipse.statet.redocs.r/META-INF/MANIFEST.MF
@@ -24,6 +24,7 @@
org.eclipse.statet.ecommons.io,
org.eclipse.statet.ecommons.variables.core,
org.eclipse.statet.jcommons.collections;version="4.0.0",
+ org.eclipse.statet.jcommons.lang;version="4.0.0",
org.eclipse.statet.jcommons.string;version="4.0.0"
Export-Package: org.eclipse.statet.redocs.r,
org.eclipse.statet.redocs.r.core.model,
diff --git a/redocs/org.eclipse.statet.redocs.r/src/org/eclipse/statet/redocs/r/ui/processing/RunRConsoleSnippetOperation.java b/redocs/org.eclipse.statet.redocs.r/src/org/eclipse/statet/redocs/r/ui/processing/RunRConsoleSnippetOperation.java
index 7998844..28b5463 100644
--- a/redocs/org.eclipse.statet.redocs.r/src/org/eclipse/statet/redocs/r/ui/processing/RunRConsoleSnippetOperation.java
+++ b/redocs/org.eclipse.statet.redocs.r/src/org/eclipse/statet/redocs/r/ui/processing/RunRConsoleSnippetOperation.java
@@ -22,7 +22,6 @@
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
-import org.eclipse.core.variables.IStringVariable;
import org.eclipse.osgi.util.NLS;
import org.eclipse.statet.ecommons.io.FileUtil;
@@ -39,6 +38,7 @@
import org.eclipse.statet.nico.core.runtime.IRequireSynch;
import org.eclipse.statet.r.console.core.IRBasicAdapter;
import org.eclipse.statet.r.console.core.RWorkspace;
+import org.eclipse.statet.r.console.core.util.RCodeVariableText;
import org.eclipse.statet.r.core.RUtil;
import org.eclipse.statet.redocs.r.RedocsRweave;
@@ -115,20 +115,8 @@
r.briefAboutToChange();
final RWorkspace rWorkspace= r.getWorkspaceData();
- final VariableText2 variableResolver= new VariableText2(
- getStepConfig().getVariableResolver().getExtraVariables() ) {
- @Override
- protected String checkValue(final IStringVariable variable, String value) throws CoreException {
- if (variable.getName().endsWith("_loc")) { //$NON-NLS-1$
- if (rWorkspace.isRemote()) {
- final IFileStore store= FileUtil.getFileStore(value);
- value= rWorkspace.toToolPath(store);
- }
- return RUtil.escapeBackslash(value);
- }
- return value;
- }
- };
+ final VariableText2 variableResolver= new RCodeVariableText(rWorkspace,
+ getStepConfig().getVariableResolver().getExtraVariables() );
{ // Set wd
final IFileStore dir= FileUtil.getFileStore(VariableUtils.getValue(
diff --git a/redocs/org.eclipse.statet.redocs.r/src/org/eclipse/statet/redocs/r/ui/processing/RunRConsoleSnippetOperationSettings.java b/redocs/org.eclipse.statet.redocs.r/src/org/eclipse/statet/redocs/r/ui/processing/RunRConsoleSnippetOperationSettings.java
index 24365bd..16d58f2 100644
--- a/redocs/org.eclipse.statet.redocs.r/src/org/eclipse/statet/redocs/r/ui/processing/RunRConsoleSnippetOperationSettings.java
+++ b/redocs/org.eclipse.statet.redocs.r/src/org/eclipse/statet/redocs/r/ui/processing/RunRConsoleSnippetOperationSettings.java
@@ -107,7 +107,7 @@
}
{ final TemplateVariableProcessor templateVariableProcessor= new TemplateVariableProcessor();
final RSourceViewerConfigurator configurator= new RTemplateSourceViewerConfigurator(
- RCore.WORKBENCH_ACCESS,
+ RCore.getWorkbenchAccess(),
templateVariableProcessor );
final SnippetEditor1 editor= new SnippetEditor1(configurator, null,
PlatformUI.getWorkbench(), RLaunchingUI.LAUNCH_CONFIG_QUALIFIER, true ) {