diff --git a/dsf/org.eclipse.cdt.dsf.ui/plugin.xml b/dsf/org.eclipse.cdt.dsf.ui/plugin.xml index f812e3d5da5..acaf81f9678 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/plugin.xml +++ b/dsf/org.eclipse.cdt.dsf.ui/plugin.xml @@ -156,6 +156,20 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -342,6 +384,24 @@ + + + + + + + + + + + + + + + actions = new ArrayList(FORMATS.size()); + for (String formatId : FORMATS) { + actions.add(new SelectFormatAction((IElementFormatProvider) provider, + context, nodes, viewerInput, elementPaths, formatId)); + } + CountingRequestMonitor crm = new CountingRequestMonitor(SimpleDisplayExecutor.getSimpleDisplayExecutor(Display.getDefault()), null) { + @Override + protected void handleCompleted() { + String activeFormat = null; + for (int i = 0; i < formats.length; i++) { + if (i == 0) { + activeFormat = formats[i]; + } else if (activeFormat != null + && activeFormat.equals(formats[i]) == false) { + activeFormat = null; + } + } + if (activeFormat != null) { + for (int i = 0; i < actions.size(); i++) { + if (activeFormat.equals(actions.get(i).fFormatId)) { + actions.get(i).setChecked(true); + } + } + } + } + }; + for (int i = 0; i < elementPaths.length; i++) { + Object segment = elementPaths[i].getLastSegment(); + if (segment instanceof IVMContext) { + nodes[i] = ((IVMContext) segment).getVMNode(); + } else { + nodes[i] = null; + } + final int index = i; + ((IElementFormatProvider) provider).getActiveFormat(context, nodes[i], viewerInput, elementPaths[i], + new DataRequestMonitor(ImmediateExecutor.getInstance(), crm) { + @Override + protected void handleSuccess() { + formats[index] = this.getData(); + super.handleSuccess(); + } + }); + } + crm.setDoneCount(elementPaths.length); + int count = actions.size(); + IContributionItem[] items = new IContributionItem[count + 2]; + for (int i = 0; i < actions.size(); i++) { + items[i] = new ActionContributionItem(actions.get(i)); + } + items[count] = new Separator(); + items[count + 1] = new ActionContributionItem(new SelectFormatAction( + (IElementFormatProvider) provider, context, nodes, viewerInput, elementPaths, null)); + return items; + } +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValueRetriever.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValueRetriever.java index f9f389c6885..25d161a364a 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValueRetriever.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValueRetriever.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 Wind River Systems and others. + * Copyright (c) 2009, 2011 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 @@ -7,6 +7,7 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Winnie Lai (Texas Instruments) - Individual Element Number Format (Bug 202556) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat; @@ -14,6 +15,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -37,6 +39,7 @@ import org.eclipse.cdt.dsf.service.DsfServices; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode; +import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesUpdateStatus; @@ -70,6 +73,7 @@ public class FormattedValueRetriever { private final IVMNode fNode; private final ICachingVMProviderExtension2 fCache; + private final IElementFormatProvider fElementFormatProvider; private final ServiceTracker fServiceTracker; private final Class fDmcType; private final String fPropertyPrefix; @@ -90,6 +94,8 @@ public class FormattedValueRetriever { public FormattedValueRetriever(IVMNode node, Filter filter, Class dmcType, String propertyPrefix) { fNode = node; fCache = (ICachingVMProviderExtension2)node.getVMProvider(); + IVMProvider vmprovider = fNode.getVMProvider(); + fElementFormatProvider = vmprovider instanceof IElementFormatProvider ? (IElementFormatProvider) vmprovider : null; fServiceTracker = new ServiceTracker(DsfUIPlugin.getBundleContext(), filter, null); fServiceTracker.open(); fDmcType = dmcType; @@ -152,45 +158,112 @@ public class FormattedValueRetriever { @ConfinedToDsfExecutor("node.getExecutor()") public void update(final IPropertiesUpdate updates[], final RequestMonitor rm) { - final Map cachedAvailableFormatsMap = calcCachedAvailableFormatsMap(updates); - if (cachedAvailableFormatsMap != null && cachedAvailableFormatsMap.size() == updates.length) { - // All updates were satisfied by the cache. - doUpdateWithAvailableFormats(updates, cachedAvailableFormatsMap, rm); - } else { - final IFormattedValues service = (IFormattedValues)fServiceTracker.getService(); - if (service == null) { - rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Service not available " + fServiceTracker, null)); //$NON-NLS-1$ - rm.done(); - return; + retreiveElementActiveFormat(updates, new DataRequestMonitor>(ImmediateExecutor.getInstance(), rm) { + @Override + protected void handleCompleted() { + final Map elementFormatMap = getData(); + final Map cachedAvailableFormatsMap = calcCachedAvailableFormatsMap(updates); + if ((cachedAvailableFormatsMap != null && cachedAvailableFormatsMap.size() == updates.length)) { + // All updates were satisfied by the cache. + doUpdateWithAvailableFormats(updates, cachedAvailableFormatsMap, elementFormatMap, rm); + } else { + final IFormattedValues service = (IFormattedValues)fServiceTracker.getService(); + if (service == null) { + rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Service not available " + fServiceTracker, null)); //$NON-NLS-1$ + rm.done(); + return; + } + try { + service.getExecutor().execute(new DsfRunnable() { + public void run() { + retrieveAvailableFormats( + calcOutstandingAvailableFormatsUpdates(updates, cachedAvailableFormatsMap), + new DataRequestMonitor>(fNode.getVMProvider().getExecutor(), rm) { + @Override + protected void handleSuccess() { + Map availableFormatsMap; + if (cachedAvailableFormatsMap != null) { + availableFormatsMap = cachedAvailableFormatsMap; + availableFormatsMap.putAll(getData()); + } else { + availableFormatsMap = getData(); + } + // Retrieve the formatted values now that we have the available formats (where needed). + // Note that we are passing off responsibility of our parent monitor + doUpdateWithAvailableFormats(updates, availableFormatsMap, elementFormatMap, rm); + } + }); + } + }); + } catch (RejectedExecutionException e) { + rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Service executor shut down " + service.getExecutor(), e)); //$NON-NLS-1$ + rm.done(); + } + } + } + }); + } + + private void retreiveElementActiveFormat(final IPropertiesUpdate updates[], final DataRequestMonitor> rm) { + if (fElementFormatProvider == null) { + rm.setData(new HashMap(0)); + rm.done(); + return; + } + Map cachedMap = null; + HashSet outstanding = null; + for (IPropertiesUpdate update : updates) { + if (isElementFormatPropertyNeeded(update) == false) { + continue; + } + String active = null; + ICacheEntry cacheEntry = fCache.getCacheEntry(fNode, update.getViewerInput(), update.getElementPath()); + if (cacheEntry != null && cacheEntry.getProperties() != null) { + active = (String) cacheEntry.getProperties().get(PROP_ACTIVE_FORMAT); } - - try { - service.getExecutor().execute(new DsfRunnable() { - public void run() { - retrieveAvailableFormats( - calcOutstandingAvailableFormatsUpdates(updates, cachedAvailableFormatsMap), - new DataRequestMonitor>(fNode.getVMProvider().getExecutor(), rm) { - @Override - protected void handleSuccess() { - Map availableFormatsMap; - if (cachedAvailableFormatsMap != null) { - availableFormatsMap = cachedAvailableFormatsMap; - availableFormatsMap.putAll(getData()); - } else { - availableFormatsMap = getData(); - } - // Retrieve the formatted values now that we have the available formats (where needed). - // Note that we are passing off responsibility of our parent monitor - doUpdateWithAvailableFormats(updates, availableFormatsMap, rm); - } - }); - } - }); - } catch (RejectedExecutionException e) { - rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Service executor shut down " + service.getExecutor(), e)); //$NON-NLS-1$ - rm.done(); + if (active != null) { + if (cachedMap == null) { + cachedMap = new HashMap(updates.length * 4/3); + } + cachedMap.put(update, active); + } else { + if (outstanding == null) { + outstanding = new HashSet(updates.length * 4/3); + } + outstanding.add(update); } + } + if (outstanding == null || outstanding.size() == 0) { + rm.setData(cachedMap == null ? new HashMap(0) : cachedMap); + rm.done(); + return; + } + if (cachedMap == null) { + cachedMap = new HashMap(updates.length * 4/3); } + final Map elementFormatMap = Collections.synchronizedMap(cachedMap); + rm.setData(elementFormatMap); + final CountingRequestMonitor countingRm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), rm); + int count = 0; + for (final IPropertiesUpdate update : outstanding) { + fElementFormatProvider.getActiveFormat(update.getPresentationContext(), fNode, update.getViewerInput(), update.getElementPath(), + new ViewerDataRequestMonitor(ImmediateExecutor.getInstance(), update) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + String active = this.getData(); + if (update.getProperties().contains(PROP_ACTIVE_FORMAT)) { + update.setProperty(PROP_ACTIVE_FORMAT, active); + } + elementFormatMap.put(update, active); + } + countingRm.done(); + } + }); + count++; + } + countingRm.setDoneCount(count); + } /** @@ -329,6 +402,7 @@ public class FormattedValueRetriever { private void doUpdateWithAvailableFormats( IPropertiesUpdate updates[], final Map availableFormatsMap, + final Map elementFormatMap, final RequestMonitor rm) { final List outstandingUpdates = new ArrayList(updates.length); @@ -341,7 +415,7 @@ public class FormattedValueRetriever { update.setProperty(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE, preferredFormat); } - final String activeFormat = calcActiveFormat(update, preferredFormat, availableFormatsMap); + final String activeFormat = calcActiveFormat(update, preferredFormat, availableFormatsMap, elementFormatMap); if (update.getProperties().contains(PROP_ACTIVE_FORMAT)) { assert activeFormat != null : "Our caller should have provided the available formats if this property was specified; given available formats, an 'active' nomination is guaranteed."; //$NON-NLS-1$ @@ -472,12 +546,18 @@ public class FormattedValueRetriever { * * @param update Properties update to calculate the active format for. * @param availableFormatsMap The map of available formats. + * @param elementFormatMap The map of element active format. * @return The active format, or null if active format not requested in * update. */ - private String calcActiveFormat(IPropertiesUpdate update, String preferredFormat, Map availableFormatsMap) { + private String calcActiveFormat(IPropertiesUpdate update, String preferredFormat, Map availableFormatsMap, + Map elementFormatMap) { String[] availableFormats = availableFormatsMap.get(update); if (availableFormats != null && availableFormats.length != 0) { + String elementFormat = elementFormatMap.get(update); + if (elementFormat != null && isFormatAvailable(elementFormat, availableFormats)) { + return elementFormat; + } if (isFormatAvailable(preferredFormat, availableFormats)) { return preferredFormat; } else { @@ -588,6 +668,21 @@ public class FormattedValueRetriever { update.getProperties().contains(PROP_ACTIVE_FORMAT_VALUE); } + /** + * For each update, query the active format for the update's + * element...but only if necessary. It is necessary only if the + * update is asking what the active format is or is asking for the value + * of the element in that format. + * @param update + * @return true if needed + */ + private boolean isElementFormatPropertyNeeded(IPropertiesUpdate update) { + if (fElementFormatProvider == null) + return false; + return update.getProperties().contains(PROP_ACTIVE_FORMAT) || + update.getProperties().contains(PROP_ACTIVE_FORMAT_VALUE); + } + /** * Extracts the formatted data DMC from the update. If update doesn't * contain DMC-based elemtn, it writes an error to the update and returns diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IElementFormatProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IElementFormatProvider.java new file mode 100644 index 00000000000..8c65dd3198f --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IElementFormatProvider.java @@ -0,0 +1,67 @@ +/***************************************************************** + * Copyright (c) 2011 Texas Instruments 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: + * Winnie Lai (Texas Instruments) - Individual Element Number Format (Bug 202556) + *****************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.jface.viewers.TreePath; + +/** + * Element format provider - an optional interface that provides individual element format + * A view model provider (org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider) can optionally implement this interface. + * If there is a requirement to persist individual format settings, this provider can + * add an persistable (IPersistable) property to PresentationContext so that when presentation context + * is invoked to persist its properties, the individual format settings are persisted as well. + * + * @since 2.2 + */ +public interface IElementFormatProvider +{ + /** + * Get active format for a given element. + * @param context presentation context + * @param node view model node + * @param viewerInput viewer input + * @param elementPath element path of the given element + * @param rm request monitor + * @return active format if available. Calls rm.setData(null) if there is no active format. + * The caller will use the active format if the returned format is available, + * and will use preference format if the returned format is null or not available. + * Note that if caller finds that the preference format is not available from service, + * it will use the first available format from service. See FormattedValueRetriever. + */ + public void getActiveFormat(IPresentationContext context, IVMNode node, Object viewerInput, TreePath elementPath, + DataRequestMonitor rm); + + /** + * Set active format for given elements. The caller will not fire any event to update view. + * The implementation of this method should fire proper events to refresh impacted elements. + * One way is to refresh the view through IVMCachingProvider.refresh but it will + * refresh other non-impacted elements. + * Another way that may be more optimal is to fire ElementFormatEvent that stores exactly the + * impacted elements. The view model can then handle the event more efficiently. + * @param context presentation context + * @param node view model nodes + * @param viewerInput viewer input + * @param elementPath element path of given elements + * @param format format + */ + public void setActiveFormat(IPresentationContext context, IVMNode[] node, Object viewerInput, TreePath[] elementPath, String format); + + /** + * Test if this provider supports individual element format for a given context + * @param context given context + * @return true if this provider supports individual element format. + */ + public boolean supportFormat(IVMContext context); +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsContribution.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsContribution.java index 39b0453fbf1..4a0b1d8384e 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsContribution.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsContribution.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Wind River Systems and others. + * Copyright (c) 2008, 2011 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 @@ -7,6 +7,7 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Winnie Lai (Texas Instruments) - Individual Element Number Format (Bug 202556) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat; @@ -38,7 +39,7 @@ import org.eclipse.ui.services.IServiceLocator; */ public class NumberFormatsContribution extends CompoundContributionItem implements IWorkbenchContribution { - private static final List FORMATS = new LinkedList(); + protected static final List FORMATS = new LinkedList(); static { FORMATS.add(IFormattedValues.NATURAL_FORMAT); FORMATS.add(IFormattedValues.HEX_FORMAT); @@ -65,7 +66,7 @@ public class NumberFormatsContribution extends CompoundContributionItem implemen } } - private IServiceLocator fServiceLocator; + protected IServiceLocator fServiceLocator; private static IContributionItem[] NO_BREAKPOINT_TYPES_CONTRIBUTION_ITEMS = new IContributionItem[] { new ContributionItem() { diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsPropertyTester.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsPropertyTester.java index 19101a8c051..f9a7e8de3da 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsPropertyTester.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsPropertyTester.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Wind River Systems and others. + * Copyright (c) 2008, 2011 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 @@ -7,6 +7,7 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Winnie Lai (Texas Instruments) - Individual Element Number Format (Bug 202556) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat; @@ -46,6 +47,7 @@ import org.eclipse.ui.IWorkbenchPart; public class NumberFormatsPropertyTester extends PropertyTester { private static final String SUPPORTED = "areNumberFormatsSupported"; //$NON-NLS-1$ + private static final String ELEMENT_FORMATS_SUPPORTED = "areElementNumberFormatsSupported"; //$NON-NLS-1$ private static final String AVAILABLE = "isNumberFormatAvailable"; //$NON-NLS-1$ private static final String ACTIVE = "isNumberFormatActive"; //$NON-NLS-1$ @@ -63,18 +65,18 @@ public class NumberFormatsPropertyTester extends PropertyTester { if (receiver instanceof IVMContext) { IVMProvider provider = ((IVMContext)receiver).getVMNode().getVMProvider(); if (provider != null) { - return testProvider(provider, property, expectedValue); + return testProvider(provider, property, expectedValue, (IVMContext) receiver); } } else if (receiver instanceof IDebugView) { IVMProvider provider = VMHandlerUtils.getVMProviderForPart((IDebugView)receiver); if (provider != null) { - return testProvider(provider, property, expectedValue); + return testProvider(provider, property, expectedValue, null); } } return false; } - private boolean testProvider(IVMProvider provider, String property, Object expectedValue) { + private boolean testProvider(IVMProvider provider, String property, Object expectedValue, IVMContext vmctx) { if (SUPPORTED.equals(property)) { return true; } else if (AVAILABLE.equals(property)) { @@ -82,7 +84,11 @@ public class NumberFormatsPropertyTester extends PropertyTester { } else if (ACTIVE.equals(property)) { Object activeId = provider.getPresentationContext().getProperty(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE); return expectedValue != null && expectedValue.equals(activeId); - } + } else if (ELEMENT_FORMATS_SUPPORTED.equals(property)) { + if (provider instanceof IElementFormatProvider) { + return ((IElementFormatProvider) provider).supportFormat(vmctx); + } + } return false; } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/DebugManualUpdatePolicy.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/DebugManualUpdatePolicy.java index ef16720e353..6b4fd1bdeae 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/DebugManualUpdatePolicy.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/DebugManualUpdatePolicy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Wind River Systems and others. + * Copyright (c) 2009, 2011 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 @@ -7,6 +7,7 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Winnie Lai (Texas Instruments) - Individual Element Number Format (Bug 202556) *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.viewmodel.update; @@ -37,6 +38,7 @@ import org.eclipse.jface.viewers.TreePath; public class DebugManualUpdatePolicy extends ManualUpdatePolicy implements IVMUpdatePolicyExtension { private final Set fActiveNumberFormatPropertiesWithPrefixes; + private final Set fElementFormatPropertiesWithPrefixes; /** * Creates a manual update policy for debug views. @@ -59,13 +61,19 @@ public class DebugManualUpdatePolicy extends ManualUpdatePolicy implements IVMUp public DebugManualUpdatePolicy(String[] prefixes) { if (prefixes.length == 0) { fActiveNumberFormatPropertiesWithPrefixes = ACTIVE_NUMBER_FORMAT_PROPERTIES; + fElementFormatPropertiesWithPrefixes = ELEMENT_FORMAT_PROPERTIES; } else { fActiveNumberFormatPropertiesWithPrefixes = new TreeSet(ACTIVE_NUMBER_FORMAT_PROPERTIES); + fElementFormatPropertiesWithPrefixes = new TreeSet(ELEMENT_FORMAT_PROPERTIES); for (String prefix : prefixes) { fActiveNumberFormatPropertiesWithPrefixes.add( (prefix + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT).intern()); fActiveNumberFormatPropertiesWithPrefixes.add( (prefix + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE).intern()); + fElementFormatPropertiesWithPrefixes.add( + (prefix + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT).intern()); + fElementFormatPropertiesWithPrefixes.add( + (prefix + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE).intern()); } } @@ -78,6 +86,12 @@ public class DebugManualUpdatePolicy extends ManualUpdatePolicy implements IVMUp ACTIVE_NUMBER_FORMAT_PROPERTIES.add(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE); } + private static final Set ELEMENT_FORMAT_PROPERTIES = new TreeSet(); + static { + ELEMENT_FORMAT_PROPERTIES.add(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT); + ELEMENT_FORMAT_PROPERTIES.add(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE); + } + /** * This specialized element update tester flushes the active number format * property of the elemetn under consideration. The partial property flush @@ -94,6 +108,7 @@ public class DebugManualUpdatePolicy extends ManualUpdatePolicy implements IVMUp } public boolean includes(IElementUpdateTester tester) { + // includes ElementFormatUpdateTester as well? return tester.equals(this); } @@ -110,6 +125,10 @@ public class DebugManualUpdatePolicy extends ManualUpdatePolicy implements IVMUp { return fNumberFormatPropertyEventUpdateTester; } + if ( event instanceof ElementFormatEvent ) + { + return new ElementFormatUpdateTester(((ElementFormatEvent) event), fElementFormatPropertiesWithPrefixes); + } return super.getElementUpdateTester(event); } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/ElementFormatEvent.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/ElementFormatEvent.java new file mode 100644 index 00000000000..6a4ccb4e4aa --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/ElementFormatEvent.java @@ -0,0 +1,59 @@ +/***************************************************************** + * Copyright (c) 2011 Texas Instruments 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: + * Winnie Lai (Texas Instruments) - Individual Element Number Format (Bug 202556) + *****************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.viewmodel.update; + +import java.util.Set; + +/** + * An event that indicates element format is changed. Even when a viewer is + * configured to be in a manual update mode, there is a need to update of the + * labels/states of the element. + * + * @since 2.2 + */ +public class ElementFormatEvent { + protected Set elements; + protected int applyDepth; + + /** + * Constructor + * @param elements the elements that have their formats changed + * @param applyDepth how deep each of the elements apply to itself and their child elements. + * -1 - recursively apply child elements to an infinite depth; + * 0 - does not apply to the element itself and its child elements; + * 1 - apply to the element itself only; + * 2 - apply to the element, its direct children and grand-children; + * and so on for other positive numbers. + */ + public ElementFormatEvent(Set elements, int applyDepth) { + this.elements = elements; + this.applyDepth = applyDepth; + } + + /** + * Get the elements that has formats changed. + * + * @return the elements + */ + public Set getElements() { + return elements; + } + + /** + * Get the depth that how each of the elements apply to itself and their + * child elements. + * + * @return the apply depth. + */ + public int getApplyDepth() { + return applyDepth; + } +} \ No newline at end of file diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/ElementFormatUpdateTester.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/ElementFormatUpdateTester.java new file mode 100644 index 00000000000..48d7e834615 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/ElementFormatUpdateTester.java @@ -0,0 +1,84 @@ +/***************************************************************** + * Copyright (c) 2011 Texas Instruments 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: + * Winnie Lai (Texas Instruments) - Individual Element Number Format (Bug 202556) + *****************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.viewmodel.update; + +import java.util.Collection; +import java.util.Set; + +import org.eclipse.cdt.dsf.ui.viewmodel.update.IElementUpdateTester; +import org.eclipse.cdt.dsf.ui.viewmodel.update.IElementUpdateTesterExtension; +import org.eclipse.cdt.dsf.ui.viewmodel.update.IVMUpdatePolicy; +import org.eclipse.jface.viewers.TreePath; + +/** + * An update tester for element format event (ElementFormatEvent). This tester + * flush partial properties for elements that are affected by a change of + * element format. + * + * @since 2.2 + */ +public class ElementFormatUpdateTester implements IElementUpdateTesterExtension { + protected Set propertiesWithPrefixes; + protected ElementFormatEvent formatEvent; + + public ElementFormatUpdateTester(ElementFormatEvent event, Set propertiesWithPrefixes) { + formatEvent = event; + this.propertiesWithPrefixes = propertiesWithPrefixes; + } + + public int getUpdateFlags(Object viewerInput, TreePath path) { + Set elements = formatEvent.getElements(); + if (elements.contains(viewerInput)) { + return IVMUpdatePolicy.FLUSH_PARTIAL_PROPERTIES; + } + int applyDepth = formatEvent.getApplyDepth(); + if (applyDepth == -1) { + for (int i = 0; i < path.getSegmentCount(); i++) { + if (elements.contains(path.getSegment(i))) { + return IVMUpdatePolicy.FLUSH_PARTIAL_PROPERTIES; + } + } + } else if (applyDepth >= 1) { + int start = path.getSegmentCount() - applyDepth; + if (start < 0) + start = 0; + for (int i = start; i < path.getSegmentCount(); i++) { + if (elements.contains(path.getSegment(i))) { + return IVMUpdatePolicy.FLUSH_PARTIAL_PROPERTIES; + } + } + } + return 0; + } + + public Collection getPropertiesToFlush(Object viewerInput, + TreePath path, boolean isDirty) { + return propertiesWithPrefixes; + } + + public boolean includes(IElementUpdateTester tester) { + if (tester.equals(this)) { + return true; + } + if (tester instanceof ElementFormatUpdateTester) { + return formatEvent.getElements().containsAll( + ((ElementFormatUpdateTester) tester).formatEvent.getElements()) + && propertiesWithPrefixes.containsAll(((ElementFormatUpdateTester) tester).propertiesWithPrefixes) + && formatEvent.getApplyDepth() == ((ElementFormatUpdateTester) tester).formatEvent.getApplyDepth(); + } + return false; + } + + @Override + public String toString() { + return "Manual (refresh = false) update tester for an element format event"; //$NON-NLS-1$ + } +} diff --git a/dsf/org.eclipse.cdt.examples.dsf.pda.ui/plugin.xml b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/plugin.xml index 2a0a9b3d948..16608bd2233 100644 --- a/dsf/org.eclipse.cdt.examples.dsf.pda.ui/plugin.xml +++ b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/plugin.xml @@ -103,5 +103,12 @@ adaptableType="org.eclipse.cdt.examples.dsf.pda.ui.editor.PDAEditor"> + + + + --> diff --git a/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/PDAExpressionVMProvider.java b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/PDAExpressionVMProvider.java new file mode 100644 index 00000000000..e3a7340d3fb --- /dev/null +++ b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/PDAExpressionVMProvider.java @@ -0,0 +1,115 @@ +/***************************************************************** + * Copyright (c) 2011 Texas Instruments 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: + * Winnie Lai (Texas Instruments) - Individual Element Number Format example (Bug 202556) + *****************************************************************/ +package org.eclipse.cdt.examples.dsf.pda.ui.viewmodel; + +import java.util.ArrayList; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.ExpressionVMProvider; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IElementFormatProvider; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableVMNode; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter; +import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.debug.core.model.IExpression; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.jface.viewers.TreePath; + +/** + * PDA View Model provider for the expression view. + */ +@SuppressWarnings("restriction") +public class PDAExpressionVMProvider extends ExpressionVMProvider implements IElementFormatProvider { + + static String myPersistId = "org.eclipse.cdt.examples.dsf.pda.ui.variablePersistable"; + + public PDAExpressionVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) { + super(adapter, context, session); + } + + public void getActiveFormat(IPresentationContext context, IVMNode node, Object viewerInput, TreePath elementPath, + DataRequestMonitor rm) { + Object p = context.getProperty(myPersistId); + if (p instanceof VariablePersistable == false) { + rm.setData(null); + rm.done(); + return; + } + VariablePersistable persistable = (VariablePersistable) p; + Object x = elementPath.getLastSegment(); + if (x instanceof VariableVMNode.VariableExpressionVMC) { + IExpressionDMContext ctx = DMContexts.getAncestorOfType(((VariableVMNode.VariableExpressionVMC) x).getDMContext(), IExpressionDMContext.class); + if (ctx == null) { + rm.setData(null); + } else { + rm.setData(persistable.getFormat(ctx.getExpression())); + } + rm.done(); + return; + } else if (x instanceof IDMVMContext) { + // register and bit field context are covered here. + // When these show up in expression view, the register/bit field vm node's associateExpression has called + // RegisterVMC/BitFieldVMC's setExpression + IExpression y = (IExpression) ((IVMContext) x).getAdapter(IExpression.class); + if (y == null) { + rm.setData(null); + } else { + rm.setData(persistable.getFormat(y.getExpressionText())); + } + rm.done(); + return; + } + rm.setData(null); + rm.done(); + return; + } + + public void setActiveFormat(IPresentationContext context, IVMNode[] node, Object viewerInput, TreePath[] elementPath, String format) { + Object p = context.getProperty(myPersistId); + VariablePersistable persistable = null; + if (p instanceof VariablePersistable) { + persistable = (VariablePersistable) p; + } else { + persistable = new VariablePersistable(); + context.setProperty(myPersistId, persistable); + } + ArrayList changed = new ArrayList(elementPath.length); + for (int i = 0; i < elementPath.length; i++) { + Object x = elementPath[i].getLastSegment(); + if (x instanceof VariableVMNode.VariableExpressionVMC) { + IExpressionDMContext ctx = DMContexts.getAncestorOfType(((VariableVMNode.VariableExpressionVMC) x).getDMContext(), IExpressionDMContext.class); + if (ctx == null) + continue; + persistable.setFormat(ctx.getExpression(), format); + changed.add((IDMVMContext) x); + } else if (x instanceof IDMVMContext) { + IExpression y = (IExpression) ((IVMContext) x).getAdapter(IExpression.class); + if (y == null) + continue; + persistable.setFormat(y.getExpressionText(), format); + } + } + if (changed.size() > 0) { + refresh(); + } + } + + public boolean supportFormat(IVMContext context) { + if (context instanceof VariableVMNode.VariableExpressionVMC) { + return true; + } + return false; + } +} diff --git a/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/PDAVMAdapter.java b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/PDAVMAdapter.java index 530e2a35385..93e12289e65 100644 --- a/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/PDAVMAdapter.java +++ b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/PDAVMAdapter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems and others. + * Copyright (c) 2006, 2011 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 @@ -7,13 +7,14 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Winnie Lai (Texas Instruments) - Individual Element Number Format example (Bug 202556) *******************************************************************************/ package org.eclipse.cdt.examples.dsf.pda.ui.viewmodel; import org.eclipse.cdt.dsf.concurrent.ThreadSafe; import org.eclipse.cdt.dsf.debug.ui.viewmodel.AbstractDebugVMAdapter; import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.ExpressionVMProvider; +//import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.ExpressionVMProvider; import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterVMProvider; import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableVMProvider; import org.eclipse.cdt.dsf.service.DsfSession; @@ -45,7 +46,7 @@ public class PDAVMAdapter extends AbstractDebugVMAdapter } else if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(context.getId()) ) { return new VariableVMProvider(this, context, getSession()); } else if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(context.getId()) ) { - return new ExpressionVMProvider(this, context, getSession()); + return new PDAExpressionVMProvider(this, context, getSession()); } else if (IDebugUIConstants.ID_REGISTER_VIEW.equals(context.getId()) ) { return new RegisterVMProvider(this, context, getSession()); } diff --git a/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/VariablePersistable.java b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/VariablePersistable.java new file mode 100644 index 00000000000..e723b106548 --- /dev/null +++ b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/VariablePersistable.java @@ -0,0 +1,81 @@ +/***************************************************************** + * Copyright (c) 2011 Texas Instruments 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: + * Winnie Lai (Texas Instruments) - Individual Element Number Format example (Bug 202556) + *****************************************************************/ +package org.eclipse.cdt.examples.dsf.pda.ui.viewmodel; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map.Entry; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IPersistableElement; + +/** + * Variable persistable for variable settings + */ +class VariablePersistable implements IPersistableElement, IAdaptable { + + HashMap map = new HashMap(); + + public void saveState(IMemento memento) { + HashMap clone = null; + synchronized (map) { + clone = new HashMap(map); + } + Iterator > it = clone.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + IMemento value = memento.createChild("variable", entry.getKey()); + value.putString("format", entry.getValue()); + } + } + + void restore(IMemento memento) { + IMemento[] list = memento.getChildren("variable"); + HashMap clone = new HashMap(); + for (int i = 0; i < list.length; i++) { + clone.put(list[i].getID(), list[i].getString("format")); + } + synchronized(map) { + map.clear(); + map.putAll(clone); + } + } + + String getFormat(String key) { + if (key == null) + return null; + synchronized (map) { + return map.get(key); + } + } + + void setFormat(String key, String format) { + synchronized (map) { + if (format == null) { + map.remove(key); + } else { + map.put(key, format); + } + } + } + + public String getFactoryId() { + return VariablePersistableFactory.getFactoryId(); + } + + public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { + if (adapter.isInstance(this)) { + return this; + } + return null; + } +} diff --git a/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/VariablePersistableFactory.java b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/VariablePersistableFactory.java new file mode 100644 index 00000000000..914fd8c6056 --- /dev/null +++ b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/VariablePersistableFactory.java @@ -0,0 +1,32 @@ +/***************************************************************** + * Copyright (c) 2011 Texas Instruments 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: + * Winnie Lai (Texas Instruments) - Individual Element Number Format example (Bug 202556) + *****************************************************************/ +package org.eclipse.cdt.examples.dsf.pda.ui.viewmodel; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.ui.IElementFactory; +import org.eclipse.ui.IMemento; + +/** + * Variable persistable factory for VariablePersistable + */ +public class VariablePersistableFactory implements IElementFactory { + + public static String getFactoryId() { + return "org.eclipse.cdt.examples.dsf.pda.ui.variablePersitableFactory"; + } + + public IAdaptable createElement(IMemento memento) { + VariablePersistable x = new VariablePersistable(); + x.restore(memento); + return x; + } + +} diff --git a/dsf/org.eclipse.cdt.tests.dsf/plugin.xml b/dsf/org.eclipse.cdt.tests.dsf/plugin.xml index 4b4d7a573fc..43c8fe3c95d 100644 --- a/dsf/org.eclipse.cdt.tests.dsf/plugin.xml +++ b/dsf/org.eclipse.cdt.tests.dsf/plugin.xml @@ -32,5 +32,12 @@ markerType="markerType.breakpoint" id="org.eclipse.cdt.tests.dsf.breakpoint"/> + + + + diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/FormattedValueTests.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/FormattedValueTests.java index e7abbd8ba42..d6a473cc30c 100644 --- a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/FormattedValueTests.java +++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/FormattedValueTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 Wind River Systems and others. + * Copyright (c) 2009, 2011 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 @@ -7,9 +7,12 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Winnie Lai (Texas Instruments) - Individual Element Number Format test cases (Bug 202556) *******************************************************************************/ package org.eclipse.cdt.tests.dsf.vm; +import java.util.ArrayList; +import java.util.HashMap; import java.util.concurrent.ExecutionException; import junit.framework.Assert; @@ -24,9 +27,11 @@ import org.eclipse.cdt.dsf.concurrent.Query; import org.eclipse.cdt.dsf.debug.service.IFormattedValues; import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IElementFormatProvider; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.service.IDsfService; import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter; +import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode; import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesUpdateStatus; @@ -40,12 +45,14 @@ import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarg import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; 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.TreeModelViewer; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.ViewerLabel; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.XMLMemento; /** * Tests to verify the operation of FormattedValuesVMUtil @@ -65,6 +72,7 @@ abstract public class FormattedValueTests extends TestCase implements IViewerUpd DummyFormattedValueService fDummyValuesService; AbstractVMAdapter fVMAdapter; TestModelCachingVMProvider fVMProvider; + int vmListenerLevel = -1; public FormattedValueTests(String name) { super(name); @@ -114,6 +122,63 @@ abstract public class FormattedValueTests extends TestCase implements IViewerUpd fShell.open (); } + /** + * helper to create view model and viewer + * @param vmOnly true to create view model only and do not create viewer + */ + void createViewer(boolean vmOnly) { + if (vmOnly == false) { + fDisplay = PlatformUI.getWorkbench().getDisplay(); + fShell = new Shell(fDisplay/*, SWT.ON_TOP | SWT.SHELL_TRIM*/); + fShell.setMaximized(true); + fShell.setLayout(new FillLayout()); + fViewer = createViewer(fDisplay, fShell); + fViewerListener = new TestModelUpdatesListener(fViewer, true, false); + } + fVMProvider = new TestElementFormatVMProvider(fVMAdapter, fViewer.getPresentationContext(), fDsfSession); + fVMListener = new TestModelUpdatesListener(); + fVMProvider.getNode().setVMUpdateListener(fVMListener); + fVMProvider.getNode().getLabelProvider().addPropertiesUpdateListener(fViewerListener); + fVMProvider.getNode().setFormattedValuesListener(fFormattedValuesListener); + if (vmOnly == false) { + fShell.open(); + } + } + + /** + * helper to destory view model and viewer + * @param vmOnly true to destory view model only and do not destroy viewer + */ + void destroyViewer(boolean vmOnly) { + fVMProvider.getNode().setFormattedValuesListener(null); + fVMProvider.getNode().getLabelProvider().removePropertiesUpdateListener(fViewerListener); + fVMProvider.getNode().setVMUpdateListener(null); + fVMListener.dispose(); + if (vmOnly == false) { + fViewerListener.dispose(); + fViewer.getPresentationContext().dispose(); + // Close the shell + fShell.close(); + while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + } + } + + /** + * helper to recreate view model only + */ + void recreateViewModel() { + destroyViewer(true); + createViewer(true); + } + + /** + * helper to recreate viewer (and view model) + */ + void recreateViewer() { + destroyViewer(false); + createViewer(false); + } + private void initializeService(final IDsfService service) throws InterruptedException, ExecutionException { Query initQuery = new Query() { @Override @@ -239,6 +304,389 @@ abstract public class FormattedValueTests extends TestCase implements IViewerUpd " (" + DummyFormattedValueService.DUMMY_FORMAT + ")"); } + /** + * Test that each element can have its own format + */ + public void testValidateElement() { + recreateViewModel(); + String preferenceFormat = IFormattedValues.NATURAL_FORMAT; + setInput(preferenceFormat); + // set each element to the same element format different than the preference format, and verify + HashMap map = new HashMap(); + String[] format = { IFormattedValues.HEX_FORMAT }; + makeElementFormatSetting(fViewer, TreePath.EMPTY, format, -1, 0, map); + ArrayList elementFormats = new ArrayList(map.values()); + setFormatAndValidate(preferenceFormat, elementFormats, elementFormats, true, false, false); + // element of same level use the same format and different levels have different formats, and verify + map.clear(); + format = new String[] { IFormattedValues.HEX_FORMAT, IFormattedValues.DECIMAL_FORMAT, + IFormattedValues.OCTAL_FORMAT, IFormattedValues.BINARY_FORMAT, + IFormattedValues.NATURAL_FORMAT }; + makeElementFormatSetting(fViewer, TreePath.EMPTY, format, -1, 0, map); + elementFormats = new ArrayList(map.values()); + setFormatAndValidate(preferenceFormat, elementFormats, elementFormats, false, false, false); + } + + /** + * Test that each element can change to a format and then restore to preference format + */ + public void testChangeElementFormat() { + recreateViewModel(); + String preferenceFormat = IFormattedValues.HEX_FORMAT; + setInput(IFormattedValues.NATURAL_FORMAT); + setFormatAndValidate(preferenceFormat, false, false, false); + // set each element to a format, and verify + HashMap map = new HashMap(); + String[] format = { IFormattedValues.HEX_FORMAT, IFormattedValues.DECIMAL_FORMAT, + IFormattedValues.OCTAL_FORMAT, IFormattedValues.BINARY_FORMAT, + IFormattedValues.NATURAL_FORMAT }; + makeElementFormatSetting(fViewer, TreePath.EMPTY, format, -1, 0, map); + ArrayList elementFormats = new ArrayList(map.values()); + setFormatAndValidate(preferenceFormat, elementFormats, elementFormats, false, false, false); + // Restore each element to preference format, and verify + for (ElementFormatSetting e : elementFormats) { + e.formatId = null; + } + setFormatAndValidate(preferenceFormat, elementFormats, elementFormats, false, false, false); + } + + /** + * Test changing element to a format and then restore to preference format, + * using a view model provider that applies a format to child elements + * of a certain level of depth. + */ + public void testChangeElementFormatApplyDepth() { + recreateViewModel(); + if (fVMProvider instanceof TestElementFormatVMProvider == false) { + return; + } + TestElementFormatVMProvider myVM = (TestElementFormatVMProvider) fVMProvider; + String preferenceFormat = IFormattedValues.HEX_FORMAT; + setInput(IFormattedValues.NATURAL_FORMAT); + setFormatAndValidate(preferenceFormat, false, false, false); + int[] myDepths = new int[] { -1, 2 }; + for (int depth : myDepths) { + myVM.elementFormatApplyDepth = depth; + // set top level element to a format, and verify top and child elements + // at certain levels have the correct format. + String[] format = { IFormattedValues.DECIMAL_FORMAT }; + HashMap map = new HashMap(); + makeElementFormatSetting(fViewer, TreePath.EMPTY, format, 1, 0, map); + ArrayList setElementFormats = new ArrayList(map.values()); + HashMap expMap = new HashMap(); + makeElementFormatSetting(fViewer, TreePath.EMPTY, format, depth, 0, expMap); + ArrayList expectElementFormats = new ArrayList(expMap.values()); + setFormatAndValidate(preferenceFormat, setElementFormats, expectElementFormats, false, false, false); + // Restore top level element to preference format, and verify. + for (ElementFormatSetting e : setElementFormats) { + e.formatId = null; + } + for (ElementFormatSetting e : expectElementFormats) { + e.formatId = null; + } + setFormatAndValidate(preferenceFormat, setElementFormats, expectElementFormats, false, false, false); + } + } + + /** + * Test changing format of each element under manual update policy. + * Formatted values should be retrieved from cache if available. + * Changing to a format whose formatted value is not in cache should get a cache miss error. + */ + public void testChangeElementFormatManualUpdateMode() { + recreateViewModel(); + String preferenceFormat = IFormattedValues.NATURAL_FORMAT; + setInput(IFormattedValues.NATURAL_FORMAT); + setUpdatePolicy(ManualUpdatePolicy.MANUAL_UPDATE_POLICY_ID); + + // Change to a new format, this does not cause the cache entries to be + // set to dirty. Retrieving new format values should happen from the service. + HashMap map1 = new HashMap(); + String[] format1 = { IFormattedValues.HEX_FORMAT }; + makeElementFormatSetting(fViewer, TreePath.EMPTY, format1, -1, 0, map1); + ArrayList elementFormats1 = new ArrayList(map1.values()); + setFormatAndValidate(preferenceFormat, elementFormats1, elementFormats1, true, false, false); + + // Remove element format and so restore back to preference - natural format. Values should be retrieved from cache. + HashMap map2 = new HashMap(); + String[] format2 = { null }; + makeElementFormatSetting(fViewer, TreePath.EMPTY, format2, -1, 0, map2); + ArrayList elementFormats2 = new ArrayList(map2.values()); + setFormatAndValidate(preferenceFormat, elementFormats2, elementFormats2, true, true, false); + + // Generate an event which will cause all cache entries to be marked dirty. + postEventInManualUpdateMode(); + + // Change back again to hex format. Values should be retrieved from cache. + setFormatAndValidate(preferenceFormat, elementFormats1, elementFormats1, true, true, false); + + // Change to a decimal, which is not cached, values should come with an error. + HashMap map3 = new HashMap(); + String[] format3 = { IFormattedValues.DECIMAL_FORMAT }; + makeElementFormatSetting(fViewer, TreePath.EMPTY, format3, -1, 0, map3); + ArrayList elementFormats3 = new ArrayList(map3.values()); + setFormatAndValidate(preferenceFormat, elementFormats3, elementFormats3, true, true, true); + } + + /** + * Test changing element format under manual update policy, + * using a view model provider that applies a format to child elements + * of a certain level of depth. + */ + public void testChangeElementFormatApplyDepthManualUpdateMode() { + int[] myDepths = new int[] { -1, 2 }; + for (int depth : myDepths) { + recreateViewer(); + if (fVMProvider instanceof TestElementFormatVMProvider == false) { + return; + } + TestElementFormatVMProvider myVM = (TestElementFormatVMProvider) fVMProvider; + String preferenceFormat = IFormattedValues.NATURAL_FORMAT; + setInput(IFormattedValues.NATURAL_FORMAT); + setUpdatePolicy(ManualUpdatePolicy.MANUAL_UPDATE_POLICY_ID); + myVM.elementFormatApplyDepth = depth; + // Change top level to a new format, this does not cause the cache entries to be + // set to dirty. Retrieving new format values should happen from the service. + String[] format1 = { IFormattedValues.HEX_FORMAT }; + HashMap map1 = new HashMap(); + makeElementFormatSetting(fViewer, TreePath.EMPTY, format1, 1, 0, map1); + ArrayList elementFormats1 = new ArrayList(map1.values()); + HashMap expMap1 = new HashMap(); + makeElementFormatSetting(fViewer, TreePath.EMPTY, format1, depth, 0, expMap1); + ArrayList expectElementFormats1 = new ArrayList(expMap1.values()); + vmListenerLevel = depth; + setFormatAndValidate(preferenceFormat, elementFormats1, expectElementFormats1, true, false, false); + + // Remove element format and so restore back to preference format - natural. Values should be retrieved from cache. + String[] format2 = { null }; + HashMap map2 = new HashMap(); + makeElementFormatSetting(fViewer, TreePath.EMPTY, format2, 1, 0, map2); + ArrayList elementFormats2 = new ArrayList(map2.values()); + HashMap expMap2 = new HashMap(); + makeElementFormatSetting(fViewer, TreePath.EMPTY, format2, depth, 0, expMap2); + ArrayList expectElementFormats2 = new ArrayList(expMap2.values()); + setFormatAndValidate(preferenceFormat, elementFormats2, expectElementFormats2, true, true, false); + + // Generate an event which will cause all cache entries to be marked dirty. + postEventInManualUpdateMode(); + + // Change back again to hex format. Values should be retrieved from cache. + setFormatAndValidate(preferenceFormat, elementFormats1, expectElementFormats1, true, true, false); + + // Change to a decimal, which is not cached, values should come with an error. + String[] format3 = { IFormattedValues.DECIMAL_FORMAT }; + HashMap map3 = new HashMap(); + makeElementFormatSetting(fViewer, TreePath.EMPTY, format3, 1, 0, map3); + ArrayList elementFormats3 = new ArrayList(map3.values()); + HashMap expMap3 = new HashMap(); + makeElementFormatSetting(fViewer, TreePath.EMPTY, format3, depth, 0, expMap3); + ArrayList expectElementFormats3 = new ArrayList(expMap3.values()); + setFormatAndValidate(preferenceFormat, elementFormats3, expectElementFormats3, true, true, true); + } + } + + /** + * Test that when the preference format is invalid, each element can still change to a format. + * Also, each element can restore to the invalid preference format such that + * the element uses first available format from service. + */ + public void testChangeElementFormatWithInvalidPreference() { + recreateViewModel(); + String preferenceFormat = IFormattedValues.NATURAL_FORMAT; + setInput(preferenceFormat); + // set preference format to an invalid format and verify + setInvalidPreferenceAndVerify(); + // set each element to a format, and verify + HashMap map = new HashMap(); + String[] format = { IFormattedValues.HEX_FORMAT, IFormattedValues.DECIMAL_FORMAT, + IFormattedValues.OCTAL_FORMAT, IFormattedValues.BINARY_FORMAT, + IFormattedValues.NATURAL_FORMAT }; + makeElementFormatSetting(fViewer, TreePath.EMPTY, format, -1, 0, map); + ArrayList elementFormats = new ArrayList(map.values()); + setFormatAndValidate("invalid format", elementFormats, elementFormats, false, false, false); + // Restore each element to preference format which is an invalid format + for (ElementFormatSetting e : elementFormats) { + e.formatId = null; + } + fViewerListener.reset(); + fViewerListener.addUpdates(TreePath.EMPTY, ((TestElementVMContext)fViewer.getInput()).getElement(), -1, ALL_UPDATES_COMPLETE | PROPERTY_UPDATES); + fVMListener.reset(); + fVMListener.addUpdates(TreePath.EMPTY, fModel.getRootElement(), -1, ALL_UPDATES_COMPLETE | PROPERTY_UPDATES); + if (fVMProvider instanceof IElementFormatProvider) { + IElementFormatProvider ep = ((IElementFormatProvider) fVMProvider); + for (ElementFormatSetting es : elementFormats) { + ep.setActiveFormat(fViewer.getPresentationContext(), + es.nodes.toArray(new IVMNode[es.nodes.size()]), fViewer.getInput(), + es.elementPaths.toArray(new TreePath[es.elementPaths.size()]), es.formatId); + } + } + while (!fViewerListener.isFinished(ALL_UPDATES_COMPLETE | PROPERTY_UPDATES) || !fVMListener.isFinished(CONTENT_UPDATES | PROPERTY_UPDATES)) { + if (!fDisplay.readAndDispatch ()) { + fDisplay.sleep (); + } + } + // verify service's first available format is used + validateModel(IFormattedValues.HEX_FORMAT, " (" + FormattedValueVMUtil.getFormatLabel(IFormattedValues.HEX_FORMAT) + ")", + DummyFormattedValueService.DUMMY_FORMAT, " (" + DummyFormattedValueService.DUMMY_FORMAT + ")"); + } + + /** + * Test that when an element is set to to an invalid format, the element uses preference format. + */ + public void testInvalidElementFormat() { + recreateViewModel(); + String preferenceFormat = IFormattedValues.NATURAL_FORMAT; + setInput(preferenceFormat); + // set each element to an invalid format + setElementInvalidFormat(); + // verify preference format is used when element format is invalid + validateModel(preferenceFormat, ""); + } + + /** + * Test that when an element is set to to an invalid format and the preference format is invalid, + * the element uses first available format from service. + */ + public void testInvalidElementFormatWithInvalidPreference() { + recreateViewModel(); + String preferenceFormat = IFormattedValues.NATURAL_FORMAT; + setInput(preferenceFormat); + // set preference format to an invalid format and verify + setInvalidPreferenceAndVerify(); + // set each element to an invalid format + setElementInvalidFormat(); + // verify service's first available format is used when element format and preference format are invalid + validateModel(IFormattedValues.HEX_FORMAT, " (" + FormattedValueVMUtil.getFormatLabel(IFormattedValues.HEX_FORMAT) + ")", + DummyFormattedValueService.DUMMY_FORMAT, " (" + DummyFormattedValueService.DUMMY_FORMAT + ")"); + } + + /** + * Test that element format can be persisted in memento and viewer + * can restore to the persisted settings. + */ + public void testPersistElementFormat() { + recreateViewModel(); + String preferenceFormat = IFormattedValues.HEX_FORMAT; + setInput(IFormattedValues.NATURAL_FORMAT); + setFormatAndValidate(preferenceFormat, false, false, false); + // set each element to a format, and verify + HashMap map = new HashMap(); + String[] format = { IFormattedValues.HEX_FORMAT, IFormattedValues.DECIMAL_FORMAT, + IFormattedValues.OCTAL_FORMAT, IFormattedValues.BINARY_FORMAT, + IFormattedValues.NATURAL_FORMAT }; + makeElementFormatSetting(fViewer, TreePath.EMPTY, format, -1, 0, map); + ArrayList elementFormats = new ArrayList(map.values()); + setFormatAndValidate(preferenceFormat, elementFormats, elementFormats, false, false, false); + // save settings + XMLMemento memento = XMLMemento.createWriteRoot("TEST"); + if (fViewer instanceof TreeModelViewer == false) + return; + ((TreeModelViewer) fViewer).saveState(memento); + // throw away any settings inside the viewer and create a new viewer + // with memento settings, this is the same effect resulted from closing + // and opening workspace again. + recreateViewer(); + if (fViewer instanceof TreeModelViewer == false) + return; + ((TreeModelViewer) fViewer).initState(memento); + setInput(IFormattedValues.NATURAL_FORMAT); + preferenceFormat = (String) fViewer.getPresentationContext().getProperty(PROP_FORMATTED_VALUE_FORMAT_PREFERENCE); + validateModel(elementFormats, preferenceFormat, "", preferenceFormat, ""); + } + + /** + * helper class that stores some element paths and nodes using a certain format + */ + class ElementFormatSetting { + ArrayList nodes; + ArrayList elementPaths; + String formatId; + } + + /** + * helper to create element format settings for all children paths of a given element path. + * Tree paths at the same level will use the same format. Tree paths at different + * levels will use different formats. + * @param _viewer tree viewer + * @param path given element path + * @param formats formats to rotate for different levels of children tree paths + * @param levelStop depth to stop recursively walk down the children. + * @param levelIndex index to a format for a level of children + * @param result store the created element format settings + */ + void makeElementFormatSetting(ITreeModelViewer _viewer, TreePath path, String[] formats, + int levelStop, int levelIndex, HashMap result) { + if (levelStop >= 0 && levelIndex >= levelStop) + return; + ITreeModelContentProviderTarget viewer = (ITreeModelContentProviderTarget)_viewer; + int childCount = viewer.getChildCount(path); + if (childCount == 0) + return; + String fmt = formats[levelIndex % formats.length]; + ElementFormatSetting setting = result.get(fmt); + if (setting == null) { + setting = new ElementFormatSetting(); + setting.nodes = new ArrayList(childCount); + setting.elementPaths = new ArrayList(childCount); + setting.formatId = fmt; + result.put(fmt, setting); + } + for (int i = 0; i < childCount; i++) { + Object viewerObject = viewer.getChildElement(path, i); + if (viewerObject instanceof TestElementVMContext) { + TreePath childPath = path.createChildPath(viewerObject); + setting.nodes.add(((TestElementVMContext)viewerObject).getVMNode()); + setting.elementPaths.add(childPath); + makeElementFormatSetting(viewer, childPath, formats, levelStop, levelIndex + 1, result); + } + } + } + + /** + * helper to set element to an invalid format + */ + void setElementInvalidFormat() { + fViewerListener.reset(); + fViewerListener.addUpdates(TreePath.EMPTY, ((TestElementVMContext)fViewer.getInput()).getElement(), -1, ALL_UPDATES_COMPLETE | PROPERTY_UPDATES); + fVMListener.reset(); + fVMListener.addUpdates(TreePath.EMPTY, fModel.getRootElement(), -1, ALL_UPDATES_COMPLETE | PROPERTY_UPDATES); + HashMap map = new HashMap(); + String[] format = { "invalid element format" }; + makeElementFormatSetting(fViewer, TreePath.EMPTY, format, -1, 0, map); + ArrayList elementFormats = new ArrayList(map.values()); + if (fVMProvider instanceof IElementFormatProvider) { + IElementFormatProvider ep = ((IElementFormatProvider) fVMProvider); + for (ElementFormatSetting es : elementFormats) { + ep.setActiveFormat(fViewer.getPresentationContext(), + es.nodes.toArray(new IVMNode[es.nodes.size()]), fViewer.getInput(), + es.elementPaths.toArray(new TreePath[es.elementPaths.size()]), es.formatId); + } + } + while (!fViewerListener.isFinished(ALL_UPDATES_COMPLETE | PROPERTY_UPDATES) || !fVMListener.isFinished(CONTENT_UPDATES | PROPERTY_UPDATES)) { + if (!fDisplay.readAndDispatch ()) { + fDisplay.sleep (); + } + } + } + + /** + * helper to set preference to an invalid format and verify. + */ + void setInvalidPreferenceAndVerify() { + fViewerListener.reset(); + fViewerListener.addUpdates(TreePath.EMPTY, ((TestElementVMContext)fViewer.getInput()).getElement(), -1, ALL_UPDATES_COMPLETE | PROPERTY_UPDATES); + fVMListener.reset(); + fVMListener.addUpdates(TreePath.EMPTY, fModel.getRootElement(), -1, ALL_UPDATES_COMPLETE | PROPERTY_UPDATES); + fViewer.getPresentationContext().setProperty(PROP_FORMATTED_VALUE_FORMAT_PREFERENCE, "invalid format"); + while (!fViewerListener.isFinished(ALL_UPDATES_COMPLETE | PROPERTY_UPDATES) || !fVMListener.isFinished(CONTENT_UPDATES | PROPERTY_UPDATES)) { + if (!fDisplay.readAndDispatch ()) { + fDisplay.sleep (); + } + } + validateModel(IFormattedValues.HEX_FORMAT, " (" + FormattedValueVMUtil.getFormatLabel(IFormattedValues.HEX_FORMAT) + ")", + DummyFormattedValueService.DUMMY_FORMAT, " (" + DummyFormattedValueService.DUMMY_FORMAT + ")"); + } + /** * Initial format is NATURAL. */ @@ -287,7 +735,17 @@ abstract public class FormattedValueTests extends TestCase implements IViewerUpd } private void setFormatAndValidate( - String formatId, + String formatId, + boolean expectContentCached, + boolean expectFormattedValuesCached, + boolean expectCacheMissError) { + setFormatAndValidate(formatId, null, null, expectContentCached, expectFormattedValuesCached, expectCacheMissError); + } + + private void setFormatAndValidate( + String formatId, + ArrayList setElementFormats, + ArrayList expectElementFormats, boolean expectContentCached, boolean expectFormattedValuesCached, boolean expectCacheMissError) @@ -300,29 +758,39 @@ abstract public class FormattedValueTests extends TestCase implements IViewerUpd if (!expectContentCached) { vmUpdateFlags |= ALL_UPDATES_COMPLETE; } - fVMListener.addUpdates(TreePath.EMPTY, fModel.getRootElement(), -1, vmUpdateFlags); + fVMListener.addUpdates(TreePath.EMPTY, fModel.getRootElement(), vmListenerLevel, vmUpdateFlags); fFormattedValuesListener.reset(); if (expectFormattedValuesCached && !expectCacheMissError) { fFormattedValuesListener.setCachedFormats(new String[] {formatId} ); } + + if (fVMProvider instanceof IElementFormatProvider && setElementFormats != null) { + IElementFormatProvider ep = ((IElementFormatProvider) fVMProvider); + for (ElementFormatSetting es : setElementFormats) { + ep.setActiveFormat(fViewer.getPresentationContext(), + es.nodes.toArray(new IVMNode[es.nodes.size()]), fViewer.getInput(), + es.elementPaths.toArray(new TreePath[es.elementPaths.size()]), es.formatId); + } + } else { + // Set the new number format to the viewer. + fViewer.getPresentationContext().setProperty(PROP_FORMATTED_VALUE_FORMAT_PREFERENCE, formatId); + } - // Set the new number format to the viewer. - fViewer.getPresentationContext().setProperty(PROP_FORMATTED_VALUE_FORMAT_PREFERENCE, formatId); while (!fViewerListener.isFinished(ALL_UPDATES_COMPLETE | PROPERTY_UPDATES) || !fVMListener.isFinished(CONTENT_UPDATES | PROPERTY_UPDATES)) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); if (expectCacheMissError) { try { - validateModel(formatId, ""); + validateModel(expectElementFormats, formatId, "", formatId, ""); throw new RuntimeException("Expected validateModel to fail"); } catch(AssertionFailedError e) { // expected } } else { - validateModel(formatId, ""); + validateModel(expectElementFormats, formatId, "", formatId, ""); } if (expectCacheMissError) { @@ -332,8 +800,23 @@ abstract public class FormattedValueTests extends TestCase implements IViewerUpd Assert.assertFalse(fFormattedValuesListener.getPropertiesUpdates().isEmpty()); for (IPropertiesUpdate update : fFormattedValuesListener.getPropertiesUpdates()) { PropertiesUpdateStatus status = (PropertiesUpdateStatus)update.getStatus(); - assertEquals(IDsfStatusConstants.INVALID_STATE, status.getCode()); - assertEquals("Cache contains stale data. Refresh view.", status.getStatus(formatProperty).getMessage()); + assertEquals(IDsfStatusConstants.INVALID_STATE, status.getCode()); + ElementFormatSetting elementFormat = null; + if (expectElementFormats != null) { + TreePath viewerPath = update.getElementPath(); + for (ElementFormatSetting es : expectElementFormats) { + if (es.elementPaths.indexOf(viewerPath) >= 0) { + elementFormat = es; + break; + } + } + } + if (elementFormat != null) { + assertEquals("Cache contains stale data. Refresh view.", status.getStatus( + FormattedValueVMUtil.getPropertyForFormatId(elementFormat.formatId)).getMessage()); + } else { + assertEquals("Cache contains stale data. Refresh view.", status.getStatus(formatProperty).getMessage()); + } assertEquals( "Cache contains stale data. Refresh view.", status.getStatus(PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE).getMessage()); @@ -352,18 +835,43 @@ abstract public class FormattedValueTests extends TestCase implements IViewerUpd } private void validateModel(final String formatId, final String suffix, final String dummyFormatId, final String dummySuffix) { + validateModel(null, formatId, suffix, dummyFormatId, dummySuffix); + } + + private void validateModel(final ArrayList elementFormats, + final String formatId, final String suffix, final String dummyFormatId, final String dummySuffix) { fModel.validateData( fViewer, TreePath.EMPTY, new TestElementValidator() { public void validate(TestElement modelElement, TestElement viewerElement, TreePath viewerPath) { ViewerLabel label = fViewer.getElementLabel(viewerPath, TestModelCachingVMProvider.COLUMN_ID); assertEquals(modelElement.getID(), label.getText()); - + ElementFormatSetting elementFormat = null; + if (elementFormats != null) { + for (ElementFormatSetting es : elementFormats) { + if (es.elementPaths.indexOf(viewerPath) >= 0) { + elementFormat = es; + break; + } + } + } label = fViewer.getElementLabel(viewerPath, TestModelCachingVMProvider.COLUMN_FORMATTED_VALUE); - assertEquals(fModel.getFormattedValueText(modelElement, formatId) + suffix, label.getText()); + if (elementFormat == null || elementFormat.formatId == null) { + assertEquals(fModel.getFormattedValueText(modelElement, formatId) + suffix, label.getText()); + } else { + String suffix = elementFormat.formatId.equals(formatId) ? "" : + " (" + FormattedValueVMUtil.getFormatLabel(elementFormat.formatId) + ")"; + assertEquals(fModel.getFormattedValueText(modelElement, elementFormat.formatId) + suffix , label.getText()); + } label = fViewer.getElementLabel(viewerPath, TestModelCachingVMProvider.COLUMN_DUMMY_VALUE); - assertEquals(dummyFormatId + dummySuffix, label.getText()); + if (elementFormat == null || elementFormat.formatId == null) { + assertEquals(dummyFormatId + dummySuffix, label.getText()); + } else { + String suffix = elementFormat.formatId.equals(formatId) ? "" : + " (" + FormattedValueVMUtil.getFormatLabel(elementFormat.formatId) + ")"; + assertEquals(elementFormat.formatId + suffix, label.getText()); + } } }); } diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestElementFormatVMProvider.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestElementFormatVMProvider.java new file mode 100644 index 00000000000..79b1aa202ec --- /dev/null +++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestElementFormatVMProvider.java @@ -0,0 +1,101 @@ +/***************************************************************** + * Copyright (c) 2011 Texas Instruments 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: + * Winnie Lai (Texas Instruments) - Individual Element Number Format (Bug 202556) + *****************************************************************/ +package org.eclipse.cdt.tests.dsf.vm; + +import java.util.HashSet; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IElementFormatProvider; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.update.ElementFormatEvent; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter; +import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.jface.viewers.TreePath; + +/** + * Test view model provider that supports element format provider interface. + * This class is used in test cases and can be extended to support other + * optional interfaces + */ +class TestElementFormatVMProvider extends TestModelCachingVMProvider implements IElementFormatProvider { + public int elementFormatApplyDepth = 1; + String myPersistId = "org.eclipse.cdt.tests.dsf.vm.testElementFormatVMProvider"; + + public TestElementFormatVMProvider(AbstractVMAdapter adapter, + IPresentationContext context, DsfSession session) { + super(adapter, context, session); + } + + public void getActiveFormat(IPresentationContext context, IVMNode node, + Object viewerInput, TreePath elementPath, DataRequestMonitor rm) { + Object p = context.getProperty(myPersistId); + if (p instanceof TestPersistable == false) { + rm.setData(null); + rm.done(); + return; + } + TestPersistable persistable = (TestPersistable) p; + int end = elementPath.getSegmentCount(); + int start = elementPath.getSegmentCount() - 1; + if (elementFormatApplyDepth == -1) { + start = 0; + } else if (elementFormatApplyDepth >= 1) { + start = elementPath.getSegmentCount() - elementFormatApplyDepth; + } + if (start < 0) + start = 0; + for (int i = end; --i >= start;) { + Object x = elementPath.getSegment(i); + if (x instanceof TestElementVMContext) { + String s = ((TestElementVMContext) x).getElement().getID(); + String format = persistable.getFormat(s); + if (format != null) { + rm.setData(format); + rm.done(); + return; + } + } + } + rm.setData(null); + rm.done(); + } + + public void setActiveFormat(IPresentationContext context, IVMNode[] node, + Object viewerInput, TreePath[] elementPath, String format) { + Object p = context.getProperty(myPersistId); + TestPersistable persistable = null; + if (p instanceof TestPersistable) { + persistable = (TestPersistable) p; + } else { + persistable = new TestPersistable(); + context.setProperty(myPersistId, persistable); + } + HashSet changed = new HashSet(elementPath.length); + for (int i = 0; i < elementPath.length; i++) { + Object x = elementPath[i].getLastSegment(); + if (x instanceof TestElementVMContext) { + String s = ((TestElementVMContext) x).getElement().getID(); + persistable.setFormat(s, format); + changed.add(x); + } + } + if (changed.size() > 0) { +// this.refresh(); + handleEvent(new ElementFormatEvent(changed, elementFormatApplyDepth)); + } + } + + public boolean supportFormat(IVMContext context) { + return true; + } +} diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestModelDMVMNode.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestModelDMVMNode.java index 19f15555ec8..18119d10084 100644 --- a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestModelDMVMNode.java +++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestModelDMVMNode.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2010 Wind River Systems and others. + * Copyright (c) 2008, 2011 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 @@ -7,15 +7,20 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Winnie Lai (Texas Instruments) - Individual Element Number Format (Bug 202556) *******************************************************************************/ package org.eclipse.cdt.tests.dsf.vm; +import java.util.Iterator; +import java.util.Set; + import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueLabelText; import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueRetriever; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.update.ElementFormatEvent; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode; import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; @@ -210,6 +215,10 @@ public class TestModelDMVMNode extends AbstractDMVMNode implements IRootVMNode, { return IModelDelta.CONTENT; } + if ( e instanceof ElementFormatEvent) + { + return IModelDelta.STATE; + } if (e instanceof TestEvent) { return ((TestEvent)e).getType(); } @@ -223,6 +232,14 @@ public class TestModelDMVMNode extends AbstractDMVMNode implements IRootVMNode, { parent.setFlags(parent.getFlags() | IModelDelta.CONTENT); } + if ( e instanceof ElementFormatEvent) + { + Set elements = ((ElementFormatEvent) e).getElements(); + Iterator it = elements.iterator(); + while (it.hasNext()) { + parent.addNode(it.next(), IModelDelta.STATE); + } + } rm.done(); } @@ -238,6 +255,10 @@ public class TestModelDMVMNode extends AbstractDMVMNode implements IRootVMNode, { flags |= IModelDelta.CONTENT; } + if ( event instanceof ElementFormatEvent) + { + flags |= IModelDelta.CONTENT; + } // TODO: make more sophisticated to update specific elements. if (event instanceof TestEvent) { diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestPersistable.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestPersistable.java new file mode 100644 index 00000000000..a6ed00a8d70 --- /dev/null +++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestPersistable.java @@ -0,0 +1,83 @@ +/***************************************************************** + * Copyright (c) 2011 Texas Instruments 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: + * Winnie Lai (Texas Instruments) - Individual Element Number Format (Bug 202556) + *****************************************************************/ +package org.eclipse.cdt.tests.dsf.vm; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map.Entry; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IPersistableElement; + +/** + * Test persistable for junit test cases. This is used along with element format + * test cases, and can be extended to support other persistable properties + * contained in PresentationContext, e.g. type cast/cast as array. + */ +class TestPersistable implements IPersistableElement, IAdaptable { + + HashMap map = new HashMap(); + + public void saveState(IMemento memento) { + HashMap clone = null; + synchronized (map) { + clone = new HashMap(map); + } + Iterator> it = clone.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + IMemento value = memento.createChild("variable", entry.getKey()); + value.putString("format", entry.getValue()); + } + } + + void restore(IMemento memento) { + IMemento[] list = memento.getChildren("variable"); + HashMap clone = new HashMap(); + for (int i = 0; i < list.length; i++) { + clone.put(list[i].getID(), list[i].getString("format")); + } + synchronized (map) { + map.clear(); + map.putAll(clone); + } + } + + String getFormat(String key) { + if (key == null) + return null; + synchronized (map) { + return map.get(key); + } + } + + void setFormat(String key, String format) { + synchronized (map) { + if (format == null) { + map.remove(key); + } else { + map.put(key, format); + } + } + } + + public String getFactoryId() { + return TestPersistableFactory.factoryId; + } + + public Object getAdapter(Class adapter) { + if (adapter.isInstance(this)) { + return this; + } + return null; + } +} diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestPersistableFactory.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestPersistableFactory.java new file mode 100644 index 00000000000..bcf685eac47 --- /dev/null +++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/vm/TestPersistableFactory.java @@ -0,0 +1,30 @@ +/***************************************************************** + * Copyright (c) 2011 Texas Instruments 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: + * Winnie Lai (Texas Instruments) - Individual Element Number Format (Bug 202556) + *****************************************************************/ +package org.eclipse.cdt.tests.dsf.vm; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.ui.IElementFactory; +import org.eclipse.ui.IMemento; + +/** + * Factory for TestPersitable + */ +public class TestPersistableFactory implements IElementFactory { + + static String factoryId = "org.eclipse.cdt.tests.dsf.vm.testPersistableFactory"; + + public IAdaptable createElement(IMemento memento) { + TestPersistable x = new TestPersistable(); + x.restore(memento); + return x; + } + +}