mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 01:15:29 +02:00
Bug 327358 - [variables][vm] "Wait for views to update after every step" preference doesn't always work
This commit is contained in:
parent
0fab073833
commit
7c8d11496e
9 changed files with 144 additions and 679 deletions
|
@ -35,7 +35,6 @@ Export-Package: org.eclipse.cdt.dsf.debug.internal.ui;x-internal:=true,
|
|||
org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.actions;x-internal:=true,
|
||||
org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.detailsupport;x-internal:=true,
|
||||
org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.numberformat.detail;x-internal:=true,
|
||||
org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional;x-internal:=true,
|
||||
org.eclipse.cdt.dsf.debug.ui,
|
||||
org.eclipse.cdt.dsf.debug.ui.actions,
|
||||
org.eclipse.cdt.dsf.debug.ui.contexts,
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008, 2009 Wind River Systems 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:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.actions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.ICachingVMProviderExtension;
|
||||
import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.IVMUpdateScope;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.VMHandlerUtils;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
|
||||
import org.eclipse.jface.action.Action;
|
||||
import org.eclipse.jface.action.ActionContributionItem;
|
||||
import org.eclipse.jface.action.ContributionItem;
|
||||
import org.eclipse.jface.action.IContributionItem;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.widgets.Menu;
|
||||
import org.eclipse.swt.widgets.MenuItem;
|
||||
import org.eclipse.ui.actions.CompoundContributionItem;
|
||||
import org.eclipse.ui.menus.IWorkbenchContribution;
|
||||
import org.eclipse.ui.services.IServiceLocator;
|
||||
|
||||
/**
|
||||
* Dynamic menu contribution that shows available update scopes
|
||||
* in the current view.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public class UpdateScopesContribution extends CompoundContributionItem implements IWorkbenchContribution {
|
||||
|
||||
private class SelectUpdateScopeAction extends Action {
|
||||
private final ICachingVMProviderExtension fProvider;
|
||||
private final IVMUpdateScope fScope;
|
||||
SelectUpdateScopeAction(ICachingVMProviderExtension provider, IVMUpdateScope scope) {
|
||||
super(scope.getName(), AS_RADIO_BUTTON);
|
||||
fProvider = provider;
|
||||
fScope = scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (isChecked()) {
|
||||
fProvider.setActiveUpdateScope(fScope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IServiceLocator fServiceLocator;
|
||||
|
||||
private static IContributionItem[] NO_BREAKPOINT_TYPES_CONTRIBUTION_ITEMS = new IContributionItem[] {
|
||||
new ContributionItem() {
|
||||
@Override
|
||||
public void fill(Menu menu, int index) {
|
||||
MenuItem item = new MenuItem(menu, SWT.NONE);
|
||||
item.setEnabled(false);
|
||||
item.setText(MessagesForVMActions.UpdateScopesContribution_EmptyScopesList_label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected IContributionItem[] getContributionItems() {
|
||||
IVMProvider provider = VMHandlerUtils.getActiveVMProvider(fServiceLocator);
|
||||
|
||||
// If no part or selection, disable all.
|
||||
if (provider == null || !(provider instanceof ICachingVMProviderExtension)) {
|
||||
return NO_BREAKPOINT_TYPES_CONTRIBUTION_ITEMS;
|
||||
}
|
||||
ICachingVMProviderExtension cachingProvider = (ICachingVMProviderExtension)provider;
|
||||
|
||||
IVMUpdateScope[] scopes = cachingProvider.getAvailableUpdateScopes();
|
||||
IVMUpdateScope activeScope = cachingProvider.getActiveUpdateScope();
|
||||
|
||||
List<Action> actions = new ArrayList<Action>(scopes.length);
|
||||
for (IVMUpdateScope scope : scopes) {
|
||||
Action action = new SelectUpdateScopeAction(cachingProvider, scope);
|
||||
if (scope.getID().equals(activeScope.getID())) {
|
||||
action.setChecked(true);
|
||||
}
|
||||
actions.add(action);
|
||||
}
|
||||
|
||||
if ( actions.isEmpty() ) {
|
||||
return NO_BREAKPOINT_TYPES_CONTRIBUTION_ITEMS;
|
||||
}
|
||||
|
||||
IContributionItem[] items = new IContributionItem[actions.size()];
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
items[i] = new ActionContributionItem(actions.get(i));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
public void initialize(IServiceLocator serviceLocator) {
|
||||
fServiceLocator = serviceLocator;
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008, 2009 Wind River Systems 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:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.actions;
|
||||
|
||||
import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.ICachingVMProviderExtension;
|
||||
import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.IVMUpdateScope;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.VMHandlerUtils;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
|
||||
import org.eclipse.core.expressions.PropertyTester;
|
||||
import org.eclipse.debug.ui.IDebugView;
|
||||
import org.eclipse.ui.IWorkbenchPart;
|
||||
|
||||
/**
|
||||
* Property tester for update scope information available through the given
|
||||
* object. The object being tested should be either an {@link IVMContext},
|
||||
* through which an instance of {@link ICachingVMProviderExtension} could be obtained.
|
||||
* Or it could be an {@link IWorkbenchPart}, which is tested to see if it
|
||||
* is a debug view through which a caching VM provider can be obtained.
|
||||
* The Caching View Model provider is used to test the given property.
|
||||
* <p>
|
||||
* Three properties are supported:
|
||||
* <ul>
|
||||
* <li> "areUpdateScopesSupported" - Checks whether update scopes are
|
||||
* available at all given the receiver.</li>
|
||||
* <li> "isUpdateScopeAvailable" - Checks whether the update scope in the
|
||||
* expected value is available for the given receiver.</li>
|
||||
* <li> "isUpdateScopeActive" - Checks whether the scope given in the expected
|
||||
* value is the currently active scope for the given receiver.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public class UpdateScopesPropertyTester extends PropertyTester {
|
||||
|
||||
private static final String SUPPORTED = "areUpdateScopesSupported"; //$NON-NLS-1$
|
||||
private static final String AVAILABLE = "isUpdateScopeAvailable"; //$NON-NLS-1$
|
||||
private static final String ACTIVE = "isUpdateScopeActive"; //$NON-NLS-1$
|
||||
|
||||
public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
|
||||
if (receiver instanceof IVMContext) {
|
||||
IVMProvider provider = ((IVMContext)receiver).getVMNode().getVMProvider();
|
||||
if (provider instanceof ICachingVMProviderExtension) {
|
||||
return testProvider((ICachingVMProviderExtension)provider, property, expectedValue);
|
||||
}
|
||||
} else if (receiver instanceof IDebugView) {
|
||||
IVMProvider provider = VMHandlerUtils.getVMProviderForPart((IDebugView)receiver);
|
||||
if (provider instanceof ICachingVMProviderExtension) {
|
||||
return testProvider((ICachingVMProviderExtension)provider, property, expectedValue);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean testProvider(ICachingVMProviderExtension provider, String property, Object expectedValue) {
|
||||
if (SUPPORTED.equals(property)) {
|
||||
return true;
|
||||
} else if (AVAILABLE.equals(property)) {
|
||||
for (IVMUpdateScope scope : provider.getAvailableUpdateScopes()) {
|
||||
if (scope.getID().equals(expectedValue)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else if (ACTIVE.equals(property)) {
|
||||
return expectedValue != null && expectedValue.equals(provider.getActiveUpdateScope().getID());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007, 2009 Wind River Systems 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:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional;
|
||||
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.ViewModelUpdateMessages;
|
||||
|
||||
|
||||
/**
|
||||
* An "automatic" update policy which causes the view model provider cache to
|
||||
* be flushed whenever an event causes a delta to be generated in the given
|
||||
* model.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public class AllUpdateScope implements IVMUpdateScope {
|
||||
|
||||
public static String ALL_UPDATE_SCOPE_ID = "org.eclipse.cdt.dsf.ui.viewmodel.update.allUpdateScope"; //$NON-NLS-1$
|
||||
|
||||
public String getID() {
|
||||
return ALL_UPDATE_SCOPE_ID;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return ViewModelUpdateMessages.AllUpdateScope_name;
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008, 2009 Wind River Systems 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:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional;
|
||||
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.ICachingVMProvider;
|
||||
|
||||
|
||||
/**
|
||||
* @since 1.1
|
||||
*/
|
||||
public interface ICachingVMProviderExtension extends ICachingVMProvider {
|
||||
|
||||
/**
|
||||
* Returns the update policies that the given provider supports.
|
||||
*/
|
||||
public IVMUpdateScope[] getAvailableUpdateScopes();
|
||||
|
||||
/**
|
||||
* Returns the active update policy.
|
||||
*/
|
||||
public IVMUpdateScope getActiveUpdateScope();
|
||||
|
||||
/**
|
||||
* Sets the active update policy. This has to be one of the update
|
||||
* policies supported by the provider.
|
||||
*/
|
||||
public void setActiveUpdateScope(IVMUpdateScope mode);
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007, 2009 Wind River Systems 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:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional;
|
||||
|
||||
|
||||
/**
|
||||
* @since 1.1
|
||||
*/
|
||||
public interface IVMUpdateScope {
|
||||
|
||||
/**
|
||||
* Returns unique ID of this update policy.
|
||||
*/
|
||||
public String getID();
|
||||
|
||||
/**
|
||||
* Returns the user-presentable name of this update policy.
|
||||
*/
|
||||
public String getName();
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007, 2009 Wind River Systems 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:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional;
|
||||
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.ViewModelUpdateMessages;
|
||||
|
||||
|
||||
/**
|
||||
* An "automatic" update policy which causes the view model provider cache to
|
||||
* be flushed whenever an event causes a delta to be generated in the given
|
||||
* model.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public class VisibleUpdateScope implements IVMUpdateScope {
|
||||
|
||||
public static String VISIBLE_UPDATE_SCOPE_ID = "org.eclipse.cdt.dsf.ui.viewmodel.update.visibleUpdateScope"; //$NON-NLS-1$
|
||||
|
||||
public String getID() {
|
||||
return VISIBLE_UPDATE_SCOPE_ID;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return ViewModelUpdateMessages.VisibleUpdateScope_name;
|
||||
}
|
||||
}
|
|
@ -25,10 +25,8 @@ import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
|||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.AllUpdateScope;
|
||||
import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.ICachingVMProviderExtension;
|
||||
import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.IVMUpdateScope;
|
||||
import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.VisibleUpdateScope;
|
||||
import org.eclipse.cdt.dsf.internal.DsfPlugin;
|
||||
import org.eclipse.cdt.dsf.internal.LoggingUtils;
|
||||
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
|
||||
import org.eclipse.cdt.dsf.ui.concurrent.ViewerCountingRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor;
|
||||
|
@ -49,15 +47,14 @@ import org.eclipse.core.runtime.Platform;
|
|||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
import org.eclipse.jface.viewers.TreeViewer;
|
||||
import org.eclipse.swt.widgets.Tree;
|
||||
import org.eclipse.swt.widgets.TreeItem;
|
||||
|
||||
/**
|
||||
* Base implementation of a caching view model provider.
|
||||
|
@ -65,7 +62,7 @@ import org.eclipse.swt.widgets.TreeItem;
|
|||
* @since 1.0
|
||||
*/
|
||||
public class AbstractCachingVMProvider extends AbstractVMProvider
|
||||
implements ICachingVMProvider, IElementPropertiesProvider, ICachingVMProviderExtension, ICachingVMProviderExtension2
|
||||
implements ICachingVMProvider, IElementPropertiesProvider, ICachingVMProviderExtension2
|
||||
{
|
||||
/**
|
||||
* @since 2.0
|
||||
|
@ -361,7 +358,6 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
protected static String SELECTED_UPDATE_SCOPE = "org.eclipse.cdt.dsf.ui.viewmodel.update.selectedUpdateScope"; //$NON-NLS-1$
|
||||
|
||||
private IVMUpdatePolicy[] fAvailableUpdatePolicies;
|
||||
private IVMUpdateScope[] fAvailableUpdateScopes;
|
||||
|
||||
public Map<Object, RootElementMarkerKey> fRootMarkers = new HashMap<Object, RootElementMarkerKey>();
|
||||
|
||||
|
@ -395,22 +391,12 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
fCacheListHead.fPrevious = fCacheListHead;
|
||||
|
||||
fAvailableUpdatePolicies = createUpdateModes();
|
||||
|
||||
fAvailableUpdateScopes = createUpdateScopes();
|
||||
setActiveUpdateScope(new VisibleUpdateScope());
|
||||
}
|
||||
|
||||
protected IVMUpdatePolicy[] createUpdateModes() {
|
||||
return new IVMUpdatePolicy[] { new AutomaticUpdatePolicy() };
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.1
|
||||
*/
|
||||
protected IVMUpdateScope[] createUpdateScopes() {
|
||||
return new IVMUpdateScope[] { new VisibleUpdateScope(), new AllUpdateScope() };
|
||||
}
|
||||
|
||||
|
||||
public IVMUpdatePolicy[] getAvailableUpdatePolicies() {
|
||||
return fAvailableUpdatePolicies;
|
||||
}
|
||||
|
@ -807,78 +793,106 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
flushMarkerEntry.insert(fCacheListHead);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener used to detect when the viewer is finished updating itself
|
||||
* after a model event. The
|
||||
*/
|
||||
// Warnings for use of ITreeModelViewer. ITreeModelViewer is an internal
|
||||
// interface in platform, but it is more generic than the public TreeModelViewer.
|
||||
// Using ITreeModelViewer will allow us to write unit tests using the
|
||||
// VirtualTreeModelViewer.
|
||||
@SuppressWarnings("restriction")
|
||||
private class ViewUpdateFinishedListener implements IViewerUpdateListener, IModelChangedListener {
|
||||
private final org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer fViewer;
|
||||
private boolean fViewerChangeStarted = false;
|
||||
private RequestMonitor fRm;
|
||||
|
||||
ViewUpdateFinishedListener(org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer viewer) {
|
||||
fViewer = viewer;
|
||||
}
|
||||
|
||||
private void start(RequestMonitor rm) {
|
||||
synchronized(this) {
|
||||
fViewer.addModelChangedListener(this);
|
||||
fViewer.addViewerUpdateListener(this);
|
||||
fRm = rm;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void viewerUpdatesComplete() {
|
||||
done();
|
||||
}
|
||||
|
||||
public void modelChanged(IModelDelta delta, IModelProxy proxy) {
|
||||
synchronized (this) {
|
||||
if (!fViewerChangeStarted) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void viewerUpdatesBegin() {
|
||||
synchronized(this) {
|
||||
fViewerChangeStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void done() {
|
||||
if (fRm != null) {
|
||||
fRm.done();
|
||||
fViewer.removeViewerUpdateListener(this);
|
||||
fViewer.removeModelChangedListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateStarted(IViewerUpdate update) {}
|
||||
public void updateComplete(IViewerUpdate update) {}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleEvent(final IVMModelProxy proxyStrategy, final Object event, final RequestMonitor rm) {
|
||||
IElementUpdateTester elementTester = getActiveUpdatePolicy().getElementUpdateTester(event);
|
||||
|
||||
flush(new FlushMarkerKey(proxyStrategy.getRootElement(), elementTester));
|
||||
|
||||
CountingRequestMonitor multiRm = new CountingRequestMonitor(getExecutor(), rm);
|
||||
super.handleEvent(proxyStrategy, event, multiRm);
|
||||
int rmCount = 1;
|
||||
|
||||
if(fDelayEventHandleForViewUpdate) {
|
||||
if(this.getActiveUpdateScope().getID().equals(AllUpdateScope.ALL_UPDATE_SCOPE_ID)) {
|
||||
new MultiLevelUpdateHandler(getExecutor(), proxyStrategy, getPresentationContext(), this, multiRm).
|
||||
startUpdate();
|
||||
rmCount++;
|
||||
} else if (!proxyStrategy.isDisposed()) {
|
||||
// block updating only the viewport
|
||||
TreeViewer viewer = (TreeViewer) proxyStrategy.getViewer();
|
||||
Tree tree = viewer.getTree();
|
||||
int count = tree.getSize().y / tree.getItemHeight();
|
||||
|
||||
TreeItem topItem = tree.getTopItem();
|
||||
int index = computeTreeIndex(topItem);
|
||||
|
||||
MultiLevelUpdateHandler handler = new MultiLevelUpdateHandler(
|
||||
getExecutor(), proxyStrategy, getPresentationContext(), this, multiRm);
|
||||
handler.setRange(index, index + count);
|
||||
handler.startUpdate();
|
||||
rmCount++;
|
||||
}
|
||||
if (!proxyStrategy.isDisposed()) {
|
||||
if (DEBUG_DELTA && (DEBUG_PRESENTATION_ID == null || getPresentationContext().getId().equals(DEBUG_PRESENTATION_ID))) {
|
||||
trace(event, null, proxyStrategy, EventHandlerAction.processing);
|
||||
}
|
||||
proxyStrategy.createDelta(
|
||||
event,
|
||||
new DataRequestMonitor<IModelDelta>(getExecutor(), rm) {
|
||||
@Override
|
||||
public void handleSuccess() {
|
||||
if (DEBUG_DELTA && (DEBUG_PRESENTATION_ID == null || getPresentationContext().getId().equals(DEBUG_PRESENTATION_ID))) {
|
||||
trace(event, null, proxyStrategy, EventHandlerAction.firedDeltaFor);
|
||||
}
|
||||
|
||||
// If we need to wait for the view to finish updating, then before posting the delta to the
|
||||
// viewer install a listener, which will in turn call rm.done().
|
||||
if (fDelayEventHandleForViewUpdate) {
|
||||
@SuppressWarnings("restriction")
|
||||
org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer viewer =
|
||||
(org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer) proxyStrategy.getViewer();
|
||||
new ViewUpdateFinishedListener(viewer).start(rm);
|
||||
}
|
||||
|
||||
proxyStrategy.fireModelChanged(getData());
|
||||
|
||||
if (!fDelayEventHandleForViewUpdate) {
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
@Override public String toString() {
|
||||
return "Result of a delta for event: '" + event.toString() + "' in VMP: '" + AbstractCachingVMProvider.this + "'" + "\n" + getData().toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if(this.getActiveUpdateScope().getID().equals(AllUpdateScope.ALL_UPDATE_SCOPE_ID)) {
|
||||
MultiLevelUpdateHandler handler = new MultiLevelUpdateHandler(
|
||||
getExecutor(), proxyStrategy, getPresentationContext(), this, multiRm);
|
||||
handler.startUpdate();
|
||||
rmCount++;
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
multiRm.setDoneCount(rmCount);
|
||||
}
|
||||
|
||||
private static int computeTreeIndex(TreeItem child) {
|
||||
if (child != null) {
|
||||
if(child.getParentItem() != null) {
|
||||
int previous = 0;
|
||||
int index = child.getParentItem().indexOf(child);
|
||||
while (--index >= 0) {
|
||||
previous += computeTreeExtent(child.getParentItem().getItem(index));
|
||||
}
|
||||
return computeTreeIndex(child.getParentItem()) + previous;
|
||||
} else {
|
||||
int previous = 0;
|
||||
int index = child.getParent().indexOf(child);
|
||||
while (--index >= 0) {
|
||||
previous += computeTreeExtent(child.getParent().getItem(index));
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int computeTreeExtent(TreeItem item) {
|
||||
int extent = 1;
|
||||
if (item.getExpanded()) {
|
||||
for (TreeItem i : item.getItems()) {
|
||||
extent += computeTreeExtent(i);
|
||||
}
|
||||
}
|
||||
return extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override default implementation to avoid automatically removing disposed proxies from
|
||||
* list of active proxies. The caching provider only removes a proxy after its root element
|
||||
|
@ -1297,43 +1311,6 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @noreference This method is an implementation of a provisional interface and
|
||||
* not intended to be referenced by clients.
|
||||
* @since 1.1
|
||||
*/
|
||||
public IVMUpdateScope[] getAvailableUpdateScopes() {
|
||||
return fAvailableUpdateScopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @noreference This method is an implementation of a provisional interface and
|
||||
* not intended to be referenced by clients.
|
||||
* @since 1.1
|
||||
*/
|
||||
public IVMUpdateScope getActiveUpdateScope() {
|
||||
String updateScopeId = (String)getPresentationContext().getProperty(SELECTED_UPDATE_SCOPE);
|
||||
if (updateScopeId != null) {
|
||||
for (IVMUpdateScope updateScope : getAvailableUpdateScopes()) {
|
||||
if (updateScope.getID().equals(updateScopeId)) {
|
||||
return updateScope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default to the first one.
|
||||
return getAvailableUpdateScopes()[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @noreference This method is an implementation of a provisional interface and
|
||||
* not intended to be referenced by clients.
|
||||
* @since 1.1
|
||||
*/
|
||||
public void setActiveUpdateScope(IVMUpdateScope updateScope) {
|
||||
getPresentationContext().setProperty(SELECTED_UPDATE_SCOPE, updateScope.getID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldWaitHandleEventToComplete() {
|
||||
return fDelayEventHandleForViewUpdate;
|
||||
|
@ -1346,4 +1323,52 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
fDelayEventHandleForViewUpdate = on;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for tracing event handling
|
||||
* <p>
|
||||
* Note: this enum is duplicated from AbstractVMProvider.
|
||||
*/
|
||||
private enum EventHandlerAction {
|
||||
received,
|
||||
queued,
|
||||
processing,
|
||||
firedDeltaFor,
|
||||
skipped,
|
||||
canceled
|
||||
}
|
||||
|
||||
/**
|
||||
* Trace that we've reached a particular phase of the handling of an event
|
||||
* for a particular proxy.
|
||||
* <p>
|
||||
* Note: this method is duplicated from AbstractVMProvider.
|
||||
*
|
||||
* @param event
|
||||
* the event being handled
|
||||
* @param skippedOrCanceledEvent
|
||||
* for a 'skip' or 'cancel' action, this is the event that is
|
||||
* being dismissed. Otherwise null
|
||||
* @param proxy
|
||||
* the target proxy; n/a (null) for a 'received' action.
|
||||
* @param action
|
||||
* what phased of the event handling has beeb reached
|
||||
*/
|
||||
private void trace(Object event, Object skippedOrCanceledEvent, IVMModelProxy proxy, EventHandlerAction action) {
|
||||
assert DEBUG_DELTA;
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append(DsfPlugin.getDebugTime());
|
||||
str.append(' ');
|
||||
if (action == EventHandlerAction.skipped || action == EventHandlerAction.canceled) {
|
||||
str.append(LoggingUtils.toString(this) + " " + action.toString() + " event " + LoggingUtils.toString(skippedOrCanceledEvent) + " because of event " + LoggingUtils.toString(event)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
}
|
||||
else {
|
||||
str.append(LoggingUtils.toString(this) + " " + action.toString() + " event " + LoggingUtils.toString(event)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
if (action != EventHandlerAction.received) {
|
||||
str.append(" for proxy " + LoggingUtils.toString(proxy) + ", whose root is " + LoggingUtils.toString(proxy.getRootElement())); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
DsfUIPlugin.debug(str.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,239 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008, 2009 Wind River Systems, Inc. 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:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.ui.viewmodel.update;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.IVMModelProxy;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.VMChildrenUpdate;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.VMHasChildrenUpdate;
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.jface.resource.ImageDescriptor;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
import org.eclipse.jface.viewers.TreeViewer;
|
||||
import org.eclipse.jface.viewers.Viewer;
|
||||
import org.eclipse.swt.graphics.FontData;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
|
||||
/**
|
||||
* @since 1.1
|
||||
*/
|
||||
class MultiLevelUpdateHandler extends DataRequestMonitor<List<Object>> {
|
||||
|
||||
private static final boolean DEBUG = Boolean.parseBoolean(Platform.getDebugOption("org.eclipse.cdt.dsf.ui/debug/vm/atomicUpdate")); //$NON-NLS-1$ //;
|
||||
|
||||
private static final class UpdateLevel {
|
||||
private final List<Object> fChildren;
|
||||
private final TreePath fPath;
|
||||
private int fChildIndex;
|
||||
private UpdateLevel(TreePath path, List<Object> children) {
|
||||
fPath = path;
|
||||
fChildren = children;
|
||||
fChildIndex = 0;
|
||||
assert !isDone();
|
||||
}
|
||||
private boolean isDone() {
|
||||
return fChildIndex == fChildren.size();
|
||||
}
|
||||
private Object nextChild() {
|
||||
if (isDone()) {
|
||||
return null;
|
||||
}
|
||||
return fChildren.get(fChildIndex++);
|
||||
}
|
||||
}
|
||||
private final class DummyLabelUpdate implements ILabelUpdate {
|
||||
private final RequestMonitor fMonitor;
|
||||
private final Object fData;
|
||||
private final TreePath fPath;
|
||||
|
||||
private DummyLabelUpdate(Object data, TreePath path, RequestMonitor rm) {
|
||||
fMonitor= rm;
|
||||
fData= data;
|
||||
fPath= path;
|
||||
}
|
||||
public Object getElement() {
|
||||
return fData;
|
||||
}
|
||||
public TreePath getElementPath() {
|
||||
return fPath.createChildPath(fData);
|
||||
}
|
||||
public IPresentationContext getPresentationContext() {
|
||||
return fPresentationContext;
|
||||
}
|
||||
public Object getViewerInput() {
|
||||
return fViewerInput;
|
||||
}
|
||||
public void cancel() { }
|
||||
public IStatus getStatus() {
|
||||
return null;
|
||||
}
|
||||
public boolean isCanceled() {
|
||||
return false;
|
||||
}
|
||||
public void setStatus(IStatus status) { }
|
||||
public String[] getColumnIds() {
|
||||
return fColumns;
|
||||
}
|
||||
public void setBackground(RGB arg0, int arg1) { }
|
||||
public void setFontData(FontData arg0, int arg1) { }
|
||||
public void setForeground(RGB arg0, int arg1) { }
|
||||
public void setImageDescriptor(ImageDescriptor arg0, int arg1) { }
|
||||
public void setLabel(String arg0, int arg1) {
|
||||
}
|
||||
public void done() {
|
||||
fMonitor.done();
|
||||
}
|
||||
}
|
||||
|
||||
private final Executor fExecutor;
|
||||
private final IElementContentProvider fContentProvider;
|
||||
private final IPresentationContext fPresentationContext;
|
||||
private final String[] fColumns;
|
||||
private final Viewer fViewer;
|
||||
private final Object fViewerInput;
|
||||
private final Stack<UpdateLevel> fStack = new Stack<UpdateLevel>();
|
||||
private final CountingRequestMonitor fRequestMonitor;
|
||||
|
||||
private int fIndex = 0;
|
||||
private TreePath fCurrentPath;
|
||||
private int fLowIndex = 0;
|
||||
private int fHighIndex = Integer.MAX_VALUE - 1;
|
||||
private int fPendingUpdates;
|
||||
private boolean fIsDone;
|
||||
|
||||
public MultiLevelUpdateHandler(Executor executor,
|
||||
IVMModelProxy modelProxy,
|
||||
IPresentationContext presentationContext,
|
||||
IElementContentProvider contentProvider,
|
||||
RequestMonitor parentRequestMonitor) {
|
||||
super(executor, null);
|
||||
fExecutor = executor;
|
||||
fViewer = modelProxy.getViewer();
|
||||
fViewerInput = modelProxy.getViewerInput();
|
||||
fCurrentPath = modelProxy.getRootPath();
|
||||
fPresentationContext = presentationContext;
|
||||
fColumns = presentationContext.getColumns();
|
||||
fContentProvider = contentProvider;
|
||||
|
||||
fRequestMonitor = new CountingRequestMonitor(fExecutor, parentRequestMonitor);
|
||||
}
|
||||
void startUpdate() {
|
||||
if (DEBUG) System.out.println("[MultiLevelUpdateHandler] startUpdate " + fLowIndex + '-' + fHighIndex); //$NON-NLS-1$
|
||||
fContentProvider.update(new IChildrenUpdate[] {
|
||||
new VMChildrenUpdate(fCurrentPath, fViewerInput, fPresentationContext, -1, -1, this)
|
||||
});
|
||||
}
|
||||
void setRange(int low, int high) {
|
||||
fLowIndex = low;
|
||||
fHighIndex = high;
|
||||
}
|
||||
@Override
|
||||
public synchronized void done() {
|
||||
assert !fIsDone;
|
||||
if (fIsDone) {
|
||||
// ignore gracefully
|
||||
return;
|
||||
}
|
||||
try {
|
||||
fExecutor.execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
final List<Object> data= getData();
|
||||
if (data != null && !data.isEmpty()) {
|
||||
if (DEBUG) System.out.println("[MultiLevelUpdateHandler] gotChildUpdate " + data.size()); //$NON-NLS-1$
|
||||
fStack.push(new UpdateLevel(fCurrentPath, data));
|
||||
}
|
||||
processNext();
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Completed: " + MultiLevelUpdateHandler.this.toString(); //$NON-NLS-1$
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException e) {
|
||||
handleRejectedExecutionException();
|
||||
}
|
||||
}
|
||||
protected void processNext() {
|
||||
while (true) {
|
||||
if (fIndex > fHighIndex) {
|
||||
fStack.clear();
|
||||
}
|
||||
if (fStack.isEmpty()) {
|
||||
fIsDone = true;
|
||||
fRequestMonitor.setDoneCount(fPendingUpdates);
|
||||
super.done();
|
||||
return;
|
||||
}
|
||||
UpdateLevel current = fStack.peek();
|
||||
assert !current.isDone();
|
||||
|
||||
TreePath path = current.fPath;
|
||||
Object data = current.nextChild();
|
||||
if (current.isDone()) {
|
||||
fStack.pop();
|
||||
}
|
||||
if (data == null) {
|
||||
// consider null children - http://bugs.eclipse.org/250309
|
||||
++fIndex;
|
||||
continue;
|
||||
}
|
||||
path = path.createChildPath(data);
|
||||
|
||||
if (fIndex >= fLowIndex && fIndex <= fHighIndex) {
|
||||
if(data instanceof IAdaptable) {
|
||||
IElementLabelProvider labelProvider = (IElementLabelProvider) ((IAdaptable)data).getAdapter(IElementLabelProvider.class);
|
||||
if (labelProvider != null) {
|
||||
++fPendingUpdates;
|
||||
if (DEBUG) System.out.println("[MultiLevelUpdateHandler] labelUpdate " + data); //$NON-NLS-1$
|
||||
labelProvider.update(new ILabelUpdate[] {
|
||||
new DummyLabelUpdate(data, path, fRequestMonitor)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
fIndex++;
|
||||
if (fViewer instanceof TreeViewer) {
|
||||
TreeViewer treeViewer = (TreeViewer) fViewer;
|
||||
if (treeViewer.getExpandedState(data)) {
|
||||
fCurrentPath = path;
|
||||
if (DEBUG) System.out.println("[MultiLevelUpdateHandler] childrenUpdate " + data); //$NON-NLS-1$
|
||||
fContentProvider.update(new IChildrenUpdate[] {
|
||||
new VMChildrenUpdate(path, fViewerInput, fPresentationContext, -1, -1, this)
|
||||
});
|
||||
return;
|
||||
} else if (fIndex >= fLowIndex) {
|
||||
// update also the hasChildren flag
|
||||
++fPendingUpdates;
|
||||
if (DEBUG) System.out.println("[MultiLevelUpdateHandler] hasChildUpdate " + data); //$NON-NLS-1$
|
||||
fContentProvider.update(new IHasChildrenUpdate[] {
|
||||
new VMHasChildrenUpdate(path, fViewerInput, fPresentationContext, new DataRequestMonitor<Boolean>(fExecutor, fRequestMonitor))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue