diff --git a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/core/events/ISystemResourceChangeEvents.java b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/core/events/ISystemResourceChangeEvents.java index 2a76b0a0c9c..7c0bf28e60b 100644 --- a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/core/events/ISystemResourceChangeEvents.java +++ b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/core/events/ISystemResourceChangeEvents.java @@ -16,6 +16,8 @@ package org.eclipse.rse.core.events; +import org.eclipse.rse.core.subsystems.IRemoteObjectIdentifier; + /** * Interface of event ID constants */ @@ -126,29 +128,78 @@ public interface ISystemResourceChangeEvents * The event is an icon change event */ public static final int EVENT_ICON_CHANGE = 81; + /** - * The event is a full refresh event: all expanded sub-nodes are re-queried for their children, unexpanded nodes lose their children cache. + * Refresh the single item passed in the "source" field of the event. + * + * All expanded sub-nodes are re-queried for their children, unexpanded + * nodes lose their children cache. Selection is not maintained by this + * event (use EVENT_REFRESH_REMOTE instead to maintain the selection). */ public static final int EVENT_REFRESH = 82; + /** - * The event is a selection-dependent refresh event: all expanded sub-nodes are re-queried for their children, unexpanded nodes lose their children cache. + * Refresh the items currently selected in the SystemView. + * + * All expanded sub-nodes are re-queried for their children, unexpanded nodes + * lose their children cache. After refreshing, selection of the currently selected + * elements is restored if possible (in case an absoluteName is available). + * + * In case any of the selected items is a leaf node, the parent of that + * leaf node is refreshed rather than the leaf node itself. In this particular + * case, a multiselect is not considered properly. + * + * The SystemScratchpadView also listens to this event and refreshes those + * elements that are selected in it. + * + * @deprecated obtain the selection yourself and do EVENT_REFRESH or EVENT_REFRESH_REMOTE */ public static final int EVENT_REFRESH_SELECTED = 83; + /** - * The event is a selection-dependent refresh event: refreshes the parent of the current selections + * Refresh the parent of the first item currently selected in the SystemView. + * + * This only refreshes the parent TreeItem of the first item in the selection. + * It does not consider multiselect, multiple occurrences of the Item under multiple + * filters, and does not maintain the current selection. + * + * @deprecated obtain the selection yourself and do EVENT_REFRESH or EVENT_REFRESH_REMOTE */ public static final int EVENT_REFRESH_SELECTED_PARENT = 84; + /** - * The event is a selection-dependent refresh event: from the filter level, all expanded sub-nodes are re-queried for their children, unexpanded nodes lose their children cache. + * Refresh the filter under which the first item currently selected in the + * SystemView is found. + * + * From the filter level, all expanded sub-nodes are re-queried + * for their children, unexpanded nodes lose their children cache. + * After refreshing, selection of the currently selected elements + * is restored if possible. Multiselect is not considered properly. + * + * @deprecated Refreshing a particular context(filter) only can lead + * to inconsistencies, so better obtain the selection yourself + * and do EVENT_REFRESH or EVENT_REFRESH_REMOTE */ public static final int EVENT_REFRESH_SELECTED_FILTER = 135; + /** - * The event is refreshes a remote object (has an ISystemViewRemoteElementAdapter) given either the remote object or a string that will match on getAbsoluteName. - * The tricky part about remote objects is their actual memory object changes on each refresh, so to find one in the tree we must use something + * Refresh a remote object in the SystemView, given either the remote + * object or a string that will match on getAbsoluteName, and optionally + * (re)select a list of objects after refreshing. + * + * An object is considered remote if it has an adapter that implements + * {@link ISystemViewElementAdapter}, so it is possible to get the + * associated subsystem and absolute name. This method refreshes all + * occurrences of the remote object, even under multiple filters. + * The tricky part about remote objects is their actual memory object changes + * on each refresh, so to find one in the tree we must use something * more permanent: hence the use of getAbsoluteName to find it. *
- * You can optionally pass a child remote object, or string, or vector of objects or strings, in the parent parameter, and it/they will be selected after the refresh.
- * If it a string then it must be the result of getAbsoluteName on the adapter.
+ * You can optionally pass a child remote object, or string, or Vector of
+ * objects or strings, in the "parent" parameter of the event, and it/they
+ * will be selected after the refresh. When passing a string, it must be
+ * the result of {@link IRemoteObjectIdentifier#getAbsoluteName(Object)}
+ * on the adapter.
*/
public static final int EVENT_REFRESH_REMOTE = 85;
@@ -192,8 +243,16 @@ public interface ISystemResourceChangeEvents
* The event is simply to force selection of the given object.
*/
public static final int EVENT_SELECT = 100;
+
/**
- * The event is to select a remote object
+ * Select one or more remote objects.
+ *
+ * The "src" parameter holds a remote object, or string, or Vector of
+ * objects or strings. When passing a string, it must be the result of
+ * {@link IRemoteObjectIdentifier#getAbsoluteName(Object)}
+ * on the adapter of the object.
+ * The "parent" parameter can optionally hold a model object that is
+ * the parent of the objects to be refreshed, in order to optimize searches.
*/
public static final int EVENT_SELECT_REMOTE = 101;
diff --git a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemView.java b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemView.java
index e00e0e4011c..2d5d6c6b8b8 100644
--- a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemView.java
+++ b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemView.java
@@ -1609,6 +1609,8 @@ public class SystemView extends SafeTreeViewer
public ResourceChangedJob(ISystemResourceChangeEvent event, SystemView originatingViewer) {
super("Resource Changed..."); //$NON-NLS-1$
+ //FIXME Shouldn't the originatingViewer be taken from the event if possible, if it is instanceof ISystemResourceChangeEventUI?
+ //See also originatedHere, below
_originatingViewer = originatingViewer;
_event = event;
}
@@ -1941,6 +1943,7 @@ public class SystemView extends SafeTreeViewer
if ((src == null) || (src == RSECorePlugin.getTheSystemRegistry()))
refreshAll();
else {
+ //FIXME Why do we forceRemote here? EVENT_REFRESH_SELECTED also does not do forceRemote.
//smartRefresh(src, false);
smartRefresh(src, true);
}
@@ -1996,6 +1999,7 @@ public class SystemView extends SafeTreeViewer
}
if (parentElementItem != null) {
//refresh(parentElement);
+ //FIXME IF a multi-select contains elements with a different parent than the one found, they will be ignored.
smartRefresh(new TreeItem[] { (TreeItem) parentElementItem });
if (selectedRemoteObjects.size() > 0) {
selectRemoteObjects(selectedRemoteObjects, ss, parentElementItem);
@@ -2797,18 +2801,27 @@ public class SystemView extends SafeTreeViewer
ISystemViewElementAdapter rmtAdapter = null;
ISubSystem subsystem = null;
String oldElementName = null;
+ boolean doesDeferredQueries = false;
if (!(remoteObject instanceof String)) {
rmtAdapter = getViewAdapter(remoteObject);
if (rmtAdapter == null) return false;
subsystem = rmtAdapter.getSubSystem(remoteObject);
oldElementName = rmtAdapter.getAbsoluteName(remoteObject);
+ doesDeferredQueries = rmtAdapter.supportsDeferredQueries(subsystem);
} else
oldElementName = (String) remoteObject;
Vector matches = new Vector();
// STEP 2: find all references to the object
findAllRemoteItemReferences(oldElementName, remoteObject, subsystem, matches);
- if (remoteObject instanceof String) remoteObject = getFirstRemoteObject(matches);
+ if (remoteObject instanceof String) {
+ remoteObject = getFirstRemoteObject(matches);
+ rmtAdapter = getViewAdapter(remoteObject);
+ if (rmtAdapter!=null) {
+ subsystem = rmtAdapter.getSubSystem(remoteObject);
+ doesDeferredQueries = rmtAdapter.supportsDeferredQueries(subsystem);
+ }
+ }
if (remoteObject instanceof ISystemContainer) {
((ISystemContainer) remoteObject).markStale(true);
@@ -2842,7 +2855,11 @@ public class SystemView extends SafeTreeViewer
// STEP 4: If requested, select the kids in the newly refreshed object.
// If the same binary object appears multiple times, select the kids in the first occurrence.
// ... what else to do?
- if (!(toSelect instanceof SystemViewDummyObject)) selectRemoteObjects(toSelect, null, match); // select the given kids in this parent
+ if (!doesDeferredQueries && !(toSelect instanceof SystemViewDummyObject)) {
+ //selecting remote objects makes only sense if not deferred, because
+ //in the deferred case the objects will be retrieved in a separate job.
+ selectRemoteObjects(toSelect, null, match); // select the given kids in this parent
+ }
}
}
}
@@ -2894,7 +2911,8 @@ public class SystemView extends SafeTreeViewer
if (forceRemote || (isSelectionRemote() && isTreeItemSelectedOrChildSelected(widget))) {
if (!isTreeItemSelected(widget)) // it is one of our kids that is selected
{
- clearSelection(); // there is nothing much else we can do. Calling code will restore it anyway hopefully
+ //MOB cannot see why the selection is cleared here
+ //clearSelection(); // there is nothing much else we can do. Calling code will restore it anyway hopefully
doOurInternalRefresh(fWidget, fElement, fDoStruct, true);
} else // it is us that is selected. This might be a refresh selected operation. TreeItem address won't change
{
diff --git a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemViewLabelAndContentProvider.java b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemViewLabelAndContentProvider.java
index b6d2dc489e9..ef64b06804b 100644
--- a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemViewLabelAndContentProvider.java
+++ b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemViewLabelAndContentProvider.java
@@ -287,7 +287,7 @@ public class SystemViewLabelAndContentProvider extends LabelProvider
// if (ss.isConnected())
{
- Object[] children = manager.getChildren(object);
+ Object[] children = manager.getChildren(object, getViewer());
if (children != null)
{
// This will be a placeholder to indicate
diff --git a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemViewPart.java b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemViewPart.java
index cec6ed7b4e4..b3896fdeab3 100644
--- a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemViewPart.java
+++ b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/internal/ui/view/SystemViewPart.java
@@ -1718,7 +1718,9 @@ public class SystemViewPart
list.add(element);
//System.out.println("Added to selection list: " + element);
}
- systemView.setSelection(new StructuredSelection(list));
+ if (list.size()>0) {
+ systemView.setSelection(new StructuredSelection(list));
+ }
if (remoteElements.size() > 0)
{
Vector v = new Vector();
diff --git a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/actions/SystemRefreshAction.java b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/actions/SystemRefreshAction.java
index e41b0e3162a..237f2cf0c33 100644
--- a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/actions/SystemRefreshAction.java
+++ b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/actions/SystemRefreshAction.java
@@ -17,7 +17,9 @@
********************************************************************************/
package org.eclipse.rse.ui.actions;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.Set;
import java.util.Vector;
import org.eclipse.core.runtime.IAdaptable;
@@ -77,40 +79,77 @@ public class SystemRefreshAction extends SystemBaseAction
ISystemRegistry sr = RSECorePlugin.getTheSystemRegistry();
if (_selection != null)
{
- Vector parents = new Vector();
+ Set localItems = new HashSet();
+ Set remoteItems = new HashSet();
+ Vector namesToSelect = new Vector();
Iterator iter = _selection.iterator();
-
- while(iter.hasNext())
- {
+ while(iter.hasNext()) {
Object obj = iter.next();
-
- if (obj instanceof ISystemContainer)
- {
+ if (obj instanceof ISystemContainer) {
((ISystemContainer)obj).markStale(true);
}
// get the adapter and find out if it's a leaf node. If so, refresh the parent as well.
ISystemViewElementAdapter adapter = getViewAdapter(obj);
-
if (adapter != null) {
- Object parent = adapter.getParent(obj);
- boolean hasChildren = adapter.hasChildren((IAdaptable)obj);
-
- if ((parent != null) && !hasChildren && (!parents.contains(parent))) {
- parents.add(parent);
- sr.fireEvent(new SystemResourceChangeEvent(parent, ISystemResourceChangeEvents.EVENT_REFRESH, parent));
+ // choose the item to refresh -- use parent in case of leaf node
+ Object itemToRefresh = obj;
+ if (!adapter.hasChildren((IAdaptable)obj)) {
+ Object parent = adapter.getParent(obj);
+ if (parent!=null) {
+ itemToRefresh = parent;
+ }
+ }
+
+ // If we can REFRESH_REMOTE, add the absolute name to reselect
+ String absoluteName = adapter.getAbsoluteName(obj);
+ if (absoluteName!=null) {
+ //Remote items will be refreshed later
+ remoteItems.add(itemToRefresh);
+ namesToSelect.add(absoluteName);
+ } else if (!localItems.contains(obj)) {
+ localItems.add(obj);
+ sr.fireEvent(new SystemResourceChangeEvent(obj, ISystemResourceChangeEvents.EVENT_REFRESH, obj));
}
-
- sr.fireEvent(new SystemResourceChangeEvent(obj, ISystemResourceChangeEvents.EVENT_REFRESH, obj));
}
else {
sr.fireEvent(new SystemResourceChangeEvent(obj, ISystemResourceChangeEvents.EVENT_REFRESH, obj));
}
}
+ //Free objects
+ localItems.clear();
+ //Deferred refresh of remote items: Try to optimize refresh by reducing the number of parents
+ boolean itemsChanged = true;
+ while (remoteItems.size()>1 && itemsChanged) {
+ itemsChanged = false;
+ Iterator it = remoteItems.iterator();
+ while (it.hasNext()) {
+ Object obj = it.next();
+ ISystemViewElementAdapter adapter = getViewAdapter(obj);
+ Object parent = adapter.getParent(obj);
+ if (remoteItems.contains(parent)) {
+ it.remove();
+ itemsChanged = true;
+ }
+ }
+ }
+ //Fire events
+ Iterator it = remoteItems.iterator();
+ while (it.hasNext()) {
+ Object obj = it.next();
+ String absName = getViewAdapter(obj).getAbsoluteName(obj);
+ if (absName!=null) {
+ sr.fireEvent(new SystemResourceChangeEvent(obj, ISystemResourceChangeEvents.EVENT_REFRESH_REMOTE, namesToSelect));
+ } else {
+ sr.fireEvent(new SystemResourceChangeEvent(obj, ISystemResourceChangeEvents.EVENT_REFRESH, obj));
+ sr.fireEvent(new SystemResourceChangeEvent(namesToSelect, ISystemResourceChangeEvents.EVENT_SELECT_REMOTE, null));
+ }
+ }
}
else
{
+ //TODO Check if this is dead code?
if ((viewer != null) && (viewer instanceof ISystemResourceChangeListener))
{
sr.fireEvent((ISystemResourceChangeListener)viewer,
diff --git a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/operations/SystemDeferredTreeContentManager.java b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/operations/SystemDeferredTreeContentManager.java
index b50df58b204..9015b543eb5 100644
--- a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/operations/SystemDeferredTreeContentManager.java
+++ b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/operations/SystemDeferredTreeContentManager.java
@@ -14,11 +14,15 @@
package org.eclipse.rse.ui.operations;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
import org.eclipse.rse.ui.view.IContextObject;
import org.eclipse.ui.progress.DeferredTreeContentManager;
import org.eclipse.ui.progress.IDeferredWorkbenchAdapter;
@@ -54,15 +58,9 @@ public class SystemDeferredTreeContentManager extends
return super.getAdapter(element);
}
- /**
- * Returns the child elements of the given element, or in the case of a
- * deferred element, returns a placeholder. If a deferred element is used, a
- * job is created to fetch the children in the background.
- *
- * @param parent
- * The parent object.
- * @return Object[] or null
if parent is not an instance of
- * IDeferredWorkbenchAdapter.
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.progress.DeferredTreeContentManager#getChildren(java.lang.Object)
*/
public Object[] getChildren(final Object parent) {
IDeferredWorkbenchAdapter element = getAdapter(parent);
@@ -80,6 +78,78 @@ public class SystemDeferredTreeContentManager extends
return null;
}
+ /**
+ * Returns the child elements of the given element, or in the case of a
+ * deferred element, returns a placeholder. If a deferred element is used, a
+ * job is created to fetch the children in the background.
+ *
+ * When the job for fetching the children is finished and the placeholder
+ * removed, the original selection is restored.
+ *
+ * @param parent
+ * The parent object.
+ * @param viewer
+ * The viewer
+ * @return Object[] or null
if parent is not an instance of
+ * IDeferredWorkbenchAdapter.
+ */
+ public Object[] getChildren(final Object parent, final Viewer viewer) {
+ final ISelection selection = viewer.getSelection();
+ if (selection.isEmpty()) {
+ return getChildren(parent);
+ }
+ IDeferredWorkbenchAdapter element = getAdapter(parent);
+ if (element == null) {
+ return null;
+ }
+ PendingUpdateAdapter placeholder = new PendingUpdateAdapter() {
+ protected void setRemoved(boolean removedValue) {
+ super.setRemoved(removedValue);
+ ISelection curSel = viewer.getSelection();
+ //Only restore selection if the user has not changed it manually.
+ //TODO in some cases we might need to send an EVENT_SELECT_REMOTE
+ //listing the absolute paths of the original selection, in order
+ //to properly find the items that should be selected.
+ if (isSelectionContainedIn(curSel, selection)) {
+ viewer.setSelection(selection);
+ }
+ }
+ };
+
+ if (!_pendingQueries.contains(parent))
+ {
+ startFetchingDeferredChildren(parent, element, placeholder);
+ _pendingQueries.add(parent);
+ return new Object[] { placeholder };
+ }
+ return null;
+ }
+
+ /**
+ * Test whether a given selection is a subset of another (parent) selection.
+ * @param sel Selection to check
+ * @param parent Parent selection
+ * @return true
if the given selection is a subset.
+ */
+ private boolean isSelectionContainedIn(ISelection sel, ISelection parent) {
+ if (sel.isEmpty())
+ return true;
+ if (sel.equals(parent))
+ return false;
+ if ((sel instanceof IStructuredSelection) && (parent instanceof IStructuredSelection)) {
+ IStructuredSelection ssel = (IStructuredSelection)sel;
+ List spar = ((IStructuredSelection)parent).toList();
+ Iterator it = ssel.iterator();
+ while (it.hasNext()) {
+ Object o = it.next();
+ if (!spar.contains(o))
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
protected void addChildren(final Object parent, final Object[] children,
IProgressMonitor monitor)
{