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:
parent
eb490366e0
commit
79273b0411
6 changed files with 227 additions and 39 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue