1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-04 07:35:24 +02:00

[181145] Restore selection after refresh

This commit is contained in:
Martin Oberhuber 2007-05-15 20:14:37 +00:00
parent eb490366e0
commit 79273b0411
6 changed files with 227 additions and 39 deletions

View file

@ -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.
* <p>
* 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;

View file

@ -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
{

View file

@ -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

View file

@ -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();

View file

@ -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,

View file

@ -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 <code>null</code> 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 <code>null</code> 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 <code>true</code> 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)
{