Multiple improvements and error fixes
diff --git a/bundles/org.eclipse.rap.ui.workbench/META-INF/MANIFEST.MF b/bundles/org.eclipse.rap.ui.workbench/META-INF/MANIFEST.MF
index b1eb198..bfe5e15 100644
--- a/bundles/org.eclipse.rap.ui.workbench/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.rap.ui.workbench/META-INF/MANIFEST.MF
@@ -152,7 +152,7 @@
org.eclipse.ui.views,
org.eclipse.ui.wizards
Bundle-Name: %pluginName
-Bundle-Version: 3.4.9.qualifier
+Bundle-Version: 3.4.10.qualifier
Bundle-ClassPath: .
Bundle-Localization: plugin
Bundle-Activator: org.eclipse.ui.internal.WorkbenchPlugin
diff --git a/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/rap/ui/partdnd/internal/WorkaroundDragPartSource.java b/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/rap/ui/partdnd/internal/WorkaroundDragPartSource.java
index bc292a0..806c9f5 100644
--- a/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/rap/ui/partdnd/internal/WorkaroundDragPartSource.java
+++ b/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/rap/ui/partdnd/internal/WorkaroundDragPartSource.java
@@ -1,174 +1,183 @@
-/*******************************************************************************
- * Copyright (c) 2017 David Marina
- * 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:
- * David Marina - initial API and implementation
- *******************************************************************************/
-package org.eclipse.rap.ui.partdnd.internal;
-
-import static org.eclipse.rap.rwt.internal.protocol.RemoteObjectFactory.getRemoteObject;
-import static org.eclipse.swt.internal.dnd.DNDUtil.convertTransferTypes;
-
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-import org.eclipse.rap.json.JsonValue;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.CTabFolder;
-import org.eclipse.swt.custom.CTabItem;
-import org.eclipse.swt.dnd.DND;
-import org.eclipse.swt.dnd.DragSource;
-import org.eclipse.swt.dnd.Transfer;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-
-
-/**
- * This class is implemented as a workaround for the following issue:<br>
- * <br>
- * When the window is resized and the mouse is on the border of the part (not the part tab itself),
- * the CTabFolder is catching the event and corrupting the browser's window widget by sending a
- * wrong JSON message. After this occurs, the window becomes frozen and it is not possible to
- * restore its functionality. <br>
- * In order to avoid this situation, a mouse listener will decide if the widget under the cursor
- * really belongs to the CTabFolder (ignoring the part's borders).It is important to note that the
- * event sequence might cause that the DragSource event is triggered before the MouseDown event is
- * sent. If that happens, the next mouse events in a short period of time have to be ignored.
- *
- * @author David Marina
- */
-public class WorkaroundDragPartSource extends DragSource {
-
- /** The serialVersionUID of this WorkaroundDragPartSource.java */
- private static final long serialVersionUID = 8801486978319382719L;
- /** The reference to a empty Transfer array */
- private static final Transfer[] EMPTY_TRANSFER = new Transfer[] {};
- /** The reference to the {@link CTabFolder} */
- private final CTabFolder ctf;
- /** Flag to indicated that the drag has started (<code>true</code>) */
- private boolean dragStarted = false;
- /**
- * Flag to ignore mouse events (with <code>true</code>) when the DragStar happens before the
- * MouseDown
- */
- private boolean ignoreEvents = false;
-
- /**
- * Creates a new WorkaroundDragPartSource
- *
- * @param control
- * @param style
- */
- public WorkaroundDragPartSource( Control control, int style ) {
- super( control, style );
- this.ctf = ( CTabFolder )control;
- Listener listener = new Listener() {
-
- /** The serialVersionUID of this WorkaroundDragPartSource.java */
- private static final long serialVersionUID = 7747075970781676002L;
-
- /** {@inheritDoc} */
- @Override
- public void handleEvent( org.eclipse.swt.widgets.Event event ) {
- if( event.type == SWT.MouseDown ) {
- Point absolutePoint = new Point( event.x, event.y );
- CTabItem item = WorkaroundDragPartSource.this.ctf.getItem( absolutePoint );
- if( item == null ) {
- setDragStarted( false );
- }
- // The mouse down event could arrive after the DragStart. In
- // that case we should ignore the mouse event
- else if( !WorkaroundDragPartSource.this.ignoreEvents ) {
- setDragStarted( true );
- startClientTransferRendering();
- }
- } else if( event.type == SWT.MouseUp ) {
- setDragStarted( false );
- }
- }
- };
- if( this.ctf.getData( "DragWorkaroundListener" ) == null ) {
- this.ctf.addListener( SWT.MouseDown, listener );
- this.ctf.addListener( SWT.MouseUp, listener );
- this.ctf.setData( "DragWorkaroundListener", listener );
- }
- }
-
- /**
- * Indicates with an argument that the drag started (<code>true</code>) or ended (
- * <code>false</code>)
- *
- * @param dragStarted a boolean indicating with <code>true</code> the drag start;
- * <code>false</code> to indicate the drag end
- */
- public void setDragStarted( boolean dragStarted ) {
- // If there is no drag operation, set the empty transfer to avoid
- // blocking the window
- if( !dragStarted ) {
- JsonValue renderValue = convertTransferTypes( EMPTY_TRANSFER );
- getRemoteObject( this ).set( "transfer", renderValue );
- this.ignoreEvents = false;
- }
- this.dragStarted = dragStarted;
- }
-
- /** {@inheritDoc} */
- @Override
- public Transfer[] getTransfer() {
- Display display = getDisplay();
- Point location = display.getCursorLocation();
- Point relativePoint = display.map( null, this.ctf, location );
- CTabItem item = this.ctf.getItem( relativePoint );
- if( this.dragStarted || item != null ) {
- return super.getTransfer();
- } else {
- return EMPTY_TRANSFER;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void notifyListeners( int eventType, Event event ) {
- if( eventType == DND.DragStart && !this.dragStarted ) {
- ignoreEvents();
- }
- super.notifyListeners( eventType, event );
- if( event.doit == false || event.type == DND.DragEnd ) {
- setDragStarted( false );
- ignoreEvents();
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected void checkSubclass() {
- // Override to enable subclassing
- }
-
- /**
- * Starts the client transfer rendering
- */
- public void startClientTransferRendering() {
- JsonValue renderValue = convertTransferTypes( super.getTransfer() );
- getRemoteObject( this ).set( "transfer", renderValue );
- }
-
- /**
- * Indicates that the next mouse events shall be ignored for a short period of time
- */
- public void ignoreEvents() {
- this.ignoreEvents = true;
- final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor( 1 );
- executor.schedule( ( ) -> {
- this.ignoreEvents = false;
- }, 500, TimeUnit.MILLISECONDS );
- }
-}
-// -----------------------------------------------------------------------------
+/*******************************************************************************
+ * Copyright (c) 2017 David Marina
+ * 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:
+ * David Marina - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rap.ui.partdnd.internal;
+
+import static org.eclipse.rap.rwt.internal.protocol.RemoteObjectFactory.getRemoteObject;
+import static org.eclipse.swt.internal.dnd.DNDUtil.convertTransferTypes;
+
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.rap.json.JsonValue;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSource;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+
+/**
+ * This class is implemented as a workaround for the following issue:<br>
+ * <br>
+ * When the window is resized and the mouse is on the border of the part (not the part tab itself),
+ * the CTabFolder is catching the event and corrupting the browser's window widget by sending a
+ * wrong JSON message. After this occurs, the window becomes frozen and it is not possible to
+ * restore its functionality. <br>
+ * In order to avoid this situation, a mouse listener will decide if the widget under the cursor
+ * really belongs to the CTabFolder (ignoring the part's borders).It is important to note that the
+ * event sequence might cause that the DragSource event is triggered before the MouseDown event is
+ * sent. If that happens, the next mouse events in a short period of time have to be ignored.
+ *
+ * @author David Marina
+ */
+public class WorkaroundDragPartSource extends DragSource {
+
+ /** The serialVersionUID of this WorkaroundDragPartSource.java */
+ private static final long serialVersionUID = 8801486978319382719L;
+ /** The reference to a empty Transfer array */
+ private static final Transfer[] EMPTY_TRANSFER = new Transfer[] {};
+ /** The reference to the {@link CTabFolder} */
+ private final CTabFolder ctf;
+ /** Flag to indicated that the drag has started (<code>true</code>) */
+ private boolean dragStarted = false;
+ /**
+ * Flag to ignore mouse events (with <code>true</code>) when the DragStar happens before the
+ * MouseDown
+ */
+ private boolean ignoreEvents = false;
+
+ /**
+ * The reference to the thread pool executor
+ */
+ private ScheduledThreadPoolExecutor executor;
+
+ /**
+ * Creates a new WorkaroundDragPartSource
+ *
+ * @param control
+ * @param style
+ */
+ public WorkaroundDragPartSource( Control control, int style ) {
+ super( control, style );
+ this.ctf = ( CTabFolder )control;
+ Listener listener = new Listener() {
+
+ /** The serialVersionUID of this WorkaroundDragPartSource.java */
+ private static final long serialVersionUID = 7747075970781676002L;
+
+ /** {@inheritDoc} */
+ @Override
+ public void handleEvent( org.eclipse.swt.widgets.Event event ) {
+ if( event.type == SWT.MouseDown ) {
+ Point absolutePoint = new Point( event.x, event.y );
+ CTabItem item = WorkaroundDragPartSource.this.ctf.getItem( absolutePoint );
+ if( item == null ) {
+ setDragStarted( false );
+ }
+ // The mouse down event could arrive after the DragStart. In
+ // that case we should ignore the mouse event
+ else if( !WorkaroundDragPartSource.this.ignoreEvents ) {
+ setDragStarted( true );
+ startClientTransferRendering();
+ }
+ } else if( event.type == SWT.MouseUp ) {
+ setDragStarted( false );
+ }
+ }
+ };
+ if( this.ctf.getData( "DragWorkaroundListener" ) == null ) {
+ this.ctf.addListener( SWT.MouseDown, listener );
+ this.ctf.addListener( SWT.MouseUp, listener );
+ this.ctf.setData( "DragWorkaroundListener", listener );
+ }
+
+ this.executor = new ScheduledThreadPoolExecutor( 1 );
+
+ this.ctf.getDisplay().disposeExec(() -> { this.executor.shutdown(); this.executor = null; });
+ }
+
+ /**
+ * Indicates with an argument that the drag started (<code>true</code>) or ended (
+ * <code>false</code>)
+ *
+ * @param dragStarted a boolean indicating with <code>true</code> the drag start;
+ * <code>false</code> to indicate the drag end
+ */
+ public void setDragStarted( boolean dragStarted ) {
+ // If there is no drag operation, set the empty transfer to avoid
+ // blocking the window
+ if( !dragStarted ) {
+ JsonValue renderValue = convertTransferTypes( EMPTY_TRANSFER );
+ getRemoteObject( this ).set( "transfer", renderValue );
+ this.ignoreEvents = false;
+ }
+ this.dragStarted = dragStarted;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Transfer[] getTransfer() {
+ Display display = getDisplay();
+ Point location = display.getCursorLocation();
+ Point relativePoint = display.map( null, this.ctf, location );
+ CTabItem item = this.ctf.getItem( relativePoint );
+ if( this.dragStarted || item != null ) {
+ return super.getTransfer();
+ } else {
+ return EMPTY_TRANSFER;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void notifyListeners( int eventType, Event event ) {
+ if( eventType == DND.DragStart && !this.dragStarted ) {
+ ignoreEvents();
+ }
+ super.notifyListeners( eventType, event );
+ if( event.doit == false || event.type == DND.DragEnd ) {
+ setDragStarted( false );
+ ignoreEvents();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void checkSubclass() {
+ // Override to enable subclassing
+ }
+
+ /**
+ * Starts the client transfer rendering
+ */
+ public void startClientTransferRendering() {
+ JsonValue renderValue = convertTransferTypes( super.getTransfer() );
+ getRemoteObject( this ).set( "transfer", renderValue );
+ }
+
+ /**
+ * Indicates that the next mouse events shall be ignored for a short period of time
+ */
+ public void ignoreEvents() {
+ this.ignoreEvents = true;
+
+ this.executor.schedule( ( ) -> {
+ this.ignoreEvents = false;
+ }, 500, TimeUnit.MILLISECONDS );
+ }
+}
+// -----------------------------------------------------------------------------
diff --git a/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/Workbench.java b/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/Workbench.java
index 22f7fbf..5c13671 100644
--- a/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/Workbench.java
+++ b/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/Workbench.java
@@ -1601,11 +1601,24 @@
*/
/* package */
boolean close(int returnCode, final boolean force) {
- this.returnCode = returnCode;
- final boolean[] ret = new boolean[1];
- BusyIndicator.showWhile(null, () -> ret[0] = busyClose(force));
- return ret[0];
- }
+// RAP [fappel]: take care of the started flag
+// this.returnCode = returnCode;
+// final boolean[] ret = new boolean[1];
+// BusyIndicator.showWhile(null, () -> ret[0] = busyClose(force));
+// return ret[0];
+ try {
+ this.returnCode = returnCode;
+ final boolean[] ret = new boolean[1];
+ BusyIndicator.showWhile(null, new Runnable() {
+ public void run() {
+ ret[0] = busyClose(force);
+ }
+ });
+ return ret[0];
+ } finally {
+ started = false;
+ }
+ }
@Override
public IWorkbenchWindow getActiveWorkbenchWindow() {
@@ -1772,6 +1785,8 @@
* @return true if init succeeded.
*/
private boolean init() {
+ // RAP [fappel]: take care of the started flag
+ started = true;
// setup debug mode if required.
if (WorkbenchPlugin.getDefault().isDebugging()) {
WorkbenchPlugin.DEBUG = true;
diff --git a/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/handlers/DirtyStateTracker.java b/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/handlers/DirtyStateTracker.java
index cc78343..7457a93 100644
--- a/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/handlers/DirtyStateTracker.java
+++ b/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/handlers/DirtyStateTracker.java
@@ -31,19 +31,21 @@
*/
public class DirtyStateTracker implements IPartListener, IWindowListener, IPropertyListener {
- private final IWorkbench workbench;
+// RAP [dm]:
+// private final IWorkbench workbench;
- public DirtyStateTracker() {
- workbench = Workbench.getInstance();
- workbench.addWindowListener(this);
- IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
- register(window);
- }
+ public DirtyStateTracker() {
+// workbench = Workbench.getInstance();
+ Workbench.getInstance().addWindowListener(this);
+ IWorkbenchWindow window = Workbench.getInstance().getActiveWorkbenchWindow();
+ register(window);
+ }
- public void update() {
- IEvaluationService service = workbench.getService(IEvaluationService.class);
- service.requestEvaluation(ISources.ACTIVE_PART_NAME);
- }
+ public void update() {
+ IEvaluationService service = Workbench.getInstance().getService(IEvaluationService.class);
+ service.requestEvaluation(ISources.ACTIVE_PART_NAME);
+ }
+// RAPEND: [dm]
private void register(IWorkbenchWindow window) {
if (window == null) {
diff --git a/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/menus/LegacyActionPersistence.java b/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/menus/LegacyActionPersistence.java
index 49c34c0..7427dac 100644
--- a/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/menus/LegacyActionPersistence.java
+++ b/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/menus/LegacyActionPersistence.java
@@ -131,24 +131,26 @@
* the collection. This should be called before every read.
*/
private final void clearActivations() {
- final IHandlerService service = window
- .getService(IHandlerService.class);
- if (service == null) {
- handlerActivations.clear();
- return;
- }
- service.deactivateHandlers(handlerActivations);
- final Iterator activationItr = handlerActivations.iterator();
- while (activationItr.hasNext()) {
- final IHandlerActivation activation = (IHandlerActivation) activationItr
- .next();
- final IHandler handler = activation.getHandler();
- if (handler != null) {
- handler.dispose();
- }
- }
- handlerActivations.clear();
- }
+ // RAP [dm]:
+// final IHandlerService service = window
+// .getService(IHandlerService.class);
+// if (service == null) {
+ handlerActivations.clear();
+ return;
+// }
+// service.deactivateHandlers(handlerActivations);
+// final Iterator activationItr = handlerActivations.iterator();
+// while (activationItr.hasNext()) {
+// final IHandlerActivation activation = (IHandlerActivation) activationItr
+// .next();
+// final IHandler handler = activation.getHandler();
+// if (handler != null) {
+// handler.dispose();
+// }
+// }
+// handlerActivations.clear();
+ // RAPEND: [dm]
+ }
/**
* Removes all of the image bindings made by this class, and then clears the
diff --git a/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/progress/ProgressViewUpdater.java b/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/progress/ProgressViewUpdater.java
index 97a7db1..fbbe12b 100644
--- a/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/progress/ProgressViewUpdater.java
+++ b/bundles/org.eclipse.rap.ui.workbench/src/org/eclipse/ui/internal/progress/ProgressViewUpdater.java
@@ -14,87 +14,111 @@
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import org.eclipse.rap.rwt.SingletonUtil;
+import org.eclipse.rap.rwt.internal.lifecycle.LifeCycleUtil;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
-import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.util.PrefUtil;
/**
* The ProgressViewUpdater is the singleton that updates viewers.
*/
-class ProgressViewUpdater implements IJobProgressManagerListener {
+//RAP [fappel]: ProgressViewUpdater needs to be a singleton per session
+//class ProgressViewUpdater implements IJobProgressManagerListener {
+//
+// private static ProgressViewUpdater singleton;
+public class ProgressViewUpdater implements IJobProgressManagerListener {
- private static ProgressViewUpdater singleton;
+ // RAP [fappel]: This class will be instanciated using the
+ // SessionSingletonUtil#getInstance(class) method to have a
+ // replacement for the class variable holding the singleton in
+ // RCP.
+ public final static class ProgressViewUpdaterHolder {
+ private ProgressViewUpdaterHolder() {
+ // prevent from instance creation
+ }
- private IProgressUpdateCollector[] collectors;
+ // this is the reference to the actual session singleton instance
+ public ProgressViewUpdater singleton;
+ }
+
+ private Set<IProgressUpdateCollector> collectors;
UpdatesInfo currentInfo = new UpdatesInfo();
boolean debug;
- Throttler throttledUpdate = new Throttler(PlatformUI.getWorkbench().getDisplay(), Duration.ofMillis(100),
- this::update);
+ // RAP [fappel]:
+ private Display display;
+
+ Throttler throttledUpdate;
/**
* The UpdatesInfo is a private class for keeping track of the updates
* required.
*/
- class UpdatesInfo {
+ static class UpdatesInfo {
- Collection additions = new HashSet();
+ Collection<JobTreeElement> additions = new LinkedHashSet<>();
- Collection deletions = new HashSet();
+ Collection<JobTreeElement> deletions = new LinkedHashSet<>();
- Collection refreshes = new HashSet();
+ Collection<JobTreeElement> refreshes = new LinkedHashSet<>();
- boolean updateAll = false;
+ volatile boolean updateAll;
private UpdatesInfo() {
//Create a new instance of the info
}
/**
- * Add an add update
- *
- * @param addition
- */
- void add(JobTreeElement addition) {
+ * Add an add update
+ *
+ * @param addition
+ */
+ synchronized void add(JobTreeElement addition) {
additions.add(addition);
}
/**
- * Add a remove update
- *
- * @param removal
- */
- void remove(JobTreeElement removal) {
+ * Add a remove update
+ *
+ * @param removal
+ */
+ synchronized void remove(JobTreeElement removal) {
deletions.add(removal);
}
/**
- * Add a refresh update
- *
- * @param refresh
- */
- void refresh(JobTreeElement refresh) {
+ * Add a refresh update
+ *
+ * @param refresh
+ */
+ synchronized void refresh(JobTreeElement refresh) {
refreshes.add(refresh);
}
/**
* Reset the caches after completion of an update.
*/
- void reset() {
+ synchronized void reset() {
additions.clear();
deletions.clear();
refreshes.clear();
updateAll = false;
}
- void processForUpdate() {
- HashSet staleAdditions = new HashSet();
+ /**
+ * @return array containing updated, added and deleted items
+ */
+ synchronized JobTreeElement[][] processForUpdate() {
+ HashSet<JobTreeElement> staleAdditions = new HashSet<>();
- Iterator additionsIterator = additions.iterator();
+ Iterator<JobTreeElement> additionsIterator = additions.iterator();
while (additionsIterator.hasNext()) {
- JobTreeElement treeElement = (JobTreeElement) additionsIterator
+ JobTreeElement treeElement = additionsIterator
.next();
if (!treeElement.isActive()) {
if (deletions.contains(treeElement)) {
@@ -105,11 +129,8 @@
additions.removeAll(staleAdditions);
- HashSet obsoleteRefresh = new HashSet();
- Iterator refreshIterator = refreshes.iterator();
- while (refreshIterator.hasNext()) {
- JobTreeElement treeElement = (JobTreeElement) refreshIterator
- .next();
+ HashSet<JobTreeElement> obsoleteRefresh = new HashSet<>();
+ for (JobTreeElement treeElement : refreshes) {
if (deletions.contains(treeElement)
|| additions.contains(treeElement)) {
obsoleteRefresh.add(treeElement);
@@ -131,7 +152,12 @@
refreshes.removeAll(obsoleteRefresh);
- }
+ JobTreeElement[] updateItems = refreshes.toArray(new JobTreeElement[0]);
+ JobTreeElement[] additionItems = additions.toArray(new JobTreeElement[0]);
+ JobTreeElement[] deletionItems = deletions.toArray(new JobTreeElement[0]);
+ return new JobTreeElement[][] { updateItems, additionItems, deletionItems };
+ }
+
}
/**
@@ -139,79 +165,88 @@
*
* @return ProgressViewUpdater
*/
- static ProgressViewUpdater getSingleton() {
- if (singleton == null) {
- singleton = new ProgressViewUpdater();
- }
- return singleton;
+ static ProgressViewUpdater getSingleton() {
+// RAP [fappel]: session aware implementation
+// if (singleton == null) {
+// singleton = new ProgressViewUpdater();
+// }
+// return singleton;
+ ProgressViewUpdaterHolder singletonHolder = getSingletonHolder();
+ if( singletonHolder.singleton == null ) {
+ singletonHolder.singleton = new ProgressViewUpdater();
+ singletonHolder.singleton.display = LifeCycleUtil.getSessionDisplay();
+ singletonHolder.singleton.throttledUpdate = new Throttler(getSingleton().display, Duration.ofMillis(100),
+ singletonHolder.singleton::update);
+ }
+ return singletonHolder.singleton;
+ }
+
+ private static ProgressViewUpdaterHolder getSingletonHolder() {
+ return SingletonUtil.getSessionInstance(ProgressViewUpdaterHolder.class);
}
/**
- * Return whether or not there is a singleton for updates to avoid creating
- * extra listeners.
- *
- * @return boolean <code>true</code> if there is already
- * a singleton
- */
+ * Return whether or not there is a singleton for updates to avoid creating
+ * extra listeners.
+ *
+ * @return boolean <code>true</code> if there is already a singleton
+ */
static boolean hasSingleton() {
- return singleton != null;
+// RAP [fappel]:
+// return singleton != null;
+ return getSingletonHolder().singleton != null;
}
static void clearSingleton() {
- if (singleton != null) {
- ProgressManager.getInstance().removeListener(singleton);
- }
- singleton = null;
+// RAP [fappel]:
+// if (singleton != null) {
+// ProgressManager.getInstance().removeListener(singleton);
+// }
+// singleton = null;
+ if( hasSingleton() ) {
+ ProgressManager.getInstance().removeListener(getSingleton());
+ getSingletonHolder().singleton.display = null;
+ }
+ getSingletonHolder().singleton = null;
}
/**
* Create a new instance of the receiver.
*/
private ProgressViewUpdater() {
- collectors = new IProgressUpdateCollector[0];
+ collectors = new LinkedHashSet<>();
ProgressManager.getInstance().addListener(this);
- debug =
+ debug =
PrefUtil.getAPIPreferenceStore().
getBoolean(IWorkbenchPreferenceConstants.SHOW_SYSTEM_JOBS);
}
/**
- * Add the new collector to the list of collectors.
- *
- * @param newCollector
- */
+ * Add the new collector to the list of collectors.
+ *
+ * @param newCollector
+ */
void addCollector(IProgressUpdateCollector newCollector) {
- IProgressUpdateCollector[] newCollectors = new IProgressUpdateCollector[collectors.length + 1];
- System.arraycopy(collectors, 0, newCollectors, 0, collectors.length);
- newCollectors[collectors.length] = newCollector;
- collectors = newCollectors;
+ collectors.add(newCollector);
}
/**
- * Remove the collector from the list of collectors.
- *
- * @param provider
- */
+ * Remove the collector from the list of collectors.
+ *
+ * @param provider
+ */
void removeCollector(IProgressUpdateCollector provider) {
- HashSet newCollectors = new HashSet();
- for (int i = 0; i < collectors.length; i++) {
- if (!collectors[i].equals(provider)) {
- newCollectors.add(collectors[i]);
- }
- }
- IProgressUpdateCollector[] newArray = new IProgressUpdateCollector[newCollectors
- .size()];
- newCollectors.toArray(newArray);
- collectors = newArray;
+ collectors.remove(provider);
//Remove ourselves if there is nothing to update
- if (collectors.length == 0) {
+ if (collectors.isEmpty()) {
clearSingleton();
}
}
+ /** Running in UI thread by throttledUpdate */
private void update() {
// Abort the update if there isn't anything
- if (collectors.length == 0) {
+ if (collectors.isEmpty()) {
return;
}
@@ -222,15 +257,11 @@
}
} else {
- // Lock while getting local copies of the caches.
- Object[] updateItems;
- Object[] additionItems;
- Object[] deletionItems;
- currentInfo.processForUpdate();
+ JobTreeElement[][] elements = currentInfo.processForUpdate();
- updateItems = currentInfo.refreshes.toArray();
- additionItems = currentInfo.additions.toArray();
- deletionItems = currentInfo.deletions.toArray();
+ JobTreeElement[] updateItems = elements[0];
+ JobTreeElement[] additionItems = elements[1];
+ JobTreeElement[] deletionItems = elements[2];
currentInfo.reset();
@@ -248,31 +279,7 @@
}
}
- /**
- * Get the updates info that we are using in the receiver.
- *
- * @return Returns the currentInfo.
- */
- UpdatesInfo getCurrentInfo() {
- return currentInfo;
- }
-
- /**
- * Refresh the supplied JobInfo.
- * @param info
- */
- public void refresh(JobInfo info) {
- currentInfo.refresh(info);
- GroupInfo group = info.getGroupInfo();
- if (group != null) {
- currentInfo.refresh(group);
- }
- //Add in a 100ms delay so as to keep priority low
- throttledUpdate.throttledExec();
-
- }
-
- @Override
+ @Override
public void refreshJobInfo(JobInfo info) {
currentInfo.refresh(info);
//Add in a 100ms delay so as to keep priority low
@@ -280,33 +287,28 @@
}
- @Override
+ @Override
public void refreshGroup(GroupInfo info) {
currentInfo.refresh(info);
//Add in a 100ms delay so as to keep priority low
throttledUpdate.throttledExec();
-
}
- @Override
+ @Override
public void addGroup(GroupInfo info) {
-
currentInfo.add(info);
throttledUpdate.throttledExec();
-
}
- @Override
+ @Override
public void refreshAll() {
-
currentInfo.updateAll = true;
//Add in a 100ms delay so as to keep priority low
throttledUpdate.throttledExec();
-
}
- @Override
+ @Override
public void addJob(JobInfo info) {
GroupInfo group = info.getGroupInfo();
@@ -316,10 +318,9 @@
currentInfo.refresh(group);
}
throttledUpdate.throttledExec();
-
}
- @Override
+ @Override
public void removeJob(JobInfo info) {
GroupInfo group = info.getGroupInfo();
if (group == null) {
@@ -330,14 +331,13 @@
throttledUpdate.throttledExec();
}
- @Override
+ @Override
public void removeGroup(GroupInfo group) {
currentInfo.remove(group);
throttledUpdate.throttledExec();
-
}
- @Override
+ @Override
public boolean showsDebug() {
return debug;
}