mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
[192019] View Model framework refactoring.
This commit is contained in:
parent
7cfa374584
commit
7d83b3a7dd
98 changed files with 5705 additions and 4532 deletions
|
@ -25,7 +25,6 @@ Export-Package:
|
|||
org.eclipse.dd.dsf.debug.ui.actions,
|
||||
org.eclipse.dd.dsf.debug.ui.sourcelookup,
|
||||
org.eclipse.dd.dsf.debug.ui.viewmodel,
|
||||
org.eclipse.dd.dsf.debug.ui.viewmodel.dm,
|
||||
org.eclipse.dd.dsf.debug.ui.viewmodel.expression,
|
||||
org.eclipse.dd.dsf.debug.ui.viewmodel.launch,
|
||||
org.eclipse.dd.dsf.debug.ui.viewmodel.modules,
|
||||
|
|
|
@ -2,6 +2,7 @@ source.. = src/
|
|||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
plugin.xml,\
|
||||
plugin.properties,\
|
||||
about.html,\
|
||||
.,\
|
||||
icons/
|
||||
|
|
|
@ -86,126 +86,23 @@
|
|||
</action>
|
||||
</viewContribution>
|
||||
<viewContribution
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.UpdatePopup"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.variable.updatePolicies"
|
||||
targetID="org.eclipse.debug.ui.VariableView">
|
||||
<menu
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu"
|
||||
label="Update Mode"
|
||||
path="additions">
|
||||
<groupMarker
|
||||
name="content">
|
||||
</groupMarker>
|
||||
<separator
|
||||
name="additions">
|
||||
</separator>
|
||||
</menu>
|
||||
<action
|
||||
class="org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions.RefreshManualActionDelegate"
|
||||
icon="icons/refreshmanual.gif"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.registers.RefreshManual"
|
||||
label="Manual"
|
||||
menubarPath="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu/content"
|
||||
style="radio"
|
||||
toolbarPath="additions">
|
||||
</action>
|
||||
<action
|
||||
class="org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions.RefreshOnBreakActionDelegate"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.registers.RefreshOnBreak"
|
||||
label="On Breakpoint Hit"
|
||||
menubarPath="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu/content"
|
||||
style="radio">
|
||||
</action>
|
||||
<action
|
||||
class="org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions.RefreshAlwaysActionDelegate"
|
||||
icon="icons/refreshalways.gif"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.registers.RefreshAlways"
|
||||
label="Always"
|
||||
menubarPath="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu/content"
|
||||
state="true"
|
||||
style="radio"
|
||||
toolbarPath="additions">
|
||||
class="org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions.SelectUpdatePolicyAction"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.selectUpdatePolicy"
|
||||
label="Update Policy"
|
||||
menubarPath="additions">
|
||||
</action>
|
||||
</viewContribution>
|
||||
<viewContribution
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.UpdatePopup"
|
||||
targetID="org.eclipse.debug.ui.ExpressionView">
|
||||
<menu
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu"
|
||||
label="Update Mode"
|
||||
path="additions">
|
||||
<groupMarker
|
||||
name="content">
|
||||
</groupMarker>
|
||||
<separator
|
||||
name="additions">
|
||||
</separator>
|
||||
</menu>
|
||||
<action
|
||||
class="org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions.RefreshManualActionDelegate"
|
||||
icon="icons/refreshmanual.gif"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.registers.RefreshManual"
|
||||
label="Manual"
|
||||
menubarPath="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu/content"
|
||||
style="radio"
|
||||
toolbarPath="additions">
|
||||
</action>
|
||||
<action
|
||||
class="org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions.RefreshOnBreakActionDelegate"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.registers.RefreshOnBreak"
|
||||
label="On Breakpoint Hit"
|
||||
menubarPath="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu/content"
|
||||
style="radio">
|
||||
</action>
|
||||
<action
|
||||
class="org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions.RefreshAlwaysActionDelegate"
|
||||
icon="icons/refreshalways.gif"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.registers.RefreshAlways"
|
||||
label="Always"
|
||||
menubarPath="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu/content"
|
||||
state="true"
|
||||
style="radio"
|
||||
toolbarPath="additions">
|
||||
</action>
|
||||
</viewContribution>
|
||||
<viewContribution
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.UpdatePopup"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.register.updatePolicies"
|
||||
targetID="org.eclipse.debug.ui.RegisterView">
|
||||
<menu
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu"
|
||||
label="Update Mode"
|
||||
path="additions">
|
||||
<groupMarker
|
||||
name="content">
|
||||
</groupMarker>
|
||||
<separator
|
||||
name="additions">
|
||||
</separator>
|
||||
</menu>
|
||||
<action
|
||||
class="org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions.RefreshManualActionDelegate"
|
||||
icon="icons/refreshmanual.gif"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.registers.RefreshManual"
|
||||
label="Manual"
|
||||
menubarPath="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu/content"
|
||||
style="radio"
|
||||
toolbarPath="additions">
|
||||
</action>
|
||||
<action
|
||||
class="org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions.RefreshOnBreakActionDelegate"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.registers.RefreshOnBreak"
|
||||
label="On Breakpoint Hit"
|
||||
menubarPath="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu/content"
|
||||
style="radio">
|
||||
</action>
|
||||
<action
|
||||
class="org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions.RefreshAlwaysActionDelegate"
|
||||
icon="icons/refreshalways.gif"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.registers.RefreshAlways"
|
||||
label="Always"
|
||||
menubarPath="org.eclipse.dd.dsf.debug.ui.update.UpdateModeSubMenu/content"
|
||||
state="true"
|
||||
style="radio"
|
||||
toolbarPath="additions">
|
||||
class="org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions.SelectUpdatePolicyAction"
|
||||
id="org.eclipse.dd.dsf.debug.ui.update.selectUpdatePolicy"
|
||||
label="Update Policy"
|
||||
menubarPath="additions">
|
||||
</action>
|
||||
</viewContribution>
|
||||
</extension>
|
||||
|
|
|
@ -20,11 +20,9 @@ import org.eclipse.dd.dsf.debug.service.IStepQueueManager;
|
|||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode.DMVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.debug.core.commands.IDebugCommandRequest;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
@Immutable
|
||||
public abstract class DsfCommandRunnable extends DsfRunnable {
|
||||
private final IExecutionDMContext fContext;
|
||||
|
@ -41,12 +39,9 @@ public abstract class DsfCommandRunnable extends DsfRunnable {
|
|||
|
||||
public DsfCommandRunnable(DsfServicesTracker servicesTracker, Object element, IDebugCommandRequest request) {
|
||||
fTracker = servicesTracker;
|
||||
if (element instanceof DMVMContext) {
|
||||
// Javac doesn't like the cast to "(AbstractDMVMLayoutNode<?>.DMVMContext)" need to use the
|
||||
// construct below and suppress warnings.
|
||||
@SuppressWarnings("unchecked")
|
||||
AbstractDMVMLayoutNode.DMVMContext vmc = (AbstractDMVMLayoutNode.DMVMContext)element;
|
||||
fContext = DMContexts.getAncestorOfType(vmc.getDMC(), IExecutionDMContext.class);
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMVMContext vmc = (IDMVMContext)element;
|
||||
fContext = DMContexts.getAncestorOfType(vmc.getDMContext(), IExecutionDMContext.class);
|
||||
} else {
|
||||
fContext = null;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
|||
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.dd.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode.DMVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
|
||||
import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
|
||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||
|
@ -81,7 +81,6 @@ import org.eclipse.ui.texteditor.ITextEditor;
|
|||
* dispatch thread to synchronize access to the state data of the running jobs.
|
||||
*/
|
||||
@ThreadSafe
|
||||
@SuppressWarnings("restriction")
|
||||
public class MISourceDisplayAdapter implements ISourceDisplay
|
||||
{
|
||||
/**
|
||||
|
@ -427,10 +426,8 @@ public class MISourceDisplayAdapter implements ISourceDisplay
|
|||
* @see org.eclipse.debug.ui.contexts.ISourceDisplayAdapter#displaySource(java.lang.Object, org.eclipse.ui.IWorkbenchPage, boolean)
|
||||
*/
|
||||
public void displaySource(Object context, final IWorkbenchPage page, final boolean force) {
|
||||
if (!(context instanceof DMVMContext)) return;
|
||||
// Correct cast: (AbstractDMVMLayoutNode<?>.DMVMContext) breaks the javac compiler
|
||||
@SuppressWarnings("unchecked")
|
||||
final IDMContext dmc = ((DMVMContext)context).getDMC();
|
||||
if (!(context instanceof IDMVMContext)) return;
|
||||
final IDMContext dmc = ((IDMVMContext)context).getDMContext();
|
||||
|
||||
// Quick test. DMC is checked again in source lookup participant, but
|
||||
// it's much quicker to test here.
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.actions;
|
||||
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
|
||||
import org.eclipse.debug.ui.AbstractDebugView;
|
||||
import org.eclipse.debug.ui.DebugUITools;
|
||||
import org.eclipse.debug.ui.contexts.DebugContextEvent;
|
||||
import org.eclipse.debug.ui.contexts.IDebugContextListener;
|
||||
import org.eclipse.debug.ui.contexts.IDebugContextService;
|
||||
import org.eclipse.jface.action.IAction;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.ui.IActionDelegate2;
|
||||
import org.eclipse.ui.IViewActionDelegate;
|
||||
import org.eclipse.ui.IViewPart;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
abstract public class AbstractVMProviderActionDelegate implements IViewActionDelegate, IDebugContextListener, IActionDelegate2 {
|
||||
|
||||
private IViewPart fView = null;
|
||||
private IAction fAction = null;
|
||||
private ISelection fDebugContext;
|
||||
|
||||
public void init(IViewPart view) {
|
||||
fView = view;
|
||||
|
||||
// Get the current selection from the DebugView so we can determine if we want this menu action to be live or not.
|
||||
IDebugContextService debugContextService = DebugUITools.getDebugContextManager().getContextService(view.getSite().getWorkbenchWindow());
|
||||
debugContextService.addPostDebugContextListener(this);
|
||||
fDebugContext = debugContextService.getActiveContext();
|
||||
}
|
||||
|
||||
public void selectionChanged(IAction action, ISelection selection) {
|
||||
if (fAction != action) {
|
||||
fAction = action;
|
||||
}
|
||||
}
|
||||
|
||||
public void runWithEvent(IAction action, Event event) {
|
||||
run(action);
|
||||
}
|
||||
|
||||
public void init(IAction action) {
|
||||
fAction = action;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
DebugUITools.getDebugContextManager().getContextService(getView().getSite().getWorkbenchWindow()).removePostDebugContextListener(this);
|
||||
}
|
||||
|
||||
public void debugContextChanged(DebugContextEvent event) {
|
||||
fDebugContext = event.getContext();
|
||||
}
|
||||
|
||||
protected IViewPart getView() { return fView; }
|
||||
|
||||
protected IAction getAction() { return fAction; }
|
||||
|
||||
protected Object getViewerInput() {
|
||||
if (fDebugContext instanceof IStructuredSelection) {
|
||||
return ((IStructuredSelection)fDebugContext).getFirstElement();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected IVMProvider getVMProvider() {
|
||||
Object viewerInput = getViewerInput();
|
||||
IPresentationContext presentationContext = getPresentationContext();
|
||||
|
||||
if (viewerInput instanceof IAdaptable && presentationContext != null) {
|
||||
IVMAdapter adapter = (IVMAdapter) ((IAdaptable)viewerInput).getAdapter(IVMAdapter.class);
|
||||
|
||||
if ( adapter != null ) {
|
||||
return adapter.getVMProvider(presentationContext);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected IPresentationContext getPresentationContext() {
|
||||
if (fView instanceof AbstractDebugView &&
|
||||
((AbstractDebugView) fView).getViewer() instanceof TreeModelViewer)
|
||||
{
|
||||
return ((TreeModelViewer) ((AbstractDebugView) fView).getViewer()).getPresentationContext();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.dm;
|
||||
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.update.VMCacheRefreshAlways;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProviderWithCache;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The purpose of this class is to satisfy package structure requirements while enabling VM update modes.
|
||||
* The non-debug centric VMCacheManager and VMCache live under org.eclipse.dd.dsf.*. The debug data view
|
||||
* caches (VMCacheRefreshAlways/Manual/OnBreak) live under org.eclipse.dd.dsf.debug.* because of their
|
||||
* awareness of debug specific events. There is a need to instantiate a default (always) cache on view
|
||||
* startup. AbstractDMVMProviderWithCache would be a good place to accomplish this task, but like the
|
||||
* VMCacheManager, this class cannot access the *dsf.debug* VMCacheRefreshAlways. AbstractDebugDMVMProviderWithCache
|
||||
* is meant to solve this problem.
|
||||
*/
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class AbstractDebugDMVMProviderWithCache extends
|
||||
AbstractDMVMProviderWithCache
|
||||
{
|
||||
|
||||
public AbstractDebugDMVMProviderWithCache(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session) {
|
||||
super(adapter, presentationContext, session);
|
||||
|
||||
VMCacheManager.getVMCacheManager().registerCache(presentationContext, new VMCacheRefreshAlways());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,305 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.debug.ui.viewmodel.expression;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMElementsUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.debug.core.model.IExpression;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public abstract class AbstractExpressionLayoutNode extends AbstractDMVMLayoutNode
|
||||
implements IExpressionLayoutNode
|
||||
{
|
||||
|
||||
public AbstractExpressionLayoutNode(AbstractVMProvider provider, DsfSession session, Class<? extends IDMContext> dmcClassType) {
|
||||
super(provider, session, dmcClassType);
|
||||
}
|
||||
|
||||
public void getElementForExpression(final IChildrenUpdate update, final String expressionText, final IExpression expression) {
|
||||
final int exprLength = getExpressionLength(expressionText);
|
||||
if (exprLength < 0) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Invalid expression", null)); //$NON-NLS-1$
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
|
||||
final String nodeExpressionText = exprLength > 0 ? expressionText.substring(0, exprLength) : expressionText;
|
||||
|
||||
getElementForExpressionPart(
|
||||
update, nodeExpressionText,
|
||||
new DataRequestMonitor<Object>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
/**
|
||||
* If the current expression is the whole expression from the argument,
|
||||
* return the VMC. Otherwise, call the child nodes to continue evaluating
|
||||
* the expression.
|
||||
*/
|
||||
if (exprLength == expressionText.length()) {
|
||||
Object element = getData();
|
||||
associateExpression(element, expression);
|
||||
update.setChild(element, 0);
|
||||
update.done();
|
||||
} else {
|
||||
getVMContextForExpressionFromChildNodes(
|
||||
update, getData(), expressionText.substring(exprLength), expression);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleErrorOrCancel() {
|
||||
update.setStatus(getStatus());
|
||||
update.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void getElementForExpressionPart(final IChildrenUpdate update, final String expressionPartText, final DataRequestMonitor<Object> rm) {
|
||||
updateElements(new VMElementsUpdate(
|
||||
update, -1, -1,
|
||||
new DataRequestMonitor<List<Object>>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
if (getData().size() == 0) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "No contexts", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
} else {
|
||||
final List<Object> elements = getData();
|
||||
|
||||
final MultiRequestMonitor<DataRequestMonitor<Boolean>> multiRm = new MultiRequestMonitor<DataRequestMonitor<Boolean>>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
boolean foundMatchingContext = false;
|
||||
for (int i = 0; i < getRequestMonitors().size(); i++) {
|
||||
if (getRequestMonitors().get(i).getData()) {
|
||||
rm.setData(elements.get(i));
|
||||
foundMatchingContext = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundMatchingContext) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Context not found", null)); //$NON-NLS-1$
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
};
|
||||
|
||||
for (Object element : elements) {
|
||||
testContextForExpression(
|
||||
element, expressionPartText,
|
||||
multiRm.add(
|
||||
new DataRequestMonitor<Boolean>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
multiRm.requestMonitorDone(this);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleErrorOrCancel() {
|
||||
update.setStatus(getStatus());
|
||||
update.done();
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ConfinedToDsfExecutor("#getSession#getExecutor")
|
||||
protected abstract void testContextForExpression(Object element, final String expression, final DataRequestMonitor<Boolean> rm);
|
||||
protected abstract void associateExpression(Object element, IExpression expression);
|
||||
|
||||
protected void getVMContextForExpressionFromChildNodes(final IChildrenUpdate update, Object parentElement, String childExpression, IExpression expression) {
|
||||
IChildrenUpdate childUpdate = new ChildExpressionElementUpdate(
|
||||
update, update.getElementPath().createChildPath(parentElement),
|
||||
new DataRequestMonitor<List<Object>>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
update.setChild(getData().get(0), 0);
|
||||
update.done();
|
||||
}
|
||||
@Override
|
||||
protected void handleErrorOrCancel() {
|
||||
update.setStatus(getStatus());
|
||||
update.done();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
for (int i = 0; i < getChildLayoutNodes().length; i++) {
|
||||
if (getChildLayoutNodes()[i] instanceof IExpressionLayoutNode) {
|
||||
IExpressionLayoutNode childNode = (IExpressionLayoutNode)getChildLayoutNodes()[i];
|
||||
if (childNode.getExpressionLength(childExpression) > 0) {
|
||||
// The child node will call update.done();
|
||||
childNode.getElementForExpression(childUpdate, childExpression, expression);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find a matching child node in the for loop above, return an error.
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Invalid expression", null)); //$NON-NLS-1$
|
||||
update.done();
|
||||
|
||||
}
|
||||
|
||||
public int getDeltaFlagsForExpression(String expressionText, Object event) {
|
||||
int exprLength = getExpressionLength(expressionText);
|
||||
if (exprLength >= 0) {
|
||||
if (exprLength == expressionText.length()) {
|
||||
return getDeltaFlags(event);
|
||||
} else {
|
||||
int retVal = getDeltaFlagsForExpressionPart(event);
|
||||
String childExpression = expressionText.substring(exprLength);
|
||||
for (int i = 0; i < getChildLayoutNodes().length; i++) {
|
||||
if (getChildLayoutNodes()[i] instanceof IExpressionLayoutNode) {
|
||||
IExpressionLayoutNode exprNode = (IExpressionLayoutNode)getChildLayoutNodes()[i];
|
||||
if (exprNode.getExpressionLength(childExpression) > 0) {
|
||||
// The child node will call update.done();
|
||||
retVal |= exprNode.getDeltaFlagsForExpression(childExpression, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
protected abstract int getDeltaFlagsForExpressionPart(Object event);
|
||||
|
||||
public void buildDeltaForExpression(final IExpression expression, final int elementIdx, final String expressionText, final Object event, final VMDelta parentDelta, final TreePath path, final RequestMonitor rm)
|
||||
{
|
||||
// Find the expression part that belong to this node. If expression
|
||||
// is not recognized, do nothing.
|
||||
final int exprLength = getExpressionLength(expressionText);
|
||||
if (exprLength < 0) {
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
final String nodeExpressionText = exprLength > 0 ? expressionText.substring(0, exprLength) : expressionText;
|
||||
|
||||
getElementForExpressionPart(
|
||||
new ElementsUpdate(new DataRequestMonitor<List<Object>>(getExecutor(), null), path),
|
||||
nodeExpressionText,
|
||||
new DataRequestMonitor<Object>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
if (exprLength == expressionText.length()) {
|
||||
associateExpression(getData(), expression);
|
||||
buildDeltaForExpressionElement(getData(), elementIdx, event, parentDelta, rm);
|
||||
} else {
|
||||
TreePath newPath = path.createChildPath(getData());
|
||||
callChildExpressionNodesToBuildDelta(
|
||||
expression, elementIdx, expressionText.substring(exprLength), event, parentDelta, newPath, rm);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleErrorOrCancel() {
|
||||
// There is no matching element for given expression. That's OK, it just
|
||||
// means that the expression is invalid.
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta, final RequestMonitor rm)
|
||||
{
|
||||
// Find the child nodes that have deltas for the given event.
|
||||
final Map<IVMLayoutNode,Integer> childNodesWithDeltaFlags = getChildNodesWithDeltaFlags(event);
|
||||
|
||||
// If no child layout nodes have deltas we can stop here.
|
||||
if (childNodesWithDeltaFlags.size() == 0) {
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
callChildNodesToBuildDelta(
|
||||
childNodesWithDeltaFlags, parentDelta.addNode(element, elementIdx, IModelDelta.NO_CHANGE), event, rm);
|
||||
}
|
||||
|
||||
protected void callChildExpressionNodesToBuildDelta(IExpression expression, int elementIdx, String expressionRemainder, Object event, VMDelta parentDelta, TreePath path, final RequestMonitor rm)
|
||||
{
|
||||
final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
rm.done();
|
||||
}
|
||||
};
|
||||
|
||||
int childRmCount = 0;
|
||||
|
||||
for (int i = 0; i < getChildLayoutNodes().length; i++) {
|
||||
if (getChildLayoutNodes()[i] instanceof IExpressionLayoutNode) {
|
||||
IExpressionLayoutNode childNode = (IExpressionLayoutNode)getChildLayoutNodes()[i];
|
||||
if (childNode.getExpressionLength(expressionRemainder) > 0 &&
|
||||
childNode.getDeltaFlagsForExpression(expressionRemainder, event) != IModelDelta.NO_CHANGE)
|
||||
{
|
||||
childNode.buildDeltaForExpression(
|
||||
expression, elementIdx, expressionRemainder, event, parentDelta, path, countingRm);
|
||||
childRmCount++;
|
||||
// The child node will call update.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
countingRm.setDoneCount(childRmCount);
|
||||
}
|
||||
|
||||
|
||||
class ChildExpressionElementUpdate extends VMElementsUpdate {
|
||||
private final TreePath fPath;
|
||||
|
||||
ChildExpressionElementUpdate(IChildrenUpdate clientUpdate, TreePath path, DataRequestMonitor<List<Object>> rm) {
|
||||
super(clientUpdate, 0, 1, rm);
|
||||
fPath = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElement() {
|
||||
return fPath.getLastSegment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreePath getElementPath() {
|
||||
return fPath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.debug.ui.viewmodel.expression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.concurrent.ViewerDataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMChildrenUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.debug.core.model.IExpression;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public abstract class AbstractExpressionVMNode extends AbstractDMVMNode
|
||||
implements IExpressionVMNode
|
||||
{
|
||||
|
||||
public AbstractExpressionVMNode(AbstractDMVMProvider provider, DsfSession session, Class<? extends IDMContext> dmcClassType) {
|
||||
super(provider, session, dmcClassType);
|
||||
}
|
||||
|
||||
public void update(final IExpressionUpdate update) {
|
||||
if (!canParseExpression(update.getExpression())) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Invalid expression", null)); //$NON-NLS-1$
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
|
||||
update(new IChildrenUpdate[] { new VMChildrenUpdate(
|
||||
update, -1, -1,
|
||||
new ViewerDataRequestMonitor<List<Object>>(getExecutor(), update) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
if (getData().size() == 0) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "No contexts", null)); //$NON-NLS-1$
|
||||
update.done();
|
||||
} else {
|
||||
final List<Object> elements = getData();
|
||||
|
||||
final MultiRequestMonitor<DataRequestMonitor<Boolean>> multiRm = new MultiRequestMonitor<DataRequestMonitor<Boolean>>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (getStatus().isOK()) {
|
||||
boolean foundMatchingContext = false;
|
||||
for (int i = 0; i < getRequestMonitors().size(); i++) {
|
||||
if (getRequestMonitors().get(i).getData()) {
|
||||
Object element = elements.get(i);
|
||||
associateExpression(element, update.getExpression());
|
||||
update.setExpressionElement(element);
|
||||
foundMatchingContext = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundMatchingContext) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Context not found", null)); //$NON-NLS-1$
|
||||
}
|
||||
} else {
|
||||
update.setStatus(getStatus());
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
};
|
||||
|
||||
for (Object element : elements) {
|
||||
testElementForExpression(
|
||||
element, update.getExpression(),
|
||||
multiRm.add(
|
||||
new DataRequestMonitor<Boolean>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
multiRm.requestMonitorDone(this);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleErrorOrCancel() {
|
||||
update.setStatus(getStatus());
|
||||
update.done();
|
||||
}
|
||||
})}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ConfinedToDsfExecutor("#getSession#getExecutor")
|
||||
protected void testElementForExpression(Object element, IExpression expression, final DataRequestMonitor<Boolean> rm) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
protected void associateExpression(Object element, IExpression expression) {
|
||||
}
|
||||
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.expression;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
|
||||
|
@ -17,12 +18,10 @@ import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
|||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.ExpressionVMProvider.ExpressionsChangedEvent;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMElementsUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.dd.dsf.ui.concurrent.ViewerCountingRequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.IExpressionManager;
|
||||
import org.eclipse.debug.core.model.IExpression;
|
||||
|
@ -35,30 +34,32 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdat
|
|||
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.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.debug.ui.DebugUITools;
|
||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||
import org.eclipse.jface.resource.JFaceResources;
|
||||
import org.eclipse.jface.viewers.CellEditor;
|
||||
import org.eclipse.jface.viewers.ICellModifier;
|
||||
import org.eclipse.jface.viewers.TextCellEditor;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
/**
|
||||
* This is the top-level layout node in the expressions view. Its job is to:
|
||||
* This is the top-level view model node in the expressions view. Its job is to:
|
||||
* <li>
|
||||
* <ol> retrieve the {@link IExpression} objects from the global {@link IExpressionManager},</ol>
|
||||
* <ol> retrieve the expression string from the <code>IExpression</code> object,</ol>
|
||||
* <ol> then to call the configured expression nodes to parse the expression string.</ol>
|
||||
* </li>
|
||||
* <p>
|
||||
* This node is not intended to have any standard child layout nodes, therefore
|
||||
* the implementation of {@link #setChildNodes(IVMLayoutNode[])} throws an exception.
|
||||
* Instead users should call {@link #setExpressionLayoutNodes(IExpressionLayoutNode[])}
|
||||
* to configure layout nodes that this node will delegate to when processing expressions.
|
||||
* This node is not intended to have any standard child nodes, therefore
|
||||
* the implementation of {@link #setChildNodes(IVMNode[])} throws an exception.
|
||||
* Instead users should call {@link #setExpressionNodes(IExpressionVMNode[])}
|
||||
* to configure the nodes that this node will delegate to when processing expressions.
|
||||
* </p>
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode
|
||||
public class ExpressionManagerVMNode extends AbstractVMNode
|
||||
implements IElementLabelProvider, IElementEditor
|
||||
{
|
||||
|
||||
|
@ -68,11 +69,11 @@ public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode
|
|||
* error message in the view, and to allow the user to edit the
|
||||
* expression.
|
||||
*/
|
||||
private class InvalidExpressionVMC extends AbstractVMContext {
|
||||
final IExpression fExpression;
|
||||
static class InvalidExpressionVMContext extends AbstractVMContext {
|
||||
final private IExpression fExpression;
|
||||
|
||||
public InvalidExpressionVMC(IExpression expression) {
|
||||
super(getVMProvider().getVMAdapter(), ExpressionManagerLayoutNode.this);
|
||||
public InvalidExpressionVMContext(ExpressionManagerVMNode node, IExpression expression) {
|
||||
super(node.getVMProvider().getVMAdapter(), node);
|
||||
fExpression = expression;
|
||||
}
|
||||
|
||||
|
@ -86,9 +87,13 @@ public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode
|
|||
}
|
||||
}
|
||||
|
||||
public IExpression getExpression() {
|
||||
return fExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof InvalidExpressionVMC && ((InvalidExpressionVMC)obj).fExpression.equals(fExpression);
|
||||
return obj instanceof InvalidExpressionVMContext && ((InvalidExpressionVMContext)obj).fExpression.equals(fExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -101,9 +106,9 @@ public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode
|
|||
* VMC for a new expression object to be added. When user clicks on this node to
|
||||
* edit it, he will create a new expression.
|
||||
*/
|
||||
public class NewExpressionVMC extends AbstractVMContext {
|
||||
class NewExpressionVMC extends AbstractVMContext {
|
||||
public NewExpressionVMC() {
|
||||
super(getVMProvider().getVMAdapter(), ExpressionManagerLayoutNode.this);
|
||||
super(getVMProvider().getVMAdapter(), ExpressionManagerVMNode.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -123,20 +128,21 @@ public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode
|
|||
}
|
||||
}
|
||||
|
||||
/** Array of expression nodes which parse the user expressions and handle model events */
|
||||
private IExpressionLayoutNode[] fExpressionNodes = new IExpressionLayoutNode[0];
|
||||
|
||||
/** Local reference to the global expression manager */
|
||||
private IExpressionManager fManager = DebugPlugin.getDefault().getExpressionManager();
|
||||
|
||||
/** Cached reference to a cell modifier for editing expression strings of invalid expressions */
|
||||
private WatchExpressionCellModifier fWatchExpressionCellModifier = new WatchExpressionCellModifier();
|
||||
|
||||
public ExpressionManagerLayoutNode(AbstractVMProvider provider) {
|
||||
public ExpressionManagerVMNode(ExpressionVMProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
public void updateHasElements(IHasChildrenUpdate[] updates) {
|
||||
private ExpressionVMProvider getExpressionVMProvider() {
|
||||
return (ExpressionVMProvider)getVMProvider();
|
||||
}
|
||||
|
||||
public void update(IHasChildrenUpdate[] updates) {
|
||||
// Test availability of children based on whether there are any expressions
|
||||
// in the manager. We assume that the getExpressions() will just read
|
||||
// local state data, so we don't bother using a job to perform this
|
||||
|
@ -147,14 +153,24 @@ public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode
|
|||
}
|
||||
}
|
||||
|
||||
public void updateElementCount(IChildrenCountUpdate update) {
|
||||
// We assume that the getExpressions() will just read local state data,
|
||||
// so we don't bother using a job to perform this operation.
|
||||
update.setChildCount(fManager.getExpressions().length + 1);
|
||||
update.done();
|
||||
public void update(IChildrenCountUpdate[] updates) {
|
||||
for (IChildrenCountUpdate update : updates) {
|
||||
if (!checkUpdate(update)) continue;
|
||||
|
||||
// We assume that the getExpressions() will just read local state data,
|
||||
// so we don't bother using a job to perform this operation.
|
||||
update.setChildCount(fManager.getExpressions().length + 1);
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateElements(final IChildrenUpdate update) {
|
||||
public void update(final IChildrenUpdate[] updates) {
|
||||
for (IChildrenUpdate update : updates) {
|
||||
doUpdateChildren(update);
|
||||
}
|
||||
}
|
||||
|
||||
public void doUpdateChildren(final IChildrenUpdate update) {
|
||||
final IExpression[] expressions = fManager.getExpressions();
|
||||
|
||||
// For each (expression) element in update, find the layout node that can
|
||||
|
@ -162,55 +178,45 @@ public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode
|
|||
// call IExpressionLayoutNode#getElementForExpression to generate a VMC.
|
||||
// Since the last is an async call, we need to create a multi-RM to wait
|
||||
// for all the calls to complete.
|
||||
final CountingRequestMonitor multiRm = new CountingRequestMonitor(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
update.done();
|
||||
}
|
||||
};
|
||||
final CountingRequestMonitor multiRm = new ViewerCountingRequestMonitor(getVMProvider().getExecutor(), update);
|
||||
int multiRmCount = 0;
|
||||
|
||||
int expressionRmCount = 0;
|
||||
for (int i = update.getOffset(); i < update.getOffset() + update.getLength() && i < expressions.length + 1; i++) {
|
||||
|
||||
// The last element is the "new expression"
|
||||
if (i == expressions.length) {
|
||||
update.setChild(new NewExpressionVMC(), i);
|
||||
} else {
|
||||
final String expressionText = expressions[i].getExpressionText();
|
||||
final int expressionIdx = i;
|
||||
if (i < expressions.length) {
|
||||
multiRmCount++;
|
||||
final int childIndex = i;
|
||||
final IExpression expression = expressions[i];
|
||||
IExpressionLayoutNode expressionNode = findNodeForExpression(expressionText);
|
||||
if (expressionNode == null) {
|
||||
update.setChild(new InvalidExpressionVMC(expression), i);
|
||||
} else {
|
||||
expressionRmCount++;
|
||||
// getElementForExpression() accepts a IElementsUpdate as an argument.
|
||||
// Construct an instance of VMElementsUpdate which will call a
|
||||
// the request monitor when it is finished. The request monitor
|
||||
// will in turn set the element in the update argument in this method.
|
||||
VMElementsUpdate expressionElementUpdate = new VMElementsUpdate(
|
||||
update, 0, 1,
|
||||
new DataRequestMonitor<List<Object>>(getExecutor(), multiRm) {
|
||||
// getElementForExpression() accepts a IElementsUpdate as an argument.
|
||||
// Construct an instance of VMElementsUpdate which will call a
|
||||
// the request monitor when it is finished. The request monitor
|
||||
// will in turn set the element in the update argument in this method.
|
||||
((ExpressionVMProvider)getVMProvider()).update(
|
||||
new VMExpressionUpdate(
|
||||
update, expression,
|
||||
new DataRequestMonitor<Object>(getVMProvider().getExecutor(), multiRm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
update.setChild(getData().get(0), expressionIdx);
|
||||
update.setChild(getData(), childIndex);
|
||||
multiRm.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleError() {
|
||||
update.setChild(new InvalidExpressionVMC(expression), expressionIdx);
|
||||
update.setChild(new InvalidExpressionVMContext(ExpressionManagerVMNode.this, expression), childIndex);
|
||||
multiRm.done();
|
||||
}
|
||||
});
|
||||
expressionNode.getElementForExpression(expressionElementUpdate, expressionText, expression);
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
// Last element in the list of expressions is the "add new expression"
|
||||
// dummy entry.
|
||||
update.setChild(new NewExpressionVMC(), i);
|
||||
}
|
||||
}
|
||||
|
||||
// If no expressions were parsed, we're finished.
|
||||
// Set the count to the counting RM.
|
||||
multiRm.setDoneCount(expressionRmCount);
|
||||
multiRm.setDoneCount(multiRmCount);
|
||||
}
|
||||
|
||||
public void update(ILabelUpdate[] updates) {
|
||||
|
@ -218,8 +224,8 @@ public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode
|
|||
// The expression layout nodes are responsible for supplying label providers
|
||||
// for their VMCs.
|
||||
for (ILabelUpdate update : updates) {
|
||||
if (update.getElement() instanceof InvalidExpressionVMC) {
|
||||
updateInvalidExpressionVMCLabel(update, (InvalidExpressionVMC) update.getElement());
|
||||
if (update.getElement() instanceof InvalidExpressionVMContext) {
|
||||
updateInvalidExpressionVMCLabel(update, (InvalidExpressionVMContext) update.getElement());
|
||||
} else if (update.getElement() instanceof NewExpressionVMC) {
|
||||
updateNewExpressionVMCLabel(update, (NewExpressionVMC) update.getElement());
|
||||
} else {
|
||||
|
@ -231,16 +237,16 @@ public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode
|
|||
/**
|
||||
* Updates the label for the InvalidExpressionVMC.
|
||||
*/
|
||||
private void updateInvalidExpressionVMCLabel(ILabelUpdate update, InvalidExpressionVMC vmc) {
|
||||
private void updateInvalidExpressionVMCLabel(ILabelUpdate update, InvalidExpressionVMContext vmc) {
|
||||
String[] columnIds = update.getColumnIds() != null ?
|
||||
update.getColumnIds() : new String[] { IDebugVMConstants.COLUMN_ID__NAME };
|
||||
|
||||
for (int i = 0; i < columnIds.length; i++) {
|
||||
if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnIds[i])) {
|
||||
update.setLabel(vmc.fExpression.getExpressionText(), i);
|
||||
update.setLabel(vmc.getExpression().getExpressionText(), i);
|
||||
update.setImageDescriptor(DebugUITools.getImageDescriptor( IDebugUIConstants.IMG_OBJS_EXPRESSION ), i);
|
||||
} else if (IDebugVMConstants.COLUMN_ID__NAME.equals(columnIds[i])) {
|
||||
update.setLabel(vmc.fExpression.getExpressionText(), i);
|
||||
update.setLabel(vmc.getExpression().getExpressionText(), i);
|
||||
update.setImageDescriptor(DebugUITools.getImageDescriptor( IDebugUIConstants.IMG_OBJS_EXPRESSION ), i);
|
||||
} else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnIds[i])) {
|
||||
update.setLabel(MessagesForExpressionVM.ExpressionManagerLayoutNode__invalidExpression_valueColumn_label, i);
|
||||
|
@ -275,54 +281,6 @@ public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode
|
|||
update.done();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience call that iterates through all the configured expression
|
||||
* layout nodes and finds the first one that can parse the given expression.
|
||||
*/
|
||||
private IExpressionLayoutNode findNodeForExpression(String expressionText) {
|
||||
for (IExpressionLayoutNode node : fExpressionNodes) {
|
||||
if (node.getExpressionLength(expressionText) > 0) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* ExpressionManagerLayoutNode does not support child layout nodes.
|
||||
* @see #setExpressionLayoutNodes(IExpressionLayoutNode[])
|
||||
*/
|
||||
@Override
|
||||
public void setChildNodes(IVMLayoutNode[] childNodes) {
|
||||
throw new UnsupportedOperationException("This node does not support children."); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the set of expression layout nodes that the expression manager layout
|
||||
* node will use to parse the expressions.
|
||||
* <p>
|
||||
* <i>Note: The nodes specified in the array will be called to parse expressions,
|
||||
* in the order as they are in the array</i>. Therefore if one node is a "greedy"
|
||||
* parser, and will accept any expression string, it should appear last in the list
|
||||
* of the nodes.
|
||||
* </p>
|
||||
* @param nodes Array of expression layout nodes to configure with the manager.
|
||||
*/
|
||||
public void setExpressionLayoutNodes(IExpressionLayoutNode[] nodes) {
|
||||
fExpressionNodes = nodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
|
||||
for (IExpressionLayoutNode exprNode : fExpressionNodes) {
|
||||
exprNode.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDeltaFlags(Object event) {
|
||||
int retVal = 0;
|
||||
|
||||
|
@ -331,52 +289,53 @@ public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode
|
|||
retVal |= IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
// If any of the expressions nodes have delta flags, that means that this
|
||||
// node probably needs to generate a delta as well. Ideally, we would call
|
||||
// IExpressionLayoutNode.getDeltaFlagsForExpression() here, but getDeltaFlags()
|
||||
// is an optimization call anyway, and it's OK if it generates some false
|
||||
// positives. We will call getDeltaFlagsForExpression in buildDelta() instead..
|
||||
for (IExpressionLayoutNode node : fExpressionNodes) {
|
||||
retVal |= node.getDeltaFlags(event);
|
||||
for (IExpression expression : fManager.getExpressions()) {
|
||||
retVal |= getExpressionVMProvider().getDeltaFlagsForExpression(expression, event);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildDelta(final Object event, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
|
||||
public void buildDelta(final Object event, final ModelDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
|
||||
// Add a flag if the list of expressions has changed.
|
||||
if (event instanceof ExpressionsChangedEvent) {
|
||||
VMCacheManager.getVMCacheManager().flush(super.getVMProvider().getPresentationContext());
|
||||
parentDelta.addFlags(IModelDelta.CONTENT);
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
// Once again, for each expression, find its corresponding layout node and ask that
|
||||
// Once again, for each expression, find its corresponding node and ask that
|
||||
// layout node for its delta flags for given event. If there are delta flags to be
|
||||
// generated, call the asynchronous method to do so.
|
||||
CountingRequestMonitor multiRm = new CountingRequestMonitor(getExecutor(), requestMonitor);
|
||||
|
||||
int buildDeltaForExpressionCallCount = 0;
|
||||
|
||||
IExpression[] expressions = fManager.getExpressions();
|
||||
for (int i = 0; i < expressions.length; i++ ) {
|
||||
String expressionText = expressions[i].getExpressionText();
|
||||
IExpressionLayoutNode node = findNodeForExpression(expressionText);
|
||||
if (node == null) continue;
|
||||
|
||||
int flags = node.getDeltaFlagsForExpression(expressionText, event);
|
||||
|
||||
// If the given node has no delta flags, skip it.
|
||||
int flags = getExpressionVMProvider().getDeltaFlagsForExpression(expressions[i], event);
|
||||
// If the given expression has no delta flags, skip it.
|
||||
if (flags == IModelDelta.NO_CHANGE) continue;
|
||||
|
||||
node.buildDeltaForExpression(expressions[i], i + nodeOffset, expressionText, event, parentDelta,
|
||||
getTreePathFromDelta(parentDelta),
|
||||
new RequestMonitor(getExecutor(), multiRm));
|
||||
int elementOffset = nodeOffset >= 0 ? nodeOffset + i : -1;
|
||||
getExpressionVMProvider().buildDeltaForExpression(
|
||||
expressions[i], elementOffset, event, parentDelta, getTreePathFromDelta(parentDelta),
|
||||
new RequestMonitor(getExecutor(), multiRm));
|
||||
buildDeltaForExpressionCallCount++;
|
||||
}
|
||||
|
||||
multiRm.setDoneCount(buildDeltaForExpressionCallCount);
|
||||
}
|
||||
|
||||
private TreePath getTreePathFromDelta(IModelDelta delta) {
|
||||
List<Object> elementList = new LinkedList<Object>();
|
||||
IModelDelta listDelta = delta;
|
||||
elementList.add(0, listDelta.getElement());
|
||||
while (listDelta.getParentDelta() != null) {
|
||||
elementList.add(0, listDelta.getElement());
|
||||
listDelta = listDelta.getParentDelta();
|
||||
}
|
||||
return new TreePath(elementList.toArray());
|
||||
}
|
||||
|
||||
|
||||
public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) {
|
||||
if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnId)) {
|
|
@ -10,44 +10,75 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.expression;
|
||||
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.dm.AbstractDebugDMVMProviderWithCache;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.FormattedValuePreferenceStore;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.register.RegisterGroupLayoutNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.register.RegisterLayoutNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.register.RegisterGroupVMNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.register.RegisterVMNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.register.SyncRegisterDataAccess;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.update.BreakpointHitUpdatePolicy;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.variable.SyncVariableDataAccess;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.variable.VariableLayoutNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.variable.VariableVMNode;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.DMVMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMModelProxy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.DefaultVMContentProviderStrategy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.RootDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.AutomaticUpdatePolicy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.IVMUpdatePolicy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.ManualUpdatePolicy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.UserEditEvent;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.model.IExpression;
|
||||
import org.eclipse.debug.internal.core.IExpressionsListener2;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.jface.util.IPropertyChangeListener;
|
||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
*
|
||||
* The expression provider is used to populate the contents of the expressions
|
||||
* view. The node hierarchy in this view is a little different than in a typical
|
||||
* provider: the expression manager node should be registered as the single child
|
||||
* of the root node and no nodes should be registered as children of expression node.
|
||||
* Instead the top level expression nodes should be registered with a call to
|
||||
* {@link #setExpressionNodes(IExpressionVMNode[])}. And each expression node can
|
||||
* have its own sub-hierarchy of elements as needed. However all nodes configured
|
||||
* with this provider (with the exception of the root and the expression manager)
|
||||
* should implement {@link IExpressionVMNode}.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class ExpressionVMProvider extends AbstractDebugDMVMProviderWithCache implements IExpressionsListener2
|
||||
public class ExpressionVMProvider extends AbstractDMVMProvider
|
||||
implements IPropertyChangeListener, IExpressionsListener2
|
||||
{
|
||||
public static class ExpressionsChangedEvent {
|
||||
/**
|
||||
* Object representing a change in configured expressions. This event is
|
||||
* object is used when generating a model delta.
|
||||
*/
|
||||
public static class ExpressionsChangedEvent extends UserEditEvent {
|
||||
enum Type {ADDED, CHANGED, REMOVED, MOVED, INSERTED}
|
||||
public final Type fType;
|
||||
public final IExpression[] fExpressions;
|
||||
public ExpressionsChangedEvent(Type type, IExpression[] expressions) {
|
||||
public ExpressionsChangedEvent(Type type, Set<Object> elements) {
|
||||
super(elements);
|
||||
fType = type;
|
||||
fExpressions = expressions;
|
||||
}
|
||||
}
|
||||
|
||||
private IExpressionVMNode[] fExpressionNodes;
|
||||
|
||||
public ExpressionVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
|
||||
super(adapter, context, session);
|
||||
|
||||
context.addPropertyChangeListener(this);
|
||||
|
||||
// The VM provider has to handle all events that result in model deltas.
|
||||
// Add the provider as listener to expression changes events.
|
||||
DebugPlugin.getDefault().getExpressionManager().addExpressionListener(this);
|
||||
|
@ -55,6 +86,99 @@ public class ExpressionVMProvider extends AbstractDebugDMVMProviderWithCache imp
|
|||
configureLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DefaultVMContentProviderStrategy createContentStrategy() {
|
||||
return new ExpressionVMProviderContentStragegy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IVMModelProxy createModelProxyStrategy(Object rootElement) {
|
||||
return new ExpressionVMProviderModelProxyStrategy(this, rootElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the given expression element. This method is used by the
|
||||
* expression manager node to obtain a view model element based on the
|
||||
* {@link IExpression} retrieved from the expression manager. The
|
||||
* implementation of this method (which is in the content strategy),
|
||||
* checks the configured expression nodes to see which one can
|
||||
* process the given expression, when it finds it it delegates
|
||||
* to that expression node's {@link IExpressionVMNode#update(IExpressionUpdate)}
|
||||
* method.
|
||||
* @param update Expression update to process.
|
||||
*/
|
||||
public void update(IExpressionUpdate update) {
|
||||
((ExpressionVMProviderContentStragegy)getContentStrategy()).update(update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the delta flags that can be generated for the given expression
|
||||
* and the given event. This method is used by the
|
||||
* expression manager node to obtain the delta flags based on the
|
||||
* {@link IExpression} retrieved from the expression manager. The
|
||||
* implementation of this method (which is in the model proxy strategy),
|
||||
* checks the configured expression nodes to see which one can
|
||||
* process the given expression, when it finds it it delegates
|
||||
* to that expression node's {@link IExpressionVMNode#getDeltaFlagsForExpression(IExpression, Object)}
|
||||
* method.
|
||||
*/
|
||||
public int getDeltaFlagsForExpression(IExpression expression, Object event) {
|
||||
// Workaround: find the first active proxy and use it.
|
||||
if (!getActiveModelProxies().isEmpty()) {
|
||||
return ((ExpressionVMProviderModelProxyStrategy)getActiveModelProxies().get(0)).getDeltaFlagsForExpression(expression, event);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the model delta based on the given expression
|
||||
* and the given event. This method is used by the
|
||||
* expression manager to build the delta based on the
|
||||
* {@link IExpression} retrieved from the expression manager. The
|
||||
* implementation of this method (which is in the model proxy strategy),
|
||||
* checks the configured expression nodes to see which one can
|
||||
* process the given expression, when it finds it it delegates
|
||||
* to that expression node's {@link IExpressionVMNode#buildDeltaForExpression(IExpression, int, Object, ModelDelta, TreePath, RequestMonitor)}
|
||||
* and {@link IExpressionVMNode#buildDeltaForExpressionElement(Object, int, Object, ModelDelta, RequestMonitor)
|
||||
* methods.
|
||||
*/
|
||||
public void buildDeltaForExpression(final IExpression expression, final int expressionElementIdx, final Object event,
|
||||
final ModelDelta parentDelta, final TreePath path, final RequestMonitor rm)
|
||||
{
|
||||
// Workaround: find the first active proxy and use it.
|
||||
if (!getActiveModelProxies().isEmpty()) {
|
||||
((ExpressionVMProviderModelProxyStrategy)getActiveModelProxies().get(0)).buildDeltaForExpression(
|
||||
expression, expressionElementIdx, event, parentDelta, path, rm);
|
||||
} else {
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the given nodes as the top-level expression nodes.
|
||||
*/
|
||||
protected void setExpressionNodes(IExpressionVMNode[] nodes) {
|
||||
fExpressionNodes = nodes;
|
||||
|
||||
// Call the base class to make sure that the nodes are also
|
||||
// returned by the getAllNodes method.
|
||||
for (IExpressionVMNode node : nodes) {
|
||||
addNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of configured top-level expression nodes.
|
||||
* @return
|
||||
*/
|
||||
public IExpressionVMNode[] getExpressionNodes() {
|
||||
return fExpressionNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the nodes of this provider. This method may be overriden by
|
||||
* sub classes to create an alternate configuration in this provider.
|
||||
*/
|
||||
protected void configureLayout() {
|
||||
|
||||
/*
|
||||
|
@ -66,29 +190,30 @@ public class ExpressionVMProvider extends AbstractDebugDMVMProviderWithCache imp
|
|||
/*
|
||||
* Create the top level node which provides the anchor starting point.
|
||||
*/
|
||||
IVMRootLayoutNode debugViewSelectionNode = new DMVMRootLayoutNode(this);
|
||||
IRootVMNode rootNode = new RootDMVMNode(this);
|
||||
|
||||
/*
|
||||
* Now the Overarching management node.
|
||||
*/
|
||||
ExpressionManagerLayoutNode expressionManagerNode = new ExpressionManagerLayoutNode(this);
|
||||
debugViewSelectionNode.setChildNodes(new IVMLayoutNode[] {expressionManagerNode});
|
||||
ExpressionManagerVMNode expressionManagerNode = new ExpressionManagerVMNode(this);
|
||||
addChildNodes(rootNode, new IVMNode[] {expressionManagerNode});
|
||||
|
||||
/*
|
||||
* The expression view wants to support fully all of the components of the register view.
|
||||
*/
|
||||
IExpressionLayoutNode registerGroupNode = new RegisterGroupLayoutNode(this, getSession(), syncRegDataAccess);
|
||||
IVMLayoutNode registerNode = new RegisterLayoutNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), syncRegDataAccess);
|
||||
registerGroupNode.setChildNodes(new IVMLayoutNode[] { registerNode });
|
||||
IExpressionVMNode registerGroupNode = new RegisterGroupVMNode(this, getSession(), syncRegDataAccess);
|
||||
|
||||
IExpressionVMNode registerNode = new RegisterVMNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), syncRegDataAccess);
|
||||
addChildNodes(registerGroupNode, new IExpressionVMNode[] {registerNode});
|
||||
|
||||
/*
|
||||
* Create the support for the SubExpressions. Anything which is brought into the expressions
|
||||
* view comes in as a fully qualified expression so we go directly to the SubExpression layout
|
||||
* node.
|
||||
*/
|
||||
IExpressionLayoutNode subExpressioNode =
|
||||
|
||||
new VariableLayoutNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), syncvarDataAccess);
|
||||
IExpressionVMNode variableNode =
|
||||
new VariableVMNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), syncvarDataAccess);
|
||||
addChildNodes(variableNode, new IExpressionVMNode[] {variableNode});
|
||||
|
||||
/*
|
||||
* Tell the expression node which subnodes it will directly support. It is very important
|
||||
|
@ -101,17 +226,54 @@ public class ExpressionVMProvider extends AbstractDebugDMVMProviderWithCache imp
|
|||
* assume what it was passed was for it and the real node which wants to handle it would be
|
||||
* left out in the cold.
|
||||
*/
|
||||
expressionManagerNode.setExpressionLayoutNodes(new IExpressionLayoutNode[] { registerGroupNode, subExpressioNode });
|
||||
setExpressionNodes(new IExpressionVMNode[] {registerGroupNode, variableNode});
|
||||
|
||||
/*
|
||||
* Let the work know which is the top level node.
|
||||
*/
|
||||
setRootLayoutNode(debugViewSelectionNode);
|
||||
setRootNode(rootNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the expression node which can parse the given expression. This
|
||||
* method is used by the expression content and model proxy strategies.
|
||||
*
|
||||
* @param parentNode The parent of the nodes to search. If <code>null</code>,
|
||||
* then the top level expressions will be searched.
|
||||
* @param expression The expression object.
|
||||
* @return The matching expression node.
|
||||
*/
|
||||
public IExpressionVMNode findNodeToParseExpression(IExpressionVMNode parentNode, IExpression expression) {
|
||||
IVMNode[] childNOdes;
|
||||
if (parentNode == null) {
|
||||
childNOdes = getExpressionNodes();
|
||||
} else {
|
||||
childNOdes = getChildVMNodes(parentNode);
|
||||
}
|
||||
for (IVMNode childNode : childNOdes) {
|
||||
if (childNode instanceof IExpressionVMNode) {
|
||||
IExpressionVMNode childExpressionNode = (IExpressionVMNode)childNode;
|
||||
if (childExpressionNode.canParseExpression(expression)) {
|
||||
return childExpressionNode;
|
||||
} else if (!childExpressionNode.equals(parentNode)) {
|
||||
// The above check is to make sure that child isn't the same as
|
||||
// parent to avoid recursive loops.
|
||||
IExpressionVMNode matchingNode =
|
||||
findNodeToParseExpression(childExpressionNode, expression);
|
||||
if (matchingNode != null) {
|
||||
return matchingNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
DebugPlugin.getDefault().getExpressionManager().removeExpressionListener(this);
|
||||
getPresentationContext().removePropertyChangeListener(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
@ -125,49 +287,42 @@ public class ExpressionVMProvider extends AbstractDebugDMVMProviderWithCache imp
|
|||
return ExpressionColumnPresentation.ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this operation to avoid the standard test of isOurLayoutNode(),
|
||||
* which does not take into account {@link ExpressionManagerLayoutNode.setExpressionLayoutNodes}
|
||||
* nodes.
|
||||
*/
|
||||
@Override
|
||||
protected IVMLayoutNode getLayoutNodeForElement(Object element) {
|
||||
/*
|
||||
* First check to see if the parent object is the root object of the
|
||||
* hierarchy. If that's the case, then retrieve the correcponding
|
||||
* root VMC from the root node, and pass this root vmc to the root's
|
||||
* child layout nodes.
|
||||
*/
|
||||
IVMRootLayoutNode rootLayoutNode = getRootLayoutNode();
|
||||
if (rootLayoutNode == null) {
|
||||
return null;
|
||||
}
|
||||
else if (element.equals(getRootElement())) {
|
||||
return rootLayoutNode;
|
||||
}
|
||||
else if (element instanceof IVMContext){
|
||||
return ((IVMContext)element).getLayoutNode();
|
||||
}
|
||||
return null;
|
||||
protected IVMUpdatePolicy[] createUpdateModes() {
|
||||
return new IVMUpdatePolicy[] { new AutomaticUpdatePolicy(), new ManualUpdatePolicy(), new BreakpointHitUpdatePolicy() };
|
||||
}
|
||||
|
||||
public void propertyChange(PropertyChangeEvent event) {
|
||||
handleEvent(event);
|
||||
}
|
||||
|
||||
public void expressionsAdded(IExpression[] expressions) {
|
||||
handleEvent(new ExpressionsChangedEvent(ExpressionsChangedEvent.Type.ADDED, expressions));
|
||||
}
|
||||
|
||||
public void expressionsChanged(IExpression[] expressions) {
|
||||
handleEvent(new ExpressionsChangedEvent(ExpressionsChangedEvent.Type.CHANGED, expressions));
|
||||
expressionsListChanged(ExpressionsChangedEvent.Type.ADDED);
|
||||
}
|
||||
|
||||
public void expressionsRemoved(IExpression[] expressions) {
|
||||
handleEvent(new ExpressionsChangedEvent(ExpressionsChangedEvent.Type.REMOVED, expressions));
|
||||
expressionsListChanged(ExpressionsChangedEvent.Type.REMOVED);
|
||||
}
|
||||
|
||||
public void expressionsInserted(IExpression[] expressions, int index) {
|
||||
handleEvent(new ExpressionsChangedEvent(ExpressionsChangedEvent.Type.INSERTED, expressions));
|
||||
expressionsListChanged(ExpressionsChangedEvent.Type.INSERTED);
|
||||
}
|
||||
|
||||
public void expressionsMoved(IExpression[] expressions, int index) {
|
||||
handleEvent(new ExpressionsChangedEvent(ExpressionsChangedEvent.Type.MOVED, expressions));
|
||||
expressionsListChanged(ExpressionsChangedEvent.Type.MOVED);
|
||||
}
|
||||
|
||||
public void expressionsChanged(IExpression[] expressions) {
|
||||
Set<Object> expressionsSet = new HashSet<Object>();
|
||||
expressionsSet.addAll(Arrays.asList(expressions));
|
||||
handleEvent(new ExpressionsChangedEvent(ExpressionsChangedEvent.Type.CHANGED, expressionsSet));
|
||||
}
|
||||
|
||||
private void expressionsListChanged(ExpressionsChangedEvent.Type type) {
|
||||
Set<Object> rootElements = new HashSet<Object>();
|
||||
for (IVMModelProxy proxy : getActiveModelProxies()) {
|
||||
rootElements.add(proxy.getRootElement());
|
||||
}
|
||||
handleEvent(new ExpressionsChangedEvent(type, rootElements));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.debug.ui.viewmodel.expression;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.concurrent.ViewerDataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.DefaultVMContentProviderStrategy;
|
||||
|
||||
/**
|
||||
* The IElementContentProvider implementation to be used with an expression
|
||||
* view model provider.
|
||||
*
|
||||
* @see ExpressionVMProvider
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class ExpressionVMProviderContentStragegy extends DefaultVMContentProviderStrategy {
|
||||
public ExpressionVMProviderContentStragegy(ExpressionVMProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
private ExpressionVMProvider getExpressionVMProvider() {
|
||||
return (ExpressionVMProvider)getVMProvider();
|
||||
}
|
||||
|
||||
public void update(final IExpressionUpdate update) {
|
||||
final IExpressionVMNode matchingNode =
|
||||
getExpressionVMProvider().findNodeToParseExpression(null, update.getExpression());
|
||||
|
||||
if (matchingNode != null) {
|
||||
updateExpressionWithNode(matchingNode, update);
|
||||
} else {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, "Cannot parse expression", null)); //$NON-NLS-1$
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateExpressionWithNode(final IExpressionVMNode node, final IExpressionUpdate update) {
|
||||
// Call the expression node to parse the expression and fill in the value.
|
||||
node.update(
|
||||
new VMExpressionUpdate(
|
||||
update, update.getExpression(),
|
||||
new ViewerDataRequestMonitor<Object>(getVMProvider().getExecutor(), update) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
// Check if the evaluated node has child expression nodes.
|
||||
// If it does, check if any of those nodes can evaluate the given
|
||||
// expression further. If they can, call the child node to further
|
||||
// process the expression. Otherwise we found our element and
|
||||
// we're done.
|
||||
final IExpressionVMNode matchingNode = getExpressionVMProvider().
|
||||
findNodeToParseExpression(node, update.getExpression());
|
||||
|
||||
if (matchingNode != null && !matchingNode.equals(node)) {
|
||||
updateExpressionWithNode(
|
||||
matchingNode,
|
||||
new VMExpressionUpdate(
|
||||
update.getElementPath().createChildPath(getData()), update.getViewerInput(),
|
||||
update.getPresentationContext(), update.getExpression(),
|
||||
new ViewerDataRequestMonitor<Object>(getVMProvider().getExecutor(), update) {
|
||||
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
update.setExpressionElement(getData());
|
||||
update.done();
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
update.setExpressionElement(getData());
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.debug.ui.viewmodel.expression;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.DefaultVMModelProxyStrategy;
|
||||
import org.eclipse.debug.core.model.IExpression;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* The IModelProxy implementation to be used with an expression
|
||||
* view model provider.
|
||||
*
|
||||
* @see ExpressionVMProvider
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class ExpressionVMProviderModelProxyStrategy extends DefaultVMModelProxyStrategy {
|
||||
|
||||
public ExpressionVMProviderModelProxyStrategy(ExpressionVMProvider provider, Object rootElement) {
|
||||
super(provider, rootElement);
|
||||
}
|
||||
|
||||
private ExpressionVMProvider getExpressionVMProvider() {
|
||||
return (ExpressionVMProvider)getVMProvider();
|
||||
}
|
||||
|
||||
public int getDeltaFlagsForExpression(IExpression expression, Object event) {
|
||||
final IExpressionVMNode matchingNode = getExpressionVMProvider().findNodeToParseExpression(null, expression);
|
||||
|
||||
if (matchingNode != null) {
|
||||
return getNodeDeltaFlagsForExpression(matchingNode, expression, event);
|
||||
}
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
private int getNodeDeltaFlagsForExpression(IExpressionVMNode node, IExpression expression, Object event) {
|
||||
int flags = node.getDeltaFlagsForExpression(expression, event);
|
||||
|
||||
IExpressionVMNode matchingNode = getExpressionVMProvider().findNodeToParseExpression(node, expression);
|
||||
if (matchingNode != null && !matchingNode.equals(node)) {
|
||||
flags = flags | getNodeDeltaFlagsForExpression(matchingNode, expression, event);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
public void buildDeltaForExpression(IExpression expression, int expressionElementIdx, Object event,
|
||||
ModelDelta parentDelta, TreePath path, RequestMonitor rm)
|
||||
{
|
||||
final IExpressionVMNode matchingNode = getExpressionVMProvider().findNodeToParseExpression(null, expression);
|
||||
|
||||
if (matchingNode != null) {
|
||||
buildNodeDeltaForExpression(matchingNode, expression, expressionElementIdx, event,
|
||||
parentDelta, path, rm);
|
||||
} else {
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
private void buildNodeDeltaForExpression(final IExpressionVMNode node, final IExpression expression,
|
||||
final int expressionElementIdx, final Object event, final ModelDelta parentDelta, final TreePath path,
|
||||
final RequestMonitor rm)
|
||||
{
|
||||
node.buildDeltaForExpression(
|
||||
expression, expressionElementIdx, event, parentDelta, path,
|
||||
new RequestMonitor(getVMProvider().getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
final IExpressionVMNode matchingNode =
|
||||
getExpressionVMProvider().findNodeToParseExpression(node, expression);
|
||||
if (matchingNode != null && !matchingNode.equals(node)) {
|
||||
buildNodeDeltaForExpression(
|
||||
matchingNode, expression, expressionElementIdx, event, parentDelta, path, rm);
|
||||
} else {
|
||||
getExpressionVMProvider().update(new VMExpressionUpdate(
|
||||
parentDelta, getVMProvider().getPresentationContext(), expression,
|
||||
new DataRequestMonitor<Object>(getVMProvider().getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
buildDeltaForExpressionElement(
|
||||
node, getData(), expressionElementIdx, event, parentDelta, path, rm);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleError() {
|
||||
// Avoid propagating the error to avoid processing the delta by
|
||||
// all nodes.
|
||||
rm.done();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void buildDeltaForExpressionElement(final IExpressionVMNode node, Object expressionElement,
|
||||
final int expressionElementIdx, final Object event, final ModelDelta parentDelta, final TreePath path,
|
||||
final RequestMonitor rm)
|
||||
{
|
||||
CountingRequestMonitor multiRm = new CountingRequestMonitor(getVMProvider().getExecutor(), rm);
|
||||
int multiRmCount = 0;
|
||||
|
||||
node.buildDeltaForExpressionElement(expressionElement, expressionElementIdx, event, parentDelta, multiRm);
|
||||
multiRmCount++;
|
||||
|
||||
// Find the child nodes that have deltas for the given event.
|
||||
Map<IVMNode,Integer> childNodesWithDeltaFlags = getChildNodesWithDeltaFlags(node, parentDelta, event);
|
||||
|
||||
// If no child layout nodes have deltas we can stop here.
|
||||
if (childNodesWithDeltaFlags.size() != 0) {
|
||||
callChildNodesToBuildDelta(
|
||||
node, childNodesWithDeltaFlags,
|
||||
parentDelta.addNode(expressionElement, expressionElementIdx, IModelDelta.NO_CHANGE),
|
||||
event, multiRm);
|
||||
multiRmCount++;
|
||||
}
|
||||
|
||||
multiRm.setDoneCount(multiRmCount);
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.debug.ui.viewmodel.expression;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.debug.core.model.IExpression;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* Interface for layout nodes that can be used within the expression view.
|
||||
* The methods of this interface allow the {@link ExpressionManagerLayoutNode}
|
||||
* to use this layout node to delegate expression parsing to this node, and to
|
||||
* generate deltas for expressions that are owned by this node.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public interface IExpressionLayoutNode extends IVMLayoutNode {
|
||||
|
||||
/**
|
||||
* Returns the length of the portion of the expression that can be parsed
|
||||
* by this node.
|
||||
* @param expression String to parse
|
||||
* @return length of the expression recognized by this node. Length of less than 1
|
||||
* indicates that this node cannot parse this expression.
|
||||
*/
|
||||
int getExpressionLength(String expression);
|
||||
|
||||
/**
|
||||
* Retrieves the element for the given expression. The node implementing
|
||||
* this method should parse the expression and set a valid view model
|
||||
* context (VMC) element in the update provided as an argument.
|
||||
* @param update to fill in with the element. The tree path in this update
|
||||
* object may contain elements which are not actually displayed in the viewer.
|
||||
* These element may have been added to the original path by other expression
|
||||
* layout nodes that have parsed preceding parts of the expression.
|
||||
* @param expressionText expression string to parse
|
||||
* @param expression expression object that the returned element should contain
|
||||
*/
|
||||
void getElementForExpression(IChildrenUpdate update, String expressionText, IExpression expression);
|
||||
|
||||
int getDeltaFlagsForExpression(String expressionText, Object event);
|
||||
|
||||
void buildDeltaForExpression(IExpression expression, int elementIdx, String expressionText, Object event,
|
||||
VMDelta parentDelta, TreePath path, RequestMonitor rm);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.debug.ui.viewmodel.expression;
|
||||
|
||||
import org.eclipse.debug.core.model.IExpression;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
|
||||
/**
|
||||
* An update for an element based on the given expression. The provider processing
|
||||
* this update needs to create an expression element based on the tree path and the
|
||||
* expression object in this update.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public interface IExpressionUpdate extends IViewerUpdate {
|
||||
|
||||
/**
|
||||
* Returns the expression object for this update.
|
||||
*/
|
||||
public IExpression getExpression();
|
||||
|
||||
/**
|
||||
* Sets the element to the update. The element is to be calculated by the provider
|
||||
* handling the update.
|
||||
*/
|
||||
public void setExpressionElement(Object element);
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.debug.ui.viewmodel.expression;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.debug.core.model.IExpression;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* Interface for view model nodes that can be used within the expression view.
|
||||
* The methods of this interface allow the {@link ExpressionManagerVMNode}
|
||||
* to use this node to delegate expression parsing to this node, and to
|
||||
* generate deltas for expressions that are owned by this node.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public interface IExpressionVMNode extends IVMNode {
|
||||
|
||||
/**
|
||||
* Returns whether the given expression node recognizes and can parse the given
|
||||
* expression.
|
||||
* @param expression Expression that needs to be parsed.
|
||||
* @return true if expression can be parsed
|
||||
*/
|
||||
public boolean canParseExpression(IExpression expression);
|
||||
|
||||
/**
|
||||
* Asynchronously fills in the given expression update.
|
||||
* @param update Update to complete.
|
||||
*/
|
||||
public void update(IExpressionUpdate update);
|
||||
|
||||
/**
|
||||
* Returns the flags that this node can generate for the given expression and
|
||||
* event.
|
||||
*/
|
||||
public int getDeltaFlagsForExpression(IExpression expression, Object event);
|
||||
|
||||
/**
|
||||
* Adds delta flags to the given parent delta based on the expression object
|
||||
* given.
|
||||
*/
|
||||
public void buildDeltaForExpression(IExpression expression, int elementIdx, Object event, ModelDelta parentDelta,
|
||||
TreePath path, RequestMonitor rm);
|
||||
|
||||
/**
|
||||
* Adds delta to the given parent delta based on the given element which was created base on
|
||||
* an expression parsed by this node.
|
||||
*/
|
||||
public void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, ModelDelta parentDelta, final RequestMonitor rm);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.debug.ui.viewmodel.expression;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.DsfUIPlugin;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMViewerUpdate;
|
||||
import org.eclipse.debug.core.model.IExpression;
|
||||
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.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
class VMExpressionUpdate extends VMViewerUpdate implements IExpressionUpdate {
|
||||
|
||||
private final IExpression fExpression;
|
||||
private Object fExpressionElement;
|
||||
|
||||
public VMExpressionUpdate(IViewerUpdate clientUpdate, IExpression expression, DataRequestMonitor<Object> rm)
|
||||
{
|
||||
super(clientUpdate, rm);
|
||||
fExpression = expression;
|
||||
}
|
||||
|
||||
public VMExpressionUpdate(IModelDelta delta, IPresentationContext presentationContext, IExpression expression, DataRequestMonitor<Object> rm)
|
||||
{
|
||||
super(delta, presentationContext, rm);
|
||||
fExpression = expression;
|
||||
}
|
||||
|
||||
public VMExpressionUpdate(TreePath elementPath, Object viewerInput, IPresentationContext presentationContext, IExpression expression, DataRequestMonitor<Object> rm)
|
||||
{
|
||||
super(elementPath, viewerInput, presentationContext, rm);
|
||||
fExpression = expression;
|
||||
}
|
||||
|
||||
|
||||
public IExpression getExpression() {
|
||||
return fExpression;
|
||||
}
|
||||
|
||||
|
||||
public void setExpressionElement(Object element) {
|
||||
fExpressionElement = element;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VMExpressionUpdate for elements under parent = " + getElement() + ", in for expression " + getExpression().getExpressionText(); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
DataRequestMonitor<Object> rm = (DataRequestMonitor<Object>)getRequestMonitor();
|
||||
if (fExpressionElement != null) {
|
||||
rm.setData(fExpressionElement);
|
||||
} else if (rm.getStatus().isOK()) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, "Incomplete elements of updates", null)); //$NON-NLS-1$
|
||||
}
|
||||
super.done();
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ package org.eclipse.dd.dsf.debug.ui.viewmodel.expression;
|
|||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.dd.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.ExpressionManagerLayoutNode.NewExpressionVMC;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.ExpressionManagerVMNode.NewExpressionVMC;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.IExpressionManager;
|
||||
import org.eclipse.debug.core.model.IWatchExpression;
|
||||
|
@ -22,7 +22,6 @@ import org.eclipse.jface.viewers.ICellModifier;
|
|||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
@ThreadSafeAndProhibitedFromDsfExecutor("")
|
||||
public class WatchExpressionCellModifier implements ICellModifier {
|
||||
|
||||
|
|
|
@ -12,15 +12,15 @@ package org.eclipse.dd.dsf.debug.ui.viewmodel.launch;
|
|||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.RootVMNode;
|
||||
import org.eclipse.debug.core.DebugEvent;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
|
@ -28,6 +28,7 @@ import org.eclipse.debug.core.ILaunchManager;
|
|||
import org.eclipse.debug.core.model.IDebugElement;
|
||||
import org.eclipse.debug.core.model.IProcess;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
|
||||
/**
|
||||
* Layout node for the standard ILaunch object. This node can only be used at
|
||||
|
@ -35,8 +36,8 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
|||
* functionality, so the default adapters should be used to retrieve the label.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class StandardLaunchRootLayoutNode extends VMRootLayoutNode
|
||||
implements IVMRootLayoutNode
|
||||
public class LaunchRootVMNode extends RootVMNode
|
||||
implements IRootVMNode
|
||||
{
|
||||
public static class LaunchesEvent {
|
||||
public enum Type { ADDED, REMOVED, CHANGED, TERMINATED }
|
||||
|
@ -49,92 +50,76 @@ public class StandardLaunchRootLayoutNode extends VMRootLayoutNode
|
|||
}
|
||||
}
|
||||
|
||||
final private ILaunch fLaunch;
|
||||
|
||||
public StandardLaunchRootLayoutNode(AbstractVMProvider provider, ILaunch launch) {
|
||||
public LaunchRootVMNode(AbstractVMProvider provider) {
|
||||
super(provider);
|
||||
fLaunch = launch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeltaEvent(Object rootObject, Object e) {
|
||||
if (e instanceof DebugEvent) {
|
||||
DebugEvent de = (DebugEvent)e;
|
||||
if (de.getSource() instanceof IProcess &&
|
||||
!((IProcess)de.getSource()).getLaunch().equals(rootObject) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (de.getSource() instanceof IDebugElement &&
|
||||
!rootObject.equals(((IDebugElement)de.getSource()).getLaunch()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDeltaFlags(Object e) {
|
||||
if (e instanceof DebugEvent) {
|
||||
DebugEvent de = (DebugEvent)e;
|
||||
if (de.getSource() instanceof IProcess &&
|
||||
!((IProcess)de.getSource()).getLaunch().equals(fLaunch) )
|
||||
{
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
else if (de.getSource() instanceof IDebugElement &&
|
||||
!fLaunch.equals(((IDebugElement)de.getSource()).getLaunch()))
|
||||
{
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
}
|
||||
int flags = 0;
|
||||
if (e instanceof LaunchesEvent) {
|
||||
LaunchesEvent le = (LaunchesEvent)e;
|
||||
for (ILaunch launch : le.fLaunches) {
|
||||
if (fLaunch == launch) {
|
||||
if (le.fType == LaunchesEvent.Type.CHANGED) {
|
||||
flags = IModelDelta.STATE | IModelDelta.CONTENT;
|
||||
} else if (le.fType == LaunchesEvent.Type.TERMINATED) {
|
||||
flags = IModelDelta.STATE | IModelDelta.CONTENT;
|
||||
}
|
||||
}
|
||||
if (le.fType == LaunchesEvent.Type.CHANGED || le.fType == LaunchesEvent.Type.TERMINATED) {
|
||||
flags = IModelDelta.STATE | IModelDelta.CONTENT;
|
||||
}
|
||||
}
|
||||
|
||||
return flags | super.getDeltaFlags(e);
|
||||
return flags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createDelta(Object event, final DataRequestMonitor<IModelDelta> rm) {
|
||||
public void createRootDelta(Object rootObject, Object event, final DataRequestMonitor<ModelDelta> rm) {
|
||||
if (!(rootObject instanceof ILaunch)) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Invalid root element configured with launch root node.", null)); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
|
||||
ILaunch rootLaunch = (ILaunch)rootObject;
|
||||
|
||||
/*
|
||||
* Create the root of the delta. Since the launch object is not at the
|
||||
* root of the view, create the delta with the path to the launch, then
|
||||
* pass that to the child layout nodes.
|
||||
* root of the view, create the delta with the path to the launch.
|
||||
*/
|
||||
ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
|
||||
List<ILaunch> launchList = Arrays.asList(manager.getLaunches());
|
||||
final VMDelta viewRootDelta = new VMDelta(manager, 0, IModelDelta.NO_CHANGE, launchList.size());
|
||||
final VMDelta rootDelta = viewRootDelta.addNode(getRootObject(), launchList.indexOf(fLaunch), IModelDelta.NO_CHANGE);
|
||||
final ModelDelta viewRootDelta = new ModelDelta(manager, 0, IModelDelta.NO_CHANGE, launchList.size());
|
||||
final ModelDelta rootDelta = viewRootDelta.addNode(rootLaunch, launchList.indexOf(rootLaunch), IModelDelta.NO_CHANGE);
|
||||
|
||||
// Generate delta for launch node.
|
||||
if (event instanceof LaunchesEvent) {
|
||||
LaunchesEvent le = (LaunchesEvent)event;
|
||||
for (ILaunch launch : le.fLaunches) {
|
||||
if (fLaunch == launch) {
|
||||
if (rootLaunch == launch) {
|
||||
if (le.fType == LaunchesEvent.Type.CHANGED) {
|
||||
rootDelta.addFlags(IModelDelta.STATE | IModelDelta.CONTENT);
|
||||
rootDelta.setFlags(rootDelta.getFlags() | IModelDelta.STATE | IModelDelta.CONTENT);
|
||||
} else if (le.fType == LaunchesEvent.Type.TERMINATED) {
|
||||
rootDelta.addFlags(IModelDelta.STATE | IModelDelta.CONTENT);
|
||||
rootDelta.setFlags(rootDelta.getFlags() | IModelDelta.STATE | IModelDelta.CONTENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call the child nodes to generate their delta.
|
||||
Map<IVMLayoutNode,Integer> childNodeDeltas = getChildNodesWithDeltaFlags(event);
|
||||
if (childNodeDeltas.size() != 0) {
|
||||
callChildNodesToBuildDelta(
|
||||
childNodeDeltas, rootDelta, event,
|
||||
new RequestMonitor(getExecutor(), rm) {
|
||||
@Override
|
||||
public void handleOK() {
|
||||
if (isDisposed()) return;
|
||||
rm.setData(viewRootDelta);
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rm.setData(viewRootDelta);
|
||||
rm.done();
|
||||
}
|
||||
rm.setData(rootDelta);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRootObject() {
|
||||
return fLaunch;
|
||||
}
|
||||
}
|
|
@ -11,11 +11,12 @@
|
|||
package org.eclipse.dd.dsf.debug.ui.viewmodel.launch;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IStack;
|
||||
import org.eclipse.dd.dsf.debug.service.IStepQueueManager;
|
||||
|
@ -28,50 +29,51 @@ import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
|
|||
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMData;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMChildrenUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
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.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.debug.ui.DebugUITools;
|
||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
|
||||
public class StackFramesVMNode extends AbstractDMVMNode
|
||||
implements IElementLabelProvider
|
||||
{
|
||||
|
||||
public IVMContext[] fCachedOldFrameVMCs;
|
||||
|
||||
public StackFramesLayoutNode(AbstractVMProvider provider, DsfSession session) {
|
||||
public StackFramesVMNode(AbstractDMVMProvider provider, DsfSession session) {
|
||||
super(provider, session, IStack.IFrameDMContext.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateHasElementsInSessionThread(IHasChildrenUpdate[] updates) {
|
||||
protected void updateHasElementsInSessionThread(IHasChildrenUpdate update) {
|
||||
if (!checkService(IStack.class, null, update)) return;
|
||||
|
||||
for (IHasChildrenUpdate update : updates) {
|
||||
if (!checkService(IStack.class, null, update)) return;
|
||||
|
||||
IExecutionDMContext execDmc = findDmcInPath(update.getElementPath(), IExecutionDMContext.class);
|
||||
if (execDmc == null) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
update.setHasChilren(getServicesTracker().getService(IStack.class).isStackAvailable(execDmc));
|
||||
update.done();
|
||||
IExecutionDMContext execDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class);
|
||||
if (execDmc == null) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
update.setHasChilren(getServicesTracker().getService(IStack.class).isStackAvailable(execDmc));
|
||||
update.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
if (!checkService(IStack.class, null, update)) return;
|
||||
|
||||
final IExecutionDMContext execDmc = findDmcInPath(update.getElementPath(), IExecutionDMContext.class);
|
||||
final IExecutionDMContext execDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class);
|
||||
if (execDmc == null) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
|
@ -110,7 +112,7 @@ public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
|
|||
* @see #getElements(IVMContext, DataRequestMonitor)
|
||||
*/
|
||||
private void getElementsTopStackFrameOnly(final IChildrenUpdate update) {
|
||||
final IExecutionDMContext execDmc = findDmcInPath(update.getElementPath(), IExecutionDMContext.class);
|
||||
final IExecutionDMContext execDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class);
|
||||
if (execDmc == null) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
|
@ -118,7 +120,7 @@ public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
|
|||
|
||||
getServicesTracker().getService(IStack.class).getTopFrame(
|
||||
execDmc,
|
||||
new DataRequestMonitor<IFrameDMContext>(getSession().getExecutor(), null) {
|
||||
new DataRequestMonitor<IFrameDMContext>(getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
|
@ -126,7 +128,7 @@ public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
|
|||
return;
|
||||
}
|
||||
|
||||
IVMContext topFrameVmc = new DMVMContext(getData());
|
||||
IVMContext topFrameVmc = createVMContext(getData());
|
||||
|
||||
update.setChild(topFrameVmc, 0);
|
||||
// If there are old frames cached, use them and only substitute the top frame object. Otherwise, create
|
||||
|
@ -143,14 +145,29 @@ public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public void update(final ILabelUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updateLabelInSessionThread(updates);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (ILabelUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
final IFrameDMContext dmc = findDmcInPath(update.getElementPath(), IFrameDMContext.class);
|
||||
final IFrameDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IFrameDMContext.class);
|
||||
if (!checkDmc(dmc, update) || !checkService(IStack.class, null, update)) continue;
|
||||
|
||||
VMCacheManager.getVMCacheManager().getCache(update.getPresentationContext())
|
||||
.getModelData(getServicesTracker().getService(IStack.class, null),
|
||||
getDMVMProvider().getModelData(
|
||||
this, update,
|
||||
getServicesTracker().getService(IStack.class, null),
|
||||
dmc,
|
||||
new DataRequestMonitor<IFrameDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
|
@ -190,7 +207,7 @@ public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
|
|||
{
|
||||
if (idx != 0) return;
|
||||
|
||||
final IExecutionDMContext execDmc = findDmcInPath(update.getElementPath(), IExecutionDMContext.class);
|
||||
final IExecutionDMContext execDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class);
|
||||
IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
|
||||
IStepQueueManager stepQueueMgrService = getServicesTracker().getService(IStepQueueManager.class);
|
||||
if (execDmc == null || runControlService == null || stepQueueMgrService == null) return;
|
||||
|
@ -253,8 +270,7 @@ public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected int getNodeDeltaFlagsForDMEvent(org.eclipse.dd.dsf.datamodel.IDMEvent<?> e) {
|
||||
public int getDeltaFlags(Object e) {
|
||||
// This node generates delta if the timers have changed, or if the
|
||||
// label has changed.
|
||||
if (e instanceof ISuspendedDMEvent) {
|
||||
|
@ -268,15 +284,14 @@ public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
|
|||
} else if (e instanceof IStepQueueManager.ISteppingTimedOutEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
return 0;
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildDeltaForDMEvent(final IDMEvent<?> e, final VMDelta parent, final int nodeOffset, final RequestMonitor rm) {
|
||||
public void buildDelta(final Object e, final ModelDelta parent, final int nodeOffset, final RequestMonitor rm) {
|
||||
if (e instanceof IContainerSuspendedDMEvent) {
|
||||
IExecutionDMContext threadDmc = null;
|
||||
if (parent.getElement() instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
threadDmc = DMContexts.getAncestorOfType( ((DMVMContext)parent.getElement()).getDMC(), IExecutionDMContext.class);
|
||||
if (parent.getElement() instanceof IDMVMContext) {
|
||||
threadDmc = DMContexts.getAncestorOfType( ((IDMVMContext)parent.getElement()).getDMContext(), IExecutionDMContext.class);
|
||||
}
|
||||
buildDeltaForSuspendedEvent((ISuspendedDMEvent)e, threadDmc, ((IContainerSuspendedDMEvent)e).getTriggeringContext(), parent, nodeOffset, rm);
|
||||
} else if (e instanceof ISuspendedDMEvent) {
|
||||
|
@ -287,17 +302,16 @@ public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
|
|||
} else if (e instanceof IStepQueueManager.ISteppingTimedOutEvent) {
|
||||
buildDeltaForSteppingTimedOutEvent((IStepQueueManager.ISteppingTimedOutEvent)e, parent, nodeOffset, rm);
|
||||
} else {
|
||||
// Call super-class to build sub-node delta's.
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
private void buildDeltaForSuspendedEvent(final ISuspendedDMEvent e, final IExecutionDMContext executionCtx, final IExecutionDMContext triggeringCtx, final VMDelta parent, final int nodeOffset, final RequestMonitor rm) {
|
||||
private void buildDeltaForSuspendedEvent(final ISuspendedDMEvent e, final IExecutionDMContext executionCtx, final IExecutionDMContext triggeringCtx, final ModelDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
|
||||
IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
|
||||
IStack stackService = getServicesTracker().getService(IStack.class);
|
||||
if (stackService == null || runControlService == null) {
|
||||
// Required services have not initialized yet. Ignore the event.
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -305,46 +319,45 @@ public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
|
|||
// which case, the refresh will occur when the stepping sequence slows down or stops. Trying to
|
||||
// refresh the whole stack trace with every step would slow down stepping too much.
|
||||
if (!runControlService.isStepping(triggeringCtx)) {
|
||||
parent.addFlags(IModelDelta.CONTENT);
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
// Check if we are building a delta for the thread that triggered the event.
|
||||
// Only then expand the stack frames and select the top one.
|
||||
if (executionCtx.equals(triggeringCtx)) {
|
||||
// Always expand the thread node to show the stack frames.
|
||||
parent.addFlags(IModelDelta.EXPAND);
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.EXPAND);
|
||||
|
||||
// Retrieve the list of stack frames, and mark the top frame to be selected.
|
||||
getElementsTopStackFrameOnly(
|
||||
new ElementsUpdate(
|
||||
new DataRequestMonitor<List<Object>>(getSession().getExecutor(), null) {
|
||||
new VMChildrenUpdate(
|
||||
parentDelta, getVMProvider().getPresentationContext(), -1, -1,
|
||||
new DataRequestMonitor<List<Object>>(getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (getStatus().isOK() && getData().size() != 0) {
|
||||
parent.addNode( getData().get(0), IModelDelta.SELECT | IModelDelta.STATE);
|
||||
parentDelta.addNode( getData().get(0), 0, IModelDelta.SELECT | IModelDelta.STATE);
|
||||
// If second frame is available repaint it, so that a "..." appears. This gives a better
|
||||
// impression that the frames are not up-to date.
|
||||
if (getData().size() >= 2) {
|
||||
parent.addNode( getData().get(1), IModelDelta.STATE);
|
||||
parentDelta.addNode( getData().get(1), 1, IModelDelta.STATE);
|
||||
}
|
||||
}
|
||||
// Even in case of errors, call super-class to complete building of the delta.
|
||||
StackFramesLayoutNode.super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
// Even in case of errors, complete the request monitor.
|
||||
rm.done();
|
||||
}
|
||||
},
|
||||
parent)
|
||||
})
|
||||
);
|
||||
} else {
|
||||
// Don't forget to call the super class to complete building the delta (and call child nodes.)
|
||||
StackFramesLayoutNode.super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
private void buildDeltaForResumedEvent(final IResumedDMEvent e, final VMDelta parent, final int nodeOffset, final RequestMonitor rm) {
|
||||
private void buildDeltaForResumedEvent(final IResumedDMEvent e, final ModelDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
|
||||
IStack stackService = getServicesTracker().getService(IStack.class);
|
||||
if (stackService == null) {
|
||||
// Required services have not initialized yet. Ignore the event.
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -352,15 +365,15 @@ public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
|
|||
if (resumedEvent.getReason() != StateChangeReason.STEP) {
|
||||
// Refresh the list of stack frames only if the run operation is not a step. Also, clear the list
|
||||
// of cached frames.
|
||||
parent.addFlags(IModelDelta.CONTENT);
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
fCachedOldFrameVMCs = null;
|
||||
}
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
private void buildDeltaForSteppingTimedOutEvent(final IStepQueueManager.ISteppingTimedOutEvent e, final VMDelta parent, final int nodeOffset, final RequestMonitor rm) {
|
||||
private void buildDeltaForSteppingTimedOutEvent(final IStepQueueManager.ISteppingTimedOutEvent e, final ModelDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
|
||||
// Repaint the stack frame images to have the running symbol.
|
||||
parent.addFlags(IModelDelta.CONTENT);
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
rm.done();
|
||||
}
|
||||
}
|
|
@ -11,11 +11,11 @@
|
|||
package org.eclipse.dd.dsf.debug.ui.viewmodel.launch;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.debug.core.DebugEvent;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
|
@ -25,6 +25,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpd
|
|||
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.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
|
@ -35,7 +36,7 @@ import org.eclipse.jface.viewers.TreePath;
|
|||
* adapters should be used to retrieve the label.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
|
||||
public class StandardProcessVMNode extends AbstractVMNode {
|
||||
|
||||
/**
|
||||
* VMC element implementation, it is a proxy for the IProcess class, to
|
||||
|
@ -47,12 +48,12 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
|
|||
private final IProcess fProcess;
|
||||
|
||||
VMC(IProcess process) {
|
||||
super(getVMProvider().getVMAdapter(), StandardProcessLayoutNode.this);
|
||||
super(getVMProvider().getVMAdapter(), StandardProcessVMNode.this);
|
||||
fProcess = process;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IVMLayoutNode getLayoutNode() { return StandardProcessLayoutNode.this; }
|
||||
public IVMNode getVMNode() { return StandardProcessVMNode.this; }
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getAdapter(Class adapter) {
|
||||
|
@ -83,46 +84,51 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
|
|||
public int hashCode() { return fProcess.hashCode(); }
|
||||
}
|
||||
|
||||
public StandardProcessLayoutNode(AbstractVMProvider provider) {
|
||||
public StandardProcessVMNode(AbstractVMProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
public void updateElements(IChildrenUpdate update) {
|
||||
ILaunch launch = findLaunch(update.getElementPath());
|
||||
if (launch == null) {
|
||||
// There is no launch in the parent of this node. This means that the
|
||||
// layout is misconfigured.
|
||||
assert false;
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
public void update(IChildrenUpdate[] updates) {
|
||||
for (IChildrenUpdate update : updates) {
|
||||
ILaunch launch = findLaunch(update.getElementPath());
|
||||
if (launch == null) {
|
||||
// There is no launch in the parent of this node. This means that the
|
||||
// layout is misconfigured.
|
||||
assert false;
|
||||
update.done();
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assume that the process objects are stored within the launch, and
|
||||
* retrieve them on dispatch thread.
|
||||
*/
|
||||
IProcess[] processes = launch.getProcesses();
|
||||
for (int i = 0; i < processes.length; i++) {
|
||||
update.setChild(new VMC(processes[i]), i);
|
||||
/*
|
||||
* Assume that the process objects are stored within the launch, and
|
||||
* retrieve them on dispatch thread.
|
||||
*/
|
||||
IProcess[] processes = launch.getProcesses();
|
||||
for (int i = 0; i < processes.length; i++) {
|
||||
update.setChild(new VMC(processes[i]), i);
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
|
||||
public void updateElementCount(IChildrenCountUpdate update) {
|
||||
ILaunch launch = findLaunch(update.getElementPath());
|
||||
if (launch == null) {
|
||||
assert false;
|
||||
update.setChildCount(0);
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
public void update(final IChildrenCountUpdate[] updates) {
|
||||
for (IChildrenCountUpdate update : updates) {
|
||||
if (!checkUpdate(update)) continue;
|
||||
ILaunch launch = findLaunch(update.getElementPath());
|
||||
if (launch == null) {
|
||||
assert false;
|
||||
update.setChildCount(0);
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
|
||||
update.setChildCount(launch.getProcesses().length);
|
||||
update.done();
|
||||
update.setChildCount(launch.getProcesses().length);
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
|
||||
// @see org.eclipse.dd.dsf.ui.viewmodel.IViewModelLayoutNode#hasElements(org.eclipse.dd.dsf.ui.viewmodel.IVMContext, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
|
||||
public void updateHasElements(IHasChildrenUpdate[] updates) {
|
||||
public void update(IHasChildrenUpdate[] updates) {
|
||||
for (IHasChildrenUpdate update : updates) {
|
||||
ILaunch launch = findLaunch(update.getElementPath());
|
||||
if (launch == null) {
|
||||
|
@ -138,7 +144,7 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
|
|||
}
|
||||
|
||||
// @see org.eclipse.dd.dsf.ui.viewmodel.IViewModelLayoutNode#retrieveLabel(org.eclipse.dd.dsf.ui.viewmodel.IVMContext, org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor)
|
||||
public void updateLabel(@SuppressWarnings("unused")IVMContext vmc, ILabelRequestMonitor result, @SuppressWarnings("unused") String[] columns) {
|
||||
public void updateLabel(IVMContext vmc, ILabelRequestMonitor result, String[] columns) {
|
||||
|
||||
/*
|
||||
* The implementation of IAdapterFactory that uses this node should not
|
||||
|
@ -163,7 +169,6 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDeltaFlags(Object e) {
|
||||
int myFlags = 0;
|
||||
if (e instanceof DebugEvent) {
|
||||
|
@ -176,11 +181,10 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
|
|||
myFlags = IModelDelta.STATE;
|
||||
}
|
||||
}
|
||||
return myFlags | super.getDeltaFlags(e);
|
||||
return myFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildDelta(Object e, VMDelta parent, int nodeOffset, RequestMonitor requestMonitor) {
|
||||
public void buildDelta(Object e, ModelDelta parent, int nodeOffset, RequestMonitor requestMonitor) {
|
||||
if (e instanceof DebugEvent && ((DebugEvent)e).getSource() instanceof IProcess) {
|
||||
DebugEvent de = (DebugEvent)e;
|
||||
if (de.getKind() == DebugEvent.CHANGE) {
|
||||
|
@ -194,21 +198,19 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
|
|||
* No other node should need to process events related to process.
|
||||
* Therefore, just invoke the request monitor without calling super.buildDelta().
|
||||
*/
|
||||
requestMonitor.done();
|
||||
} else {
|
||||
super.buildDelta(e, parent, nodeOffset, requestMonitor);
|
||||
}
|
||||
requestMonitor.done();
|
||||
}
|
||||
|
||||
protected void handleChange(DebugEvent event, VMDelta parent) {
|
||||
protected void handleChange(DebugEvent event, ModelDelta parent) {
|
||||
parent.addNode(new VMC((IProcess)event.getSource()), IModelDelta.STATE);
|
||||
}
|
||||
|
||||
protected void handleCreate(@SuppressWarnings("unused") DebugEvent event, @SuppressWarnings("unused") VMDelta parent) {
|
||||
protected void handleCreate(DebugEvent event, ModelDelta parent) {
|
||||
// do nothing - Launch change notification handles this
|
||||
}
|
||||
|
||||
protected void handleTerminate(DebugEvent event, VMDelta parent) {
|
||||
protected void handleTerminate(DebugEvent event, ModelDelta parent) {
|
||||
handleChange(event, parent);
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.detail.TextViewerActio
|
|||
import org.eclipse.dd.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.debug.core.model.IDebugElement;
|
||||
import org.eclipse.debug.internal.ui.DebugUIPlugin;
|
||||
import org.eclipse.debug.internal.ui.IDebugHelpContextIds;
|
||||
|
@ -389,8 +389,8 @@ public class ModuleDetailPane extends AbstractDetailPane implements IAdaptable,
|
|||
// service.getModuleData(modDmc, modData);
|
||||
// }
|
||||
IModuleDMContext dmc = null;
|
||||
if (fElement instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
IDMContext vmcdmc = ((AbstractDMVMLayoutNode.DMVMContext)fElement).getDMC();
|
||||
if (fElement instanceof IDMVMContext) {
|
||||
IDMContext vmcdmc = ((IDMVMContext)fElement).getDMContext();
|
||||
dmc = DMContexts.getAncestorOfType(vmcdmc, IModuleDMContext.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@ public class ModuleDetailPaneFactory implements IDetailPaneFactory {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Set getDetailPaneTypes(IStructuredSelection selection) {
|
||||
Set possibleIDs = new HashSet(1);
|
||||
public Set<?> getDetailPaneTypes(IStructuredSelection selection) {
|
||||
Set<String> possibleIDs = new HashSet<String>(1);
|
||||
possibleIDs.add(ModuleDetailPane.ID);
|
||||
return possibleIDs;
|
||||
}
|
||||
|
|
|
@ -10,32 +10,34 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.modules;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IModules;
|
||||
import org.eclipse.dd.dsf.debug.service.IRegisters;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IModules.IModuleDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IModules.IModuleDMData;
|
||||
import org.eclipse.dd.dsf.debug.service.IModules.ISymbolDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRegisters.IGroupChangedDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.debug.ui.IDsfDebugUIConstants;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
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.ModelDelta;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class ModulesLayoutNode extends AbstractDMVMLayoutNode
|
||||
public class ModulesVMNode extends AbstractDMVMNode
|
||||
implements IElementLabelProvider
|
||||
{
|
||||
public ModulesLayoutNode(AbstractVMProvider provider, DsfSession session) {
|
||||
public ModulesVMNode(AbstractDMVMProvider provider, DsfSession session) {
|
||||
super(provider, session, IModuleDMContext.class);
|
||||
}
|
||||
|
||||
|
@ -43,7 +45,7 @@ public class ModulesLayoutNode extends AbstractDMVMLayoutNode
|
|||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
if (!checkService(IRegisters.class, null, update)) return;
|
||||
|
||||
final ISymbolDMContext symDmc = findDmcInPath(update.getElementPath(), ISymbolDMContext.class) ;
|
||||
final ISymbolDMContext symDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), ISymbolDMContext.class) ;
|
||||
|
||||
if (symDmc != null) {
|
||||
getServicesTracker().getService(IModules.class).getModules(
|
||||
|
@ -64,10 +66,24 @@ public class ModulesLayoutNode extends AbstractDMVMLayoutNode
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public void update(final ILabelUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updateLabelInSessionThread(updates);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (ILabelUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
final IModuleDMContext dmc = findDmcInPath(update.getElementPath(), IModuleDMContext.class);
|
||||
final IModuleDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IModuleDMContext.class);
|
||||
if (!checkDmc(dmc, update) || !checkService(IModules.class, null, update)) continue;
|
||||
// Use different image for loaded and unloaded symbols when event to report loading of symbols is implemented.
|
||||
update.setImageDescriptor(DsfDebugUIPlugin.getImageDescriptor(IDsfDebugUIConstants.IMG_OBJS_SHARED_LIBRARY_SYMBOLS_LOADED), 0);
|
||||
|
@ -119,41 +135,19 @@ public class ModulesLayoutNode extends AbstractDMVMLayoutNode
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNodeDeltaFlagsForDMEvent(IDMEvent<?> e) {
|
||||
public int getDeltaFlags(Object e) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
else if (e instanceof IRegisters.IGroupsChangedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
else if (e instanceof IRegisters.IGroupChangedDMEvent) {
|
||||
return IModelDelta.STATE;
|
||||
}
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildDeltaForDMEvent(IDMEvent<?> e, VMDelta parent, int nodeOffset, RequestMonitor rm) {
|
||||
public void buildDelta(Object e, ModelDelta parentDelta, int nodeOffset, RequestMonitor rm) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// Create a delta that indicates all groups have changed
|
||||
parent.addFlags(IModelDelta.CONTENT);
|
||||
}
|
||||
else if (e instanceof IRegisters.IGroupsChangedDMEvent) {
|
||||
// flush the cache
|
||||
VMCacheManager.getVMCacheManager().flush(super.getVMProvider().getPresentationContext());
|
||||
|
||||
// Create a delta that indicates all groups have changed
|
||||
parent.addFlags(IModelDelta.CONTENT);
|
||||
}
|
||||
else if (e instanceof IRegisters.IGroupChangedDMEvent) {
|
||||
// flush the cache
|
||||
VMCacheManager.getVMCacheManager().flush(super.getVMProvider().getPresentationContext());
|
||||
|
||||
// Create a delta that indicates that specific group changed
|
||||
parent.addNode( createVMContext(((IGroupChangedDMEvent)e).getDMContext()), IModelDelta.STATE );
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
rm.done();
|
||||
}
|
||||
}
|
|
@ -12,10 +12,10 @@ package org.eclipse.dd.dsf.debug.ui.viewmodel.modules;
|
|||
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.DMVMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.RootDMVMNode;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
/**
|
||||
|
@ -32,17 +32,17 @@ public class ModulesVMProvider extends AbstractDMVMProvider {
|
|||
/*
|
||||
* Create the top level node to deal with the root selection.
|
||||
*/
|
||||
IVMRootLayoutNode debugViewSelection = new DMVMRootLayoutNode(this);
|
||||
IRootVMNode rootNode = new RootDMVMNode(this);
|
||||
|
||||
/*
|
||||
* Create the Group nodes next. They represent the first level shown in the view.
|
||||
*/
|
||||
IVMLayoutNode modulesNode = new ModulesLayoutNode(this, getSession());
|
||||
debugViewSelection.setChildNodes(new IVMLayoutNode[] { modulesNode });
|
||||
IVMNode modulesNode = new ModulesVMNode(this, getSession());
|
||||
addChildNodes(rootNode, new IVMNode[] { modulesNode });
|
||||
|
||||
/*
|
||||
* Now set this schema set as the layout set.
|
||||
*/
|
||||
setRootLayoutNode(debugViewSelection);
|
||||
setRootNode(rootNode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,9 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat;
|
||||
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.dd.dsf.debug.service.IFormattedValues;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode.DMVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.debug.core.model.IDebugElement;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
|
||||
|
@ -126,25 +123,6 @@ public class AbstractSetFormatStyle implements IViewActionDelegate, IDebugContex
|
|||
* Store the new style. So it will be picked up by the view when the view changes.
|
||||
*/
|
||||
context.setProperty( IDebugVMConstants.CURRENT_FORMAT_STORAGE, getFormatStyle() );
|
||||
|
||||
/*
|
||||
* Now go tell the view to update. We do so by finding the VM provider for this view
|
||||
* and telling it to redraw the entire view.
|
||||
*/
|
||||
if (fViewInput instanceof IAdaptable) {
|
||||
IVMAdapter adapter = (IVMAdapter) ((IAdaptable)fViewInput).getAdapter(IVMAdapter.class);
|
||||
|
||||
if ( adapter != null ) {
|
||||
IVMProvider provider = adapter.getVMProvider(context);
|
||||
|
||||
if ( provider != null ) {
|
||||
/*
|
||||
* "null" means redraw the entire view.
|
||||
*/
|
||||
provider.refresh( null );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +147,7 @@ public class AbstractSetFormatStyle implements IViewActionDelegate, IDebugContex
|
|||
|
||||
Object element = ( (IStructuredSelection) selection ).getFirstElement();
|
||||
|
||||
if ( element instanceof DMVMContext ) { fViewInput = element; }
|
||||
if (element instanceof IDMVMContext ) { fViewInput = element; }
|
||||
else {
|
||||
/*
|
||||
* We deliberately do nothing here. A valid structured selection has already been
|
||||
|
@ -202,7 +180,7 @@ public class AbstractSetFormatStyle implements IViewActionDelegate, IDebugContex
|
|||
{
|
||||
fAction.setEnabled(true);
|
||||
}
|
||||
else if ( fViewInput instanceof DMVMContext )
|
||||
else if ( fViewInput instanceof IDMVMContext )
|
||||
{
|
||||
fAction.setEnabled(true);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ import org.eclipse.dd.dsf.debug.service.IRegisters.IBitFieldDMContext;
|
|||
import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterDMContext;
|
||||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode.DMVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.model.IDebugElement;
|
||||
import org.eclipse.debug.core.model.IExpression;
|
||||
|
@ -53,6 +53,7 @@ import org.eclipse.debug.internal.ui.actions.variables.details.DetailPaneMaxLeng
|
|||
import org.eclipse.debug.internal.ui.actions.variables.details.DetailPaneWordWrapAction;
|
||||
import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
|
||||
import org.eclipse.debug.internal.ui.views.variables.IndexedValuePartition;
|
||||
import org.eclipse.debug.internal.ui.views.variables.StatusLineContributionItem;
|
||||
import org.eclipse.debug.internal.ui.views.variables.details.DetailMessages;
|
||||
import org.eclipse.debug.ui.IDebugModelPresentation;
|
||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||
|
@ -65,7 +66,6 @@ import org.eclipse.jface.action.IMenuManager;
|
|||
import org.eclipse.jface.action.IStatusLineManager;
|
||||
import org.eclipse.jface.action.MenuManager;
|
||||
import org.eclipse.jface.action.Separator;
|
||||
import org.eclipse.jface.action.StatusLineContributionItem;
|
||||
import org.eclipse.jface.resource.JFaceResources;
|
||||
import org.eclipse.jface.text.BadLocationException;
|
||||
import org.eclipse.jface.text.Document;
|
||||
|
@ -315,7 +315,7 @@ public class NumberFormatDetailPane implements IDetailPane, IAdaptable, IPropert
|
|||
/*
|
||||
* Make sure this is an element we want to deal with.
|
||||
*/
|
||||
if ( element instanceof DMVMContext) {
|
||||
if (element instanceof IDMVMContext) {
|
||||
IFormattedValues service = null;
|
||||
IFormattedDataDMContext dmc = null ;
|
||||
|
||||
|
@ -341,23 +341,23 @@ public class NumberFormatDetailPane implements IDetailPane, IAdaptable, IPropert
|
|||
* register not the bit field.
|
||||
*/
|
||||
|
||||
DsfServicesTracker tracker = new DsfServicesTracker(DsfDebugUIPlugin.getBundleContext(), ((DMVMContext) element).getDMC().getSessionId());
|
||||
DsfServicesTracker tracker = new DsfServicesTracker(DsfDebugUIPlugin.getBundleContext(), ((IDMVMContext) element).getDMContext().getSessionId());
|
||||
|
||||
IBitFieldDMContext bitfieldDmc = DMContexts.getAncestorOfType(((DMVMContext) element).getDMC(), IBitFieldDMContext.class);
|
||||
IBitFieldDMContext bitfieldDmc = DMContexts.getAncestorOfType(((IDMVMContext) element).getDMContext(), IBitFieldDMContext.class);
|
||||
|
||||
if ( bitfieldDmc != null ) {
|
||||
dmc = bitfieldDmc ;
|
||||
service = tracker.getService(IRegisters.class);
|
||||
}
|
||||
else {
|
||||
IRegisterDMContext regDmc = DMContexts.getAncestorOfType(((DMVMContext) element).getDMC(), IRegisterDMContext.class);
|
||||
IRegisterDMContext regDmc = DMContexts.getAncestorOfType(((IDMVMContext) element).getDMContext(), IRegisterDMContext.class);
|
||||
|
||||
if ( regDmc != null ) {
|
||||
dmc = regDmc ;
|
||||
service = tracker.getService(IRegisters.class);
|
||||
}
|
||||
else {
|
||||
IExpressionDMContext exprDmc = DMContexts.getAncestorOfType(((DMVMContext) element).getDMC(), IExpressionDMContext.class);
|
||||
IExpressionDMContext exprDmc = DMContexts.getAncestorOfType(((IDMVMContext) element).getDMContext(), IExpressionDMContext.class);
|
||||
|
||||
if ( exprDmc != null ) {
|
||||
dmc = exprDmc ;
|
||||
|
|
|
@ -16,21 +16,27 @@ import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
|||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModifier;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.AbstractCachingVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.UserEditEvent;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RegisterBitFieldLayoutCellModifier extends WatchExpressionCellModifier {
|
||||
public class RegisterBitFieldCellModifier extends WatchExpressionCellModifier {
|
||||
|
||||
public static enum BitFieldEditorStyle { NOTHING, BITFIELDCOMBO, BITFIELDTEXT }
|
||||
|
||||
private AbstractCachingVMProvider fProvider;
|
||||
private BitFieldEditorStyle fStyle;
|
||||
private IBitFieldDMData fBitFieldData = null;
|
||||
private Object fElement = null;
|
||||
private SyncRegisterDataAccess fDataAccess = null;
|
||||
private IFormattedValuePreferenceStore fFormatPrefStore;
|
||||
|
||||
public RegisterBitFieldLayoutCellModifier( IFormattedValuePreferenceStore formatPrefStore, BitFieldEditorStyle style, SyncRegisterDataAccess access ) {
|
||||
public RegisterBitFieldCellModifier(AbstractCachingVMProvider provider,
|
||||
IFormattedValuePreferenceStore formatPrefStore, BitFieldEditorStyle style, SyncRegisterDataAccess access )
|
||||
{
|
||||
fProvider = provider;
|
||||
fStyle = style;
|
||||
fDataAccess = access;
|
||||
fFormatPrefStore = formatPrefStore;
|
||||
|
@ -40,8 +46,8 @@ public class RegisterBitFieldLayoutCellModifier extends WatchExpressionCellModif
|
|||
* Used to make sure we are dealing with a valid register.
|
||||
*/
|
||||
private IBitFieldDMContext getBitFieldDMC(Object element) {
|
||||
if (element instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
IDMContext dmc = ((AbstractDMVMLayoutNode.DMVMContext)element).getDMC();
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
return DMContexts.getAncestorOfType(dmc, IBitFieldDMContext.class);
|
||||
}
|
||||
return null;
|
||||
|
@ -98,7 +104,7 @@ public class RegisterBitFieldLayoutCellModifier extends WatchExpressionCellModif
|
|||
* Find the presentation context and then use it to get the current desired format.
|
||||
*/
|
||||
IVMContext ctx = (IVMContext) element;
|
||||
IPresentationContext presCtx = ctx.getLayoutNode().getVMProvider().getPresentationContext();
|
||||
IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
|
||||
|
||||
formatId = fFormatPrefStore.getCurrentNumericFormat(presCtx);
|
||||
}
|
||||
|
@ -156,7 +162,7 @@ public class RegisterBitFieldLayoutCellModifier extends WatchExpressionCellModif
|
|||
* Find the presentation context and then use it to get the current desired format.
|
||||
*/
|
||||
IVMContext ctx = (IVMContext) element;
|
||||
IPresentationContext presCtx = ctx.getLayoutNode().getVMProvider().getPresentationContext();
|
||||
IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
|
||||
|
||||
formatId = fFormatPrefStore.getCurrentNumericFormat(presCtx);
|
||||
}
|
||||
|
@ -164,6 +170,7 @@ public class RegisterBitFieldLayoutCellModifier extends WatchExpressionCellModif
|
|||
formatId = IFormattedValues.NATURAL_FORMAT;
|
||||
}
|
||||
fDataAccess.writeBitField(element, (String) value, formatId);
|
||||
fProvider.handleEvent(new UserEditEvent(element));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -177,6 +184,7 @@ public class RegisterBitFieldLayoutCellModifier extends WatchExpressionCellModif
|
|||
* Write the bit field using the selected mnemonic.
|
||||
*/
|
||||
fDataAccess.writeBitField(element, fBitFieldData.getMnemonics()[val.intValue()]);
|
||||
fProvider.handleEvent(new UserEditEvent(element));
|
||||
}
|
||||
}
|
||||
} else {
|
|
@ -10,14 +10,16 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.register;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IFormattedValues;
|
||||
import org.eclipse.dd.dsf.debug.service.IRegisters;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
|
@ -32,17 +34,15 @@ import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupDMContext;
|
|||
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.AbstractExpressionLayoutNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.IFormattedValueVMContext;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.register.RegisterBitFieldLayoutCellModifier.BitFieldEditorStyle;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.register.RegisterBitFieldCellModifier.BitFieldEditorStyle;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.model.IDebugTarget;
|
||||
|
@ -51,10 +51,13 @@ import org.eclipse.debug.core.model.IValue;
|
|||
import org.eclipse.debug.core.model.IVariable;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
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.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapterExtension;
|
||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||
import org.eclipse.jface.viewers.CellEditor;
|
||||
import org.eclipse.jface.viewers.ComboBoxCellEditor;
|
||||
import org.eclipse.jface.viewers.ICellModifier;
|
||||
|
@ -63,7 +66,9 @@ import org.eclipse.jface.viewers.TreePath;
|
|||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode implements IElementEditor {
|
||||
public class RegisterBitFieldVMNode extends AbstractExpressionVMNode
|
||||
implements IElementEditor, IElementLabelProvider
|
||||
{
|
||||
|
||||
protected class BitFieldVMC extends DMVMContext
|
||||
implements IVariable, IFormattedValueVMContext
|
||||
|
@ -133,7 +138,7 @@ public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode imp
|
|||
|
||||
StringBuffer exprBuf = new StringBuffer();
|
||||
IRegisterGroupDMContext groupDmc =
|
||||
DMContexts.getAncestorOfType(bitFieldVmc.getDMC(), IRegisterGroupDMContext.class);
|
||||
DMContexts.getAncestorOfType(bitFieldVmc.getDMContext(), IRegisterGroupDMContext.class);
|
||||
if (groupDmc != null) {
|
||||
exprBuf.append("$$\""); //$NON-NLS-1$
|
||||
exprBuf.append(groupDmc.getName());
|
||||
|
@ -141,14 +146,14 @@ public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode imp
|
|||
}
|
||||
|
||||
IRegisterDMContext registerDmc =
|
||||
DMContexts.getAncestorOfType(bitFieldVmc.getDMC(), IRegisterDMContext.class);
|
||||
DMContexts.getAncestorOfType(bitFieldVmc.getDMContext(), IRegisterDMContext.class);
|
||||
if (registerDmc != null) {
|
||||
exprBuf.append('$');
|
||||
exprBuf.append(registerDmc.getName());
|
||||
}
|
||||
|
||||
IBitFieldDMContext bitFieldDmc =
|
||||
DMContexts.getAncestorOfType(bitFieldVmc.getDMC(), IBitFieldDMContext.class);
|
||||
DMContexts.getAncestorOfType(bitFieldVmc.getDMContext(), IBitFieldDMContext.class);
|
||||
if (bitFieldDmc != null) {
|
||||
exprBuf.append('.');
|
||||
exprBuf.append(bitFieldDmc.getName());
|
||||
|
@ -162,7 +167,7 @@ public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode imp
|
|||
final protected BitFieldExpressionFactory fBitFieldExpressionFactory = new BitFieldExpressionFactory();
|
||||
private final IFormattedValuePreferenceStore fFormattedPrefStore;
|
||||
|
||||
public RegisterBitFieldLayoutNode(IFormattedValuePreferenceStore prefStore, AbstractVMProvider provider, DsfSession session, SyncRegisterDataAccess access) {
|
||||
public RegisterBitFieldVMNode(IFormattedValuePreferenceStore prefStore, AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess access) {
|
||||
super(provider, session, IRegisters.IBitFieldDMContext.class);
|
||||
fDataAccess = access;
|
||||
fFormattedPrefStore = prefStore;
|
||||
|
@ -237,9 +242,8 @@ public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode imp
|
|||
*/
|
||||
FormattedValueDMContext valueDmc = regService.getFormattedValueContext(dmc, finalFormatId);
|
||||
|
||||
VMCacheManager.getVMCacheManager().getCache(update.getPresentationContext())
|
||||
.getModelData(regService,
|
||||
valueDmc,
|
||||
getDMVMProvider().getModelData(
|
||||
RegisterBitFieldVMNode.this, update, regService, valueDmc,
|
||||
new DataRequestMonitor<FormattedValueDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
|
@ -269,22 +273,29 @@ public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode imp
|
|||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* We override the Abstract method because we now need to perform an extra level of data fetch
|
||||
* to get the formatted value represenatation of the register. Before we obtained the data from
|
||||
* the IDMData returned for the Register DMC. Now basically the level of information returned
|
||||
* is attribute information and the formatted value requires a separate transaction.
|
||||
*
|
||||
* @see org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode#updateLabelInSessionThread(org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate[])
|
||||
*/
|
||||
@Override
|
||||
|
||||
public void update(final ILabelUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updateLabelInSessionThread(updates);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (ILabelUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
|
||||
final IBitFieldDMContext dmc = findDmcInPath(update.getElementPath(), IRegisters.IBitFieldDMContext.class);
|
||||
final IBitFieldDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IRegisters.IBitFieldDMContext.class);
|
||||
|
||||
VMCacheManager.getVMCacheManager().getCache(update.getPresentationContext())
|
||||
.getModelData(getServicesTracker().getService(IRegisters.class),
|
||||
getDMVMProvider().getModelData(
|
||||
this, update,
|
||||
getServicesTracker().getService(IRegisters.class),
|
||||
dmc,
|
||||
new DataRequestMonitor<IBitFieldDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
|
@ -367,7 +378,7 @@ public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode imp
|
|||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
final IRegisterDMContext regDmc = findDmcInPath(update.getElementPath(), IRegisterDMContext.class);
|
||||
final IRegisterDMContext regDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IRegisterDMContext.class);
|
||||
|
||||
if (regDmc == null) {
|
||||
handleFailedUpdate(update);
|
||||
|
@ -391,61 +402,49 @@ public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode imp
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IVMContext createVMContext(IDMContext dmc) {
|
||||
protected IDMVMContext createVMContext(IDMContext dmc) {
|
||||
return new BitFieldVMC(dmc);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNodeDeltaFlagsForDMEvent(IDMEvent<?> e) {
|
||||
// In theory we want each node to act independently in terms of events. It might be
|
||||
// the case that we would only have elements of this type at the root level. It is
|
||||
// the case that the current layout model always starts with the GROUPS followed by
|
||||
// REGISTERS followed by BITFIELDS. But if we do this when a run-control event has
|
||||
// occured we generate a DELTA for every element, which can create a massive list
|
||||
// of entries all of which say update the entire view. So for now we will just have
|
||||
// the GROUP LAYOUT node do this. Later we need to revisit the logic and make sure
|
||||
// there is a way for the nodes to operate independently and efficiently.
|
||||
//
|
||||
//if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// return IModelDelta.CONTENT;
|
||||
//}
|
||||
public int getDeltaFlags(Object e) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
if (e instanceof IRegisters.IBitFieldChangedDMEvent) {
|
||||
return IModelDelta.STATE;
|
||||
}
|
||||
|
||||
if (e instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildDeltaForDMEvent(IDMEvent<?> e, VMDelta parent, int nodeOffset, RequestMonitor rm) {
|
||||
// In theory we want each node to act independently in terms of events. It might be
|
||||
// the case that we would only have elements of this type at the root level. It is
|
||||
// the case that the current layout model always starts with the GROUPS followed by
|
||||
// REGISTERS followed by BITFIELDS. But if we do this when a run-control event has
|
||||
// occured we generate a DELTA for every element, which can create a massive list
|
||||
// of entries all of which say update the entire view. So for now we will just have
|
||||
// the GROUP LAYOUT node do this. Later we need to revisit the logic and make sure
|
||||
// there is a way for the nodes to operate independently and efficiently.
|
||||
//
|
||||
// if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// // Create a delta that the whole register group has changed.
|
||||
// parent.addFlags(IModelDelta.CONTENT);
|
||||
// }
|
||||
public void buildDelta(Object e, ModelDelta parentDelta, int nodeOffset, RequestMonitor rm) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// Create a delta that the whole register group has changed.
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
if (e instanceof IRegisters.IBitFieldChangedDMEvent) {
|
||||
/*
|
||||
* Flush the cache.
|
||||
*/
|
||||
VMCacheManager.getVMCacheManager().flush(super.getVMProvider().getPresentationContext());
|
||||
|
||||
/*
|
||||
* Create a delta indicating the bit field has changed.
|
||||
*/
|
||||
parent.addNode( createVMContext(((IRegisters.IBitFieldChangedDMEvent)e).getDMContext()), IModelDelta.STATE );
|
||||
parentDelta.addNode( createVMContext(((IRegisters.IBitFieldChangedDMEvent)e).getDMContext()), IModelDelta.STATE );
|
||||
}
|
||||
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
if (e instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
rm.done();
|
||||
}
|
||||
|
||||
public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) {
|
||||
|
@ -510,13 +509,15 @@ public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode imp
|
|||
/*
|
||||
* Note we are complex COMBO and return the right editor.
|
||||
*/
|
||||
return new RegisterBitFieldLayoutCellModifier( fFormattedPrefStore, BitFieldEditorStyle.BITFIELDCOMBO, fDataAccess );
|
||||
return new RegisterBitFieldCellModifier(
|
||||
getDMVMProvider(), fFormattedPrefStore, BitFieldEditorStyle.BITFIELDCOMBO, fDataAccess );
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Text editor even if we need to clamp the value entered.
|
||||
*/
|
||||
return new RegisterBitFieldLayoutCellModifier( fFormattedPrefStore, BitFieldEditorStyle.BITFIELDTEXT, fDataAccess );
|
||||
return new RegisterBitFieldCellModifier(
|
||||
getDMVMProvider(), fFormattedPrefStore, BitFieldEditorStyle.BITFIELDTEXT, fDataAccess );
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -525,22 +526,22 @@ public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode imp
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void testContextForExpression(Object element, final String expression, final DataRequestMonitor<Boolean> rm) {
|
||||
if (!(element instanceof AbstractDMVMLayoutNode.DMVMContext)) {
|
||||
protected void testElementForExpression(Object element, IExpression expression, DataRequestMonitor<Boolean> rm) {
|
||||
if (!(element instanceof IDMVMContext)) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
final IBitFieldDMContext dmc = DMContexts.getAncestorOfType(((DMVMContext)element).getDMC(), IBitFieldDMContext.class);
|
||||
final IBitFieldDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)element).getDMContext(), IBitFieldDMContext.class);
|
||||
if (dmc == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
String bitFieldName = expression.substring(1);
|
||||
if (bitFieldName.equals(dmc.getName())) {
|
||||
String bitFieldName = parseExpressionForBitFieldName(expression.getExpressionText());
|
||||
if (dmc.getName().equals(bitFieldName)) {
|
||||
rm.setData(Boolean.TRUE);
|
||||
} else {
|
||||
rm.setData(Boolean.FALSE);
|
||||
|
@ -548,6 +549,38 @@ public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode imp
|
|||
rm.done();
|
||||
}
|
||||
|
||||
public boolean canParseExpression(IExpression expression) {
|
||||
return parseExpressionForBitFieldName(expression.getExpressionText()) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected format: $$"Group Name"$Register_Name.Bit_Field_Name
|
||||
*/
|
||||
private String parseExpressionForBitFieldName(String expression) {
|
||||
if (expression.startsWith("$$\"")) { //$NON-NLS-1$
|
||||
int secondQuoteIdx = expression.indexOf('"', "$$\"".length()); //$NON-NLS-1$
|
||||
if (secondQuoteIdx > 0) {
|
||||
String registerSubString = expression.substring(secondQuoteIdx + 1);
|
||||
if (registerSubString.length() != 0 &&
|
||||
registerSubString.charAt(0) == '$' &&
|
||||
Character.isLetterOrDigit(registerSubString.charAt(1)))
|
||||
{
|
||||
int registerEnd = 1;
|
||||
while ( registerEnd < registerSubString.length() &&
|
||||
Character.isLetterOrDigit(registerSubString.charAt(registerEnd)) )
|
||||
{
|
||||
registerEnd++;
|
||||
}
|
||||
if ((registerEnd + 1) < registerSubString.length() && '.' == registerSubString.charAt(registerEnd)) {
|
||||
return registerSubString.substring(registerEnd + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public int getExpressionLength(String expression) {
|
||||
if (expression.charAt(0) == '.' && Character.isLetterOrDigit(expression.charAt(1))) {
|
||||
int length = 1;
|
||||
|
@ -567,35 +600,43 @@ public class RegisterBitFieldLayoutNode extends AbstractExpressionLayoutNode imp
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDeltaFlagsForExpressionPart(Object event) {
|
||||
public int getDeltaFlagsForExpression(IExpression expression, Object event) {
|
||||
if (event instanceof IRunControl.ISuspendedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
if (event instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildDeltaForExpression(final IExpression expression, final int elementIdx, final String expressionText, final Object event, final VMDelta parentDelta, final TreePath path, final RequestMonitor rm)
|
||||
public void buildDeltaForExpression(final IExpression expression, final int elementIdx, final Object event, final ModelDelta parentDelta, final TreePath path, final RequestMonitor rm)
|
||||
{
|
||||
if (event instanceof ISuspendedDMEvent) {
|
||||
// Mark the partent delta indicating that elements were added and/or removed.
|
||||
parentDelta.addFlags(IModelDelta.CONTENT);
|
||||
// Mark the parent delta indicating that elements were added and/or removed.
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
} else if (event instanceof IRegisters.IRegisterChangedDMEvent) {
|
||||
parentDelta.addFlags(IModelDelta.CONTENT);
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
super.buildDeltaForExpression(expression, elementIdx, expressionText, event, parentDelta, path, rm);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta, final RequestMonitor rm)
|
||||
public void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, ModelDelta parentDelta, final RequestMonitor rm)
|
||||
{
|
||||
if (event instanceof IBitFieldChangedDMEvent) {
|
||||
parentDelta.addNode(element, IModelDelta.STATE);
|
||||
}
|
||||
|
||||
super.buildDeltaForExpressionElement(element, elementIdx, event, parentDelta, rm);
|
||||
if (event instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
parentDelta.addNode(element, IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
rm.done();
|
||||
}
|
||||
}
|
|
@ -19,16 +19,22 @@ import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
|||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModifier;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.AbstractCachingVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.UserEditEvent;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RegisterLayoutValueCellModifier extends WatchExpressionCellModifier {
|
||||
public class RegisterCellModifier extends WatchExpressionCellModifier {
|
||||
|
||||
private AbstractCachingVMProvider fProvider;
|
||||
private SyncRegisterDataAccess fDataAccess = null;
|
||||
private IFormattedValuePreferenceStore fFormattedValuePreferenceStore;
|
||||
|
||||
public RegisterLayoutValueCellModifier(IFormattedValuePreferenceStore formattedValuePreferenceStore, SyncRegisterDataAccess access) {
|
||||
public RegisterCellModifier(AbstractCachingVMProvider provider,
|
||||
IFormattedValuePreferenceStore formattedValuePreferenceStore, SyncRegisterDataAccess access)
|
||||
{
|
||||
fProvider = provider;
|
||||
fDataAccess = access;
|
||||
fFormattedValuePreferenceStore = formattedValuePreferenceStore;
|
||||
}
|
||||
|
@ -44,8 +50,8 @@ public class RegisterLayoutValueCellModifier extends WatchExpressionCellModifier
|
|||
* Used to make sure we are dealing with a valid register.
|
||||
*/
|
||||
protected IRegisterDMContext getRegisterDMC(Object element) {
|
||||
if (element instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
IDMContext dmc = ((AbstractDMVMLayoutNode.DMVMContext)element).getDMC();
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
return DMContexts.getAncestorOfType(dmc, IRegisterDMContext.class);
|
||||
}
|
||||
return null;
|
||||
|
@ -95,7 +101,7 @@ public class RegisterLayoutValueCellModifier extends WatchExpressionCellModifier
|
|||
* Find the presentation context and then use it to get the current desired format.
|
||||
*/
|
||||
IVMContext ctx = (IVMContext) element;
|
||||
IPresentationContext presCtx = ctx.getLayoutNode().getVMProvider().getPresentationContext();
|
||||
IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
|
||||
|
||||
formatId = fFormattedValuePreferenceStore.getCurrentNumericFormat(presCtx);
|
||||
}
|
||||
|
@ -134,7 +140,7 @@ public class RegisterLayoutValueCellModifier extends WatchExpressionCellModifier
|
|||
* Find the presentation context and then use it to get the current desired format.
|
||||
*/
|
||||
IVMContext ctx = (IVMContext) element;
|
||||
IPresentationContext presCtx = ctx.getLayoutNode().getVMProvider().getPresentationContext();
|
||||
IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
|
||||
|
||||
formatId = fFormattedValuePreferenceStore.getCurrentNumericFormat(presCtx);
|
||||
}
|
||||
|
@ -143,6 +149,7 @@ public class RegisterLayoutValueCellModifier extends WatchExpressionCellModifier
|
|||
}
|
||||
|
||||
fDataAccess.writeRegister(element, (String) value, formatId);
|
||||
fProvider.handleEvent(new UserEditEvent(element));
|
||||
}
|
||||
} else {
|
||||
super.modify(element, property, value);
|
|
@ -10,14 +10,16 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.register;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRegisters;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IRegisters.IGroupChangedDMEvent;
|
||||
|
@ -25,16 +27,14 @@ import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupDMContext;
|
|||
import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupDMData;
|
||||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.AbstractExpressionLayoutNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModifier;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.CompositeDMVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.model.IDebugTarget;
|
||||
|
@ -44,9 +44,11 @@ import org.eclipse.debug.core.model.IVariable;
|
|||
import org.eclipse.debug.internal.ui.DebugPluginImages;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
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.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||
import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapterExtension;
|
||||
import org.eclipse.jface.viewers.CellEditor;
|
||||
|
@ -56,8 +58,8 @@ import org.eclipse.jface.viewers.TreePath;
|
|||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RegisterGroupLayoutNode extends AbstractExpressionLayoutNode
|
||||
implements IElementEditor
|
||||
public class RegisterGroupVMNode extends AbstractExpressionVMNode
|
||||
implements IElementEditor, IElementLabelProvider
|
||||
{
|
||||
|
||||
protected class RegisterGroupVMC extends DMVMContext implements IVariable
|
||||
|
@ -122,7 +124,7 @@ public class RegisterGroupLayoutNode extends AbstractExpressionLayoutNode
|
|||
RegisterGroupVMC registerVmc = ((RegisterGroupVMC)variable);
|
||||
|
||||
StringBuffer exprBuf = new StringBuffer();
|
||||
IRegisterGroupDMContext groupDmc = DMContexts.getAncestorOfType(registerVmc.getDMC(), IRegisterGroupDMContext.class);
|
||||
IRegisterGroupDMContext groupDmc = DMContexts.getAncestorOfType(registerVmc.getDMContext(), IRegisterGroupDMContext.class);
|
||||
if (groupDmc != null) {
|
||||
exprBuf.append("$$\""); //$NON-NLS-1$
|
||||
exprBuf.append(groupDmc.getName());
|
||||
|
@ -138,7 +140,7 @@ public class RegisterGroupLayoutNode extends AbstractExpressionLayoutNode
|
|||
final protected RegisterGroupExpressionFactory fRegisterGroupExpressionFactory = new RegisterGroupExpressionFactory();
|
||||
private WatchExpressionCellModifier fWatchExpressionCellModifier = new WatchExpressionCellModifier();
|
||||
|
||||
public RegisterGroupLayoutNode(AbstractVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) {
|
||||
public RegisterGroupVMNode(AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) {
|
||||
super(provider, session, IRegisters.IRegisterGroupDMContext.class);
|
||||
fSyncRegisterDataAccess = syncDataAccess;
|
||||
}
|
||||
|
@ -149,11 +151,8 @@ public class RegisterGroupLayoutNode extends AbstractExpressionLayoutNode
|
|||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
if (!checkService(IRegisters.class, null, update)) return;
|
||||
|
||||
CompositeDMVMContext compositeDmc = new CompositeDMVMContext(getVMProvider().getRootElement(), update.getElementPath());
|
||||
getServicesTracker().getService(IRegisters.class).getRegisterGroups(
|
||||
compositeDmc,
|
||||
new CompositeDMVMContext(update),
|
||||
new DataRequestMonitor<IRegisterGroupDMContext[]>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
|
@ -167,19 +166,33 @@ public class RegisterGroupLayoutNode extends AbstractExpressionLayoutNode
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IVMContext createVMContext(IDMContext dmc) {
|
||||
protected IDMVMContext createVMContext(IDMContext dmc) {
|
||||
return new RegisterGroupVMC(dmc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(final ILabelUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updateLabelInSessionThread(updates);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (ILabelUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
final IRegisterGroupDMContext dmc = findDmcInPath(update.getElementPath(), IRegisterGroupDMContext.class);
|
||||
final IRegisterGroupDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IRegisterGroupDMContext.class);
|
||||
if (!checkDmc(dmc, update) || !checkService(IRegisters.class, null, update)) continue;
|
||||
|
||||
VMCacheManager.getVMCacheManager().getCache(update.getPresentationContext())
|
||||
.getModelData(getServicesTracker().getService(IRegisters.class, null),
|
||||
getDMVMProvider().getModelData(
|
||||
this, update,
|
||||
getServicesTracker().getService(IRegisters.class, null),
|
||||
dmc,
|
||||
new DataRequestMonitor<IRegisterGroupDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
|
@ -247,8 +260,7 @@ public class RegisterGroupLayoutNode extends AbstractExpressionLayoutNode
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNodeDeltaFlagsForDMEvent(IDMEvent<?> e) {
|
||||
public int getDeltaFlags(Object e) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
@ -261,28 +273,37 @@ public class RegisterGroupLayoutNode extends AbstractExpressionLayoutNode
|
|||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildDeltaForDMEvent(IDMEvent<?> e, VMDelta parent, int nodeOffset, RequestMonitor rm) {
|
||||
public void buildDelta(Object e, ModelDelta parentDelta, int nodeOffset, RequestMonitor rm) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// Create a delta that indicates all groups have changed
|
||||
parent.addFlags(IModelDelta.CONTENT);
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
else if (e instanceof IRegisters.IGroupsChangedDMEvent) {
|
||||
// flush the cache
|
||||
VMCacheManager.getVMCacheManager().flush(super.getVMProvider().getPresentationContext());
|
||||
|
||||
// Create a delta that indicates all groups have changed
|
||||
parent.addFlags(IModelDelta.CONTENT);
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
else if (e instanceof IRegisters.IGroupChangedDMEvent) {
|
||||
// flush the cache
|
||||
VMCacheManager.getVMCacheManager().flush(super.getVMProvider().getPresentationContext());
|
||||
|
||||
// Create a delta that indicates that specific group changed
|
||||
parent.addNode( createVMContext(((IGroupChangedDMEvent)e).getDMContext()), IModelDelta.STATE );
|
||||
parentDelta.addNode( createVMContext(((IGroupChangedDMEvent)e).getDMContext()), IModelDelta.STATE );
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
public boolean canParseExpression(IExpression expression) {
|
||||
return parseExpressionForGroupName(expression.getExpressionText()) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected format: $$"Group Name"$Register_Name.Bit_Field_Name
|
||||
*/
|
||||
private String parseExpressionForGroupName(String expression) {
|
||||
if (expression.startsWith("$$\"")) { //$NON-NLS-1$
|
||||
int secondQuoteIdx = expression.indexOf('"', "$$\"".length()); //$NON-NLS-1$
|
||||
if (secondQuoteIdx > 0) {
|
||||
return expression.substring(3, secondQuoteIdx);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getExpressionLength(String expression) {
|
||||
|
@ -295,8 +316,7 @@ public class RegisterGroupLayoutNode extends AbstractExpressionLayoutNode
|
|||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDeltaFlagsForExpressionPart(Object event) {
|
||||
public int getDeltaFlagsForExpression(IExpression expression, Object event) {
|
||||
if (event instanceof IRunControl.ISuspendedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
@ -304,19 +324,17 @@ public class RegisterGroupLayoutNode extends AbstractExpressionLayoutNode
|
|||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildDeltaForExpression(final IExpression expression, final int elementIdx, final String expressionText, final Object event, final VMDelta parentDelta, final TreePath path, final RequestMonitor rm)
|
||||
public void buildDeltaForExpression(IExpression expression, int elementIdx, Object event, ModelDelta parentDelta,
|
||||
TreePath path, RequestMonitor rm)
|
||||
{
|
||||
if (event instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// Mark the partent delta indicating that elements were added and/or removed.
|
||||
parentDelta.addFlags(IModelDelta.CONTENT);
|
||||
// Mark the parent delta indicating that elements were added and/or removed.
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
super.buildDeltaForExpression(expression, elementIdx, expressionText, event, parentDelta, path, rm);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta, final RequestMonitor rm)
|
||||
public void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, ModelDelta parentDelta, final RequestMonitor rm)
|
||||
{
|
||||
if (event instanceof IRegisters.IGroupsChangedDMEvent) {
|
||||
parentDelta.addNode(element, IModelDelta.CONTENT);
|
||||
|
@ -324,28 +342,25 @@ public class RegisterGroupLayoutNode extends AbstractExpressionLayoutNode
|
|||
if (event instanceof IRegisters.IGroupChangedDMEvent) {
|
||||
parentDelta.addNode(element, IModelDelta.STATE);
|
||||
}
|
||||
|
||||
super.buildDeltaForExpressionElement(element, elementIdx, event, parentDelta, rm);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void testContextForExpression(Object element, final String expression, final DataRequestMonitor<Boolean> rm) {
|
||||
if (!(element instanceof AbstractDMVMLayoutNode.DMVMContext)) {
|
||||
protected void testElementForExpression(Object element, IExpression expression, DataRequestMonitor<Boolean> rm) {
|
||||
if (!(element instanceof IDMVMContext)) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
final IRegisterGroupDMContext dmc = DMContexts.getAncestorOfType(((DMVMContext)element).getDMC(), IRegisterGroupDMContext.class);
|
||||
final IRegisterGroupDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)element).getDMContext(), IRegisterGroupDMContext.class);
|
||||
if (dmc == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
int startIdx = "$$\"".length(); //$NON-NLS-1$
|
||||
int endIdx = expression.indexOf('"', startIdx);
|
||||
String groupName = expression.substring(startIdx, endIdx);
|
||||
if (groupName.equals(dmc.getName())) {
|
||||
String groupName = parseExpressionForGroupName(expression.getExpressionText());
|
||||
if (dmc.getName().equals(groupName)) {
|
||||
rm.setData(Boolean.TRUE);
|
||||
} else {
|
||||
rm.setData(Boolean.FALSE);
|
|
@ -10,14 +10,16 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.register;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IFormattedValues;
|
||||
import org.eclipse.dd.dsf.debug.service.IRegisters;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
|
@ -29,17 +31,15 @@ import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterDMData;
|
|||
import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupDMContext;
|
||||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.AbstractExpressionLayoutNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.IFormattedValueVMContext;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.CompositeDMVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.model.IDebugTarget;
|
||||
|
@ -51,11 +51,14 @@ import org.eclipse.debug.internal.ui.DebugUIPlugin;
|
|||
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
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.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||
import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapterExtension;
|
||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||
import org.eclipse.jface.viewers.CellEditor;
|
||||
import org.eclipse.jface.viewers.ICellModifier;
|
||||
import org.eclipse.jface.viewers.TextCellEditor;
|
||||
|
@ -63,8 +66,8 @@ import org.eclipse.jface.viewers.TreePath;
|
|||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
||||
implements IElementEditor
|
||||
public class RegisterVMNode extends AbstractExpressionVMNode
|
||||
implements IElementEditor, IElementLabelProvider
|
||||
{
|
||||
protected class RegisterVMC extends DMVMContext
|
||||
implements IVariable, IFormattedValueVMContext
|
||||
|
@ -134,7 +137,7 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
|
||||
StringBuffer exprBuf = new StringBuffer();
|
||||
IRegisterGroupDMContext groupDmc =
|
||||
DMContexts.getAncestorOfType(registerVmc.getDMC(), IRegisterGroupDMContext.class);
|
||||
DMContexts.getAncestorOfType(registerVmc.getDMContext(), IRegisterGroupDMContext.class);
|
||||
if (groupDmc != null) {
|
||||
exprBuf.append("$$\""); //$NON-NLS-1$
|
||||
exprBuf.append(groupDmc.getName());
|
||||
|
@ -142,7 +145,7 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
}
|
||||
|
||||
IRegisterDMContext registerDmc =
|
||||
DMContexts.getAncestorOfType(registerVmc.getDMC(), IRegisterDMContext.class);
|
||||
DMContexts.getAncestorOfType(registerVmc.getDMContext(), IRegisterDMContext.class);
|
||||
if (registerDmc != null) {
|
||||
exprBuf.append('$');
|
||||
exprBuf.append(registerDmc.getName());
|
||||
|
@ -157,7 +160,7 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
final private SyncRegisterDataAccess fSyncRegisterDataAccess;
|
||||
private final IFormattedValuePreferenceStore fFormattedPrefStore;
|
||||
|
||||
public RegisterLayoutNode(IFormattedValuePreferenceStore prefStore, AbstractVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) {
|
||||
public RegisterVMNode(IFormattedValuePreferenceStore prefStore, AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) {
|
||||
super(provider, session, IRegisters.IRegisterDMContext.class);
|
||||
fSyncRegisterDataAccess = syncDataAccess;
|
||||
fFormattedPrefStore = prefStore;
|
||||
|
@ -237,8 +240,8 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
*/
|
||||
final FormattedValueDMContext valueDmc = regService.getFormattedValueContext(dmc, finalFormatId);
|
||||
|
||||
VMCacheManager.getVMCacheManager().getCache( context ).getModelData(regService,
|
||||
valueDmc,
|
||||
getDMVMProvider().getModelData(
|
||||
RegisterVMNode.this, update, regService, valueDmc,
|
||||
new DataRequestMonitor<FormattedValueDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
|
@ -252,8 +255,9 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
update.setLabel(getData().getFormattedValue(), labelIndex);
|
||||
|
||||
// color based on change history
|
||||
FormattedValueDMData oldData = (FormattedValueDMData) VMCacheManager.getVMCacheManager()
|
||||
.getCache(context).getArchivedModelData(valueDmc);
|
||||
|
||||
FormattedValueDMData oldData = (FormattedValueDMData) getDMVMProvider().getArchivedModelData(
|
||||
RegisterVMNode.this, update, valueDmc);
|
||||
if(oldData != null && !oldData.getFormattedValue().equals(getData().getFormattedValue())) {
|
||||
update.setBackground(
|
||||
DebugUIPlugin.getPreferenceColor(
|
||||
|
@ -270,111 +274,115 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* We override the Abstract method because we now need to perform an extra level of data fetch
|
||||
* to get the formatted value represenatation of the register. Before we obtained the data from
|
||||
* the IDMData returned for the Register DMC. Now basically the level of information returned
|
||||
* is attribute information and the formatted value requires a separate transaction.
|
||||
*
|
||||
* @see org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode#updateLabelInSessionThread(org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate[])
|
||||
*/
|
||||
@Override
|
||||
|
||||
public void update(final ILabelUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updateLabelInSessionThread(updates);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (ILabelUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
final IRegisterDMContext dmc = findDmcInPath(update.getElementPath(), IRegisters.IRegisterDMContext.class);
|
||||
final IRegisterDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IRegisters.IRegisterDMContext.class);
|
||||
if (!checkDmc(dmc, update) || !checkService(IRegisters.class, null, update)) continue;
|
||||
|
||||
VMCacheManager.getVMCacheManager().getCache(update.getPresentationContext())
|
||||
.getModelData(getServicesTracker().getService(IRegisters.class),
|
||||
dmc,
|
||||
new DataRequestMonitor<IRegisterDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
/*
|
||||
* Check that the request was evaluated and data is still
|
||||
* valid. The request could fail if the state of the
|
||||
* service changed during the request, but the view model
|
||||
* has not been updated yet.
|
||||
*/
|
||||
if (!getStatus().isOK()) {
|
||||
assert getStatus().isOK() ||
|
||||
getStatus().getCode() != IDsfService.INTERNAL_ERROR ||
|
||||
getStatus().getCode() != IDsfService.NOT_SUPPORTED;
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
getDMVMProvider().getModelData(
|
||||
this, update,
|
||||
getServicesTracker().getService(IRegisters.class),
|
||||
dmc,
|
||||
new DataRequestMonitor<IRegisterDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
/*
|
||||
* Check that the request was evaluated and data is still
|
||||
* valid. The request could fail if the state of the
|
||||
* service changed during the request, but the view model
|
||||
* has not been updated yet.
|
||||
*/
|
||||
if (!getStatus().isOK()) {
|
||||
assert getStatus().isOK() ||
|
||||
getStatus().getCode() != IDsfService.INTERNAL_ERROR ||
|
||||
getStatus().getCode() != IDsfService.NOT_SUPPORTED;
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If columns are configured, extract the selected values for each
|
||||
* understood column. First we fill all of those columns which can
|
||||
* be filled without the extra data mining. We also note if we do
|
||||
* have to datamine. Any columns need to set the processing flag
|
||||
* so we know we have further work to do. If there are more columns
|
||||
* which need data extraction they need to be added in both "for"
|
||||
* loops.
|
||||
*/
|
||||
String[] localColumns = update.getPresentationContext().getColumns();
|
||||
if (localColumns == null) localColumns = new String[] { IDebugVMConstants.COLUMN_ID__NAME };
|
||||
/*
|
||||
* If columns are configured, extract the selected values for each
|
||||
* understood column. First we fill all of those columns which can
|
||||
* be filled without the extra data mining. We also note if we do
|
||||
* have to datamine. Any columns need to set the processing flag
|
||||
* so we know we have further work to do. If there are more columns
|
||||
* which need data extraction they need to be added in both "for"
|
||||
* loops.
|
||||
*/
|
||||
String[] localColumns = update.getPresentationContext().getColumns();
|
||||
if (localColumns == null) localColumns = new String[] { IDebugVMConstants.COLUMN_ID__NAME };
|
||||
|
||||
boolean weAreExtractingFormattedData = false;
|
||||
boolean weAreExtractingFormattedData = false;
|
||||
|
||||
for (int idx = 0; idx < localColumns.length; idx++) {
|
||||
if (IDebugVMConstants.COLUMN_ID__NAME.equals(localColumns[idx])) {
|
||||
for (int idx = 0; idx < localColumns.length; idx++) {
|
||||
if (IDebugVMConstants.COLUMN_ID__NAME.equals(localColumns[idx])) {
|
||||
update.setLabel(getData().getName(), idx);
|
||||
update.setImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER), idx);
|
||||
} else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) {
|
||||
weAreExtractingFormattedData = true;
|
||||
} else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(localColumns[idx])) {
|
||||
IRegisterDMData data = getData();
|
||||
String typeStr = "Unsigned"; //$NON-NLS-1$
|
||||
String ReadAttrStr = "ReadNone"; //$NON-NLS-1$
|
||||
String WriteAddrStr = "WriteNone"; //$NON-NLS-1$
|
||||
|
||||
if ( data.isFloat() ) { typeStr = "Floating Point"; } //$NON-NLS-1$
|
||||
|
||||
if ( data.isReadOnce() ) { ReadAttrStr = "ReadOnce"; } //$NON-NLS-1$
|
||||
else if ( data.isReadable() ) { ReadAttrStr = "Readable"; } //$NON-NLS-1$
|
||||
|
||||
if ( data.isReadOnce() ) { WriteAddrStr = "WriteOnce"; } //$NON-NLS-1$
|
||||
else if ( data.isReadable() ) { WriteAddrStr = "Writeable"; } //$NON-NLS-1$
|
||||
|
||||
typeStr += " - " + ReadAttrStr + "/" + WriteAddrStr; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
update.setLabel(typeStr, idx);
|
||||
} else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) {
|
||||
update.setLabel(getData().getDescription(), idx);
|
||||
} else if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(localColumns[idx])) {
|
||||
IVMContext vmc = (IVMContext)update.getElement();
|
||||
IExpression expression = (IExpression)vmc.getAdapter(IExpression.class);
|
||||
if (expression != null) {
|
||||
update.setLabel(expression.getExpressionText(), idx);
|
||||
} else {
|
||||
update.setLabel(getData().getName(), idx);
|
||||
update.setImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER), idx);
|
||||
} else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) {
|
||||
weAreExtractingFormattedData = true;
|
||||
} else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(localColumns[idx])) {
|
||||
IRegisterDMData data = getData();
|
||||
String typeStr = "Unsigned"; //$NON-NLS-1$
|
||||
String ReadAttrStr = "ReadNone"; //$NON-NLS-1$
|
||||
String WriteAddrStr = "WriteNone"; //$NON-NLS-1$
|
||||
|
||||
if ( data.isFloat() ) { typeStr = "Floating Point"; } //$NON-NLS-1$
|
||||
|
||||
if ( data.isReadOnce() ) { ReadAttrStr = "ReadOnce"; } //$NON-NLS-1$
|
||||
else if ( data.isReadable() ) { ReadAttrStr = "Readable"; } //$NON-NLS-1$
|
||||
|
||||
if ( data.isReadOnce() ) { WriteAddrStr = "WriteOnce"; } //$NON-NLS-1$
|
||||
else if ( data.isReadable() ) { WriteAddrStr = "Writeable"; } //$NON-NLS-1$
|
||||
|
||||
typeStr += " - " + ReadAttrStr + "/" + WriteAddrStr; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
update.setLabel(typeStr, idx);
|
||||
} else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) {
|
||||
update.setLabel(getData().getDescription(), idx);
|
||||
} else if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(localColumns[idx])) {
|
||||
IVMContext vmc = (IVMContext)update.getElement();
|
||||
IExpression expression = (IExpression)vmc.getAdapter(IExpression.class);
|
||||
if (expression != null) {
|
||||
update.setLabel(expression.getExpressionText(), idx);
|
||||
} else {
|
||||
update.setLabel(getData().getName(), idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! weAreExtractingFormattedData ) {
|
||||
update.done();
|
||||
} else {
|
||||
for (int idx = 0; idx < localColumns.length; idx++) {
|
||||
if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) {
|
||||
updateFormattedRegisterValue(update, idx, dmc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
getSession().getExecutor()
|
||||
);
|
||||
|
||||
if ( ! weAreExtractingFormattedData ) {
|
||||
update.done();
|
||||
} else {
|
||||
for (int idx = 0; idx < localColumns.length; idx++) {
|
||||
if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) {
|
||||
updateFormattedRegisterValue(update, idx, dmc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
getSession().getExecutor());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
CompositeDMVMContext compositeDmc = new CompositeDMVMContext(getVMProvider().getRootElement(), update.getElementPath());
|
||||
|
||||
getServicesTracker().getService(IRegisters.class).getRegisters(
|
||||
compositeDmc,
|
||||
new CompositeDMVMContext(update),
|
||||
new DataRequestMonitor<IRegisterDMContext[]>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
|
@ -389,12 +397,11 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IVMContext createVMContext(IDMContext dmc) {
|
||||
protected IDMVMContext createVMContext(IDMContext dmc) {
|
||||
return new RegisterVMC(dmc);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNodeDeltaFlagsForDMEvent(IDMEvent<?> e) {
|
||||
public int getDeltaFlags(Object e) {
|
||||
// In theory we want each node to act independently in terms of events. It might be
|
||||
// the case that we would only have elements of this type at the root level. It is
|
||||
// the case that the current layout model always starts with the GROUPS followed by
|
||||
|
@ -404,60 +411,81 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
// the GROUP LAYOUT node do this. Later we need to revisit the logic and make sure
|
||||
// there is a way for the nodes to operate independently and efficiently.
|
||||
//
|
||||
// if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// return IModelDelta.CONTENT;
|
||||
// }
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
if (e instanceof IRegisters.IRegistersChangedDMEvent) {
|
||||
/*
|
||||
* Flush the cache.
|
||||
*/
|
||||
VMCacheManager.getVMCacheManager().flush(super.getVMProvider().getPresentationContext());
|
||||
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
if (e instanceof IRegisters.IRegisterChangedDMEvent) {
|
||||
/*
|
||||
* Flush the cache.
|
||||
*/
|
||||
VMCacheManager.getVMCacheManager().flush(super.getVMProvider().getPresentationContext());
|
||||
|
||||
/*
|
||||
* Logically one would think that STATE should be specified here. But we specifiy CONTENT
|
||||
* as well so that if there are subregisters ( BIT FIELDS ) they will be forced to update
|
||||
* and show new values when the total register changes.
|
||||
*/
|
||||
return IModelDelta.CONTENT | IModelDelta.STATE;
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
if (e instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildDeltaForDMEvent(IDMEvent<?> e, VMDelta parent, int nodeOffset, RequestMonitor rm) {
|
||||
// In theory we want each node to act independently in terms of events. It might be
|
||||
// the case that we would only have elements of this type at the root level. It is
|
||||
// the case that the current layout model always starts with the GROUPS followed by
|
||||
// REGISTERS followed by BITFIELDS. But if we do this when a run-control event has
|
||||
// occured we generate a DELTA for every element, which can create a massive list
|
||||
// of entries all of which say update the entire view. So for now we will just have
|
||||
// the GROUP LAYOUT node do this. Later we need to revisit the logic and make sure
|
||||
// there is a way for the nodes to operate independently and efficiently.
|
||||
//
|
||||
// if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// // Create a delta that the whole register group has changed.
|
||||
// parent.addFlags(IModelDelta.CONTENT);
|
||||
// }
|
||||
public void buildDelta(Object e, ModelDelta parentDelta, int nodeOffset, RequestMonitor rm) {
|
||||
if (e instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// Create a delta that the whole register group has changed.
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
if (e instanceof IRegisters.IRegistersChangedDMEvent) {
|
||||
parent.addFlags(IModelDelta.CONTENT);;
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);;
|
||||
}
|
||||
|
||||
if (e instanceof IRegisters.IRegisterChangedDMEvent) {
|
||||
parent.addNode( createVMContext(((IRegisterChangedDMEvent)e).getDMContext()), IModelDelta.CONTENT | IModelDelta.STATE );
|
||||
parentDelta.addNode( createVMContext(((IRegisterChangedDMEvent)e).getDMContext()), IModelDelta.CONTENT | IModelDelta.STATE );
|
||||
}
|
||||
|
||||
super.buildDeltaForDMEvent(e, parent, nodeOffset, rm);
|
||||
if (e instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
rm.done();
|
||||
}
|
||||
|
||||
public boolean canParseExpression(IExpression expression) {
|
||||
return parseExpressionForRegisterName(expression.getExpressionText()) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected format: $$"Group Name"$Register_Name.Bit_Field_Name
|
||||
*/
|
||||
private String parseExpressionForRegisterName(String expression) {
|
||||
if (expression.startsWith("$$\"")) { //$NON-NLS-1$
|
||||
int secondQuoteIdx = expression.indexOf('"', "$$\"".length()); //$NON-NLS-1$
|
||||
if (secondQuoteIdx > 0) {
|
||||
String registerSubString = expression.substring(secondQuoteIdx + 1);
|
||||
if (registerSubString.length() != 0 &&
|
||||
registerSubString.charAt(0) == '$' &&
|
||||
Character.isLetterOrDigit(registerSubString.charAt(1)))
|
||||
{
|
||||
int registerEnd = 1;
|
||||
while ( registerEnd < registerSubString.length() &&
|
||||
Character.isLetterOrDigit(registerSubString.charAt(registerEnd)) )
|
||||
{
|
||||
registerEnd++;
|
||||
}
|
||||
return registerSubString.substring(1, registerEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getExpressionLength(String expression) {
|
||||
|
@ -473,21 +501,21 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void testContextForExpression(Object element, final String expression, final DataRequestMonitor<Boolean> rm) {
|
||||
if (!(element instanceof AbstractDMVMLayoutNode.DMVMContext)) {
|
||||
protected void testElementForExpression(Object element, IExpression expression, DataRequestMonitor<Boolean> rm) {
|
||||
if (!(element instanceof IDMVMContext)) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
final IRegisterDMContext dmc = DMContexts.getAncestorOfType(((DMVMContext)element).getDMC(), IRegisterDMContext.class);
|
||||
final IRegisterDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)element).getDMContext(), IRegisterDMContext.class);
|
||||
if (dmc == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
String regName = expression.substring(1);
|
||||
if (regName.equals(dmc.getName())) {
|
||||
String regName = parseExpressionForRegisterName(expression.getExpressionText());
|
||||
if (dmc.getName().equals(regName)) {
|
||||
rm.setData(Boolean.TRUE);
|
||||
} else {
|
||||
rm.setData(Boolean.FALSE);
|
||||
|
@ -502,28 +530,30 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDeltaFlagsForExpressionPart(Object event) {
|
||||
public int getDeltaFlagsForExpression(IExpression expression, Object event) {
|
||||
if (event instanceof IRunControl.ISuspendedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
if (event instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildDeltaForExpression(final IExpression expression, final int elementIdx, final String expressionText, final Object event, final VMDelta parentDelta, final TreePath path, final RequestMonitor rm)
|
||||
public void buildDeltaForExpression(IExpression expression, int elementIdx, Object event, ModelDelta parentDelta,
|
||||
TreePath path, RequestMonitor rm)
|
||||
{
|
||||
if (event instanceof IRunControl.ISuspendedDMEvent) {
|
||||
// Mark the parent delta indicating that elements were added and/or removed.
|
||||
parentDelta.addFlags(IModelDelta.CONTENT);
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
super.buildDeltaForExpression(expression, elementIdx, expressionText, event, parentDelta, path, rm);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta, final RequestMonitor rm)
|
||||
public void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, ModelDelta parentDelta, final RequestMonitor rm)
|
||||
{
|
||||
if (event instanceof IRegisters.IRegisterChangedDMEvent) {
|
||||
parentDelta.addNode(element, IModelDelta.STATE);
|
||||
|
@ -533,7 +563,13 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
parentDelta.addNode(element, IModelDelta.STATE);
|
||||
}
|
||||
|
||||
super.buildDeltaForExpressionElement(element, elementIdx, event, parentDelta, rm);
|
||||
if (event instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
parentDelta.addNode(element, IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
rm.done();
|
||||
}
|
||||
|
||||
|
||||
|
@ -556,7 +592,7 @@ public class RegisterLayoutNode extends AbstractExpressionLayoutNode
|
|||
}
|
||||
|
||||
public ICellModifier getCellModifier(IPresentationContext context, Object element) {
|
||||
|
||||
return new RegisterLayoutValueCellModifier( fFormattedPrefStore, fSyncRegisterDataAccess );
|
||||
return new RegisterCellModifier(
|
||||
getDMVMProvider(), fFormattedPrefStore, fSyncRegisterDataAccess );
|
||||
}
|
||||
}
|
|
@ -10,21 +10,28 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.register;
|
||||
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.dm.AbstractDebugDMVMProviderWithCache;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.FormattedValuePreferenceStore;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.update.BreakpointHitUpdatePolicy;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.DMVMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.RootDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.AutomaticUpdatePolicy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.IVMUpdatePolicy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.ManualUpdatePolicy;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.jface.util.IPropertyChangeListener;
|
||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||
|
||||
/**
|
||||
* Provides the VIEW MODEL for the DEBUG MODEL REGISTER view.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class RegisterVMProvider extends AbstractDebugDMVMProviderWithCache
|
||||
public class RegisterVMProvider extends AbstractDMVMProvider
|
||||
implements IPropertyChangeListener
|
||||
{
|
||||
/*
|
||||
* Current default for register formatting.
|
||||
|
@ -32,6 +39,8 @@ public class RegisterVMProvider extends AbstractDebugDMVMProviderWithCache
|
|||
public RegisterVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
|
||||
super(adapter, context, session);
|
||||
|
||||
context.addPropertyChangeListener(this);
|
||||
|
||||
/*
|
||||
* Create the register data access routines.
|
||||
*/
|
||||
|
@ -40,30 +49,41 @@ public class RegisterVMProvider extends AbstractDebugDMVMProviderWithCache
|
|||
/*
|
||||
* Create the top level node to deal with the root selection.
|
||||
*/
|
||||
IVMRootLayoutNode debugViewSelection = new DMVMRootLayoutNode(this);
|
||||
IRootVMNode rootNode = new RootDMVMNode(this);
|
||||
|
||||
/*
|
||||
* Create the Group nodes next. They represent the first level shown in the view.
|
||||
*/
|
||||
IVMLayoutNode registerGroupNode = new RegisterGroupLayoutNode(this, getSession(), regAccess);
|
||||
debugViewSelection.setChildNodes(new IVMLayoutNode[] { registerGroupNode });
|
||||
IVMNode registerGroupNode = new RegisterGroupVMNode(this, getSession(), regAccess);
|
||||
addChildNodes(rootNode, new IVMNode[] { registerGroupNode });
|
||||
|
||||
/*
|
||||
* Create the next level which is the registers themselves.
|
||||
*/
|
||||
IVMLayoutNode registerNode = new RegisterLayoutNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), regAccess);
|
||||
registerGroupNode.setChildNodes(new IVMLayoutNode[] { registerNode });
|
||||
IVMNode registerNode = new RegisterVMNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), regAccess);
|
||||
addChildNodes(registerGroupNode, new IVMNode[] { registerNode });
|
||||
|
||||
/*
|
||||
* Create the next level which is the bitfield level.
|
||||
*/
|
||||
IVMLayoutNode bitFieldNode = new RegisterBitFieldLayoutNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), regAccess);
|
||||
registerNode.setChildNodes(new IVMLayoutNode[] { bitFieldNode });
|
||||
IVMNode bitFieldNode = new RegisterBitFieldVMNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), regAccess);
|
||||
addChildNodes(registerNode, new IVMNode[] { bitFieldNode });
|
||||
|
||||
/*
|
||||
* Now set this schema set as the layout set.
|
||||
*/
|
||||
setRootLayoutNode(debugViewSelection);
|
||||
setRootNode(rootNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IVMUpdatePolicy[] createUpdateModes() {
|
||||
return new IVMUpdatePolicy[] { new AutomaticUpdatePolicy(), new ManualUpdatePolicy(), new BreakpointHitUpdatePolicy() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
getPresentationContext().removePropertyChangeListener(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,4 +95,8 @@ public class RegisterVMProvider extends AbstractDebugDMVMProviderWithCache
|
|||
public String getColumnPresentationId(IPresentationContext context, Object element) {
|
||||
return RegisterColumnPresentation.ID;
|
||||
}
|
||||
|
||||
public void propertyChange(PropertyChangeEvent event) {
|
||||
handleEvent(event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupDMData;
|
|||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.osgi.framework.InvalidSyntaxException;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
|
@ -154,8 +154,8 @@ public class SyncRegisterDataAccess {
|
|||
}
|
||||
|
||||
public IBitFieldDMContext getBitFieldDMC(Object element) {
|
||||
if (element instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
IDMContext dmc = ((AbstractDMVMLayoutNode.DMVMContext)element).getDMC();
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
return DMContexts.getAncestorOfType(dmc, IBitFieldDMContext.class);
|
||||
}
|
||||
return null;
|
||||
|
@ -410,24 +410,24 @@ public class SyncRegisterDataAccess {
|
|||
}
|
||||
|
||||
public IRegisterGroupDMContext getRegisterGroupDMC(Object element) {
|
||||
if (element instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
IDMContext dmc = ((AbstractDMVMLayoutNode.DMVMContext)element).getDMC();
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
return DMContexts.getAncestorOfType(dmc, IRegisterGroupDMContext.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public IRegisterDMContext getRegisterDMC(Object element) {
|
||||
if (element instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
IDMContext dmc = ((AbstractDMVMLayoutNode.DMVMContext)element).getDMC();
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
return DMContexts.getAncestorOfType(dmc, IRegisterDMContext.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public IFormattedDataDMContext getFormattedDMC(Object element) {
|
||||
if (element instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
IDMContext dmc = ((AbstractDMVMLayoutNode.DMVMContext)element).getDMC();
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
IRegisterDMContext regdmc = DMContexts.getAncestorOfType(dmc, IRegisterDMContext.class);
|
||||
return DMContexts.getAncestorOfType(regdmc, IFormattedDataDMContext.class);
|
||||
}
|
||||
|
@ -795,8 +795,8 @@ public class SyncRegisterDataAccess {
|
|||
* session is stale, then bail out.
|
||||
*/
|
||||
IFormattedDataDMContext dmc = null;
|
||||
if (element instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
IDMContext vmcdmc = ((AbstractDMVMLayoutNode.DMVMContext)element).getDMC();
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMContext vmcdmc = ((IDMVMContext)element).getDMContext();
|
||||
IRegisterDMContext regdmc = DMContexts.getAncestorOfType(vmcdmc, IRegisterDMContext.class);
|
||||
dmc = DMContexts.getAncestorOfType(regdmc, IFormattedDataDMContext.class);
|
||||
}
|
||||
|
@ -899,8 +899,8 @@ public class SyncRegisterDataAccess {
|
|||
* session is stale, then bail out.
|
||||
*/
|
||||
IFormattedDataDMContext dmc = null;
|
||||
if (element instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
IDMContext vmcdmc = ((AbstractDMVMLayoutNode.DMVMContext)element).getDMC();
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMContext vmcdmc = ((IDMVMContext)element).getDMContext();
|
||||
IRegisterDMContext regdmc = DMContexts.getAncestorOfType(vmcdmc, IRegisterDMContext.class);
|
||||
dmc = DMContexts.getAncestorOfType(regdmc, IFormattedDataDMContext.class);
|
||||
}
|
||||
|
@ -939,8 +939,8 @@ public class SyncRegisterDataAccess {
|
|||
* session is stale, then bail out.
|
||||
*/
|
||||
IFormattedDataDMContext dmc = null;
|
||||
if (element instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
IDMContext vmcdmc = ((AbstractDMVMLayoutNode.DMVMContext)element).getDMC();
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMContext vmcdmc = ((IDMVMContext)element).getDMContext();
|
||||
IBitFieldDMContext bitfielddmc = DMContexts.getAncestorOfType(vmcdmc, IBitFieldDMContext.class);
|
||||
dmc = DMContexts.getAncestorOfType(bitfielddmc, IFormattedDataDMContext.class);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.debug.ui.viewmodel.update;
|
||||
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.IElementUpdateTester;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.ManualUpdatePolicy;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class BreakpointHitUpdatePolicy extends ManualUpdatePolicy {
|
||||
|
||||
public static String BREAKPOINT_HIT_UPDATE_POLICY_ID = "org.eclipse.dd.dsf.debug.ui.viewmodel.update.breakpointHitUpdatePolicy"; //$NON-NLS-1$
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return BREAKPOINT_HIT_UPDATE_POLICY_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Breakpoint Hit";
|
||||
}
|
||||
|
||||
@Override
|
||||
public IElementUpdateTester getTesterTester(Object event) {
|
||||
if(event instanceof ISuspendedDMEvent) {
|
||||
ISuspendedDMEvent suspendedEvent = (ISuspendedDMEvent)event;
|
||||
if(suspendedEvent.getReason().equals(StateChangeReason.BREAKPOINT)) {
|
||||
return super.getTesterTester(REFRESH_EVENT);
|
||||
}
|
||||
}
|
||||
return super.getTesterTester(event);
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.update;
|
||||
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCache;
|
||||
|
||||
public class VMCacheRefreshAlways extends VMCache
|
||||
{
|
||||
public VMCacheRefreshAlways()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public VMCacheRefreshAlways(VMCache oldCache)
|
||||
{
|
||||
super(oldCache);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void handleEvent(IDMEvent event) {
|
||||
if(event instanceof IRunControl.ISuspendedDMEvent)
|
||||
flush(true);
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.update;
|
||||
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCache;
|
||||
|
||||
public class VMCacheRefreshManual extends VMCache
|
||||
{
|
||||
public VMCacheRefreshManual()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public VMCacheRefreshManual(VMCache oldCache)
|
||||
{
|
||||
super(oldCache);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void handleEvent(IDMEvent event) {}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.update;
|
||||
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCache;
|
||||
|
||||
public class VMCacheRefreshOnBreak extends VMCache
|
||||
{
|
||||
public VMCacheRefreshOnBreak()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public VMCacheRefreshOnBreak(VMCache oldCache)
|
||||
{
|
||||
super(oldCache);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void handleEvent(IDMEvent event) {
|
||||
if(event instanceof IRunControl.ISuspendedDMEvent)
|
||||
{
|
||||
if(((IRunControl.ISuspendedDMEvent) event).getReason().equals(StateChangeReason.BREAKPOINT))
|
||||
flush(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6,131 +6,45 @@
|
|||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions;
|
||||
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMAdapter;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.actions.AbstractVMProviderActionDelegate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProviderWithCache;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
|
||||
import org.eclipse.debug.ui.AbstractDebugView;
|
||||
import org.eclipse.debug.ui.DebugUITools;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.ICachingVMProvider;
|
||||
import org.eclipse.debug.ui.contexts.DebugContextEvent;
|
||||
import org.eclipse.debug.ui.contexts.IDebugContextListener;
|
||||
import org.eclipse.jface.action.IAction;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.jface.viewers.Viewer;
|
||||
import org.eclipse.ui.IViewActionDelegate;
|
||||
import org.eclipse.ui.IViewPart;
|
||||
import org.eclipse.ui.IViewSite;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RefreshActionDelegate implements IViewActionDelegate, IDebugContextListener {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class RefreshActionDelegate extends AbstractVMProviderActionDelegate {
|
||||
|
||||
protected IViewPart fView = null;
|
||||
private Object fViewInput = null;
|
||||
|
||||
public void init(IViewPart view) {
|
||||
/*
|
||||
* Save the view information for later reference and data retrieval.
|
||||
*/
|
||||
fView = view;
|
||||
|
||||
/*
|
||||
* Get the current selection from the DebugView so we can determine if we want this menu action to be live or not.
|
||||
*/
|
||||
IViewSite site = (IViewSite) view.getSite();
|
||||
String combinedViewId = site.getId() + (site.getSecondaryId() != null ? (":" + site.getSecondaryId()) : ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
DebugUITools.getDebugContextManager().getContextService(view.getSite().getWorkbenchWindow()).addPostDebugContextListener(this, combinedViewId);
|
||||
ISelection sel = DebugUITools.getDebugContextManager().getContextService(view.getSite().getWorkbenchWindow()).getActiveContext();
|
||||
|
||||
if ( sel instanceof IStructuredSelection ) {
|
||||
/*
|
||||
* Save the view selection as well so we can later determine if we want our action to be valid or not.
|
||||
*/
|
||||
fViewInput = ( (IStructuredSelection) sel ).getFirstElement();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.eclipse.debug.ui.contexts.IDebugContextListener#debugContextChanged(org.eclipse.debug.ui.contexts.DebugContextEvent)
|
||||
*/
|
||||
public void debugContextChanged(DebugContextEvent event) {
|
||||
/*
|
||||
* This handler is called whenever a selection in the debug view is changed. So here is
|
||||
* where we will know when we need to reenable the menu actions.
|
||||
*/
|
||||
ISelection sel = event.getContext();
|
||||
|
||||
if (sel instanceof IStructuredSelection) {
|
||||
fViewInput = ((IStructuredSelection)sel).getFirstElement();
|
||||
public void run(IAction action) {
|
||||
IVMProvider provider = getVMProvider();
|
||||
if (provider instanceof ICachingVMProvider) {
|
||||
((ICachingVMProvider)provider).refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void run(IAction action) {
|
||||
/*
|
||||
* Make sure we have a valid set of information. Otherwise we cannot go forward.
|
||||
*/
|
||||
if ( fView instanceof AbstractDebugView && fViewInput != null )
|
||||
{
|
||||
Viewer viewer = ( (AbstractDebugView) fView).getViewer();
|
||||
@Override
|
||||
public void init(IViewPart view) {
|
||||
super.init(view);
|
||||
getAction().setEnabled(getVMProvider() instanceof ICachingVMProvider);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we need to make sure this is one of the Flexible Hierarchy viewws.
|
||||
*/
|
||||
if ( viewer instanceof TreeModelViewer ) {
|
||||
/*
|
||||
* Get the presentation context and see if there is a numeric property there. If so then this
|
||||
* is a view implementation which supports changing the format.
|
||||
*/
|
||||
TreeModelViewer treeViewer = (TreeModelViewer) viewer;
|
||||
IPresentationContext context = treeViewer.getPresentationContext();
|
||||
@Override
|
||||
public void debugContextChanged(DebugContextEvent event) {
|
||||
super.debugContextChanged(event);
|
||||
getAction().setEnabled(getVMProvider() instanceof ICachingVMProvider);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now go tell the view to update. We do so by finding the VM provider for this view
|
||||
* and telling it to redraw the entire view.
|
||||
*/
|
||||
if (fViewInput instanceof IAdaptable) {
|
||||
IVMAdapter adapter = (IVMAdapter) ((IAdaptable)fViewInput).getAdapter(IVMAdapter.class);
|
||||
|
||||
if ( adapter != null ) {
|
||||
IVMProvider provider = adapter.getVMProvider(context);
|
||||
|
||||
if ( provider != null ) {
|
||||
|
||||
if ( provider instanceof AbstractDMVMProviderWithCache ) {
|
||||
AbstractDMVMProviderWithCache prov = (AbstractDMVMProviderWithCache) provider;
|
||||
|
||||
prov.flush();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* As a fallback we will flush the cache without involving the provider if it for some
|
||||
* reason does not measure up.
|
||||
*/
|
||||
|
||||
VMCacheManager.getVMCacheManager().flush(getContext());
|
||||
}
|
||||
|
||||
public void selectionChanged(IAction action, ISelection selection) {
|
||||
}
|
||||
|
||||
private Object getContext()
|
||||
{
|
||||
return ((TreeModelViewer) ((AbstractDebugView) fView).getViewer()).getPresentationContext();
|
||||
}
|
||||
@Override
|
||||
public void selectionChanged(IAction action, ISelection selection) {
|
||||
super.selectionChanged(action, selection);
|
||||
getAction().setEnabled(getVMProvider() instanceof ICachingVMProvider);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions;
|
||||
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.update.VMCacheRefreshAlways;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCache;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.actions.AbstractRefreshActionDelegate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
|
||||
import org.eclipse.debug.ui.AbstractDebugView;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RefreshAlwaysActionDelegate extends AbstractRefreshActionDelegate
|
||||
{
|
||||
@Override
|
||||
public Object getContext()
|
||||
{
|
||||
return ((TreeModelViewer) ((AbstractDebugView) fView).getViewer()).getPresentationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VMCache createCache()
|
||||
{
|
||||
return new VMCacheRefreshAlways(VMCacheManager.getVMCacheManager().getCache(getContext()));
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions;
|
||||
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.update.VMCacheRefreshManual;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCache;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.actions.AbstractRefreshActionDelegate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
|
||||
import org.eclipse.debug.ui.AbstractDebugView;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RefreshManualActionDelegate extends AbstractRefreshActionDelegate
|
||||
{
|
||||
@Override
|
||||
public Object getContext()
|
||||
{
|
||||
return ((TreeModelViewer) ((AbstractDebugView) fView).getViewer()).getPresentationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VMCache createCache()
|
||||
{
|
||||
return new VMCacheRefreshManual(VMCacheManager.getVMCacheManager().getCache(getContext()));
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.update.actions;
|
||||
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.update.VMCacheRefreshOnBreak;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCache;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.actions.AbstractRefreshActionDelegate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
|
||||
import org.eclipse.debug.ui.AbstractDebugView;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class RefreshOnBreakActionDelegate extends AbstractRefreshActionDelegate
|
||||
{
|
||||
@Override
|
||||
public Object getContext()
|
||||
{
|
||||
return ((TreeModelViewer) ((AbstractDebugView) fView).getViewer()).getPresentationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VMCache createCache()
|
||||
{
|
||||
return new VMCacheRefreshOnBreak(VMCacheManager.getVMCacheManager().getCache(getContext()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.debug.ui.viewmodel.update.actions;
|
||||
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.actions.AbstractVMProviderActionDelegate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.ICachingVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.IVMUpdatePolicy;
|
||||
import org.eclipse.debug.ui.contexts.DebugContextEvent;
|
||||
import org.eclipse.jface.action.Action;
|
||||
import org.eclipse.jface.action.ActionContributionItem;
|
||||
import org.eclipse.jface.action.IAction;
|
||||
import org.eclipse.jface.action.IMenuCreator;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.swt.events.MenuAdapter;
|
||||
import org.eclipse.swt.events.MenuEvent;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Menu;
|
||||
import org.eclipse.swt.widgets.MenuItem;
|
||||
import org.eclipse.ui.IViewPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SelectUpdatePolicyAction extends AbstractVMProviderActionDelegate implements IMenuCreator {
|
||||
|
||||
|
||||
class SelectPolicy extends Action {
|
||||
private ICachingVMProvider fVMProvider;
|
||||
private IVMUpdatePolicy fUpdatePolicy;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (isChecked()) {
|
||||
fVMProvider.setActiveUpdatePolicy(fUpdatePolicy);
|
||||
}
|
||||
}
|
||||
|
||||
public SelectPolicy(ICachingVMProvider provider, IVMUpdatePolicy updatePolicy) {
|
||||
super(updatePolicy.getName(), IAction.AS_RADIO_BUTTON);
|
||||
fVMProvider = provider;
|
||||
fUpdatePolicy = updatePolicy;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Menu getMenu(Control parent) {
|
||||
// Never called
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(IViewPart view) {
|
||||
super.init(view);
|
||||
getAction().setEnabled(getVMProvider() instanceof ICachingVMProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(IAction action) {
|
||||
super.init(action);
|
||||
action.setMenuCreator(this);
|
||||
}
|
||||
|
||||
public void run(IAction action) {
|
||||
// Do nothing, this is a pull-down menu
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectionChanged(IAction action, ISelection selection) {
|
||||
if (action != getAction()) {
|
||||
action.setMenuCreator(this);
|
||||
}
|
||||
super.selectionChanged(action, selection);
|
||||
getAction().setEnabled(getVMProvider() instanceof ICachingVMProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debugContextChanged(DebugContextEvent event) {
|
||||
super.debugContextChanged(event);
|
||||
getAction().setEnabled(getVMProvider() instanceof ICachingVMProvider);
|
||||
}
|
||||
|
||||
public Menu getMenu(Menu parent) {
|
||||
Menu menu = new Menu(parent);
|
||||
menu.addMenuListener(new MenuAdapter() {
|
||||
@Override
|
||||
public void menuShown(MenuEvent e) {
|
||||
Menu m = (Menu)e.widget;
|
||||
MenuItem[] items = m.getItems();
|
||||
for (int i=0; i < items.length; i++) {
|
||||
items[i].dispose();
|
||||
}
|
||||
fillMenu(m);
|
||||
}
|
||||
});
|
||||
return menu;
|
||||
}
|
||||
|
||||
private void fillMenu(Menu menu) {
|
||||
|
||||
IVMUpdatePolicy[] updatePolicies = new IVMUpdatePolicy[0];
|
||||
IVMUpdatePolicy activePolicy = null;
|
||||
IVMProvider provider = getVMProvider();
|
||||
if (provider instanceof ICachingVMProvider) {
|
||||
ICachingVMProvider cachingProvider = (ICachingVMProvider)provider;
|
||||
updatePolicies = cachingProvider.getAvailableUpdatePolicies();
|
||||
activePolicy = cachingProvider.getActiveUpdatePolicy();
|
||||
|
||||
for (IVMUpdatePolicy updatePolicy : updatePolicies) {
|
||||
SelectPolicy action = new SelectPolicy(cachingProvider, updatePolicy);
|
||||
if (updatePolicy.equals(activePolicy)) {
|
||||
action.setChecked(true);
|
||||
}
|
||||
ActionContributionItem item = new ActionContributionItem(action);
|
||||
item.fill(menu, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -13,15 +13,21 @@ import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
|||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModifier;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.AbstractCachingVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.UserEditEvent;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class VariableLayoutValueCellModifier extends WatchExpressionCellModifier {
|
||||
public class VariableCellModifier extends WatchExpressionCellModifier {
|
||||
|
||||
private AbstractCachingVMProvider fProvider;
|
||||
private SyncVariableDataAccess fDataAccess = null;
|
||||
private IFormattedValuePreferenceStore fPrefStore;
|
||||
|
||||
public VariableLayoutValueCellModifier(IFormattedValuePreferenceStore formattedValuePreferenceStore, SyncVariableDataAccess access) {
|
||||
public VariableCellModifier(AbstractCachingVMProvider provider,
|
||||
IFormattedValuePreferenceStore formattedValuePreferenceStore, SyncVariableDataAccess access)
|
||||
{
|
||||
fProvider = provider;
|
||||
fDataAccess = access;
|
||||
fPrefStore = formattedValuePreferenceStore;
|
||||
}
|
||||
|
@ -69,7 +75,7 @@ public class VariableLayoutValueCellModifier extends WatchExpressionCellModifier
|
|||
* Find the presentation context and then use it to get the current desired format.
|
||||
*/
|
||||
IVMContext ctx = (IVMContext) element;
|
||||
IPresentationContext presCtx = ctx.getLayoutNode().getVMProvider().getPresentationContext();
|
||||
IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
|
||||
|
||||
formatId = fPrefStore.getCurrentNumericFormat(presCtx);
|
||||
}
|
||||
|
@ -107,7 +113,7 @@ public class VariableLayoutValueCellModifier extends WatchExpressionCellModifier
|
|||
* Find the presentation context and then use it to get the current desired format.
|
||||
*/
|
||||
IVMContext ctx = (IVMContext) element;
|
||||
IPresentationContext presCtx = ctx.getLayoutNode().getVMProvider().getPresentationContext();
|
||||
IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
|
||||
|
||||
formatId = fPrefStore.getCurrentNumericFormat(presCtx);
|
||||
}
|
||||
|
@ -115,7 +121,7 @@ public class VariableLayoutValueCellModifier extends WatchExpressionCellModifier
|
|||
formatId = IFormattedValues.NATURAL_FORMAT;
|
||||
}
|
||||
|
||||
fDataAccess.writeVariable(element, (String) value, formatId);
|
||||
fProvider.handleEvent(new UserEditEvent(element));
|
||||
}
|
||||
}
|
||||
else {
|
|
@ -11,10 +11,14 @@ package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
|
@ -23,6 +27,7 @@ import org.eclipse.dd.dsf.debug.service.IExpressions;
|
|||
import org.eclipse.dd.dsf.debug.service.IFormattedValues;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IStack;
|
||||
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionChangedDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMData;
|
||||
import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
|
||||
|
@ -32,17 +37,16 @@ import org.eclipse.dd.dsf.debug.service.IStack.IVariableDMContext;
|
|||
import org.eclipse.dd.dsf.debug.service.IStack.IVariableDMData;
|
||||
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.AbstractExpressionLayoutNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.IExpressionUpdate;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.IFormattedValueVMContext;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.CompositeDMVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.IDMVMContext;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.model.IDebugTarget;
|
||||
|
@ -53,32 +57,27 @@ import org.eclipse.debug.internal.ui.DebugUIPlugin;
|
|||
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
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.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapterExtension;
|
||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||
import org.eclipse.jface.viewers.CellEditor;
|
||||
import org.eclipse.jface.viewers.ICellModifier;
|
||||
import org.eclipse.jface.viewers.TextCellEditor;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
@SuppressWarnings({"restriction", "nls"})
|
||||
public class VariableLayoutNode extends AbstractExpressionLayoutNode implements IElementEditor {
|
||||
|
||||
/**
|
||||
* List of child nodes containing only a reference to this. This is what enables the view model
|
||||
* provider to know about the recursive nature of subexpression nodes.
|
||||
*/
|
||||
private final IVMLayoutNode[] fChildLayoutNodes = { this };
|
||||
|
||||
@Override
|
||||
public IVMLayoutNode[] getChildLayoutNodes() {
|
||||
return fChildLayoutNodes;
|
||||
}
|
||||
public class VariableVMNode extends AbstractExpressionVMNode
|
||||
implements IElementEditor, IElementLabelProvider
|
||||
{
|
||||
|
||||
private final static int MAX_STRING_VALUE_LENGTH = 40;
|
||||
|
||||
@Override
|
||||
public int getDeltaFlags(Object e) {
|
||||
/*
|
||||
* @see buildDelta()
|
||||
|
@ -92,21 +91,22 @@ public class VariableLayoutNode extends AbstractExpressionLayoutNode implements
|
|||
return IModelDelta.STATE;
|
||||
}
|
||||
|
||||
if (e instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildDelta(final Object event, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
|
||||
public void buildDelta(final Object event, final ModelDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
|
||||
|
||||
if (event instanceof IRunControl.ISuspendedDMEvent) {
|
||||
parentDelta.addFlags(IModelDelta.CONTENT);
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
else if ( event instanceof IExpressions.IExpressionChangedDMEvent) {
|
||||
/*
|
||||
* Flush the cache.
|
||||
*/
|
||||
VMCacheManager.getVMCacheManager().flush(super.getVMProvider().getPresentationContext());
|
||||
|
||||
if ( event instanceof IExpressions.IExpressionChangedDMEvent) {
|
||||
/*
|
||||
* Logically one would think that STATE should be specified here. But we specifiy CONTENT
|
||||
* as well so that if there sub expressions which are affected in some way ( such as with
|
||||
|
@ -115,6 +115,12 @@ public class VariableLayoutNode extends AbstractExpressionLayoutNode implements
|
|||
parentDelta.addNode( createVMContext(((IExpressions.IExpressionChangedDMEvent)event).getDMContext()), IModelDelta.CONTENT | IModelDelta.STATE );
|
||||
}
|
||||
|
||||
if (event instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
requestMonitor.done();
|
||||
}
|
||||
|
||||
|
@ -189,7 +195,7 @@ public class VariableLayoutNode extends AbstractExpressionLayoutNode implements
|
|||
|
||||
VariableExpressionVMC exprVmc = (VariableExpressionVMC) variable;
|
||||
|
||||
IExpressionDMContext exprDmc = DMContexts.getAncestorOfType(exprVmc.getDMC(), IExpressionDMContext.class);
|
||||
IExpressionDMContext exprDmc = DMContexts.getAncestorOfType(exprVmc.getDMContext(), IExpressionDMContext.class);
|
||||
if (exprDmc != null) {
|
||||
return exprDmc.getExpression();
|
||||
}
|
||||
|
@ -200,32 +206,42 @@ public class VariableLayoutNode extends AbstractExpressionLayoutNode implements
|
|||
|
||||
final protected VariableExpressionFactory fVariableExpressionFactory = new VariableExpressionFactory();
|
||||
|
||||
public VariableLayoutNode(IFormattedValuePreferenceStore prefStore, AbstractVMProvider provider,
|
||||
DsfSession session, SyncVariableDataAccess syncVariableDataAccess) {
|
||||
public VariableVMNode(IFormattedValuePreferenceStore prefStore, AbstractDMVMProvider provider,
|
||||
DsfSession session, SyncVariableDataAccess syncVariableDataAccess)
|
||||
{
|
||||
super(provider, session, IExpressions.IExpressionDMContext.class);
|
||||
fFormattedPrefStore = prefStore;
|
||||
fSyncVariableDataAccess = syncVariableDataAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IVMContext createVMContext(IDMContext dmc) {
|
||||
protected IDMVMContext createVMContext(IDMContext dmc) {
|
||||
return new VariableExpressionVMC(dmc);
|
||||
}
|
||||
|
||||
/**
|
||||
* We override this method because we now need to perform an extra level of data fetch to get the
|
||||
* formatted value of the expression.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@Override
|
||||
|
||||
public void update(final ILabelUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updateLabelInSessionThread(updates);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (ILabelUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
|
||||
final IExpressionDMContext dmc = findDmcInPath(update.getElementPath(), IExpressions.IExpressionDMContext.class);
|
||||
final IExpressionDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExpressions.IExpressionDMContext.class);
|
||||
|
||||
VMCacheManager.getVMCacheManager().getCache(update.getPresentationContext())
|
||||
.getModelData(getServicesTracker().getService(IExpressions.class, null),
|
||||
getDMVMProvider().getModelData(
|
||||
this, update,
|
||||
getServicesTracker().getService(IExpressions.class, null),
|
||||
dmc,
|
||||
new DataRequestMonitor<IExpressionDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
|
@ -381,8 +397,9 @@ public class VariableLayoutNode extends AbstractExpressionLayoutNode implements
|
|||
*/
|
||||
final FormattedValueDMContext valueDmc = expressionService.getFormattedValueContext(dmc, finalFormatId);
|
||||
|
||||
VMCacheManager.getVMCacheManager().getCache(update.getPresentationContext())
|
||||
.getModelData(expressionService,
|
||||
getDMVMProvider().getModelData(
|
||||
VariableVMNode.this, update,
|
||||
expressionService,
|
||||
valueDmc,
|
||||
new DataRequestMonitor<FormattedValueDMData>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
|
@ -403,11 +420,11 @@ public class VariableLayoutNode extends AbstractExpressionLayoutNode implements
|
|||
update.setLabel(stringValueBuf.toString(), labelIndex);
|
||||
|
||||
// Color based on change history
|
||||
FormattedValueDMData oldData = (FormattedValueDMData) VMCacheManager.getVMCacheManager()
|
||||
.getCache(VariableLayoutNode.this.getVMProvider().getPresentationContext())
|
||||
.getArchivedModelData(valueDmc);
|
||||
FormattedValueDMData oldData = (FormattedValueDMData) getDMVMProvider().getArchivedModelData(
|
||||
VariableVMNode.this, update, valueDmc);
|
||||
|
||||
IExpressionDMData oldDMData = (IExpressionDMData) VMCacheManager.getVMCacheManager().getCache(update.getPresentationContext()).getArchivedModelData(dmc);
|
||||
IExpressionDMData oldDMData = (IExpressionDMData) getDMVMProvider().getArchivedModelData(
|
||||
VariableVMNode.this, update, dmc);
|
||||
String oldStringValue = oldDMData == null ? null : oldDMData.getStringValue();
|
||||
|
||||
// highlight the value if either the value (address) has changed or the string (memory at the value) has changed
|
||||
|
@ -441,19 +458,51 @@ public class VariableLayoutNode extends AbstractExpressionLayoutNode implements
|
|||
}
|
||||
|
||||
public ICellModifier getCellModifier(IPresentationContext context, Object element) {
|
||||
return new VariableLayoutValueCellModifier(fFormattedPrefStore, fSyncVariableDataAccess);
|
||||
return new VariableCellModifier(getDMVMProvider(), fFormattedPrefStore, fSyncVariableDataAccess);
|
||||
}
|
||||
|
||||
public boolean canParseExpression(IExpression expression) {
|
||||
// Indicate that we can parse any expression that does not start with
|
||||
// the reserved '$' and '#' characters.
|
||||
String expressionText = expression.getExpressionText();
|
||||
return !expressionText.startsWith("$") && !expressionText.startsWith("#");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getElementForExpressionPart(IChildrenUpdate update, String expressionPartText, DataRequestMonitor<Object> rm) {
|
||||
CompositeDMVMContext compositeDmc = new CompositeDMVMContext(getVMProvider().getRootElement(), update.getElementPath());
|
||||
public void update(final IExpressionUpdate update) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
|
||||
if (expressionService != null) {
|
||||
IExpressionDMContext expressionDMC = expressionService.createExpression(
|
||||
new CompositeDMVMContext(update),
|
||||
update.getExpression().getExpressionText());
|
||||
VariableExpressionVMC variableVmc = new VariableExpressionVMC(expressionDMC);
|
||||
variableVmc.setExpression(update.getExpression());
|
||||
|
||||
final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
|
||||
IExpressionDMContext expressionDMC = expressionService.createExpression(compositeDmc, expressionPartText);
|
||||
rm.setData(createVMContext(expressionDMC));
|
||||
rm.done();
|
||||
update.setExpressionElement(variableVmc);
|
||||
update.done();
|
||||
} else {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException e) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void handleFailedUpdate(IViewerUpdate update) {
|
||||
if (update instanceof IExpressionUpdate) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Update failed", null)); //$NON-NLS-1$
|
||||
update.done();
|
||||
} else {
|
||||
super.handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void associateExpression(Object element, IExpression expression) {
|
||||
if (element instanceof VariableExpressionVMC) {
|
||||
|
@ -461,36 +510,60 @@ public class VariableLayoutNode extends AbstractExpressionLayoutNode implements
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDeltaFlagsForExpressionPart(Object event) {
|
||||
public int getDeltaFlagsForExpression(IExpression expression, Object event) {
|
||||
if (event instanceof IRunControl.ISuspendedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
if (event instanceof IExpressionChangedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
if (event instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void testContextForExpression(Object element, String expression, DataRequestMonitor<Boolean> rm) {
|
||||
/*
|
||||
* Since we are overriding "getElementForExpression" we do not need to do anything here. But
|
||||
* we are forced to supply this routine because it is abstract in the extending class.
|
||||
*/
|
||||
public void buildDeltaForExpression(IExpression expression, int elementIdx, Object event, ModelDelta parentDelta,
|
||||
TreePath path, RequestMonitor rm)
|
||||
{
|
||||
rm.done();
|
||||
}
|
||||
|
||||
public int getExpressionLength(String expression) {
|
||||
/*
|
||||
* Since we are overriding "getElementForExpression" we do not need to do anything here.
|
||||
* We just assume the entire expression is for us.
|
||||
*/
|
||||
return expression.length() ;
|
||||
public void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, ModelDelta parentDelta,
|
||||
RequestMonitor rm)
|
||||
{
|
||||
if (event instanceof IRunControl.ISuspendedDMEvent) {
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
if ( event instanceof IExpressions.IExpressionChangedDMEvent) {
|
||||
/*
|
||||
* Logically one would think that STATE should be specified here. But we specify CONTENT
|
||||
* as well so that if there sub expressions which are affected in some way ( such as with
|
||||
* an expanded union then they will show the changes also.
|
||||
*/
|
||||
parentDelta.addNode(element, IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
|
||||
if (event instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE)
|
||||
{
|
||||
parentDelta.addNode(element, IModelDelta.CONTENT);
|
||||
}
|
||||
|
||||
rm.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
// Get the data model context object for the current node in the hierarchy.
|
||||
|
||||
final IExpressionDMContext expressionDMC = findDmcInPath(update.getElementPath(), IExpressionDMContext.class);
|
||||
final IExpressionDMContext expressionDMC = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExpressionDMContext.class);
|
||||
|
||||
if ( expressionDMC != null ) {
|
||||
getSubexpressionsUpdateElementsInSessionThread( update );
|
||||
|
@ -502,7 +575,7 @@ public class VariableLayoutNode extends AbstractExpressionLayoutNode implements
|
|||
|
||||
private void getSubexpressionsUpdateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
|
||||
final IExpressionDMContext expressionDMC = findDmcInPath(update.getElementPath(), IExpressionDMContext.class);
|
||||
final IExpressionDMContext expressionDMC = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExpressionDMContext.class);
|
||||
|
||||
if ( expressionDMC != null ) {
|
||||
|
||||
|
@ -542,7 +615,7 @@ public class VariableLayoutNode extends AbstractExpressionLayoutNode implements
|
|||
|
||||
private void getLocalsUpdateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
|
||||
final IFrameDMContext frameDmc = findDmcInPath(update.getElementPath(), IFrameDMContext.class);
|
||||
final IFrameDMContext frameDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IFrameDMContext.class);
|
||||
|
||||
// Get the services we need to use.
|
||||
|
||||
|
@ -641,8 +714,7 @@ public class VariableLayoutNode extends AbstractExpressionLayoutNode implements
|
|||
|
||||
mrm.add(rm);
|
||||
|
||||
VMCacheManager.getVMCacheManager().getCache(VariableLayoutNode.this.getVMProvider().getPresentationContext())
|
||||
.getModelData(stackFrameService, localDMC, rm, getExecutor());
|
||||
getDMVMProvider().getModelData(VariableVMNode.this, update, stackFrameService, localDMC, rm, getExecutor());
|
||||
}
|
||||
}
|
||||
};
|
|
@ -8,23 +8,33 @@
|
|||
*/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.variable;
|
||||
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.dm.AbstractDebugDMVMProviderWithCache;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.numberformat.FormattedValuePreferenceStore;
|
||||
import org.eclipse.dd.dsf.debug.ui.viewmodel.update.BreakpointHitUpdatePolicy;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.DMVMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.RootDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.AutomaticUpdatePolicy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.IVMUpdatePolicy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.ManualUpdatePolicy;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.jface.util.IPropertyChangeListener;
|
||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class VariableVMProvider extends AbstractDebugDMVMProviderWithCache implements IColumnPresentationFactory {
|
||||
public class VariableVMProvider extends AbstractDMVMProvider
|
||||
implements IPropertyChangeListener, IColumnPresentationFactory
|
||||
{
|
||||
|
||||
public VariableVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
|
||||
super(adapter, context, session);
|
||||
|
||||
context.addPropertyChangeListener(this);
|
||||
|
||||
/*
|
||||
* Create the variable data access routines.
|
||||
*/
|
||||
|
@ -33,18 +43,24 @@ public class VariableVMProvider extends AbstractDebugDMVMProviderWithCache imple
|
|||
/*
|
||||
* Create the top level node to deal with the root selection.
|
||||
*/
|
||||
IVMRootLayoutNode debugViewSelection = new DMVMRootLayoutNode(this);
|
||||
IRootVMNode rootNode = new RootDMVMNode(this);
|
||||
setRootNode(rootNode);
|
||||
|
||||
/*
|
||||
* Create the next level which represents members of structs/unions/enums and elements of arrays.
|
||||
*/
|
||||
IVMLayoutNode subExpressioNode = new VariableLayoutNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), varAccess);
|
||||
debugViewSelection.setChildNodes(new IVMLayoutNode[] { subExpressioNode });
|
||||
IVMNode subExpressioNode = new VariableVMNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), varAccess);
|
||||
addChildNodes(rootNode, new IVMNode[] { subExpressioNode });
|
||||
|
||||
/*
|
||||
* Now set this schema set as the layout set.
|
||||
*/
|
||||
setRootLayoutNode(debugViewSelection);
|
||||
// Configure the sub-expression node to be a child of itself. This way the content
|
||||
// provider will recursively drill-down the variable hierarchy.
|
||||
addChildNodes(subExpressioNode, new IVMNode[] { subExpressioNode });
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
getPresentationContext().removePropertyChangeListener(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,4 +72,14 @@ public class VariableVMProvider extends AbstractDebugDMVMProviderWithCache imple
|
|||
public String getColumnPresentationId(IPresentationContext context, Object element) {
|
||||
return VariableColumnPresentation.ID;
|
||||
}
|
||||
|
||||
public void propertyChange(PropertyChangeEvent event) {
|
||||
handleEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IVMUpdatePolicy[] createUpdateModes() {
|
||||
return new IVMUpdatePolicy[] { new AutomaticUpdatePolicy(), new ManualUpdatePolicy(), new BreakpointHitUpdatePolicy() };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,4 +3,5 @@ output.. = bin/
|
|||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.xml,\
|
||||
plugin.properties,\
|
||||
about.html
|
||||
|
|
|
@ -15,6 +15,5 @@ Export-Package: org.eclipse.dd.dsf.ui.concurrent,
|
|||
org.eclipse.dd.dsf.ui.viewmodel,
|
||||
org.eclipse.dd.dsf.ui.viewmodel.dm,
|
||||
org.eclipse.dd.dsf.ui.viewmodel.properties,
|
||||
org.eclipse.dd.dsf.ui.viewmodel.update,
|
||||
org.eclipse.dd.dsf.ui.viewmodel.update.actions
|
||||
org.eclipse.dd.dsf.ui.viewmodel.update
|
||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||
|
|
|
@ -3,4 +3,5 @@ output.. = bin/
|
|||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.xml,\
|
||||
plugin.properties,\
|
||||
about.html
|
||||
|
|
|
@ -22,11 +22,18 @@ import java.util.concurrent.ScheduledFuture;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DefaultDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfExecutable;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.SWTException;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
/**
|
||||
* DSF executor which uses the display thread to run the submitted runnables
|
||||
* and callables. The implementation is based on the default DSF executor
|
||||
* which still creates its own thread. However this thread blocks when running
|
||||
* each executable in the display thread.
|
||||
*/
|
||||
public class DisplayDsfExecutor extends DefaultDsfExecutor
|
||||
{
|
||||
/**
|
||||
|
@ -61,6 +68,15 @@ public class DisplayDsfExecutor extends DefaultDsfExecutor
|
|||
fDisplay = display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to check if we're in the display thread rather than the helper
|
||||
* thread of the super-class.
|
||||
*/
|
||||
@Override
|
||||
public boolean isInExecutorThread() {
|
||||
return Thread.currentThread().equals(fDisplay.getThread());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a callable wrapper, which delegates to the display to perform the
|
||||
* operation. The callable blocks the executor thread while each call
|
||||
|
@ -70,7 +86,13 @@ public class DisplayDsfExecutor extends DefaultDsfExecutor
|
|||
* @return Wrapper callable.
|
||||
*/
|
||||
private <V> Callable<V> createSWTDispatchCallable(final Callable<V> callable) {
|
||||
return new Callable<V>() {
|
||||
// Check if executable wasn't executed already.
|
||||
if (DEBUG_EXECUTOR && callable instanceof DsfExecutable) {
|
||||
assert !((DsfExecutable)callable).getSubmitted() : "Executable was previously executed."; //$NON-NLS-1$
|
||||
((DsfExecutable)callable).setSubmitted();
|
||||
}
|
||||
|
||||
return new Callable<V>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public V call() throws Exception {
|
||||
final Object[] v = new Object[1];
|
||||
|
@ -110,7 +132,14 @@ public class DisplayDsfExecutor extends DefaultDsfExecutor
|
|||
* @return Wrapper runnable.
|
||||
*/
|
||||
private Runnable createSWTDispatchRunnable(final Runnable runnable) {
|
||||
return new Runnable() {
|
||||
|
||||
// Check if executable wasn't executed already.
|
||||
if (DEBUG_EXECUTOR && runnable instanceof DsfExecutable) {
|
||||
assert !((DsfExecutable)runnable).getSubmitted() : "Executable was previously executed."; //$NON-NLS-1$
|
||||
((DsfExecutable)runnable).setSubmitted();
|
||||
}
|
||||
|
||||
return new Runnable() {
|
||||
public void run() {
|
||||
final Throwable[] e = new Throwable[1];
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.ui.concurrent;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
|
||||
/**
|
||||
* Counting multi data request monitor that takes a <code>IViewerUpdate</code>
|
||||
* as a parent. If the IViewerUpdate is canceled, this request monitor becomes
|
||||
* canceled as well.
|
||||
*
|
||||
* @see IViewerUpdate.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class ViewerCountingRequestMonitor extends CountingRequestMonitor {
|
||||
|
||||
private final IViewerUpdate fUpdate;
|
||||
public ViewerCountingRequestMonitor(Executor executor, IViewerUpdate update) {
|
||||
super(executor, null);
|
||||
fUpdate = update;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isCanceled() {
|
||||
return fUpdate.isCanceled() || super.isCanceled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
fUpdate.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleError() {
|
||||
fUpdate.setStatus(getStatus());
|
||||
fUpdate.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleCancel() {
|
||||
fUpdate.setStatus(getStatus());
|
||||
fUpdate.done();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.ui.concurrent;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
|
||||
/**
|
||||
* Data Request monitor that takean <code>IViewerUpdate</code> as a parent.
|
||||
* If the IViewerUpdate is canceled, this request monitor becomes canceled as well.
|
||||
* @see IViewerUpdate
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class ViewerDataRequestMonitor<V> extends DataRequestMonitor<V> {
|
||||
|
||||
private final IViewerUpdate fUpdate;
|
||||
public ViewerDataRequestMonitor(Executor executor, IViewerUpdate update) {
|
||||
super(executor, null);
|
||||
fUpdate = update;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isCanceled() {
|
||||
return fUpdate.isCanceled() || super.isCanceled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
fUpdate.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleError() {
|
||||
fUpdate.setStatus(getStatus());
|
||||
fUpdate.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleCancel() {
|
||||
fUpdate.setStatus(getStatus());
|
||||
fUpdate.done();
|
||||
}
|
||||
}
|
|
@ -17,9 +17,6 @@ import java.util.concurrent.RejectedExecutionException;
|
|||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DefaultDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.DsfUIPlugin;
|
||||
|
@ -41,7 +38,6 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
|||
@SuppressWarnings("restriction")
|
||||
abstract public class AbstractVMAdapter implements IVMAdapter
|
||||
{
|
||||
private final DsfExecutor fExecutor;
|
||||
private boolean fDisposed;
|
||||
|
||||
private final Map<IPresentationContext, IVMProvider> fViewModelProviders =
|
||||
|
@ -56,16 +52,6 @@ abstract public class AbstractVMAdapter implements IVMAdapter
|
|||
* @param session
|
||||
*/
|
||||
public AbstractVMAdapter() {
|
||||
fExecutor = new DefaultDsfExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the executor that will be used to communicate with the providers
|
||||
* and the layout nodes.
|
||||
* @return
|
||||
*/
|
||||
public DsfExecutor getExecutor() {
|
||||
return fExecutor;
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
|
@ -85,89 +71,80 @@ abstract public class AbstractVMAdapter implements IVMAdapter
|
|||
}
|
||||
|
||||
public void dispose() {
|
||||
// Execute the shutdown in adapter's dispatch thread.
|
||||
getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
synchronized(fViewModelProviders) {
|
||||
fDisposed = true;
|
||||
for (IVMProvider provider : fViewModelProviders.values()) {
|
||||
IVMProvider[] providers = new IVMProvider[0];
|
||||
synchronized(fViewModelProviders) {
|
||||
providers = fViewModelProviders.values().toArray(new IVMProvider[fViewModelProviders.size()]);
|
||||
fViewModelProviders.clear();
|
||||
fDisposed = true;
|
||||
}
|
||||
|
||||
for (final IVMProvider provider : providers) {
|
||||
try {
|
||||
provider.getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
provider.dispose();
|
||||
}
|
||||
fViewModelProviders.clear();
|
||||
}
|
||||
fExecutor.shutdown();
|
||||
});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Not much we can do at this point.
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void update(IHasChildrenUpdate[] updates) {
|
||||
handleUpdates(updates);
|
||||
IVMProvider provider = getVMProvider(updates[0].getPresentationContext());
|
||||
if (provider != null) {
|
||||
updateProvider(provider, updates);
|
||||
} else {
|
||||
for (IViewerUpdate update : updates) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR,
|
||||
"No model provider for update " + update, null)); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void update(IChildrenCountUpdate[] updates) {
|
||||
handleUpdates(updates);
|
||||
IVMProvider provider = getVMProvider(updates[0].getPresentationContext());
|
||||
if (provider != null) {
|
||||
updateProvider(provider, updates);
|
||||
} else {
|
||||
for (IViewerUpdate update : updates) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR,
|
||||
"No model provider for update " + update, null)); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void update(final IChildrenUpdate[] updates) {
|
||||
handleUpdates(updates);
|
||||
}
|
||||
|
||||
private void handleUpdates(final IViewerUpdate[] updates) {
|
||||
try {
|
||||
getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
IPresentationContext context = null;
|
||||
int firstIdx = 0;
|
||||
int curIdx = 0;
|
||||
for (curIdx = 0; curIdx < updates.length; curIdx++) {
|
||||
if (!updates[curIdx].getPresentationContext().equals(context)) {
|
||||
if (context != null) {
|
||||
callProviderWithUpdate(updates, firstIdx, curIdx);
|
||||
}
|
||||
context = updates[curIdx].getPresentationContext();
|
||||
firstIdx = curIdx;
|
||||
}
|
||||
}
|
||||
callProviderWithUpdate(updates, firstIdx, curIdx);
|
||||
}
|
||||
});
|
||||
} catch(RejectedExecutionException e) {
|
||||
for (IViewerUpdate update : updates) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, "VM adapter executor not available", e)); //$NON-NLS-1$
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void callProviderWithUpdate(IViewerUpdate[] updates, int startIdx, int endIdx) {
|
||||
final IVMProvider provider = getVMProvider(updates[0].getPresentationContext());
|
||||
if (provider == null) {
|
||||
IVMProvider provider = getVMProvider(updates[0].getPresentationContext());
|
||||
if (provider != null) {
|
||||
updateProvider(provider, updates);
|
||||
} else {
|
||||
for (IViewerUpdate update : updates) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR,
|
||||
"No model provider for update " + update, null)); //$NON-NLS-1$
|
||||
update.done();
|
||||
"No model provider for update " + update, null)); //$NON-NLS-1$
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (startIdx == 0 && endIdx == updates.length) {
|
||||
if (updates instanceof IHasChildrenUpdate[]) provider.update((IHasChildrenUpdate[])updates);
|
||||
else if (updates instanceof IChildrenCountUpdate[]) provider.update((IChildrenCountUpdate[])updates);
|
||||
else if (updates instanceof IChildrenUpdate[]) provider.update((IChildrenUpdate[])updates);
|
||||
} else {
|
||||
if (updates instanceof IHasChildrenUpdate[]) {
|
||||
IHasChildrenUpdate[] providerUpdates = new IHasChildrenUpdate[endIdx - startIdx];
|
||||
System.arraycopy(updates, startIdx, providerUpdates, 0, endIdx - startIdx);
|
||||
provider.update(providerUpdates);
|
||||
}
|
||||
else if (updates instanceof IChildrenCountUpdate[]) {
|
||||
IChildrenCountUpdate[] providerUpdates = new IChildrenCountUpdate[endIdx - startIdx];
|
||||
System.arraycopy(updates, startIdx, providerUpdates, 0, endIdx - startIdx);
|
||||
provider.update(providerUpdates);
|
||||
}
|
||||
else if (updates instanceof IChildrenUpdate[]) {
|
||||
IChildrenUpdate[] providerUpdates = new IChildrenUpdate[endIdx - startIdx];
|
||||
System.arraycopy(updates, startIdx, providerUpdates, 0, endIdx - startIdx);
|
||||
provider.update(providerUpdates);
|
||||
}
|
||||
|
||||
private void updateProvider(final IVMProvider provider, final IViewerUpdate[] updates) {
|
||||
try {
|
||||
provider.getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (updates instanceof IHasChildrenUpdate[]) {
|
||||
provider.update((IHasChildrenUpdate[])updates);
|
||||
} else if (updates instanceof IChildrenCountUpdate[]) {
|
||||
provider.update((IChildrenCountUpdate[])updates);
|
||||
} else if (updates instanceof IChildrenUpdate[]) {
|
||||
provider.update((IChildrenUpdate[])updates);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (IViewerUpdate update : updates) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR,
|
||||
"Display is disposed, cannot complete update " + update, null)); //$NON-NLS-1$
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package org.eclipse.dd.dsf.ui.viewmodel;
|
||||
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
|
||||
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.IModelProxyFactory;
|
||||
|
||||
/**
|
||||
* Implementation of basic view model context interface. The main
|
||||
* purpose of the VMC wrapper is to re-direct adapter queries to the IVMAdapter
|
||||
* and the layout node that the given context was created by.
|
||||
* <p/>
|
||||
* Note: Deriving classes must override the Object.equals/hashCode methods.
|
||||
* This is because the view model context objects are just wrappers that are
|
||||
* created by the view model on demand, so the equals methods must use the
|
||||
* object being wrapped to perform a meaningful comparison.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
abstract public class AbstractVMContext implements IVMContext {
|
||||
protected final IVMAdapter fVMAdapter;
|
||||
protected final IVMNode fNode;
|
||||
|
||||
public AbstractVMContext(IVMAdapter adapter, IVMNode node) {
|
||||
fVMAdapter = adapter;
|
||||
fNode = node;
|
||||
}
|
||||
|
||||
public IVMNode getVMNode() { return fNode; }
|
||||
|
||||
/**
|
||||
* IAdapter implementation returns the {@link IVMAdapter} instance for
|
||||
* the interfaces that are actually implemented by the VM Adapter.
|
||||
* These should at least include {@link IElementContentProvider},
|
||||
* {@link IModelProxyFactory}, and {@link IColumnPresentationFactory}.
|
||||
* It also returns the {@link IVMNode} instance for adapters implemented
|
||||
* by the context's node. The interfaces typically implemented by the
|
||||
* node include {@link IElementLabelProvider} and {@link IElementPropertiesProvider}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getAdapter(Class adapter) {
|
||||
if (adapter.isInstance(fVMAdapter)) {
|
||||
return fVMAdapter;
|
||||
} else if (adapter.isInstance(fNode)) {
|
||||
return fNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Deriving classes must override. */
|
||||
@Override
|
||||
abstract public boolean equals(Object obj);
|
||||
|
||||
/** Deriving classes must override. */
|
||||
@Override
|
||||
abstract public int hashCode();
|
||||
}
|
|
@ -1,517 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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.dd.dsf.ui.viewmodel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
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.IColumnPresentationFactory;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
|
||||
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.IModelProxyFactory;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* Base implementation of the View Model layout node.
|
||||
* The main functionality implemented here is for building the view model
|
||||
* deltas (IModelDelta), based on the flags returned by child nodes.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
|
||||
|
||||
private final AbstractVMProvider fProvider;
|
||||
private boolean fDisposed = false;
|
||||
|
||||
/** Child schema nodes of this node. */
|
||||
private IVMLayoutNode[] fChildNodes = new IVMLayoutNode[0];
|
||||
|
||||
|
||||
public AbstractVMLayoutNode(AbstractVMProvider provider) {
|
||||
fProvider = provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor method for sub-classes.
|
||||
*/
|
||||
protected DsfExecutor getExecutor() {
|
||||
return fProvider.getExecutor();
|
||||
}
|
||||
|
||||
public IVMProvider getVMProvider() {
|
||||
return fProvider;
|
||||
}
|
||||
|
||||
public void setChildNodes(IVMLayoutNode[] childNodes) {
|
||||
fChildNodes = childNodes;
|
||||
}
|
||||
|
||||
public IVMLayoutNode[] getChildLayoutNodes() {
|
||||
return fChildNodes;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
fDisposed = true;
|
||||
for (IVMLayoutNode childNode : getChildLayoutNodes()) {
|
||||
childNode.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If any of the children nodes have delta flags, that means that this
|
||||
* node has to generate a delta as well.
|
||||
* <p> Note: If a child node has a <code>IModelDelta.CONTENT</code> delta
|
||||
* flag, it means that this flag will be added to this node's element.
|
||||
* To allow for optimization change the child's <code>IModelDelta.CONTENT</code>
|
||||
* flag into a <code>IModelDelta.STATE</code> flag.
|
||||
*/
|
||||
public int getDeltaFlags(Object e) {
|
||||
int retVal = 0;
|
||||
for (IVMLayoutNode childNode : getChildLayoutNodes()) {
|
||||
int childNodeDeltaFlags = childNode.getDeltaFlags(e);
|
||||
if ((childNodeDeltaFlags | IModelDelta.CONTENT) != 0) {
|
||||
childNodeDeltaFlags &= ~IModelDelta.CONTENT;
|
||||
childNodeDeltaFlags |= IModelDelta.STATE;
|
||||
}
|
||||
retVal |= childNode.getDeltaFlags(e);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base implementation that handles calling child layout nodes to build
|
||||
* the model delta. The child nodes are called with all the elements
|
||||
* in this node, which could be very inefficient. In order to build delta
|
||||
* only for specific elements in this node, the class extending
|
||||
* <code>AbstractVMLayoutNode</code> should override this method.
|
||||
* @see IVMLayoutNode#buildDelta(Object, VMDelta, int, RequestMonitor)
|
||||
*/
|
||||
public void buildDelta(final Object event, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
|
||||
// Find the child nodes that have deltas for the given event.
|
||||
final Map<IVMLayoutNode,Integer> childNodesWithDeltaFlags = getChildNodesWithDeltaFlags(event);
|
||||
|
||||
// If no child layout nodes have deltas we can stop here.
|
||||
if (childNodesWithDeltaFlags.size() == 0) {
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the child delta only has an IModelDelta.CONTENT or
|
||||
// IModelDelta.STATE flags. If that's the case, we can skip
|
||||
// creating a delta for this node, because the TreeUpdatePolicy does not
|
||||
// use the full path from the delta to handle these flags.
|
||||
// Similarly, the index argument is not necessary either.
|
||||
boolean mustGetElements = false;
|
||||
for (int childDelta : childNodesWithDeltaFlags.values()) {
|
||||
if ((childDelta & ~IModelDelta.STATE) != 0) {
|
||||
mustGetElements = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mustGetElements) {
|
||||
callChildNodesToBuildDelta(childNodesWithDeltaFlags, parentDelta, event, requestMonitor);
|
||||
} else {
|
||||
// The given child layout nodes have deltas potentially for all elements
|
||||
// from this node. Retrieve all elements and call the child nodes with
|
||||
// each element as the parent of their delta.
|
||||
updateElements(new ElementsUpdate(
|
||||
new DataRequestMonitor<List<Object>>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (fDisposed) return;
|
||||
|
||||
// Check for an empty list of elements. If it's empty then we
|
||||
// don't have to call the children nodes, so return here.
|
||||
// No need to propagate error, there's no means or need to display it.
|
||||
if (!getStatus().isOK() || getData().size() == 0) {
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
final MultiRequestMonitor<RequestMonitor> elementsDeltasMultiRequestMon =
|
||||
new MultiRequestMonitor<RequestMonitor>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isDisposed()) return;
|
||||
requestMonitor.done();
|
||||
}
|
||||
};
|
||||
|
||||
// For each element from this node, create a new delta,
|
||||
// and then call all the child nodes to build their delta.
|
||||
for (int i = 0; i < getData().size(); i++) {
|
||||
VMDelta delta = parentDelta.addNode(getData().get(i), nodeOffset + i, IModelDelta.NO_CHANGE);
|
||||
callChildNodesToBuildDelta(
|
||||
childNodesWithDeltaFlags, delta, event,
|
||||
elementsDeltasMultiRequestMon.add(new RequestMonitor(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
elementsDeltasMultiRequestMon.requestMonitorDone(this);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
},
|
||||
parentDelta));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the specified child layout nodes to build the delta for the given event.
|
||||
* @param nodes Map of layout nodes to be invoked, and the corresponding delta
|
||||
* flags that they will generate. This map is generated with a call to
|
||||
* {@link #getChildNodesWithDeltaFlags(Object)}.
|
||||
* @param delta The delta object to build on. This delta should have been
|
||||
* gerated by this node, unless the full delta path is not being calculated
|
||||
* due to an optimization.
|
||||
* @param event The event object that the delta is being built for.
|
||||
* @param requestMonitor The result token to invoke when the delta is completed.
|
||||
*/
|
||||
protected void callChildNodesToBuildDelta(final Map<IVMLayoutNode,Integer> nodes, final VMDelta delta, final Object event, final RequestMonitor requestMonitor) {
|
||||
assert nodes.size() != 0;
|
||||
|
||||
// Check if any of the child nodes are will generate IModelDelta.SELECT or
|
||||
// IModelDelta.EXPAND flags. If so, we must calcuate the index for this
|
||||
// VMC.
|
||||
boolean calculateOffsets = false;
|
||||
for (int childDelta : nodes.values()) {
|
||||
if ( (childDelta & (IModelDelta.SELECT | IModelDelta.EXPAND)) != 0 ) {
|
||||
calculateOffsets = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
getChildNodesElementOffsets(
|
||||
delta, !calculateOffsets,
|
||||
new DataRequestMonitor<Map<IVMLayoutNode, Integer>>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
final MultiRequestMonitor<RequestMonitor> childrenBuildDeltaDoneCollector =
|
||||
new MultiRequestMonitor<RequestMonitor>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isDisposed()) return;
|
||||
requestMonitor.done();
|
||||
}
|
||||
};
|
||||
|
||||
// Set the total count of number of children in the parent delta.
|
||||
delta.setChildCount(getData().get(null));
|
||||
|
||||
for (IVMLayoutNode node : nodes.keySet()) {
|
||||
node.buildDelta(
|
||||
event, delta, getData().get(node),
|
||||
childrenBuildDeltaDoneCollector.add(new RequestMonitor(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
childrenBuildDeltaDoneCollector.requestMonitorDone(this);
|
||||
}})
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the indexes at which the elements of each of the child
|
||||
* layout nodes begin. These indexes are necessary to correctly
|
||||
* calculate the deltas for elements in the child nodes.
|
||||
* @param delta The delta object to build on. This delta should have been
|
||||
* gerated by this node, unless the full delta path is not being calculated
|
||||
* due to an optimization.
|
||||
* @param fakeIt If true, it causes this method to fill the return data
|
||||
* structure with dummy values. The dummy values indicate that the indexes
|
||||
* are not known and are acceptable in the delta if the delta flags being
|
||||
* generated do not require full index information.
|
||||
* @param rm Return token containing the results. The result data is a
|
||||
* mapping between the child nodes and the indexes at which the child nodes'
|
||||
* elements begin. There is a special value in the map with a <code>null</code>
|
||||
* key, which contains the full element count for all the nodes.
|
||||
*/
|
||||
private void getChildNodesElementOffsets(IModelDelta delta, boolean fakeIt, final DataRequestMonitor<Map<IVMLayoutNode, Integer>> rm) {
|
||||
assert getChildLayoutNodes().length != 0;
|
||||
|
||||
if (!fakeIt) {
|
||||
final Integer[] counts = new Integer[getChildLayoutNodes().length];
|
||||
final MultiRequestMonitor<RequestMonitor> childrenCountMultiRequestMon =
|
||||
new MultiRequestMonitor<RequestMonitor>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isDisposed()) return;
|
||||
super.handleCompleted();
|
||||
}
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
Map<IVMLayoutNode, Integer> data = new HashMap<IVMLayoutNode, Integer>();
|
||||
int offset = 0;
|
||||
for (int i = 0; i < getChildLayoutNodes().length; i++) {
|
||||
data.put(getChildLayoutNodes()[i], offset);
|
||||
offset += counts[i];
|
||||
}
|
||||
// As the final value, put the total count in the return map, with null key.
|
||||
data.put(null, offset);
|
||||
rm.setData(data);
|
||||
rm.done();
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < getChildLayoutNodes().length; i++) {
|
||||
final int nodeIndex = i;
|
||||
getChildLayoutNodes()[i].updateElementCount(
|
||||
new ElementsCountUpdate(
|
||||
childrenCountMultiRequestMon.add(
|
||||
new DataRequestMonitor<Integer>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
counts[nodeIndex] = getData();
|
||||
childrenCountMultiRequestMon.requestMonitorDone(this);
|
||||
}
|
||||
}),
|
||||
delta)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
Map<IVMLayoutNode, Integer> data = new HashMap<IVMLayoutNode, Integer>();
|
||||
for (int i = 0; i < getChildLayoutNodes().length; i++) {
|
||||
data.put(getChildLayoutNodes()[i], -1);
|
||||
}
|
||||
data.put(null, -1);
|
||||
rm.setData(data);
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isDisposed() {
|
||||
return fDisposed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that returns the child layout nodes which return
|
||||
* <code>true</code> to the <code>hasDeltaFlags()</code> test for the given
|
||||
* event.
|
||||
*/
|
||||
protected Map<IVMLayoutNode, Integer> getChildNodesWithDeltaFlags(Object e) {
|
||||
Map<IVMLayoutNode, Integer> nodes = new HashMap<IVMLayoutNode, Integer>();
|
||||
for (final IVMLayoutNode childNode : getChildLayoutNodes()) {
|
||||
int delta = childNode.getDeltaFlags(e);
|
||||
if (delta != IModelDelta.NO_CHANGE) {
|
||||
nodes.put(childNode, delta);
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that returns a token value in case when the services
|
||||
* that the layout node depends on, are not available.
|
||||
*/
|
||||
protected boolean checkUpdate(IViewerUpdate update) {
|
||||
if (update.isCanceled()) {
|
||||
update.done();
|
||||
return false;
|
||||
}
|
||||
if (fDisposed) {
|
||||
handleFailedUpdate(update);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method that completes update object in case of an error.
|
||||
* Different types of update need to have some data configured to exhibit
|
||||
* desired behavior in the viewer.
|
||||
* @param update Update to handle.
|
||||
*/
|
||||
protected void handleFailedUpdate(IViewerUpdate update) {
|
||||
if (update instanceof IHasChildrenUpdate) {
|
||||
((IHasChildrenUpdate)update).setHasChilren(false);
|
||||
} else if (update instanceof IChildrenCountUpdate) {
|
||||
((IChildrenCountUpdate)update).setChildCount(0);
|
||||
} else if (update instanceof ILabelUpdate) {
|
||||
ILabelUpdate labelUpdate = (ILabelUpdate)update;
|
||||
String[] columns = labelUpdate.getPresentationContext().getColumns();
|
||||
for (int i = 0; i < (columns != null ? columns.length : 1); i++) {
|
||||
labelUpdate.setLabel("...", i); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of basic View Model Context node functionality. The main
|
||||
* purpose of the VMC wrapper is to re-direct adapter queries to the IVMAdapter
|
||||
* and the layout node that the given context was created by.
|
||||
* <p>
|
||||
* Note: Deriving classes must override the Object.equals/hashCode methods.
|
||||
* This is because the VMC objects are just wrappers that are created
|
||||
* by the view model on demand, so the equals methods must use the object
|
||||
* being wrapped by the VMC to perform a meaningful comparison.
|
||||
*/
|
||||
abstract public static class AbstractVMContext implements IVMContext {
|
||||
protected final IVMAdapter fVMAdapter;
|
||||
protected final IVMLayoutNode fLayoutNode;
|
||||
|
||||
public AbstractVMContext(IVMAdapter adapter, IVMLayoutNode node) {
|
||||
fVMAdapter = adapter;
|
||||
fLayoutNode = node;
|
||||
}
|
||||
|
||||
public IVMLayoutNode getLayoutNode() { return fLayoutNode; }
|
||||
|
||||
/**
|
||||
* IAdapter implementation returns the IVMAdapter instance for the
|
||||
* interfaces that are actually implemented by the VM Adapter. These
|
||||
* should at least include {@link IElementContentProvider},
|
||||
* {@link IModelProxyFactory}, and
|
||||
* {@link IColumnPresentationFactory}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getAdapter(Class adapter) {
|
||||
if (adapter.isInstance(fVMAdapter)) {
|
||||
return fVMAdapter;
|
||||
} else if (adapter.isInstance(fLayoutNode)) {
|
||||
return fLayoutNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Deriving classes must override. */
|
||||
@Override
|
||||
abstract public boolean equals(Object obj);
|
||||
|
||||
/** Deriving classes must override. */
|
||||
@Override
|
||||
abstract public int hashCode();
|
||||
}
|
||||
|
||||
protected TreePath getTreePathFromDelta(IModelDelta delta) {
|
||||
List<Object> elementList = new LinkedList<Object>();
|
||||
IModelDelta listDelta = delta;
|
||||
elementList.add(0, listDelta.getElement());
|
||||
while (listDelta.getParentDelta() != null) {
|
||||
elementList.add(0, listDelta.getElement());
|
||||
listDelta = listDelta.getParentDelta();
|
||||
}
|
||||
return new TreePath(elementList.toArray());
|
||||
}
|
||||
|
||||
protected class ViewerUpdate implements IViewerUpdate {
|
||||
|
||||
final private RequestMonitor fRequestMonitor;
|
||||
final private TreePath fTreePath;
|
||||
private IStatus fStatus;
|
||||
private boolean fCancelled = false;
|
||||
|
||||
public ViewerUpdate(RequestMonitor requestMonitor, IModelDelta delta) {
|
||||
fRequestMonitor = requestMonitor;
|
||||
List<Object> elementList = new LinkedList<Object>();
|
||||
IModelDelta listDelta = delta;
|
||||
elementList.add(0, listDelta.getElement());
|
||||
while (listDelta.getParentDelta() != null) {
|
||||
elementList.add(0, listDelta.getElement());
|
||||
listDelta = listDelta.getParentDelta();
|
||||
}
|
||||
fTreePath = new TreePath(elementList.toArray());
|
||||
}
|
||||
|
||||
public ViewerUpdate(RequestMonitor requestMonitor, TreePath path) {
|
||||
fRequestMonitor = requestMonitor;
|
||||
fTreePath = path;
|
||||
}
|
||||
|
||||
public Object getViewerInput() {
|
||||
return getVMProvider().getRootElement();
|
||||
}
|
||||
|
||||
public Object getElement() {
|
||||
return getElementPath().getLastSegment();
|
||||
}
|
||||
|
||||
public IPresentationContext getPresentationContext() { return getVMProvider().getPresentationContext(); }
|
||||
public TreePath getElementPath() { return fTreePath; }
|
||||
public IStatus getStatus() { return fStatus; }
|
||||
public void setStatus(IStatus status) { fStatus = status; }
|
||||
public boolean isCanceled() { return fCancelled; }
|
||||
public void cancel() { fCancelled = true; }
|
||||
|
||||
public void done() {
|
||||
try {
|
||||
fRequestMonitor.done();
|
||||
} catch (RejectedExecutionException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected class ElementsCountUpdate extends ViewerUpdate implements IChildrenCountUpdate {
|
||||
private final DataRequestMonitor<Integer> fElementCountRequestMonitor;
|
||||
|
||||
public ElementsCountUpdate(DataRequestMonitor<Integer> rm, IModelDelta delta) {
|
||||
super(rm, delta);
|
||||
fElementCountRequestMonitor = rm;
|
||||
}
|
||||
|
||||
public void setChildCount(int numChildren) {
|
||||
fElementCountRequestMonitor.setData(numChildren);
|
||||
}
|
||||
}
|
||||
|
||||
protected class ElementsUpdate extends ViewerUpdate implements IChildrenUpdate {
|
||||
private final List<Object> fChildren = new ArrayList<Object>();
|
||||
private DataRequestMonitor<List<Object>> fElementUpdateRequestMonitor;
|
||||
|
||||
public ElementsUpdate(DataRequestMonitor<List<Object>> rm, IModelDelta delta) {
|
||||
super(rm, delta);
|
||||
fElementUpdateRequestMonitor = rm;
|
||||
fElementUpdateRequestMonitor.setData(fChildren);
|
||||
}
|
||||
|
||||
public ElementsUpdate(DataRequestMonitor<List<Object>> rm, TreePath path) {
|
||||
super(rm, path);
|
||||
fElementUpdateRequestMonitor = rm;
|
||||
fElementUpdateRequestMonitor.setData(fChildren);
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void setChild(Object child, int offset) {
|
||||
fChildren.add(offset, child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VMElementsUpdate for all elements under parent = " + getElement(); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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.dd.dsf.ui.viewmodel;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
|
||||
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.IViewerUpdate;
|
||||
|
||||
/**
|
||||
* Base implementation of the view model node.
|
||||
* The main functionality implemented here is for building the view model
|
||||
* deltas (IModelDelta), based on the flags returned by child nodes.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
abstract public class AbstractVMNode implements IVMNode {
|
||||
|
||||
private final AbstractVMProvider fProvider;
|
||||
private boolean fDisposed = false;
|
||||
|
||||
public AbstractVMNode(AbstractVMProvider provider) {
|
||||
fProvider = provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor method for sub-classes.
|
||||
*/
|
||||
protected DsfExecutor getExecutor() {
|
||||
return fProvider.getExecutor();
|
||||
}
|
||||
|
||||
public IVMProvider getVMProvider() {
|
||||
return fProvider;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
fDisposed = true;
|
||||
}
|
||||
|
||||
public IVMContext getContextFromEvent(Object event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean isDisposed() {
|
||||
return fDisposed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that returns a token value in case when the services
|
||||
* that the layout node depends on, are not available.
|
||||
*/
|
||||
protected boolean checkUpdate(IViewerUpdate update) {
|
||||
if (update.isCanceled()) {
|
||||
update.done();
|
||||
return false;
|
||||
}
|
||||
if (fDisposed) {
|
||||
handleFailedUpdate(update);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method that completes update object in case of an error.
|
||||
* Different types of update need to have some data configured to exhibit
|
||||
* desired behavior in the viewer.
|
||||
* @param update Update to handle.
|
||||
*/
|
||||
protected void handleFailedUpdate(IViewerUpdate update) {
|
||||
if (update instanceof IHasChildrenUpdate) {
|
||||
((IHasChildrenUpdate)update).setHasChilren(false);
|
||||
} else if (update instanceof IChildrenCountUpdate) {
|
||||
((IChildrenCountUpdate)update).setChildCount(0);
|
||||
} else if (update instanceof ILabelUpdate) {
|
||||
ILabelUpdate labelUpdate = (ILabelUpdate)update;
|
||||
String[] columns = labelUpdate.getPresentationContext().getColumns();
|
||||
for (int i = 0; i < (columns != null ? columns.length : 1); i++) {
|
||||
labelUpdate.setLabel("...", i); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
}
|
|
@ -12,58 +12,55 @@ package org.eclipse.dd.dsf.ui.viewmodel;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.ISchedulingRule;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.DsfUIPlugin;
|
||||
import org.eclipse.dd.dsf.ui.concurrent.DisplayDsfExecutor;
|
||||
import org.eclipse.dd.dsf.ui.concurrent.ViewerDataRequestMonitor;
|
||||
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.IColumnPresentation;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||
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.IViewerInputProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy;
|
||||
import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousContentAdapter;
|
||||
import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapter;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
/**
|
||||
* View model provider implements the asynchronous view model functionality for
|
||||
* a single view. This provider is just a holder which further delegates the
|
||||
* model provider functionality to the view model layout nodes that need
|
||||
* model provider functionality to the view model nodes that need
|
||||
* to be configured with each provider.
|
||||
* <p>
|
||||
*
|
||||
* <p/>
|
||||
* The view model provider, often does not provide the model for the entire
|
||||
* view. Rather, it needs to be able to plug in at any level in the viewer's
|
||||
* content model and provide data for a sub-tree.
|
||||
*
|
||||
* <p/>
|
||||
* Clients are intended to extend this class.
|
||||
*
|
||||
* @see IAsynchronousContentAdapter
|
||||
* @see IAsynchronousLabelAdapter
|
||||
* @see IModelProxy
|
||||
* @see IVMLayoutNode
|
||||
* @see IVMNode
|
||||
*/
|
||||
@ConfinedToDsfExecutor("getVMAdapter#getExecutor")
|
||||
@SuppressWarnings("restriction")
|
||||
abstract public class AbstractVMProvider implements IVMProvider
|
||||
{
|
||||
|
||||
/** Reference to the VM adapter that owns this provider */
|
||||
private final AbstractVMAdapter fVMAdapter;
|
||||
|
||||
|
@ -71,15 +68,52 @@ abstract public class AbstractVMProvider implements IVMProvider
|
|||
private final IPresentationContext fPresentationContext;
|
||||
|
||||
/**
|
||||
* The current root element of this view model. This element is obtained
|
||||
* from the argument to {@link #createModelProxy(Object, IPresentationContext)}.
|
||||
* The executor that this VM provider operates in. This executor will be
|
||||
* initialized properly when we can access the display from the
|
||||
* IPresentationContext object (bug 213629). For now utilize the
|
||||
* assumption that there is only one display.
|
||||
*/
|
||||
private Object fRootElement;
|
||||
private final DsfExecutor fExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(Display.getDefault());
|
||||
|
||||
/**
|
||||
*
|
||||
* The element content provider implementation that this provider delegates to.
|
||||
* Sub-classes may override the content strategy used for custom functionality.
|
||||
*/
|
||||
private final IElementContentProvider fContentStrategy;
|
||||
|
||||
/**
|
||||
* The list of active model proxies in this provider. A new model
|
||||
* proxy is created when a viewer has a new input element
|
||||
* (see {@link #createModelProxy(Object, IPresentationContext)}).
|
||||
* Typically there will be only one active model proxy in a given
|
||||
* provider. However, if a view model provider fills only a sub-tree
|
||||
* in a viewer, and there are several sub-trees active in the same viewer
|
||||
* at the same time, each of these sub-trees will have it's own model
|
||||
* proxy.
|
||||
*/
|
||||
private List<IVMModelProxy> fActiveModelProxies = new LinkedList<IVMModelProxy>();
|
||||
|
||||
/**
|
||||
* Convencience constant.
|
||||
*/
|
||||
private static final IVMNode[] EMPTY_NODES_ARRAY = new IVMNode[0];
|
||||
|
||||
|
||||
/**
|
||||
* The mapping of parent to child nodes.
|
||||
*/
|
||||
private Map<IVMNode,IVMNode[]> fChildNodesMap =
|
||||
new HashMap<IVMNode,IVMNode[]>();
|
||||
|
||||
/**
|
||||
* Cached array of all the configued view model nodes. It is generated
|
||||
* based on the child nodes map.
|
||||
*/
|
||||
private IVMNode[] fNodesListCache = null;
|
||||
|
||||
/**
|
||||
* Flag indicating that the provider is disposed.
|
||||
*/
|
||||
private ModelProxy fModelProxy = new ModelProxy();
|
||||
private boolean fDisposed = false;
|
||||
|
||||
/**
|
||||
|
@ -87,7 +121,7 @@ abstract public class AbstractVMProvider implements IVMProvider
|
|||
* null when first created, to allow sub-classes to prorperly configure the
|
||||
* root node in the sub-class constructor.
|
||||
*/
|
||||
private AtomicReference<IVMRootLayoutNode> fRootLayoutNodeRef = new AtomicReference<IVMRootLayoutNode>();
|
||||
private IRootVMNode fRootNode;
|
||||
|
||||
/**
|
||||
* Constructs the view model provider for given DSF session. The
|
||||
|
@ -98,6 +132,7 @@ abstract public class AbstractVMProvider implements IVMProvider
|
|||
public AbstractVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext) {
|
||||
fVMAdapter = adapter;
|
||||
fPresentationContext = presentationContext;
|
||||
fContentStrategy = createContentStrategy();
|
||||
}
|
||||
|
||||
public IPresentationContext getPresentationContext() {
|
||||
|
@ -109,345 +144,321 @@ abstract public class AbstractVMProvider implements IVMProvider
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the root node for this provider.
|
||||
* Creates the strategy class that will be used to implement the content
|
||||
* provider interface of this view model provider. This method can be
|
||||
* overridden by sub-classes to provider custom content provider strategy.
|
||||
* <p/>
|
||||
* Note this method can be called by the base class constructor, therefore
|
||||
* it should not reference any fields initialized in the sub-class.
|
||||
*
|
||||
* @return New content provider implementation.
|
||||
*/
|
||||
@ThreadSafe
|
||||
protected void setRootLayoutNode(IVMRootLayoutNode rootLayoutNode) {
|
||||
final IVMRootLayoutNode oldRootLayoutNode = fRootLayoutNodeRef.getAndSet(rootLayoutNode);
|
||||
if (oldRootLayoutNode != null) {
|
||||
oldRootLayoutNode.dispose();
|
||||
protected IElementContentProvider createContentStrategy() {
|
||||
return new DefaultVMContentProviderStrategy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access method for the content provider strategy.
|
||||
*
|
||||
* @return Content provider implementation currently being used by this
|
||||
* class.
|
||||
*/
|
||||
protected IElementContentProvider getContentStrategy() {
|
||||
return fContentStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the strategy class that will be used to implement the content
|
||||
* model proxy of this view model provider. It is normally called by
|
||||
* {@link #createModelProxy(Object, IPresentationContext)} every time the
|
||||
* input in the viewer is updated. This method can be overridden by
|
||||
* sub-classes to provider custom model proxy strategy.
|
||||
*
|
||||
* @return New model proxy implementation.
|
||||
*/
|
||||
protected IVMModelProxy createModelProxyStrategy(Object rootElement) {
|
||||
return new DefaultVMModelProxyStrategy(this, rootElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of active proxies in this provider. The returned
|
||||
* list is not a copy and if a sub-class modifies this list, it will
|
||||
* modify the current list of active proxies. This allows the
|
||||
* sub-classes to change how the active proxies are managed and
|
||||
* retained.
|
||||
*/
|
||||
protected List<IVMModelProxy> getActiveModelProxies() {
|
||||
return fActiveModelProxies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the given event in the given provider, sending model
|
||||
* deltas if necessary.
|
||||
*/
|
||||
public void handleEvent(final Object event) {
|
||||
for (final IVMModelProxy proxyStrategy : getActiveModelProxies()) {
|
||||
if (proxyStrategy.isDeltaEvent(event)) {
|
||||
proxyStrategy.createDelta(
|
||||
event,
|
||||
new DataRequestMonitor<IModelDelta>(getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (getStatus().isOK()) {
|
||||
proxyStrategy.fireModelChanged(getData());
|
||||
}
|
||||
}
|
||||
@Override public String toString() {
|
||||
return "Result of a delta for event: '" + event.toString() + "' in VMP: '" + this + "'" + "\n" + getData().toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
protected synchronized ModelProxy getModelProxy() {
|
||||
return fModelProxy;
|
||||
|
||||
public IRootVMNode getRootVMNode() {
|
||||
return fRootNode;
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
public synchronized Object getRootElement() {
|
||||
return fRootElement;
|
||||
public IVMNode[] getAllVMNodes() {
|
||||
if (fNodesListCache != null) {
|
||||
return fNodesListCache;
|
||||
}
|
||||
List<IVMNode> list = new ArrayList<IVMNode>();
|
||||
for (IVMNode node : fChildNodesMap.keySet()) {
|
||||
if (node != null) {
|
||||
list.add(node);
|
||||
}
|
||||
}
|
||||
fNodesListCache = list.toArray(new IVMNode[list.size()]);;
|
||||
return fNodesListCache;
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
public IVMRootLayoutNode getRootLayoutNode() {
|
||||
return fRootLayoutNodeRef.get();
|
||||
public IVMNode[] getChildVMNodes(IVMNode node) {
|
||||
IVMNode[] retVal = fChildNodesMap.get(node);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
return EMPTY_NODES_ARRAY;
|
||||
}
|
||||
|
||||
/** Called to dispose the provider. */
|
||||
public void dispose() {
|
||||
fDisposed = true;
|
||||
if (fRootLayoutNodeRef.get() != null) {
|
||||
fRootLayoutNodeRef.get().dispose();
|
||||
/**
|
||||
* Configures the given array of nodes as children of the given parent node.
|
||||
* Sub-classes should call this method to define the hierarchy of nodes.
|
||||
*/
|
||||
protected void addChildNodes(IVMNode parentNode, IVMNode[] childNodes) {
|
||||
// Add to the child nodes array.
|
||||
IVMNode[] existingChildNodes = fChildNodesMap.get(parentNode);
|
||||
if (existingChildNodes == null) {
|
||||
fChildNodesMap.put(parentNode, childNodes);
|
||||
} else {
|
||||
IVMNode[] newNodes = new IVMNode[existingChildNodes.length + childNodes.length];
|
||||
System.arraycopy(existingChildNodes, 0, newNodes, 0, existingChildNodes.length);
|
||||
System.arraycopy(childNodes, 0, newNodes, existingChildNodes.length, childNodes.length);
|
||||
fChildNodesMap.put(parentNode, newNodes);
|
||||
}
|
||||
|
||||
// Make sure that each new expression node has an entry of its own.
|
||||
for (IVMNode childNode : childNodes) {
|
||||
addNode(childNode);
|
||||
}
|
||||
|
||||
fNodesListCache = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given node to configured nodes, without creating any
|
||||
* parent-child relationship for it. It is useful for providers which do have
|
||||
* a strict tree hierarchy of ndoes.
|
||||
*/
|
||||
protected void addNode(IVMNode node) {
|
||||
if (!fChildNodesMap.containsKey(node)) {
|
||||
fChildNodesMap.put(node, EMPTY_NODES_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows other subsystems to force the layout mode associated with the specified
|
||||
* VM context to refresh. If null is passed then the RootLayoutNode is told to refresh.
|
||||
* Clears all configured nodes. This allows a subclass to reset and
|
||||
* reconfigure its nodes.
|
||||
*/
|
||||
public void refresh(final IVMContext element) {
|
||||
try {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
if ( element == null ) {
|
||||
VMDelta rootDelta = new VMDelta(getRootElement(), IModelDelta.CONTENT);
|
||||
getModelProxy().fireModelChangedNonDispatch(rootDelta);
|
||||
}
|
||||
else {
|
||||
VMDelta elementDelta = new VMDelta(element, IModelDelta.CONTENT);
|
||||
getModelProxy().fireModelChangedNonDispatch(elementDelta);
|
||||
}
|
||||
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Ignore. This exception could be thrown if the provider is being
|
||||
// shut down.
|
||||
protected void clearNodes() {
|
||||
for (IVMNode node : fChildNodesMap.keySet()) {
|
||||
node.dispose();
|
||||
}
|
||||
return;
|
||||
fChildNodesMap.clear();
|
||||
fRootNode = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the root node for this provider.
|
||||
*/
|
||||
protected void setRootNode(IRootVMNode rootNode) {
|
||||
fRootNode = rootNode;
|
||||
}
|
||||
|
||||
/** Called to dispose the provider. */
|
||||
public void dispose() {
|
||||
clearNodes();
|
||||
fRootNode = null;
|
||||
}
|
||||
|
||||
public void update(final IHasChildrenUpdate[] updates) {
|
||||
fContentStrategy.update(updates);
|
||||
}
|
||||
|
||||
public void update(final IChildrenCountUpdate[] updates) {
|
||||
fContentStrategy.update(updates);
|
||||
}
|
||||
|
||||
public void update(final IChildrenUpdate[] updates) {
|
||||
fContentStrategy.update(updates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the given view model node to perform the given updates. This
|
||||
* method is called by view model provider and it's helper classes instead
|
||||
* of calling the IVMNode method directly, in order to allow additional
|
||||
* processing of the udpate. For example the AbstractCachingVMProvider
|
||||
* overrides this method to optionally return the results for an update from
|
||||
* a cache.
|
||||
*/
|
||||
protected void updateNode(final IVMNode node, IHasChildrenUpdate[] updates) {
|
||||
IHasChildrenUpdate[] updateProxies = new IHasChildrenUpdate[updates.length];
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
final IHasChildrenUpdate update = updates[i];
|
||||
updateProxies[i] = new VMHasChildrenUpdate(
|
||||
update,
|
||||
new ViewerDataRequestMonitor<Boolean>(getExecutor(), updates[i]) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
update.setHasChilren(getData());
|
||||
update.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleError() {
|
||||
if (getStatus().getCode() == IDsfService.NOT_SUPPORTED) {
|
||||
updateNode(
|
||||
node,
|
||||
new VMChildrenUpdate[] { new VMChildrenUpdate(
|
||||
update, -1, -1,
|
||||
new ViewerDataRequestMonitor<List<Object>>(getExecutor(), update) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
update.setHasChilren( !getData().isEmpty() );
|
||||
update.done();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
} else {
|
||||
update.setStatus(getStatus());
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
node.update(updateProxies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the given view model node to perform the given updates. This
|
||||
* method is called by view model provider and it's helper classes instead
|
||||
* of calling the IVMNode method directly, in order to allow additional
|
||||
* processing of the udpate. For example the AbstractCachingVMProvider
|
||||
* overrides this method to optionally return the results for an update from
|
||||
* a cache.
|
||||
*/
|
||||
protected void updateNode(final IVMNode node, IChildrenCountUpdate[] updates) {
|
||||
IChildrenCountUpdate[] updateProxies = new IChildrenCountUpdate[updates.length];
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
final IChildrenCountUpdate update = updates[i];
|
||||
updateProxies[i] = new VMChildrenCountUpdate(
|
||||
update,
|
||||
new ViewerDataRequestMonitor<Integer>(getExecutor(), updates[i]) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
update.setChildCount(getData());
|
||||
update.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleError() {
|
||||
if (getStatus().getCode() == IDsfService.NOT_SUPPORTED) {
|
||||
updateNode(
|
||||
node,
|
||||
new VMChildrenUpdate[] { new VMChildrenUpdate(
|
||||
update, -1, -1,
|
||||
new ViewerDataRequestMonitor<List<Object>>(getExecutor(), update) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
update.setChildCount( getData().size() );
|
||||
update.done();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
node.update(updateProxies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the given view model node to perform the given updates. This
|
||||
* method is called by view model provider and it's helper classes instead
|
||||
* of calling the IVMNode method directly, in order to allow additional
|
||||
* processing of the udpate. For example the AbstractCachingVMProvider
|
||||
* overrides this method to optionally return the results for an update from
|
||||
* a cache.
|
||||
*/
|
||||
protected void updateNode(IVMNode node, IChildrenUpdate[] updates) {
|
||||
node.update(updates);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether this provider has been disposed.
|
||||
*/
|
||||
protected boolean isDisposed() {
|
||||
return fDisposed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to access the View Model's executor.
|
||||
* The abstract provider uses a the display-thread executor so that the
|
||||
* provider will operate on the same thread as the viewer. This way no
|
||||
* synchronization is necessary when the provider is called by the viewer.
|
||||
* Also, the display thread is likely to be shut down long after any of the
|
||||
* view models are disposed, so the users of this abstract provider do not
|
||||
* need to worry about the executor throwing the {@link RejectedExecutionException}
|
||||
* exception.
|
||||
*/
|
||||
public DsfExecutor getExecutor() { return fVMAdapter.getExecutor(); }
|
||||
|
||||
|
||||
public void update(IHasChildrenUpdate[] updates) {
|
||||
// Sort the updates by the layout node.
|
||||
Map<IVMLayoutNode,List<IHasChildrenUpdate>> nodeUpdatesMap = new HashMap<IVMLayoutNode,List<IHasChildrenUpdate>>();
|
||||
for (IHasChildrenUpdate update : updates) {
|
||||
// Get the VM Context for last element in path.
|
||||
IVMLayoutNode layoutNode = getLayoutNodeForElement(update.getElement());
|
||||
if (layoutNode == null) {
|
||||
// Stale update, most likely as a result of the layout nodes being
|
||||
// changed. Just ignore it.
|
||||
update.done();
|
||||
continue;
|
||||
}
|
||||
if (!nodeUpdatesMap.containsKey(layoutNode)) {
|
||||
nodeUpdatesMap.put(layoutNode, new ArrayList<IHasChildrenUpdate>());
|
||||
}
|
||||
nodeUpdatesMap.get(layoutNode).add(update);
|
||||
}
|
||||
|
||||
// Iterate through the nodes in the sorted map.
|
||||
for (IVMLayoutNode node : nodeUpdatesMap.keySet()) {
|
||||
updateNode(node, nodeUpdatesMap.get(node).toArray(new IHasChildrenUpdate[nodeUpdatesMap.get(node).size()]));
|
||||
}
|
||||
public DsfExecutor getExecutor() {
|
||||
return fExecutor;
|
||||
}
|
||||
|
||||
private void updateNode(IVMLayoutNode node, final IHasChildrenUpdate[] updates) {
|
||||
// If parent element's layout node has no children, just set the
|
||||
// result and coninue to next element.
|
||||
if (node.getChildLayoutNodes().length == 0) {
|
||||
for (IHasChildrenUpdate update : updates) {
|
||||
update.setHasChilren(false);
|
||||
update.done();
|
||||
}
|
||||
return;
|
||||
}
|
||||
public IModelProxy createModelProxy(Object element, IPresentationContext context) {
|
||||
assert getExecutor().isInExecutorThread();
|
||||
|
||||
// Create a matrix of element updates:
|
||||
// The first dimension "i" is the list of children updates that came from the viewer.
|
||||
// For each of these updates, there are "j" number of elment updates corresponding
|
||||
// to the number of child layout nodes in this node.
|
||||
// Each children update from the viewer is complete when all the child layout nodes
|
||||
// fill in their elements update.
|
||||
// Once the matrix is constructed, the child layout nodes are given the list of updates
|
||||
// equal to the updates requested by the viewer.
|
||||
VMHasElementsUpdate[][] elementsUpdates =
|
||||
new VMHasElementsUpdate[node.getChildLayoutNodes().length][updates.length];
|
||||
for (int i = 0; i < updates.length; i ++)
|
||||
{
|
||||
final IHasChildrenUpdate update = updates[i];
|
||||
|
||||
final MultiRequestMonitor<DataRequestMonitor<Boolean>> hasChildrenMultiRequestMon =
|
||||
new MultiRequestMonitor<DataRequestMonitor<Boolean>>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
// Status is OK, only if all request monitors are OK.
|
||||
if (getStatus().isOK()) {
|
||||
boolean isContainer = false;
|
||||
for (DataRequestMonitor<Boolean> hasElementsDone : getRequestMonitors()) {
|
||||
isContainer |= hasElementsDone.getStatus().isOK() &&
|
||||
hasElementsDone.getData().booleanValue();
|
||||
}
|
||||
update.setHasChilren(isContainer);
|
||||
} else {
|
||||
update.setStatus(getStatus());
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
};
|
||||
|
||||
for (int j = 0; j < node.getChildLayoutNodes().length; j++)
|
||||
{
|
||||
elementsUpdates[j][i] = new VMHasElementsUpdate(
|
||||
update,
|
||||
hasChildrenMultiRequestMon.add(
|
||||
new DataRequestMonitor<Boolean>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
hasChildrenMultiRequestMon.requestMonitorDone(this);
|
||||
}
|
||||
}));
|
||||
// Iterate through the current active proxies to try to find a proxy with the same
|
||||
// element and re-use it if found. At the same time purge proxies that are no longer
|
||||
IVMModelProxy proxy = null;
|
||||
for (Iterator<IVMModelProxy> itr = getActiveModelProxies().iterator(); itr.hasNext();) {
|
||||
IVMModelProxy next = itr.next();
|
||||
if (next == null && next.getRootElement().equals(element)) {
|
||||
proxy = next;
|
||||
} else if (next.isDisposed()) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < node.getChildLayoutNodes().length; j++) {
|
||||
node.getChildLayoutNodes()[j].updateHasElements(elementsUpdates[j]);
|
||||
if (proxy == null) {
|
||||
proxy = createModelProxyStrategy(element);
|
||||
getActiveModelProxies().add(proxy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void update(final IChildrenCountUpdate[] updates) {
|
||||
for (final IChildrenCountUpdate update : updates) {
|
||||
if (update.isCanceled()) {
|
||||
update.done();
|
||||
continue;
|
||||
}
|
||||
|
||||
getChildrenCountsForNode(
|
||||
update,
|
||||
new DataRequestMonitor<Integer[]>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (getStatus().isOK()) {
|
||||
int numChildren = 0;
|
||||
for (Integer count : getData()) {
|
||||
numChildren += count.intValue();
|
||||
}
|
||||
update.setChildCount(numChildren);
|
||||
} else {
|
||||
update.setChildCount(0);
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void update(IChildrenUpdate[] updates) {
|
||||
for (final IChildrenUpdate update : updates) {
|
||||
getChildrenCountsForNode(
|
||||
update,
|
||||
new DataRequestMonitor<Integer[]>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
updateChildrenWithCounts(update, getData());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void getChildrenCountsForNode(IViewerUpdate update, final DataRequestMonitor<Integer[]> rm) {
|
||||
if (isDisposed()) return;
|
||||
|
||||
// Get the VM Context for last element in path.
|
||||
final IVMLayoutNode layoutNode = getLayoutNodeForElement(update.getElement());
|
||||
if (layoutNode == null) {
|
||||
// Stale update. Just ignore.
|
||||
rm.setStatus(new Status(
|
||||
IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Stale update.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
IVMLayoutNode[] childNodes = layoutNode.getChildLayoutNodes();
|
||||
|
||||
// If parent element's layout node has no children, just mark done and
|
||||
// return.
|
||||
if (childNodes.length == 0) {
|
||||
rm.setData(new Integer[0]);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Get the mapping of all the counts.
|
||||
final Integer[] counts = new Integer[childNodes.length];
|
||||
final MultiRequestMonitor<RequestMonitor> childrenCountMultiReqMon =
|
||||
new MultiRequestMonitor<RequestMonitor>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!fDisposed) super.handleCompleted();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
rm.setData(counts);
|
||||
rm.done();
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < childNodes.length; i++) {
|
||||
final int nodeIndex = i;
|
||||
childNodes[i].updateElementCount(
|
||||
new VMElementsCountUpdate(
|
||||
update,
|
||||
childrenCountMultiReqMon.add(
|
||||
new DataRequestMonitor<Integer>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
counts[nodeIndex] = getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
super.handleCompleted();
|
||||
childrenCountMultiReqMon.requestMonitorDone(this);
|
||||
}
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChildrenWithCounts(final IChildrenUpdate update, Integer[] nodeElementCounts) {
|
||||
final IVMLayoutNode layoutNode = getLayoutNodeForElement(update.getElement());
|
||||
if (layoutNode == null) {
|
||||
// Stale update. Just ignore.
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the multi request monitor to mark update when querying all
|
||||
// children nodes is finished.
|
||||
final MultiRequestMonitor<RequestMonitor> elementsMultiRequestMon =
|
||||
new MultiRequestMonitor<RequestMonitor>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
update.done();
|
||||
}
|
||||
};
|
||||
|
||||
// Iterate through all child nodes and if requested range matches, call them to
|
||||
// get their elements.
|
||||
int updateStartIdx = update.getOffset();
|
||||
int updateEndIdx = update.getOffset() + update.getLength();
|
||||
int idx = 0;
|
||||
IVMLayoutNode[] layoutNodes = layoutNode.getChildLayoutNodes();
|
||||
for (int i = 0; i < layoutNodes.length; i++) {
|
||||
final int nodeStartIdx = idx;
|
||||
final int nodeEndIdx = idx + nodeElementCounts[i];
|
||||
idx = nodeEndIdx;
|
||||
|
||||
// Check if update range overlaps the node's range.
|
||||
if (updateStartIdx <= nodeEndIdx && updateEndIdx > nodeStartIdx) {
|
||||
final int elementsStartIdx = Math.max(updateStartIdx - nodeStartIdx, 0);
|
||||
final int elementsEndIdx = Math.min(updateEndIdx - nodeStartIdx, nodeElementCounts[i]);
|
||||
final int elementsLength = elementsEndIdx - elementsStartIdx;
|
||||
if (elementsLength > 0) {
|
||||
layoutNodes[i].updateElements(
|
||||
new VMElementsUpdate(
|
||||
update, elementsStartIdx, elementsLength,
|
||||
elementsMultiRequestMon.add(new DataRequestMonitor<List<Object>>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (getStatus().isOK()) {
|
||||
for (int i = 0; i < elementsLength; i++) {
|
||||
update.setChild(getData().get(i), elementsStartIdx + nodeStartIdx + i);
|
||||
}
|
||||
}
|
||||
elementsMultiRequestMon.requestMonitorDone(this);
|
||||
}
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Guard against invalid queries.
|
||||
if (elementsMultiRequestMon.getRequestMonitors().isEmpty()) {
|
||||
update.done();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ModelProxy createModelProxy(Object element, IPresentationContext context) {
|
||||
/*
|
||||
* Model proxy is the object that correlates events from the data model
|
||||
* into view model deltas that the view can process. This method is called
|
||||
* by the viewer when a new input object is set to the view. We need to create
|
||||
* a new instance of the ModelProxy object with every call, because the viewer
|
||||
* disposes the old proxy before calling this method.
|
||||
*/
|
||||
synchronized(this) {
|
||||
fRootElement = element;
|
||||
fModelProxy = new ModelProxy();
|
||||
}
|
||||
return fModelProxy;
|
||||
return proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -466,6 +477,7 @@ abstract public class AbstractVMProvider implements IVMProvider
|
|||
* @see IColumnPresentationFactory#createColumnPresentation(IPresentationContext, Object)
|
||||
*/
|
||||
public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
|
||||
assert fExecutor.isInExecutorThread();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -501,118 +513,4 @@ abstract public class AbstractVMProvider implements IVMProvider
|
|||
update.setInputElement(update.getElement());
|
||||
update.done();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method that finds the VMC corresponding to given parent
|
||||
* argument given to isContainer() or retrieveChildren().
|
||||
* @param object Object to find the VMC for.
|
||||
* @return parent VMC, if null it indicates that the object did not originate
|
||||
* from this view or is stale.
|
||||
*/
|
||||
protected IVMLayoutNode getLayoutNodeForElement(Object element) {
|
||||
/*
|
||||
* First check to see if the parent object is the root object of the
|
||||
* hierarchy. If that's the case, then retrieve the correcponding
|
||||
* root VMC from the root node, and pass this root vmc to the root's
|
||||
* child layout nodes.
|
||||
*/
|
||||
IVMRootLayoutNode rootLayoutNode = getRootLayoutNode();
|
||||
if (rootLayoutNode == null) {
|
||||
return null;
|
||||
}
|
||||
else if (element.equals(getRootElement())) {
|
||||
return rootLayoutNode;
|
||||
}
|
||||
else if (element instanceof IVMContext){
|
||||
/*
|
||||
* The parent is a VMC. Check to make sure that the VMC
|
||||
* originated from a node in this ViewModelProvider. If it didn't
|
||||
* it is most likely a result of a change in view layout, and this
|
||||
* request is a stale request. So just ignore it.
|
||||
*/
|
||||
if (isOurLayoutNode( ((IVMContext)element).getLayoutNode(),
|
||||
new IVMLayoutNode[] { rootLayoutNode } ))
|
||||
{
|
||||
return ((IVMContext)element).getLayoutNode();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method which checks whether given layout node is a node
|
||||
* that is configured in this ViewModelProvider. Implementation
|
||||
* recursively walks the layout hierarchy, and returns true if it finds
|
||||
* the node.
|
||||
*/
|
||||
private boolean isOurLayoutNode(IVMLayoutNode layoutNode, IVMLayoutNode[] nodesToSearch) {
|
||||
for (IVMLayoutNode node : nodesToSearch) {
|
||||
if (node == layoutNode) return true;
|
||||
if (isOurLayoutNode(layoutNode, node.getChildLayoutNodes())) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected void handleEvent(final Object event) {
|
||||
// We're in session's executor thread. Re-dispach to VM Adapter
|
||||
// executor thread and then call root layout node.
|
||||
try {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
IVMRootLayoutNode rootLayoutNode = getRootLayoutNode();
|
||||
if (rootLayoutNode != null && rootLayoutNode.getDeltaFlags(event) != 0) {
|
||||
rootLayoutNode.createDelta(
|
||||
event,
|
||||
new DataRequestMonitor<IModelDelta>(getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
if (getStatus().isOK()) {
|
||||
getModelProxy().fireModelChangedNonDispatch(getData());
|
||||
}
|
||||
}
|
||||
@Override public String toString() {
|
||||
return "Result of a delta for event: '" + event.toString() + "' in VMP: '" + AbstractVMProvider.this + "'" + "\n" + getData().toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
});
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Ignore. This exception could be thrown if the provider is being
|
||||
// shut down.
|
||||
}
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
protected class ModelProxy extends AbstractModelProxy {
|
||||
/**
|
||||
* Scheduling rule for running the update jobs.
|
||||
*/
|
||||
private ISchedulingRule fModelChangeRule = new ISchedulingRule() {
|
||||
public boolean contains(ISchedulingRule rule) { return this == rule; }
|
||||
public boolean isConflicting(ISchedulingRule rule) { return rule == this; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Fires given delta using a job. Processing the delta on the dispatch
|
||||
* thread can lead to dead-locks.
|
||||
* @param delta
|
||||
*/
|
||||
public void fireModelChangedNonDispatch(final IModelDelta delta) {
|
||||
Job job = new Job("Processing view model delta.") { //$NON-NLS-1$
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
fireModelChanged(delta);
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
};
|
||||
job.setPriority(Job.INTERACTIVE);
|
||||
job.setRule(fModelChangeRule);
|
||||
job.schedule();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,370 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.ui.viewmodel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
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.IElementContentProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
|
||||
/**
|
||||
* The default strategy for implementing the IElementContentProvider
|
||||
* functionality for an IVMProvider. It implements an algorithm to populate
|
||||
* contents of the view in accordance with the tree structure of the
|
||||
* view model nodes configured in the view model provider.
|
||||
* <p/>
|
||||
* This class may be used by an <code>IVMProvider</code> directly, or it
|
||||
* may be be extended to customize for the provider's needs.
|
||||
* <p/>
|
||||
* This class is closely linked with a view model provider which is required
|
||||
* for the constructor. The view model provider is used to access the correct
|
||||
* executor and the node hierarchy.
|
||||
*/
|
||||
@ConfinedToDsfExecutor("#getExecutor()")
|
||||
@SuppressWarnings("restriction")
|
||||
public class DefaultVMContentProviderStrategy implements IElementContentProvider {
|
||||
|
||||
private final AbstractVMProvider fVMProvider;
|
||||
|
||||
public DefaultVMContentProviderStrategy(AbstractVMProvider provider) {
|
||||
fVMProvider = provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the view model provider that this strategy is configured for.
|
||||
* @return
|
||||
*/
|
||||
protected AbstractVMProvider getVMProvider() { return fVMProvider; }
|
||||
|
||||
public void update(final IHasChildrenUpdate[] updates) {
|
||||
if (updates.length == 0) return;
|
||||
|
||||
// Optimization: if all the updates belong to the same node, avoid creating any new lists/arrays.
|
||||
boolean allNodesTheSame = true;
|
||||
IVMNode firstNode = getNodeForElement(updates[0].getElement());
|
||||
for (int i = 1; i < updates.length; i++) {
|
||||
if (firstNode != getNodeForElement(updates[i].getElement())) {
|
||||
allNodesTheSame = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allNodesTheSame) {
|
||||
updateNode(firstNode, updates);
|
||||
} else {
|
||||
// Sort the updates by the node.
|
||||
Map<IVMNode,List<IHasChildrenUpdate>> nodeUpdatesMap = new HashMap<IVMNode,List<IHasChildrenUpdate>>();
|
||||
for (IHasChildrenUpdate update : updates) {
|
||||
// Get the VM Context for last element in path.
|
||||
IVMNode node = getNodeForElement(update.getElement());
|
||||
if (node == null) {
|
||||
// Stale update, most likely as a result of the nodes being
|
||||
// changed. Just ignore it.
|
||||
update.done();
|
||||
continue;
|
||||
}
|
||||
if (!nodeUpdatesMap.containsKey(node)) {
|
||||
nodeUpdatesMap.put(node, new ArrayList<IHasChildrenUpdate>());
|
||||
}
|
||||
nodeUpdatesMap.get(node).add(update);
|
||||
}
|
||||
|
||||
// Iterate through the nodes in the sorted map.
|
||||
for (IVMNode node : nodeUpdatesMap.keySet()) {
|
||||
updateNode(node, nodeUpdatesMap.get(node).toArray(new IHasChildrenUpdate[nodeUpdatesMap.get(node).size()]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNode(IVMNode node, final IHasChildrenUpdate[] updates) {
|
||||
// If parent element's node has no children, just set the
|
||||
// result and continue to next element.
|
||||
final IVMNode[] childNodes = getVMProvider().getChildVMNodes(node);
|
||||
if (childNodes.length == 0) {
|
||||
for (IHasChildrenUpdate update : updates) {
|
||||
update.setHasChilren(false);
|
||||
update.done();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a matrix of element updates:
|
||||
// The first dimension "i" is the list of children updates that came from the viewer.
|
||||
// For each of these updates, there are "j" number of elment updates corresponding
|
||||
// to the number of child nodes in this node.
|
||||
// Each children update from the viewer is complete when all the child nodes
|
||||
// fill in their elements update.
|
||||
// Once the matrix is constructed, the child nodes are given the list of updates
|
||||
// equal to the updates requested by the viewer.
|
||||
VMHasChildrenUpdate[][] elementsUpdates =
|
||||
new VMHasChildrenUpdate[childNodes.length][updates.length];
|
||||
for (int i = 0; i < updates.length; i ++)
|
||||
{
|
||||
final IHasChildrenUpdate update = updates[i];
|
||||
|
||||
final MultiRequestMonitor<DataRequestMonitor<Boolean>> hasChildrenMultiRequestMon =
|
||||
new MultiRequestMonitor<DataRequestMonitor<Boolean>>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
// Status is OK, only if all request monitors are OK.
|
||||
if (getStatus().isOK()) {
|
||||
boolean isContainer = false;
|
||||
for (DataRequestMonitor<Boolean> hasElementsDone : getRequestMonitors()) {
|
||||
isContainer |= hasElementsDone.getStatus().isOK() &&
|
||||
hasElementsDone.getData().booleanValue();
|
||||
}
|
||||
update.setHasChilren(isContainer);
|
||||
} else {
|
||||
update.setStatus(getStatus());
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
};
|
||||
|
||||
for (int j = 0; j < childNodes.length; j++)
|
||||
{
|
||||
elementsUpdates[j][i] = new VMHasChildrenUpdate(
|
||||
update,
|
||||
hasChildrenMultiRequestMon.add(
|
||||
new DataRequestMonitor<Boolean>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
hasChildrenMultiRequestMon.requestMonitorDone(this);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < childNodes.length; j++) {
|
||||
getVMProvider().updateNode(childNodes[j], elementsUpdates[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void update(final IChildrenCountUpdate[] updates) {
|
||||
for (final IChildrenCountUpdate update : updates) {
|
||||
IVMNode node = getNodeForElement(update.getElement());
|
||||
|
||||
if (node != null && !update.isCanceled()) {
|
||||
IVMNode[] childNodes = getVMProvider().getChildVMNodes(node);
|
||||
|
||||
if (childNodes.length == 0) {
|
||||
update.setChildCount(0);
|
||||
update.done();
|
||||
} else if (childNodes.length == 1) {
|
||||
getVMProvider().updateNode(childNodes[0], new IChildrenCountUpdate[] { update } );
|
||||
} else {
|
||||
getChildrenCountsForNode(
|
||||
update,
|
||||
node,
|
||||
new DataRequestMonitor<Integer[]>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (getStatus().isOK()) {
|
||||
int numChildren = 0;
|
||||
for (Integer count : getData()) {
|
||||
numChildren += count.intValue();
|
||||
}
|
||||
update.setChildCount(numChildren);
|
||||
} else {
|
||||
update.setChildCount(0);
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (update.isCanceled()) {
|
||||
update.done();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void update(final IChildrenUpdate[] updates) {
|
||||
for (final IChildrenUpdate update : updates) {
|
||||
// Get the VM Context for last element in path.
|
||||
final IVMNode node = getNodeForElement(update.getElement());
|
||||
if (node != null && !update.isCanceled()) {
|
||||
IVMNode[] childNodes = getVMProvider().getChildVMNodes(node);
|
||||
if (childNodes.length == 0) {
|
||||
// Invalid update, just mark done.
|
||||
update.done();
|
||||
} else if (childNodes.length == 1) {
|
||||
getVMProvider().updateNode(childNodes[0], new IChildrenUpdate[] { update });
|
||||
} else {
|
||||
getChildrenCountsForNode(
|
||||
update,
|
||||
node,
|
||||
new DataRequestMonitor<Integer[]>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!getStatus().isOK()) {
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
|
||||
updateChildrenWithCounts(update, node, getData());
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Stale update. Just ignore.
|
||||
update.done();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the number of elements in each child node for the element in
|
||||
* update. These counts are then used to delegate the children update to
|
||||
* the correct nodes.
|
||||
*/
|
||||
private void getChildrenCountsForNode(IViewerUpdate update, IVMNode updateNode, final DataRequestMonitor<Integer[]> rm) {
|
||||
|
||||
IVMNode[] childNodes = getVMProvider().getChildVMNodes(updateNode);
|
||||
|
||||
// Check for an invalid call
|
||||
assert childNodes.length != 0;
|
||||
|
||||
// Get the mapping of all the counts.
|
||||
final Integer[] counts = new Integer[childNodes.length];
|
||||
final MultiRequestMonitor<RequestMonitor> childrenCountMultiReqMon =
|
||||
new MultiRequestMonitor<RequestMonitor>(getVMProvider().getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
rm.setData(counts);
|
||||
rm.done();
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < childNodes.length; i++) {
|
||||
final int nodeIndex = i;
|
||||
getVMProvider().updateNode(
|
||||
childNodes[i],
|
||||
new IChildrenCountUpdate[] {
|
||||
new VMChildrenCountUpdate(
|
||||
update,
|
||||
childrenCountMultiReqMon.add(
|
||||
new DataRequestMonitor<Integer>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
counts[nodeIndex] = getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
super.handleCompleted();
|
||||
childrenCountMultiReqMon.requestMonitorDone(this);
|
||||
}
|
||||
}))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the given children update among the configured child nodes. Then calls
|
||||
* each child node to complete the update.
|
||||
*/
|
||||
private void updateChildrenWithCounts(final IChildrenUpdate update, IVMNode node, Integer[] nodeElementCounts) {
|
||||
// Create the multi request monitor to mark update when querying all
|
||||
// children nodes is finished.
|
||||
final MultiRequestMonitor<RequestMonitor> elementsMultiRequestMon =
|
||||
new MultiRequestMonitor<RequestMonitor>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
update.done();
|
||||
}
|
||||
};
|
||||
|
||||
// Iterate through all child nodes and if requested range matches, call them to
|
||||
// get their elements.
|
||||
int updateStartIdx = update.getOffset();
|
||||
int updateEndIdx = update.getOffset() + update.getLength();
|
||||
int idx = 0;
|
||||
IVMNode[] nodes = getVMProvider().getChildVMNodes(node);
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
final int nodeStartIdx = idx;
|
||||
final int nodeEndIdx = idx + nodeElementCounts[i];
|
||||
idx = nodeEndIdx;
|
||||
|
||||
// Check if update range overlaps the node's range.
|
||||
if (updateStartIdx <= nodeEndIdx && updateEndIdx > nodeStartIdx) {
|
||||
final int elementsStartIdx = Math.max(updateStartIdx - nodeStartIdx, 0);
|
||||
final int elementsEndIdx = Math.min(updateEndIdx - nodeStartIdx, nodeElementCounts[i]);
|
||||
final int elementsLength = elementsEndIdx - elementsStartIdx;
|
||||
if (elementsLength > 0) {
|
||||
getVMProvider().updateNode(
|
||||
nodes[i],
|
||||
new IChildrenUpdate[] {
|
||||
new VMChildrenUpdate(
|
||||
update, elementsStartIdx, elementsLength,
|
||||
elementsMultiRequestMon.add(new DataRequestMonitor<List<Object>>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (getStatus().isOK()) {
|
||||
for (int i = 0; i < elementsLength; i++) {
|
||||
update.setChild(getData().get(i), elementsStartIdx + nodeStartIdx + i);
|
||||
}
|
||||
}
|
||||
elementsMultiRequestMon.requestMonitorDone(this);
|
||||
}
|
||||
}))
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Guard against invalid queries.
|
||||
assert !elementsMultiRequestMon.getRequestMonitors().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that finds the VMC corresponding to given parent
|
||||
* argument given to isContainer() or retrieveChildren().
|
||||
* @param object Object to find the VMC for.
|
||||
* @return parent VMC, if null it indicates that the object did not originate
|
||||
* from this view or is stale.
|
||||
*/
|
||||
protected IVMNode getNodeForElement(Object element) {
|
||||
if (element instanceof IVMContext) {
|
||||
IVMNode node = ((IVMContext)element).getVMNode();
|
||||
if (isOurNode(((IVMContext)element).getVMNode())) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return getVMProvider().getRootVMNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method which checks whether given layout node is a node
|
||||
* that is configured in this ViewModelProvider.
|
||||
*/
|
||||
private boolean isOurNode(IVMNode node) {
|
||||
for (IVMNode nodeToSearch : getVMProvider().getAllVMNodes()) {
|
||||
if (nodeToSearch.equals(node)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,615 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 IBM Corporation 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
* Wind River Systems - adapted to use with DSF
|
||||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.ui.viewmodel;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.runtime.ISafeRunnable;
|
||||
import org.eclipse.core.runtime.ListenerList;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.SafeRunner;
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.debug.internal.ui.DebugUIPlugin;
|
||||
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.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.ModelDelta;
|
||||
import org.eclipse.jface.viewers.Viewer;
|
||||
|
||||
|
||||
/**
|
||||
* This is the default implementation of {@link IModelProxy} interface for
|
||||
* use by a view model provider. It implements an algorithm to walk the
|
||||
* tree hierarchy of nodes configured with a provider in order to compose
|
||||
* an {@link IModelDelta} for a given data model event.
|
||||
* <p/>
|
||||
* This class is closely linked with a view model provider which is required
|
||||
* for the constructor. The view model provider is used to access the correct
|
||||
* executor and the node hierarchy.
|
||||
*/
|
||||
@ConfinedToDsfExecutor("#getProvider()#getExecutor()")
|
||||
@SuppressWarnings("restriction")
|
||||
public class DefaultVMModelProxyStrategy implements IVMModelProxy {
|
||||
|
||||
private final AbstractVMProvider fProvider;
|
||||
private final Object fRootElement;
|
||||
private IPresentationContext fContext;
|
||||
private Viewer fViewer;
|
||||
private boolean fDisposed = false;
|
||||
private ListenerList fListeners = new ListenerList();
|
||||
|
||||
/**
|
||||
* Debug flag indicating whether the deltas should be traced in stdout.
|
||||
*/
|
||||
private static boolean DEBUG_DELTAS = false;
|
||||
|
||||
static {
|
||||
DEBUG_DELTAS = DebugUIPlugin.DEBUG && "true".equals( //$NON-NLS-1$
|
||||
Platform.getDebugOption("org.eclipse.debug.ui/debug/viewers/deltas")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates this model proxy strategy for the given provider.
|
||||
*/
|
||||
public DefaultVMModelProxyStrategy(AbstractVMProvider provider, Object rootElement) {
|
||||
fProvider = provider;
|
||||
fRootElement = rootElement;
|
||||
}
|
||||
|
||||
public boolean isDeltaEvent(Object event) {
|
||||
IRootVMNode rootNode = getVMProvider().getRootVMNode();
|
||||
return rootNode != null &&
|
||||
rootNode.isDeltaEvent(getRootElement(), event) &&
|
||||
getDeltaFlags(rootNode, null, event) != 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the view model provider that this strategy is configured for.
|
||||
* @return
|
||||
*/
|
||||
protected AbstractVMProvider getVMProvider() {
|
||||
return fProvider;
|
||||
}
|
||||
|
||||
|
||||
private Object[] getListeners() {
|
||||
return fListeners.getListeners();
|
||||
}
|
||||
|
||||
public void addModelChangedListener(IModelChangedListener listener) {
|
||||
fListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeModelChangedListener(IModelChangedListener listener) {
|
||||
fListeners.remove(listener);
|
||||
}
|
||||
|
||||
public Object getRootElement() {
|
||||
return fRootElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies registered listeners of the given delta.
|
||||
*
|
||||
* @param delta model delta to broadcast
|
||||
*/
|
||||
public void fireModelChanged(IModelDelta delta) {
|
||||
final IModelDelta root = getRootDelta(delta);
|
||||
Object[] listeners = getListeners();
|
||||
if (DEBUG_DELTAS) {
|
||||
DebugUIPlugin.debug("FIRE DELTA: " + delta.toString()); //$NON-NLS-1$
|
||||
}
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
final IModelChangedListener listener = (IModelChangedListener) listeners[i];
|
||||
ISafeRunnable safeRunnable = new ISafeRunnable() {
|
||||
public void handleException(Throwable exception) {
|
||||
DebugUIPlugin.log(exception);
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
listener.modelChanged(root, DefaultVMModelProxyStrategy.this);
|
||||
}
|
||||
|
||||
};
|
||||
SafeRunner.run(safeRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that returns the root node of the given delta.
|
||||
*
|
||||
* @param delta delta node
|
||||
* @return returns the root of the given delta
|
||||
*/
|
||||
protected IModelDelta getRootDelta(IModelDelta delta) {
|
||||
IModelDelta parent = delta.getParentDelta();
|
||||
while (parent != null) {
|
||||
delta = parent;
|
||||
parent = delta.getParentDelta();
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.IModelProxy#dispose()
|
||||
*/
|
||||
public void dispose() {
|
||||
fDisposed = true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.IModelProxy#init(org.eclipse.debug.internal.ui.viewers.IPresentationContext)
|
||||
*/
|
||||
public void init(IPresentationContext context) {
|
||||
fDisposed = false;
|
||||
fContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the context this model proxy is installed in.
|
||||
*
|
||||
* @return presentation context, or <code>null</code> if this
|
||||
* model proxy has been disposed
|
||||
*/
|
||||
public IPresentationContext getPresentationContext() {
|
||||
return fContext;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
*
|
||||
* Subclasses should override as required.
|
||||
*
|
||||
* @see org.eclipse.debug.internal.ui.viewers.provisional.IModelProxy#installed(org.eclipse.jface.viewers.Viewer)
|
||||
*/
|
||||
public void installed(Viewer viewer) {
|
||||
fViewer = viewer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the viewer this proxy is installed in.
|
||||
*
|
||||
* @return viewer or <code>null</code> if not installed
|
||||
*/
|
||||
protected Viewer getViewer() {
|
||||
return fViewer;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy#isDisposed()
|
||||
*/
|
||||
public boolean isDisposed() {
|
||||
return fDisposed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively calls the VM nodes in the hierarchy of the given node
|
||||
* to calculate the delta flags that are
|
||||
* <p/>
|
||||
* Note: If a child node has a <code>IModelDelta.CONTENT</code> delta
|
||||
* flag, it means that this flag will be added to this node's element.
|
||||
* To allow for optimization change the child's <code>IModelDelta.CONTENT</code>
|
||||
* flag into a <code>IModelDelta.STATE</code> flag.
|
||||
*
|
||||
* @param node
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
protected int getDeltaFlags(IVMNode node, ModelDelta parentDelta, Object event) {
|
||||
int flags = node.getDeltaFlags(event);
|
||||
for (IVMNode childNode : getVMProvider().getChildVMNodes(node)) {
|
||||
if (!childNode.equals(node)) {
|
||||
int childNodeDeltaFlags = getDeltaFlags(childNode, parentDelta, event);
|
||||
if ((childNodeDeltaFlags & IModelDelta.CONTENT) != 0) {
|
||||
childNodeDeltaFlags &= ~IModelDelta.CONTENT;
|
||||
childNodeDeltaFlags |= IModelDelta.STATE;
|
||||
}
|
||||
flags |= childNodeDeltaFlags;
|
||||
}
|
||||
}
|
||||
// Optimization: If the parent delta contains the "content" flag, we do
|
||||
// not need to add it to the child. This can shorten delta processing
|
||||
// considerably so check for it.
|
||||
while (parentDelta != null) {
|
||||
if ( (parentDelta.getFlags() & IModelDelta.CONTENT) != 0 ) {
|
||||
flags = flags & ~IModelDelta.CONTENT & ~IModelDelta.STATE;
|
||||
break;
|
||||
}
|
||||
parentDelta = (ModelDelta)parentDelta.getParentDelta();
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation creates a delta assuming that the root node
|
||||
* is the input object into the view.
|
||||
*/
|
||||
public void createDelta(final Object event, final DataRequestMonitor<IModelDelta> rm) {
|
||||
final IRootVMNode rootNode = getVMProvider().getRootVMNode();
|
||||
|
||||
// Always create the rootDelta, no matter what delta flags the child nodes have.
|
||||
rootNode.createRootDelta(
|
||||
getRootElement(), event,
|
||||
new DataRequestMonitor<ModelDelta>(getVMProvider().getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
// Find the root delta for the whole view to use when firing the delta.
|
||||
// Note: the view root is going to be different than the model root
|
||||
// in case when the view model provider is registered to populate only
|
||||
// a sub-tree of a view.
|
||||
final IModelDelta viewRootDelta = getRootDelta(getData());
|
||||
|
||||
// Find the child nodes that have deltas for the given event.
|
||||
final Map<IVMNode,Integer> childNodesWithDeltaFlags = getChildNodesWithDeltaFlags(rootNode, getData(), event);
|
||||
|
||||
// If no child nodes have deltas we can stop here.
|
||||
if (childNodesWithDeltaFlags.size() == 0) {
|
||||
rm.done();
|
||||
rm.setData(viewRootDelta);
|
||||
return;
|
||||
}
|
||||
|
||||
callChildNodesToBuildDelta(
|
||||
rootNode,
|
||||
childNodesWithDeltaFlags, getData(), event,
|
||||
new RequestMonitor(getVMProvider().getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
rm.setData(viewRootDelta);
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void buildChildDeltas(final IVMNode node, final Object event, final ModelDelta parentDelta,
|
||||
final int nodeOffset, final RequestMonitor rm)
|
||||
{
|
||||
final IVMContext vmc = node.getContextFromEvent(event);
|
||||
|
||||
if (vmc != null) {
|
||||
buildChildDeltasForEventContext(vmc, node, event, parentDelta, nodeOffset, rm);
|
||||
} else {
|
||||
// The DMC for this node was not found in the event. Call the
|
||||
// super-class to resort to the default behavior which may add a
|
||||
// delta for every element in this node.
|
||||
buildChildDeltasForAllContexts(node, event, parentDelta, nodeOffset, rm);
|
||||
}
|
||||
}
|
||||
|
||||
protected void buildChildDeltasForEventContext(final IVMContext vmc, final IVMNode node, final Object event,
|
||||
final ModelDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor)
|
||||
{
|
||||
final Map<IVMNode,Integer> childNodeDeltas = getChildNodesWithDeltaFlags(node, parentDelta, event);
|
||||
if (childNodeDeltas.size() == 0) {
|
||||
// There are no child nodes with deltas, just return to parent.
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if any of the child nodes are will generate IModelDelta.SELECT or
|
||||
// IModelDelta.EXPAND flags. If so, we must calculate the index for this
|
||||
// VMC.
|
||||
boolean calculateIndex = false;
|
||||
if (nodeOffset >= 0) {
|
||||
for (int childDelta : childNodeDeltas.values()) {
|
||||
if ( (childDelta & (IModelDelta.SELECT | IModelDelta.EXPAND)) != 0 ) {
|
||||
calculateIndex = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (calculateIndex) {
|
||||
// Calculate the index of this node by retrieving all the
|
||||
// elements and then finding the DMC that the event is for.
|
||||
getVMProvider().updateNode(
|
||||
node,
|
||||
new IChildrenUpdate[] {
|
||||
new VMChildrenUpdate(
|
||||
parentDelta, getVMProvider().getPresentationContext(), -1, -1,
|
||||
new DataRequestMonitor<List<Object>>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
// Check for an empty list of elements. If it's empty then we
|
||||
// don't have to call the children nodes, so return here.
|
||||
// No need to propagate error, there's no means or need to display it.
|
||||
if (!getStatus().isOK() || getData().isEmpty()) {
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the index.
|
||||
int i;
|
||||
for (i = 0; i < getData().size(); i++) {
|
||||
if (vmc.equals(getData().get(i))) break;
|
||||
}
|
||||
if (i == getData().size()) {
|
||||
// Element not found, no need to generate the delta.
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Optimization: Try to find a delta with a matching element, if found use it.
|
||||
// Otherwise create a new delta for the event element.
|
||||
int elementIndex = nodeOffset + i;
|
||||
ModelDelta delta = parentDelta.getChildDelta(vmc);
|
||||
if (delta == null || delta.getIndex() != elementIndex) {
|
||||
delta = parentDelta.addNode(vmc, elementIndex, IModelDelta.NO_CHANGE);
|
||||
}
|
||||
|
||||
callChildNodesToBuildDelta(node, childNodeDeltas, delta, event, requestMonitor);
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
// Optimization: Try to find a delta with a matching element, if found use it.
|
||||
// Otherwise create a new delta for the event element.
|
||||
ModelDelta delta = parentDelta.getChildDelta(vmc);
|
||||
if (delta == null) {
|
||||
delta = parentDelta.addNode(vmc, IModelDelta.NO_CHANGE);
|
||||
}
|
||||
callChildNodesToBuildDelta(node, childNodeDeltas, delta, event, requestMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base implementation that handles calling child nodes to build
|
||||
* the model delta. The child nodes are called with all the elements
|
||||
* in this node, which could be very inefficient. In order to build delta
|
||||
* only for specific elements in this node, the class extending
|
||||
* <code>AbstractVMNode</code> should override this method.
|
||||
* @see IVMNode#buildDelta(Object, ModelDelta, int, RequestMonitor)
|
||||
*/
|
||||
protected void buildChildDeltasForAllContexts(final IVMNode node, final Object event, final ModelDelta parentDelta,
|
||||
final int nodeOffset, final RequestMonitor requestMonitor)
|
||||
{
|
||||
// Find the child nodes that have deltas for the given event.
|
||||
final Map<IVMNode,Integer> childNodesWithDeltaFlags = getChildNodesWithDeltaFlags(node, parentDelta, event);
|
||||
|
||||
// If no child nodes have deltas we can stop here.
|
||||
if (childNodesWithDeltaFlags.size() == 0) {
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the child delta only has an IModelDelta.STATE flag.
|
||||
// If that's the case, we can skip creating a delta for this node,
|
||||
// because the TreeUpdatePolicy does not use the full path from the
|
||||
// delta to handle these flags. Similarly, the index argument is
|
||||
// not necessary either.
|
||||
boolean mustGetElements = false;
|
||||
for (int childDelta : childNodesWithDeltaFlags.values()) {
|
||||
if ((childDelta & ~IModelDelta.STATE) != 0) {
|
||||
mustGetElements = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mustGetElements) {
|
||||
callChildNodesToBuildDelta(node, childNodesWithDeltaFlags, parentDelta, event, requestMonitor);
|
||||
} else {
|
||||
// The given child nodes have deltas potentially for all elements
|
||||
// from this node. Retrieve all elements and call the child nodes with
|
||||
// each element as the parent of their delta.
|
||||
getVMProvider().updateNode(
|
||||
node,
|
||||
new IChildrenUpdate[] {
|
||||
new VMChildrenUpdate(
|
||||
parentDelta, getVMProvider().getPresentationContext(), -1, -1,
|
||||
new DataRequestMonitor<List<Object>>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (fDisposed) return;
|
||||
|
||||
// Check for an empty list of elements. If it's empty then we
|
||||
// don't have to call the children nodes, so return here.
|
||||
// No need to propagate error, there's no means or need to display it.
|
||||
if (!getStatus().isOK() || getData().size() == 0) {
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
final MultiRequestMonitor<RequestMonitor> elementsDeltasMultiRequestMon =
|
||||
new MultiRequestMonitor<RequestMonitor>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isDisposed()) return;
|
||||
requestMonitor.done();
|
||||
}
|
||||
};
|
||||
|
||||
// For each element from this node, create a new delta,
|
||||
// and then call all the child nodes to build their delta.
|
||||
for (int i = 0; i < getData().size(); i++) {
|
||||
int elementIndex = nodeOffset >= 0 ? nodeOffset + i : -1;
|
||||
ModelDelta delta =
|
||||
parentDelta.addNode(getData().get(i), elementIndex, IModelDelta.NO_CHANGE);
|
||||
callChildNodesToBuildDelta(
|
||||
node, childNodesWithDeltaFlags, delta, event,
|
||||
elementsDeltasMultiRequestMon.add(new RequestMonitor(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
elementsDeltasMultiRequestMon.requestMonitorDone(this);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the specified child nodes to build the delta for the given event.
|
||||
* @param childNodes Map of nodes to be invoked, and the corresponding delta
|
||||
* flags that they will generate. This map is generated with a call to
|
||||
* {@link #getChildNodesWithDeltaFlags(Object)}.
|
||||
* @param delta The delta object to build on. This delta should have been
|
||||
* generated by this node, unless the full delta path is not being calculated
|
||||
* due to an optimization.
|
||||
* @param event The event object that the delta is being built for.
|
||||
* @param requestMonitor The result token to invoke when the delta is completed.
|
||||
*/
|
||||
protected void callChildNodesToBuildDelta(final IVMNode node, final Map<IVMNode,Integer> childNodes, final ModelDelta delta, final Object event, final RequestMonitor requestMonitor) {
|
||||
assert childNodes.size() != 0;
|
||||
|
||||
// Check if any of the child nodes are will generate IModelDelta.SELECT or
|
||||
// IModelDelta.EXPAND flags. If so, we must calculate the index for this
|
||||
// VMC.
|
||||
boolean calculateOffsets = false;
|
||||
for (int childDelta : childNodes.values()) {
|
||||
if ( (childDelta & (IModelDelta.SELECT | IModelDelta.EXPAND)) != 0 ) {
|
||||
calculateOffsets = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
getChildNodesElementOffsets(
|
||||
node, delta, calculateOffsets,
|
||||
new DataRequestMonitor<Map<IVMNode, Integer>>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
final CountingRequestMonitor multiRm = new CountingRequestMonitor(getVMProvider().getExecutor(), requestMonitor);
|
||||
int multiRmCount = 0;
|
||||
|
||||
// Set the total count of number of children in the parent delta.
|
||||
delta.setChildCount(getData().get(null));
|
||||
|
||||
for (final IVMNode childNode : childNodes.keySet()) {
|
||||
// Avoid descending into recursive node hierarchy's when calculating the delta.
|
||||
if (node.equals(childNode)) continue;
|
||||
|
||||
final int nodeOffset = getData().get(childNode);
|
||||
childNode.buildDelta(
|
||||
event, delta, nodeOffset,
|
||||
new RequestMonitor(getVMProvider().getExecutor(), multiRm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
buildChildDeltas(
|
||||
childNode, event, delta, nodeOffset, new RequestMonitor(getVMProvider().getExecutor(), multiRm));
|
||||
}
|
||||
});
|
||||
multiRmCount++;
|
||||
}
|
||||
multiRm.setDoneCount(multiRmCount);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the indexes at which the elements of each of the child
|
||||
* nodes begin. These indexes are necessary to correctly
|
||||
* calculate the deltas for elements in the child nodes.
|
||||
* @param delta The delta object to build on. This delta should have been
|
||||
* generated by this node, unless the full delta path is not being calculated
|
||||
* due to an optimization.
|
||||
* @param doCalculdateOffsets If true, the method calls each node to get its
|
||||
* element count. If false, it causes this method to fill the return data
|
||||
* structure with dummy values. The dummy values indicate that the indexes
|
||||
* are not known and are acceptable in the delta if the delta flags being
|
||||
* generated do not require full index information.
|
||||
* @param rm Return token containing the results. The result data is a
|
||||
* mapping between the child nodes and the indexes at which the child nodes'
|
||||
* elements begin. There is a special value in the map with a <code>null</code>
|
||||
* key, which contains the full element count for all the nodes.
|
||||
*/
|
||||
private void getChildNodesElementOffsets(IVMNode node, IModelDelta delta, boolean calculdateOffsets, final DataRequestMonitor<Map<IVMNode, Integer>> rm) {
|
||||
final IVMNode[] childNodes = getVMProvider().getChildVMNodes(node);
|
||||
assert childNodes.length != 0;
|
||||
|
||||
if (calculdateOffsets) {
|
||||
final Integer[] counts = new Integer[childNodes.length];
|
||||
final MultiRequestMonitor<RequestMonitor> childrenCountMultiRequestMon =
|
||||
new MultiRequestMonitor<RequestMonitor>(getVMProvider().getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isDisposed()) return;
|
||||
super.handleCompleted();
|
||||
}
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
Map<IVMNode, Integer> data = new HashMap<IVMNode, Integer>();
|
||||
int offset = 0;
|
||||
for (int i = 0; i < childNodes.length; i++) {
|
||||
data.put(childNodes[i], offset);
|
||||
offset += counts[i];
|
||||
}
|
||||
// As the final value, put the total count in the return map, with null key.
|
||||
data.put(null, offset);
|
||||
rm.setData(data);
|
||||
rm.done();
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < childNodes.length; i++) {
|
||||
final int nodeIndex = i;
|
||||
getVMProvider().updateNode(
|
||||
childNodes[i],
|
||||
new IChildrenCountUpdate[] {
|
||||
new VMChildrenCountUpdate(
|
||||
delta, getVMProvider().getPresentationContext(),
|
||||
childrenCountMultiRequestMon.add(
|
||||
new DataRequestMonitor<Integer>(getVMProvider().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
counts[nodeIndex] = getData();
|
||||
childrenCountMultiRequestMon.requestMonitorDone(this);
|
||||
}
|
||||
})
|
||||
)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Map<IVMNode, Integer> data = new HashMap<IVMNode, Integer>();
|
||||
for (int i = 0; i < childNodes.length; i++) {
|
||||
data.put(childNodes[i], -1);
|
||||
}
|
||||
data.put(null, -1);
|
||||
rm.setData(data);
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that returns the child nodes which return
|
||||
* <code>true</code> to the <code>hasDeltaFlags()</code> test for the given
|
||||
* event.
|
||||
*/
|
||||
protected Map<IVMNode, Integer> getChildNodesWithDeltaFlags(IVMNode node, ModelDelta parentDelta, Object e) {
|
||||
Map<IVMNode, Integer> nodes = new HashMap<IVMNode, Integer>();
|
||||
for (final IVMNode childNode : getVMProvider().getChildVMNodes(node)) {
|
||||
if (!childNode.equals(node)) {
|
||||
int delta = getDeltaFlags(childNode, parentDelta, e);
|
||||
if (delta != IModelDelta.NO_CHANGE) {
|
||||
nodes.put(childNode, delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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.dd.dsf.ui.viewmodel;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
|
||||
/**
|
||||
* Special type of the view model node, which can be used as a root node
|
||||
* for a hierarchy. The root node of a layout hierarchy has to implement this
|
||||
* interface.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public interface IRootVMNode extends IVMNode{
|
||||
|
||||
/**
|
||||
* Returns whether the given event should be processed for delta generation.
|
||||
* Root node is different than other nodes in that there is only one root
|
||||
* element in the view model provider hierarchy. This method allows the root
|
||||
* node to match up the root object of the provider with the given event. If
|
||||
* the root node can determine that the given event does not apply to the root
|
||||
* object, it should return false so that the event is ignored.
|
||||
*
|
||||
* @param rootObject The root object of the VM provider
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
public boolean isDeltaEvent(Object rootObject, Object event);
|
||||
|
||||
/**
|
||||
* Version of the {@link IVMNode#buildDelta(Object, ViewModelDelta, org.eclipse.dd.dsf.concurrent.RequestMonitor)}
|
||||
* method, which creates and returns the root node of the delta. It does
|
||||
* not require a parent object for the delta, as this is the root node.
|
||||
* @param event Event to process.
|
||||
* @param rm Result notification, contains the root of the delta.
|
||||
*/
|
||||
public void createRootDelta(Object rootObject, Object event, DataRequestMonitor<ModelDelta> rm);
|
||||
}
|
|
@ -14,13 +14,16 @@ import org.eclipse.core.runtime.IAdaptable;
|
|||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* View Model element which is stored as the data object of nodes in the viewer.
|
||||
* View model element which is stored as the data object of nodes in the viewer.
|
||||
* The implementation of this interface is usually a wrapper object for an object
|
||||
* from some data model, which is then used to correctly implement the
|
||||
* {@link #equals(Object)} and {@link #hashCode()} methods of this wrapper.
|
||||
*/
|
||||
@Immutable
|
||||
public interface IVMContext extends IAdaptable {
|
||||
|
||||
/**
|
||||
* Returns the layout node that originated this element.
|
||||
* Returns the view model node that originated this element.
|
||||
*/
|
||||
public IVMLayoutNode getLayoutNode();
|
||||
public IVMNode getVMNode();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.ui.viewmodel;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public interface IVMModelProxy extends IModelProxy {
|
||||
|
||||
public Object getRootElement();
|
||||
|
||||
public boolean isDeltaEvent(Object event);
|
||||
|
||||
public void createDelta(final Object event, final DataRequestMonitor<IModelDelta> rm);
|
||||
|
||||
public void fireModelChanged(IModelDelta delta);
|
||||
|
||||
}
|
|
@ -12,82 +12,46 @@ package org.eclipse.dd.dsf.ui.viewmodel;
|
|||
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
|
||||
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.IElementContentProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
|
||||
/**
|
||||
* View model layout nodes are combined together into a tree, to collectively
|
||||
* View model nodes are configured with a view model provider to collectively
|
||||
* define the layout of a view. Each layout node generates elements of type
|
||||
* IVMContext which are then stored in the viewer.
|
||||
* <p>
|
||||
* Besides the standard Data Model Context based implementation, this
|
||||
* node could be implemented to present data from any source, not necessarily
|
||||
* DSF services. It could also define a static node which operates on basis
|
||||
* of other data in the view tree.
|
||||
* {@link IVMContext} which are then stored in the viewer.
|
||||
*
|
||||
* <p/>
|
||||
* NOTE: This interface extends <code>IElementContentProvider</code> but it has
|
||||
* slightly different parameter requirements. For the
|
||||
* {@link IElementContentProvider#update(IChildrenUpdate[])} method, this class
|
||||
* can accept an update where {@link IChildrenUpdate#getOffset()} and
|
||||
* {@link IChildrenUpdate#getLength()} may return -1. In this case the
|
||||
* implementation should return all available elements for the given parent.<br>
|
||||
* Also the for the {@link IElementContentProvider#update(IHasChildrenUpdate[])} and
|
||||
* {@link IElementContentProvider#update(IChildrenCountUpdate[])} methods, the
|
||||
* implementation may return an error with an error code of {@link IDsfService#NOT_SUPPORTED}.
|
||||
* In this case the caller of this update should call
|
||||
* {@link IElementContentProvider#update(IChildrenUpdate[])}
|
||||
* instead.
|
||||
*
|
||||
* @see AbstractDMVMProvider
|
||||
* @see IElementContentProvider
|
||||
*/
|
||||
@ConfinedToDsfExecutor("")
|
||||
@SuppressWarnings("restriction")
|
||||
public interface IVMLayoutNode
|
||||
public interface IVMNode extends IElementContentProvider
|
||||
{
|
||||
/**
|
||||
* Retrieves the associated VM Provider.
|
||||
* Retrieves the view model provider that this node is configured with.
|
||||
*/
|
||||
public IVMProvider getVMProvider();
|
||||
|
||||
/**
|
||||
* Retrieves information whether for a given path in the viewer,
|
||||
* there are any elements available in this node.
|
||||
*
|
||||
* @param updates The update objects which need to be filled in with results
|
||||
* calculated by this method.
|
||||
* Even though the "children" interface is reused, the updates refer to the
|
||||
* elements of this layout node, and not it's children.
|
||||
*/
|
||||
public void updateHasElements(IHasChildrenUpdate[] updates);
|
||||
|
||||
/**
|
||||
* Retrieves the number of available elements in this node for the given
|
||||
* path in the viewer.
|
||||
*
|
||||
* @param updates The update object which needs to be filled in with result
|
||||
* calculated by this method.
|
||||
* Even though the "children" interface is reused, the updates refer to the
|
||||
* elements of this layout node, and not it's children.
|
||||
*/
|
||||
public void updateElementCount(IChildrenCountUpdate update);
|
||||
|
||||
/**
|
||||
* Retrieves the element objects of this node for the given path in the
|
||||
* viewer, and for the given range of indexes. <br>
|
||||
* NOTE: update.getOffset() and update.getLength() may return -1.
|
||||
* The range of children, denoted by ILabelUpdate.getOffset()
|
||||
* and ILabelUpdate.getLength(), may not be specified, in which case these
|
||||
* methods may return -1. This means that all the elements should be
|
||||
* retrieved for this node.<br>
|
||||
*
|
||||
* @param updates The update object which needs to be filled in with result
|
||||
* calculated by this method.
|
||||
* Even though the "children" interface is reused, the updates refer to the
|
||||
* elements of this layout node, and not it's children.
|
||||
*/
|
||||
public void updateElements(IChildrenUpdate update);
|
||||
|
||||
|
||||
/**
|
||||
* Configures the child layout nodes for this node.
|
||||
* @param childNodes
|
||||
*/
|
||||
public void setChildNodes(IVMLayoutNode[] childNodes);
|
||||
|
||||
/**
|
||||
* Returns the list of child layout nodes which are configured for this node.
|
||||
*/
|
||||
public IVMLayoutNode[] getChildLayoutNodes();
|
||||
|
||||
/**
|
||||
* Returns the potential delta flags that would be generated by this node
|
||||
* for the given event.
|
||||
|
@ -126,7 +90,23 @@ public interface IVMLayoutNode
|
|||
* @param requestMonitor Return token, which notifies the caller that the calculation is
|
||||
* complete.
|
||||
*/
|
||||
public void buildDelta(Object event, VMDelta parent, int nodeOffset, RequestMonitor requestMonitor);
|
||||
public void buildDelta(Object event, ModelDelta parent, int nodeOffset, RequestMonitor requestMonitor);
|
||||
|
||||
/**
|
||||
* Returns the view model element for the given data model event. This method
|
||||
* is optional and it allows the view model provider to optimize event processing
|
||||
* by avoiding the need to retrieve all possible elements for the given node.
|
||||
* </p>
|
||||
* For example: If a threads node implementation is given a thread stopped event in
|
||||
* for this method, and the stopped event included a reference to the thread. Then
|
||||
* the implementation should create a view model context for that thread and return it
|
||||
* here.
|
||||
*
|
||||
* @param event The event to check for the data model object.
|
||||
* @return A view model object if it can be calculated, <code>null</code>
|
||||
* if it cannot.
|
||||
*/
|
||||
public IVMContext getContextFromEvent(Object event);
|
||||
|
||||
/**
|
||||
* Releases the resources held by this node.
|
|
@ -1,6 +1,8 @@
|
|||
package org.eclipse.dd.dsf.ui.viewmodel;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory;
|
||||
|
@ -8,11 +10,31 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationCont
|
|||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputProvider;
|
||||
|
||||
/**
|
||||
* The View Model Provider handles the layout of a given model within a
|
||||
* The view model provider handles the layout of a given model within a
|
||||
* single viewer. The View Model Adapter delegates calls for view content to
|
||||
* this object for a view that this provider handles.
|
||||
*
|
||||
* <p/>
|
||||
* A given view model provider is typically configured with a number of
|
||||
* {@link IVMNode} objects which are organized in a parent-child hierarchy.
|
||||
* The node hierarchy has a root node which is retrieved using {@link #getRootVMNode()}.
|
||||
*
|
||||
* <p/>
|
||||
* Note on concurency: The view model provider is single-threaded and it has to be
|
||||
* accessed only using the <code>Executor</code> returned by {@link #getExecutor()}.
|
||||
* The thread of this executor should be the display thread used by the viewer
|
||||
* corresponding to the view model provider. Currently the flexible hierarchy
|
||||
* interfaces that this interface extends do not guarantee that their methods
|
||||
* will be called on the display thread, although from their use we are making
|
||||
* this assumption (bug 213629). {@link IElementContentProvider} is an
|
||||
* exception to this, it is called by the TreeModelViewer on a background
|
||||
* thread, however it is not expected that the viewer will be calling the
|
||||
* IVMProvider directly. Rather, it is expected that the viewer will call
|
||||
* {@link IVMAdapter} which implements <code>IElementContentProvider</code>,
|
||||
* and <code>IVMAdapter</code> implementation is expected to switch to
|
||||
* provider's thread before delegating the call to it.
|
||||
*/
|
||||
@ThreadSafe
|
||||
@ConfinedToDsfExecutor("#getExecutor()")
|
||||
@SuppressWarnings("restriction")
|
||||
public interface IVMProvider
|
||||
extends IElementContentProvider, IModelProxyFactory, IColumnPresentationFactory, IViewerInputProvider
|
||||
|
@ -23,19 +45,25 @@ public interface IVMProvider
|
|||
public IVMAdapter getVMAdapter();
|
||||
|
||||
/**
|
||||
* Returns the root layout node that is configured in this provider.
|
||||
* It may return null, if a root node is not yet configured.
|
||||
* Returns the executor that needs to be used to access this provider.
|
||||
*/
|
||||
public IVMRootLayoutNode getRootLayoutNode();
|
||||
public Executor getExecutor();
|
||||
|
||||
/**
|
||||
* Returns the root element of the view model. If the given view model is
|
||||
* used to populate the entire contents of the view, then this is the input
|
||||
* element for the viewer. If the view model is used to populate only a
|
||||
* sub-tree section of the view, then this is the root element of that
|
||||
* sub-tree.
|
||||
* Returns the root node that is configured in this provider.
|
||||
* It may return null, if a root node is not yet configured.
|
||||
*/
|
||||
public Object getRootElement();
|
||||
public IRootVMNode getRootVMNode();
|
||||
|
||||
/**
|
||||
* Returns an array of nodes which are configured as child nodes of the given node.
|
||||
*/
|
||||
public IVMNode[] getChildVMNodes(IVMNode node);
|
||||
|
||||
/**
|
||||
* Retrieves the list of all nodes configured for this provider.
|
||||
*/
|
||||
public IVMNode[] getAllVMNodes();
|
||||
|
||||
/**
|
||||
* Returns the presentation context of the viewer that this provider
|
||||
|
@ -43,12 +71,6 @@ public interface IVMProvider
|
|||
*/
|
||||
public IPresentationContext getPresentationContext();
|
||||
|
||||
/**
|
||||
* Allows other subsystems to force the layout mode associated with the specified
|
||||
* VM context to refresh. If null is passed then the RootLayoutNode is told to refresh.
|
||||
*/
|
||||
public void refresh(IVMContext element);
|
||||
|
||||
/**
|
||||
* Cleans up the resources associated with this provider.
|
||||
*/
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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.dd.dsf.ui.viewmodel;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
|
||||
/**
|
||||
* Special type of the view model layout node, which can be used as a root node
|
||||
* for a hierarchy. The root node of a layout hierarchy has to implement this
|
||||
* interface.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public interface IVMRootLayoutNode extends IVMLayoutNode{
|
||||
|
||||
/**
|
||||
* Version of the {@link IVMLayoutNode#buildDelta(Object, ViewModelDelta, org.eclipse.dd.dsf.concurrent.RequestMonitor)}
|
||||
* method, which creates and returns the root node of the delta. It does
|
||||
* not require a parent object for the delta, as this is the root node.
|
||||
* @param event Event to process.
|
||||
* @param rm Result notification, contains the root of the delta.
|
||||
*/
|
||||
public void createDelta(Object event, DataRequestMonitor<IModelDelta> rm);
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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.dd.dsf.ui.viewmodel;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
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.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
|
||||
/**
|
||||
* Default implementation of a root view model node. This class may be sub-classed
|
||||
* to implement model-specific event handling.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class RootVMNode extends AbstractVMNode implements IRootVMNode {
|
||||
|
||||
public RootVMNode(AbstractVMProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
public void update(IChildrenUpdate[] updates) {
|
||||
throw new UnsupportedOperationException("Root view model node should never be queried for list of elements."); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public void update(IChildrenCountUpdate[] updates) {
|
||||
throw new UnsupportedOperationException("Root view model node should never be queried for list of elements."); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public void update(IHasChildrenUpdate[] updates) {
|
||||
throw new UnsupportedOperationException("Root view model node should never be queried for list of elements."); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation does not examine the event and assumes that every
|
||||
* event should be processed to generate a delta.
|
||||
*/
|
||||
public boolean isDeltaEvent(Object rootObject, Object event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation creates a delta assuming that the root layout node
|
||||
* is the input object into the view.
|
||||
*/
|
||||
public void createRootDelta(Object rootObject, Object event, final DataRequestMonitor<ModelDelta> rm) {
|
||||
rm.setData(new ModelDelta(rootObject, 0, IModelDelta.NO_CHANGE));
|
||||
rm.done();
|
||||
}
|
||||
|
||||
|
||||
public int getDeltaFlags(Object event) {
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
public void buildDelta(Object event, ModelDelta parent, int nodeOffset, RequestMonitor requestMonitor) {
|
||||
requestMonitor.done();
|
||||
}
|
||||
}
|
|
@ -12,22 +12,35 @@ package org.eclipse.dd.dsf.ui.viewmodel;
|
|||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
|
||||
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.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* Helper class implementation of an update object to use with IElementContentProvider.
|
||||
* @see IElementContentProvider
|
||||
* Helper class implementation of the {@link IChildrenCountUpdate} update object.
|
||||
*
|
||||
* @see VMViewerUpdate
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class VMElementsCountUpdate extends VMViewerUpdate implements IChildrenCountUpdate {
|
||||
public class VMChildrenCountUpdate extends VMViewerUpdate implements IChildrenCountUpdate {
|
||||
final private DataRequestMonitor<Integer> fCountRequestMonitor;
|
||||
|
||||
public VMElementsCountUpdate(IViewerUpdate clientUpdate, DataRequestMonitor<Integer> rm) {
|
||||
public VMChildrenCountUpdate(IViewerUpdate clientUpdate, DataRequestMonitor<Integer> rm) {
|
||||
super(clientUpdate, rm);
|
||||
fCountRequestMonitor = rm;
|
||||
}
|
||||
|
||||
public VMChildrenCountUpdate(IModelDelta delta, IPresentationContext presentationContext, DataRequestMonitor<Integer> rm) {
|
||||
super(delta, presentationContext, rm);
|
||||
fCountRequestMonitor = rm;
|
||||
}
|
||||
|
||||
public VMChildrenCountUpdate(TreePath elementPath, Object viewerInput, IPresentationContext presentationContext, DataRequestMonitor<Integer> rm) {
|
||||
super(elementPath, viewerInput, presentationContext, rm);
|
||||
fCountRequestMonitor = rm;
|
||||
}
|
||||
|
||||
public void setChildCount(int count) {
|
||||
fCountRequestMonitor.setData(count);
|
||||
}
|
|
@ -19,25 +19,49 @@ import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
|||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.DsfUIPlugin;
|
||||
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.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* Helper class implementation of an update object to use with IElementContentProvider.
|
||||
* @see IElementContentProvider
|
||||
* Helper class implementation of the {@link IChildrenUpdate} update object.
|
||||
*
|
||||
* @see VMViewerUpdate
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class VMElementsUpdate extends VMViewerUpdate implements IChildrenUpdate {
|
||||
public class VMChildrenUpdate extends VMViewerUpdate implements IChildrenUpdate {
|
||||
private final int fOffset;
|
||||
private final int fLength;
|
||||
protected final List<Object> fElements;
|
||||
|
||||
public VMElementsUpdate(IChildrenUpdate clientUpdate, int offset, int length, DataRequestMonitor<List<Object>> requestMonitor) {
|
||||
public VMChildrenUpdate(IViewerUpdate clientUpdate, int offset, int length,
|
||||
DataRequestMonitor<List<Object>> requestMonitor)
|
||||
{
|
||||
super(clientUpdate, requestMonitor);
|
||||
fOffset = offset;
|
||||
fLength = length;
|
||||
fElements = length > 0 ? new ArrayList<Object>(length) : new ArrayList<Object>();
|
||||
}
|
||||
|
||||
public VMChildrenUpdate(IModelDelta delta, IPresentationContext presentationContext, int offset, int length,
|
||||
DataRequestMonitor<List<Object>> rm)
|
||||
{
|
||||
super(delta, presentationContext, rm);
|
||||
fOffset = offset;
|
||||
fLength = length;
|
||||
fElements = length > 0 ? new ArrayList<Object>(length) : new ArrayList<Object>();
|
||||
}
|
||||
|
||||
public VMChildrenUpdate(TreePath elementPath, Object viewerInput, IPresentationContext presentationContext,
|
||||
int offset, int length, DataRequestMonitor<List<Object>> rm)
|
||||
{
|
||||
super(elementPath, viewerInput, presentationContext, rm);
|
||||
fOffset = offset;
|
||||
fLength = length;
|
||||
fElements = length > 0 ? new ArrayList<Object>(length) : new ArrayList<Object>();
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return fOffset;
|
||||
}
|
||||
|
@ -74,10 +98,37 @@ public class VMElementsUpdate extends VMViewerUpdate implements IChildrenUpdate
|
|||
@Override
|
||||
public void done() {
|
||||
@SuppressWarnings("unchecked")
|
||||
DataRequestMonitor<List<Object>> rm = (DataRequestMonitor<List<Object>>)fRequestMonitor;
|
||||
if (fElements.size() == fLength || fLength == -1 ) {
|
||||
rm.setData(fElements);
|
||||
} else {
|
||||
DataRequestMonitor<List<Object>> rm = (DataRequestMonitor<List<Object>>)getRequestMonitor();
|
||||
|
||||
/* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=202109
|
||||
*
|
||||
* A flexible hierarchy bug/optimization causes query with incorrect
|
||||
* IChildrenUpdate[] array length.
|
||||
*
|
||||
* We found this while deleting a register node. Example:
|
||||
*
|
||||
* the register view displays:
|
||||
* PC
|
||||
* EAX
|
||||
* EBX
|
||||
* ECX
|
||||
* EDX
|
||||
*
|
||||
* we delete EBX and force a context refresh.
|
||||
*
|
||||
* flexible hierarchy queries for IChildrenUpdate[5] and IChildrenCountUpdate at
|
||||
* the same time.
|
||||
*
|
||||
* VMElementsUpdate, used by VMCache to wrap the IChildrenUpdate, generates an
|
||||
* IStatus.ERROR with message "Incomplete elements of updates" when fElements
|
||||
* count (provided by service) does not match the length provided by the original
|
||||
* update query.
|
||||
*
|
||||
* Workaround, always set the elements array in the request monitor, but still set
|
||||
* the error status.
|
||||
*/
|
||||
rm.setData(fElements);
|
||||
if (rm.getStatus().isOK() && fLength != -1 && fElements.size() != fLength) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, "Incomplete elements of updates", null)); //$NON-NLS-1$
|
||||
}
|
||||
super.done();
|
|
@ -1,330 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2006 IBM Corporation 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
* Wind River Systems - adapted to use in DSF
|
||||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.ui.viewmodel;
|
||||
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDeltaVisitor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
|
||||
/**
|
||||
* This delta class mostly just duplicates the ModelDelta implemention, but
|
||||
* it allows clients to modify the flags after the original object is
|
||||
* constructed.
|
||||
*
|
||||
* @see IModelDelta#getNodes()
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class VMDelta extends ModelDelta {
|
||||
|
||||
private VMDelta fParent;
|
||||
private Object fElement;
|
||||
private int fFlags;
|
||||
private VMDelta[] fNodes = EMPTY_NODES;
|
||||
private Object fReplacement;
|
||||
private int fIndex;
|
||||
private static final VMDelta[] EMPTY_NODES = new VMDelta[0];
|
||||
private int fChildCount = -1;
|
||||
|
||||
/**
|
||||
* Constructs a new delta for the given element.
|
||||
*
|
||||
* @param vmcElement model element
|
||||
* @param flags change flags
|
||||
*/
|
||||
public VMDelta(Object element, int flags) {
|
||||
super(element, flags);
|
||||
fElement = element;
|
||||
fFlags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new delta for the given element to be replaced
|
||||
* with the specified replacement element.
|
||||
*
|
||||
* @param vmcElement model element
|
||||
* @param replacement replacement element
|
||||
* @param flags change flags
|
||||
*/
|
||||
public VMDelta(Object element, Object replacement, int flags) {
|
||||
super(element, replacement, flags);
|
||||
fElement = element;
|
||||
fReplacement = replacement;
|
||||
fFlags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new delta for the given element to be inserted at
|
||||
* the specified index.
|
||||
*
|
||||
* @param vmcElement model element
|
||||
* @param index insertion position
|
||||
* @param flags change flags
|
||||
*/
|
||||
public VMDelta(Object element, int index, int flags) {
|
||||
super(element, index, flags);
|
||||
fElement = element;
|
||||
fIndex = index;
|
||||
fFlags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new delta for the given element at the specified index
|
||||
* relative to its parent with the given number of children.
|
||||
*
|
||||
* @param element model element
|
||||
* @param index insertion position
|
||||
* @param flags change flags
|
||||
* @param childCount number of children this node has
|
||||
*/
|
||||
public VMDelta(Object element, int index, int flags, int childCount) {
|
||||
super(element, index, flags, childCount);
|
||||
fElement = element;
|
||||
fIndex = index;
|
||||
fFlags = flags;
|
||||
fChildCount = childCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the non-VMC element if one is set, otherwise returns the VMC
|
||||
* element of this delta node.
|
||||
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getElement()
|
||||
*/
|
||||
@Override
|
||||
public Object getElement() {
|
||||
return fElement;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getFlags()
|
||||
*/
|
||||
@Override
|
||||
public int getFlags() {
|
||||
return fFlags;
|
||||
}
|
||||
|
||||
public void addFlags(int flags) {
|
||||
fFlags |= flags;
|
||||
}
|
||||
|
||||
public void setChildCount(int count) {
|
||||
fChildCount = count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a child node to this delta with the given element and change flags,
|
||||
* and returns the child delta.
|
||||
*
|
||||
* @param element child element to add
|
||||
* @param flags change flags for child
|
||||
* @return newly created child delta
|
||||
*/
|
||||
@Override
|
||||
public VMDelta addNode(Object element, int flags) {
|
||||
VMDelta node = new VMDelta(element, flags);
|
||||
node.setParent(this);
|
||||
addDelta(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a child node to this delta to replace the given element with the
|
||||
* specified replacement element and change flags, and returns the
|
||||
* newly created child delta.
|
||||
*
|
||||
* @param element child element to add to this delta
|
||||
* @param replacement replacement element for the child element
|
||||
* @param flags change flags
|
||||
* @return newly created child delta
|
||||
*/
|
||||
@Override
|
||||
public VMDelta addNode(Object element, Object replacement, int flags) {
|
||||
VMDelta node = new VMDelta(element, replacement, flags);
|
||||
node.setParent(this);
|
||||
addDelta(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a child delta to this delta to insert the specified element at
|
||||
* the given index, and returns the newly created child delta.
|
||||
*
|
||||
* @param element child element in insert
|
||||
* @param index index of insertion
|
||||
* @param flags change flags
|
||||
* @return newly created child delta
|
||||
*/
|
||||
@Override
|
||||
public VMDelta addNode(Object element, int index, int flags) {
|
||||
VMDelta node = new VMDelta(element, index, flags);
|
||||
node.setParent(this);
|
||||
addDelta(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a child delta to this delta at the specified index with the
|
||||
* given number of children, and returns the newly created child delta.
|
||||
*
|
||||
* @param element child element in insert
|
||||
* @param index index of the element relative to parent
|
||||
* @param flags change flags
|
||||
* @param numChildren the number of children the element has
|
||||
* @return newly created child delta
|
||||
*/
|
||||
@Override
|
||||
public VMDelta addNode(Object element, int index, int flags, int numChildren) {
|
||||
VMDelta node = new VMDelta(element, index, flags, numChildren);
|
||||
node.setParent(this);
|
||||
addDelta(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parent delta of this delta
|
||||
*
|
||||
* @param node parent delta
|
||||
*/
|
||||
void setParent(VMDelta node) {
|
||||
fParent = node;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getParent()
|
||||
*/
|
||||
@Override
|
||||
public VMDelta getParentDelta() {
|
||||
return fParent;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getReplacementElement()
|
||||
*/
|
||||
@Override
|
||||
public Object getReplacementElement() {
|
||||
return fReplacement;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getIndex()
|
||||
*/
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return fIndex;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getNodes()
|
||||
*/
|
||||
@Override
|
||||
public VMDelta[] getChildDeltas() {
|
||||
return fNodes;
|
||||
}
|
||||
|
||||
private void addDelta(VMDelta delta) {
|
||||
if (fNodes.length == 0) {
|
||||
fNodes = new VMDelta[]{delta};
|
||||
} else {
|
||||
VMDelta[] nodes = new VMDelta[fNodes.length + 1];
|
||||
System.arraycopy(fNodes, 0, nodes, 0, fNodes.length);
|
||||
nodes[fNodes.length] = delta;
|
||||
fNodes = nodes;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("Model Delta Start\n"); //$NON-NLS-1$
|
||||
appendDetail(buf, this);
|
||||
buf.append("Model Delta End\n"); //$NON-NLS-1$
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void appendDetail(StringBuffer buf, VMDelta delta) {
|
||||
buf.append("\tElement: "); //$NON-NLS-1$
|
||||
buf.append(delta.getElement());
|
||||
buf.append('\n');
|
||||
buf.append("\t\tFlags: "); //$NON-NLS-1$
|
||||
int flags = delta.getFlags();
|
||||
if (flags == 0) {
|
||||
buf.append("NO_CHANGE"); //$NON-NLS-1$
|
||||
} else {
|
||||
if ((flags & IModelDelta.ADDED) > 0) {
|
||||
buf.append("ADDED | "); //$NON-NLS-1$
|
||||
}
|
||||
if ((flags & IModelDelta.CONTENT) > 0) {
|
||||
buf.append("CONTENT | "); //$NON-NLS-1$
|
||||
}
|
||||
if ((flags & IModelDelta.EXPAND) > 0) {
|
||||
buf.append("EXPAND | "); //$NON-NLS-1$
|
||||
}
|
||||
if ((flags & IModelDelta.INSERTED) > 0) {
|
||||
buf.append("INSERTED | "); //$NON-NLS-1$
|
||||
}
|
||||
if ((flags & IModelDelta.REMOVED) > 0) {
|
||||
buf.append("REMOVED | "); //$NON-NLS-1$
|
||||
}
|
||||
if ((flags & IModelDelta.REPLACED) > 0) {
|
||||
buf.append("REPLACED | "); //$NON-NLS-1$
|
||||
}
|
||||
if ((flags & IModelDelta.SELECT) > 0) {
|
||||
buf.append("SELECT | "); //$NON-NLS-1$
|
||||
}
|
||||
if ((flags & IModelDelta.STATE) > 0) {
|
||||
buf.append("STATE | "); //$NON-NLS-1$
|
||||
}
|
||||
if ((flags & IModelDelta.INSTALL) > 0) {
|
||||
buf.append("INSTALL | "); //$NON-NLS-1$
|
||||
}
|
||||
if ((flags & IModelDelta.UNINSTALL) > 0) {
|
||||
buf.append("UNINSTALL | "); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
buf.append('\n');
|
||||
buf.append("\t\tIndex: "); //$NON-NLS-1$
|
||||
buf.append(delta.fIndex);
|
||||
buf.append(" Child Count: "); //$NON-NLS-1$
|
||||
buf.append(delta.fChildCount);
|
||||
buf.append('\n');
|
||||
IModelDelta[] nodes = delta.getChildDeltas();
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
appendDetail(buf, (VMDelta)nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta#getChildCount()
|
||||
*/
|
||||
@Override
|
||||
public int getChildCount() {
|
||||
return fChildCount;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta#accept(org.eclipse.debug.internal.ui.viewers.provisional.IModelDeltaVisitor)
|
||||
*/
|
||||
@Override
|
||||
public void accept(IModelDeltaVisitor visitor) {
|
||||
doAccept(visitor, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doAccept(IModelDeltaVisitor visitor, int depth) {
|
||||
if (visitor.visit(this, depth)) {
|
||||
ModelDelta[] childDeltas = getChildDeltas();
|
||||
for (int i = 0; i < childDeltas.length; i++) {
|
||||
((VMDelta)childDeltas[i]).doAccept(visitor, depth+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -11,23 +11,37 @@
|
|||
package org.eclipse.dd.dsf.ui.viewmodel;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||
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.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* Helper class implementation of an update object to use with IElementContentProvider.
|
||||
* @see IElementContentProvider
|
||||
* Helper class implementation of the {@link IHasChildrenUpdate} update object.
|
||||
*
|
||||
* @see VMViewerUpdate
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class VMHasElementsUpdate extends VMViewerUpdate implements IHasChildrenUpdate {
|
||||
public class VMHasChildrenUpdate extends VMViewerUpdate implements IHasChildrenUpdate {
|
||||
|
||||
final private DataRequestMonitor<Boolean> fHasElemsRequestMonitor;
|
||||
|
||||
public VMHasElementsUpdate(IHasChildrenUpdate clientUpdate, DataRequestMonitor<Boolean> rm) {
|
||||
public VMHasChildrenUpdate(IViewerUpdate clientUpdate, DataRequestMonitor<Boolean> rm) {
|
||||
super(clientUpdate, rm);
|
||||
fHasElemsRequestMonitor = rm;
|
||||
}
|
||||
|
||||
public VMHasChildrenUpdate(IModelDelta delta, IPresentationContext presentationContext, DataRequestMonitor<Boolean> rm) {
|
||||
super(delta, presentationContext, rm);
|
||||
fHasElemsRequestMonitor = rm;
|
||||
}
|
||||
|
||||
public VMHasChildrenUpdate(TreePath elementPath, Object viewerInput, IPresentationContext presentationContext, DataRequestMonitor<Boolean> rm) {
|
||||
super(elementPath, viewerInput, presentationContext, rm);
|
||||
fHasElemsRequestMonitor = rm;
|
||||
}
|
||||
|
||||
public void setHasChilren(boolean hasChildren) {
|
||||
fHasElemsRequestMonitor.setData(hasChildren);
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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.dd.dsf.ui.viewmodel;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
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.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
|
||||
/**
|
||||
* Default implementation of a root layout node. This class may be sub-classed
|
||||
* to implement model-specific event handling.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class VMRootLayoutNode extends AbstractVMLayoutNode implements IVMRootLayoutNode {
|
||||
|
||||
public VMRootLayoutNode(AbstractVMProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation only fulfills the requirements of the super-interface.
|
||||
* There is no use case for a root node implementing this method, but its
|
||||
* easier to just implement it for sake of uniformity of model.
|
||||
*/
|
||||
public void updateElements(IChildrenUpdate update) {
|
||||
// Ignore startIdx, endIdx, since there's only one element to be had.
|
||||
update.setChild(getVMProvider().getRootElement(), 0);
|
||||
update.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation only fulfills the requirements of the super-interface.
|
||||
* There is no use case for a root node implementing this method, but its
|
||||
* easier to just impelemnt it for sake of uniformity of model.
|
||||
*/
|
||||
public void updateElementCount(IChildrenCountUpdate update) {
|
||||
update.setChildCount(1);
|
||||
update.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation only fulfills the requirements of the super-interface.
|
||||
* There is no use case for a root node implementing this method, but its
|
||||
* easier to just implement it for sake of uniformity of model.
|
||||
*/
|
||||
public void updateHasElements(IHasChildrenUpdate[] updates) {
|
||||
for (IHasChildrenUpdate update : updates) {
|
||||
update.setHasChilren(true);
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation only fulfills the requirements of the super-interface.
|
||||
* There is no use case for a root node implementing this method, but its
|
||||
* easier to just implement it for sake of uniformity of model.
|
||||
*/
|
||||
public void updateLabel(@SuppressWarnings("unused")
|
||||
IVMContext vmc, ILabelUpdate update) {
|
||||
update.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation creates a delta assuming that the root layout node
|
||||
* is the input object into the view.
|
||||
*/
|
||||
public void createDelta(Object event, final DataRequestMonitor<IModelDelta> rm) {
|
||||
final Map<IVMLayoutNode,Integer> childNodeDeltas = getChildNodesWithDeltaFlags(event);
|
||||
assert childNodeDeltas.size() != 0 : "Caller should make sure that there are deltas for given event."; //$NON-NLS-1$
|
||||
|
||||
// Always create the rootDelta, no matter what delta flags the child nodes have.
|
||||
final VMDelta rootDelta = new VMDelta(getVMProvider().getRootElement(), IModelDelta.NO_CHANGE);
|
||||
|
||||
callChildNodesToBuildDelta(
|
||||
childNodeDeltas, rootDelta, event,
|
||||
new RequestMonitor(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!isDisposed()) super.handleCompleted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleOK() {
|
||||
rm.setData(rootDelta);
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Object getRootObject() {
|
||||
return getVMProvider().getRootElement();
|
||||
}
|
||||
}
|
|
@ -10,41 +10,161 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.ui.viewmodel;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.DsfUIPlugin;
|
||||
import org.eclipse.debug.core.IRequest;
|
||||
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.IElementMementoProvider;
|
||||
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.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* Helper class implementation of an update object to use with IElementContentProvider.
|
||||
* @see IElementContentProvider
|
||||
* Helper class implementation of the update objects used with
|
||||
* {@link IElementContentProvider}, {@link IElementLabelProvider},
|
||||
* and {@link IElementMementoProvider}. The viewer update can be constructed
|
||||
* using a higher level update object or a set of parameters to fulfill the
|
||||
* <code>IViewerUpdate</code> interface.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class VMViewerUpdate implements IViewerUpdate {
|
||||
final protected RequestMonitor fRequestMonitor;
|
||||
final protected IViewerUpdate fClientUpdate;
|
||||
|
||||
/**
|
||||
* The request monitor to be called when this update is completed.
|
||||
*/
|
||||
final private RequestMonitor fRequestMonitor;
|
||||
|
||||
/**
|
||||
* A higher-level update that this update is based on. If specified, the given
|
||||
* update is used to delegate calls to {@link #cancel()} and {@link #isCanceled()}.
|
||||
*/
|
||||
final private IViewerUpdate fClientUpdate;
|
||||
|
||||
/**
|
||||
* The flag indicating whether this update was cancelled. This flag is not used
|
||||
* if the {@link #fClientUpdate} is initialized.
|
||||
*/
|
||||
final private AtomicBoolean fCanceled;
|
||||
|
||||
/**
|
||||
* The viewer input object for this update.
|
||||
*/
|
||||
final private Object fViewerInput;
|
||||
|
||||
/**
|
||||
* The element object of this update.
|
||||
*/
|
||||
final private Object fElement;
|
||||
|
||||
/**
|
||||
* The element path of this update.
|
||||
*/
|
||||
final private TreePath fElementPath;
|
||||
|
||||
/**
|
||||
* The presentation context of this update.
|
||||
*/
|
||||
final private IPresentationContext fPresentationContext;
|
||||
|
||||
/**
|
||||
* Creates a viewer update based on a higher-level update. The update element
|
||||
* information as well as cancel requests are delegated to the given client
|
||||
* update.
|
||||
* <p/>
|
||||
* Note: this update will not automatically call the client update's
|
||||
* {@link IRequest#done()} method. The user of this update should supply
|
||||
* a request monitor which properly completes the client update.
|
||||
*
|
||||
* @param clientUpdate Client update that this update is based on.
|
||||
* @param requestMonitor Call-back invoked when this update completes.
|
||||
*/
|
||||
public VMViewerUpdate(IViewerUpdate clientUpdate, RequestMonitor requestMonitor) {
|
||||
fViewerInput = clientUpdate.getViewerInput();
|
||||
fElement = clientUpdate.getElement();
|
||||
fElementPath = clientUpdate.getElementPath();
|
||||
fPresentationContext = clientUpdate.getPresentationContext();
|
||||
fRequestMonitor = requestMonitor;
|
||||
fClientUpdate = clientUpdate;
|
||||
fCanceled = null;
|
||||
}
|
||||
|
||||
public Object getViewerInput() { return fClientUpdate.getViewerInput(); }
|
||||
public Object getElement() { return fClientUpdate.getElement(); }
|
||||
public TreePath getElementPath() { return fClientUpdate.getElementPath(); }
|
||||
public IPresentationContext getPresentationContext() { return fClientUpdate.getPresentationContext(); }
|
||||
/**
|
||||
* Request monitor which uses a model delta to calculate the element information.
|
||||
* This update is useful when calculating a model delta for a given view model node.
|
||||
*
|
||||
* @param delta Model delta of a parent element.
|
||||
* @param presentationContext Presentation context for this update.
|
||||
* @param requestMonitor Call-back invoked when this update completes.
|
||||
*/
|
||||
public VMViewerUpdate(IModelDelta delta, IPresentationContext presentationContext, RequestMonitor requestMonitor) {
|
||||
List<Object> elementList = new LinkedList<Object>();
|
||||
IModelDelta listDelta = delta;
|
||||
elementList.add(0, listDelta.getElement());
|
||||
while (listDelta.getParentDelta() != null) {
|
||||
listDelta = listDelta.getParentDelta();
|
||||
elementList.add(0, listDelta.getElement());
|
||||
}
|
||||
fViewerInput = elementList.get(0);
|
||||
fElement = elementList.get(elementList.size() - 1);
|
||||
elementList.remove(0);
|
||||
fElementPath = new TreePath(elementList.toArray());
|
||||
fPresentationContext = presentationContext;
|
||||
fRequestMonitor = requestMonitor;
|
||||
fClientUpdate = null;
|
||||
fCanceled = new AtomicBoolean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a viewer update with the given parameters.
|
||||
*
|
||||
* @param elementPath The path to the element for which the update is generated.
|
||||
* @param viewerInput Input into the viewer of the update.
|
||||
* @param presentationContext Presentation context for this update.
|
||||
* @param requestMonitor Call-back invoked when this update completes.
|
||||
*/
|
||||
public VMViewerUpdate(TreePath elementPath, Object viewerInput, IPresentationContext presentationContext, RequestMonitor requestMonitor) {
|
||||
fViewerInput = viewerInput;
|
||||
fElement = elementPath.getSegmentCount() != 0 ? elementPath.getLastSegment() : viewerInput;
|
||||
fElementPath = elementPath;
|
||||
fPresentationContext = presentationContext;
|
||||
fRequestMonitor = requestMonitor;
|
||||
fClientUpdate = null;
|
||||
fCanceled = new AtomicBoolean(false);
|
||||
}
|
||||
|
||||
protected RequestMonitor getRequestMonitor() {
|
||||
return fRequestMonitor;
|
||||
}
|
||||
|
||||
public Object getViewerInput() { return fViewerInput; }
|
||||
public Object getElement() { return fElement; }
|
||||
public TreePath getElementPath() { return fElementPath; }
|
||||
public IPresentationContext getPresentationContext() { return fPresentationContext; }
|
||||
public IStatus getStatus() { return fRequestMonitor.getStatus(); }
|
||||
public void setStatus(IStatus status) { fRequestMonitor.setStatus(status); }
|
||||
public boolean isCanceled() { return fClientUpdate.isCanceled(); }
|
||||
|
||||
public boolean isCanceled() {
|
||||
if (fClientUpdate != null) {
|
||||
return fClientUpdate.isCanceled();
|
||||
} else {
|
||||
return fCanceled.get();
|
||||
}
|
||||
}
|
||||
public void cancel() {
|
||||
fClientUpdate.cancel();
|
||||
if (fClientUpdate != null) {
|
||||
fClientUpdate.cancel();
|
||||
} else {
|
||||
fCanceled.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void done() {
|
||||
|
|
|
@ -1,481 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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.dd.dsf.ui.viewmodel.dm;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.DsfUIPlugin;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
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.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.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.jface.viewers.ITreeSelection;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
|
||||
/**
|
||||
* View model layout node based on a single Data Model Context type.
|
||||
* The assumption in this implementation is that elements of this node have
|
||||
* a single IDMContext associated with them, and all of these contexts
|
||||
* are of the same class type.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
abstract public class AbstractDMVMLayoutNode extends AbstractVMLayoutNode
|
||||
implements IElementLabelProvider
|
||||
{
|
||||
|
||||
/**
|
||||
* IVMContext implementation used for this schema node.
|
||||
*/
|
||||
@Immutable
|
||||
public class DMVMContext extends AbstractVMContext {
|
||||
private final IDMContext fDmc;
|
||||
|
||||
public DMVMContext(IDMContext dmc) {
|
||||
super(getVMProvider().getVMAdapter(), AbstractDMVMLayoutNode.this);
|
||||
fDmc = dmc;
|
||||
}
|
||||
|
||||
public IDMContext getDMC() { return fDmc; }
|
||||
|
||||
/**
|
||||
* The IAdaptable implementation. If the adapter is the DM context,
|
||||
* return the context, otherwise delegate to IDMContext.getAdapter().
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getAdapter(Class adapter) {
|
||||
Object superAdapter = super.getAdapter(adapter);
|
||||
if (superAdapter != null) {
|
||||
return superAdapter;
|
||||
} else if (adapter.isInstance(fDmc)) {
|
||||
return fDmc;
|
||||
} else {
|
||||
return fDmc.getAdapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof AbstractDMVMLayoutNode.DMVMContext)) return false;
|
||||
DMVMContext otherVmc = (DMVMContext)other;
|
||||
return AbstractDMVMLayoutNode.this.equals(otherVmc.getLayoutNode()) &&
|
||||
fDmc.equals(otherVmc.fDmc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return AbstractDMVMLayoutNode.this.hashCode() + fDmc.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fDmc.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private DsfSession fSession;
|
||||
|
||||
private DsfServicesTracker fServicesTracker;
|
||||
|
||||
/**
|
||||
* Concrete class type that the elements of this schema node are based on.
|
||||
* Even though the data model type is a parameter the DMContextVMLayoutNode,
|
||||
* this type is erased at runtime, so a concrete class typs of the DMC
|
||||
* is needed for instanceof chacks.
|
||||
*/
|
||||
private Class<? extends IDMContext> fDMCClassType;
|
||||
|
||||
/**
|
||||
* Constructor initializes instance data, except for the child nodes.
|
||||
* Child nodes must be initialized by calling setChildNodes()
|
||||
* @param session
|
||||
* @param dmcClassType
|
||||
* @see #setChildNodes(IVMLayoutNode[])
|
||||
*/
|
||||
public AbstractDMVMLayoutNode(AbstractVMProvider provider, DsfSession session, Class<? extends IDMContext> dmcClassType) {
|
||||
super(provider);
|
||||
fSession = session;
|
||||
fServicesTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
|
||||
fDMCClassType = dmcClassType;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
fServicesTracker.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
protected DsfSession getSession() {
|
||||
return fSession;
|
||||
}
|
||||
|
||||
protected DsfServicesTracker getServicesTracker() {
|
||||
return fServicesTracker;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkUpdate(IViewerUpdate update) {
|
||||
if (!super.checkUpdate(update)) return false;
|
||||
|
||||
// Extract the VMC from the update (whatever the update sub-class.
|
||||
Object element = update.getElement();
|
||||
if (element instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
// If update element is a DMC, check if session is still alive.
|
||||
IDMContext dmc = ((DMVMContext)element).getDMC();
|
||||
if (dmc.getSessionId() != getSession().getId() || !DsfSession.isSessionActive(dmc.getSessionId())) {
|
||||
handleFailedUpdate(update);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that checks whether the given dmc context is null. If it is null, an
|
||||
* appropriate error message is set in the update.
|
||||
* @param dmc Data Model Context (DMC) to check.
|
||||
* @param update Update to handle in case the DMC is null.
|
||||
* @return true if the DMC is NOT null, indicating that it's OK to proceed.
|
||||
*/
|
||||
protected boolean checkDmc(IDMContext dmc, IViewerUpdate update) {
|
||||
if (dmc == null) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE,
|
||||
"No valid context found.", null)); //$NON-NLS-1$
|
||||
handleFailedUpdate(update);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method that checks whether a given service exists. If the service does not
|
||||
* exist, the update is filled in with the appropriate error message.
|
||||
* @param serviceClass Service class to find.
|
||||
* @param filter Service filter to use in addition to the service class name.
|
||||
* @param update Update object to fill in.
|
||||
* @return true if service IS found, indicating that it's OK to proceed.
|
||||
*/
|
||||
protected boolean checkService(Class<? extends IDsfService> serviceClass, String filter, IViewerUpdate update) {
|
||||
if (getServicesTracker().getService(serviceClass, filter) == null) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE,
|
||||
"Service " + serviceClass.getName() + " not available.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
handleFailedUpdate(update);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateHasElements(final IHasChildrenUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updateHasElementsInSessionThread(updates);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (IHasChildrenUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateHasElementsInSessionThread(IHasChildrenUpdate[] updates) {
|
||||
for (final IHasChildrenUpdate update : updates) {
|
||||
if (!checkUpdate(update)) continue;
|
||||
|
||||
updateElementsInSessionThread(
|
||||
new ElementsUpdate(
|
||||
new DataRequestMonitor<List<Object>>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!checkUpdate(update)) return;
|
||||
if (getStatus().isOK()) {
|
||||
update.setHasChilren(getData().size() != 0);
|
||||
} else {
|
||||
update.setHasChilren(false);
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
},
|
||||
update.getElementPath())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateElementCount(final IChildrenCountUpdate update) {
|
||||
if (!checkUpdate(update)) return;
|
||||
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
// After every dispatch, must check if update still valid.
|
||||
if (!checkUpdate(update)) return;
|
||||
updateElementCountInSessionThread(update);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateElementCountInSessionThread(final IChildrenCountUpdate update) {
|
||||
updateElementsInSessionThread(
|
||||
new ElementsUpdate(
|
||||
new DataRequestMonitor<List<Object>>(getSession().getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (!checkUpdate(update)) return;
|
||||
if (getStatus().isOK()) {
|
||||
update.setChildCount(getData().size());
|
||||
} else {
|
||||
update.setChildCount(0);
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
},
|
||||
update.getElementPath())
|
||||
);
|
||||
}
|
||||
|
||||
public void updateElements(final IChildrenUpdate update) {
|
||||
if (!checkUpdate(update)) return;
|
||||
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
// After every dispatch, must check if update still valid.
|
||||
if (!checkUpdate(update)) return;
|
||||
updateElementsInSessionThread(update);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected void updateElementsInSessionThread(IChildrenUpdate update);
|
||||
|
||||
public void update(final ILabelUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
// After every dispatch, must check if update still valid.
|
||||
updateLabelInSessionThread(updates);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (ILabelUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected void updateLabelInSessionThread(ILabelUpdate[] updates);
|
||||
|
||||
@Override
|
||||
public int getDeltaFlags(Object e) {
|
||||
int flags = 0;
|
||||
if (e instanceof IDMEvent) {
|
||||
flags = getNodeDeltaFlagsForDMEvent((IDMEvent<?>)e);
|
||||
}
|
||||
return flags | super.getDeltaFlags(e);
|
||||
}
|
||||
|
||||
protected int getNodeDeltaFlagsForDMEvent(@SuppressWarnings("unused") IDMEvent<?> e) {
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildDelta(final Object e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
|
||||
if (e instanceof IDMEvent) {
|
||||
// Call handler for Data Model events. But check to make sure
|
||||
// that session is still active.
|
||||
if (DsfSession.isSessionActive(getSession().getId())) {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
buildDeltaForDMEvent((IDMEvent<?>)e, parentDelta, nodeOffset, requestMonitor);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (isDisposed()) return;
|
||||
requestMonitor.done();
|
||||
}
|
||||
} else {
|
||||
super.buildDelta(e, parentDelta, nodeOffset, requestMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle all Data Model events. If a DM context in the event contains
|
||||
* a context of the type tracked by this node, then this base implementation
|
||||
* will only create a delta node for this one element.
|
||||
*/
|
||||
protected void buildDeltaForDMEvent(final IDMEvent<?> event, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
|
||||
IDMContext dmc = DMContexts.getAncestorOfType(event.getDMContext(), fDMCClassType);
|
||||
|
||||
if (dmc != null) {
|
||||
// Create the VM context based on the DM context from the DM event.
|
||||
final IVMContext vmc = createVMContext(DMContexts.getAncestorOfType(event.getDMContext(), fDMCClassType));
|
||||
|
||||
final Map<IVMLayoutNode,Integer> childNodeDeltas = getChildNodesWithDeltaFlags(event);
|
||||
if (childNodeDeltas.size() == 0) {
|
||||
// There are no child nodes with deltas, just return to parent.
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if any of the child nodes are will generate IModelDelta.SELECT or
|
||||
// IModelDelta.EXPAND flags. If so, we must calcuate the index for this
|
||||
// VMC.
|
||||
boolean calculateIndex = false;
|
||||
for (int childDelta : childNodeDeltas.values()) {
|
||||
if ( (childDelta & (IModelDelta.SELECT | IModelDelta.EXPAND)) != 0 ) {
|
||||
calculateIndex = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (calculateIndex) {
|
||||
// Calculate the index of this node by retrieving all the
|
||||
// elements and then finding the DMC that the event is for.
|
||||
updateElements(new ElementsUpdate(
|
||||
new DataRequestMonitor<List<Object>>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
// Check for an empty list of elements. If it's empty then we
|
||||
// don't have to call the children nodes, so return here.
|
||||
// No need to propagate error, there's no means or need to display it.
|
||||
if (!getStatus().isOK() || getData().isEmpty()) {
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the index.
|
||||
int i;
|
||||
for (i = 0; i < getData().size(); i++) {
|
||||
if (vmc.equals(getData().get(i))) break;
|
||||
}
|
||||
if (i == getData().size()) {
|
||||
// Element not found, no need to generate the delta.
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
VMDelta delta = parentDelta.addNode(vmc, nodeOffset + i, IModelDelta.NO_CHANGE);
|
||||
callChildNodesToBuildDelta(childNodeDeltas, delta, event, requestMonitor);
|
||||
}
|
||||
},
|
||||
parentDelta));
|
||||
} else {
|
||||
VMDelta delta = parentDelta.addNode(vmc, IModelDelta.NO_CHANGE);
|
||||
callChildNodesToBuildDelta(childNodeDeltas, delta, event, requestMonitor);
|
||||
}
|
||||
} else {
|
||||
// The DMC for this node was not found in the event. Call the
|
||||
// super-class to resort to the default behavior which may add a
|
||||
// delta for every element in this node.
|
||||
super.buildDelta(event, parentDelta, nodeOffset, requestMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that takes an array of DMC object and creates a
|
||||
* corresponding array of IVMContext elements base on that.
|
||||
* @param parent The parent for generated IVMContext elements.
|
||||
* @param dmcs Array of DMC objects to build return array on.
|
||||
* @return Array of IVMContext objects.
|
||||
*/
|
||||
protected IVMContext[] dmcs2vmcs(IDMContext[] dmcs) {
|
||||
IVMContext[] vmContexts = new IVMContext[dmcs.length];
|
||||
for (int i = 0; i < dmcs.length; i++) {
|
||||
vmContexts[i] = new DMVMContext(dmcs[i]);
|
||||
}
|
||||
return vmContexts;
|
||||
}
|
||||
|
||||
protected void fillUpdateWithVMCs(IChildrenUpdate update, IDMContext[] dmcs) {
|
||||
int startIdx = update.getOffset() != -1 ? update.getOffset() : 0;
|
||||
int endIdx = update.getLength() != -1 ? startIdx + update.getLength() : dmcs.length;
|
||||
// Ted: added bounds limitation of dmcs.length
|
||||
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=202109
|
||||
for (int i = startIdx; i < endIdx && i < dmcs.length; i++) {
|
||||
update.setChild(createVMContext(dmcs[i]), i);
|
||||
}
|
||||
}
|
||||
|
||||
protected IVMContext createVMContext(IDMContext dmc) {
|
||||
return new DMVMContext(dmc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a DMC of given type in the tree patch contained in given
|
||||
* VMC. Only a DMC in the same session will be returned.
|
||||
* @param <V> Type of the DMC that will be returned.
|
||||
* @param vmc VMC element to search.
|
||||
* @param dmcType Class object for matching the type.
|
||||
* @return DMC, or null if not found.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends IDMContext> T findDmcInPath(TreePath path, Class<T> dmcType) {
|
||||
T retVal = null;
|
||||
for (int i = path.getSegmentCount() - 1; i >= 0; i--) {
|
||||
if (path.getSegment(i) instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
IDMContext dmc = ((DMVMContext)path.getSegment(i)).getDMC();
|
||||
if ( dmc.getSessionId().equals(getSession().getId()) ) {
|
||||
retVal = DMContexts.getAncestorOfType(dmc, dmcType);
|
||||
if (retVal != null) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Search the root object of the layout hierarchy.
|
||||
if (retVal == null) {
|
||||
Object inputObject = getVMProvider().getRootElement();
|
||||
if (inputObject instanceof ITreeSelection) {
|
||||
ITreeSelection inputSelection = (ITreeSelection)inputObject;
|
||||
if (inputSelection.getPaths().length == 1) {
|
||||
retVal = findDmcInPath(inputSelection.getPaths()[0], dmcType);
|
||||
}
|
||||
} else if (inputObject instanceof IStructuredSelection) {
|
||||
Object rootElement = ((IStructuredSelection)inputObject).getFirstElement();
|
||||
if (rootElement instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
retVal = DMContexts.getAncestorOfType(((DMVMContext)rootElement).getDMC(), dmcType);
|
||||
}
|
||||
} else if (inputObject instanceof AbstractDMVMLayoutNode.DMVMContext) {
|
||||
retVal = DMContexts.getAncestorOfType(((DMVMContext)inputObject).getDMC(), dmcType);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,334 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 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.dd.dsf.ui.viewmodel.dm;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.service.IDsfService;
|
||||
import org.eclipse.dd.dsf.ui.DsfUIPlugin;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
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.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.jface.viewers.ITreeSelection;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
|
||||
/**
|
||||
* View model node based on a single Data Model Context type.
|
||||
* The assumption in this implementation is that elements of this node have
|
||||
* a single IDMContext associated with them, and all of these contexts
|
||||
* are of the same class type.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
abstract public class AbstractDMVMNode extends AbstractVMNode implements IVMNode {
|
||||
|
||||
/**
|
||||
* IVMContext implementation used for this schema node.
|
||||
*/
|
||||
@Immutable
|
||||
protected class DMVMContext extends AbstractVMContext implements IDMVMContext {
|
||||
private final IDMContext fDmc;
|
||||
|
||||
public DMVMContext(IDMContext dmc) {
|
||||
super(getVMProvider().getVMAdapter(), AbstractDMVMNode.this);
|
||||
fDmc = dmc;
|
||||
}
|
||||
|
||||
public IDMContext getDMContext() { return fDmc; }
|
||||
|
||||
/**
|
||||
* The IAdaptable implementation. If the adapter is the DM context,
|
||||
* return the context, otherwise delegate to IDMContext.getAdapter().
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getAdapter(Class adapter) {
|
||||
Object superAdapter = super.getAdapter(adapter);
|
||||
if (superAdapter != null) {
|
||||
return superAdapter;
|
||||
} else if (adapter.isInstance(fDmc)) {
|
||||
return fDmc;
|
||||
} else {
|
||||
return fDmc.getAdapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof AbstractDMVMNode.DMVMContext)) return false;
|
||||
DMVMContext otherVmc = (DMVMContext)other;
|
||||
return AbstractDMVMNode.this.equals(otherVmc.getVMNode()) &&
|
||||
fDmc.equals(otherVmc.fDmc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return AbstractDMVMNode.this.hashCode() + fDmc.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fDmc.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private DsfSession fSession;
|
||||
|
||||
private DsfServicesTracker fServicesTracker;
|
||||
|
||||
/**
|
||||
* Concrete class type that the elements of this schema node are based on.
|
||||
* Even though the data model type is a parameter the DMContextVMLayoutNode,
|
||||
* this type is erased at runtime, so a concrete class typs of the DMC
|
||||
* is needed for instanceof chacks.
|
||||
*/
|
||||
private Class<? extends IDMContext> fDMCClassType;
|
||||
|
||||
/**
|
||||
* Constructor initializes instance data, except for the child nodes.
|
||||
* Child nodes must be initialized by calling setChildNodes()
|
||||
* @param session
|
||||
* @param dmcClassType
|
||||
* @see #setChildNodes(IVMNode[])
|
||||
*/
|
||||
public AbstractDMVMNode(AbstractDMVMProvider provider, DsfSession session, Class<? extends IDMContext> dmcClassType) {
|
||||
super(provider);
|
||||
fSession = session;
|
||||
fServicesTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
|
||||
fDMCClassType = dmcClassType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
fServicesTracker.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IVMContext getContextFromEvent(Object event) {
|
||||
if (event instanceof IDMEvent<?>) {
|
||||
IDMEvent<?> dmEvent = (IDMEvent<?>)event;
|
||||
IDMContext dmc = DMContexts.getAncestorOfType(dmEvent.getDMContext(), fDMCClassType);
|
||||
if (dmc != null) {
|
||||
return createVMContext(dmc);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected AbstractDMVMProvider getDMVMProvider() {
|
||||
return (AbstractDMVMProvider)getVMProvider();
|
||||
}
|
||||
|
||||
protected DsfSession getSession() {
|
||||
return fSession;
|
||||
}
|
||||
|
||||
protected DsfServicesTracker getServicesTracker() {
|
||||
return fServicesTracker;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkUpdate(IViewerUpdate update) {
|
||||
if (!super.checkUpdate(update)) return false;
|
||||
|
||||
// Extract the VMC from the update (whatever the update sub-class.
|
||||
Object element = update.getElement();
|
||||
if (element instanceof IDMVMContext) {
|
||||
// If update element is a DMC, check if session is still alive.
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
if (dmc.getSessionId() != getSession().getId() || !DsfSession.isSessionActive(dmc.getSessionId())) {
|
||||
handleFailedUpdate(update);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that checks whether the given dmc context is null. If it is null, an
|
||||
* appropriate error message is set in the update.
|
||||
* @param dmc Data Model Context (DMC) to check.
|
||||
* @param update Update to handle in case the DMC is null.
|
||||
* @return true if the DMC is NOT null, indicating that it's OK to proceed.
|
||||
*/
|
||||
protected boolean checkDmc(IDMContext dmc, IViewerUpdate update) {
|
||||
if (dmc == null) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE,
|
||||
"No valid context found.", null)); //$NON-NLS-1$
|
||||
handleFailedUpdate(update);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method that checks whether a given service exists. If the service does not
|
||||
* exist, the update is filled in with the appropriate error message.
|
||||
* @param serviceClass Service class to find.
|
||||
* @param filter Service filter to use in addition to the service class name.
|
||||
* @param update Update object to fill in.
|
||||
* @return true if service IS found, indicating that it's OK to proceed.
|
||||
*/
|
||||
protected boolean checkService(Class<? extends IDsfService> serviceClass, String filter, IViewerUpdate update) {
|
||||
if (getServicesTracker().getService(serviceClass, filter) == null) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE,
|
||||
"Service " + serviceClass.getName() + " not available.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
handleFailedUpdate(update);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void update(final IHasChildrenUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
for (IHasChildrenUpdate update : updates) {
|
||||
if (!checkUpdate(update)) continue;
|
||||
updateHasElementsInSessionThread(update);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (IViewerUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateHasElementsInSessionThread(final IHasChildrenUpdate update) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.NOT_SUPPORTED, "Not implemented, clients should call to update all children instead.", null)); //$NON-NLS-1$
|
||||
update.done();
|
||||
}
|
||||
|
||||
public void update(final IChildrenCountUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
for (IChildrenCountUpdate update : updates) {
|
||||
if (!checkUpdate(update)) continue;
|
||||
updateElementCountInSessionThread(update);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (IViewerUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateElementCountInSessionThread(final IChildrenCountUpdate update) {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.NOT_SUPPORTED, "Not implemented, clients should call to update all children instead.", null)); //$NON-NLS-1$
|
||||
update.done();
|
||||
}
|
||||
|
||||
public void update(final IChildrenUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
// After every dispatch, must check if update still valid.
|
||||
for (IChildrenUpdate update : updates) {
|
||||
if (!checkUpdate(update)) continue;
|
||||
updateElementsInSessionThread(update);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (IViewerUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected void updateElementsInSessionThread(IChildrenUpdate update);
|
||||
|
||||
/**
|
||||
* Utility method that takes an array of DMC object and creates a
|
||||
* corresponding array of IVMContext elements base on that.
|
||||
* @param parent The parent for generated IVMContext elements.
|
||||
* @param dmcs Array of DMC objects to build return array on.
|
||||
* @return Array of IVMContext objects.
|
||||
*/
|
||||
protected IVMContext[] dmcs2vmcs(IDMContext[] dmcs) {
|
||||
IVMContext[] vmContexts = new IVMContext[dmcs.length];
|
||||
for (int i = 0; i < dmcs.length; i++) {
|
||||
vmContexts[i] = createVMContext(dmcs[i]);
|
||||
}
|
||||
return vmContexts;
|
||||
}
|
||||
|
||||
protected void fillUpdateWithVMCs(IChildrenUpdate update, IDMContext[] dmcs) {
|
||||
int startIdx = update.getOffset() != -1 ? update.getOffset() : 0;
|
||||
int endIdx = update.getLength() != -1 ? startIdx + update.getLength() : dmcs.length;
|
||||
// Ted: added bounds limitation of dmcs.length
|
||||
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=202109
|
||||
for (int i = startIdx; i < endIdx && i < dmcs.length; i++) {
|
||||
update.setChild(createVMContext(dmcs[i]), i);
|
||||
}
|
||||
}
|
||||
|
||||
protected IDMVMContext createVMContext(IDMContext dmc) {
|
||||
return new DMVMContext(dmc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a DMC of given type in the tree patch contained in given
|
||||
* VMC. Only a DMC in the same session will be returned.
|
||||
* @param <V> Type of the DMC that will be returned.
|
||||
* @param vmc VMC element to search.
|
||||
* @param dmcType Class object for matching the type.
|
||||
* @return DMC, or null if not found.
|
||||
*/
|
||||
public <T extends IDMContext> T findDmcInPath(Object inputObject, TreePath path, Class<T> dmcType) {
|
||||
T retVal = null;
|
||||
for (int i = path.getSegmentCount() - 1; i >= 0; i--) {
|
||||
if (path.getSegment(i) instanceof IDMVMContext) {
|
||||
IDMContext dmc = ((IDMVMContext)path.getSegment(i)).getDMContext();
|
||||
if ( dmc.getSessionId().equals(getSession().getId()) ) {
|
||||
retVal = DMContexts.getAncestorOfType(dmc, dmcType);
|
||||
if (retVal != null) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Search the root object of the layout hierarchy.
|
||||
if (retVal == null) {
|
||||
if (inputObject instanceof ITreeSelection) {
|
||||
ITreeSelection inputSelection = (ITreeSelection)inputObject;
|
||||
if (inputSelection.getPaths().length == 1) {
|
||||
retVal = findDmcInPath(null, inputSelection.getPaths()[0], dmcType);
|
||||
}
|
||||
} else if (inputObject instanceof IStructuredSelection) {
|
||||
Object rootElement = ((IStructuredSelection)inputObject).getFirstElement();
|
||||
if (rootElement instanceof IDMVMContext) {
|
||||
retVal = DMContexts.getAncestorOfType(((IDMVMContext)rootElement).getDMContext(), dmcType);
|
||||
}
|
||||
} else if (inputObject instanceof IDMVMContext) {
|
||||
retVal = DMContexts.getAncestorOfType(((IDMVMContext)inputObject).getDMContext(), dmcType);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
|
@ -17,8 +17,8 @@ import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
|||
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.AbstractCachingVMProvider;
|
||||
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.provisional.IAsynchronousContentAdapter;
|
||||
|
@ -27,7 +27,7 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapt
|
|||
/**
|
||||
* View model provider implements the asynchronous view model functionality for
|
||||
* a single view. This provider is just a holder which further delegates the
|
||||
* model provider functionality to the view model layout nodes that need
|
||||
* model provider functionality to the view model nodes that need
|
||||
* to be configured with each provider.
|
||||
* <p>
|
||||
* The view model provider, often does not provide the model for the entire
|
||||
|
@ -37,11 +37,11 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapt
|
|||
* @see IAsynchronousContentAdapter
|
||||
* @see IAsynchronousLabelAdapter
|
||||
* @see IModelProxy
|
||||
* @see IVMLayoutNode
|
||||
* @see IVMNode
|
||||
*/
|
||||
@ConfinedToDsfExecutor("fSession#getExecutor")
|
||||
@SuppressWarnings("restriction")
|
||||
abstract public class AbstractDMVMProvider extends AbstractVMProvider
|
||||
abstract public class AbstractDMVMProvider extends AbstractCachingVMProvider
|
||||
{
|
||||
private final DsfSession fSession;
|
||||
|
||||
|
@ -93,9 +93,7 @@ abstract public class AbstractDMVMProvider extends AbstractVMProvider
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
protected DsfSession getSession() { return fSession; }
|
||||
|
||||
|
||||
public DsfSession getSession() { return fSession; }
|
||||
|
||||
/**
|
||||
* Handle "data model changed" event by generating a delta object for each
|
||||
|
@ -106,8 +104,21 @@ abstract public class AbstractDMVMProvider extends AbstractVMProvider
|
|||
*/
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(final IDMEvent<?> event) {
|
||||
// We're in session's executor thread (session in which the event originated).
|
||||
// Re-dispach to the view model provider executor thread and then call the
|
||||
// model proxy strategy to handle the event.
|
||||
if (isDisposed()) return;
|
||||
|
||||
handleEvent(event);
|
||||
try {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed()) return;
|
||||
handleEvent(event);
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Ignore. This exception could be thrown if the provider is being
|
||||
// shut down.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.ui.viewmodel.dm;
|
||||
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
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.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public abstract class AbstractDMVMProviderWithCache extends AbstractDMVMProvider
|
||||
implements VMCacheManager.CacheListener
|
||||
{
|
||||
@DsfServiceEventHandler
|
||||
@Override
|
||||
public void eventDispatched(IDMEvent<?> event) {
|
||||
VMCacheManager.getVMCacheManager().getCache(getPresentationContext()).handleEvent(event);
|
||||
super.eventDispatched(event);
|
||||
}
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public void cacheFlushed(Object context) {
|
||||
if(getPresentationContext().equals(context))
|
||||
getModelProxy().fireModelChanged(new ModelDelta(getRootElement(),IModelDelta.CONTENT));
|
||||
}
|
||||
|
||||
public AbstractDMVMProviderWithCache(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session) {
|
||||
super(adapter, presentationContext, session);
|
||||
|
||||
VMCacheManager.getVMCacheManager().addCacheListener(getPresentationContext(), this);
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
VMCacheManager.getVMCacheManager().flush(getPresentationContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(IHasChildrenUpdate[] updates) {
|
||||
super.update(VMCacheManager.getVMCacheManager().getCache(getPresentationContext()).update(updates));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(IChildrenCountUpdate[] updates) {
|
||||
super.update(VMCacheManager.getVMCacheManager().getCache(getPresentationContext()).update(updates));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final IChildrenUpdate[] updates) {
|
||||
super.update(VMCacheManager.getVMCacheManager().getCache(getPresentationContext()).update(updates));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
VMCacheManager.getVMCacheManager().removeCacheListener(getPresentationContext(), this);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
|
@ -13,9 +13,9 @@ package org.eclipse.dd.dsf.ui.viewmodel.dm;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.CompositeDMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode.DMVMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
|
@ -23,6 +23,7 @@ import org.eclipse.jface.viewers.TreePath;
|
|||
* update. This object allows the view model to pass complete data model context
|
||||
* information found in the view to the services.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class CompositeDMVMContext extends CompositeDMContext {
|
||||
|
||||
/**
|
||||
|
@ -38,18 +39,25 @@ public class CompositeDMVMContext extends CompositeDMContext {
|
|||
private IDMContext[] fParents;
|
||||
|
||||
/**
|
||||
* Creates a composite context based on view model
|
||||
* Creates a composite context based in a viewer update.
|
||||
*/
|
||||
public CompositeDMVMContext(IViewerUpdate update) {
|
||||
this(update.getViewerInput(), update.getElementPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a composite context based on a viewer input and a tree path.
|
||||
*/
|
||||
public CompositeDMVMContext(Object viewerInputObject, TreePath treePath) {
|
||||
super(EMPTY_CONTEXTS_ARRAY);
|
||||
List<IDMContext> parentsList = new ArrayList<IDMContext>(treePath.getSegmentCount() + 1);
|
||||
for (int i = treePath.getSegmentCount() - 1; i >=0 ; i--) {
|
||||
if (treePath.getSegment(i) instanceof DMVMContext) {
|
||||
parentsList.add( ((DMVMContext)treePath.getSegment(i)).getDMC() );
|
||||
if (treePath.getSegment(i) instanceof IDMVMContext) {
|
||||
parentsList.add( ((IDMVMContext)treePath.getSegment(i)).getDMContext() );
|
||||
}
|
||||
}
|
||||
if (viewerInputObject instanceof DMVMContext) {
|
||||
parentsList.add( ((DMVMContext)viewerInputObject).getDMC() );
|
||||
if (viewerInputObject instanceof IDMVMContext) {
|
||||
parentsList.add( ((IDMVMContext)viewerInputObject).getDMContext() );
|
||||
}
|
||||
|
||||
fParents = parentsList.toArray(new IDMContext[parentsList.size()]);
|
||||
|
|
|
@ -8,12 +8,20 @@
|
|||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.ui.viewmodel.expression;
|
||||
package org.eclipse.dd.dsf.ui.viewmodel.dm;
|
||||
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* Interface for a view model context based on a DSF data model context.
|
||||
*/
|
||||
public interface IExpressionVMContext extends IVMContext {
|
||||
public interface IDMVMContext extends IVMContext {
|
||||
|
||||
public static Object REFRESH_EVENT = new Object();
|
||||
|
||||
/**
|
||||
* returns the data model context that this view model context wraps.
|
||||
*/
|
||||
public IDMContext getDMContext();
|
||||
}
|
|
@ -14,10 +14,8 @@ import org.eclipse.dd.dsf.datamodel.DMContexts;
|
|||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode.DMVMContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.RootVMNode;
|
||||
|
||||
/**
|
||||
* This is is a standard root node which listens to the selection in Debug View.
|
||||
|
@ -30,11 +28,10 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
|||
* node also has to use the first element as the root object instead of the
|
||||
* whole selection.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class DMVMRootLayoutNode extends VMRootLayoutNode
|
||||
implements IVMRootLayoutNode
|
||||
public class RootDMVMNode extends RootVMNode
|
||||
implements IRootVMNode
|
||||
{
|
||||
public DMVMRootLayoutNode(AbstractVMProvider provider) {
|
||||
public RootDMVMNode(AbstractVMProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
|
@ -60,39 +57,30 @@ public class DMVMRootLayoutNode extends VMRootLayoutNode
|
|||
* determine whether a delta is needed.
|
||||
*/
|
||||
@Override
|
||||
public int getDeltaFlags(Object event) {
|
||||
IDMContext inputDmc = getSelectedDMC();
|
||||
if (event instanceof IDMEvent && inputDmc != null) {
|
||||
boolean potentialMatchFound = false;
|
||||
boolean matchFound = false;
|
||||
public boolean isDeltaEvent(Object rootObject, Object event) {
|
||||
if (rootObject instanceof IDMVMContext) {
|
||||
IDMContext inputDmc = ((IDMVMContext)rootObject).getDMContext();
|
||||
if (event instanceof IDMEvent && inputDmc != null) {
|
||||
boolean potentialMatchFound = false;
|
||||
boolean matchFound = false;
|
||||
|
||||
IDMContext eventDmc = ((IDMEvent<?>)event).getDMContext();
|
||||
for (IDMContext eventDmcAncestor : DMContexts.toList(eventDmc)) {
|
||||
IDMContext inputDmcAncestor = DMContexts.getAncestorOfType(inputDmc, eventDmcAncestor.getClass());
|
||||
if (inputDmcAncestor != null) {
|
||||
potentialMatchFound = true;
|
||||
if (inputDmcAncestor.equals(eventDmcAncestor)) {
|
||||
return super.getDeltaFlags(event);
|
||||
IDMContext eventDmc = ((IDMEvent<?>)event).getDMContext();
|
||||
for (IDMContext eventDmcAncestor : DMContexts.toList(eventDmc)) {
|
||||
IDMContext inputDmcAncestor = DMContexts.getAncestorOfType(inputDmc, eventDmcAncestor.getClass());
|
||||
if (inputDmcAncestor != null) {
|
||||
potentialMatchFound = true;
|
||||
if (inputDmcAncestor.equals(eventDmcAncestor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (potentialMatchFound && !matchFound) {
|
||||
return IModelDelta.NO_CHANGE;
|
||||
if (potentialMatchFound && !matchFound) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.getDeltaFlags(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
private IDMContext getSelectedDMC() {
|
||||
Object rootObject = getVMProvider().getRootElement();
|
||||
if (rootObject instanceof DMVMContext)
|
||||
{
|
||||
// Correct cast: (AbstractDMVMLayoutNode<?>.DMVMContext) breaks the javac compiler
|
||||
@SuppressWarnings("unchecked")
|
||||
DMVMContext vmc = (DMVMContext)rootObject;
|
||||
return vmc.getDMC();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
|||
/**
|
||||
* Context sensitive properties update request for an element.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public interface IPropertiesUpdate extends IViewerUpdate {
|
||||
/**
|
||||
* Returns the list of element properties that the provider should set.
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
|||
@SuppressWarnings("restriction")
|
||||
public class LabelText extends LabelAttribute {
|
||||
|
||||
public static final MessageFormat DEFAULT_MESSAGE = new MessageFormat("<unknown>");
|
||||
public static final MessageFormat DEFAULT_MESSAGE = new MessageFormat(MessagesForProperties.DefaultLabelMessage_label);
|
||||
|
||||
/**
|
||||
* Message format used to generate the label text.
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package org.eclipse.dd.dsf.ui.viewmodel.properties;
|
||||
|
||||
import org.eclipse.osgi.util.NLS;
|
||||
|
||||
class MessagesForProperties extends NLS {
|
||||
private static final String BUNDLE_NAME = "org.eclipse.dd.dsf.ui.viewmodel.properties.messages"; //$NON-NLS-1$
|
||||
|
||||
public static String DefaultLabelMessage_label;
|
||||
|
||||
static {
|
||||
// initialize resource bundle
|
||||
NLS.initializeMessages(BUNDLE_NAME, MessagesForProperties.class);
|
||||
}
|
||||
|
||||
private MessagesForProperties() {
|
||||
}
|
||||
}
|
|
@ -77,7 +77,7 @@ public class PropertyBasedLabelProvider
|
|||
@Override
|
||||
public void done() {
|
||||
@SuppressWarnings("unchecked")
|
||||
DataRequestMonitor<Map<String,Object>> rm = (DataRequestMonitor<Map<String,Object>>)fRequestMonitor;
|
||||
DataRequestMonitor<Map<String,Object>> rm = (DataRequestMonitor<Map<String,Object>>)getRequestMonitor();
|
||||
if (fProperties == null || fValues.size() >= fProperties.length) {
|
||||
rm.setData(fValues);
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
DefaultLabelMessage_label=<unknown>
|
|
@ -0,0 +1,761 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.ui.viewmodel.update;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMData;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMService;
|
||||
import org.eclipse.dd.dsf.ui.concurrent.ViewerCountingRequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMModelProxy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMChildrenCountUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMChildrenUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMHasChildrenUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
|
||||
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.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.ModelDelta;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* Base implementation of a caching view model provider.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class AbstractCachingVMProvider extends AbstractVMProvider implements ICachingVMProvider {
|
||||
|
||||
private static final int MAX_CACHE_SIZE = 1000;
|
||||
|
||||
/**
|
||||
* Class representing a key to an element's data in the cache. The main
|
||||
* components of this key are the viewer input and the path, they uniquely
|
||||
* identify an element. The root element is used to track when a given
|
||||
* root element is no longer in the cache and can therefore be disposed.
|
||||
* The node is needed because different nodes have different lists of
|
||||
* children for the same parent element.
|
||||
*/
|
||||
private static class ElementDataKey {
|
||||
ElementDataKey(Object rootElement, IVMNode node, Object viewerInput, TreePath path) {
|
||||
fRootElement = rootElement;
|
||||
fNode = node;
|
||||
fViewerInput = viewerInput;
|
||||
fPath = path;
|
||||
}
|
||||
|
||||
final Object fRootElement;
|
||||
final IVMNode fNode;
|
||||
final Object fViewerInput;
|
||||
final TreePath fPath;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fViewerInput + "." + fPath.toString() + "(" + fNode + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof ElementDataKey)) return false;
|
||||
ElementDataKey key = (ElementDataKey)obj;
|
||||
return
|
||||
(fNode == null && key.fNode == null || (fNode != null && fNode.equals(key.fNode))) &&
|
||||
(fRootElement == null && key.fRootElement == null || (fRootElement != null && fRootElement.equals(key.fRootElement))) &&
|
||||
(fViewerInput == null && key.fViewerInput == null || (fViewerInput != null && fViewerInput.equals(key.fViewerInput))) &&
|
||||
(fPath == null && key.fPath == null || (fPath != null && fPath.equals(key.fPath)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return
|
||||
(fRootElement != null ? fRootElement.hashCode() : 0) +
|
||||
(fNode != null ? fNode.hashCode() : 0) +
|
||||
(fViewerInput != null ? fViewerInput.hashCode() : 0) +
|
||||
(fPath != null ? fPath.hashCode() : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A base calss for the entry in the cache. Since the cache maintains
|
||||
* a double-linked list through all the entries, the linked list references
|
||||
* are maintained in this class.
|
||||
*/
|
||||
private static class Entry {
|
||||
final Object fKey;
|
||||
|
||||
Entry fNext;
|
||||
Entry fPrevious;
|
||||
|
||||
Entry(Object key) {
|
||||
fKey = key;
|
||||
}
|
||||
|
||||
void insert(Entry nextEntry) {
|
||||
fNext = nextEntry;
|
||||
fPrevious = nextEntry.fPrevious;
|
||||
fPrevious.fNext = this;
|
||||
fNext.fPrevious = this;
|
||||
}
|
||||
|
||||
void remove() {
|
||||
fPrevious.fNext = fNext;
|
||||
fNext.fPrevious = fPrevious;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry with cached element data.
|
||||
*/
|
||||
static class ElementDataEntry extends Entry {
|
||||
ElementDataEntry(ElementDataKey key) {
|
||||
super(key);
|
||||
}
|
||||
|
||||
Boolean fDirty = false;
|
||||
Boolean fHasChildren = null;
|
||||
Integer fChildrenCount = null;
|
||||
boolean fAllChildrenKnown = false;
|
||||
Map<Integer,Object> fChildren = null;
|
||||
Map<IDMContext,Object> fDataOrStatus = new HashMap<IDMContext,Object>(1);
|
||||
Map<IDMContext,IDMData> fArchiveData = new HashMap<IDMContext,IDMData>(1);;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fKey.toString() + " = " + //$NON-NLS-1$
|
||||
"[hasChildren=" + fHasChildren + ", " +//$NON-NLS-1$ //$NON-NLS-2$
|
||||
"childrenCount=" + fChildrenCount + //$NON-NLS-1$
|
||||
", children=" + fChildren + //$NON-NLS-1$
|
||||
", data/status=" + fDataOrStatus + //$NON-NLS-1$
|
||||
", oldData=" + fArchiveData + "]"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A key for a special marker entry in the cache. This marker entry is used
|
||||
* to optimize repeated flushing of the cache.
|
||||
* @see AbstractCachingVMProvider#flush(List)
|
||||
*/
|
||||
private static class FlushMarkerKey {
|
||||
private Object fRootElement;
|
||||
private IElementUpdateTester fElementTester;
|
||||
|
||||
FlushMarkerKey(Object rootElement, IElementUpdateTester pathTester) {
|
||||
fRootElement = rootElement;
|
||||
fElementTester = pathTester;
|
||||
}
|
||||
|
||||
boolean includes(FlushMarkerKey key) {
|
||||
return fRootElement.equals(key.fRootElement) &&
|
||||
fElementTester.includes(key.fElementTester);
|
||||
}
|
||||
|
||||
int getUpdateFlags(ElementDataKey key) {
|
||||
if (fRootElement.equals(key.fRootElement)) {
|
||||
return fElementTester.getUpdateFlags(key.fViewerInput, key.fPath);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marker used to keep track of whether any entries with the given
|
||||
* root element are present in the cache.
|
||||
*/
|
||||
private static class RootElementMarkerKey {
|
||||
|
||||
private Object fRootElement;
|
||||
|
||||
RootElementMarkerKey(Object rootElement) {
|
||||
fRootElement = rootElement;
|
||||
}
|
||||
}
|
||||
|
||||
class RootElementMarkerEntry extends Entry {
|
||||
RootElementMarkerEntry(RootElementMarkerKey key) {
|
||||
super(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
void remove() {
|
||||
super.remove();
|
||||
rootElementRemovedFromCache(((RootElementMarkerKey)fKey).fRootElement);
|
||||
}
|
||||
}
|
||||
|
||||
protected static String SELECTED_UPDATE_MODE = "org.eclipse.dd.dsf.ui.viewmodel.update.selectedUpdateMode"; //$NON-NLS-1$
|
||||
|
||||
private IVMUpdatePolicy fCurrentUpdatePolicy;
|
||||
|
||||
private IVMUpdatePolicy[] fAvailableUpdatePolicies;
|
||||
|
||||
public Map<Object, RootElementMarkerKey> fRootMarkers = new HashMap<Object, RootElementMarkerKey>();
|
||||
|
||||
/**
|
||||
* Hash map holding cache data. To store the cache information, the cache uses a
|
||||
* combination of this hash map and a double-linked list running through all
|
||||
* the entries in the cache. The linked list is used to organize the cache entries
|
||||
* in least recently used (LRU) order. This ordering is then used to delete least
|
||||
* recently used entries in the cache and keep the cache from growing indefinitely.
|
||||
* Also, the ordering is used to optimize the flushing of the cache data (see
|
||||
* {@link FlushMarkerKey} for more details).
|
||||
*/
|
||||
private final Map<Object, Entry> fCacheData = new HashMap<Object, Entry>(200, 0.75f);
|
||||
|
||||
/**
|
||||
* Pointer to the first cache entry in the double-linked list of cache entries.
|
||||
*/
|
||||
private final Entry fCacheListHead;
|
||||
|
||||
|
||||
public AbstractCachingVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext) {
|
||||
super(adapter, presentationContext);
|
||||
|
||||
fCacheListHead = new Entry(null);
|
||||
fCacheListHead.fNext = fCacheListHead;
|
||||
fCacheListHead.fPrevious = fCacheListHead;
|
||||
|
||||
String updateModeId = (String)presentationContext.getProperty(SELECTED_UPDATE_MODE);
|
||||
if (updateModeId != null) {
|
||||
for (IVMUpdatePolicy updateMode : getAvailableUpdatePolicies()) {
|
||||
if (updateMode.getID().equals(updateModeId)) {
|
||||
fCurrentUpdatePolicy = updateMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fAvailableUpdatePolicies = createUpdateModes();
|
||||
fCurrentUpdatePolicy = fAvailableUpdatePolicies[0];
|
||||
}
|
||||
|
||||
protected IVMUpdatePolicy[] createUpdateModes() {
|
||||
return new IVMUpdatePolicy[] { new AutomaticUpdatePolicy() };
|
||||
}
|
||||
|
||||
public IVMUpdatePolicy[] getAvailableUpdatePolicies() {
|
||||
return fAvailableUpdatePolicies;
|
||||
}
|
||||
|
||||
public IVMUpdatePolicy getActiveUpdatePolicy() {
|
||||
return fCurrentUpdatePolicy;
|
||||
}
|
||||
|
||||
public void setActiveUpdatePolicy(IVMUpdatePolicy updatePolicy) {
|
||||
fCurrentUpdatePolicy = updatePolicy;
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
IElementUpdateTester elementTester = getActiveUpdatePolicy().getTesterTester(ManualUpdatePolicy.REFRESH_EVENT);
|
||||
|
||||
List<FlushMarkerKey> flushKeys = new LinkedList<FlushMarkerKey>();
|
||||
|
||||
for (final IVMModelProxy proxyStrategy : getActiveModelProxies()) {
|
||||
flushKeys.add(new FlushMarkerKey(proxyStrategy.getRootElement(), elementTester));
|
||||
}
|
||||
|
||||
flush(flushKeys);
|
||||
|
||||
for (final IVMModelProxy proxyStrategy : getActiveModelProxies()) {
|
||||
if (!proxyStrategy.isDisposed()) {
|
||||
proxyStrategy.fireModelChanged(new ModelDelta(proxyStrategy.getRootElement(), IModelDelta.CONTENT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateNode(IVMNode node, IHasChildrenUpdate[] updates) {
|
||||
LinkedList <IHasChildrenUpdate> missUpdates = new LinkedList<IHasChildrenUpdate>();
|
||||
for(final IHasChildrenUpdate update : updates) {
|
||||
ElementDataKey key = makeEntryKey(node, update);
|
||||
final ElementDataEntry entry = getElementDataEntry(key);
|
||||
if (entry.fHasChildren != null) {
|
||||
update.setHasChilren(entry.fHasChildren.booleanValue());
|
||||
update.done();
|
||||
} else {
|
||||
missUpdates.add(
|
||||
new VMHasChildrenUpdate(update, new DataRequestMonitor<Boolean>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if(getStatus().isOK()) {
|
||||
entry.fHasChildren = this.getData();
|
||||
update.setHasChilren(getData());
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (!missUpdates.isEmpty()) {
|
||||
super.updateNode(node, missUpdates.toArray(new IHasChildrenUpdate[missUpdates.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateNode(IVMNode node, IChildrenCountUpdate[] updates) {
|
||||
// Given our knowledge of DefaultVMContentProviderStragety, make an
|
||||
// assumption about the updates argument: there should always be
|
||||
// exactly one update in this array.
|
||||
assert updates.length == 1;
|
||||
final IChildrenCountUpdate update = updates[0];
|
||||
|
||||
ElementDataKey key = makeEntryKey(node, update);
|
||||
final ElementDataEntry entry = getElementDataEntry(key);
|
||||
if(entry.fChildrenCount != null) {
|
||||
update.setChildCount(entry.fChildrenCount.intValue());
|
||||
update.done();
|
||||
} else {
|
||||
updates[0] = new VMChildrenCountUpdate(update, new DataRequestMonitor<Integer>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if(getStatus().isOK()) {
|
||||
entry.fChildrenCount = this.getData();
|
||||
update.setChildCount(getData());
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
});
|
||||
super.updateNode(node, updates);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateNode(IVMNode node, IChildrenUpdate[] updates) {
|
||||
// Given our knowledge of DefaultVMContentProviderStragety, make an
|
||||
// assumption about the updates argument: there should always be
|
||||
// exactly one update in this array.
|
||||
assert updates.length == 1;
|
||||
final IChildrenUpdate update = updates[0];
|
||||
|
||||
ElementDataKey key = makeEntryKey(node, update);
|
||||
|
||||
final ElementDataEntry entry = getElementDataEntry(key);
|
||||
if (entry.fChildren == null || (update.getOffset() < 0 && !entry.fAllChildrenKnown)) {
|
||||
// We need to retrieve all the children if we don't have any children information.
|
||||
// Or if the client requested all children (offset = -1, length -1) and we have not
|
||||
// retrieved that before.
|
||||
updates[0] = new VMChildrenUpdate(
|
||||
update, update.getOffset(), update.getLength(),
|
||||
new DataRequestMonitor<List<Object>>(getExecutor(), null)
|
||||
{
|
||||
@Override
|
||||
protected void handleCompleted()
|
||||
{
|
||||
if(getData() != null) {
|
||||
// Check if the udpate retrieved all children by specifying "offset = -1, length = -1"
|
||||
int updateOffset = update.getOffset();
|
||||
if (updateOffset < 0) {
|
||||
updateOffset = 0;
|
||||
entry.fAllChildrenKnown = true;
|
||||
}
|
||||
|
||||
// Estimate size of children map.
|
||||
Integer childrenCount = entry.fChildrenCount;
|
||||
childrenCount = childrenCount != null ? childrenCount : 0;
|
||||
int capacity = Math.max((childrenCount.intValue() * 4)/3, 32);
|
||||
// Create a new map, but only if it hasn't been created yet by another update.
|
||||
if (entry.fChildren == null) {
|
||||
entry.fChildren = new HashMap<Integer,Object>(capacity);
|
||||
}
|
||||
|
||||
// Set the children to map and update.
|
||||
for(int j = 0; j < getData().size(); j++) {
|
||||
int offset = updateOffset + j;
|
||||
Object child = getData().get(j);
|
||||
|
||||
entry.fChildren.put(offset, child);
|
||||
update.setChild(child, offset);
|
||||
}
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
});
|
||||
super.updateNode(node, updates);
|
||||
} else if (update.getOffset() < 0 ) {
|
||||
// The udpate requested all children. Fill in all children assuming that
|
||||
// the children array is complete.
|
||||
|
||||
// The following assert should never fail given the first if statement.
|
||||
assert entry.fAllChildrenKnown;
|
||||
|
||||
// we have all of the children in cache; return from cache
|
||||
for(int position = 0; position < entry.fChildren.size(); position++) {
|
||||
update.setChild(entry.fChildren.get(position), position);
|
||||
}
|
||||
update.done();
|
||||
} else {
|
||||
// Make the list of missing children. If we've retrieved the
|
||||
List<Integer> childrenMissingFromCache = new LinkedList<Integer>();
|
||||
for (int i = update.getOffset(); i < update.getOffset() + update.getLength(); i++) {
|
||||
childrenMissingFromCache.add(i);
|
||||
}
|
||||
childrenMissingFromCache.removeAll(entry.fChildren.keySet());
|
||||
|
||||
if (childrenMissingFromCache.size() > 0) {
|
||||
// perform a partial update; we only have some of the children of the update request
|
||||
|
||||
List<IChildrenUpdate> partialUpdates = new ArrayList<IChildrenUpdate>(2);
|
||||
|
||||
final CountingRequestMonitor multiRm = new ViewerCountingRequestMonitor(getExecutor(), update);
|
||||
|
||||
while(childrenMissingFromCache.size() > 0)
|
||||
{
|
||||
final int offset = childrenMissingFromCache.get(0);
|
||||
childrenMissingFromCache.remove(0);
|
||||
int length = 1;
|
||||
while(childrenMissingFromCache.size() > 0 && childrenMissingFromCache.get(0) == offset + length)
|
||||
{
|
||||
length++;
|
||||
childrenMissingFromCache.remove(0);
|
||||
}
|
||||
|
||||
partialUpdates.add(new VMChildrenUpdate(
|
||||
update, offset, length,
|
||||
new DataRequestMonitor<List<Object>>(getExecutor(), multiRm) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (getData() != null) {
|
||||
for (int i = 0; i < getData().size(); i++) {
|
||||
update.setChild(getData().get(i), offset + i);
|
||||
}
|
||||
}
|
||||
multiRm.done();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
super.updateNode( node, partialUpdates.toArray(new IChildrenUpdate[partialUpdates.size()]) );
|
||||
multiRm.setDoneCount(partialUpdates.size());
|
||||
} else {
|
||||
// we have all of the children in cache; return from cache
|
||||
for(int position = update.getOffset(); position < update.getOffset() + update.getLength(); position++) {
|
||||
update.setChild(entry.fChildren.get(position), position);
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the cache with given DMC as the root element.
|
||||
* @param dmcToFlush DM Context which is the root of the flush operation. Entries
|
||||
* for all DMCs that have this DMC as their ancestor will be flushed. If this
|
||||
* parameter is null, then all entries are flushed.
|
||||
* @param archive
|
||||
*/
|
||||
private void flush(List<FlushMarkerKey> flushKeys) {
|
||||
// To flush the cache data for given context, we have to iterate through all the contexts
|
||||
// in cache. For each entry that has the given context as a parent, perform the flush.
|
||||
List<FlushMarkerKey> flushKeysCopy = new ArrayList<FlushMarkerKey>(flushKeys.size());
|
||||
flushKeysCopy.addAll(flushKeys);
|
||||
|
||||
// Iterate through the cache entries backwards. This means that we will be
|
||||
// iterating in order of most-recently-used to least-recently-used.
|
||||
Entry entry = fCacheListHead.fPrevious;
|
||||
while (entry != fCacheListHead && flushKeysCopy.size() != 0) {
|
||||
for (Iterator<FlushMarkerKey> flushKeyItr = flushKeysCopy.iterator(); flushKeyItr.hasNext();) {
|
||||
FlushMarkerKey flushKey = flushKeyItr.next();
|
||||
|
||||
if (entry.fKey instanceof FlushMarkerKey) {
|
||||
FlushMarkerKey entryFlushKey = (FlushMarkerKey)entry.fKey;
|
||||
// If the context currently being flushed includes the flush
|
||||
// context in current entry, remove the current entry since it will
|
||||
// be replaced with one at the end of the list.
|
||||
// Use special handling for null contexts, which we treat like it's an
|
||||
// ancestor of all other contexts.
|
||||
if (flushKey.includes(entryFlushKey)) {
|
||||
fCacheData.remove(entryFlushKey);
|
||||
entry.remove();
|
||||
}
|
||||
|
||||
// If the flush context in current entry includes the current context
|
||||
// being flushed, we can stop iterating through the cache entries
|
||||
// now.
|
||||
if (entryFlushKey.includes(flushKey)) {
|
||||
flushKeyItr.remove();
|
||||
}
|
||||
}
|
||||
else if (entry instanceof ElementDataEntry) {
|
||||
ElementDataEntry elementDataEntry = (ElementDataEntry)entry;
|
||||
int updateFlags = flushKey.getUpdateFlags((ElementDataKey)elementDataEntry.fKey);
|
||||
if ((updateFlags & IVMUpdatePolicy.FLUSH) != 0) {
|
||||
if ((updateFlags & IVMUpdatePolicy.ARCHIVE) != 0) {
|
||||
// We are saving current data for change history, check if the data is valid.
|
||||
// If it valid, save it for archive, if it's not valid old archive data will be used
|
||||
// if there is any. And if there is no old archive data, just remove the cache entry.
|
||||
for (Iterator<Map.Entry<IDMContext, Object>> itr = elementDataEntry.fDataOrStatus.entrySet().iterator();
|
||||
itr.hasNext();)
|
||||
{
|
||||
Map.Entry<IDMContext, Object> dataOrStatusEntry = itr.next();
|
||||
if (dataOrStatusEntry.getValue() instanceof IDMData) {
|
||||
elementDataEntry.fArchiveData.put(dataOrStatusEntry.getKey(), (IDMData)dataOrStatusEntry.getValue());
|
||||
}
|
||||
}
|
||||
elementDataEntry.fDataOrStatus.clear();
|
||||
if (elementDataEntry.fArchiveData.isEmpty()) {
|
||||
fCacheData.remove(entry.fKey);
|
||||
entry.remove();
|
||||
}
|
||||
} else {
|
||||
// We are not changing the archived data. If archive data exists in the entry, leave it.
|
||||
// Otherwise remove the whole entry.
|
||||
if (!elementDataEntry.fArchiveData.isEmpty()) {
|
||||
elementDataEntry.fDataOrStatus.clear();
|
||||
} else {
|
||||
fCacheData.remove(entry.fKey);
|
||||
entry.remove();
|
||||
}
|
||||
}
|
||||
elementDataEntry.fHasChildren = null;
|
||||
elementDataEntry.fChildrenCount = null;
|
||||
elementDataEntry.fChildren = null;
|
||||
} else if ((updateFlags & IVMUpdatePolicy.DIRTY) != 0) {
|
||||
elementDataEntry.fDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
entry = entry.fPrevious;
|
||||
}
|
||||
|
||||
for (FlushMarkerKey flushKey : flushKeys) {
|
||||
// Insert a marker for this flush operation.
|
||||
Entry flushMarkerEntry = new Entry(flushKey);
|
||||
fCacheData.put(flushKey, flushMarkerEntry);
|
||||
flushMarkerEntry.insert(fCacheListHead);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void handleEvent(final Object event) {
|
||||
IElementUpdateTester elementTester = getActiveUpdatePolicy().getTesterTester(event);
|
||||
|
||||
List<FlushMarkerKey> flushKeys = new LinkedList<FlushMarkerKey>();
|
||||
List<IVMModelProxy> proxies = new LinkedList<IVMModelProxy>();
|
||||
|
||||
for (final IVMModelProxy proxyStrategy : getActiveModelProxies()) {
|
||||
if (proxyStrategy.isDeltaEvent(event)) {
|
||||
flushKeys.add(new FlushMarkerKey(proxyStrategy.getRootElement(), elementTester));
|
||||
proxies.add(proxyStrategy);
|
||||
}
|
||||
}
|
||||
|
||||
flush(flushKeys);
|
||||
|
||||
for (final IVMModelProxy proxyStrategy : proxies) {
|
||||
if (!proxyStrategy.isDisposed() && proxyStrategy.isDeltaEvent(event)) {
|
||||
proxyStrategy.createDelta(
|
||||
event,
|
||||
new DataRequestMonitor<IModelDelta>(getExecutor(), null) {
|
||||
@Override
|
||||
public void handleCompleted() {
|
||||
|
||||
if (getStatus().isOK()) {
|
||||
proxyStrategy.fireModelChanged(getData());
|
||||
}
|
||||
}
|
||||
@Override public String toString() {
|
||||
return "Result of a delta for event: '" + event.toString() + "' in VMP: '" + this + "'" + "\n" + getData().toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* is no longer in the cache.
|
||||
*/
|
||||
@Override
|
||||
public IModelProxy createModelProxy(Object element, IPresentationContext context) {
|
||||
assert getExecutor().isInExecutorThread();
|
||||
|
||||
// Iterate through the current active proxies to try to find a proxy with the same
|
||||
// element and re-use it if found. At the same time purge proxies that are no longer
|
||||
IVMModelProxy proxy = null;
|
||||
for (Iterator<IVMModelProxy> itr = getActiveModelProxies().iterator(); itr.hasNext();) {
|
||||
IVMModelProxy next = itr.next();
|
||||
if (next == null && next.getRootElement().equals(element)) {
|
||||
proxy = next;
|
||||
}
|
||||
}
|
||||
if (proxy == null) {
|
||||
proxy = createModelProxyStrategy(element);
|
||||
getActiveModelProxies().add(proxy);
|
||||
}
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when a given all cache entries for the given root element have
|
||||
* been removed from the cache. In order to property track changed elements,
|
||||
* the caching VM provider does not immediately remove entries for a given root
|
||||
* element, when the viewer root element changes. Instead it keeps this root
|
||||
* element and keeps processing deltas for that root element until the
|
||||
* cache entries for this element are gone.
|
||||
*/
|
||||
protected void rootElementRemovedFromCache(Object rootElement) {
|
||||
fRootMarkers.remove(rootElement);
|
||||
|
||||
for (Iterator<IVMModelProxy> proxiesItr = getActiveModelProxies().iterator(); proxiesItr.hasNext();) {
|
||||
IVMModelProxy proxy = proxiesItr.next();
|
||||
if (proxy.isDisposed() && proxy.getRootElement().equals(rootElement) ) {
|
||||
proxiesItr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience class that searches for teh root element for the given
|
||||
* update and creates an element cache entry key.
|
||||
*/
|
||||
private ElementDataKey makeEntryKey(IVMNode node, IViewerUpdate update) {
|
||||
Object rootElement = update.getViewerInput(); // Default
|
||||
outer: for (IVMModelProxy proxy : getActiveModelProxies()) {
|
||||
Object proxyRoot = proxy.getRootElement();
|
||||
if (proxyRoot.equals(update.getViewerInput())) {
|
||||
rootElement = proxyRoot;
|
||||
break;
|
||||
}
|
||||
TreePath path = update.getElementPath();
|
||||
for (int i = 0; i < path.getSegmentCount(); i++) {
|
||||
if (proxyRoot.equals(path.getSegment(i))) {
|
||||
rootElement = proxyRoot;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ElementDataKey(rootElement, node, update.getElement(), update.getElementPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the only method that should be used to access a cache entry.
|
||||
* It creates a new entry if needed and it maintains the ordering in
|
||||
* the least-recently-used linked list.
|
||||
*/
|
||||
private ElementDataEntry getElementDataEntry(ElementDataKey key) {
|
||||
assert key != null;
|
||||
ElementDataEntry entry = (ElementDataEntry)fCacheData.get(key);
|
||||
if (entry == null) {
|
||||
// Create a new entry and add it to the end of the list.
|
||||
entry = new ElementDataEntry(key);
|
||||
addEntry(key, entry);
|
||||
} else {
|
||||
// Entry exists, move it to the end of the list.
|
||||
entry.remove();
|
||||
entry.insert(fCacheListHead);
|
||||
}
|
||||
|
||||
// Update they root element marker.
|
||||
RootElementMarkerKey rootMarker = fRootMarkers.get(key.fRootElement);
|
||||
if (rootMarker == null) {
|
||||
rootMarker = new RootElementMarkerKey(key.fRootElement);
|
||||
fRootMarkers.put(key.fRootElement, rootMarker);
|
||||
}
|
||||
Entry rootMarkerEntry = fCacheData.get(rootMarker);
|
||||
if (rootMarkerEntry == null) {
|
||||
rootMarkerEntry = new RootElementMarkerEntry(rootMarker);
|
||||
addEntry(rootMarker, rootMarkerEntry);
|
||||
} else {
|
||||
rootMarkerEntry.remove();
|
||||
rootMarkerEntry.insert(fCacheListHead);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method used by {@link #getElementDataEntry(ElementDataKey)}
|
||||
*/
|
||||
private void addEntry(Object key, Entry entry) {
|
||||
fCacheData.put(key, entry);
|
||||
entry.insert(fCacheListHead);
|
||||
// If we are at capacity in the cache, remove the entry from head.
|
||||
if (fCacheData.size() > MAX_CACHE_SIZE) {
|
||||
fCacheData.remove(fCacheListHead.fNext.fKey);
|
||||
fCacheListHead.fNext.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the deprecated IDMData object for the given IDMContext. This
|
||||
* method should be removed once the use of IDMData is replaced with
|
||||
* {@link IElementPropertiesProvider}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void getModelData(IVMNode node, IViewerUpdate update, IDMService service, final IDMContext dmc,
|
||||
final DataRequestMonitor rm, Executor executor)
|
||||
{
|
||||
ElementDataKey key = makeEntryKey(node, update);
|
||||
final ElementDataEntry entry = getElementDataEntry(key);
|
||||
Object dataOrStatus = entry.fDataOrStatus.get(dmc);
|
||||
if(dataOrStatus != null) {
|
||||
if (dataOrStatus instanceof IDMData) {
|
||||
rm.setData( (IDMData)dataOrStatus );
|
||||
} else {
|
||||
rm.setStatus((IStatus)dataOrStatus );
|
||||
}
|
||||
rm.done();
|
||||
} else {
|
||||
service.getModelData(dmc,
|
||||
new DataRequestMonitor<IDMData>(executor, rm) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (getStatus().isOK()) {
|
||||
entry.fDataOrStatus.put(dmc, getData());
|
||||
rm.setData(getData());
|
||||
} else {
|
||||
entry.fDataOrStatus.put(dmc, getStatus());
|
||||
rm.setStatus(getStatus());
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the deprecated IDMData object for the given IDMContext. This
|
||||
* method should be removed once the use of IDMData is replaced with
|
||||
* {@link IElementPropertiesProvider}.
|
||||
*/
|
||||
@Deprecated
|
||||
public IDMData getArchivedModelData(IVMNode node, IViewerUpdate update, IDMContext dmc) {
|
||||
ElementDataKey key = makeEntryKey(node, update);
|
||||
final ElementDataEntry entry = getElementDataEntry(key);
|
||||
if ( entry.fArchiveData != null) {
|
||||
return entry.fArchiveData.get(dmc);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.ui.viewmodel.update;
|
||||
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public class AutomaticUpdatePolicy implements IVMUpdatePolicy {
|
||||
|
||||
public static String AUTOMATIC_UPDATE_POLICY_ID = "org.eclipse.dd.dsf.ui.viewmodel.update.defaultUpdatePolicy"; //$NON-NLS-1$
|
||||
|
||||
public static IElementUpdateTester fgUpdateTester = new IElementUpdateTester() {
|
||||
public int getUpdateFlags(Object viewerInput, TreePath path) {
|
||||
return FLUSH | ARCHIVE;
|
||||
}
|
||||
|
||||
public boolean includes(IElementUpdateTester tester) {
|
||||
return tester.equals(this);
|
||||
}
|
||||
};
|
||||
|
||||
public String getID() {
|
||||
return AUTOMATIC_UPDATE_POLICY_ID;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "Automatic";
|
||||
}
|
||||
|
||||
public IElementUpdateTester getTesterTester(Object event) {
|
||||
return fgUpdateTester;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.ui.viewmodel.update;
|
||||
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMProvider;
|
||||
|
||||
/**
|
||||
* A view model provider which supports caching of data returned by view model
|
||||
* nodes. The methods in this interface allow clients to configure how the
|
||||
* cache should be updated in response to different events.
|
||||
*/
|
||||
public interface ICachingVMProvider extends IVMProvider {
|
||||
|
||||
/**
|
||||
* Returns the update policies that the given provider supports.
|
||||
*/
|
||||
public IVMUpdatePolicy[] getAvailableUpdatePolicies();
|
||||
|
||||
/**
|
||||
* Returns the active update policy.
|
||||
*/
|
||||
public IVMUpdatePolicy getActiveUpdatePolicy();
|
||||
|
||||
/**
|
||||
* Sets the active update policy. This has to be one of the update
|
||||
* policies supported by the provider.
|
||||
*/
|
||||
public void setActiveUpdatePolicy(IVMUpdatePolicy mode);
|
||||
|
||||
/**
|
||||
* Forces the view to flush its cache and re-fetch data from the view
|
||||
* model nodes.
|
||||
*/
|
||||
public void refresh();
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.ui.viewmodel.update;
|
||||
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* Tester object used to determine how individual update cache
|
||||
* entries should be updated during a flush operation.
|
||||
*
|
||||
* @see IVMUpdatePolicy
|
||||
*/
|
||||
public interface IElementUpdateTester {
|
||||
|
||||
/**
|
||||
* Returns the flags indicating what updates should be performed on the
|
||||
* cache entry of the given element.
|
||||
*/
|
||||
public int getUpdateFlags(Object viewerInput, TreePath path);
|
||||
|
||||
/**
|
||||
* Returns whether update represented by this tester includes another
|
||||
* update. For example if update A was created as a result of an element X,
|
||||
* and update B was created for an element Y, and element X is a parent of
|
||||
* element Y, then tester A should include tester B. Also a tester should
|
||||
* always include itself.
|
||||
* <p/>
|
||||
* This method is used to optimize the repeated flushing of the cache as
|
||||
* it allows the cache to avoid needlessly updating the same cache entries.
|
||||
*/
|
||||
public boolean includes(IElementUpdateTester tester);
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.ui.viewmodel.update;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for an update policy. The main function of an update policy is
|
||||
* to create an element tester for each given event. The element tester
|
||||
* is then used to update the viewer cache.
|
||||
*/
|
||||
public interface IVMUpdatePolicy {
|
||||
|
||||
/**
|
||||
* Flag indicating that a given entry in the cache should be cleared.
|
||||
*/
|
||||
public static int FLUSH = 0x1;
|
||||
|
||||
/**
|
||||
* Flag indicating that a given entry in the cache should be cleared
|
||||
* and saved for purpose of change tracking.
|
||||
*/
|
||||
public static int ARCHIVE = FLUSH | 0x2; // Flush is required when archiving.
|
||||
|
||||
/**
|
||||
* Flag indicating that the a given cache entry should be marked as dirty.
|
||||
* A dirty cache entry is one that is known not to be consistent with
|
||||
* target data.
|
||||
*/
|
||||
public static int DIRTY = 0x4;
|
||||
|
||||
/**
|
||||
* Returns unique ID of this update policy.
|
||||
*/
|
||||
public String getID();
|
||||
|
||||
/**
|
||||
* Returns the user-presentable name of this update policy.
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Creates an element tester for the given event.
|
||||
*/
|
||||
public IElementUpdateTester getTesterTester(Object event);
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.ui.viewmodel.update;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
|
||||
/**
|
||||
* An "manual" update policy which causes the view model provider cache to be
|
||||
* flushed only as a result of an explicit user action.
|
||||
*/
|
||||
public class ManualUpdatePolicy implements IVMUpdatePolicy {
|
||||
|
||||
public static String MANUAL_UPDATE_POLICY_ID = "org.eclipse.dd.dsf.ui.viewmodel.update.manualUpdatePolicy"; //$NON-NLS-1$
|
||||
|
||||
public static Object REFRESH_EVENT = new Object();
|
||||
|
||||
private static class UserEditEventUpdateTester implements IElementUpdateTester {
|
||||
private final Set<Object> fElements;
|
||||
|
||||
public UserEditEventUpdateTester(Set<Object> elements) {
|
||||
fElements = elements;
|
||||
}
|
||||
|
||||
public int getUpdateFlags(Object viewerInput, TreePath path) {
|
||||
if (fElements.contains(viewerInput)) {
|
||||
return FLUSH;
|
||||
}
|
||||
for (int i = 0; i < path.getSegmentCount(); i++) {
|
||||
if (fElements.contains(path.getSegment(i))) {
|
||||
return FLUSH;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean includes(IElementUpdateTester tester) {
|
||||
return
|
||||
tester instanceof UserEditEventUpdateTester &&
|
||||
fElements.equals(((UserEditEventUpdateTester)tester).fElements);
|
||||
}
|
||||
}
|
||||
|
||||
private static IElementUpdateTester fgUpdateTester = new IElementUpdateTester() {
|
||||
public int getUpdateFlags(Object viewerInput, TreePath path) {
|
||||
return DIRTY;
|
||||
}
|
||||
|
||||
public boolean includes(IElementUpdateTester tester) {
|
||||
return tester.equals(this);
|
||||
}
|
||||
};
|
||||
|
||||
private static IElementUpdateTester fgRefreshUpdateTester = new IElementUpdateTester() {
|
||||
public int getUpdateFlags(Object viewerInput, TreePath path) {
|
||||
return FLUSH | ARCHIVE;
|
||||
}
|
||||
|
||||
public boolean includes(IElementUpdateTester tester) {
|
||||
return tester.equals(this) || tester.equals(fgUpdateTester) || tester instanceof UserEditEventUpdateTester;
|
||||
}
|
||||
};
|
||||
|
||||
public String getID() {
|
||||
return MANUAL_UPDATE_POLICY_ID;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "Manual";
|
||||
}
|
||||
|
||||
public IElementUpdateTester getTesterTester(Object event) {
|
||||
if (event.equals(REFRESH_EVENT)) {
|
||||
return fgRefreshUpdateTester;
|
||||
}
|
||||
return fgUpdateTester;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.dd.dsf.ui.viewmodel.update;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* An event representing a user editing of the data in the viewer. Typically, when
|
||||
* a viewer is configured to be in a manual update mode, if user edits a value, the
|
||||
* viewer should still update at least the value that the user editor. This event
|
||||
* is used to accomplish that behavior.
|
||||
*/
|
||||
public class UserEditEvent {
|
||||
private final Set<Object> fElements;
|
||||
|
||||
public UserEditEvent(Object element) {
|
||||
fElements = new HashSet<Object>();
|
||||
fElements.add(element);
|
||||
}
|
||||
|
||||
public UserEditEvent(Set<Object> elements) {
|
||||
fElements = elements;
|
||||
}
|
||||
|
||||
public Set<Object> getElements() {
|
||||
return fElements;
|
||||
}
|
||||
}
|
|
@ -1,384 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.ui.viewmodel.update;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DefaultDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMData;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMService;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMElementsCountUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMElementsUpdate;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMHasElementsUpdate;
|
||||
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;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public abstract class VMCache
|
||||
{
|
||||
protected Executor fExecutor = new DefaultDsfExecutor();
|
||||
|
||||
protected HashMap<Object, Integer> fChildrenCounts = new HashMap<Object, Integer>();
|
||||
|
||||
protected HashMap<Object, HashMap<Integer,Object>> fChildren = new HashMap<Object, HashMap<Integer,Object>>();
|
||||
|
||||
protected HashMap<Object, Boolean> fHasChildren = new HashMap<Object, Boolean>();
|
||||
|
||||
protected HashMap<IDMContext, IDMData> fData = new HashMap<IDMContext, IDMData>();
|
||||
|
||||
protected HashMap<IDMContext, IDMData> fDataArchive = fData;
|
||||
|
||||
public HashMap<?,?>[] getCacheData()
|
||||
{
|
||||
return new HashMap<?,?>[] { fHasChildren, fChildrenCounts, fChildren, fData, fDataArchive };
|
||||
}
|
||||
|
||||
public VMCache()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Suppress warnings related to the lost type information in getCacheData()
|
||||
@SuppressWarnings("unchecked")
|
||||
public VMCache(VMCache oldCache)
|
||||
{
|
||||
if(oldCache != null)
|
||||
{
|
||||
HashMap<?,?> oldCacheData[] = oldCache.getCacheData();
|
||||
|
||||
fHasChildren = (HashMap<Object, Boolean>)oldCacheData[0];
|
||||
fChildrenCounts = (HashMap<Object, Integer>)oldCacheData[1];
|
||||
fChildren = (HashMap<Object, HashMap<Integer,Object>>)oldCacheData[2];
|
||||
fData = (HashMap<IDMContext, IDMData>)oldCacheData[3];
|
||||
fDataArchive = (HashMap<IDMContext, IDMData>)oldCacheData[4];
|
||||
}
|
||||
}
|
||||
|
||||
protected void flush(boolean archive)
|
||||
{
|
||||
if(archive)
|
||||
fDataArchive = fData;
|
||||
fData = new HashMap<IDMContext, IDMData>();
|
||||
fChildrenCounts.clear();
|
||||
fChildren.clear();
|
||||
fHasChildren.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the data in this cache should used when servicing
|
||||
* view updates. If this method returns false all updates will be
|
||||
* sent to the view model, although the retrieved data should still
|
||||
* be stored in the cache if {@link #isCacheWriteEnabled()} returns true.
|
||||
* @return
|
||||
*/
|
||||
protected boolean isCacheReadEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if data retrieved from the view model should be cached.
|
||||
* If this returns false, then the state of the cache is frozen.
|
||||
*/
|
||||
protected boolean isCacheWriteEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public IHasChildrenUpdate[] update(IHasChildrenUpdate[] updates) {
|
||||
if(!isCacheReadEnabled())
|
||||
return updates;
|
||||
|
||||
Vector<IHasChildrenUpdate> missVector = new Vector<IHasChildrenUpdate>();
|
||||
for(IHasChildrenUpdate update : updates)
|
||||
{
|
||||
if(fHasChildren.containsKey(update.getElement()) && isCacheReadEnabled())
|
||||
{
|
||||
update.setHasChilren(fHasChildren.get(update.getElement()).booleanValue());
|
||||
update.done();
|
||||
}
|
||||
else
|
||||
{
|
||||
missVector.addElement(update);
|
||||
}
|
||||
}
|
||||
|
||||
updates = new IHasChildrenUpdate[missVector.size()];
|
||||
for(int i = 0; i < updates.length; i++)
|
||||
{
|
||||
final IHasChildrenUpdate update = missVector.elementAt(i);
|
||||
updates[i] = new VMHasElementsUpdate(update, new DataRequestMonitor<Boolean>(fExecutor, null)
|
||||
{
|
||||
@Override
|
||||
protected void handleCompleted()
|
||||
{
|
||||
if(getStatus().isOK())
|
||||
{
|
||||
if(isCacheWriteEnabled())
|
||||
fHasChildren.put(update.getElement(), this.getData());
|
||||
update.setHasChilren(getData());
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return updates;
|
||||
}
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public IChildrenCountUpdate[] update(IChildrenCountUpdate[] updates)
|
||||
{
|
||||
if(!isCacheReadEnabled())
|
||||
return updates;
|
||||
|
||||
Vector<IChildrenCountUpdate> missVector = new Vector<IChildrenCountUpdate>();
|
||||
for(IChildrenCountUpdate update : updates)
|
||||
{
|
||||
if(fChildrenCounts.containsKey(update.getElement()) && isCacheReadEnabled())
|
||||
{
|
||||
update.setChildCount(fChildrenCounts.get(update.getElement()));
|
||||
update.done();
|
||||
}
|
||||
else
|
||||
{
|
||||
missVector.addElement(update);
|
||||
}
|
||||
}
|
||||
|
||||
updates = new IChildrenCountUpdate[missVector.size()];
|
||||
for(int i = 0; i < updates.length; i++)
|
||||
{
|
||||
final IChildrenCountUpdate update = missVector.elementAt(i);
|
||||
updates[i] = new VMElementsCountUpdate(update, new DataRequestMonitor<Integer>(fExecutor, null)
|
||||
{
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if(getStatus().isOK())
|
||||
{
|
||||
if(isCacheWriteEnabled())
|
||||
fChildrenCounts.put(update.getElement(), this.getData());
|
||||
update.setChildCount(this.getData());
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return updates;
|
||||
}
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public IChildrenUpdate[] update(IChildrenUpdate[] updates) {
|
||||
if(!isCacheReadEnabled())
|
||||
return updates;
|
||||
|
||||
Vector<IChildrenUpdate> updatesEntirelyMissingFromCache = new Vector<IChildrenUpdate>();
|
||||
for(final IChildrenUpdate update : updates)
|
||||
{
|
||||
if(fChildren.containsKey(update.getElement()) && isCacheReadEnabled())
|
||||
{
|
||||
Vector<Integer> childrenMissingFromCache = new Vector<Integer>();
|
||||
for(int i = update.getOffset(); i < update.getOffset() + update.getLength(); i++)
|
||||
childrenMissingFromCache.addElement(i);
|
||||
childrenMissingFromCache.removeAll(fChildren.get(update.getElement()).keySet());
|
||||
|
||||
if(childrenMissingFromCache.size() > 0)
|
||||
{
|
||||
// perform a partial update; we only have some of the children of the update request
|
||||
|
||||
final HashMap<DataRequestMonitor<List<Object>>,IChildrenUpdate> associationsRequestMonitorToChildUpdate
|
||||
= new HashMap<DataRequestMonitor<List<Object>>,IChildrenUpdate>();
|
||||
|
||||
final MultiRequestMonitor<DataRequestMonitor<List<Object>>> childrenMultiRequestMon =
|
||||
new MultiRequestMonitor<DataRequestMonitor<List<Object>>>(fExecutor, null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
// Status is OK, only if all request monitors are OK.
|
||||
if (getStatus().isOK())
|
||||
{
|
||||
for (DataRequestMonitor<List<Object>> monitor : getRequestMonitors())
|
||||
{
|
||||
int offset = associationsRequestMonitorToChildUpdate.get(monitor).getOffset();
|
||||
for(Object child : monitor.getData())
|
||||
update.setChild(child, offset++);
|
||||
}
|
||||
} else {
|
||||
update.setStatus(getStatus());
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
};
|
||||
|
||||
while(childrenMissingFromCache.size() > 0)
|
||||
{
|
||||
int offset = childrenMissingFromCache.elementAt(0);
|
||||
childrenMissingFromCache.removeElementAt(0);
|
||||
int length = 1;
|
||||
while(childrenMissingFromCache.size() > 0 && childrenMissingFromCache.elementAt(0) == offset + length)
|
||||
{
|
||||
length++;
|
||||
childrenMissingFromCache.removeElementAt(0);
|
||||
}
|
||||
|
||||
DataRequestMonitor<List<Object>> partialUpdateMonitor = new DataRequestMonitor<List<Object>>(fExecutor, null)
|
||||
{
|
||||
@Override
|
||||
protected void handleCompleted()
|
||||
{
|
||||
|
||||
childrenMultiRequestMon.requestMonitorDone(this);
|
||||
}
|
||||
};
|
||||
|
||||
final IChildrenUpdate partialUpdate = new VMElementsUpdate(update, offset, length,
|
||||
childrenMultiRequestMon.add(partialUpdateMonitor));
|
||||
|
||||
associationsRequestMonitorToChildUpdate.put(partialUpdateMonitor, partialUpdate);
|
||||
|
||||
updatesEntirelyMissingFromCache.add(partialUpdate);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have all of the children in cache; return from cache
|
||||
for(int position = update.getOffset(); position < update.getOffset() + update.getLength(); position++)
|
||||
update.setChild(fChildren.get(update.getElement()).get(position), position);
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
updatesEntirelyMissingFromCache.addElement(update);
|
||||
}
|
||||
}
|
||||
|
||||
updates = new IChildrenUpdate[updatesEntirelyMissingFromCache.size()];
|
||||
for(int i = 0; i < updates.length; i++)
|
||||
{
|
||||
final IChildrenUpdate update = updatesEntirelyMissingFromCache.elementAt(i);
|
||||
updates[i] =
|
||||
new VMElementsUpdate(
|
||||
update, update.getOffset(), update.getLength(),
|
||||
new DataRequestMonitor<List<Object>>(fExecutor, null)
|
||||
{
|
||||
@Override
|
||||
protected void handleCompleted()
|
||||
{
|
||||
if(getData() != null)
|
||||
{
|
||||
for(int j = 0; j < getData().size(); j++)
|
||||
{
|
||||
if(isCacheWriteEnabled())
|
||||
{
|
||||
if(!fChildren.containsKey(update.getElement()))
|
||||
fChildren.put(update.getElement(), new HashMap<Integer,Object>());
|
||||
|
||||
fChildren.get(update.getElement()).put(update.getOffset() + j, getData().get(j));
|
||||
}
|
||||
|
||||
update.setChild(getData().get(j), update.getOffset() + j);
|
||||
}
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
})
|
||||
{
|
||||
/* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=202109
|
||||
*
|
||||
* A flexible hierarchy bug/optimization causes query with incorrect
|
||||
* IChildrenUpdate[] array length.
|
||||
*
|
||||
* We found this while deleting a register node. Example:
|
||||
*
|
||||
* the register view displays:
|
||||
* PC
|
||||
* EAX
|
||||
* EBX
|
||||
* ECX
|
||||
* EDX
|
||||
*
|
||||
* we delete EBX and force a context refresh.
|
||||
*
|
||||
* flexible hierarchy queries for IChildrenUpdate[5] and IChildrenCountUpdate at
|
||||
* the same time.
|
||||
*
|
||||
* VMElementsUpdate, used by VMCache to wrap the IChildrenUpdate, generates an
|
||||
* IStatus.ERROR with message "Incomplete elements of updates" when fElements
|
||||
* count (provided by service) does not match the length provided by the original
|
||||
* update query.
|
||||
*
|
||||
* Workaround, respect getData() != null instead of IStatus.OK, override
|
||||
* VMElementsUpdate.done() to set elements regardless of count
|
||||
*/
|
||||
@Override
|
||||
public void done() {
|
||||
@SuppressWarnings("unchecked")
|
||||
DataRequestMonitor<List<Object>> rm = (DataRequestMonitor<List<Object>>)fRequestMonitor;
|
||||
rm.setData(fElements);
|
||||
super.done();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return updates;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@ConfinedToDsfExecutor("DsfSession.getSession(dmc.getSessionId()).getExecutor()")
|
||||
public void getModelData(IDMService service, final IDMContext dmc, final DataRequestMonitor rm, DsfExecutor executor)
|
||||
{
|
||||
if(fData.containsKey(dmc) && isCacheReadEnabled())
|
||||
{
|
||||
rm.setData( fData.get(dmc));
|
||||
rm.done();
|
||||
}
|
||||
else
|
||||
{
|
||||
service.getModelData(dmc,
|
||||
new DataRequestMonitor<IDMData>(executor, rm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
if(isCacheWriteEnabled())
|
||||
fData.put(dmc, getData());
|
||||
rm.setData(getData());
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public IDMData getArchivedModelData(IDMContext dmc)
|
||||
{
|
||||
return fDataArchive.get(dmc);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public abstract void handleEvent(IDMEvent event);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.ui.viewmodel.update;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
|
||||
|
||||
public class VMCacheManager
|
||||
{
|
||||
private static VMCacheManager fInstance = null;
|
||||
|
||||
private HashMap<Object, VMCache> fAssociations = new HashMap<Object, VMCache>();
|
||||
|
||||
public interface CacheListener
|
||||
{
|
||||
public void cacheFlushed(Object context);
|
||||
}
|
||||
|
||||
private HashMap<Object, Vector<CacheListener>> fListeners = new HashMap<Object, Vector<CacheListener>>();
|
||||
|
||||
public VMCacheManager()
|
||||
{
|
||||
}
|
||||
|
||||
public static VMCacheManager getVMCacheManager()
|
||||
{
|
||||
if(fInstance == null)
|
||||
fInstance = new VMCacheManager();
|
||||
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
public VMCache getCache(Object context)
|
||||
{
|
||||
if(!fAssociations.containsKey(context))
|
||||
fAssociations.put(context, new VMCache()
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void handleEvent(IDMEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCacheReadEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCacheWriteEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return fAssociations.get(context);
|
||||
}
|
||||
|
||||
public void registerCache(Object context, VMCache cache)
|
||||
{
|
||||
fAssociations.put(context, cache);
|
||||
}
|
||||
|
||||
public void addCacheListener(Object context, CacheListener listener)
|
||||
{
|
||||
if(!fListeners.containsKey(context))
|
||||
fListeners.put(context, new Vector<CacheListener>());
|
||||
|
||||
fListeners.get(context).addElement(listener);
|
||||
}
|
||||
|
||||
public void removeCacheListener(Object context, CacheListener listener)
|
||||
{
|
||||
if(!fListeners.containsKey(context))
|
||||
{
|
||||
fListeners.get(context).removeElement(listener);
|
||||
if(fListeners.get(context).isEmpty())
|
||||
fListeners.remove(context);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireCacheFlushed(Object context)
|
||||
{
|
||||
if(fListeners.containsKey(context))
|
||||
{
|
||||
for(CacheListener listener : fListeners.get(context))
|
||||
listener.cacheFlushed(context);
|
||||
}
|
||||
}
|
||||
|
||||
public void flush(Object context)
|
||||
{
|
||||
getCache(context).flush(false);
|
||||
fireCacheFlushed(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.dsf.ui.viewmodel.update.actions;
|
||||
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCache;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.VMCacheManager;
|
||||
import org.eclipse.jface.action.IAction;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.ui.IViewActionDelegate;
|
||||
import org.eclipse.ui.IViewPart;
|
||||
|
||||
public abstract class AbstractRefreshActionDelegate implements IViewActionDelegate {
|
||||
|
||||
protected IViewPart fView;
|
||||
|
||||
public void init(IViewPart view) {
|
||||
fView = view;
|
||||
}
|
||||
|
||||
public void run(IAction action) {
|
||||
VMCacheManager.getVMCacheManager().registerCache(getContext(), createCache());
|
||||
}
|
||||
|
||||
public void selectionChanged(IAction action, ISelection selection) {
|
||||
}
|
||||
|
||||
protected abstract Object getContext();
|
||||
|
||||
protected abstract VMCache createCache();
|
||||
|
||||
}
|
|
@ -3,4 +3,5 @@ output.. = bin/
|
|||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.xml,\
|
||||
plugin.properties,\
|
||||
about.html
|
||||
|
|
|
@ -90,6 +90,10 @@ public class DefaultDsfExecutor extends ScheduledThreadPoolExecutor
|
|||
return Thread.currentThread().equals( ((DsfThreadFactory)getThreadFactory()).fThread );
|
||||
}
|
||||
|
||||
protected String getName() {
|
||||
return fName;
|
||||
}
|
||||
|
||||
static void logException(Throwable t) {
|
||||
DsfPlugin plugin = DsfPlugin.getDefault();
|
||||
if (plugin == null) return;
|
||||
|
@ -114,14 +118,14 @@ public class DefaultDsfExecutor extends ScheduledThreadPoolExecutor
|
|||
//
|
||||
// Utilities used for tracing.
|
||||
//
|
||||
static boolean DEBUG_EXECUTOR = false;
|
||||
static String DEBUG_EXECUTOR_NAME = "";
|
||||
static boolean ASSERTIONS_ENABLED = false;
|
||||
protected static boolean DEBUG_EXECUTOR = false;
|
||||
protected static String DEBUG_EXECUTOR_NAME = ""; //$NON-NLS-1$
|
||||
protected static boolean ASSERTIONS_ENABLED = false;
|
||||
static {
|
||||
DEBUG_EXECUTOR = DsfPlugin.DEBUG && "true".equals( //$NON-NLS-1$
|
||||
Platform.getDebugOption("org.eclipse.dd.dsf/debug/executor")); //$NON-NLS-1$
|
||||
DEBUG_EXECUTOR_NAME = DsfPlugin.DEBUG
|
||||
? Platform.getDebugOption("org.eclipse.dd.dsf/debug/executorName") : ""; //$NON-NLS-1$
|
||||
? Platform.getDebugOption("org.eclipse.dd.dsf/debug/executorName") : ""; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
assert (ASSERTIONS_ENABLED = true) == true;
|
||||
}
|
||||
|
||||
|
@ -253,9 +257,7 @@ public class DefaultDsfExecutor extends ScheduledThreadPoolExecutor
|
|||
fRunnable = runnable;
|
||||
|
||||
// Check if executable wasn't executed already.
|
||||
if (fRunnable instanceof DsfExecutable &&
|
||||
DEBUG_EXECUTOR && ("".equals(DEBUG_EXECUTOR_NAME) || fName.equals(DEBUG_EXECUTOR_NAME))) //$NON-NLS-1$
|
||||
{
|
||||
if (DEBUG_EXECUTOR && fRunnable instanceof DsfExecutable) {
|
||||
assert !((DsfExecutable)fRunnable).getSubmitted() : "Executable was previously executed."; //$NON-NLS-1$
|
||||
((DsfExecutable)fRunnable).setSubmitted();
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ public class DsfExecutable {
|
|||
* Flag indicating whether this executable was ever executed by an
|
||||
* executor. Used for tracing only.
|
||||
*/
|
||||
private boolean fSubmitted = false;
|
||||
private volatile boolean fSubmitted = false;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public DsfExecutable() {
|
||||
|
@ -96,7 +96,7 @@ public class DsfExecutable {
|
|||
}
|
||||
}
|
||||
|
||||
boolean getSubmitted() {
|
||||
public boolean getSubmitted() {
|
||||
return fSubmitted;
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ public class DsfExecutable {
|
|||
* Marks this executable to indicate that it has been executed by the
|
||||
* executor. To be invoked only by DsfExecutor.
|
||||
*/
|
||||
void setSubmitted() {
|
||||
public void setSubmitted() {
|
||||
fSubmitted = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@ package org.eclipse.dd.dsf.concurrent;
|
|||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.dd.dsf.DsfPlugin;
|
||||
|
||||
/**
|
||||
* Executor that executes a runnable immediately as it is submitted. This
|
||||
* executor is useful for clients that need to create <code>RequestMonitor</code>
|
||||
|
@ -20,6 +23,16 @@ import java.util.concurrent.Executor;
|
|||
*/
|
||||
public class ImmediateExecutor implements Executor {
|
||||
|
||||
/**
|
||||
* Debug flag used for tracking runnables that were never executed,
|
||||
* or executed multiple times.
|
||||
*/
|
||||
protected static boolean DEBUG_EXECUTOR = false;
|
||||
static {
|
||||
DEBUG_EXECUTOR = DsfPlugin.DEBUG && "true".equals( //$NON-NLS-1$
|
||||
Platform.getDebugOption("org.eclipse.dd.dsf/debug/executor")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private static ImmediateExecutor fInstance = new ImmediateExecutor();
|
||||
|
||||
/**
|
||||
|
@ -36,6 +49,11 @@ public class ImmediateExecutor implements Executor {
|
|||
}
|
||||
|
||||
public void execute(Runnable command) {
|
||||
// Check if executable wasn't executed already.
|
||||
if (DEBUG_EXECUTOR && command instanceof DsfExecutable) {
|
||||
assert !((DsfExecutable)command).getSubmitted() : "Executable was previously executed."; //$NON-NLS-1$
|
||||
((DsfExecutable)command).setSubmitted();
|
||||
}
|
||||
command.run();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue