diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java index 6b7532d33cc..ec2227c80cb 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java @@ -57,7 +57,7 @@ public class GdbViewModelAdapter extends AbstractDebugVMAdapter } else if (IDebugUIConstants.ID_MODULE_VIEW.equals(context.getId()) ) { return new ModulesVMProvider(this, context, getSession()); } else if (IDebugUIConstants.ID_BREAKPOINT_VIEW.equals(context.getId()) ) { - return new GdbBreakpointVMProvider(this, context); + return new GdbBreakpointVMProvider(this, context, getSession()); } return null; } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/breakpoints/GdbBreakpointVMProvider.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/breakpoints/GdbBreakpointVMProvider.java index 76d76cac92e..5d9601a9cca 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/breakpoints/GdbBreakpointVMProvider.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/breakpoints/GdbBreakpointVMProvider.java @@ -12,29 +12,59 @@ package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.breakpoints; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.debug.core.CDebugCorePlugin; import org.eclipse.cdt.debug.core.model.ICBreakpoint; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.DsfRunnable; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.debug.service.IBreakpoints; +import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; import org.eclipse.cdt.dsf.debug.ui.viewmodel.breakpoints.BreakpointVMProvider; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.breakpoints.RawBreakpointVMNode; +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter; +import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.internal.ui.breakpoints.provisional.IBreakpointUIConstants; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; /** * @since 3.0 */ public class GdbBreakpointVMProvider extends BreakpointVMProvider { - public GdbBreakpointVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext) { + final private DsfSession fSession; + + final private DsfServicesTracker fServicesTracker; + + public GdbBreakpointVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session) { super(adapter, presentationContext); + fSession = session; + fServicesTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), fSession.getId()); + } + + @Override + public void dispose() { + fServicesTracker.dispose(); + super.dispose(); } @Override protected void calcFileteredBreakpoints(DataRequestMonitor rm) { - if (getPresentationContext().getProperty(IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION) != null) { + if (Boolean.TRUE.equals(getPresentationContext().getProperty(IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION))) { IBreakpoint[] allBreakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(); List filteredBPs = new ArrayList(allBreakpoints.length); for (IBreakpoint bp : allBreakpoints) { @@ -48,4 +78,71 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider { super.calcFileteredBreakpoints(rm); } } + + @Override + protected IVMNode createBreakpointVMNode() { + return new RawBreakpointVMNode(this); + } + + @Override + public void getBreakpointsForDebugContext(ISelection debugContext, final DataRequestMonitor rm) { + IExecutionDMContext _execCtx = null; + if (debugContext instanceof IStructuredSelection) { + Object element = ((IStructuredSelection)debugContext).getFirstElement(); + if (element instanceof IDMVMContext) { + _execCtx = DMContexts.getAncestorOfType( ((IDMVMContext)element).getDMContext(), IExecutionDMContext.class); + } + } + + if (_execCtx == null || !fSession.getId().equals(_execCtx.getSessionId())) { + rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "Debug context doesn't contain a thread", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + final IExecutionDMContext execCtx = _execCtx; + + try { + fSession.getExecutor().execute(new DsfRunnable() { + public void run() { + IBreakpointsExtension bpService = fServicesTracker.getService(IBreakpointsExtension.class); + if (bpService == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Breakpoints service not available", null)); //$NON-NLS-1$ + rm.done(); + return; + } + bpService.getExecutionContextBreakpoints( + execCtx, + new DataRequestMonitor(fSession.getExecutor(), rm) { + @Override + protected void handleSuccess() { + MIBreakpointsManager bpManager = fServicesTracker.getService(MIBreakpointsManager.class); + if (bpManager == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Breakpoints service not available", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + IBreakpoint bp = null; + + + if (getData().length > 0) { + bp = bpManager.findPlatformBreakpoint(getData()[0]); + } + + if (bp != null) { + rm.setData(new IBreakpoint[] { bp }); + } else { + rm.setData(new IBreakpoint[0]); + } + rm.done(); + } + }); + } + }); + } catch (RejectedExecutionException e) { + rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Request for monitor: '" + toString() + "' resulted in a rejected execution exception.", e)); //$NON-NLS-1$ //$NON-NLS-2$); + rm.done(); + } + } } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/AbstractBreakpointVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/AbstractBreakpointVMNode.java new file mode 100644 index 00000000000..12820121036 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/AbstractBreakpointVMNode.java @@ -0,0 +1,299 @@ +/******************************************************************************* + * Copyright (c) 2008 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.ui.viewmodel.breakpoints; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; +import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMNode; +import org.eclipse.cdt.dsf.ui.viewmodel.ModelProxyInstalledEvent; +import org.eclipse.cdt.dsf.ui.viewmodel.VMChildrenUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.model.IBreakpoint; +import org.eclipse.debug.internal.ui.breakpoints.provisional.IBreakpointUIConstants; +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.IModelDelta; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.contexts.DebugContextEvent; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchWindow; + +/** + * Base class for breakpoint VM Nodes. Concrete implementations must + * implement the breakpoint object to be populated into the view. + * Also this node only implements the content provider so sub-classes + * must also implement a label provider, element editor, etc. + * + * @since 2.1 + */ +public abstract class AbstractBreakpointVMNode extends AbstractVMNode { + + public AbstractBreakpointVMNode(BreakpointVMProvider provider) { + super(provider); + } + + /** + * Class that creates the element object for the corresponding breakpoints. + * This element object will be populated in the breakpoitns view to represent + * the given breakpoint. + */ + abstract protected Object createBreakpiontElement(IBreakpoint bp); + + public void update(final IHasChildrenUpdate[] updates) { + for (final IHasChildrenUpdate update : updates) { + if (!checkUpdate(update)) continue; + ((BreakpointVMProvider)getVMProvider()).getNestingCategoryBreakpoints( + update.getElementPath(), + new ViewerDataRequestMonitor(getExecutor(), update) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + update.setHasChilren(getData().length != 0); + } else { + update.setHasChilren(false); + } + update.done(); + } + }); + } + } + + public void update(final IChildrenCountUpdate[] updates) { + for (final IChildrenCountUpdate update : updates) { + if (!checkUpdate(update)) continue; + ((BreakpointVMProvider)getVMProvider()).getNestingCategoryBreakpoints( + update.getElementPath(), + new ViewerDataRequestMonitor(getExecutor(), update) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + update.setChildCount(getData().length); + } else { + update.setChildCount(0); + } + update.done(); + } + }); + } + } + + public void update(IChildrenUpdate[] updates) { + for (final IChildrenUpdate update : updates) { + if (!checkUpdate(update)) continue; + ((BreakpointVMProvider)getVMProvider()).getNestingCategoryBreakpoints( + update.getElementPath(), + new ViewerDataRequestMonitor(getExecutor(), update) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + @SuppressWarnings("unchecked") + Comparator comparator = + (Comparator)getVMProvider().getPresentationContext().getProperty( + IBreakpointUIConstants.PROP_BREAKPOINTS_ELEMENT_COMPARATOR); + if (comparator != null) { + Arrays.sort(getData(), comparator); + } + fillUpdateWithBreakpointElements(update, getData()); + } + update.done(); + } + }); + } + } + + private void fillUpdateWithBreakpointElements(IChildrenUpdate update, IBreakpoint[] bps) { + int updateIdx = update.getOffset() != -1 ? update.getOffset() : 0; + int endIdx = updateIdx + (update.getLength() != -1 ? update.getLength() : bps.length); + while (updateIdx < endIdx && updateIdx < bps.length) { + update.setChild(createBreakpiontElement(bps[updateIdx]), updateIdx); + updateIdx++; + } + } + + public int getDeltaFlags(Object event) { + if (event instanceof BreakpointsChangedEvent) { + BreakpointsChangedEvent bpChangedEvent = ((BreakpointsChangedEvent)event); + if (BreakpointsChangedEvent.Type.ADDED.equals(bpChangedEvent.getType())) { + return IModelDelta.CONTENT | IModelDelta.SELECT | IModelDelta.EXPAND; + } + return IModelDelta.CONTENT; + } + else if (BreakpointVMProvider.isPresentationContextEvent(event)) { + PropertyChangeEvent propertyEvent = (PropertyChangeEvent)event; + if (IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION.equals(propertyEvent.getProperty()) || + IBreakpointUIConstants.PROP_BREAKPOINTS_ELEMENT_COMPARATOR.equals(propertyEvent.getProperty())) + { + return IModelDelta.CONTENT; + } else if (IBreakpointUIConstants.PROP_BREAKPOINTS_ORGANIZERS.equals(propertyEvent.getProperty())) { + return IModelDelta.EXPAND | IModelDelta.CONTENT; + } else if (IBreakpointUIConstants.PROP_BREAKPOINTS_TRACK_SELECTION.equals(propertyEvent.getProperty()) && + Boolean.TRUE.equals(propertyEvent.getNewValue()) ) + { + return IModelDelta.EXPAND | IModelDelta.SELECT; + } + } + else if (event instanceof DebugContextEvent && (((DebugContextEvent)event).getFlags() | DebugContextEvent.ACTIVATED) != 0) { + int flags = IModelDelta.NO_CHANGE; + if ( Boolean.TRUE.equals(getVMProvider().getPresentationContext().getProperty(IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION)) ) { + flags |= IModelDelta.CONTENT; + } + if (Boolean.TRUE.equals(getVMProvider().getPresentationContext().getProperty(IBreakpointUIConstants.PROP_BREAKPOINTS_TRACK_SELECTION)) ) { + flags |= IModelDelta.EXPAND | IModelDelta.SELECT; + } + return flags; + } else if (event instanceof ModelProxyInstalledEvent) { + // Upon model proxy installed, check whether we need to select a + // breakpoint in linking with Debug view + if (Boolean.TRUE.equals(getVMProvider().getPresentationContext().getProperty(IBreakpointUIConstants.PROP_BREAKPOINTS_TRACK_SELECTION)) ) { + return IModelDelta.EXPAND | IModelDelta.SELECT; + } + } + return 0; + } + + public void buildDelta(Object event, VMDelta parent, int nodeOffset, RequestMonitor rm) { + if (event instanceof BreakpointsChangedEvent) { + BreakpointsChangedEvent bpChangedEvent = ((BreakpointsChangedEvent)event); + if (BreakpointsChangedEvent.Type.ADDED.equals(bpChangedEvent.getType())) { + buildBreakpointAddedDelta(bpChangedEvent, parent, nodeOffset, rm); + // Do not call rm.done() in this method! + return; + } else { + parent.setFlags(parent.getFlags() | IModelDelta.CONTENT); + } + } + else if (BreakpointVMProvider.isPresentationContextEvent(event)) { + PropertyChangeEvent propertyEvent = (PropertyChangeEvent)event; + if (IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION.equals(propertyEvent.getProperty()) || + IBreakpointUIConstants.PROP_BREAKPOINTS_ELEMENT_COMPARATOR.equals(propertyEvent.getProperty())) + { + parent.setFlags(parent.getFlags() | IModelDelta.CONTENT); + } else if (IBreakpointUIConstants.PROP_BREAKPOINTS_ORGANIZERS.equals(propertyEvent.getProperty())) { + parent.setFlags(parent.getFlags() | IModelDelta.EXPAND | IModelDelta.CONTENT); + } else if (IBreakpointUIConstants.PROP_BREAKPOINTS_TRACK_SELECTION.equals(propertyEvent.getProperty()) && + Boolean.TRUE.equals(propertyEvent.getNewValue()) ) + { + IWorkbenchWindow window = getVMProvider().getPresentationContext().getWindow(); + if (window != null) { + ISelection activeContext = DebugUITools.getDebugContextManager().getContextService(window).getActiveContext(); + buildTrackSelectionDelta(activeContext, parent, nodeOffset, rm); + // Do not call rm.done() in this method! + return; + } + } + } + else if (event instanceof DebugContextEvent && (((DebugContextEvent)event).getFlags() | DebugContextEvent.ACTIVATED) != 0) { + if ( Boolean.TRUE.equals(getVMProvider().getPresentationContext().getProperty(IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION)) ) { + parent.setFlags(parent.getFlags() | IModelDelta.CONTENT); + } + if (Boolean.TRUE.equals(getVMProvider().getPresentationContext().getProperty(IBreakpointUIConstants.PROP_BREAKPOINTS_TRACK_SELECTION)) ) { + buildTrackSelectionDelta(((DebugContextEvent)event).getContext(), parent, nodeOffset, rm); + // Do not call rm.done() in this method! + return; + } + } else if (event instanceof ModelProxyInstalledEvent) { + if (Boolean.TRUE.equals(getVMProvider().getPresentationContext().getProperty(IBreakpointUIConstants.PROP_BREAKPOINTS_TRACK_SELECTION)) ) { + IWorkbenchWindow window = getVMProvider().getPresentationContext().getWindow(); + if (window != null) { + ISelection activeContext = DebugUITools.getDebugContextManager().getContextService(window).getActiveContext(); + buildTrackSelectionDelta(activeContext, parent, nodeOffset, rm); + return; + } + } + } + + rm.done(); + } + + private void buildBreakpointAddedDelta(final BreakpointsChangedEvent event, final VMDelta parent, final int nodeOffset, final RequestMonitor rm) { + getVMProvider().updateNode(this, new VMChildrenUpdate( + parent, getVMProvider().getPresentationContext(), -1, -1, + new DataRequestMonitor>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + for (int i = 0; i < event.getBreakpoints().length; i++) { + IBreakpoint eventBp = event.getBreakpoints()[i]; + int bpIndex = findBreakpointIndex(eventBp, getData()); + if (bpIndex >= 0) { + // Select only the first breakpoint that was added + if (i == 0) { + parent.addNode(getData().get(bpIndex), bpIndex, IModelDelta.SELECT); + } + // For all other added breakpoints, expand the parent. + parent.setFlags(parent.getFlags() | IModelDelta.CONTENT | IModelDelta.EXPAND); + } + } + rm.done(); + } + })); + } + + protected void buildTrackSelectionDelta(ISelection debugContext, final VMDelta parent, final int nodeOffset, final RequestMonitor rm) { + assert getVMProvider() instanceof BreakpointVMProvider; + + ((BreakpointVMProvider)getVMProvider()).getBreakpointsForDebugContext( + debugContext, + new DataRequestMonitor(getExecutor(), rm) { + @Override + protected void handleSuccess() { + if (getData().length == 0) { + // No breakpoints to select, we're done. + rm.done(); + return; + } + final IBreakpoint[] bpsToSelect = getData(); + + getVMProvider().updateNode(AbstractBreakpointVMNode.this, new VMChildrenUpdate( + parent, getVMProvider().getPresentationContext(), -1, -1, + new DataRequestMonitor>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + for (int i = 0; i < bpsToSelect.length; i++) { + int bpIndex = findBreakpointIndex(bpsToSelect[i], getData()); + if (bpIndex >= 0) { + // Select only the first breakpoint that was added + if (i == 0) { + parent.addNode(getData().get(bpIndex), bpIndex, IModelDelta.SELECT); + } + // For all other added breakpoints, expand the parent. + parent.setFlags(parent.getFlags() | IModelDelta.EXPAND); + } + } + rm.done(); + } + })); + } + + @Override + protected void handleErrorOrWarning() { + rm.done(); + } + }); + } + + private int findBreakpointIndex(IBreakpoint bp, List bpElements) { + for (int j = 0; j < bpElements.size(); j++) { + IBreakpoint elementBp = (IBreakpoint)DebugPlugin.getAdapter(bpElements.get(j), IBreakpoint.class); + if (elementBp != null && elementBp.equals(bp)) { + return j; + } + } + return -1; + } +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMInput.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMInput.java index f00ea9dd920..b28ed211a2f 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMInput.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMInput.java @@ -11,11 +11,9 @@ package org.eclipse.cdt.dsf.debug.ui.viewmodel.breakpoints; import org.eclipse.cdt.dsf.datamodel.IDMContext; -import org.eclipse.cdt.dsf.ui.viewmodel.IVMAdapter; +import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode; -import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest; @@ -23,14 +21,19 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRe /** * @since 2.1 */ -public class BreakpointVMInput extends PlatformObject implements IElementMementoProvider { +public class BreakpointVMInput extends AbstractVMContext implements IElementMementoProvider, IDMVMContext { - private IVMNode fVMNode; + final private IDMContext fDMContext; - public BreakpointVMInput(IVMNode node, IDMContext activeDMContext) { - fVMNode = node; + public BreakpointVMInput(IVMNode node, IDMContext dmc) { + super(node); + fDMContext = dmc; } + public IDMContext getDMContext() { + return fDMContext; + } + public void encodeElements(IElementMementoRequest[] requests) { for (IElementMementoRequest request : requests) { request.getMemento().putString("ELEMENT_NAME", "BreakpointInputMemento"); //$NON-NLS-1$//$NON-NLS-2$ @@ -45,34 +48,13 @@ public class BreakpointVMInput extends PlatformObject implements IElementMemento } } - @Override - @SuppressWarnings({"rawtypes" }) - public Object getAdapter(Class adapter) { - // If the context implements the given adapter directly, it always takes - // precedence. - if (adapter.isInstance(this)) { - return this; - } - - IVMProvider vmProvider = fVMNode.getVMProvider(); - IVMAdapter vmAdapter = vmProvider.getVMAdapter(); - if (adapter.isInstance(vmAdapter)) { - return vmAdapter; - } else if (adapter.isInstance(vmProvider)) { - return vmProvider; - } else if (adapter.isInstance(fVMNode)) { - return fVMNode; - } - return Platform.getAdapterManager().getAdapter(this, adapter); - } - @Override public boolean equals(Object obj) { - return obj instanceof BreakpointVMInput; + return obj instanceof BreakpointVMInput && ((BreakpointVMInput)obj).getDMContext().equals(fDMContext); } @Override public int hashCode() { - return getClass().hashCode(); + return fDMContext.hashCode(); } } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMNode.java index 07f4ad95557..82b85c945a6 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMNode.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMNode.java @@ -11,123 +11,41 @@ package org.eclipse.cdt.dsf.debug.ui.viewmodel.breakpoints; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; -import org.eclipse.cdt.dsf.concurrent.RequestMonitor; -import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; -import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMNode; -import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider; -import org.eclipse.cdt.dsf.ui.viewmodel.VMChildrenUpdate; -import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.core.model.IBreakpoint; -import org.eclipse.debug.internal.ui.breakpoints.provisional.IBreakpointUIConstants; import org.eclipse.debug.internal.ui.viewers.model.provisional.ICheckUpdate; -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.IElementCompareRequest; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest; -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.IModelDelta; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.TreePath; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.RGB; import org.eclipse.ui.IMemento; /** - * + * Breakpiont VM Node which uses VM Contexts to populate breakpoint elements + * in the view. Any actions or other selection listeners which depend on the + * breakpoint object will not work with these elements unless they use the + * adapter mechanism to obtain the breakpoints. * * @since 2.1 */ -public class BreakpointVMNode extends AbstractVMNode implements IElementLabelProvider, IElementMementoProvider { +public class BreakpointVMNode extends AbstractBreakpointVMNode implements IElementLabelProvider, IElementMementoProvider { - public BreakpointVMNode(IVMProvider provider) { + public BreakpointVMNode(BreakpointVMProvider provider) { super(provider); } - public void update(final IHasChildrenUpdate[] updates) { - for (final IHasChildrenUpdate update : updates) { - if (!checkUpdate(update)) continue; - ((BreakpointVMProvider)getVMProvider()).getNestingCategoryBreakpoints( - update.getElementPath(), - new ViewerDataRequestMonitor(getExecutor(), update) { - @Override - protected void handleCompleted() { - if (isSuccess()) { - update.setHasChilren(getData().length != 0); - } else { - update.setHasChilren(false); - } - update.done(); - } - }); - } - } - - public void update(final IChildrenCountUpdate[] updates) { - for (final IChildrenCountUpdate update : updates) { - if (!checkUpdate(update)) continue; - ((BreakpointVMProvider)getVMProvider()).getNestingCategoryBreakpoints( - update.getElementPath(), - new ViewerDataRequestMonitor(getExecutor(), update) { - @Override - protected void handleCompleted() { - if (isSuccess()) { - update.setChildCount(getData().length); - } else { - update.setChildCount(0); - } - update.done(); - } - }); - } - } - - public void update(IChildrenUpdate[] updates) { - for (final IChildrenUpdate update : updates) { - if (!checkUpdate(update)) continue; - ((BreakpointVMProvider)getVMProvider()).getNestingCategoryBreakpoints( - update.getElementPath(), - new ViewerDataRequestMonitor(getExecutor(), update) { - @Override - protected void handleCompleted() { - if (isSuccess()) { - @SuppressWarnings("unchecked") - Comparator comparator = - (Comparator)getVMProvider().getPresentationContext().getProperty( - IBreakpointUIConstants.PROP_BREAKPOINTS_ELEMENT_COMPARATOR); - if (comparator != null) { - Arrays.sort(getData(), comparator); - } - fillUpdateWithBreakpointVMCs(update, getData()); - } - update.done(); - } - }); - } - } - - private void fillUpdateWithBreakpointVMCs(IChildrenUpdate update, IBreakpoint[] bps) { - int updateIdx = update.getOffset() != -1 ? update.getOffset() : 0; - int endIdx = updateIdx + (update.getLength() != -1 ? update.getLength() : bps.length); - while (updateIdx < endIdx && updateIdx < bps.length) { - update.setChild(createVMContext(bps[updateIdx]), updateIdx); - updateIdx++; - } - } - - protected BreakpointVMContext createVMContext(IBreakpoint bp) { + @Override + protected Object createBreakpiontElement(IBreakpoint bp) { return new BreakpointVMContext(this, bp); } @@ -252,71 +170,4 @@ public class BreakpointVMNode extends AbstractVMNode implements IElementLabelPro } } - public int getDeltaFlags(Object event) { - if (event instanceof BreakpointsChangedEvent) { - BreakpointsChangedEvent bpChangedEvent = ((BreakpointsChangedEvent)event); - if (BreakpointsChangedEvent.Type.ADDED.equals(bpChangedEvent.getType())) { - return IModelDelta.CONTENT | IModelDelta.SELECT | IModelDelta.EXPAND; - } - return IModelDelta.CONTENT; - } - else if (BreakpointVMProvider.isPresentationContextEvent(event)) { - PropertyChangeEvent propertyEvent = (PropertyChangeEvent)event; - if (IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION.equals(propertyEvent.getProperty()) || - IBreakpointUIConstants.PROP_BREAKPOINTS_ELEMENT_COMPARATOR.equals(propertyEvent.getProperty())) - { - return IModelDelta.CONTENT; - } else if (IBreakpointUIConstants.PROP_BREAKPOINTS_ORGANIZERS.equals(propertyEvent.getProperty())) { - return IModelDelta.EXPAND | IModelDelta.CONTENT; - } - } - return 0; - } - - public void buildDelta(Object event, VMDelta parent, int nodeOffset, RequestMonitor rm) { - if (event instanceof BreakpointsChangedEvent) { - BreakpointsChangedEvent bpChangedEvent = ((BreakpointsChangedEvent)event); - if (BreakpointsChangedEvent.Type.ADDED.equals(bpChangedEvent.getType())) { - buildBreakpointAddedDelta(bpChangedEvent, parent, nodeOffset, rm); - // Do not call rm.done() in this method! - return; - } else { - parent.setFlags(parent.getFlags() | IModelDelta.CONTENT); - } - } - else if (BreakpointVMProvider.isPresentationContextEvent(event)) { - PropertyChangeEvent propertyEvent = (PropertyChangeEvent)event; - if (IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION.equals(propertyEvent.getProperty()) || - IBreakpointUIConstants.PROP_BREAKPOINTS_ELEMENT_COMPARATOR.equals(propertyEvent.getProperty())) - { - parent.setFlags(parent.getFlags() | IModelDelta.CONTENT); - } else if (IBreakpointUIConstants.PROP_BREAKPOINTS_ORGANIZERS.equals(propertyEvent.getProperty())) { - parent.setFlags(parent.getFlags() | IModelDelta.EXPAND | IModelDelta.CONTENT); - } - } - - rm.done(); - } - - private void buildBreakpointAddedDelta(final BreakpointsChangedEvent event, final VMDelta parent, final int nodeOffset, final RequestMonitor rm) { - getVMProvider().updateNode(this, new VMChildrenUpdate( - parent, getVMProvider().getPresentationContext(), -1, -1, - new DataRequestMonitor>(getExecutor(), rm) { - @Override - protected void handleSuccess() { - for (int i = 0; i < event.getBreakpoints().length; i++) { - int bpIndex = getData().indexOf(event.getBreakpoints()[i]); - if (bpIndex >= 0) { - // Select only the first breakpoint that was added - if (i == 0) { - parent.addNode(getData().get(bpIndex), bpIndex, IModelDelta.SELECT); - } - // For all other added breakpoints, expand the parent. - parent.setFlags(parent.getFlags() | IModelDelta.CONTENT | IModelDelta.EXPAND); - } - } - rm.done(); - } - })); - } } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMProvider.java index 4621ffb37b9..8e1e248e3e0 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/BreakpointVMProvider.java @@ -17,17 +17,17 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.eclipse.cdt.dsf.concurrent.DataCache; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter; import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider; -import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode; import org.eclipse.cdt.dsf.ui.viewmodel.IVMModelProxy; import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; @@ -42,15 +42,20 @@ import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.internal.ui.breakpoints.provisional.IBreakpointOrganizer; import org.eclipse.debug.internal.ui.breakpoints.provisional.IBreakpointUIConstants; import org.eclipse.debug.internal.ui.breakpoints.provisional.OtherBreakpointCategory; +import org.eclipse.debug.internal.ui.elements.adapters.DefaultBreakpointsViewInput; import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputUpdate; +import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IBreakpointOrganizerDelegate; +import org.eclipse.debug.ui.contexts.DebugContextEvent; +import org.eclipse.debug.ui.contexts.IDebugContextListener; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; -import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.TreePath; +import org.eclipse.ui.IWorkbenchWindow; /** * The expression provider is used to populate the contents of the expressions @@ -88,6 +93,12 @@ public class BreakpointVMProvider extends AbstractVMProvider }; + private IDebugContextListener fDebugContextListener = new IDebugContextListener() { + public void debugContextChanged(final DebugContextEvent event) { + handleEventInExecThread(event); + } + }; + private class ContainerBreakpointsCache extends DataCache> { private BreakpointOrganizerVMNode fOrganizerVMNode; @@ -169,9 +180,21 @@ public class BreakpointVMProvider extends AbstractVMProvider public BreakpointVMProvider(AbstractVMAdapter adapter, IPresentationContext context) { super(adapter, context); + // Create the top level node which provides the anchor starting point. + // This node is referenced by the BreakpointVMInput element so it + // should not change when the view layout is updated. + setRootNode(new RootDMVMNode(this)); + // Configure the rest of the layout nodes. configureLayout(); + context.addPropertyChangeListener(fPresentationContextListener); DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(fBreakpointsListener); + IWorkbenchWindow window = context.getWindow(); + if (window != null) { + DebugUITools.getDebugContextManager().getContextService(window).addDebugContextListener( + fDebugContextListener); + } + } @Override @@ -188,15 +211,10 @@ public class BreakpointVMProvider extends AbstractVMProvider * sub classes to create an alternate configuration in this provider. */ protected void configureLayout() { - /* - * Create the top level node which provides the anchor starting point. - */ - IRootVMNode rootNode = new RootDMVMNode(this); - IBreakpointOrganizer[] organizers = (IBreakpointOrganizer[]) getPresentationContext().getProperty(IBreakpointUIConstants.PROP_BREAKPOINTS_ORGANIZERS); - IVMNode parentNode = rootNode; + IVMNode parentNode = getRootVMNode(); if (organizers != null) { for (IBreakpointOrganizer organizer : organizers) { IVMNode organizerNode = new BreakpointOrganizerVMNode(this, organizer); @@ -207,11 +225,6 @@ public class BreakpointVMProvider extends AbstractVMProvider IVMNode bpsNode = createBreakpointVMNode(); addChildNodes(parentNode, new IVMNode[] {bpsNode}); - - /* - * Let the work know which is the top level node. - */ - setRootNode(rootNode); } @@ -219,6 +232,11 @@ public class BreakpointVMProvider extends AbstractVMProvider public void dispose() { getPresentationContext().removePropertyChangeListener(fPresentationContextListener); DebugPlugin.getDefault().getBreakpointManager().removeBreakpointListener(fBreakpointsListener); + IWorkbenchWindow window = getPresentationContext().getWindow(); + if (window != null) { + DebugUITools.getDebugContextManager().getContextService(window).addDebugContextListener( + fDebugContextListener); + } super.dispose(); } @@ -234,15 +252,18 @@ public class BreakpointVMProvider extends AbstractVMProvider @Override public void update(IViewerInputUpdate update) { - IStructuredSelection filterSelection = (IStructuredSelection) - update.getPresentationContext().getProperty(IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION); IDMContext activeDMContext = null; - if (filterSelection != null) { - if (update.getElement() instanceof IDMVMContext) { - activeDMContext = ((IDMVMContext)update.getElement()).getDMContext(); - } + if (update.getElement() instanceof IDMVMContext) { + activeDMContext = ((IDMVMContext)update.getElement()).getDMContext(); + activeDMContext = DMContexts.getAncestorOfType(activeDMContext, IBreakpointsTargetDMContext.class); + } + if (activeDMContext != null) { + update.setInputElement(new BreakpointVMInput(getRootVMNode(), activeDMContext)); + } else { + // If no breakpoints target found in active context, delegate the breakpoint + // presentation to the default: breakpoint manager. + update.setInputElement(new DefaultBreakpointsViewInput(update.getPresentationContext())); } - update.setInputElement(new BreakpointVMInput(getRootVMNode(), activeDMContext)); update.done(); } @@ -306,6 +327,11 @@ public class BreakpointVMProvider extends AbstractVMProvider rm.done(); } + public void getBreakpointsForDebugContext(ISelection debugContext, DataRequestMonitor rm) { + rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$ + rm.done(); + } + public void handleEventInExecThread(final Object event) { getExecutor().execute(new DsfRunnable() { public void run() { @@ -320,7 +346,7 @@ public class BreakpointVMProvider extends AbstractVMProvider PropertyChangeEvent propertyEvent = (PropertyChangeEvent)event; if (IBreakpointUIConstants.PROP_BREAKPOINTS_ORGANIZERS.equals(propertyEvent.getProperty())) { - clearNodes(); + clearNodes(false); configureLayout(); } } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/DataCache.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/DataCache.java new file mode 100644 index 00000000000..9c1961c5a7c --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/DataCache.java @@ -0,0 +1,220 @@ +package org.eclipse.cdt.dsf.debug.ui.viewmodel.breakpoints; + +/******************************************************************************* + * Copyright (c) 2008 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 + *******************************************************************************/ + +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Executor; + +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.internal.DsfPlugin; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * A general purpose cache, which caches the result of a single request. + * Sub classes need to implement {@link #retrieve(DataRequestMonitor)} to fetch + * data from the data source. Clients are responsible for calling + * {@link #disable()} and {@link #reset()} to manage the state of the cache in + * response to events from the data source. + *

+ * This cache requires an executor to use. The executor is used to synchronize + * access to the cache state and data. + *

+ *

+ * This class is intended as a general utility, but it's not quite ready for + * API, so it's just private class for now. + *

+ * @since 2.1 + */ +@ConfinedToDsfExecutor("fExecutor") +abstract class DataCache { + + final private Executor fExecutor; + + private boolean fValid; + + protected DataRequestMonitor fRm; + private V fData; + private IStatus fStatus; + + private List> fWaitingList = new LinkedList>(); + + public DataCache(Executor executor) { + fExecutor = executor; + } + + + /** + * Sub-classes should override this method to retrieve the cache data + * from its source. + * + * @param rm Request monitor for completion of data retrieval. + */ + protected abstract void retrieve(DataRequestMonitor rm); + + /** + * Returns true if the cache is currently valid. I.e. + * whether the cache can return a value immediately without first + * retrieving it from the data source. + */ + public boolean isValid() { + return fValid; + } + + /** + * Returns true if the cache is currently waiting for data + * from the data source. + */ + public boolean isPending() { + return fRm != null; + } + + /** + * Returns the current data value held by this cache. Clients should first + * call isValid() to determine if the data is up to date. + */ + public V getData() { + return fData; + } + + /** + * Returns the status of the source request held by this cache. Clients + * should first call isValid() to determine if the data is up to date. + */ + public IStatus getStatus() { + return fStatus; + } + + /** + * Request data from the cache. The cache is valid, it will complete the + * request immediately, otherwise data will first be retrieved from the + * source. + * @param req + */ + public void request(final DataRequestMonitor rm) { + if (!fValid) { + boolean first = fWaitingList.isEmpty(); + fWaitingList.add(rm); + if(first) { + fRm = new DataRequestMonitor(fExecutor, null) { + @Override + protected void handleCompleted() { + if (!isCanceled()) { + fValid = true; + fRm = null; + set(getData(), getStatus()); + } + } + }; + retrieve(fRm); + } + } else { + rm.setData(fData); + rm.setStatus(fStatus); + rm.done(); + } + } + + + private void set(V data, IStatus status) { + fData = data; + fStatus = status; + List> waitingList = fWaitingList; + fWaitingList = new LinkedList>(); + + for (DataRequestMonitor rm : waitingList) { + rm.setData(data); + rm.setStatus(status); + rm.done(); + } + } + + /** + * Resets the cache with a data value null and an error + * status with code {@link IDsfStatusConstants#INVALID_STATE}. + * + * @see #reset(Object, IStatus) + */ + public void reset() { + reset(null, new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Cache reset", null)); //$NON-NLS-1$ + } + + /** + * Resets the cache with given data and status. Resetting the cache + * forces the cache to be invalid and cancels any current pending requests + * from data source. + *

+ * This method should be called when the data source has issued an event + * indicating that the source data has changed but data may still be + * retrieved. Clients may need to re-request data following cache reset. + *

+ * @param data The data that should be returned to any clients currently + * waiting for cache data. + * @status The status that should be returned to any clients currently + * waiting for cache data. + */ + public void reset(V data, IStatus status) { + fValid = false; + if (fRm != null) { + fRm.cancel(); + fRm = null; + } + set(data, status); + } + + /** + * Disables the cache from retrieving data from the source. If the cache + * is already valid the data and status is retained. If the cache is not + * valid, then data value null and an error status with code + * {@link IDsfStatusConstants#INVALID_STATE} are set. + * + * @see #disable(Object, IStatus) + */ + public void disable() { + //TODO: better. + + V data; + IStatus status; + if (fValid) { + data = getData(); + status = getStatus(); + } else { + data = null; + status = new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Cache disable", null); //$NON-NLS-1$ + } + disable(data, status); + } + + /** + * Resets the cache then disables it. When a cache is disabled it means + * that it is valid and requests to the data source will not be sent. + *

+ * This method should be called when the data source has issued an event + * indicating that the source data has changed and future requests for + * data will return the given data and status. Once the source data + * becomes available again, clients should call {@link #reset()}. + *

+ * @param data The data that should be returned to any clients waiting for + * cache data and for clients requesting data until the cache is reset again. + * @status The status that should be returned to any clients waiting for + * cache data and for clients requesting data until the cache is reset again. + * + * @see #reset(Object, IStatus) + */ + public void disable(V data, IStatus status) { + reset(data, status); + fValid = true; + } +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/RawBreakpointVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/RawBreakpointVMNode.java index a9a33e21c6b..c31f4c14895 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/RawBreakpointVMNode.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/breakpoints/RawBreakpointVMNode.java @@ -10,172 +10,24 @@ *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.viewmodel.breakpoints; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - -import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; -import org.eclipse.cdt.dsf.concurrent.RequestMonitor; -import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; -import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMNode; -import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider; -import org.eclipse.cdt.dsf.ui.viewmodel.VMChildrenUpdate; -import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.debug.core.model.IBreakpoint; -import org.eclipse.debug.internal.ui.breakpoints.provisional.IBreakpointUIConstants; -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.IModelDelta; -import org.eclipse.jface.util.PropertyChangeEvent; /** - * + * Breakpoint node which uses raw breakpiont objects (without a wrapper) as + * elements which are populated into the view. The breakpoint objects are + * responsible for supplying their own label and memento providers, as well + * as content provider for any children. * * @since 2.1 */ -public class RawBreakpointVMNode extends AbstractVMNode { +public class RawBreakpointVMNode extends AbstractBreakpointVMNode { - public RawBreakpointVMNode(IVMProvider provider) { + public RawBreakpointVMNode(BreakpointVMProvider provider) { super(provider); } - - public void update(final IHasChildrenUpdate[] updates) { - for (final IHasChildrenUpdate update : updates) { - if (!checkUpdate(update)) continue; - ((BreakpointVMProvider)getVMProvider()).getNestingCategoryBreakpoints( - update.getElementPath(), - new ViewerDataRequestMonitor(getExecutor(), update) { - @Override - protected void handleCompleted() { - if (isSuccess()) { - update.setHasChilren(getData().length != 0); - } else { - update.setHasChilren(false); - } - update.done(); - } - }); - } - } - public void update(final IChildrenCountUpdate[] updates) { - for (final IChildrenCountUpdate update : updates) { - if (!checkUpdate(update)) continue; - ((BreakpointVMProvider)getVMProvider()).getNestingCategoryBreakpoints( - update.getElementPath(), - new ViewerDataRequestMonitor(getExecutor(), update) { - @Override - protected void handleCompleted() { - if (isSuccess()) { - update.setChildCount(getData().length); - } else { - update.setChildCount(0); - } - update.done(); - } - }); - } - } - - public void update(IChildrenUpdate[] updates) { - for (final IChildrenUpdate update : updates) { - if (!checkUpdate(update)) continue; - ((BreakpointVMProvider)getVMProvider()).getNestingCategoryBreakpoints( - update.getElementPath(), - new ViewerDataRequestMonitor(getExecutor(), update) { - @Override - protected void handleCompleted() { - if (isSuccess()) { - @SuppressWarnings("unchecked") - Comparator comparator = - (Comparator)getVMProvider().getPresentationContext().getProperty( - IBreakpointUIConstants.PROP_BREAKPOINTS_ELEMENT_COMPARATOR); - if (comparator != null) { - Arrays.sort(getData(), comparator); - } - fillUpdateWithBreakpoints(update, getData()); - } - update.done(); - } - }); - } - } - - private void fillUpdateWithBreakpoints(IChildrenUpdate update, IBreakpoint[] bps) { - int updateIdx = update.getOffset() != -1 ? update.getOffset() : 0; - int endIdx = updateIdx + (update.getLength() != -1 ? update.getLength() : bps.length); - while (updateIdx < endIdx && updateIdx < bps.length) { - update.setChild(bps[updateIdx], updateIdx); - updateIdx++; - } - } - - public int getDeltaFlags(Object event) { - if (event instanceof BreakpointsChangedEvent) { - BreakpointsChangedEvent bpChangedEvent = ((BreakpointsChangedEvent)event); - if (BreakpointsChangedEvent.Type.ADDED.equals(bpChangedEvent.getType())) { - return IModelDelta.CONTENT | IModelDelta.SELECT | IModelDelta.EXPAND; - } - return IModelDelta.CONTENT; - } - else if (BreakpointVMProvider.isPresentationContextEvent(event)) { - PropertyChangeEvent propertyEvent = (PropertyChangeEvent)event; - if (IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION.equals(propertyEvent.getProperty()) || - IBreakpointUIConstants.PROP_BREAKPOINTS_ELEMENT_COMPARATOR.equals(propertyEvent.getProperty())) - { - return IModelDelta.CONTENT; - } else if (IBreakpointUIConstants.PROP_BREAKPOINTS_ORGANIZERS.equals(propertyEvent.getProperty())) { - return IModelDelta.EXPAND | IModelDelta.CONTENT; - } - } - return 0; - } - - public void buildDelta(Object event, VMDelta parent, int nodeOffset, RequestMonitor rm) { - if (event instanceof BreakpointsChangedEvent) { - BreakpointsChangedEvent bpChangedEvent = ((BreakpointsChangedEvent)event); - if (BreakpointsChangedEvent.Type.ADDED.equals(bpChangedEvent.getType())) { - buildBreakpointAddedDelta(bpChangedEvent, parent, nodeOffset, rm); - // Do not call rm.done() in this method! - return; - } else { - parent.setFlags(parent.getFlags() | IModelDelta.CONTENT); - } - } - else if (BreakpointVMProvider.isPresentationContextEvent(event)) { - PropertyChangeEvent propertyEvent = (PropertyChangeEvent)event; - if (IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION.equals(propertyEvent.getProperty()) || - IBreakpointUIConstants.PROP_BREAKPOINTS_ELEMENT_COMPARATOR.equals(propertyEvent.getProperty())) - { - parent.setFlags(parent.getFlags() | IModelDelta.CONTENT); - } else if (IBreakpointUIConstants.PROP_BREAKPOINTS_ORGANIZERS.equals(propertyEvent.getProperty())) { - parent.setFlags(parent.getFlags() | IModelDelta.EXPAND | IModelDelta.CONTENT); - } - } - - rm.done(); - } - - private void buildBreakpointAddedDelta(final BreakpointsChangedEvent event, final VMDelta parent, final int nodeOffset, final RequestMonitor rm) { - getVMProvider().updateNode(this, new VMChildrenUpdate( - parent, getVMProvider().getPresentationContext(), -1, -1, - new DataRequestMonitor>(getExecutor(), rm) { - @Override - protected void handleSuccess() { - for (int i = 0; i < event.getBreakpoints().length; i++) { - int bpIndex = getData().indexOf(event.getBreakpoints()[i]); - if (bpIndex >= 0) { - // Select only the first breakpoint that was added - if (i == 0) { - parent.addNode(getData().get(bpIndex), bpIndex, IModelDelta.SELECT); - } - // For all other added breakpoints, expand the parent. - parent.setFlags(parent.getFlags() | IModelDelta.CONTENT | IModelDelta.EXPAND); - } - } - rm.done(); - } - })); + @Override + protected Object createBreakpiontElement(IBreakpoint bp) { + return bp; } } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/AbstractVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/AbstractVMProvider.java index 1930b5593e3..7fe73ec167a 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/AbstractVMProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/AbstractVMProvider.java @@ -484,10 +484,11 @@ abstract public class AbstractVMProvider implements IVMProvider, IVMEventListene } /** - * Clears all configured nodes. This allows a subclass to reset and - * reconfigure its nodes. + * Clears all configured nodes, including the root node. This allows a + * subclass to reset and reconfigure its nodes. */ protected void clearNodes() { + clearNodes(true); for (IVMNode node : fChildNodesMap.keySet()) { node.dispose(); } @@ -495,6 +496,27 @@ abstract public class AbstractVMProvider implements IVMProvider, IVMEventListene fRootNode = null; } + /** + * Clears all configured nodes. This allows a subclass to reset and + * reconfigure its nodes. + * + * @param clearRootNode Flag indicating whether to also clear the root node. + * @since 2.1 + */ + protected void clearNodes(boolean clearRootNode) { + for (IVMNode node : fChildNodesMap.keySet()) { + if ( !clearRootNode || !node.equals(getRootVMNode()) ) { + node.dispose(); + } + } + fChildNodesMap.clear(); + if (clearRootNode) { + fRootNode = null; + } else { + fChildNodesMap.put(getRootVMNode(), EMPTY_NODES_ARRAY); + } + } + /** * Sets the root node for this provider. */