From 91d23282637427b8895cefcc3e84cffde2feb21c Mon Sep 17 00:00:00 2001 From: Pawel Piech Date: Fri, 10 Nov 2006 00:18:15 +0000 Subject: [PATCH] Finished refactoring view model adapter, cleaned up warnings, added column support (bugs 159161, 159679, 161981). --- .../META-INF/MANIFEST.MF | 4 +- .../dd/dsf/debug/ui/DsfDebugUIPlugin.java | 2 +- .../DebugViewSelectionRootLayoutNode.java | 4 +- .../LaunchViewModelProvider.java} | 16 +- .../{ => launch}/StackFramesLayoutNode.java | 28 +-- .../StandardLaunchRootLayoutNode.java | 4 +- .../StandardProcessLayoutNode.java | 14 +- .../register/MessagesForRegisterVM.java | 20 ++ .../register/RegisterColumnPresentation.java | 72 ++++++ .../RegisterGroupLayoutNode.java | 54 ++-- .../{ => register}/RegisterLayoutNode.java | 22 +- .../register/RegisterVMProvider.java | 46 ++++ .../ui/viewmodel/register/messages.properties | 3 + .../dsf/ui/viewmodel/AbstractVMAdapter.java | 71 ++++-- .../ui/viewmodel/AbstractVMLayoutNode.java | 7 +- .../viewmodel/AbstractVMRootLayoutNode.java | 2 +- .../ui/viewmodel/DMContextVMLayoutNode.java | 162 ++++++++++-- .../dd/dsf/ui/viewmodel/IVMLayoutNode.java | 7 +- .../dd/dsf/ui/viewmodel/VMProvider.java | 237 +++++++++++------- .../dd/dsf/service/DsfServicesTracker.java | 17 +- 20 files changed, 573 insertions(+), 219 deletions(-) rename plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/{DebugViewModelProvider.java => launch/LaunchViewModelProvider.java} (84%) rename plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/{ => launch}/StackFramesLayoutNode.java (94%) rename plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/{ => launch}/StandardLaunchRootLayoutNode.java (97%) rename plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/{ => launch}/StandardProcessLayoutNode.java (95%) create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/MessagesForRegisterVM.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java rename plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/{ => register}/RegisterGroupLayoutNode.java (65%) rename plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/{ => register}/RegisterLayoutNode.java (86%) create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/messages.properties diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.dd.dsf.debug.ui/META-INF/MANIFEST.MF index e5261d510a5..28fe51ed363 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.dd.dsf.debug.ui/META-INF/MANIFEST.MF @@ -17,5 +17,7 @@ Require-Bundle: org.eclipse.ui, org.eclipse.dd.dsf.debug Eclipse-LazyStart: true Export-Package: - org.eclipse.dd.dsf.debug.ui.viewmodel + org.eclipse.dd.dsf.debug.ui.viewmodel, + org.eclipse.dd.dsf.debug.ui.viewmodel.register, + org.eclipse.dd.dsf.debug.ui.viewmodel.launch Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/DsfDebugUIPlugin.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/DsfDebugUIPlugin.java index 528fa8d8359..f38e404fc17 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/DsfDebugUIPlugin.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/DsfDebugUIPlugin.java @@ -10,7 +10,7 @@ import org.osgi.framework.BundleContext; public class DsfDebugUIPlugin extends AbstractUIPlugin { // The plug-in ID - public static final String PLUGIN_ID = "org.eclipse.dd.dsf.debug.ui"; + public static final String PLUGIN_ID = "org.eclipse.dd.dsf.debug.ui"; //$NON-NLS-1$ // The shared instance private static DsfDebugUIPlugin plugin; diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/DebugViewSelectionRootLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/DebugViewSelectionRootLayoutNode.java index 9a2722ffd32..18d00b8d4b4 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/DebugViewSelectionRootLayoutNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/DebugViewSelectionRootLayoutNode.java @@ -47,9 +47,9 @@ public class DebugViewSelectionRootLayoutNode extends AbstractVMRootLayoutNode } @Override - public void sessionDispose() { + public void dispose() { DebugUITools.getDebugContextManager().removeDebugContextListener(this); - super.sessionDispose(); + super.dispose(); } /** diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/DebugViewModelProvider.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/LaunchViewModelProvider.java similarity index 84% rename from plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/DebugViewModelProvider.java rename to plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/LaunchViewModelProvider.java index a3be1415e88..1999f647def 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/DebugViewModelProvider.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/LaunchViewModelProvider.java @@ -8,10 +8,11 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.dd.dsf.debug.ui.viewmodel; +package org.eclipse.dd.dsf.debug.ui.viewmodel.launch; import org.eclipse.dd.dsf.concurrent.DsfRunnable; import org.eclipse.dd.dsf.concurrent.GetDataDone; +import org.eclipse.dd.dsf.concurrent.ThreadSafe; import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode; import org.eclipse.dd.dsf.ui.viewmodel.VMProvider; @@ -25,11 +26,11 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta; * */ @SuppressWarnings("restriction") -public class DebugViewModelProvider extends VMProvider +public class LaunchViewModelProvider extends VMProvider implements IDebugEventSetListener { - - public DebugViewModelProvider(DsfSession session, IVMRootLayoutNode rootLayoutNode) { + @ThreadSafe + public LaunchViewModelProvider(DsfSession session, IVMRootLayoutNode rootLayoutNode) { super(session, rootLayoutNode); DebugPlugin.getDefault().addDebugEventListener(this); } @@ -50,7 +51,7 @@ public class DebugViewModelProvider extends VMProvider * Just like with DMC events, go through all the layout nodes and * collect delta information for the received event. */ - if (getRootLayoutNode().hasDeltaFlags(event)) { + if (getRootLayoutNode() != null && getRootLayoutNode().hasDeltaFlags(event)) { getRootLayoutNode().createDelta(event, new GetDataDone() { public void run() { if (getStatus().isOK()) { @@ -61,10 +62,9 @@ public class DebugViewModelProvider extends VMProvider } } - @Override - public void sessionDispose() { + public void dispose() { DebugPlugin.getDefault().removeDebugEventListener(this); - super.sessionDispose(); + super.dispose(); } } diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/StackFramesLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StackFramesLayoutNode.java similarity index 94% rename from plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/StackFramesLayoutNode.java rename to plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StackFramesLayoutNode.java index 57d77adfd42..91458bd6894 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/StackFramesLayoutNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StackFramesLayoutNode.java @@ -8,7 +8,7 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.dd.dsf.debug.ui.viewmodel; +package org.eclipse.dd.dsf.debug.ui.viewmodel.launch; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.dd.dsf.concurrent.Done; @@ -34,7 +34,7 @@ import org.eclipse.jface.resource.ImageDescriptor; @SuppressWarnings("restriction") -public class StackFramesLayoutNode extends DMContextVMLayoutNode { +public class StackFramesLayoutNode extends DMContextVMLayoutNode { public IVMContext[] fCachedOldFramesVMCs; @@ -72,7 +72,7 @@ public class StackFramesLayoutNode extends DMContextVMLayoutNode { if (getServicesTracker().getService(IRunControl.class).isStepping(execDmc)) { getElementsTopStackFrameOnly(parentVmc, done); } else { - propagateError(getExecutor(), done, "Failed retrieving stack frames"); + propagateError(getExecutor(), done, "Failed retrieving stack frames"); //$NON-NLS-1$ } return; } @@ -95,7 +95,7 @@ public class StackFramesLayoutNode extends DMContextVMLayoutNode { getServicesTracker().getService(IStack.class).getTopFrame( execDmc, new GetDataDone() { public void run() { - if (propagateError(getExecutor(), done, "Failed retrieving top stack frame")) return; + if (propagateError(getExecutor(), done, "Failed retrieving top stack frame")) return; //$NON-NLS-1$ IVMContext topFrameVmc = new DMContextVMContext(parentVmc, getData()); // If there are old frames cached, use them and only substitute the top frame object. Otherwise, create @@ -110,7 +110,7 @@ public class StackFramesLayoutNode extends DMContextVMLayoutNode { }}); } - public void retrieveLabel(IVMContext vmc, final ILabelRequestMonitor result) { + public void retrieveLabel(IVMContext vmc, final ILabelRequestMonitor result, String[] columns) { final IExecutionDMContext execDmc = findDmcInVmc(vmc, IExecutionDMContext.class); if (execDmc == null || getServicesTracker().getService(IStack.class) == null || getServicesTracker().getService(IRunControl.class) == null) { result.done(); @@ -142,9 +142,9 @@ public class StackFramesLayoutNode extends DMContextVMLayoutNode { // If failed set a dummy label, and only propagate the // error if we are not stepping, since that would be a // common cause of failure. - result.setLabels(new String[] { "..." }); + result.setLabels(new String[] { "..." }); //$NON-NLS-1$ if (!getServicesTracker().getService(IRunControl.class).isStepping(execDmc)) { - MultiStatus status = new MultiStatus(DsfDebugUIPlugin.PLUGIN_ID, 0, "Failed to retrieve stack frame label", null); + MultiStatus status = new MultiStatus(DsfDebugUIPlugin.PLUGIN_ID, 0, "Failed to retrieve stack frame label", null); //$NON-NLS-1$ status.add(getStatus()); result.setStatus(status); } @@ -164,22 +164,22 @@ public class StackFramesLayoutNode extends DMContextVMLayoutNode { // Add the function name if (getData().getFunction() != null && getData().getFunction().length() != 0) { - label.append(" "); + label.append(" "); //$NON-NLS-1$ label.append(getData().getFunction()); - label.append("()"); + label.append("()"); //$NON-NLS-1$ } // Add full file name if (getData().getFile() != null && getData().getFile().length() != 0) { - label.append(" at "); + label.append(" at "); //$NON-NLS-1$ label.append(getData().getFile()); } // Add line number if (getData().getLine() >= 0) { - label.append(":"); + label.append(":"); //$NON-NLS-1$ label.append(getData().getLine()); - label.append(" "); + label.append(" "); //$NON-NLS-1$ } // Add the address @@ -191,7 +191,7 @@ public class StackFramesLayoutNode extends DMContextVMLayoutNode { }}); } - public boolean hasDeltaFlagsForDMEvent(IDMEvent e) { + public boolean hasDeltaFlagsForDMEvent(IDMEvent e) { // This node generates delta if the timers have changed, or if the // label has changed. return e instanceof IRunControl.ISuspendedDMEvent || @@ -200,7 +200,7 @@ public class StackFramesLayoutNode extends DMContextVMLayoutNode { super.hasDeltaFlagsForDMEvent(e); } - public void buildDeltaForDMEvent(final IDMEvent e, final VMDelta parent, final Done done) { + public void buildDeltaForDMEvent(final IDMEvent e, final VMDelta parent, final Done done) { if (getServicesTracker().getService(IStack.class) == null || getServicesTracker().getService(IRunControl.class) == null) { // Required services have not initialized yet. Ignore the event. super.buildDeltaForDMEvent(e, parent, done); diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/StandardLaunchRootLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardLaunchRootLayoutNode.java similarity index 97% rename from plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/StandardLaunchRootLayoutNode.java rename to plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardLaunchRootLayoutNode.java index ef6add3693c..ac19bf205f3 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/StandardLaunchRootLayoutNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardLaunchRootLayoutNode.java @@ -8,7 +8,7 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.dd.dsf.debug.ui.viewmodel; +package org.eclipse.dd.dsf.debug.ui.viewmodel.launch; import org.eclipse.dd.dsf.concurrent.DoneCollector; import org.eclipse.dd.dsf.concurrent.DsfExecutor; @@ -87,7 +87,7 @@ public class StandardLaunchRootLayoutNode extends AbstractVMRootLayoutNode */ final DoneCollector doneCollector = new DoneCollector(getExecutor()) { public void run() { - if (propagateError(getExecutor(), done, "Failed to generate child deltas.")) return; + if (propagateError(getExecutor(), done, "Failed to generate child deltas.")) return; //$NON-NLS-1$ done.setData(delta); getExecutor().execute(done); } diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/StandardProcessLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardProcessLayoutNode.java similarity index 95% rename from plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/StandardProcessLayoutNode.java rename to plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardProcessLayoutNode.java index 5fe46857a7c..652034f9416 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/StandardProcessLayoutNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardProcessLayoutNode.java @@ -8,7 +8,7 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.dd.dsf.debug.ui.viewmodel; +package org.eclipse.dd.dsf.debug.ui.viewmodel.launch; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; @@ -54,9 +54,9 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode { } public IVMContext getParent() { return fParentVmc; } - public IVMLayoutNode getLayoutNode() { return StandardProcessLayoutNode.this; } - public Object getAdapter(Class adapter) { return fProcess.getAdapter(adapter); } - public String toString() { return "IProcess " + fProcess.toString(); } + public IVMLayoutNode getLayoutNode() { return StandardProcessLayoutNode.this; } + @SuppressWarnings("unchecked") public Object getAdapter(Class adapter) { return fProcess.getAdapter(adapter); } + public String toString() { return "IProcess " + fProcess.toString(); } //$NON-NLS-1$ public String getAttribute(String key) { return fProcess.getAttribute(key); } public int getExitValue() throws DebugException { return fProcess.getExitValue(); } @@ -85,7 +85,7 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode { * layout is misconfigured. */ assert false; - done.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Can't get list of processes, because there is no launch.", null)); + done.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Can't get list of processes, because there is no launch.", null)); //$NON-NLS-1$ getExecutor().execute(done); return; } @@ -108,7 +108,7 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode { ILaunch launch = findLaunch(parentVmc); if (launch == null) { assert false; - done.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Can't get list of processes, because there is no launch.", null)); + done.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Can't get list of processes, because there is no launch.", null)); //$NON-NLS-1$ getExecutor().execute(done); return; } @@ -118,7 +118,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 retrieveLabel(IVMContext vmc, ILabelRequestMonitor result) { + public void retrieveLabel(IVMContext vmc, ILabelRequestMonitor result, String[] columns) { /* * The implementation of IAdapterFactory that uses this node should not diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/MessagesForRegisterVM.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/MessagesForRegisterVM.java new file mode 100644 index 00000000000..c0ef4c28346 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/MessagesForRegisterVM.java @@ -0,0 +1,20 @@ +package org.eclipse.dd.dsf.debug.ui.viewmodel.register; + +import org.eclipse.osgi.util.NLS; + +public class MessagesForRegisterVM extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.dd.dsf.debug.ui.viewmodel.register.messages"; //$NON-NLS-1$ + + public static String RegisterColumnPresentation_description; + + public static String RegisterColumnPresentation_name; + + public static String RegisterColumnPresentation_value; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, MessagesForRegisterVM.class); + } + + private MessagesForRegisterVM() { + } +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java new file mode 100644 index 00000000000..c259d78b3a1 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * 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.debug.ui.viewmodel.register; + +import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin; +import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation; +import org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext; +import org.eclipse.jface.resource.ImageDescriptor; + +/** + * + */ +@SuppressWarnings("restriction") +public class RegisterColumnPresentation implements IColumnPresentation { + + public static final String ID = DsfDebugUIPlugin.PLUGIN_ID + ".REGISTERS_COLUMN_PRESENTATION_ID"; //$NON-NLS-1$ + public static final String COL_NAME = ID + ".COL_NAME"; //$NON-NLS-1$ + public static final String COL_VALUE = ID + ".COL_VALUE"; //$NON-NLS-1$ + public static final String COL_DESCRIPTION = ID + ".COL_DESCRIPTION"; //$NON-NLS-1$ + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#init(org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext) + public void init(IPresentationContext context) {} + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#dispose() + public void dispose() {} + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getAvailableColumns() + public String[] getAvailableColumns() { + return new String[] { COL_NAME, COL_VALUE, COL_DESCRIPTION }; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getHeader(java.lang.String) + public String getHeader(String id) { + if (COL_NAME.equals(id)) { + return MessagesForRegisterVM.RegisterColumnPresentation_name; + } else if (COL_VALUE.equals(id)) { + return MessagesForRegisterVM.RegisterColumnPresentation_value; + } else if (COL_DESCRIPTION.equals(id)) { + return MessagesForRegisterVM.RegisterColumnPresentation_description; + } + return null; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getId() + public String getId() { + return ID; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getImageDescriptor(java.lang.String) + public ImageDescriptor getImageDescriptor(String id) { + return null; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getInitialColumns() + public String[] getInitialColumns() { + return new String[] { COL_NAME, COL_VALUE }; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#isOptional() + public boolean isOptional() { + return true; + } + +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/RegisterGroupLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterGroupLayoutNode.java similarity index 65% rename from plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/RegisterGroupLayoutNode.java rename to plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterGroupLayoutNode.java index 3701e2f8e41..ef96b6ac340 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/RegisterGroupLayoutNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterGroupLayoutNode.java @@ -8,24 +8,26 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.dd.dsf.debug.ui.viewmodel; +package org.eclipse.dd.dsf.debug.ui.viewmodel.register; import org.eclipse.dd.dsf.concurrent.Done; import org.eclipse.dd.dsf.concurrent.GetDataDone; +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.IRegisters.IRegisterGroupDMContext; import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupData; import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; import org.eclipse.dd.dsf.service.DsfSession; -import org.eclipse.dd.dsf.service.IDsfService; import org.eclipse.dd.dsf.ui.viewmodel.DMContextVMLayoutNode; import org.eclipse.dd.dsf.ui.viewmodel.IVMContext; import org.eclipse.dd.dsf.ui.viewmodel.VMDelta; -import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.RGB; @SuppressWarnings("restriction") -public class RegisterGroupLayoutNode extends DMContextVMLayoutNode { +public class RegisterGroupLayoutNode extends DMContextVMLayoutNode { public RegisterGroupLayoutNode(DsfSession session) { super(session, IRegisters.IRegisterGroupDMContext.class); @@ -43,7 +45,7 @@ public class RegisterGroupLayoutNode extends DMContextVMLayoutNode { getServicesTracker().getService(IRegisters.class).getRegisterGroups( execDmc, null, new GetDataDone() { public void run() { - if (propagateError(getExecutor(), done, "Failed to retrieve register groups")) return; + if (propagateError(getExecutor(), done, "Failed to retrieve register groups")) return; //$NON-NLS-1$ done.setData(getData().length != 0); getExecutor().execute(done); }}); @@ -61,43 +63,31 @@ public class RegisterGroupLayoutNode extends DMContextVMLayoutNode { getServicesTracker().getService(IRegisters.class).getRegisterGroups( execDmc, null, new GetDataDone() { public void run() { - if (propagateError(getExecutor(), done, "Failed to retrieve register groups")) return; + if (propagateError(getExecutor(), done, "Failed to retrieve register groups")) return; //$NON-NLS-1$ done.setData(dmcs2vmcs(parentVmc, getData())); getExecutor().execute(done); }}); } - public void retrieveLabel( final IVMContext vmc , final ILabelRequestMonitor result ) { - if (getServicesTracker().getService(IRegisters.class) == null) { - result.done(); - return; - } - - final IRegisterGroupDMContext registerGroupDmc = (IRegisterGroupDMContext) ( (DMContextVMContext) vmc ).getDMC() ; - - getServicesTracker().getService( IRegisters.class ).getModelData( - registerGroupDmc, - new GetDataDone() { - public void run() { - if (!getStatus().isOK()) { - // Some error conditions are expected. - assert getStatus().getCode() == IDsfService.INVALID_STATE || getStatus().getCode() == IDsfService.INVALID_HANDLE : getStatus().toString(); - result.setLabels( new String[] { "...", "...", "..." } ) ; - } else { - result.setLabels(new String[] { getData().getName(), "", getData().getDescription() }); //$NON-NLS-1$ - } - result.done(); - return; - } - } - ) ; + @Override + protected void fillColumnLabel(IDMContext dmContext, IRegisterGroupData dmData, + String columnId, int idx, String[] text, ImageDescriptor[] image, + FontData[] fontData, RGB[] foreground, RGB[] background) + { + if (RegisterColumnPresentation.COL_NAME.equals(columnId)) { + text[idx] = dmData.getName(); + } else if (RegisterColumnPresentation.COL_VALUE.equals(columnId)) { + text[idx] = ""; //$NON-NLS-1$ + } else if (RegisterColumnPresentation.COL_DESCRIPTION.equals(columnId)) { + text[idx] = dmData.getDescription(); + } } - public boolean hasDeltaFlagsForDMEvent(IDMEvent e) { + public boolean hasDeltaFlagsForDMEvent(IDMEvent e) { return super.hasDeltaFlagsForDMEvent(e); } - public void buildDeltaForDMEvent(final IDMEvent e, final VMDelta parent, final Done done) { + public void buildDeltaForDMEvent(final IDMEvent e, final VMDelta parent, final Done done) { super.buildDeltaForDMEvent(e, parent, done); } } diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/RegisterLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterLayoutNode.java similarity index 86% rename from plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/RegisterLayoutNode.java rename to plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterLayoutNode.java index 86b9ae992db..dce21df6358 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/RegisterLayoutNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterLayoutNode.java @@ -8,7 +8,7 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.dd.dsf.debug.ui.viewmodel; +package org.eclipse.dd.dsf.debug.ui.viewmodel.register; import org.eclipse.dd.dsf.concurrent.Done; import org.eclipse.dd.dsf.concurrent.GetDataDone; @@ -27,7 +27,7 @@ import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor; import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta; @SuppressWarnings("restriction") -public class RegisterLayoutNode extends DMContextVMLayoutNode { +public class RegisterLayoutNode extends DMContextVMLayoutNode { public IVMContext[] fCachedRegisterVMCs; @@ -48,7 +48,7 @@ public class RegisterLayoutNode extends DMContextVMLayoutNode { registerGroupDmc, new GetDataDone() { public void run() { - if (propagateError(getExecutor(), done, "Failed to retrieve registers")) return; + if (propagateError(getExecutor(), done, "Failed to retrieve registers")) return; //$NON-NLS-1$ done.setData(getData().length != 0); getExecutor().execute(done); } @@ -66,13 +66,13 @@ public class RegisterLayoutNode extends DMContextVMLayoutNode { getServicesTracker().getService( IRegisters.class ).getRegisters( execDmc, new GetDataDone() { public void run() { - if (propagateError(getExecutor(), done, "Failed to retrieve registers")) return; + if (propagateError(getExecutor(), done, "Failed to retrieve registers")) return; //$NON-NLS-1$ done.setData( dmcs2vmcs( parentVmc, getData()) ); getExecutor().execute(done); }}); } - public void retrieveLabel( final IVMContext vmc , final ILabelRequestMonitor result ) { + public void retrieveLabel(final IVMContext vmc , final ILabelRequestMonitor result, String[] columns) { if ( getServicesTracker().getService( IRegisters.class ) == null ) { result.done(); @@ -88,11 +88,11 @@ public class RegisterLayoutNode extends DMContextVMLayoutNode { if ( !getStatus().isOK() ) { assert getStatus().getCode() == IDsfService.INVALID_STATE || getStatus().getCode() == IDsfService.INVALID_HANDLE : getStatus().toString(); // Some error conditions are expected. - result.setLabels( new String[] { "...", "...", "..." } ) ; + result.setLabels( new String[] { "...", "...", "..." } ) ; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } else { String size = getData().getDescription(); String value = getData().getHexValue(); - if ("".equals(size)) { + if ("".equals(size)) { //$NON-NLS-1$ if ( value.contains( "uint64" ) ) { //$NON-NLS-1$ size = "64 bit register" ; //$NON-NLS-1$ } else if ( value.contains( "v4_float" ) ) { //$NON-NLS-1$ @@ -110,17 +110,19 @@ public class RegisterLayoutNode extends DMContextVMLayoutNode { ) ; } - public boolean hasDeltaFlagsForDMEvent( IDMEvent e ) { + public boolean hasDeltaFlagsForDMEvent( IDMEvent e ) { return (e instanceof IRunControl.ISuspendedDMEvent) || super.hasDeltaFlagsForDMEvent(e) ; } - public void buildDeltaForDMEvent( final IDMEvent e, final VMDelta parent, final Done done ) { + public void buildDeltaForDMEvent( final IDMEvent e, final VMDelta parent, final Done done ) { if (e instanceof IRunControl.ISuspendedDMEvent) { // Create a delta that the whole register group has changed. parent.addFlags(IModelDelta.CONTENT); } if (e instanceof IRegisters.IRegisterChangedDMEvent) { - parent.addNode(new DMContextVMContext(parent.getVMC(), e.getDMContext()), IModelDelta.STATE); + parent.addNode( + new DMContextVMContext(parent.getVMC(), ((IRegisters.IRegisterChangedDMEvent)e).getDMContext()), + IModelDelta.STATE); } super.buildDeltaForDMEvent(e, parent, done); diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java new file mode 100644 index 00000000000..24e9527c19a --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java @@ -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.debug.ui.viewmodel.register; + +import org.eclipse.dd.dsf.debug.ui.viewmodel.DebugViewSelectionRootLayoutNode; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode; +import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode; +import org.eclipse.dd.dsf.ui.viewmodel.VMProvider; +import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation; +import org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext; + +/** + * + */ +@SuppressWarnings("restriction") +public class RegisterVMProvider extends VMProvider { + public RegisterVMProvider(DsfSession session, IPresentationContext context) { + super(session, null); + IVMRootLayoutNode debugViewSelection = new DebugViewSelectionRootLayoutNode( + getSession().getExecutor(), context.getPart().getSite().getWorkbenchWindow() ); + IVMLayoutNode registerGroupNode = new RegisterGroupLayoutNode(getSession()); + debugViewSelection.setChildNodes(new IVMLayoutNode[] { registerGroupNode }); + IVMLayoutNode registerNode = new RegisterLayoutNode(getSession()); + registerGroupNode.setChildNodes(new IVMLayoutNode[] { registerNode }); + setRootLayoutNode(debugViewSelection); + } + + @Override + public IColumnPresentation createColumnPresentation(Object element) { + return new RegisterColumnPresentation(); + } + + @Override + public String getColumnPresentationId(Object element) { + return RegisterColumnPresentation.ID; + } +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/messages.properties b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/messages.properties new file mode 100644 index 00000000000..5b6ea684c42 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/messages.properties @@ -0,0 +1,3 @@ +RegisterColumnPresentation_name=Name +RegisterColumnPresentation_value=Value +RegisterColumnPresentation_description=Description diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java index b136046b82c..43caaf6a69f 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.dd.dsf.ui.viewmodel; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.RejectedExecutionException; @@ -25,6 +26,8 @@ import org.eclipse.dd.dsf.ui.DsfUIPlugin; import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousContentAdapter; import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapter; import org.eclipse.debug.internal.ui.viewers.provisional.IChildrenRequestMonitor; +import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation; +import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentationFactoryAdapter; import org.eclipse.debug.internal.ui.viewers.provisional.IContainerRequestMonitor; import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor; import org.eclipse.debug.internal.ui.viewers.provisional.IModelProxy; @@ -39,37 +42,46 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext; abstract public class AbstractVMAdapter implements IAsynchronousLabelAdapter, IAsynchronousContentAdapter, - IModelProxyFactoryAdapter + IModelProxyFactoryAdapter, + IColumnPresentationFactoryAdapter { private final DsfSession fSession; @ConfinedToDsfExecutor("getSession().getExecutor()") - private Map fViewModelProviders = - new HashMap(); + private final Map fViewModelProviders = + Collections.synchronizedMap( new HashMap() ); + /** + * Constructor for the View Model session. It is tempting to have the + * adapter register itself here with the session as the model adapter, but + * that would mean that the adapter might get accessed on another thread + * even before the deriving class is fully constructed. So it it better + * to have the owner of this object register it with the session. + * @param session + */ public AbstractVMAdapter(DsfSession session) { fSession = session; - // regieterModelAdapter() is thread safe, so we're OK calling it from here. - fSession.registerModelAdapter(IAsynchronousLabelAdapter.class, this); - fSession.registerModelAdapter(IAsynchronousContentAdapter.class, this); - fSession.registerModelAdapter(IModelProxyFactoryAdapter.class, this); } - @ConfinedToDsfExecutor("getSession().getExecutor()") + @ThreadSafe abstract protected VMProvider createViewModelProvider(IPresentationContext context); protected DsfSession getSession() { return fSession; } - @ConfinedToDsfExecutor("getSession().getExecutor()") + @ThreadSafe private VMProvider getViewModelProvider(IPresentationContext context) { - VMProvider provider = fViewModelProviders.get(context); - if (provider == null) { - provider = createViewModelProvider(context); - if (provider != null) { - fViewModelProviders.put(context, provider); + assert DsfSession.isSessionActive(getSession().getId()); + + synchronized(fViewModelProviders) { + VMProvider provider = fViewModelProviders.get(context); + if (provider == null) { + provider = createViewModelProvider(context); + if (provider != null) { + fViewModelProviders.put(context, provider); + } } + return provider; } - return provider; } @ConfinedToDsfExecutor("getSession().getExecutor()") @@ -80,12 +92,8 @@ abstract public class AbstractVMAdapter public void dispose() { assert getSession().getExecutor().isInExecutorThread(); - fSession.unregisterModelAdapter(IAsynchronousLabelAdapter.class); - fSession.unregisterModelAdapter(IAsynchronousContentAdapter.class); - fSession.unregisterModelAdapter(IModelProxyFactoryAdapter.class); - for (VMProvider provider : fViewModelProviders.values()) { - provider.sessionDispose(); + provider.dispose(); } fViewModelProviders.clear(); } @@ -101,7 +109,7 @@ abstract public class AbstractVMAdapter result.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "No model provider for object: " + object.toString(), null)); //$NON-NLS-1$ result.done(); } - provider.retrieveLabel(object, result); + provider.retrieveLabel(object, result, context.getColumns()); } @Override public String toString() { return "Switch to dispatch thread to execute retrieveLabel()"; } //$NON-NLS-1$ @@ -161,9 +169,28 @@ abstract public class AbstractVMAdapter * create a proxy for the root element of the tree. */ VMProvider provider = getViewModelProvider(context); - if (provider != null && element.equals(provider.getRootLayoutNode().getRootVMC().getInputObject())) { + if (provider != null && + provider.getRootLayoutNode() != null && + element.equals(provider.getRootLayoutNode().getRootVMC().getInputObject())) + { return provider.getModelProxy(); } return null; } + + public String getColumnPresentationId(IPresentationContext context, Object element) { + VMProvider provider = getViewModelProvider(context); + if (provider != null) { + return provider.getColumnPresentationId(element); + } + return null; + } + + public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) { + VMProvider provider = getViewModelProvider(context); + if (provider != null) { + return provider.createColumnPresentation(element); + } + return null; + } } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMLayoutNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMLayoutNode.java index 634f03c58b3..562f867f2d6 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMLayoutNode.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMLayoutNode.java @@ -51,9 +51,9 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode { return fChildNodes; } - public void sessionDispose() { + public void dispose() { for (IVMLayoutNode childNode : getChildLayoutNodes()) { - childNode.sessionDispose(); + childNode.dispose(); } } @@ -122,7 +122,7 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode { } }); } - + /** * Convenience method that returns the child layout nodes which return * true to the hasDeltaFlags() test for the given @@ -165,5 +165,4 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode { result.done(); } - } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMRootLayoutNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMRootLayoutNode.java index ab4bbc43d40..baacc1cfc7c 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMRootLayoutNode.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMRootLayoutNode.java @@ -88,7 +88,7 @@ abstract public class AbstractVMRootLayoutNode extends AbstractVMLayoutNode impl * 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 retrieveLabel(IVMContext vmc, ILabelRequestMonitor result) { + public void retrieveLabel(IVMContext vmc, ILabelRequestMonitor result, String[] columns) { result.done(); } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DMContextVMLayoutNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DMContextVMLayoutNode.java index 122209c834a..005aef1da0f 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DMContextVMLayoutNode.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DMContextVMLayoutNode.java @@ -10,17 +10,29 @@ *******************************************************************************/ package org.eclipse.dd.dsf.ui.viewmodel; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.dd.dsf.concurrent.Done; import org.eclipse.dd.dsf.concurrent.DoneCollector; +import org.eclipse.dd.dsf.concurrent.GetDataDone; 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.IDMData; import org.eclipse.dd.dsf.datamodel.IDMEvent; +import org.eclipse.dd.dsf.datamodel.IDMService; 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.IVMRootLayoutNode.IRootVMC; +import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapter; +import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentationFactoryAdapter; +import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor; import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.RGB; /** @@ -30,7 +42,7 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta; * are of the same class type. */ @SuppressWarnings("restriction") -abstract public class DMContextVMLayoutNode extends AbstractVMLayoutNode { +abstract public class DMContextVMLayoutNode extends AbstractVMLayoutNode { /** * IVMContext implementation used for this schema node. @@ -38,25 +50,33 @@ abstract public class DMContextVMLayoutNode extends AbstractVMLayoutNode { @Immutable public class DMContextVMContext implements IVMContext { private final IVMContext fParent; - private final IDMContext fDmc; + private final IDMContext fDmc; - public DMContextVMContext(IVMContext parent, IDMContext dmc) { + public DMContextVMContext(IVMContext parent, IDMContext dmc) { fParent = parent; fDmc = dmc; } - public IDMContext getDMC() { return fDmc; } + public IDMContext getDMC() { return fDmc; } public IVMContext getParent() { return fParent; } public IVMLayoutNode getLayoutNode() { return DMContextVMLayoutNode.this; } + /** + * The IAdaptable implementation. If the adapter is the DM context, + * return the context, otherwise delegate to IDMContext.getAdapter(). + */ @SuppressWarnings("unchecked") public Object getAdapter(Class adapter) { - return fDmc.getAdapter(adapter); + if (adapter.isInstance(fDmc)) { + return fDmc; + } else { + return fDmc.getAdapter(adapter); + } } public boolean equals(Object other) { - if (!(other instanceof DMContextVMContext)) return false; - DMContextVMContext otherVmc = (DMContextVMContext)other; + if (!(other instanceof DMContextVMLayoutNode.DMContextVMContext)) return false; + DMContextVMLayoutNode.DMContextVMContext otherVmc = (DMContextVMLayoutNode.DMContextVMContext)other; return DMContextVMLayoutNode.this.equals(otherVmc.getLayoutNode()) && fParent.equals(otherVmc.fParent) && fDmc.equals(otherVmc.fDmc); @@ -75,8 +95,13 @@ abstract public class DMContextVMLayoutNode extends AbstractVMLayoutNode { private DsfServicesTracker fServices; - /** Class type that the elements of this schema node are based on. */ - private Class> fDMCClassType; + /** + * 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> fDMCClassType; /** * Constructor initializes instance data, except for the child nodes. @@ -85,14 +110,12 @@ abstract public class DMContextVMLayoutNode extends AbstractVMLayoutNode { * @param dmcClassType * @see #setChildNodes(IVMLayoutNode[]) */ - public DMContextVMLayoutNode(DsfSession session, Class> dmcClassType) { + public DMContextVMLayoutNode(DsfSession session, Class> dmcClassType) { super(session.getExecutor()); fServices = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId()); fDMCClassType = dmcClassType; } - - - + /** * Returns the services tracker for sub-class use. */ @@ -100,6 +123,111 @@ abstract public class DMContextVMLayoutNode extends AbstractVMLayoutNode { return fServices; } + /** + * The default implementation of the retrieve label method. It acquires + * the service, using parameters in the DMC, then it fetches the model + * data from the service, and then it calls the protected method + * fillColumnLabel() for each column. The deriving classes should override + * this method if a different method of computing the label is needed. + * + * @see #fillColumnLabel(IDMData, String, int, String[], ImageDescriptor[], FontData[], RGB[], RGB[]) + */ + @SuppressWarnings("unchecked") + public void retrieveLabel(IVMContext vmc, final ILabelRequestMonitor result, final String[] columns) { + /* + * Extract the DMContext from the VMContext, see DMContextVMContext.getAdapter(). + * Since the VMContext is supplied by this node, the DMContext should never be null. + * Note: had to suppress type cast warnings here, because getAdapter() does not support + * generics, and even if it did, I'm not sure it would help. + */ + final IDMContext dmc = (IDMContext)(vmc).getAdapter(IDMContext.class); + if (dmc == null) { + assert false; + result.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Invalid VMC type", null)); //$NON-NLS-1$ + result.done(); + return; + } + + /* + * Get the instance of the service using the service filter in the DMContext + * If null it could mean that the service already shut down, and the view + * is holding stale elements which will be cleaned up shortly. + */ + IDMService dmService = (IDMService)getServicesTracker().getService(null, dmc.getServiceFilter()); + if (dmService == null) { + handleFailedRetrieveLabel(result); + return; + } + + dmService.getModelData( + dmc, + new GetDataDone() { + public void run() { + /* + * 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() || !getData().isValid()) { + assert getStatus().isOK() || + getStatus().getCode() != IDsfService.INTERNAL_ERROR || + getStatus().getCode() != IDsfService.NOT_SUPPORTED; + handleFailedRetrieveLabel(result); + return; + } + + /* + * If columns are configured, call the protected methods to + * fill in column values. + */ + String[] localColumns = columns; + if (localColumns == null) localColumns = new String[] { null }; + + String[] text = new String[localColumns.length]; + ImageDescriptor[] image = new ImageDescriptor[localColumns.length]; + FontData[] fontData = new FontData[localColumns.length]; + RGB[] foreground = new RGB[localColumns.length]; + RGB[] background = new RGB[localColumns.length]; + for (int i = 0; i < localColumns.length; i++) { + fillColumnLabel(dmc, getData(), localColumns[i], i, text, image, fontData, foreground, background); + } + result.setLabels(text); + result.setImageDescriptors(image); + result.setFontDatas(fontData); + result.setBackgrounds(background); + result.setForegrounds(foreground); + result.done(); + } + }); + } + + /** + * Fills in label information for given column. This method is intended to + * be overriden by deriving classes, to supply label information specific + * to the node.
+ * The implementation should fill in the correct value in each array at the + * given index. + * @param dmContext Data Model Context object for which the label is generated. + * @param dmData Data Model Data object retrieved from the model service. + * for the DM Context supplied to the retrieveLabel() call. + * @param columnId Name of the column to fill in, null if no columns specified. + * @param idx Index to fill in in the label arrays. + * @param text + * @param image + * @param fontData + * @param foreground + * @param background + * + * @see IAsynchronousLabelAdapter + * @see IColumnPresentationFactoryAdapter + */ + protected void fillColumnLabel(IDMContext dmContext, V dmData, String columnId, int idx, String[] text, + ImageDescriptor[] image, FontData[] fontData, RGB[] foreground, RGB[] background ) + { + text[idx] = ""; //$NON-NLS-1$ + } + @Override public boolean hasDeltaFlags(Object e) { if (e instanceof IDMEvent) { @@ -139,7 +267,7 @@ abstract public class DMContextVMLayoutNode extends AbstractVMLayoutNode { * behavior and generate a IModelDelta for every element in this schema * node. */ - IDMContext dmc = DMContexts.getAncestorOfType(e.getDMContext(), fDMCClassType); + IDMContext dmc = DMContexts.getAncestorOfType(e.getDMContext(), fDMCClassType); if (dmc != null) { IVMLayoutNode[] childNodes = getChildNodesWithDeltas(e); if (childNodes.length == 0) { @@ -180,7 +308,7 @@ abstract public class DMContextVMLayoutNode extends AbstractVMLayoutNode { * @param dmcs Array of DMC objects to build return array on. * @return Array of IVMContext objects. */ - protected IVMContext[] dmcs2vmcs(IVMContext parent, IDMContext[] dmcs) { + protected IVMContext[] dmcs2vmcs(IVMContext parent, IDMContext[] dmcs) { IVMContext[] vmContexts = new IVMContext[dmcs.length]; for (int i = 0; i < dmcs.length; i++) { vmContexts[i] = new DMContextVMContext(parent, dmcs[i]); @@ -216,8 +344,8 @@ abstract public class DMContextVMLayoutNode extends AbstractVMLayoutNode { return null; } - public void sessionDispose() { + public void dispose() { fServices.dispose(); - super.sessionDispose(); + super.dispose(); } } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMLayoutNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMLayoutNode.java index 982e95a6825..4a677ebb2c4 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMLayoutNode.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMLayoutNode.java @@ -15,6 +15,7 @@ import org.eclipse.dd.dsf.concurrent.Done; import org.eclipse.dd.dsf.concurrent.GetDataDone; import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor; import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta; +import org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext; /** * View model layout nodes are combined together into a tree, to collectively @@ -52,8 +53,10 @@ public interface IVMLayoutNode { * Retrieves the label for the given element. * @param vmc Element for which to retrieve label information. * @param result Monitor which accepts the data. + * @param columns Currently configured columns in view. + * @see IPresentationContext */ - public void retrieveLabel(IVMContext vmc, ILabelRequestMonitor result); + public void retrieveLabel(IVMContext vmc, ILabelRequestMonitor result, String[] columns); /** * Configures the child layout nodes for this node. @@ -89,5 +92,5 @@ public interface IVMLayoutNode { /** * Disposes the resources held by this node. */ - public void sessionDispose(); + public void dispose(); } \ No newline at end of file diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMProvider.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMProvider.java index 524c92dc0ba..9f26d2e1a40 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMProvider.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMProvider.java @@ -27,11 +27,13 @@ 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.debug.internal.ui.viewers.provisional.IChildrenRequestMonitor; +import org.eclipse.debug.internal.ui.viewers.provisional.IColumnEditorFactoryAdapter; +import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation; import org.eclipse.debug.internal.ui.viewers.provisional.IContainerRequestMonitor; import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor; -import org.eclipse.debug.internal.ui.viewers.provisional.IModelChangedListener; import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta; import org.eclipse.debug.internal.ui.viewers.provisional.IModelProxy; +import org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext; /** * View model provider implements the asynchronous view model functionality for @@ -52,83 +54,48 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IModelProxy; @SuppressWarnings("restriction") public class VMProvider { - @ThreadSafe - public class ModelProxy extends AbstractModelProxy { - /** - * Counter for whether the model proxy is currently installed in the viewer. - * Data model events are processed only if the model proxy is active. - */ - private int fProxyActive = 0; - - /** - * 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; } - }; - - public void installed() { - fProxyActive++; - } - - public void dispose() { - fProxyActive--; - super.dispose(); - } - - @Override - public void removeModelChangedListener(IModelChangedListener listener) { - // TODO Auto-generated method stub - super.removeModelChangedListener(listener); - } - - @Override - public void addModelChangedListener(IModelChangedListener listener) { - // TODO Auto-generated method stub - super.addModelChangedListener(listener); - } - - /** - * 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) { - if (fProxyActive <= 0) return; - - Job job = new Job("Processing view model delta.") { //$NON-NLS-1$ - protected IStatus run(IProgressMonitor monitor) { - fireModelChanged(delta); - return Status.OK_STATUS; - } - }; - job.setPriority(Job.INTERACTIVE); - job.setRule(fModelChangeRule); - job.schedule(); - } - - } - private final DsfSession fSession; private final ModelProxy fModelProxy = new ModelProxy(); + /** + * It is theoretically possible for a VMProvider to be disposed before it + * has a chance to register itself as event listener. This flag is used + * to avoid removing itself as listener in such situation. + */ + private boolean fRegisteredAsEventListener = false; + + /** + * The root node for this model provider. The root layout node could be + * null when first created, to allow sub-classes to prorperly configure the + * root node in the sub-class constructor. + */ private IVMRootLayoutNode fRootLayoutNode; /** - * Constructs the view model provider for given DSF session. + * Constructs the view model provider for given DSF session. The + * constructor is thread-safe to allow VM provider to be constructed + * synchronously when a call to getAdapter() is made on an element + * in a view. */ + @ThreadSafe public VMProvider(DsfSession session, IVMRootLayoutNode rootLayoutNode) { fSession = session; - setRootLayoutNode(rootLayoutNode); + fRootLayoutNode = rootLayoutNode; // Add ourselves as listener for DM events events. - session.addServiceEventListener(this, null); + session.getExecutor().execute(new Runnable() { + public void run() { + if (DsfSession.isSessionActive(getSession().getId())) { + getSession().addServiceEventListener(VMProvider.this, null); + fRegisteredAsEventListener = true; + } + } + }); } /** Sets the layout nodes */ public void setRootLayoutNode(IVMRootLayoutNode rootLayoutNode) { if (fRootLayoutNode != null) { - fRootLayoutNode.sessionDispose(); + fRootLayoutNode.dispose(); } fRootLayoutNode = rootLayoutNode; } @@ -138,9 +105,13 @@ public class VMProvider } /** Called to dispose the provider. */ - public void sessionDispose() { - fSession.removeServiceEventListener(this); - fRootLayoutNode.sessionDispose(); + public void dispose() { + if (fRegisteredAsEventListener) { + fSession.removeServiceEventListener(this); + } + if (fRootLayoutNode != null) { + fRootLayoutNode.dispose(); + } } protected DsfSession getSession() { return fSession; } @@ -248,6 +219,71 @@ public class VMProvider } } + /** + * Retrieves the label information for given object. + * The implementation converts the object into a VM-Context, then delegates + * to the context's layout node. + * Note: this method must be called on the provider's dispatch thread. + + * @see IAsynchronousLabelAdapter#retrieveLabel(Object, org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext, ILabelRequestMonitor) + */ + public void retrieveLabel(Object object, ILabelRequestMonitor result, String[] columns) + { + IVMContext vmc = getVmcForObject(object); + if (vmc == null) { + result.done(); + return; + } + + vmc.getLayoutNode().retrieveLabel(vmc, result, columns); + } + + public ModelProxy getModelProxy() { + return fModelProxy; + } + + + /** + * Creates the column presentation for the given object. This method is meant + * to be overriden by deriving class to provide view-specific functionality. + * The default is to return null, meaning no columns. + *

+ * The viewer only reads the column presentation for the root/input element of + * the tree/table, so the VMProvider must be configured to own the root element + * in the view in order for this setting to be effective. + *

+ * Note: since the IColumnEditorFactoryAdapter interface is synchronous, and since + * column info is fairly static, this method is thread-safe, and it will + * not be called on the executor thread. + * + * @see IColumnEditorFactoryAdapter#createColumnEditor(IPresentationContext, Object) + */ + @ThreadSafe + public IColumnPresentation createColumnPresentation(Object element) { + return null; + } + + /** + * Returns the ID of the column presentation for the given object. This method + * is meant to be overriden by deriving class to provide view-specific + * functionality. The default is to return null, meaning no columns. + *

+ * The viewer only reads the column presentation for the root/input element of + * the tree/table, so the VMProvider must be configured to own the root element + * in the view in order for this setting to be effective. + *

+ * Note: since the IColumnEditorFactoryAdapter interface is synchronous, and since + * column info is fairly static, this method is thread-safe, and it will + * not be called on the executor thread. + * + * @see IColumnEditorFactoryAdapter#getColumnEditorId(IPresentationContext, Object) + */ + @ThreadSafe + public String getColumnPresentationId(Object element) { + return null; + } + + /** * Convenience method that finds the VMC corresponding to given parent * argument given to isContainer() or retrieveChildren(). @@ -293,28 +329,7 @@ public class VMProvider } return false; } - - - /** - * Retrieves the label information for given VMC. - * Note: this method must be called on the provider's dispatch thread. - * @see IAsynchronousLabelAdapter#retrieveLabel(Object, org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext, ILabelRequestMonitor) - */ - public void retrieveLabel(Object object, final ILabelRequestMonitor result) - { - IVMContext vmc = getVmcForObject(object); - if (vmc == null) { - result.done(); - return; - } - - vmc.getLayoutNode().retrieveLabel(vmc, result); - } - - public ModelProxy getModelProxy() { - return fModelProxy; - } - + /** * Handle "data model changed" event by generating a delta object for each * view and passing it to the corresponding view model provider. The view @@ -337,4 +352,50 @@ public class VMProvider }); } } + + @ThreadSafe + public class ModelProxy extends AbstractModelProxy { + /** + * Counter for whether the model proxy is currently installed in the viewer. + * Data model events are processed only if the model proxy is active. + */ + private int fProxyActive = 0; + + /** + * 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; } + }; + + public void installed() { + fProxyActive++; + } + + public void dispose() { + fProxyActive--; + super.dispose(); + } + + /** + * 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) { + if (fProxyActive <= 0) return; + + Job job = new Job("Processing view model delta.") { //$NON-NLS-1$ + protected IStatus run(IProgressMonitor monitor) { + fireModelChanged(delta); + return Status.OK_STATUS; + } + }; + job.setPriority(Job.INTERACTIVE); + job.setRule(fModelChangeRule); + job.schedule(); + } + + } } diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/DsfServicesTracker.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/DsfServicesTracker.java index 7ea47d7af0b..1253077b32a 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/DsfServicesTracker.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/DsfServicesTracker.java @@ -48,23 +48,24 @@ public class DsfServicesTracker { private static class ServiceKey { - String fClassString; + String fClassName; String fFilter; - public ServiceKey(String classString, String filter) { - fClassString = classString; + public ServiceKey(Class clazz, String filter) { + fClassName = clazz != null ? clazz.getName() : null; fFilter = filter; } public boolean equals(Object other) { // I guess this doesn't have to assume fFilter can be null, but oh well. - return other instanceof ServiceKey && - ((ServiceKey)other).fClassString.equals(fClassString) && + return other instanceof ServiceKey && + ((fClassName == null && ((ServiceKey)other).fClassName == null) || + (fClassName != null && fClassName.equals(((ServiceKey)other).fClassName))) && ((fFilter == null && ((ServiceKey)other).fFilter == null) || (fFilter != null && fFilter.equals(((ServiceKey)other).fFilter))); } public int hashCode() { - return fClassString.hashCode() + (fFilter == null ? 0 : fFilter.hashCode()); + return (fClassName == null ? 0 : fClassName.hashCode()) + (fFilter == null ? 0 : fFilter.hashCode()); } } @@ -95,13 +96,13 @@ public class DsfServicesTracker { */ @SuppressWarnings("unchecked") public ServiceReference getServiceReference(Class serviceClass, String filter) { - ServiceKey key = new ServiceKey(serviceClass.getName().intern(), filter != null ? filter : fServiceFilter); + ServiceKey key = new ServiceKey(serviceClass, filter != null ? filter : fServiceFilter); if (fServiceReferences.containsKey(key)) { return fServiceReferences.get(key); } try { - ServiceReference[] references = fBundleContext.getServiceReferences(key.fClassString, key.fFilter); + ServiceReference[] references = fBundleContext.getServiceReferences(key.fClassName, key.fFilter); assert references == null || references.length <= 1; if (references == null || references.length == 0) { return null;