1
0
Fork 0
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:
Pawel Piech 2010-10-08 18:10:14 +00:00
parent 0fab073833
commit 7c8d11496e
9 changed files with 144 additions and 679 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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