mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 09:25:31 +02:00
Bug 321932 - [update policy] When in manual mode, switching number format should still show value in other formats if value is cached.
This commit is contained in:
parent
de6322ba9c
commit
4d3edd80a2
44 changed files with 3956 additions and 844 deletions
|
@ -323,7 +323,7 @@ public class NumberFormatDetailPane implements IDetailPane2, IAdaptable, IProper
|
|||
IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS);
|
||||
if (formats != null) {
|
||||
for (String format : formats) {
|
||||
properties.add(FormattedValueVMUtil.getPropertyForFormatId(format));
|
||||
properties.add(FormattedValueVMUtil.getPropertyForFormatId(format, null));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,7 @@ public class NumberFormatDetailPane implements IDetailPane2, IAdaptable, IProper
|
|||
finalResult.append(SPACES);
|
||||
finalResult.append( FormattedValueVMUtil.getFormatLabel(formatId) );
|
||||
finalResult.append(FORMAT_SEPARATOR);
|
||||
finalResult.append( getData().get(FormattedValueVMUtil.getPropertyForFormatId(formatId)) );
|
||||
finalResult.append( getData().get(FormattedValueVMUtil.getPropertyForFormatId(formatId, null)) );
|
||||
if ( i < formats.length + 1 ) {
|
||||
finalResult.append(CRLF);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.debug.ui.viewmodel;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelForeground;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.jface.preference.JFacePreferences;
|
||||
import org.eclipse.jface.resource.ColorRegistry;
|
||||
import org.eclipse.swt.graphics.Color;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.themes.ITheme;
|
||||
import org.eclipse.ui.themes.IThemeManager;
|
||||
|
||||
/**
|
||||
* Label attribute that sets the label color to the standard workbench
|
||||
* error color. The color is activated when the property update contains
|
||||
* a status with error codes: {@link IDsfStatusConstants#INTERNAL_ERROR},
|
||||
* {@link IDsfStatusConstants#REQUEST_FAILED}, or
|
||||
* {@link IDsfStatusConstants#NOT_SUPPORTED}.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class ErrorLabelForeground extends LabelForeground {
|
||||
|
||||
private static final RGB DEFAULT_COLOR = new RGB(255, 0, 0);
|
||||
|
||||
public ErrorLabelForeground() {
|
||||
super(DEFAULT_COLOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(IStatus status, java.util.Map<String,Object> properties) {
|
||||
return !status.isOK() && status.getCode() >= IDsfStatusConstants.NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RGB getForeground() {
|
||||
IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager();
|
||||
ITheme currentTheme = themeManager.getCurrentTheme();
|
||||
|
||||
ColorRegistry colorRegistry = currentTheme.getColorRegistry();
|
||||
|
||||
Color color = colorRegistry.get(JFacePreferences.ERROR_COLOR);
|
||||
|
||||
if (color != null) {
|
||||
return color.getRGB();
|
||||
}
|
||||
return super.getForeground();
|
||||
}
|
||||
}
|
|
@ -16,6 +16,9 @@ import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText;
|
|||
import org.eclipse.core.runtime.IStatus;
|
||||
|
||||
/**
|
||||
* Label attribute that fills in the text of an error status into the label
|
||||
* column.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ErrorLabelText extends LabelText {
|
||||
|
@ -23,16 +26,14 @@ public class ErrorLabelText extends LabelText {
|
|||
protected final static String PROP_ERROR_MESSAGE = "error_message"; //$NON-NLS-1$
|
||||
|
||||
public ErrorLabelText() {
|
||||
this(
|
||||
MessagesForDebugVM.ErrorLabelText__text_format,
|
||||
new String[] { PROP_ERROR_MESSAGE });
|
||||
this(MessagesForDebugVM.ErrorLabelText__text_format, new String[] {});
|
||||
}
|
||||
|
||||
public ErrorLabelText(String formatPattern, String[] propertyNames) {
|
||||
super(formatPattern, addActiveFormatPropertyNames(propertyNames));
|
||||
super(formatPattern, addErrorMessageProperty(propertyNames));
|
||||
}
|
||||
|
||||
private static String[] addActiveFormatPropertyNames(String[] propertyNames) {
|
||||
private static String[] addErrorMessageProperty(String[] propertyNames) {
|
||||
String[] newPropertyNames = new String[propertyNames.length + 1];
|
||||
System.arraycopy(propertyNames, 0, newPropertyNames, 0, propertyNames.length);
|
||||
newPropertyNames[propertyNames.length + 0] = PROP_ERROR_MESSAGE;
|
||||
|
@ -42,12 +43,24 @@ public class ErrorLabelText extends LabelText {
|
|||
@Override
|
||||
protected Object getPropertyValue(String propertyName, IStatus status, Map<String, Object> properties) {
|
||||
if (PROP_ERROR_MESSAGE.equals(propertyName)) {
|
||||
return status.getMessage().replaceAll(
|
||||
"\n", MessagesForDebugVM.ErrorLabelText_Error_message__text_page_break_delimiter); //$NON-NLS-1$
|
||||
if (status.getChildren().length < 2) {
|
||||
return replaceNewlines(status.getMessage());
|
||||
} else {
|
||||
StringBuffer buf = new StringBuffer( status.getMessage() );
|
||||
for (IStatus childStatus : status.getChildren()) {
|
||||
buf.append(MessagesForDebugVM.ErrorLabelText_Error_message__text_page_break_delimiter);
|
||||
buf.append( replaceNewlines(childStatus.getMessage()) );
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
return super.getPropertyValue(propertyName, status, properties);
|
||||
}
|
||||
|
||||
private String replaceNewlines(String message) {
|
||||
return message.replaceAll("\n", MessagesForDebugVM.ErrorLabelText_Error_message__text_page_break_delimiter); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkProperty(String propertyName, IStatus status, Map<String,Object> properties) {
|
||||
if (PROP_ERROR_MESSAGE.equals(propertyName)) {
|
||||
|
|
|
@ -14,4 +14,4 @@ ErrorLabelText__text_format=Error: {0}
|
|||
|
||||
# If multiple errors are shown in the combined error message, this
|
||||
# string is used as a separator between them.
|
||||
ErrorLabelText_Error_message__text_page_break_delimiter= \
|
||||
ErrorLabelText_Error_message__text_page_break_delimiter= \\
|
|
@ -10,45 +10,62 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat;
|
||||
|
||||
import com.ibm.icu.text.MessageFormat;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
|
||||
import com.ibm.icu.text.MessageFormat;
|
||||
|
||||
/**
|
||||
*
|
||||
* Label attribute that fills in the formatted value text using the active
|
||||
* number format for the view.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class FormattedValueLabelText extends LabelText {
|
||||
|
||||
private final String fPropertyPrefix;
|
||||
private final String PROP_ACTIVE_FORMAT;
|
||||
private final String PROP_ACTIVE_FORMAT_VALUE;
|
||||
|
||||
public FormattedValueLabelText() {
|
||||
this(
|
||||
MessagesForNumberFormat.FormattedValueLabelText__text_format,
|
||||
new String[] { IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE });
|
||||
this(MessagesForNumberFormat.FormattedValueLabelText__text_format, new String[0], ""); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public FormattedValueLabelText(String popertyPrefix) {
|
||||
this(MessagesForNumberFormat.FormattedValueLabelText__text_format, new String[0], popertyPrefix);
|
||||
}
|
||||
|
||||
public FormattedValueLabelText(String formatPattern, String[] propertyNames) {
|
||||
super(formatPattern, addActiveFormatPropertyNames(propertyNames));
|
||||
this(formatPattern, propertyNames, ""); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private static String[] addActiveFormatPropertyNames(String[] propertyNames) {
|
||||
String[] newPropertyNames = new String[propertyNames.length + 2];
|
||||
|
||||
public FormattedValueLabelText(String formatPattern, String[] propertyNames, String propertyPrefix) {
|
||||
super(formatPattern, addActiveFormatPropertyNames(propertyNames, propertyPrefix));
|
||||
fPropertyPrefix = propertyPrefix;
|
||||
PROP_ACTIVE_FORMAT = (fPropertyPrefix + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT).intern();
|
||||
PROP_ACTIVE_FORMAT_VALUE = (fPropertyPrefix + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE).intern();
|
||||
}
|
||||
|
||||
private static String[] addActiveFormatPropertyNames(String[] propertyNames, String prefix) {
|
||||
String[] newPropertyNames = new String[propertyNames.length + 4];
|
||||
System.arraycopy(propertyNames, 0, newPropertyNames, 0, propertyNames.length);
|
||||
newPropertyNames[propertyNames.length + 0] = IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT;
|
||||
newPropertyNames[propertyNames.length + 1] = IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE;
|
||||
newPropertyNames[propertyNames.length + 0] = (prefix + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE).intern();
|
||||
newPropertyNames[propertyNames.length + 1] = (prefix + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT).intern();
|
||||
newPropertyNames[propertyNames.length + 2] = (prefix + IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS).intern();
|
||||
newPropertyNames[propertyNames.length + 3] = IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE;
|
||||
return newPropertyNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getPropertyValue(String propertyName, IStatus status, Map<String, Object> properties) {
|
||||
// If the format is not the same as the preferred format, include it in the value string.
|
||||
if ( IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE.equals(propertyName) ) {
|
||||
Object activeFormat = properties.get(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT);
|
||||
if ( PROP_ACTIVE_FORMAT_VALUE.equals(propertyName) ) {
|
||||
Object activeFormat = properties.get(PROP_ACTIVE_FORMAT);
|
||||
Object preferredFormat = properties.get(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE);
|
||||
Object value = properties.get(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE);
|
||||
Object value = properties.get(PROP_ACTIVE_FORMAT_VALUE);
|
||||
if (value != null && activeFormat != null && !activeFormat.equals(preferredFormat)) {
|
||||
return MessageFormat.format(
|
||||
MessagesForNumberFormat.FormattedValueLabelText__Value__text_format,
|
||||
|
@ -63,8 +80,8 @@ public class FormattedValueLabelText extends LabelText {
|
|||
@Override
|
||||
public boolean isEnabled(IStatus status, Map<String, Object> properties) {
|
||||
for (String property : getPropertyNames()) {
|
||||
if ( IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT.equals(property) ||
|
||||
IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE.equals(property) )
|
||||
if ( PROP_ACTIVE_FORMAT.equals(property) ||
|
||||
IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE.equals(property) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,608 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData;
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.IFormattedDataDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
|
||||
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.datamodel.IDMVMContext;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesUpdateStatus;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.ICacheEntry;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.ICachingVMProviderExtension2;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.IVMUpdatePolicyExtension;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.osgi.framework.Filter;
|
||||
import org.osgi.framework.InvalidSyntaxException;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
/**
|
||||
* A helper class for View Model Node implementations that support elements
|
||||
* to be formatted using different number formats. This object can be
|
||||
* instantiated by a VM node to retrieve formatted values from a given service
|
||||
* using given DMC type.
|
||||
* <p>
|
||||
* Note: This class is a replacement for the {@link FormattedValueVMUtil#updateFormattedValues(IPropertiesUpdate[], IFormattedValues, Class, RequestMonitor)}
|
||||
* static method. This new implementation retrieves cached values if they are
|
||||
* available in the VM Cache.
|
||||
* </p>
|
||||
*
|
||||
* @see FormattedValueVMUtil
|
||||
* @see org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider
|
||||
* @see org.eclipse.cdt.dsf.debug.service.IFormattedValues
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class FormattedValueRetriever {
|
||||
|
||||
private final IVMNode fNode;
|
||||
private final ICachingVMProviderExtension2 fCache;
|
||||
private final ServiceTracker fServiceTracker;
|
||||
private final Class<? extends IFormattedDataDMContext> fDmcType;
|
||||
private final String fPropertyPrefix;
|
||||
|
||||
private final String PROP_AVAILABLE_FORMATS;
|
||||
private final String PROP_ACTIVE_FORMAT;
|
||||
private final String PROP_ACTIVE_FORMAT_VALUE;
|
||||
private final String PROP_BASE;
|
||||
|
||||
public FormattedValueRetriever(IVMNode node, DsfSession session, Class<?> serviceClass, Class<? extends IFormattedDataDMContext> dmcType) {
|
||||
this(node, createFilter(session, serviceClass), dmcType, null);
|
||||
}
|
||||
|
||||
public FormattedValueRetriever(IVMNode node, DsfSession session, Class<?> serviceClass, Class<? extends IFormattedDataDMContext> dmcType, String propertyPrefix) {
|
||||
this(node, createFilter(session, serviceClass), dmcType, propertyPrefix);
|
||||
}
|
||||
|
||||
public FormattedValueRetriever(IVMNode node, Filter filter, Class<? extends IFormattedDataDMContext> dmcType, String propertyPrefix) {
|
||||
fNode = node;
|
||||
fCache = (ICachingVMProviderExtension2)node.getVMProvider();
|
||||
fServiceTracker = new ServiceTracker(DsfUIPlugin.getBundleContext(), filter, null);
|
||||
fServiceTracker.open();
|
||||
fDmcType = dmcType;
|
||||
if (propertyPrefix == null) {
|
||||
propertyPrefix = ""; //$NON-NLS-1$
|
||||
}
|
||||
fPropertyPrefix = propertyPrefix;
|
||||
PROP_AVAILABLE_FORMATS = (fPropertyPrefix + IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS).intern();
|
||||
PROP_ACTIVE_FORMAT = (fPropertyPrefix + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT).intern();
|
||||
PROP_ACTIVE_FORMAT_VALUE = (fPropertyPrefix + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE).intern();
|
||||
PROP_BASE = (fPropertyPrefix + IDebugVMConstants.PROP_FORMATTED_VALUE_BASE).intern();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an OSGI service filter for the given service type in a given
|
||||
* DSF session.
|
||||
*/
|
||||
private static Filter createFilter(DsfSession session, Class<?> serviceClass) {
|
||||
try {
|
||||
return DsfUIPlugin.getBundleContext().createFilter( DsfServices.createServiceFilter(serviceClass, session.getId()) );
|
||||
} catch (InvalidSyntaxException e) {
|
||||
throw new RuntimeException("Unable to create service filter for " + serviceClass, e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
fServiceTracker.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method fills in the formatted value properties in the given array
|
||||
* of property update objects using data retrieved from the given
|
||||
* formatted values service.
|
||||
* <p>
|
||||
* Note: The node parameter must return a <code>ICachingVMProviderExtension2</code>
|
||||
* through its {@link IVMNode#getVMProvider()} method.
|
||||
*
|
||||
* @param node This method also takes an <code>IVMNode</code> parameter
|
||||
* which allows for retrieving the format value data from the View Model
|
||||
* cache. If the needed value property is cached already, the cached
|
||||
* value will be used otherwise the properties will be retrieved from the
|
||||
* service.
|
||||
*
|
||||
* @param updates The array of updates to fill in information to. This
|
||||
* update is used to retrieve the data model context and to write the
|
||||
* properties into. Implementation will not directly mark these updates
|
||||
* complete, but contribute towards that end by marking [monitor] complete.
|
||||
*
|
||||
* @param service The service to be used to retrieve the values from.
|
||||
*
|
||||
* @param dmcType The class type of the data model context. Some updates
|
||||
* can contain multiple formatted data data model contexts, and this
|
||||
* method assures that there is no ambiguity in which context should be
|
||||
* used.
|
||||
*
|
||||
* @param rm Request monitor used to signal completion of work
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
@ConfinedToDsfExecutor("node.getExecutor()")
|
||||
public void update(final IPropertiesUpdate updates[], final RequestMonitor rm)
|
||||
{
|
||||
final Map<IPropertiesUpdate, String[]> 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;
|
||||
}
|
||||
|
||||
try {
|
||||
service.getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
retrieveAvailableFormats(
|
||||
calcOutstandingAvailableFormatsUpdates(updates, cachedAvailableFormatsMap),
|
||||
new DataRequestMonitor<Map<IPropertiesUpdate, String[]>>(fNode.getVMProvider().getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
Map<IPropertiesUpdate, String[]> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the <code>PROP_FORMATTED_VALUE_AVAILABLE_FORMATS</code>
|
||||
* property for each update and returns it in a map. The returned
|
||||
* map may be <code>null</code> if no cache data is available.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
private Map<IPropertiesUpdate, String[]> calcCachedAvailableFormatsMap(IPropertiesUpdate updates[]) {
|
||||
Map<IPropertiesUpdate, String[]> cachedAvailableFormatsMap = null; // delay creating map till needed
|
||||
for (IPropertiesUpdate update : updates) {
|
||||
ICacheEntry cacheEntry = fCache.getCacheEntry(fNode, update.getViewerInput(), update.getElementPath());
|
||||
if (cacheEntry != null && cacheEntry.getProperties() != null) {
|
||||
String[] availableFormats = (String[])
|
||||
cacheEntry.getProperties().get(PROP_AVAILABLE_FORMATS);
|
||||
// Add the cached entry to the cached map even if its null. This will help keep track
|
||||
// of whether we need to call the service for data.
|
||||
if (availableFormats != null || !isAvailableFormatsPropertyNeeded(update)) {
|
||||
if (cachedAvailableFormatsMap == null) {
|
||||
cachedAvailableFormatsMap = new HashMap<IPropertiesUpdate, String[]>(updates.length * 4/3);
|
||||
}
|
||||
cachedAvailableFormatsMap.put(update, availableFormats);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cachedAvailableFormatsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a list of updates which still need the
|
||||
* <code>PROP_FORMATTED_VALUE_AVAILABLE_FORMATS</code> property.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
private List<IPropertiesUpdate> calcOutstandingAvailableFormatsUpdates(IPropertiesUpdate[] updates, Map<IPropertiesUpdate, String[]> cachedAvailableFormatsMap) {
|
||||
if (cachedAvailableFormatsMap != null) {
|
||||
List<IPropertiesUpdate> outstandingUpdates = new ArrayList<IPropertiesUpdate>(updates.length - cachedAvailableFormatsMap.size());
|
||||
for (IPropertiesUpdate update : updates) {
|
||||
if (!cachedAvailableFormatsMap.containsKey(update)) {
|
||||
outstandingUpdates.add(update);
|
||||
}
|
||||
}
|
||||
return outstandingUpdates;
|
||||
} else {
|
||||
return Arrays.asList(updates);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to retrieve available formats for each update's element (if
|
||||
* needed). The result is returned in a map and in the
|
||||
* update object (if requested).
|
||||
* <p>
|
||||
* Note that we use a synchronized map because it's updated by a request
|
||||
* monitor with an ImmediateExecutor.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
@ConfinedToDsfExecutor("service.getExecutor()")
|
||||
private void retrieveAvailableFormats(
|
||||
final List<IPropertiesUpdate> updates,
|
||||
final DataRequestMonitor<Map<IPropertiesUpdate, String[]>> rm)
|
||||
{
|
||||
IFormattedValues service = (IFormattedValues)fServiceTracker.getService();
|
||||
assert service.getExecutor().isInExecutorThread();
|
||||
|
||||
final Map<IPropertiesUpdate, String[]> availableFormats = Collections.synchronizedMap(new HashMap<IPropertiesUpdate, String[]>(updates.size() * 4/3));
|
||||
rm.setData(availableFormats);
|
||||
final CountingRequestMonitor countingRm = new CountingRequestMonitor(service.getExecutor(), rm);
|
||||
int count = 0;
|
||||
|
||||
for (final IPropertiesUpdate update : updates) {
|
||||
|
||||
if (!isAvailableFormatsPropertyNeeded(update)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IFormattedDataDMContext dmc = getFormattedDataDMContext(update);
|
||||
if (dmc == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
service.getAvailableFormats(
|
||||
dmc,
|
||||
new ViewerDataRequestMonitor<String[]>(ImmediateExecutor.getInstance(), update) {
|
||||
/**
|
||||
* Note we don't mark the update object done, and we
|
||||
* avoid calling our base implementation so that it
|
||||
* doesn't either. The completion of this request is
|
||||
* just a step in servicing the update.
|
||||
*/
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isSuccess()) {
|
||||
// Set the result (available formats) into the update object if it was requested
|
||||
if (update.getProperties().contains(PROP_AVAILABLE_FORMATS)) {
|
||||
update.setProperty(PROP_AVAILABLE_FORMATS, getData());
|
||||
}
|
||||
|
||||
if (getData().length != 0) {
|
||||
// also add it to the map; we'll need to access it when querying the element's value.
|
||||
availableFormats.put(update, getData());
|
||||
} else {
|
||||
update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "No number formats available for " + update.getElement(), null)); //$NON-NLS-1$
|
||||
}
|
||||
} else {
|
||||
update.setStatus(getStatus());
|
||||
}
|
||||
countingRm.done();
|
||||
}
|
||||
});
|
||||
count++;
|
||||
}
|
||||
countingRm.setDoneCount(count);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method continues retrieving formatted value properties. It is
|
||||
* called once the available formats are calculated for each requested
|
||||
* update.
|
||||
*
|
||||
* @param availableFormatsMap Prior to calling this method, the caller
|
||||
* queries (where necessary) the formats supported by the element in each
|
||||
* update, and it puts that information in this map. If an entry in
|
||||
* [updates] does not appear in this map, it means that its view-model
|
||||
* element doesn't support any formats (very unlikely), or that the
|
||||
* available formats aren't necessary to service the properties specified
|
||||
* in the update
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
@ConfinedToDsfExecutor("fNode.getExecutor()")
|
||||
private void doUpdateWithAvailableFormats(
|
||||
IPropertiesUpdate updates[],
|
||||
final Map<IPropertiesUpdate, String[]> availableFormatsMap,
|
||||
final RequestMonitor rm)
|
||||
{
|
||||
final List<IPropertiesUpdate> outstandingUpdates = new ArrayList<IPropertiesUpdate>(updates.length);
|
||||
final Map<IPropertiesUpdate, List<String>> requestedFormatsMap = new HashMap<IPropertiesUpdate, List<String>>(updates.length * 4 / 3);
|
||||
final Map<IPropertiesUpdate, String> activeFormatsMap = new HashMap<IPropertiesUpdate, String>(updates.length * 4 / 3);
|
||||
|
||||
for (final IPropertiesUpdate update : updates) {
|
||||
String preferredFormat = FormattedValueVMUtil.getPreferredFormat(update.getPresentationContext());
|
||||
if (update.getProperties().contains(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE)) {
|
||||
update.setProperty(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE, preferredFormat);
|
||||
}
|
||||
|
||||
final String activeFormat = calcActiveFormat(update, preferredFormat, availableFormatsMap);
|
||||
|
||||
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$
|
||||
update.setProperty(PROP_ACTIVE_FORMAT, activeFormat);
|
||||
}
|
||||
List<String> requestedFormats = calcRequestedFormats(update, activeFormat, availableFormatsMap.get(update));
|
||||
|
||||
ICacheEntry cacheEntry = fCache.getCacheEntry(fNode, update.getViewerInput(), update.getElementPath());
|
||||
if (cacheEntry != null && cacheEntry.getProperties() != null) {
|
||||
IVMUpdatePolicyExtension updatePolicy = getVMUpdatePolicyExtension();
|
||||
Iterator<String> itr = requestedFormats.iterator();
|
||||
while (itr.hasNext()) {
|
||||
String format = itr.next();
|
||||
String formatProperty = FormattedValueVMUtil.getPropertyForFormatId(format, fPropertyPrefix);
|
||||
Object value = cacheEntry.getProperties().get(formatProperty);
|
||||
if (value != null || !canUpdateProperty(cacheEntry, updatePolicy, formatProperty)) {
|
||||
itr.remove();
|
||||
setUpdateFormatProperty(update, activeFormat, format, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!requestedFormats.isEmpty()) {
|
||||
outstandingUpdates.add(update);
|
||||
requestedFormatsMap.put(update, requestedFormats);
|
||||
activeFormatsMap.put(update, activeFormat);
|
||||
}
|
||||
}
|
||||
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() {
|
||||
doUpdateWithRequestedFormats(outstandingUpdates, requestedFormatsMap, activeFormatsMap, 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 IVMUpdatePolicyExtension getVMUpdatePolicyExtension() {
|
||||
if( fCache.getActiveUpdatePolicy() instanceof IVMUpdatePolicyExtension) {
|
||||
return (IVMUpdatePolicyExtension)fCache.getActiveUpdatePolicy();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean canUpdateProperty(ICacheEntry entry, IVMUpdatePolicyExtension updatePolicy, String property) {
|
||||
return !entry.isDirty() || (updatePolicy != null && updatePolicy.canUpdateDirtyProperty(entry, property));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the specified formatted values from the service.
|
||||
*
|
||||
* @param requestedFormatsMap Map containing the formats to be retrieved
|
||||
* and filled in for each given update.
|
||||
* @param activeFormatsMap Map containing the active format for each given
|
||||
* update. The active format value needs to be set in the update using the
|
||||
* special property <code>PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE</code>.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
@ConfinedToDsfExecutor("service.getExecutor()")
|
||||
private void doUpdateWithRequestedFormats(
|
||||
List<IPropertiesUpdate> updates,
|
||||
final Map<IPropertiesUpdate, List<String>> requestedFormatsMap,
|
||||
final Map<IPropertiesUpdate, String> activeFormatsMap,
|
||||
final RequestMonitor monitor)
|
||||
{
|
||||
IFormattedValues service = (IFormattedValues)fServiceTracker.getService();
|
||||
assert service.getExecutor().isInExecutorThread();
|
||||
|
||||
// Use a single counting RM for all the requested formats for each update.
|
||||
final CountingRequestMonitor countingRm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), monitor);
|
||||
int count = 0;
|
||||
|
||||
for (final IPropertiesUpdate update : updates) {
|
||||
IFormattedDataDMContext dmc = getFormattedDataDMContext(update);
|
||||
if (dmc == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<String> requestedFormats = requestedFormatsMap.get(update);
|
||||
for (String requestedFormat : requestedFormats) {
|
||||
final FormattedValueDMContext formattedValueDmc = service.getFormattedValueContext(dmc, requestedFormat);
|
||||
service.getFormattedExpressionValue(
|
||||
formattedValueDmc,
|
||||
// Here also use the ViewerDataRequestMonitor in order to propagate the update's cancel request.
|
||||
// However, when operation is complete, call the counting RM's done().
|
||||
// Use an immediate executor to avoid the possibility of a rejected execution exception.
|
||||
new ViewerDataRequestMonitor<FormattedValueDMData>(ImmediateExecutor.getInstance(), update) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isSuccess()) {
|
||||
setUpdateFormatProperty(
|
||||
update,
|
||||
activeFormatsMap.get(update),
|
||||
formattedValueDmc.getFormatID(),
|
||||
getData().getFormattedValue());
|
||||
} else {
|
||||
update.setStatus(getStatus());
|
||||
}
|
||||
// Note: we must not call the update's done method, instead call counting RM done.
|
||||
countingRm.done();
|
||||
|
||||
};
|
||||
});
|
||||
count++;
|
||||
}
|
||||
}
|
||||
countingRm.setDoneCount(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the 'active' value format. It is the view preference if
|
||||
* and only if the element supports it. Otherwise it is the first
|
||||
* format supported by the element.
|
||||
* <p>
|
||||
* Note: If the availableFormatsMap doesn't contain the available formats
|
||||
* for the given update, it means the update doesn't request any properties
|
||||
* which requires the active format to be calculated.
|
||||
*
|
||||
* @param update Properties update to calculate the active format for.
|
||||
* @param availableFormatsMap The map of available formats.
|
||||
* @return The active format, or null if active format not requested in
|
||||
* update.
|
||||
*/
|
||||
private String calcActiveFormat(IPropertiesUpdate update, String preferredFormat, Map<IPropertiesUpdate, String[]> availableFormatsMap) {
|
||||
String[] availableFormats = availableFormatsMap.get(update);
|
||||
if (availableFormats != null && availableFormats.length != 0) {
|
||||
if (isFormatAvailable(preferredFormat, availableFormats)) {
|
||||
return preferredFormat;
|
||||
} else {
|
||||
return availableFormats[0];
|
||||
}
|
||||
}
|
||||
return null; // null means we don't need to know what the active format is
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the given availableFormats array contains
|
||||
* the given format.
|
||||
*/
|
||||
private boolean isFormatAvailable(String format, String[] availableFormats) {
|
||||
for (String availableFormat : availableFormats) {
|
||||
if (availableFormat.equals(format)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service the properties that ask for the value in a specific
|
||||
* format. If the update request contains the property
|
||||
* PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, and the active format
|
||||
* has not been explicitly requested, then we need an additional
|
||||
* iteration to provide it.
|
||||
*/
|
||||
private List<String> calcRequestedFormats(IPropertiesUpdate update, String activeFormat, String[] availableFormats) {
|
||||
List<String> requestedFormats = new ArrayList<String>(10);
|
||||
|
||||
boolean activeFormatValueHandled = false; // have we come across a specific format request that is the active format?
|
||||
|
||||
for (Iterator<String> itr = update.getProperties().iterator(); itr.hasNext() || (activeFormat != null && !activeFormatValueHandled);) {
|
||||
String nextFormat;
|
||||
if (itr.hasNext()) {
|
||||
String propertyName = itr.next();
|
||||
if (propertyName.startsWith(PROP_BASE)) {
|
||||
nextFormat = FormattedValueVMUtil.getFormatFromProperty(propertyName, fPropertyPrefix);
|
||||
if (nextFormat.equals(activeFormat)) {
|
||||
activeFormatValueHandled = true;
|
||||
}
|
||||
// if we know the supported formats (we may not), then no-op if this format is unsupported
|
||||
if (availableFormats != null && !isFormatAvailable(nextFormat, availableFormats)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// the additional iteration to handle the active format
|
||||
nextFormat = activeFormat;
|
||||
activeFormatValueHandled = true;
|
||||
}
|
||||
requestedFormats.add(nextFormat);
|
||||
}
|
||||
return requestedFormats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the given formatted property value into the update. It also
|
||||
* writes the active format property if needed.
|
||||
* <p>
|
||||
* If the given property value is null, this method writes an error status
|
||||
* instead.
|
||||
*/
|
||||
private void setUpdateFormatProperty(IPropertiesUpdate update, String activeFormat, String format, Object value) {
|
||||
String formatProperty = FormattedValueVMUtil.getPropertyForFormatId(format, fPropertyPrefix);
|
||||
if (value != null) {
|
||||
update.setProperty(formatProperty, value);
|
||||
if (update.getProperties().contains(PROP_ACTIVE_FORMAT_VALUE) &&
|
||||
format.equals(activeFormat))
|
||||
{
|
||||
update.setProperty(PROP_ACTIVE_FORMAT_VALUE, value);
|
||||
}
|
||||
} else {
|
||||
IStatus staleDataStatus = DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_STATE, "Cache contains stale data. Refresh view.", null );//$NON-NLS-1$
|
||||
if (update.getProperties().contains(PROP_ACTIVE_FORMAT_VALUE) &&
|
||||
format.equals(activeFormat))
|
||||
{
|
||||
PropertiesUpdateStatus.getPropertiesStatus(update).setStatus(
|
||||
new String[] { PROP_ACTIVE_FORMAT_VALUE, formatProperty },
|
||||
staleDataStatus);
|
||||
} else {
|
||||
PropertiesUpdateStatus.getPropertiesStatus(update).setStatus(formatProperty, staleDataStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For each update, query the formats available for the update's
|
||||
* element...but only if necessary. The available formats are necessary
|
||||
* only if the update explicitly requests that information, or if the
|
||||
* update is asking what the active format is or is asking for the value
|
||||
* of the element in that format. The reason we need them in the last
|
||||
* two cases is that we can't establish the 'active' format for an
|
||||
* element without knowing its available formats. See
|
||||
* updateFormattedValuesWithAvailableFormats(), as that's where we make
|
||||
* that determination.
|
||||
* @param update
|
||||
* @return
|
||||
*/
|
||||
private boolean isAvailableFormatsPropertyNeeded(IPropertiesUpdate update) {
|
||||
return update.getProperties().contains(PROP_AVAILABLE_FORMATS) ||
|
||||
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
|
||||
* <code>null</code>.
|
||||
*/
|
||||
private IFormattedDataDMContext getFormattedDataDMContext(IPropertiesUpdate update)
|
||||
{
|
||||
IFormattedDataDMContext dmc = null;
|
||||
if (update.getElement() instanceof IDMVMContext) {
|
||||
dmc = DMContexts.getAncestorOfType(((IDMVMContext)update.getElement()).getDMContext(), fDmcType);
|
||||
}
|
||||
|
||||
if (dmc == null) {
|
||||
update.setStatus(DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_HANDLE, "Update element did not contain a valid context: " + fDmcType, null)); //$NON-NLS-1$
|
||||
}
|
||||
return dmc;
|
||||
}
|
||||
}
|
|
@ -10,12 +10,11 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat;
|
||||
|
||||
import com.ibm.icu.text.MessageFormat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||
|
@ -34,6 +33,8 @@ import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
|||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
import com.ibm.icu.text.MessageFormat;
|
||||
|
||||
/**
|
||||
* A helper class for View Model Node implementations that support elements
|
||||
* to be formatted using different number formats. The various static methods in
|
||||
|
@ -47,6 +48,12 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationCont
|
|||
*/
|
||||
public class FormattedValueVMUtil {
|
||||
|
||||
/**
|
||||
* Cache to avoid creating many duplicate strings of formats and properties.
|
||||
*/
|
||||
private static Map<String, Map<String, String>> fFormatProperties =
|
||||
Collections.synchronizedMap(new TreeMap<String, Map<String, String>>());
|
||||
|
||||
/**
|
||||
* Common map of user-readable labels for format IDs.
|
||||
*/
|
||||
|
@ -66,7 +73,7 @@ public class FormattedValueVMUtil {
|
|||
* add its label to the map of format IDs using this method.
|
||||
*
|
||||
* @param formatId Format ID to set the label for.
|
||||
* @param label User-readable lable for a format.
|
||||
* @param label User-readable label for a format.
|
||||
*/
|
||||
public static void setFormatLabel(String formatId, String label) {
|
||||
fFormatLabels.put(formatId, label);
|
||||
|
@ -87,20 +94,102 @@ public class FormattedValueVMUtil {
|
|||
|
||||
/**
|
||||
* Returns an element property representing an element value in a given format.
|
||||
|
||||
* @deprecated Replaced by {@link #getPropertyForFormatId(String, String)}
|
||||
*/
|
||||
public static String getPropertyForFormatId(String formatId) {
|
||||
return getPropertyForFormatId(formatId, ""); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an element property representing an element value in a given format.
|
||||
*
|
||||
* @param Format ID to create the property for.
|
||||
* @param prefix The prefix for the property that is used to distinguish
|
||||
* it from other number format values in a given property map. May be
|
||||
* <code>null</code> or an empty string if no prefix is used.
|
||||
* @return The generated property name.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public static String getPropertyForFormatId(String formatId, String prefix) {
|
||||
if (formatId == null) {
|
||||
return null;
|
||||
}
|
||||
return IDebugVMConstants.PROP_FORMATTED_VALUE_BASE + "." + formatId; //$NON-NLS-1$
|
||||
if (prefix == null) {
|
||||
prefix = ""; //$NON-NLS-1$
|
||||
}
|
||||
synchronized(fFormatProperties) {
|
||||
Map<String, String> formatsMap = getFormatsMap(prefix);
|
||||
String property = formatsMap.get(formatId);
|
||||
if (property == null) {
|
||||
property = (prefix + IDebugVMConstants.PROP_FORMATTED_VALUE_BASE + "." + formatId).intern(); //$NON-NLS-1$
|
||||
formatsMap.put(formatId, property);
|
||||
}
|
||||
return property;
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> getFormatsMap(String prefix) {
|
||||
synchronized(fFormatProperties) {
|
||||
Map<String, String> prefixMap = fFormatProperties.get(prefix);
|
||||
if (prefixMap == null) {
|
||||
prefixMap = new TreeMap<String, String>();
|
||||
fFormatProperties.put(prefix, prefixMap);
|
||||
}
|
||||
return prefixMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a format ID based on the element property representing a
|
||||
* formatted element value.
|
||||
*
|
||||
* @deprecated Replaced by {@link #getFormatFromProperty(String, String)}
|
||||
*/
|
||||
public static String getFormatFromProperty(String property) {
|
||||
return getFormatFromProperty(property, ""); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a format ID based on the element property representing a
|
||||
* formatted element value.
|
||||
* formatted element value. This method has an additional prefix parameter
|
||||
* which is used when multiple number formats are stored in a single
|
||||
* property map.
|
||||
*
|
||||
* @param property The property to extract the format from.
|
||||
* @param prefix The prefix for the property that is used to distinguish
|
||||
* it from other number format values in a given property map. May be
|
||||
* <code>null</code> or an empty string if no prefix is used.
|
||||
* @return The format ID.
|
||||
*
|
||||
* @throws IllegalArgumentException if the property is not a formatted value
|
||||
* property.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public static String getFormatFromProperty(String property) {
|
||||
return property.substring(IDebugVMConstants.PROP_FORMATTED_VALUE_BASE.length() + 1);
|
||||
public static String getFormatFromProperty(String property, String prefix) {
|
||||
if (prefix == null) {
|
||||
prefix = ""; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
synchronized(fFormatProperties) {
|
||||
Map<String, String> formatsMap = getFormatsMap(prefix);
|
||||
for (Map.Entry<String, String> entry : formatsMap.entrySet()) {
|
||||
if (entry.getValue().equals(property)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
if ( !property.startsWith(prefix) ||
|
||||
!property.startsWith(IDebugVMConstants.PROP_FORMATTED_VALUE_BASE, prefix.length()) )
|
||||
{
|
||||
throw new IllegalArgumentException("Property " + property + " is not a valid formatted value format property."); //$NON-NLS-1$//$NON-NLS-2$
|
||||
}
|
||||
String formatId = property.substring(
|
||||
prefix.length() + IDebugVMConstants.PROP_FORMATTED_VALUE_BASE.length() + 1).intern();
|
||||
formatsMap.put(formatId, property);
|
||||
return formatId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,6 +205,7 @@ public class FormattedValueVMUtil {
|
|||
return IFormattedValues.NATURAL_FORMAT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method fills in the formatted value properties in the given array
|
||||
* of property update objects using data retrieved from the given
|
||||
|
@ -131,6 +221,9 @@ public class FormattedValueVMUtil {
|
|||
* method assures that there is no ambiguity in which context should be
|
||||
* used.
|
||||
* @param monitor Request monitor used to signal completion of work
|
||||
*
|
||||
* @deprecated This method has been replaced by the {@link FormattedValueRetriever}
|
||||
* utility.
|
||||
*/
|
||||
@ConfinedToDsfExecutor("service.getExecutor()")
|
||||
public static void updateFormattedValues(
|
||||
|
|
|
@ -22,8 +22,8 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
|||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters;
|
||||
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldChangedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMData;
|
||||
|
@ -33,11 +33,12 @@ import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext;
|
|||
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMData;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelForeground;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelText;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueLabelText;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueRetriever;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValueVMContext;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterBitFieldCellModifier.BitFieldEditorStyle;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableLabelFont;
|
||||
|
@ -56,6 +57,7 @@ import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelForeground;
|
|||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.VMDelegatingPropertiesUpdate;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.ICachingVMProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.StaleDataLabelBackground;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.StaleDataLabelForeground;
|
||||
|
@ -83,7 +85,6 @@ import org.eclipse.jface.viewers.ComboBoxCellEditor;
|
|||
import org.eclipse.jface.viewers.ICellModifier;
|
||||
import org.eclipse.jface.viewers.TextCellEditor;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
public class RegisterBitFieldVMNode extends AbstractExpressionVMNode
|
||||
|
@ -173,12 +174,25 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode
|
|||
*/
|
||||
private IElementLabelProvider fLabelProvider;
|
||||
|
||||
/**
|
||||
* Retriever for formatted values configured for this VM node.
|
||||
* @since 2.2
|
||||
*/
|
||||
private final FormattedValueRetriever fFormattedValueRetriever;
|
||||
|
||||
public RegisterBitFieldVMNode(AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess access) {
|
||||
super(provider, session, IBitFieldDMContext.class);
|
||||
fSyncRegisterDataAccess = access;
|
||||
fLabelProvider = createLabelProvider();
|
||||
fFormattedValueRetriever =
|
||||
new FormattedValueRetriever(this, session, IRegisters.class, IBitFieldDMContext.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
fFormattedValueRetriever.dispose();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -284,15 +298,7 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode
|
|||
IRegisterVMConstants.PROP_CURRENT_MNEMONIC_LONG_NAME}),
|
||||
new FormattedValueLabelText(),
|
||||
new ErrorLabelText(),
|
||||
new LabelForeground(new RGB(255, 0, 0)) // TODO: replace with preference error color
|
||||
{
|
||||
{ setPropertyNames(new String[] { PROP_NAME }); }
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(IStatus status, java.util.Map<String,Object> properties) {
|
||||
return !status.isOK();
|
||||
}
|
||||
},
|
||||
new ErrorLabelForeground(),
|
||||
new LabelBackground(
|
||||
DebugUITools.getPreferenceColor(IDebugUIConstants.PREF_CHANGED_VALUE_BACKGROUND).getRGB())
|
||||
{
|
||||
|
@ -493,23 +499,51 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode
|
|||
}
|
||||
|
||||
/**
|
||||
* Update the variable view properties. The formatted values need to be
|
||||
* updated in the VM executor thread while the rest of the properties is
|
||||
* updated in the service session's executor thread. The implementation
|
||||
* splits the handling of the updates to accomplish that.
|
||||
*
|
||||
* @see IElementPropertiesProvider#update(IPropertiesUpdate[])
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public void update(final IPropertiesUpdate[] updates) {
|
||||
final CountingRequestMonitor countingRm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
updates[i].done();
|
||||
}
|
||||
};
|
||||
};
|
||||
int count = 0;
|
||||
|
||||
fFormattedValueRetriever.update(updates, countingRm);
|
||||
count++;
|
||||
|
||||
final IPropertiesUpdate[] subUpdates = new IPropertiesUpdate[updates.length];
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
final IPropertiesUpdate update = updates[i];
|
||||
subUpdates[i] = new VMDelegatingPropertiesUpdate(update, countingRm);
|
||||
count++;
|
||||
}
|
||||
countingRm.setDoneCount(count);
|
||||
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updatePropertiesInSessionThread(updates);
|
||||
updatePropertiesInSessionThread(subUpdates);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (IPropertiesUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
for (IPropertiesUpdate subUpdate : subUpdates) {
|
||||
subUpdate.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Session executor shut down " + getSession().getExecutor(), e)); //$NON-NLS-1$
|
||||
subUpdate.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// @param return-value Boolean.TRUE --> Show Types ICON is selected/depressed
|
||||
// @param return-value Boolean.FALSE --> Show Types ICON is not selected/depressed
|
||||
|
@ -541,11 +575,6 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode
|
|||
};
|
||||
int count = 0;
|
||||
|
||||
if (service != null) {
|
||||
FormattedValueVMUtil.updateFormattedValues(updates, service, IBitFieldDMContext.class, countingRm);
|
||||
count++;
|
||||
}
|
||||
|
||||
for (final IPropertiesUpdate update : updates) {
|
||||
IExpression expression = (IExpression)DebugPlugin.getAdapter(update.getElement(), IExpression.class);
|
||||
if (expression != null) {
|
||||
|
|
|
@ -22,19 +22,20 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
|||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters;
|
||||
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterChangedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMData;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegistersChangedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelForeground;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelText;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueLabelText;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueRetriever;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValueVMContext;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableLabelFont;
|
||||
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
|
||||
|
@ -52,6 +53,7 @@ import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelForeground;
|
|||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.VMDelegatingPropertiesUpdate;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.ICachingVMProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.StaleDataLabelBackground;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.StaleDataLabelForeground;
|
||||
|
@ -80,7 +82,6 @@ import org.eclipse.jface.viewers.CellEditor;
|
|||
import org.eclipse.jface.viewers.ICellModifier;
|
||||
import org.eclipse.jface.viewers.TextCellEditor;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
/**
|
||||
|
@ -171,10 +172,18 @@ public class RegisterVMNode extends AbstractExpressionVMNode
|
|||
*/
|
||||
private IElementLabelProvider fLabelProvider;
|
||||
|
||||
/**
|
||||
* Retriever for formatted values configured for this VM node.
|
||||
* @since 2.2
|
||||
*/
|
||||
private final FormattedValueRetriever fFormattedValueRetriever;
|
||||
|
||||
public RegisterVMNode(AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) {
|
||||
super(provider, session, IRegisterDMContext.class);
|
||||
fSyncRegisterDataAccess = syncDataAccess;
|
||||
fLabelProvider = createLabelProvider();
|
||||
fFormattedValueRetriever =
|
||||
new FormattedValueRetriever(this, session, IRegisters.class, IRegisterDMContext.class);
|
||||
}
|
||||
|
||||
private Object[] constructTypeObjects( Map<String, Object> properties ) {
|
||||
|
@ -218,7 +227,9 @@ public class RegisterVMNode extends AbstractExpressionVMNode
|
|||
DebugUITools.getPreferenceStore().removePropertyChangeListener(fPreferenceChangeListener);
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
super.dispose();
|
||||
|
||||
fFormattedValueRetriever.dispose();
|
||||
}
|
||||
|
||||
protected IElementLabelProvider createLabelProvider() {
|
||||
|
@ -325,15 +336,7 @@ public class RegisterVMNode extends AbstractExpressionVMNode
|
|||
new LabelColumnInfo(new LabelAttribute[] {
|
||||
new FormattedValueLabelText(),
|
||||
new ErrorLabelText(),
|
||||
new LabelForeground(new RGB(255, 0, 0)) // TODO: replace with preference error color
|
||||
{
|
||||
{ setPropertyNames(new String[] { PROP_NAME }); }
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(IStatus status, java.util.Map<String,Object> properties) {
|
||||
return !status.isOK();
|
||||
}
|
||||
},
|
||||
new ErrorLabelForeground(),
|
||||
columnIdValueBackground,
|
||||
new StaleDataLabelForeground(),
|
||||
new VariableLabelFont(),
|
||||
|
@ -460,19 +463,46 @@ public class RegisterVMNode extends AbstractExpressionVMNode
|
|||
}
|
||||
|
||||
/**
|
||||
* Update the variable view properties. The formatted values need to be
|
||||
* updated in the VM executor thread while the rest of the properties is
|
||||
* updated in the service session's executor thread. The implementation
|
||||
* splits the handling of the updates to accomplish that.
|
||||
*
|
||||
* @see IElementPropertiesProvider#update(IPropertiesUpdate[])
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public void update(final IPropertiesUpdate[] updates) {
|
||||
final CountingRequestMonitor countingRm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
updates[i].done();
|
||||
}
|
||||
};
|
||||
};
|
||||
int count = 0;
|
||||
|
||||
fFormattedValueRetriever.update(updates, countingRm);
|
||||
count++;
|
||||
|
||||
final IPropertiesUpdate[] subUpdates = new IPropertiesUpdate[updates.length];
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
final IPropertiesUpdate update = updates[i];
|
||||
subUpdates[i] = new VMDelegatingPropertiesUpdate(update, countingRm);
|
||||
count++;
|
||||
}
|
||||
countingRm.setDoneCount(count);
|
||||
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updatePropertiesInSessionThread(updates);
|
||||
updatePropertiesInSessionThread(subUpdates);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (IPropertiesUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
for (IPropertiesUpdate subUpdate : subUpdates) {
|
||||
subUpdate.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Session executor shut down " + getSession().getExecutor(), e)); //$NON-NLS-1$
|
||||
subUpdate.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -513,11 +543,6 @@ public class RegisterVMNode extends AbstractExpressionVMNode
|
|||
};
|
||||
int count = 0;
|
||||
|
||||
if (service != null) {
|
||||
FormattedValueVMUtil.updateFormattedValues(updates, service, IRegisterDMContext.class, countingRm);
|
||||
count++;
|
||||
}
|
||||
|
||||
for (final IPropertiesUpdate update : updates) {
|
||||
IExpression expression = (IExpression)DebugPlugin.getAdapter(update.getElement(), IExpression.class);
|
||||
if (expression != null) {
|
||||
|
|
|
@ -10,13 +10,17 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.debug.ui.viewmodel.update;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueRetriever;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.ICacheEntry;
|
||||
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.IVMUpdatePolicyExtension;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.ManualUpdatePolicy;
|
||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
@ -24,17 +28,54 @@ import org.eclipse.jface.viewers.TreePath;
|
|||
/**
|
||||
* Manual update policy with extensions specific for the debugger views. It
|
||||
* properly handles the changes in active number format values in debug view.
|
||||
* This requires clearing of cached properties related to the active format
|
||||
* preference, but not clearing the formatted value data retrieved from the
|
||||
* service.
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
public class DebugManualUpdatePolicy extends ManualUpdatePolicy {
|
||||
public class DebugManualUpdatePolicy extends ManualUpdatePolicy implements IVMUpdatePolicyExtension {
|
||||
|
||||
public static String DEBUG_MANUAL_UPDATE_POLICY_ID = "org.eclipse.cdt.dsf.debug.ui.viewmodel.update.debugManualUpdatePolicy"; //$NON-NLS-1$
|
||||
private final Set<String> fActiveNumberFormatPropertiesWithPrefixes;
|
||||
|
||||
private static final List<String> ACTIVE_NUMBER_FORMAT_PROPERTIES = new ArrayList<String>(1);
|
||||
/**
|
||||
* Creates a manual update policy for debug views.
|
||||
*/
|
||||
public DebugManualUpdatePolicy() {
|
||||
this(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a manual update policy for debug views for models that retrieve
|
||||
* multiple formatted values for each view entry. The given prefixes
|
||||
* distinguish the formatted values properties from each other.
|
||||
*
|
||||
* @see FormattedValueRetriever
|
||||
* @see FormattedValueVMUtil#getPropertyForFormatId(String, String)
|
||||
*
|
||||
* @param prefixes Prefixes to use when flushing the active formatted value
|
||||
* from VM cache.
|
||||
*/
|
||||
public DebugManualUpdatePolicy(String[] prefixes) {
|
||||
if (prefixes.length == 0) {
|
||||
fActiveNumberFormatPropertiesWithPrefixes = ACTIVE_NUMBER_FORMAT_PROPERTIES;
|
||||
} else {
|
||||
fActiveNumberFormatPropertiesWithPrefixes = new TreeSet<String>(ACTIVE_NUMBER_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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final Set<String> ACTIVE_NUMBER_FORMAT_PROPERTIES = new TreeSet<String>();
|
||||
static {
|
||||
ACTIVE_NUMBER_FORMAT_PROPERTIES.add(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT);
|
||||
ACTIVE_NUMBER_FORMAT_PROPERTIES.add(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE);
|
||||
ACTIVE_NUMBER_FORMAT_PROPERTIES.add(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,17 +83,14 @@ public class DebugManualUpdatePolicy extends ManualUpdatePolicy {
|
|||
* property of the elemetn under consideration. The partial property flush
|
||||
* is performed only if the cache entry is not yet dirty.
|
||||
*/
|
||||
private static IElementUpdateTester fgNumberFormatPropertyEventUpdateTester = new IElementUpdateTesterExtension() {
|
||||
private IElementUpdateTester fNumberFormatPropertyEventUpdateTester = new IElementUpdateTesterExtension() {
|
||||
|
||||
public int getUpdateFlags(Object viewerInput, TreePath path) {
|
||||
return FLUSH_PARTIAL_PROPERTIES;
|
||||
}
|
||||
|
||||
public Collection<String> getPropertiesToFlush(Object viewerInput, TreePath path, boolean isDirty) {
|
||||
if (!isDirty) {
|
||||
return ACTIVE_NUMBER_FORMAT_PROPERTIES;
|
||||
}
|
||||
return null;
|
||||
return fActiveNumberFormatPropertiesWithPrefixes;
|
||||
}
|
||||
|
||||
public boolean includes(IElementUpdateTester tester) {
|
||||
|
@ -65,18 +103,17 @@ public class DebugManualUpdatePolicy extends ManualUpdatePolicy {
|
|||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return DEBUG_MANUAL_UPDATE_POLICY_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IElementUpdateTester getElementUpdateTester(Object event) {
|
||||
if ((event instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE))
|
||||
if ( event instanceof PropertyChangeEvent &&
|
||||
IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE.equals( ((PropertyChangeEvent)event).getProperty()) )
|
||||
{
|
||||
return fgNumberFormatPropertyEventUpdateTester;
|
||||
return fNumberFormatPropertyEventUpdateTester;
|
||||
}
|
||||
return super.getElementUpdateTester(event);
|
||||
}
|
||||
|
||||
public boolean canUpdateDirtyProperty(ICacheEntry entry, String property) {
|
||||
return fActiveNumberFormatPropertiesWithPrefixes.contains(property);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,11 +47,13 @@ import org.eclipse.cdt.dsf.debug.service.IStack;
|
|||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMData;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelForeground;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelText;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionUpdate;
|
||||
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.numberformat.FormattedValueVMUtil;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValueVMContext;
|
||||
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
|
||||
|
@ -70,6 +72,7 @@ import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelForeground;
|
|||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.VMDelegatingPropertiesUpdate;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.ICachingVMProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.StaleDataLabelBackground;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.StaleDataLabelForeground;
|
||||
|
@ -100,7 +103,6 @@ import org.eclipse.jface.viewers.CellEditor;
|
|||
import org.eclipse.jface.viewers.ICellModifier;
|
||||
import org.eclipse.jface.viewers.TextCellEditor;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.ui.IMemento;
|
||||
|
||||
|
@ -143,6 +145,12 @@ public class VariableVMNode extends AbstractExpressionVMNode
|
|||
*/
|
||||
private final IElementLabelProvider fLabelProvider;
|
||||
|
||||
/**
|
||||
* Retriever for formatted values configured for this VM node.
|
||||
* @since 2.2
|
||||
*/
|
||||
private final FormattedValueRetriever fFormattedValueRetriever;
|
||||
|
||||
public class VariableExpressionVMC extends DMVMContext implements IFormattedValueVMContext {
|
||||
|
||||
private IExpression fExpression;
|
||||
|
@ -227,6 +235,8 @@ public class VariableVMNode extends AbstractExpressionVMNode
|
|||
super(provider, session, IExpressions.IExpressionDMContext.class);
|
||||
fSyncVariableDataAccess = syncVariableDataAccess;
|
||||
fLabelProvider = createLabelProvider();
|
||||
fFormattedValueRetriever =
|
||||
new FormattedValueRetriever(this, session, IExpressions.class, IExpressionDMContext.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -263,7 +273,10 @@ public class VariableVMNode extends AbstractExpressionVMNode
|
|||
DebugUITools.getPreferenceStore().removePropertyChangeListener(fPreferenceChangeListener);
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
|
||||
super.dispose();
|
||||
|
||||
fFormattedValueRetriever.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -459,16 +472,7 @@ public class VariableVMNode extends AbstractExpressionVMNode
|
|||
},
|
||||
new FormattedValueLabelText(),
|
||||
new ErrorLabelText(),
|
||||
new LabelForeground(new RGB(255, 0, 0)) // TODO: replace with preference error color
|
||||
{
|
||||
{ setPropertyNames(new String[] { PROP_NAME }); }
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(IStatus status, java.util.Map<String,Object> properties) {
|
||||
return !status.isOK();
|
||||
}
|
||||
},
|
||||
//
|
||||
new ErrorLabelForeground(),
|
||||
columnIdValueBackground,
|
||||
new StaleDataLabelForeground(),
|
||||
new VariableLabelFont(),
|
||||
|
@ -607,15 +611,7 @@ public class VariableVMNode extends AbstractExpressionVMNode
|
|||
POINTER_LABEL_IMAGE,
|
||||
AGGREGATE_LABEL_IMAGE,
|
||||
SIMPLE_LABEL_IMAGE,
|
||||
new LabelForeground(new RGB(255, 0, 0)) // TODO: replace with preference error color
|
||||
{
|
||||
{ setPropertyNames(new String[] { PROP_NAME }); }
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(IStatus status, java.util.Map<String,Object> properties) {
|
||||
return !status.isOK();
|
||||
}
|
||||
},
|
||||
new ErrorLabelForeground(),
|
||||
new LabelForeground(
|
||||
DebugUITools.getPreferenceColor(IDebugUIConstants.PREF_CHANGED_DEBUG_ELEMENT_COLOR).getRGB())
|
||||
{
|
||||
|
@ -659,19 +655,46 @@ public class VariableVMNode extends AbstractExpressionVMNode
|
|||
}
|
||||
|
||||
/**
|
||||
* Update the variable view properties. The formatted values need to be
|
||||
* updated in the VM executor thread while the rest of the properties is
|
||||
* updated in the service session's executor thread. The implementation
|
||||
* splits the handling of the updates to accomplish that.
|
||||
*
|
||||
* @see IElementPropertiesProvider#update(IPropertiesUpdate[])
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public void update(final IPropertiesUpdate[] updates) {
|
||||
final CountingRequestMonitor countingRm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
updates[i].done();
|
||||
}
|
||||
};
|
||||
};
|
||||
int count = 0;
|
||||
|
||||
fFormattedValueRetriever.update(updates, countingRm);
|
||||
count++;
|
||||
|
||||
final IPropertiesUpdate[] subUpdates = new IPropertiesUpdate[updates.length];
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
final IPropertiesUpdate update = updates[i];
|
||||
subUpdates[i] = new VMDelegatingPropertiesUpdate(update, countingRm);
|
||||
count++;
|
||||
}
|
||||
countingRm.setDoneCount(count);
|
||||
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updatePropertiesInSessionThread(updates);
|
||||
updatePropertiesInSessionThread(subUpdates);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (IPropertiesUpdate update : updates) {
|
||||
handleFailedUpdate(update);
|
||||
for (IPropertiesUpdate subUpdate : subUpdates) {
|
||||
subUpdate.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Session executor shut down " + getSession().getExecutor(), e)); //$NON-NLS-1$
|
||||
subUpdate.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -707,11 +730,6 @@ public class VariableVMNode extends AbstractExpressionVMNode
|
|||
};
|
||||
int count = 0;
|
||||
|
||||
if (service != null) {
|
||||
FormattedValueVMUtil.updateFormattedValues(updates, service, IExpressionDMContext.class, countingRm);
|
||||
count++;
|
||||
}
|
||||
|
||||
for (final IPropertiesUpdate update : updates) {
|
||||
IExpression expression = (IExpression)DebugPlugin.getAdapter(update.getElement(), IExpression.class);
|
||||
if (expression != null) {
|
||||
|
|
|
@ -36,6 +36,9 @@ public interface IPropertiesUpdate extends IViewerUpdate {
|
|||
|
||||
/**
|
||||
* Sets the given map as the complete property map for this update.
|
||||
* If other properties were already set to this update, the properties
|
||||
* given here will be added. If properties are added later, the properties
|
||||
* map given here will not be modified, instead it will be copied.
|
||||
*
|
||||
* @param properties Full properties map.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.ui.viewmodel.properties;
|
||||
|
||||
/**
|
||||
* Listener for properties updates requested by a property based label provider.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public interface IPropertiesUpdateListener {
|
||||
|
||||
/**
|
||||
* Indicates that the given updates were requested from a properties provider.
|
||||
*/
|
||||
public void propertiesUpdatesStarted(IPropertiesUpdate[] updates);
|
||||
|
||||
/**
|
||||
* Indicates that the given update has been completed.
|
||||
*/
|
||||
public void propertiesUpdateCompleted(IPropertiesUpdate update);
|
||||
|
||||
}
|
|
@ -17,6 +17,7 @@ import org.eclipse.osgi.util.NLS;
|
|||
*/
|
||||
class MessagesForProperties extends NLS {
|
||||
public static String DefaultLabelMessage_label;
|
||||
public static String PropertiesUpdateStatus_message;
|
||||
|
||||
static {
|
||||
// initialize resource bundle
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2006, 2009 Wind River Systems and others.
|
||||
# Copyright (c) 2006, 2010 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
|
||||
|
@ -9,3 +9,4 @@
|
|||
# Wind River Systems - initial API and implementation
|
||||
###############################################################################
|
||||
DefaultLabelMessage_label=<unknown>
|
||||
PropertiesUpdateStatus_message=Multiple errors reported.
|
|
@ -10,6 +10,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.ui.viewmodel.properties;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -49,6 +50,8 @@ public class PropertiesBasedLabelProvider
|
|||
*/
|
||||
private Map<String, LabelColumnInfo> fColumnInfos = Collections.synchronizedMap(new HashMap<String,LabelColumnInfo>());
|
||||
|
||||
private IPropertiesUpdateListener[] fListeners = new IPropertiesUpdateListener[0];
|
||||
|
||||
/**
|
||||
* Standard constructor. A property based label constructor does not
|
||||
* initialize column attribute information {@link #setColumnInfo(String, LabelColumnInfo)}
|
||||
|
@ -81,6 +84,40 @@ public class PropertiesBasedLabelProvider
|
|||
return fColumnInfos.get(columnId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener for properties updates generated by this label provider.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public void addPropertiesUpdateListener(IPropertiesUpdateListener listener) {
|
||||
synchronized(this) {
|
||||
if (!Arrays.asList(fListeners).contains(listener)) {
|
||||
IPropertiesUpdateListener[] newListeners = new IPropertiesUpdateListener[fListeners.length + 1];
|
||||
System.arraycopy(fListeners, 0, newListeners, 0, fListeners.length);
|
||||
newListeners[fListeners.length] = listener;
|
||||
fListeners = newListeners;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener for properties updates generated by this label provider.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public void removePropertiesUpdateListener(IPropertiesUpdateListener listener) {
|
||||
synchronized(this) {
|
||||
int listenerIdx = Arrays.asList(fListeners).indexOf(listener);
|
||||
|
||||
if (listenerIdx != -1) {
|
||||
IPropertiesUpdateListener[] newListeners = new IPropertiesUpdateListener[fListeners.length - 1];
|
||||
System.arraycopy(fListeners, 0, newListeners, 0, listenerIdx);
|
||||
System.arraycopy(fListeners, listenerIdx + 1, newListeners, listenerIdx, newListeners.length - listenerIdx);
|
||||
fListeners = newListeners;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In addition to guarantees on [labelUpdates] declared by
|
||||
* {@link IElementLabelProvider}, we further require/assume that all the
|
||||
|
@ -89,7 +126,7 @@ public class PropertiesBasedLabelProvider
|
|||
*
|
||||
* @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider#update(org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate[])
|
||||
*/
|
||||
public void update(ILabelUpdate[] labelUpdates) {
|
||||
public void update(final ILabelUpdate[] labelUpdates) {
|
||||
IElementPropertiesProvider propertiesProvider = getElementPropertiesProvider(labelUpdates[0].getElement());
|
||||
if (propertiesProvider == null) {
|
||||
for (ILabelUpdate update : labelUpdates) {
|
||||
|
@ -109,19 +146,41 @@ public class PropertiesBasedLabelProvider
|
|||
// Call the properties provider. Create a request monitor for each label update.
|
||||
// We can use an immediate executor for the request monitor because the label provider
|
||||
// is thread safe.
|
||||
IPropertiesUpdate[] propertiesUpdates = new IPropertiesUpdate[labelUpdates.length];
|
||||
final IPropertiesUpdate[] propertiesUpdates = new IPropertiesUpdate[labelUpdates.length];
|
||||
for (int i = 0; i < labelUpdates.length; i++) {
|
||||
final ILabelUpdate labelUpdate = labelUpdates[i];
|
||||
propertiesUpdates[i] = new VMPropertiesUpdate(
|
||||
propertyNames, labelUpdate,
|
||||
new ViewerDataRequestMonitor<Map<String, Object>>(ImmediateExecutor.getInstance(), labelUpdate) {
|
||||
final int idx = i;
|
||||
propertiesUpdates[idx] = new VMPropertiesUpdate(
|
||||
propertyNames, labelUpdates[idx],
|
||||
new ViewerDataRequestMonitor<Map<String, Object>>(ImmediateExecutor.getInstance(), labelUpdates[idx]) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
updateLabel(labelUpdate, getStatus(), getData());
|
||||
notifyPropertiesUpdateCompleted(propertiesUpdates[idx]);
|
||||
updateLabel(labelUpdates[idx], getStatus(), getData());
|
||||
}
|
||||
});
|
||||
}
|
||||
propertiesProvider.update(propertiesUpdates);
|
||||
notifyPropertiesUpdatesStarted(propertiesUpdates);
|
||||
propertiesProvider.update(propertiesUpdates);
|
||||
}
|
||||
|
||||
private void notifyPropertiesUpdatesStarted(IPropertiesUpdate[] updates) {
|
||||
IPropertiesUpdateListener[] listeners = null;
|
||||
synchronized(this) {
|
||||
listeners = fListeners;
|
||||
}
|
||||
for (IPropertiesUpdateListener listener : listeners) {
|
||||
listener.propertiesUpdatesStarted(updates);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyPropertiesUpdateCompleted(IPropertiesUpdate update) {
|
||||
IPropertiesUpdateListener[] listeners = null;
|
||||
synchronized(this) {
|
||||
listeners = fListeners;
|
||||
}
|
||||
for (IPropertiesUpdateListener listener : listeners) {
|
||||
listener.propertiesUpdateCompleted(update);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.ui.viewmodel.properties;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfMultiStatus;
|
||||
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
|
||||
/**
|
||||
* Status object for use with the IPropertiesUpdate. This status class
|
||||
* allows setting a different status result for each property. This allows
|
||||
* for better interpretation of status by the client of the update.
|
||||
* <p>
|
||||
* This status class derives from MultiStatus class such that the status
|
||||
* objects for each property can be accessed through the standard
|
||||
* {@link #getChildren()} method. Also, multiple properties can reference
|
||||
* the same status object, meaning that the number of properties returned
|
||||
* by {@link #getProperties()} may be greater than the status objects
|
||||
* returned by <code>getChildren()</code>.
|
||||
* <p>
|
||||
* The properties status object does not have its own message, severity,
|
||||
* error status or exception. All these attributes are calculated from
|
||||
* the child status objects. If the status has more than one status child,
|
||||
* the String returned by {@link #getMessage()} is: "Multiple errors reported".
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class PropertiesUpdateStatus extends DsfMultiStatus {
|
||||
|
||||
final private Map<String,IStatus> fPropertiesStatus = new HashMap<String, IStatus>(1);
|
||||
private boolean fFirstStatusSet;
|
||||
|
||||
public PropertiesUpdateStatus() {
|
||||
super(DsfUIPlugin.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns set of properties that have an additional status specified.
|
||||
*/
|
||||
public Set<String> getProperties() {
|
||||
return fPropertiesStatus.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an additional status for the given property in a property
|
||||
* update. Returned value may be <code>null</code> if no additional
|
||||
* status is given.
|
||||
*/
|
||||
public IStatus getStatus(String property) {
|
||||
return fPropertiesStatus.get(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given status for the given property.
|
||||
*/
|
||||
public void setStatus(String property, IStatus status) {
|
||||
IStatus child = findEquivalentChild(status);
|
||||
if (child != null) {
|
||||
status = child;
|
||||
} else {
|
||||
add(status);
|
||||
}
|
||||
|
||||
fPropertiesStatus.put(property, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given status for the properties array.
|
||||
*/
|
||||
public void setStatus(String[] properties, IStatus status) {
|
||||
IStatus child = findEquivalentChild(status);
|
||||
if (child != null) {
|
||||
status = child;
|
||||
} else {
|
||||
add(status);
|
||||
}
|
||||
|
||||
for (String property : properties) {
|
||||
fPropertiesStatus.put(property, status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges data in the new status into the base status data, and returns the
|
||||
* resulting status. Only properties specified in the given set are merged.
|
||||
* <p>
|
||||
* The new status is considered to be more up to date than the base
|
||||
* status and its data overrides the base status . If the base status
|
||||
* holds an error for a given property, which is found in the
|
||||
* given set, and the new status does not, then the base error status is
|
||||
* removed.
|
||||
*
|
||||
* @param baseStatus Properties into which the new status properties will
|
||||
* be merged.
|
||||
* @param newStatus Properties status to merge.
|
||||
* @param properties The properties to consider in the new status.
|
||||
* @return Resulting merged status object.
|
||||
*/
|
||||
public static PropertiesUpdateStatus mergePropertiesStatus(PropertiesUpdateStatus baseStatus,
|
||||
PropertiesUpdateStatus newStatus, Set<String> properties)
|
||||
{
|
||||
PropertiesUpdateStatus mergedStatus = new PropertiesUpdateStatus();
|
||||
mergedStatus.fPropertiesStatus.putAll(baseStatus.fPropertiesStatus);
|
||||
|
||||
for (String property : properties) {
|
||||
IStatus propertyStatus = newStatus.getStatus(property);
|
||||
if (propertyStatus != null) {
|
||||
mergedStatus.fPropertiesStatus.put(property, propertyStatus);
|
||||
} else {
|
||||
mergedStatus.fPropertiesStatus.remove(property);
|
||||
}
|
||||
}
|
||||
Set<IStatus> children = new HashSet<IStatus>((baseStatus.getChildren().length + newStatus.getChildren().length) * 4/3);
|
||||
|
||||
children.addAll(mergedStatus.fPropertiesStatus.values());
|
||||
for (IStatus child : children) {
|
||||
mergedStatus.add(child);
|
||||
}
|
||||
|
||||
return mergedStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given status object as a child of this status. If there's an
|
||||
* equivalent child status already, the new status is ignored.
|
||||
*/
|
||||
@Override
|
||||
public void add(IStatus status) {
|
||||
if (findEquivalentChild(status) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.add(status);
|
||||
|
||||
boolean firstSet;
|
||||
synchronized(this) {
|
||||
firstSet = fFirstStatusSet;
|
||||
fFirstStatusSet = true;
|
||||
}
|
||||
|
||||
if (!firstSet) {
|
||||
setMessage(status.getMessage());
|
||||
} else {
|
||||
setMessage(MessagesForProperties.PropertiesUpdateStatus_message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a child status that is equivalent to the given status.
|
||||
*/
|
||||
private IStatus findEquivalentChild(IStatus status) {
|
||||
if (getChildren().length != 0) {
|
||||
for (IStatus child : getChildren()) {
|
||||
if (areEquivalent(child, status)) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two status objects to determine if they are equivalent.
|
||||
*/
|
||||
private boolean areEquivalent(IStatus s1, IStatus s2) {
|
||||
if ( (s1 == null && s2 != null) || (s1 != null && s2 == null) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (s1 == null) {
|
||||
return true;
|
||||
}
|
||||
if ( (s1.getSeverity() != s2.getSeverity()) ||
|
||||
!s1.getPlugin().equals(s2.getPlugin()) ||
|
||||
(s1.getCode() != s2.getCode()) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ( (s1.getException() == null && s1.getException() != null) ||
|
||||
(s1.getException() != null && s1.getException() == null) ||
|
||||
(s1.getException() != null && !s1.getException().equals(s2.getException())) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return s1.getMessage().equals(s2.getMessage());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method that returns and optionally creates a properties
|
||||
* update status object for the given update.
|
||||
*/
|
||||
public static PropertiesUpdateStatus getPropertiesStatus(IPropertiesUpdate update) {
|
||||
IStatus updateStatus = update.getStatus();
|
||||
if (updateStatus instanceof PropertiesUpdateStatus) {
|
||||
return (PropertiesUpdateStatus)updateStatus;
|
||||
} else {
|
||||
PropertiesUpdateStatus propertiesStatus = new PropertiesUpdateStatus();
|
||||
if (!updateStatus.isOK()) {
|
||||
propertiesStatus.add(updateStatus);
|
||||
}
|
||||
return propertiesStatus;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009 Wind River Systems and others.
|
||||
* Copyright (c) 2009, 2010 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
|
||||
|
@ -15,6 +15,7 @@ import java.util.Set;
|
|||
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.VMViewerUpdate;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
|
||||
/**
|
||||
* Properties update used as to collect property data from the provider.
|
||||
|
@ -45,6 +46,22 @@ public class VMDelegatingPropertiesUpdate extends VMViewerUpdate implements IPro
|
|||
fParentUpdate.setAllProperties(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
*/
|
||||
@Override
|
||||
public IStatus getStatus() {
|
||||
return fParentUpdate.getStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
*/
|
||||
@Override
|
||||
public void setStatus(IStatus status) {
|
||||
fParentUpdate.setStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VMDelegatingPropertiesUpdate -> " + fParentUpdate; //$NON-NLS-1$
|
||||
|
|
|
@ -22,12 +22,20 @@ import org.eclipse.cdt.dsf.internal.DsfPlugin;
|
|||
import org.eclipse.cdt.dsf.internal.LoggingUtils;
|
||||
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.VMViewerUpdate;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* Properties update used as to collect property data from the provider.
|
||||
* Properties update used as to collect property data from the provider.
|
||||
* <p>
|
||||
* The status returned by the VMPropertiesUpdate is always going to be of type
|
||||
* PropertiesUpdateStatus, which allows for setting status for individual
|
||||
* properties.
|
||||
* </p>
|
||||
*
|
||||
* @see PropertiesUpdateStatus
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
|
@ -51,11 +59,13 @@ public class VMPropertiesUpdate extends VMViewerUpdate implements IPropertiesUpd
|
|||
|
||||
public VMPropertiesUpdate(Set<String> properties, IViewerUpdate parentUpdate, DataRequestMonitor<Map<String,Object>> rm) {
|
||||
super(parentUpdate, rm);
|
||||
super.setStatus(new PropertiesUpdateStatus());
|
||||
fProperties = properties;
|
||||
}
|
||||
|
||||
public VMPropertiesUpdate(Set<String> properties, TreePath elementPath, Object viewerInput, IPresentationContext presentationContext, DataRequestMonitor<Map<String,Object>> rm) {
|
||||
super(elementPath, viewerInput, presentationContext, rm);
|
||||
super.setStatus(new PropertiesUpdateStatus());
|
||||
fProperties = properties;
|
||||
}
|
||||
|
||||
|
@ -64,6 +74,13 @@ public class VMPropertiesUpdate extends VMViewerUpdate implements IPropertiesUpd
|
|||
return fProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
*/
|
||||
public Map<String, Object> getValues() {
|
||||
return fValues;
|
||||
}
|
||||
|
||||
public synchronized void setProperty(String property, Object value) {
|
||||
if (!fCreatedOwnMap) {
|
||||
fCreatedOwnMap = true;
|
||||
|
@ -85,6 +102,25 @@ public class VMPropertiesUpdate extends VMViewerUpdate implements IPropertiesUpd
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the base class to implement special handling of
|
||||
* {@link PropertiesUpdateStatus}. If the given status is an instance of
|
||||
* properties status, this new status will be set to the update. Otherwise, the
|
||||
* given status will be merged into the updates existing properties status.
|
||||
* This way {@link #getStatus()} should always return an instance of
|
||||
* <code>PropertiesUpdateStatus</code>.
|
||||
*/
|
||||
@Override
|
||||
public void setStatus(IStatus status) {
|
||||
if (status instanceof PropertiesUpdateStatus) {
|
||||
super.setStatus(status);
|
||||
} else if ((getStatus() instanceof PropertiesUpdateStatus)) {
|
||||
((PropertiesUpdateStatus)getStatus()).add(status);
|
||||
} else {
|
||||
assert false : "VMPropertiesUpdate status should always be a PropertiesUpdateStatus"; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the standard done in order to store the retrieved values
|
||||
* in the client's request monitor.
|
||||
|
|
|
@ -14,10 +14,12 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
|
@ -40,6 +42,7 @@ import org.eclipse.cdt.dsf.ui.viewmodel.VMChildrenUpdate;
|
|||
import org.eclipse.cdt.dsf.ui.viewmodel.VMHasChildrenUpdate;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesUpdateStatus;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.VMPropertiesUpdate;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
|
@ -62,7 +65,7 @@ import org.eclipse.swt.widgets.TreeItem;
|
|||
* @since 1.0
|
||||
*/
|
||||
public class AbstractCachingVMProvider extends AbstractVMProvider
|
||||
implements ICachingVMProvider, IElementPropertiesProvider, ICachingVMProviderExtension
|
||||
implements ICachingVMProvider, IElementPropertiesProvider, ICachingVMProviderExtension, ICachingVMProviderExtension2
|
||||
{
|
||||
/**
|
||||
* @since 2.0
|
||||
|
@ -175,7 +178,7 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
/**
|
||||
* Entry with cached element data.
|
||||
*/
|
||||
private static class ElementDataEntry extends Entry {
|
||||
private static class ElementDataEntry extends Entry implements ICacheEntry {
|
||||
ElementDataEntry(ElementDataKey key) {
|
||||
super(key);
|
||||
}
|
||||
|
@ -254,6 +257,16 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
", properties=" + fProperties + //$NON-NLS-1$
|
||||
", oldProperties=" + fArchiveProperties + "]"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
public IVMNode getNode() { return ((ElementDataKey)fKey).fNode; }
|
||||
public Object getViewerInput() { return ((ElementDataKey)fKey).fViewerInput; }
|
||||
public TreePath getElementPath() { return ((ElementDataKey)fKey).fPath; }
|
||||
public boolean isDirty() { return fDirty; }
|
||||
public Boolean getHasChildren() { return fHasChildren; }
|
||||
public Integer getChildCount() { return fChildrenCount; }
|
||||
public Map<Integer, Object> getChildren() { return fChildren; }
|
||||
public Map<String, Object> getProperties() { return fProperties; }
|
||||
public java.util.Map<String,Object> getArchiveProperties() { return fArchiveProperties; }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -294,7 +307,6 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
public String toString() {
|
||||
return fElementTester.toString() + " " + fRootElement.toString(); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -443,13 +455,18 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
}
|
||||
}
|
||||
|
||||
public ICacheEntry getCacheEntry(IVMNode node, Object viewerInput, TreePath path) {
|
||||
ElementDataKey key = makeEntryKey(node, viewerInput, path);
|
||||
return getElementDataEntry(key, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNode(final IVMNode node, IHasChildrenUpdate[] updates) {
|
||||
LinkedList <IHasChildrenUpdate> missUpdates = new LinkedList<IHasChildrenUpdate>();
|
||||
for(final IHasChildrenUpdate update : updates) {
|
||||
// Find or create the cache entry for the element of this update.
|
||||
ElementDataKey key = makeEntryKey(node, update);
|
||||
final ElementDataEntry entry = getElementDataEntry(key);
|
||||
final ElementDataEntry entry = getElementDataEntry(key, true);
|
||||
updateRootElementMarker(key.fRootElement, node, update);
|
||||
|
||||
// Check if the cache entry has this request result cached.
|
||||
|
@ -498,7 +515,7 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
public void updateNode(final IVMNode node, final IChildrenCountUpdate update) {
|
||||
// Find or create the cache entry for the element of this update.
|
||||
ElementDataKey key = makeEntryKey(node, update);
|
||||
final ElementDataEntry entry = getElementDataEntry(key);
|
||||
final ElementDataEntry entry = getElementDataEntry(key, true);
|
||||
updateRootElementMarker(key.fRootElement, node, update);
|
||||
|
||||
// Check if the cache entry has this request result cached.
|
||||
|
@ -541,7 +558,7 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
public void updateNode(final IVMNode node, final IChildrenUpdate update) {
|
||||
// Find or create the cache entry for the element of this update.
|
||||
ElementDataKey key = makeEntryKey(node, update);
|
||||
final ElementDataEntry entry = getElementDataEntry(key);
|
||||
final ElementDataEntry entry = getElementDataEntry(key, true);
|
||||
updateRootElementMarker(key.fRootElement, node, update);
|
||||
|
||||
final int flushCounter = entry.fFlushCounter;
|
||||
|
@ -928,14 +945,21 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
* update and creates an element cache entry key.
|
||||
*/
|
||||
private ElementDataKey makeEntryKey(IVMNode node, IViewerUpdate update) {
|
||||
Object rootElement = update.getViewerInput(); // Default
|
||||
return makeEntryKey(node, update.getViewerInput(), update.getElementPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience class that searches for the root element for the given
|
||||
* update and creates an element cache entry key.
|
||||
*/
|
||||
private ElementDataKey makeEntryKey(IVMNode node, Object viewerInput, TreePath path) {
|
||||
Object rootElement = viewerInput; // Default
|
||||
outer: for (IVMModelProxy proxy : getActiveModelProxies()) {
|
||||
Object proxyRoot = proxy.getRootElement();
|
||||
if (proxyRoot.equals(update.getViewerInput())) {
|
||||
if (proxyRoot.equals(viewerInput)) {
|
||||
rootElement = proxyRoot;
|
||||
break;
|
||||
}
|
||||
TreePath path = update.getElementPath();
|
||||
for (int i = 0; i < path.getSegmentCount(); i++) {
|
||||
if (proxyRoot.equals(path.getSegment(i))) {
|
||||
rootElement = proxyRoot;
|
||||
|
@ -944,27 +968,29 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
}
|
||||
}
|
||||
|
||||
return new ElementDataKey(rootElement, node, update.getViewerInput(), update.getElementPath());
|
||||
return new ElementDataKey(rootElement, node, viewerInput, path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is the only method that should be used to access a cache entry.
|
||||
* It creates a new entry if needed and it maintains the ordering in
|
||||
* the least-recently-used linked list.
|
||||
* @param create Create the entry if needed.
|
||||
* @return cache element entry, may be <code>null</code> if entry does
|
||||
* not exist and the create parameter is <code>false</code>
|
||||
*/
|
||||
private ElementDataEntry getElementDataEntry(ElementDataKey key) {
|
||||
private ElementDataEntry getElementDataEntry(ElementDataKey key, boolean create) {
|
||||
assert key != null;
|
||||
ElementDataEntry entry = (ElementDataEntry)fCacheData.get(key);
|
||||
if (entry == null) {
|
||||
if (entry != null) {
|
||||
// Entry exists, move it to the end of the list.
|
||||
entry.reinsert(fCacheListHead);
|
||||
} else if (create) {
|
||||
// Create a new entry and add it to the end of the list.
|
||||
entry = new ElementDataEntry(key);
|
||||
addEntry(key, entry);
|
||||
} else {
|
||||
// Entry exists, move it to the end of the list.
|
||||
entry.reinsert(fCacheListHead);
|
||||
}
|
||||
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -991,7 +1017,7 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
if (created) {
|
||||
ElementDataKey rootElementDataKey =
|
||||
new ElementDataKey(rootElement, node, update.getViewerInput(), update.getElementPath());
|
||||
ElementDataEntry entry = getElementDataEntry(rootElementDataKey);
|
||||
ElementDataEntry entry = getElementDataEntry(rootElementDataKey, false);
|
||||
|
||||
Object[] rootElementChildren = getActiveUpdatePolicy().getInitialRootElementChildren(rootElement);
|
||||
if (rootElementChildren != null) {
|
||||
|
@ -1104,7 +1130,7 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
for(final IPropertiesUpdate update : updates) {
|
||||
// Find or create the cache entry for the element of this update.
|
||||
ElementDataKey key = makeEntryKey(node, update);
|
||||
final ElementDataEntry entry = getElementDataEntry(key);
|
||||
final ElementDataEntry entry = getElementDataEntry(key, true);
|
||||
updateRootElementMarker(key.fRootElement, node, update);
|
||||
|
||||
// The request can be retrieved from cache if all the properties that were requested in the update are
|
||||
|
@ -1120,28 +1146,59 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
update.setAllProperties(entry.fProperties);
|
||||
update.setStatus((IStatus)entry.fProperties.get(PROP_UPDATE_STATUS));
|
||||
update.done();
|
||||
} else if (entry.fProperties != null && entry.fDirty) {
|
||||
// Cache miss, BUT the entry is dirty already. Rather then fetch new data from model, return
|
||||
// incomplete data to user. User can refresh the view to get the complete data set.
|
||||
if (DEBUG_CACHE && (DEBUG_PRESENTATION_ID == null || getPresentationContext().getId().equals(DEBUG_PRESENTATION_ID))) {
|
||||
DsfUIPlugin.debug("cacheHitPropertiesPartialStaleData(node = " + node + ", update = " + update + ", " + entry.fProperties + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
if (entry.fProperties.containsKey(PROP_UPDATE_POLICY_ID)) {
|
||||
entry.fProperties.put(PROP_UPDATE_POLICY_ID, getActiveUpdatePolicy().getID());
|
||||
}
|
||||
update.setAllProperties(entry.fProperties);
|
||||
update.setStatus(DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_STATE, "Cache contains partial stale data for this request.", null)); //$NON-NLS-1$
|
||||
update.done();
|
||||
} else {
|
||||
// Cache miss! Save the flush counter of the entry and create a proxy update.
|
||||
// Cache miss! Check if already cached properties can be re-used.
|
||||
Set<String> missingProperties = null;
|
||||
if (entry.fProperties != null) {
|
||||
missingProperties = new HashSet<String>(update.getProperties().size() * 4/3);
|
||||
missingProperties.addAll(update.getProperties());
|
||||
missingProperties.removeAll(entry.fProperties.keySet());
|
||||
|
||||
if (entry.fDirty) {
|
||||
// Cache miss, BUT the entry is dirty already. Determine which properties can still be updated
|
||||
// (if any), then request the missing properties from node, or return an error.
|
||||
if (getActiveUpdatePolicy() instanceof IVMUpdatePolicyExtension) {
|
||||
IVMUpdatePolicyExtension updatePolicyExt = (IVMUpdatePolicyExtension)getActiveUpdatePolicy();
|
||||
for (Iterator<String> itr = missingProperties.iterator(); itr.hasNext();) {
|
||||
String missingProperty = itr.next();
|
||||
if ( !updatePolicyExt.canUpdateDirtyProperty(entry, missingProperty) ) {
|
||||
itr.remove();
|
||||
PropertiesUpdateStatus.getPropertiesStatus(update).setStatus(
|
||||
missingProperty,
|
||||
DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_STATE, "Cache contains stale data. Refresh view.", null ));//$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PropertiesUpdateStatus.getPropertiesStatus(update).setStatus(
|
||||
missingProperties.toArray(new String[missingProperties.size()]),
|
||||
DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_STATE, "Cache contains stale data. Refresh view.", null ));//$NON-NLS-1$
|
||||
missingProperties.clear();
|
||||
}
|
||||
if (missingProperties.isEmpty()) {
|
||||
if (entry.fProperties.containsKey(PROP_UPDATE_POLICY_ID)) {
|
||||
entry.fProperties.put(PROP_UPDATE_POLICY_ID, getActiveUpdatePolicy().getID());
|
||||
}
|
||||
update.setAllProperties(entry.fProperties);
|
||||
update.done();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
missingProperties = update.getProperties();
|
||||
}
|
||||
|
||||
final Set<String> _missingProperties = missingProperties;
|
||||
// Save the flush counter of the entry and create a proxy update.
|
||||
final int flushCounter = entry.fFlushCounter;
|
||||
missUpdates.add(new VMPropertiesUpdate(
|
||||
update.getProperties(),
|
||||
missingProperties,
|
||||
update,
|
||||
new ViewerDataRequestMonitor<Map<String, Object>>(getExecutor(), update) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
Map<String, Object> properties;
|
||||
PropertiesUpdateStatus missUpdateStatus = (PropertiesUpdateStatus)getStatus();
|
||||
Map<String, Object> cachedProperties;
|
||||
PropertiesUpdateStatus cachedStatus;
|
||||
if (!isCanceled() && flushCounter == entry.fFlushCounter) {
|
||||
// We are caching the result of this update. Copy the properties from the update
|
||||
// to the cached properties map.
|
||||
|
@ -1150,56 +1207,67 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
if (update.getProperties().contains(PROP_CACHE_ENTRY_DIRTY)) {
|
||||
entry.fProperties.put(PROP_CACHE_ENTRY_DIRTY, entry.fDirty);
|
||||
}
|
||||
entry.fProperties.put(PROP_UPDATE_STATUS, new PropertiesUpdateStatus());
|
||||
}
|
||||
properties = entry.fProperties;
|
||||
properties.putAll(getData());
|
||||
cachedProperties = entry.fProperties;
|
||||
cachedProperties.putAll(getData());
|
||||
|
||||
// Make sure that all the properties that were
|
||||
// requested by the update object are in the
|
||||
// cache entry's properties map. It's possible the
|
||||
// ViewerDataRequestMonitor was able to provide
|
||||
// us only a subset of the requested ones. We
|
||||
// want to prevent that from causing future
|
||||
// cache misses, since a cache hit requires the
|
||||
// cache entry to contain all requested
|
||||
// properties. Use a null value for the missing
|
||||
// items.
|
||||
for (String updateProperty : update.getProperties()) {
|
||||
if (!properties.containsKey(updateProperty)) {
|
||||
properties.put(updateProperty, null);
|
||||
// Make sure that all the properties that were requested by the update object are in
|
||||
// the cache entry's properties map. It's possible he ViewerDataRequestMonitor was able
|
||||
// to provide us only a subset of the requested ones. We want to prevent that from
|
||||
// causing future cache misses, since a cache hit requires the cache entry to contain
|
||||
// all requested properties. Use a null value for the missing items.
|
||||
for (String property : _missingProperties) {
|
||||
if (!getData().containsKey(property)) {
|
||||
cachedProperties.put(property, null);
|
||||
}
|
||||
}
|
||||
|
||||
// Merge status from properties that came back from the node into the status that's in
|
||||
// the cache.
|
||||
cachedStatus = (PropertiesUpdateStatus)cachedProperties.get(PROP_UPDATE_STATUS);
|
||||
cachedStatus = PropertiesUpdateStatus.mergePropertiesStatus(
|
||||
cachedStatus, missUpdateStatus, _missingProperties);
|
||||
cachedProperties.put(PROP_UPDATE_STATUS, cachedStatus);
|
||||
} else {
|
||||
// We are not caching the result of this update, but we should still
|
||||
// return valid data to the client. In case the update was canceled
|
||||
// we can also return valid data to the client even if the client
|
||||
// is likely to ignore it since the cost of doing so is relatively low.
|
||||
properties = new HashMap<String, Object>((getData().size() + 3) * 4/3);
|
||||
if (update.getProperties().contains(PROP_CACHE_ENTRY_DIRTY)) {
|
||||
properties.put(PROP_CACHE_ENTRY_DIRTY, Boolean.TRUE);
|
||||
// We are not caching the result of this update, but we should still return valid data
|
||||
// to the client. In case the update was canceled we can also return valid data to the
|
||||
// client even if the client is likely to ignore it since the cost of doing so is
|
||||
// relatively low.
|
||||
// Create a temporary cached properties map and add existing cache and node update
|
||||
// properties to it.
|
||||
if (entry.fProperties != null) {
|
||||
cachedProperties = new HashMap<String, Object>((entry.fProperties.size() + getData().size() + 3) * 4/3);
|
||||
cachedProperties.putAll(entry.fProperties);
|
||||
cachedStatus = PropertiesUpdateStatus.mergePropertiesStatus(
|
||||
(PropertiesUpdateStatus)cachedProperties.get(PROP_UPDATE_STATUS),
|
||||
missUpdateStatus, _missingProperties);
|
||||
} else {
|
||||
cachedProperties = new HashMap<String, Object>((getData().size() + 3) * 4/3);
|
||||
cachedStatus = missUpdateStatus;
|
||||
}
|
||||
cachedProperties.putAll(getData());
|
||||
cachedProperties.put(PROP_UPDATE_STATUS, missUpdateStatus);
|
||||
if (update.getProperties().contains(PROP_CACHE_ENTRY_DIRTY)) {
|
||||
cachedProperties.put(PROP_CACHE_ENTRY_DIRTY, Boolean.TRUE);
|
||||
}
|
||||
properties.putAll(getData());
|
||||
}
|
||||
|
||||
// Refresh the update policy property.
|
||||
if (update.getProperties().contains(PROP_UPDATE_POLICY_ID)) {
|
||||
properties.put(PROP_UPDATE_POLICY_ID, getActiveUpdatePolicy().getID());
|
||||
cachedProperties.put(PROP_UPDATE_POLICY_ID, getActiveUpdatePolicy().getID());
|
||||
}
|
||||
|
||||
// Save the update status result in the properties as well, it will be
|
||||
// written to the client update when client updates are completed from
|
||||
// cache.
|
||||
properties.put(PROP_UPDATE_STATUS, getStatus());
|
||||
|
||||
// If there is archive data available, calculate the requested changed value properties.
|
||||
// Do not calculate the changed flags if the entry has been flushed.
|
||||
if (entry.fArchiveProperties != null && flushCounter == entry.fFlushCounter) {
|
||||
for (String updateProperty : update.getProperties()) {
|
||||
if (updateProperty.startsWith(PROP_IS_CHANGED_PREFIX)) {
|
||||
String changedPropertyName = updateProperty.substring(LENGTH_PROP_IS_CHANGED_PREFIX);
|
||||
Object newValue = properties.get(changedPropertyName);
|
||||
Object newValue = cachedProperties.get(changedPropertyName);
|
||||
Object oldValue = entry.fArchiveProperties.get(changedPropertyName);
|
||||
if (oldValue != null) {
|
||||
properties.put(updateProperty, !oldValue.equals(newValue));
|
||||
cachedProperties.put(updateProperty, !oldValue.equals(newValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1209,8 +1277,14 @@ public class AbstractCachingVMProvider extends AbstractVMProvider
|
|||
DsfUIPlugin.debug("cacheSavedProperties(node = " + node + ", update = " + update + ", " + getData() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
|
||||
update.setAllProperties(properties);
|
||||
update.setStatus(getStatus());
|
||||
// Fill in requested properties and status into the update.
|
||||
for (String property : update.getProperties()) {
|
||||
update.setProperty(property, cachedProperties.get(property));
|
||||
}
|
||||
PropertiesUpdateStatus updateStatus = PropertiesUpdateStatus.getPropertiesStatus(update);
|
||||
updateStatus = PropertiesUpdateStatus.mergePropertiesStatus(
|
||||
updateStatus, cachedStatus, update.getProperties());
|
||||
update.setStatus(updateStatus);
|
||||
update.done();
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.ui.viewmodel.update;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* Cache entry in a caching VM provider.
|
||||
*
|
||||
* @see ICachingVMProvider
|
||||
* @see ICachingVMProviderExtension2
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
@ConfinedToDsfExecutor("")
|
||||
public interface ICacheEntry {
|
||||
|
||||
/**
|
||||
* The VM node that this cache entry is for. This parameter is part of the
|
||||
* key to finding the cache entry.
|
||||
*/
|
||||
public IVMNode getNode();
|
||||
|
||||
/**
|
||||
* The viewer input object that this cache entry is for. This parameter
|
||||
* is part of the key to finding the cache entry.
|
||||
*/
|
||||
public Object getViewerInput();
|
||||
|
||||
/**
|
||||
* The element path that this cache entry is for. This parameter is part
|
||||
* of the key to finding the cache entry.
|
||||
*/
|
||||
public TreePath getElementPath();
|
||||
|
||||
/**
|
||||
* Says whether this cache entry is currently marked as dirty. If a cache
|
||||
* entry is dirty, it means that it contains stale data which has not been
|
||||
* flushed as indicated by the cache's update policy.
|
||||
* @return
|
||||
*/
|
||||
public boolean isDirty();
|
||||
|
||||
/**
|
||||
* Returns the a flag indicating whether the element pointing to this entry
|
||||
* has children. Returns <code>null</code> if this value is not known by
|
||||
* cache.
|
||||
*/
|
||||
public Boolean getHasChildren();
|
||||
|
||||
/**
|
||||
* Returns the count of children for the element belonging to this entry.
|
||||
* Returns <code>null</code> if this value is not known by cache.
|
||||
*/
|
||||
public Integer getChildCount();
|
||||
|
||||
/**
|
||||
* Returns a map of children of the element belonging to this entry.
|
||||
* The returned map contains integer keys which are indexes of the
|
||||
* element's children. The values in the map are the child element.
|
||||
* Returns <code>null</code> if this value is not known by cache.
|
||||
*/
|
||||
public Map<Integer, Object> getChildren();
|
||||
|
||||
/**
|
||||
* Returns map of properties of the element belonging to this entry.
|
||||
* Returns <code>null</code> if this value is not known by cache.
|
||||
*/
|
||||
public Map<String, Object> getProperties();
|
||||
|
||||
/**
|
||||
* Returns the archived map of properties of the element belong to this
|
||||
* entry. The archived properties are properties which were saved when
|
||||
* the cache was last flushed, as indicated by the cache's active update
|
||||
* policy. Returns <code>null</code> if this value is not known by cache.
|
||||
*/
|
||||
public Map<String, Object> getArchiveProperties();
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.ui.viewmodel.update;
|
||||
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
|
||||
/**
|
||||
* Extension allowing access to the caching VM provider cache entries.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public interface ICachingVMProviderExtension2 extends ICachingVMProvider {
|
||||
|
||||
/**
|
||||
* Returns the cache entry for the given parameters. May return <code>null</code>
|
||||
* if the cache entry does not exist in the cache.
|
||||
*/
|
||||
public ICacheEntry getCacheEntry(IVMNode node, Object viewerInput, TreePath path);
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.ui.viewmodel.update;
|
||||
|
||||
|
||||
/**
|
||||
* Extension to the VM Update policy which allows the policy to control how to
|
||||
* update missing property values in a dirty cache entry.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public interface IVMUpdatePolicyExtension extends IVMUpdatePolicy {
|
||||
|
||||
/**
|
||||
* Determines whether the given dirty cache entry should have the given
|
||||
* missing property updated.
|
||||
*
|
||||
* @param entry The dirty cache entry that is missing the given requested
|
||||
* property.
|
||||
* @param property Property missing from cache.
|
||||
* @return If <code>true</code> cache can update the given missing property
|
||||
* in the dirty cache entry with data from the VM node.
|
||||
*/
|
||||
public boolean canUpdateDirtyProperty(ICacheEntry entry, String property);
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf;
|
||||
|
||||
/**
|
||||
* Convenience interface with constants used by the test model update listener.
|
||||
* @since 2.2
|
||||
*/
|
||||
public interface IViewerUpdatesListenerConstants {
|
||||
|
||||
public static final int LABEL_SEQUENCE_COMPLETE = 0X00000001;
|
||||
public static final int CONTENT_SEQUENCE_COMPLETE = 0X00000002;
|
||||
public static final int CONTENT_SEQUENCE_STARTED = 0X00020000;
|
||||
public static final int LABEL_UPDATES = 0X00000004;
|
||||
public static final int LABEL_SEQUENCE_STARTED = 0X00040000;
|
||||
public static final int HAS_CHILDREN_UPDATES = 0X00000008;
|
||||
public static final int HAS_CHILDREN_UPDATES_STARTED = 0X00080000;
|
||||
public static final int CHILD_COUNT_UPDATES = 0X00000010;
|
||||
public static final int CHILD_COUNT_UPDATES_STARTED = 0X00100000;
|
||||
public static final int CHILDREN_UPDATES = 0X00000020;
|
||||
public static final int CHILDREN_UPDATES_STARTED = 0X00200000;
|
||||
public static final int MODEL_CHANGED_COMPLETE = 0X00000040;
|
||||
public static final int MODEL_PROXIES_INSTALLED = 0X00000080;
|
||||
public static final int STATE_SAVE_COMPLETE = 0X00000100;
|
||||
public static final int STATE_SAVE_STARTED = 0X01000000;
|
||||
public static final int STATE_RESTORE_COMPLETE = 0X00000200;
|
||||
public static final int STATE_RESTORE_STARTED = 0X02000000;
|
||||
public static final int STATE_UPDATES = 0X00000400;
|
||||
public static final int STATE_UPDATES_STARTED = 0X04000000;
|
||||
public static final int PROPERTY_UPDATES = 0X00000800;
|
||||
public static final int PROPERTY_UPDATES_STARTED = 0X08000000;
|
||||
|
||||
public static final int VIEWER_UPDATES_RUNNING = 0X00001000;
|
||||
public static final int LABEL_UPDATES_RUNNING = 0X00002000;
|
||||
|
||||
public static final int VIEWER_UPDATES_STARTED = HAS_CHILDREN_UPDATES_STARTED | CHILD_COUNT_UPDATES_STARTED | CHILDREN_UPDATES_STARTED;
|
||||
|
||||
public static final int LABEL_COMPLETE = LABEL_SEQUENCE_COMPLETE | LABEL_UPDATES | LABEL_UPDATES_RUNNING;
|
||||
public static final int CONTENT_UPDATES = HAS_CHILDREN_UPDATES | CHILD_COUNT_UPDATES | CHILDREN_UPDATES;
|
||||
public static final int CONTENT_COMPLETE = CONTENT_UPDATES | CONTENT_SEQUENCE_COMPLETE | VIEWER_UPDATES_RUNNING;
|
||||
|
||||
public static final int ALL_UPDATES_COMPLETE = LABEL_COMPLETE | CONTENT_COMPLETE | MODEL_PROXIES_INSTALLED | LABEL_UPDATES_RUNNING | VIEWER_UPDATES_RUNNING;
|
||||
}
|
|
@ -12,6 +12,7 @@ package org.eclipse.cdt.tests.dsf;
|
|||
|
||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
/*
|
||||
* This class provides a way to wait for an asynchronous ServerEvent
|
||||
|
@ -34,14 +35,16 @@ public class ServiceEventWaitor<V> {
|
|||
|
||||
/* The type of event to wait for */
|
||||
private Class<V> fEventTypeClass;
|
||||
private DsfSession fSession;
|
||||
private final DsfSession fSession;
|
||||
private V fEvent;
|
||||
private final Display fDisplay;
|
||||
|
||||
|
||||
/* Empty contructor. registerForEvent() should be called when
|
||||
* this constructor is used.
|
||||
*/
|
||||
public ServiceEventWaitor(DsfSession session) {
|
||||
fDisplay = Display.getDefault();
|
||||
fSession = session;
|
||||
}
|
||||
|
||||
|
@ -62,10 +65,12 @@ public class ServiceEventWaitor<V> {
|
|||
fSession.addServiceEventListener(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
if (fEventTypeClass != null) fSession.removeServiceEventListener(this);
|
||||
public DsfSession getSession() {
|
||||
return fSession;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (fEventTypeClass != null) fSession.removeServiceEventListener(this);
|
||||
}
|
||||
|
||||
/* Block until 'timeout' or the previously specified event has been
|
||||
|
@ -80,7 +85,15 @@ public class ServiceEventWaitor<V> {
|
|||
// The event might have already been received
|
||||
if (fEvent != null) return fEvent;
|
||||
|
||||
wait(timeout);
|
||||
long timeoutTime = System.currentTimeMillis() + timeout;
|
||||
while (timeoutTime > System.currentTimeMillis()) {
|
||||
if (fEvent != null) {
|
||||
break;
|
||||
}
|
||||
if (!fDisplay.readAndDispatch()) {
|
||||
Thread.sleep(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (fEvent == null) {
|
||||
throw new Exception("Timed out waiting for ServiceEvent: " + fEventTypeClass.getName());
|
||||
|
|
|
@ -0,0 +1,644 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdateListener;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ILabelUpdateListener;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IStateUpdateListener;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
*/
|
||||
public class ViewerUpdatesListener
|
||||
implements IViewerUpdateListener, ILabelUpdateListener, IModelChangedListener, IViewerUpdatesListenerConstants,
|
||||
IStateUpdateListener, IPropertiesUpdateListener
|
||||
{
|
||||
private ITreeModelViewer fViewer;
|
||||
|
||||
private boolean fFailOnRedundantUpdates;
|
||||
private Set<IViewerUpdate> fRedundantUpdates = new HashSet<IViewerUpdate>();
|
||||
|
||||
private boolean fFailOnMultipleModelUpdateSequences;
|
||||
private boolean fMultipleModelUpdateSequencesObserved;
|
||||
private boolean fFailOnMultipleLabelUpdateSequences;
|
||||
private boolean fMultipleLabelUpdateSequencesObserved;
|
||||
|
||||
private Set<TreePath> fHasChildrenUpdatesScheduled = makeTreePathSet();
|
||||
private Set<IViewerUpdate> fHasChildrenUpdatesRunning = new HashSet<IViewerUpdate>();
|
||||
private Set<IViewerUpdate> fHasChildrenUpdatesCompleted = new HashSet<IViewerUpdate>();
|
||||
private Map<TreePath, Set<Integer>> fChildrenUpdatesScheduled = makeTreePathMap();
|
||||
private Set<IViewerUpdate> fChildrenUpdatesRunning = new HashSet<IViewerUpdate>();
|
||||
private Set<IViewerUpdate> fChildrenUpdatesCompleted = new HashSet<IViewerUpdate>();
|
||||
private Set<TreePath> fChildCountUpdatesScheduled = makeTreePathSet();
|
||||
private Set<IViewerUpdate> fChildCountUpdatesRunning = new HashSet<IViewerUpdate>();
|
||||
private Set<IViewerUpdate> fChildCountUpdatesCompleted = new HashSet<IViewerUpdate>();
|
||||
private Set<TreePath> fLabelUpdates = makeTreePathSet();
|
||||
private Set<IViewerUpdate> fLabelUpdatesRunning = new HashSet<IViewerUpdate>();
|
||||
private Set<IViewerUpdate> fLabelUpdatesCompleted = new HashSet<IViewerUpdate>();
|
||||
private Set<TreePath> fPropertiesUpdates = makeTreePathSet();
|
||||
private Set<IViewerUpdate> fPropertiesUpdatesRunning = new HashSet<IViewerUpdate>();
|
||||
private Set<IViewerUpdate> fPropertiesUpdatesCompleted = new HashSet<IViewerUpdate>();
|
||||
// private Set<TreePath> fProxyModels = new HashSet<TreePath>();
|
||||
private Set<TreePath> fStateUpdates = makeTreePathSet();
|
||||
private boolean fContentSequenceStarted;
|
||||
private boolean fContentSequenceComplete;
|
||||
private boolean fLabelUpdatesStarted;
|
||||
private boolean fLabelSequenceComplete;
|
||||
private boolean fModelChangedComplete;
|
||||
private boolean fStateSaveStarted;
|
||||
private boolean fStateSaveComplete;
|
||||
private boolean fStateRestoreStarted;
|
||||
private boolean fStateRestoreComplete;
|
||||
private int fContentUpdatesCounter;
|
||||
private int fLabelUpdatesCounter;
|
||||
private int fPropertiesUpdatesCounter;
|
||||
private int fTimeoutInterval = 60000;
|
||||
private long fTimeoutTime;
|
||||
|
||||
protected Set<TreePath> makeTreePathSet() {
|
||||
return new HashSet<TreePath>();
|
||||
}
|
||||
|
||||
protected <V> Map<TreePath, V> makeTreePathMap() {
|
||||
return new HashMap<TreePath, V>();
|
||||
}
|
||||
|
||||
|
||||
public ViewerUpdatesListener(ITreeModelViewer viewer, boolean failOnRedundantUpdates, boolean failOnMultipleModelUpdateSequences) {
|
||||
this(viewer);
|
||||
setFailOnRedundantUpdates(failOnRedundantUpdates);
|
||||
setFailOnMultipleModelUpdateSequences(failOnMultipleModelUpdateSequences);
|
||||
}
|
||||
|
||||
public ViewerUpdatesListener() {
|
||||
// No viewer to register with. Client will have to register the listener manually.
|
||||
}
|
||||
|
||||
public ViewerUpdatesListener(ITreeModelViewer viewer) {
|
||||
fViewer = viewer;
|
||||
fViewer.addLabelUpdateListener(this);
|
||||
fViewer.addModelChangedListener(this);
|
||||
fViewer.addStateUpdateListener(this);
|
||||
fViewer.addViewerUpdateListener(this);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (fViewer != null) {
|
||||
fViewer.removeLabelUpdateListener(this);
|
||||
fViewer.removeModelChangedListener(this);
|
||||
fViewer.removeStateUpdateListener(this);
|
||||
fViewer.removeViewerUpdateListener(this);
|
||||
fViewer = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setFailOnRedundantUpdates(boolean failOnRedundantUpdates) {
|
||||
fFailOnRedundantUpdates = failOnRedundantUpdates;
|
||||
}
|
||||
|
||||
public void setFailOnMultipleModelUpdateSequences(boolean failOnMultipleLabelUpdateSequences) {
|
||||
fFailOnMultipleModelUpdateSequences = failOnMultipleLabelUpdateSequences;
|
||||
}
|
||||
|
||||
public void setFailOnMultipleLabelUpdateSequences(boolean failOnMultipleLabelUpdateSequences) {
|
||||
fFailOnMultipleLabelUpdateSequences = failOnMultipleLabelUpdateSequences;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the the maximum amount of time (in milliseconds) that the update listener
|
||||
* is going to wait. If set to -1, the listener will wait indefinitely.
|
||||
*/
|
||||
public void setTimeoutInterval(int milis) {
|
||||
fTimeoutInterval = milis;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
fRedundantUpdates.clear();
|
||||
fMultipleLabelUpdateSequencesObserved = false;
|
||||
fMultipleModelUpdateSequencesObserved = false;
|
||||
fHasChildrenUpdatesScheduled.clear();
|
||||
fHasChildrenUpdatesRunning.clear();
|
||||
fHasChildrenUpdatesCompleted.clear();
|
||||
fChildrenUpdatesScheduled.clear();
|
||||
fChildrenUpdatesRunning.clear();
|
||||
fChildrenUpdatesCompleted.clear();
|
||||
fChildCountUpdatesScheduled.clear();
|
||||
fChildCountUpdatesRunning.clear();
|
||||
fChildCountUpdatesCompleted.clear();
|
||||
fLabelUpdates.clear();
|
||||
fLabelUpdatesRunning.clear();
|
||||
fLabelUpdatesCompleted.clear();
|
||||
// fProxyModels.clear();
|
||||
fContentSequenceStarted = false;
|
||||
fContentSequenceComplete = false;
|
||||
fLabelUpdatesStarted = false;
|
||||
fLabelSequenceComplete = false;
|
||||
fStateSaveStarted = false;
|
||||
fStateSaveComplete = false;
|
||||
fStateRestoreStarted = false;
|
||||
fStateRestoreComplete = false;
|
||||
fTimeoutTime = System.currentTimeMillis() + fTimeoutInterval;
|
||||
resetModelChanged();
|
||||
}
|
||||
|
||||
public void resetModelChanged() {
|
||||
fModelChangedComplete = false;
|
||||
}
|
||||
|
||||
public void addHasChildrenUpdate(TreePath path) {
|
||||
fHasChildrenUpdatesScheduled.add(path);
|
||||
}
|
||||
|
||||
public void removeHasChildrenUpdate(TreePath path) {
|
||||
fHasChildrenUpdatesScheduled.remove(path);
|
||||
}
|
||||
|
||||
public void addChildCountUpdate(TreePath path) {
|
||||
fChildCountUpdatesScheduled.add(path);
|
||||
}
|
||||
|
||||
public void removeChildreCountUpdate(TreePath path) {
|
||||
fChildCountUpdatesScheduled.remove(path);
|
||||
}
|
||||
|
||||
public void addChildreUpdate(TreePath path, int index) {
|
||||
Set<Integer> childrenIndexes = fChildrenUpdatesScheduled.get(path);
|
||||
if (childrenIndexes == null) {
|
||||
childrenIndexes = new TreeSet<Integer>();
|
||||
fChildrenUpdatesScheduled.put(path, childrenIndexes);
|
||||
}
|
||||
childrenIndexes.add(new Integer(index));
|
||||
}
|
||||
|
||||
public void removeChildrenUpdate(TreePath path, int index) {
|
||||
Set<Integer> childrenIndexes = fChildrenUpdatesScheduled.get(path);
|
||||
if (childrenIndexes != null) {
|
||||
childrenIndexes.remove(new Integer(index));
|
||||
if (childrenIndexes.isEmpty()) {
|
||||
fChildrenUpdatesScheduled.remove(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addLabelUpdate(TreePath path) {
|
||||
fLabelUpdates.add(path);
|
||||
}
|
||||
|
||||
public void addPropertiesUpdate(TreePath path) {
|
||||
fPropertiesUpdates.add(path);
|
||||
}
|
||||
|
||||
public void removeLabelUpdate(TreePath path) {
|
||||
fLabelUpdates.remove(path);
|
||||
}
|
||||
|
||||
public void addStateUpdate(TreePath path) {
|
||||
fStateUpdates.add(path);
|
||||
}
|
||||
|
||||
public void removeStateUpdate(TreePath path) {
|
||||
fStateUpdates.remove(path);
|
||||
}
|
||||
|
||||
|
||||
public boolean isFinished() {
|
||||
return isFinished(ALL_UPDATES_COMPLETE);
|
||||
}
|
||||
|
||||
public boolean isTimedOut() {
|
||||
return fTimeoutInterval > 0 && fTimeoutTime < System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean isFinished(int flags) {
|
||||
if (isTimedOut()) {
|
||||
throw new RuntimeException("Timed Out: " + toString(flags));
|
||||
}
|
||||
|
||||
if (fFailOnRedundantUpdates && !fRedundantUpdates.isEmpty()) {
|
||||
Assert.fail("Redundant Updates: " + fRedundantUpdates.toString());
|
||||
}
|
||||
if (fFailOnMultipleLabelUpdateSequences && !fMultipleLabelUpdateSequencesObserved) {
|
||||
Assert.fail("Multiple label update sequences detected");
|
||||
}
|
||||
if (fFailOnMultipleModelUpdateSequences && fMultipleModelUpdateSequencesObserved) {
|
||||
Assert.fail("Multiple viewer update sequences detected");
|
||||
}
|
||||
|
||||
if ( (flags & LABEL_SEQUENCE_COMPLETE) != 0) {
|
||||
if (!fLabelSequenceComplete) return false;
|
||||
}
|
||||
if ( (flags & LABEL_SEQUENCE_STARTED) != 0) {
|
||||
if (!fLabelUpdatesStarted) return false;
|
||||
}
|
||||
if ( (flags & LABEL_UPDATES) != 0) {
|
||||
if (!fLabelUpdates.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & CONTENT_SEQUENCE_STARTED) != 0) {
|
||||
if (!fContentSequenceStarted) return false;
|
||||
}
|
||||
if ( (flags & CONTENT_SEQUENCE_COMPLETE) != 0) {
|
||||
if (!fContentSequenceComplete) return false;
|
||||
}
|
||||
if ( (flags & HAS_CHILDREN_UPDATES_STARTED) != 0) {
|
||||
if (fHasChildrenUpdatesRunning.isEmpty() && fHasChildrenUpdatesCompleted.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & HAS_CHILDREN_UPDATES) != 0) {
|
||||
if (!fHasChildrenUpdatesScheduled.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & CHILD_COUNT_UPDATES_STARTED) != 0) {
|
||||
if (fChildCountUpdatesRunning.isEmpty() && fChildCountUpdatesCompleted.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & CHILD_COUNT_UPDATES) != 0) {
|
||||
if (!fChildCountUpdatesScheduled.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & CHILDREN_UPDATES_STARTED) != 0) {
|
||||
if (fChildrenUpdatesRunning.isEmpty() && fChildrenUpdatesCompleted.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & CHILDREN_UPDATES) != 0) {
|
||||
if (!fChildrenUpdatesScheduled.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & MODEL_CHANGED_COMPLETE) != 0) {
|
||||
if (!fModelChangedComplete) return false;
|
||||
}
|
||||
if ( (flags & STATE_SAVE_COMPLETE) != 0) {
|
||||
if (!fStateSaveComplete) return false;
|
||||
}
|
||||
if ( (flags & STATE_SAVE_STARTED) != 0) {
|
||||
if (!fStateSaveStarted) return false;
|
||||
}
|
||||
if ( (flags & STATE_RESTORE_COMPLETE) != 0) {
|
||||
if (!fStateRestoreComplete) return false;
|
||||
}
|
||||
if ( (flags & STATE_RESTORE_STARTED) != 0) {
|
||||
if (!fStateRestoreStarted) return false;
|
||||
}
|
||||
// if ( (flags & MODEL_PROXIES_INSTALLED) != 0) {
|
||||
// if (fProxyModels.size() != 0) return false;
|
||||
// }
|
||||
if ( (flags & VIEWER_UPDATES_RUNNING) != 0) {
|
||||
if (fContentUpdatesCounter != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( (flags & LABEL_UPDATES_RUNNING) != 0) {
|
||||
if (fLabelUpdatesCounter != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( (flags & PROPERTY_UPDATES) != 0) {
|
||||
if (!fPropertiesUpdates.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & PROPERTY_UPDATES_STARTED) != 0) {
|
||||
if (fPropertiesUpdatesRunning.isEmpty() && fPropertiesUpdatesCompleted.isEmpty()) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateStarted(IViewerUpdate update) {
|
||||
synchronized (this) {
|
||||
fContentUpdatesCounter++;
|
||||
if (update instanceof IHasChildrenUpdate) {
|
||||
fHasChildrenUpdatesRunning.add(update);
|
||||
} if (update instanceof IChildrenCountUpdate) {
|
||||
fChildCountUpdatesRunning.add(update);
|
||||
} else if (update instanceof IChildrenUpdate) {
|
||||
fChildCountUpdatesRunning.add(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateComplete(IViewerUpdate update) {
|
||||
synchronized (this) {
|
||||
fContentUpdatesCounter--;
|
||||
}
|
||||
|
||||
if (!update.isCanceled()) {
|
||||
if (update instanceof IHasChildrenUpdate) {
|
||||
fHasChildrenUpdatesRunning.remove(update);
|
||||
fHasChildrenUpdatesCompleted.add(update);
|
||||
if (!fHasChildrenUpdatesScheduled.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
|
||||
fRedundantUpdates.add(update);
|
||||
}
|
||||
} if (update instanceof IChildrenCountUpdate) {
|
||||
fChildCountUpdatesRunning.remove(update);
|
||||
fChildCountUpdatesCompleted.add(update);
|
||||
if (!fChildCountUpdatesScheduled.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
|
||||
fRedundantUpdates.add(update);
|
||||
}
|
||||
} else if (update instanceof IChildrenUpdate) {
|
||||
fChildrenUpdatesRunning.remove(update);
|
||||
fChildrenUpdatesCompleted.add(update);
|
||||
|
||||
int start = ((IChildrenUpdate)update).getOffset();
|
||||
int end = start + ((IChildrenUpdate)update).getLength();
|
||||
|
||||
Set<Integer> childrenIndexes = fChildrenUpdatesScheduled.get(update.getElementPath());
|
||||
if (childrenIndexes != null) {
|
||||
for (int i = start; i < end; i++) {
|
||||
childrenIndexes.remove(new Integer(i));
|
||||
}
|
||||
if (childrenIndexes.isEmpty()) {
|
||||
fChildrenUpdatesScheduled.remove(update.getElementPath());
|
||||
}
|
||||
} else if (fFailOnRedundantUpdates) {
|
||||
fRedundantUpdates.add(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void viewerUpdatesBegin() {
|
||||
if (fFailOnMultipleModelUpdateSequences && fContentSequenceComplete) {
|
||||
fMultipleModelUpdateSequencesObserved = true;
|
||||
}
|
||||
fContentSequenceStarted = true;
|
||||
}
|
||||
|
||||
public void viewerUpdatesComplete() {
|
||||
fContentSequenceComplete = true;
|
||||
}
|
||||
|
||||
public void labelUpdateComplete(ILabelUpdate update) {
|
||||
synchronized (this) {
|
||||
fLabelUpdatesRunning.remove(update);
|
||||
fLabelUpdatesCompleted.add(update);
|
||||
fLabelUpdatesCounter--;
|
||||
}
|
||||
if (!fLabelUpdates.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
|
||||
fRedundantUpdates.add(update);
|
||||
}
|
||||
}
|
||||
|
||||
public void labelUpdateStarted(ILabelUpdate update) {
|
||||
synchronized (this) {
|
||||
fLabelUpdatesRunning.add(update);
|
||||
fLabelUpdatesCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
public void labelUpdatesBegin() {
|
||||
if (fFailOnMultipleLabelUpdateSequences && fLabelSequenceComplete) {
|
||||
fMultipleLabelUpdateSequencesObserved = true;
|
||||
}
|
||||
fLabelUpdatesStarted = true;
|
||||
}
|
||||
|
||||
public void labelUpdatesComplete() {
|
||||
fLabelSequenceComplete = true;
|
||||
}
|
||||
|
||||
public void propertiesUpdatesStarted(IPropertiesUpdate[] updates) {
|
||||
for (IPropertiesUpdate update : updates) {
|
||||
fPropertiesUpdatesRunning.add(update);
|
||||
fPropertiesUpdatesCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
public void propertiesUpdateCompleted(IPropertiesUpdate update) {
|
||||
synchronized (this) {
|
||||
fPropertiesUpdatesRunning.remove(update);
|
||||
fPropertiesUpdatesCompleted.add(update);
|
||||
fPropertiesUpdatesCounter--;
|
||||
}
|
||||
if (!fPropertiesUpdates.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
|
||||
fRedundantUpdates.add(update);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void modelChanged(IModelDelta delta, IModelProxy proxy) {
|
||||
fModelChangedComplete = true;
|
||||
}
|
||||
|
||||
public void stateRestoreUpdatesBegin(Object input) {
|
||||
fStateRestoreStarted = true;
|
||||
}
|
||||
|
||||
public void stateRestoreUpdatesComplete(Object input) {
|
||||
fStateRestoreComplete = true;
|
||||
}
|
||||
|
||||
public void stateSaveUpdatesBegin(Object input) {
|
||||
fStateSaveStarted = true;
|
||||
}
|
||||
|
||||
public void stateSaveUpdatesComplete(Object input) {
|
||||
fStateSaveComplete = true;
|
||||
}
|
||||
|
||||
public void stateUpdateComplete(Object input, IViewerUpdate update) {
|
||||
}
|
||||
|
||||
public void stateUpdateStarted(Object input, IViewerUpdate update) {
|
||||
}
|
||||
|
||||
private String toString(int flags) {
|
||||
StringBuffer buf = new StringBuffer("Viewer Update Listener");
|
||||
|
||||
if (fFailOnRedundantUpdates) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fRedundantUpdates = ");
|
||||
buf.append( toStringViewerUpdatesSet(fRedundantUpdates) );
|
||||
}
|
||||
if (fFailOnMultipleLabelUpdateSequences) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fMultipleLabelUpdateSequencesObserved = " + fMultipleLabelUpdateSequencesObserved);
|
||||
}
|
||||
if (fFailOnMultipleModelUpdateSequences) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fMultipleModelUpdateSequencesObserved = " + fMultipleModelUpdateSequencesObserved);
|
||||
}
|
||||
if ( (flags & LABEL_SEQUENCE_COMPLETE) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fLabelSequenceComplete = " + fLabelSequenceComplete);
|
||||
}
|
||||
if ( (flags & LABEL_UPDATES_RUNNING) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fLabelUpdatesRunning = " + fLabelUpdatesCounter);
|
||||
}
|
||||
if ( (flags & LABEL_SEQUENCE_STARTED) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fLabelUpdatesRunning = ");
|
||||
buf.append( toStringViewerUpdatesSet(fLabelUpdatesRunning) );
|
||||
buf.append("\n\t");
|
||||
buf.append("fLabelUpdatesCompleted = ");
|
||||
buf.append( toStringViewerUpdatesSet(fLabelUpdatesCompleted) );
|
||||
}
|
||||
if ( (flags & LABEL_UPDATES) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fLabelUpdates = ");
|
||||
buf.append( toString(fLabelUpdates) );
|
||||
}
|
||||
if ( (flags & CONTENT_SEQUENCE_COMPLETE) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fContentSequenceComplete = " + fContentSequenceComplete);
|
||||
}
|
||||
if ( (flags & VIEWER_UPDATES_RUNNING) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fContentUpdatesCounter = " + fContentUpdatesCounter);
|
||||
}
|
||||
if ( (flags & HAS_CHILDREN_UPDATES_STARTED) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fHasChildrenUpdatesRunning = ");
|
||||
buf.append( toStringViewerUpdatesSet(fHasChildrenUpdatesRunning) );
|
||||
buf.append("\n\t");
|
||||
buf.append("fHasChildrenUpdatesCompleted = ");
|
||||
buf.append( toStringViewerUpdatesSet(fHasChildrenUpdatesCompleted) );
|
||||
}
|
||||
if ( (flags & HAS_CHILDREN_UPDATES) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fHasChildrenUpdates = ");
|
||||
buf.append( toString(fHasChildrenUpdatesScheduled) );
|
||||
}
|
||||
if ( (flags & CHILD_COUNT_UPDATES_STARTED) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fChildCountUpdatesRunning = ");
|
||||
buf.append( toStringViewerUpdatesSet(fChildCountUpdatesRunning) );
|
||||
buf.append("\n\t");
|
||||
buf.append("fChildCountUpdatesCompleted = ");
|
||||
buf.append( toStringViewerUpdatesSet(fChildCountUpdatesCompleted) );
|
||||
}
|
||||
if ( (flags & CHILD_COUNT_UPDATES) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fChildCountUpdates = ");
|
||||
buf.append( toString(fChildCountUpdatesScheduled) );
|
||||
}
|
||||
if ( (flags & CHILDREN_UPDATES_STARTED) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fChildrenUpdatesRunning = ");
|
||||
buf.append( fChildrenUpdatesRunning );
|
||||
buf.append("\n\t");
|
||||
buf.append("fChildrenUpdatesCompleted = ");
|
||||
buf.append( toStringViewerUpdatesSet(fChildrenUpdatesCompleted) );
|
||||
}
|
||||
if ( (flags & CHILDREN_UPDATES) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fChildrenUpdates = ");
|
||||
buf.append( toStringTreePathMap(fChildrenUpdatesScheduled) );
|
||||
}
|
||||
if ( (flags & MODEL_CHANGED_COMPLETE) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fModelChangedComplete = " + fModelChangedComplete);
|
||||
}
|
||||
if ( (flags & STATE_SAVE_COMPLETE) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fStateSaveComplete = " + fStateSaveComplete);
|
||||
}
|
||||
if ( (flags & STATE_RESTORE_COMPLETE) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fStateRestoreComplete = " + fStateRestoreComplete);
|
||||
}
|
||||
// if ( (flags & MODEL_PROXIES_INSTALLED) != 0) {
|
||||
// buf.append("\n\t");
|
||||
// buf.append("fProxyModels = " + fProxyModels);
|
||||
// }
|
||||
if ( (flags & PROPERTY_UPDATES_STARTED) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fPropertiesUpdatesRunning = ");
|
||||
buf.append(toStringViewerUpdatesSet(fPropertiesUpdatesRunning));
|
||||
buf.append("\n\t");
|
||||
buf.append("fPropertiesUpdatesCompleted = " + fPropertiesUpdatesCompleted);
|
||||
}
|
||||
if ( (flags & PROPERTY_UPDATES) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fPropertiesUpdates = ");
|
||||
buf.append( toString(fPropertiesUpdates) );
|
||||
}
|
||||
if (fTimeoutInterval > 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fTimeoutInterval = " + fTimeoutInterval);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String toString(Set<TreePath> set) {
|
||||
if (set.isEmpty()) {
|
||||
return "(EMPTY)";
|
||||
}
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (Iterator<TreePath> itr = set.iterator(); itr.hasNext(); ) {
|
||||
buf.append("\n\t\t");
|
||||
buf.append(toStringTreePath(itr.next()));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String toStringViewerUpdatesSet(Set<IViewerUpdate> set) {
|
||||
if (set.isEmpty()) {
|
||||
return "(EMPTY)";
|
||||
}
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (Iterator<IViewerUpdate> itr = set.iterator(); itr.hasNext(); ) {
|
||||
buf.append("\n\t\t");
|
||||
buf.append(toStringTreePath((itr.next()).getElementPath()));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String toStringTreePathMap(Map<TreePath, Set<Integer>> map) {
|
||||
if (map.isEmpty()) {
|
||||
return "(EMPTY)";
|
||||
}
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (Iterator<TreePath> itr = map.keySet().iterator(); itr.hasNext(); ) {
|
||||
buf.append("\n\t\t");
|
||||
TreePath path = itr.next();
|
||||
buf.append(toStringTreePath(path));
|
||||
Set<?> updates = map.get(path);
|
||||
buf.append(" = ");
|
||||
buf.append(updates.toString());
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String toStringTreePath(TreePath path) {
|
||||
if (path.getSegmentCount() == 0) {
|
||||
return "/";
|
||||
}
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i = 0; i < path.getSegmentCount(); i++) {
|
||||
buf.append("/");
|
||||
buf.append(path.getSegment(i));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(ALL_UPDATES_COMPLETE | MODEL_CHANGED_COMPLETE | STATE_RESTORE_COMPLETE |
|
||||
VIEWER_UPDATES_STARTED | LABEL_SEQUENCE_STARTED | PROPERTY_UPDATES | PROPERTY_UPDATES_STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.debug.vm.launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Query;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.ILaunchVMConstants;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.VMPropertiesUpdate;
|
||||
import org.eclipse.cdt.examples.dsf.pda.PDAPlugin;
|
||||
import org.eclipse.cdt.tests.dsf.IViewerUpdatesListenerConstants;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModelUpdatesListener;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDeltaVisitor;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualTreeModelViewer;
|
||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class VMTest1 extends VMTestBase implements IViewerUpdatesListenerConstants {
|
||||
|
||||
@Override
|
||||
protected String getProgramPath() {
|
||||
File programFile = PDAPlugin.getFileInPlugin(new Path("samples/example.pda"));
|
||||
return programFile.getPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRun() throws Throwable {
|
||||
|
||||
Display display = Display.getDefault();
|
||||
|
||||
final VirtualTreeModelViewer dv = new VirtualTreeModelViewer(
|
||||
display, 0, new PresentationContext(IDebugUIConstants.ID_DEBUG_VIEW));
|
||||
|
||||
TestModelUpdatesListener listener = new TestModelUpdatesListener(dv, false, false);
|
||||
|
||||
// Wait for container expand delta, sent by the model upon DV install event.
|
||||
final boolean[] containerExpandReceived = new boolean[1];
|
||||
containerExpandReceived[0] = false;
|
||||
dv.addModelChangedListener(new IModelChangedListener() {
|
||||
public void modelChanged(IModelDelta delta, IModelProxy proxy) {
|
||||
delta.accept(new IModelDeltaVisitor() {
|
||||
public boolean visit(IModelDelta delta, int depth) {
|
||||
if (delta.getElement() instanceof IDMVMContext &&
|
||||
((IDMVMContext)delta.getElement()).getDMContext() instanceof IContainerDMContext &&
|
||||
(delta.getFlags() & IModelDelta.EXPAND) != 0)
|
||||
{
|
||||
containerExpandReceived[0] = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
dv.setInput(DebugPlugin.getDefault().getLaunchManager());
|
||||
|
||||
while(!containerExpandReceived[0]) {
|
||||
if (!display.readAndDispatch()) display.sleep();
|
||||
}
|
||||
|
||||
listener.reset();
|
||||
|
||||
// TODO: need to wait for the install delta for the launch to be processed
|
||||
while (!listener.isFinished(CONTENT_SEQUENCE_COMPLETE)) {
|
||||
if (!display.readAndDispatch()) display.sleep();
|
||||
}
|
||||
|
||||
// Find our launch
|
||||
int launchIdx = dv.findElementIndex(TreePath.EMPTY, getLaunch());
|
||||
Assert.assertTrue(-1 != launchIdx);
|
||||
|
||||
// Find the debug container
|
||||
TreePath launchPath = TreePath.EMPTY.createChildPath(getLaunch());
|
||||
int launchChildCount = dv.getChildCount(launchPath);
|
||||
IDMVMContext _containerVMC = null;
|
||||
for (int i = 0; i < launchChildCount; i++) {
|
||||
Object launchChild = dv.getChildElement(launchPath, i);
|
||||
if (launchChild instanceof IDMVMContext &&
|
||||
((IDMVMContext)launchChild).getDMContext() instanceof IContainerDMContext)
|
||||
{
|
||||
_containerVMC = (IDMVMContext)launchChild;
|
||||
}
|
||||
}
|
||||
Assert.assertNotNull(_containerVMC);
|
||||
final IDMVMContext containerVMC = _containerVMC;
|
||||
final TreePath containerPath = launchPath.createChildPath(containerVMC);
|
||||
final IElementPropertiesProvider containerPropProvider =
|
||||
(IElementPropertiesProvider)containerVMC.getAdapter(IElementPropertiesProvider.class);
|
||||
Assert.assertNotNull(containerPropProvider);
|
||||
|
||||
// Check if container is suspended.
|
||||
Query<Map<String,Object>> suspendedQuery = new Query<Map<String,Object>>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<Map<String, Object>> rm) {
|
||||
Set<String> properties = new HashSet<String>();
|
||||
properties.add(ILaunchVMConstants.PROP_IS_SUSPENDED);
|
||||
|
||||
containerPropProvider.update( new VMPropertiesUpdate[] {
|
||||
new VMPropertiesUpdate(properties, containerPath, dv.getInput(), dv.getPresentationContext(), rm) });
|
||||
}
|
||||
};
|
||||
suspendedQuery.run();
|
||||
|
||||
// Wait for the properties update to complete
|
||||
while (!suspendedQuery.isDone()) {
|
||||
if (!display.readAndDispatch()) display.sleep();
|
||||
}
|
||||
|
||||
Map<String,Object> properties = suspendedQuery.get();
|
||||
Assert.assertEquals(Boolean.TRUE, properties.get(ILaunchVMConstants.PROP_IS_SUSPENDED));
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Ericsson 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:
|
||||
* Ericsson - Initial Implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.debug.vm.launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession.SessionStartedListener;
|
||||
import org.eclipse.cdt.examples.dsf.pda.PDAPlugin;
|
||||
import org.eclipse.cdt.examples.dsf.pda.launch.PDALaunch;
|
||||
import org.eclipse.cdt.tests.dsf.ServiceEventWaitor;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||
import org.eclipse.debug.core.ILaunchConfigurationType;
|
||||
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
|
||||
import org.eclipse.debug.core.ILaunchManager;
|
||||
import org.eclipse.debug.internal.ui.DebugUIPlugin;
|
||||
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
|
||||
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
/**
|
||||
* This is the base class for the GDB/MI Unit tests.
|
||||
* It provides the @Before and @After methods which setup
|
||||
* and teardown the launch, for each test.
|
||||
* If these methods are overwridden by a subclass, the new method
|
||||
* must call super.baseSetup or super.baseTeardown itself, if this
|
||||
* code is to be run.
|
||||
*/
|
||||
public class VMTestBase {
|
||||
|
||||
private PDALaunch fLaunch;
|
||||
public PDALaunch getPDALaunch() { return fLaunch; }
|
||||
|
||||
@BeforeClass
|
||||
public static void baseBeforeClassMethod() {
|
||||
DebugUIPlugin.getDefault().getPreferenceStore().setValue(
|
||||
IInternalDebugUIConstants.PREF_SWITCH_TO_PERSPECTIVE, MessageDialogWithToggle.NEVER);
|
||||
DebugUIPlugin.getDefault().getPreferenceStore().setValue(
|
||||
IInternalDebugUIConstants.PREF_SWITCH_PERSPECTIVE_ON_SUSPEND, MessageDialogWithToggle.NEVER);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void baseBeforeMethod() throws Exception {
|
||||
Map<String, Object> attrs = new HashMap<String, Object>();
|
||||
|
||||
initLaunchAttributes(attrs);
|
||||
|
||||
System.out.println("====================================================================");
|
||||
System.out.println("Launching test application: " + attrs.get(PDAPlugin.ATTR_PDA_PROGRAM));
|
||||
System.out.println("====================================================================");
|
||||
|
||||
ILaunchManager launchMgr = DebugPlugin.getDefault().getLaunchManager();
|
||||
ILaunchConfigurationType lcType = launchMgr.getLaunchConfigurationType("org.eclipse.cdt.examples.dsf.pda.launchType");
|
||||
assert lcType != null;
|
||||
|
||||
ILaunchConfigurationWorkingCopy lcWorkingCopy = lcType.newInstance(
|
||||
null,
|
||||
launchMgr.generateUniqueLaunchConfigurationNameFrom("Test Launch")); //$NON-NLS-1$
|
||||
assert lcWorkingCopy != null;
|
||||
lcWorkingCopy.setAttributes(attrs);
|
||||
|
||||
final ILaunchConfiguration lc = lcWorkingCopy.doSave();
|
||||
assert lc != null;
|
||||
|
||||
final ServiceEventWaitor<?> eventWaitor[] = new ServiceEventWaitor<?>[1];
|
||||
|
||||
SessionStartedListener newSessionListener = new SessionStartedListener() {
|
||||
public void sessionStarted(DsfSession session) {
|
||||
eventWaitor[0] = new ServiceEventWaitor<IStartedDMEvent>(session, IStartedDMEvent.class);
|
||||
}
|
||||
};
|
||||
|
||||
DsfSession.addSessionStartedListener(newSessionListener);
|
||||
try {
|
||||
fLaunch = (PDALaunch)lc.launch(ILaunchManager.DEBUG_MODE, new NullProgressMonitor());
|
||||
Assert.assertNotNull(fLaunch);
|
||||
Assert.assertNotNull(eventWaitor[0]);
|
||||
Assert.assertSame(fLaunch.getSession(), eventWaitor[0].getSession());
|
||||
eventWaitor[0].waitForEvent(60000);
|
||||
} finally {
|
||||
DsfSession.removeSessionStartedListener(newSessionListener);
|
||||
if (eventWaitor[0] != null) {
|
||||
eventWaitor[0].dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void initLaunchAttributes(Map<String, Object> attrs) {
|
||||
attrs.put(PDAPlugin.ATTR_PDA_PROGRAM, getProgramPath());
|
||||
}
|
||||
|
||||
protected String getProgramPath() {
|
||||
File programFile = PDAPlugin.getFileInPlugin(new Path("samples/example.pda"));
|
||||
return programFile.getPath();
|
||||
}
|
||||
|
||||
protected ILaunch getLaunch() {
|
||||
return fLaunch;
|
||||
}
|
||||
|
||||
@After
|
||||
public void baseAfterMethod() throws Exception {
|
||||
if (fLaunch != null) {
|
||||
fLaunch.terminate();
|
||||
fLaunch = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package org.eclipse.cdt.tests.dsf.vm;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
|
||||
import org.eclipse.cdt.dsf.service.AbstractDsfService;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.tests.dsf.DsfTestPlugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
public class DummyFormattedValueService extends AbstractDsfService implements IFormattedValues {
|
||||
|
||||
public static String DUMMY_FORMAT = "dummy";
|
||||
public static String[] AVAILABLE_FORMATS = new String[] { DUMMY_FORMAT, HEX_FORMAT, OCTAL_FORMAT, BINARY_FORMAT, NATURAL_FORMAT, DECIMAL_FORMAT, STRING_FORMAT };
|
||||
|
||||
public DummyFormattedValueService(DsfSession session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(RequestMonitor rm) {
|
||||
super.initialize(new RequestMonitor(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
register(new String[0], new Hashtable<String, String>() );
|
||||
super.handleSuccess();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown(RequestMonitor rm) {
|
||||
unregister();
|
||||
super.shutdown(rm);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BundleContext getBundleContext() {
|
||||
return DsfTestPlugin.getBundleContext();
|
||||
}
|
||||
|
||||
public void getAvailableFormats(IFormattedDataDMContext dmc, DataRequestMonitor<String[]> rm) {
|
||||
rm.setData(AVAILABLE_FORMATS);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
public FormattedValueDMContext getFormattedValueContext(IFormattedDataDMContext dmc, String formatId) {
|
||||
return new FormattedValueDMContext(this, dmc, formatId);
|
||||
}
|
||||
|
||||
public void getFormattedExpressionValue(FormattedValueDMContext dmc, DataRequestMonitor<FormattedValueDMData> rm) {
|
||||
rm.setData(new FormattedValueDMData(dmc.getFormatID()));
|
||||
rm.done();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,372 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.vm;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||
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.service.DsfSession;
|
||||
import org.eclipse.cdt.dsf.service.IDsfService;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
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;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.IVMUpdatePolicy;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.ManualUpdatePolicy;
|
||||
import org.eclipse.cdt.tests.dsf.IViewerUpdatesListenerConstants;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModel.TestElement;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModel.TestElementValidator;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModel.TestEvent;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
|
||||
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.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;
|
||||
|
||||
/**
|
||||
* Tests to verify the operation of FormattedValuesVMUtil
|
||||
* @since 2.2
|
||||
*/
|
||||
abstract public class FormattedValueTests extends TestCase implements IViewerUpdatesListenerConstants, IDebugVMConstants {
|
||||
|
||||
Display fDisplay;
|
||||
Shell fShell;
|
||||
DsfExecutor fDsfExecutor;
|
||||
DsfSession fDsfSession;
|
||||
ITreeModelViewer fViewer;
|
||||
TestModelUpdatesListener fViewerListener;
|
||||
TestModelUpdatesListener fVMListener;
|
||||
FormattedValuesListener fFormattedValuesListener;
|
||||
TestModel fModel;
|
||||
DummyFormattedValueService fDummyValuesService;
|
||||
AbstractVMAdapter fVMAdapter;
|
||||
TestModelCachingVMProvider fVMProvider;
|
||||
|
||||
public FormattedValueTests(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
fDsfExecutor = new DefaultDsfExecutor();
|
||||
fDsfSession = DsfSession.startSession(fDsfExecutor, getClass().getName());
|
||||
|
||||
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);
|
||||
|
||||
fModel = new TestModel(fDsfSession);
|
||||
initializeService(fModel);
|
||||
fDummyValuesService = new DummyFormattedValueService(fDsfSession);
|
||||
initializeService(fDummyValuesService);
|
||||
|
||||
fViewerListener = new TestModelUpdatesListener(fViewer, true, false);
|
||||
|
||||
fModel.setRoot( new TestElement(fModel, "root", new TestElement[0] ) );
|
||||
fModel.setElementChildren(TreePath.EMPTY, makeModelElements(fModel, getTestModelDepth(), "model"));
|
||||
|
||||
fVMAdapter = new AbstractVMAdapter() {
|
||||
@Override
|
||||
protected IVMProvider createViewModelProvider(IPresentationContext context) {
|
||||
return fVMProvider;
|
||||
}
|
||||
};
|
||||
fVMProvider = new TestModelCachingVMProvider(fVMAdapter, fViewer.getPresentationContext(), fDsfSession);
|
||||
|
||||
fVMListener = new TestModelUpdatesListener();
|
||||
fVMProvider.getNode().setVMUpdateListener(fVMListener);
|
||||
fVMProvider.getNode().getLabelProvider().addPropertiesUpdateListener(fViewerListener);
|
||||
|
||||
fFormattedValuesListener = new FormattedValuesListener(fModel);
|
||||
fVMProvider.getNode().setFormattedValuesListener(fFormattedValuesListener);
|
||||
fModel.setTestModelListener(fFormattedValuesListener);
|
||||
|
||||
fShell.open ();
|
||||
}
|
||||
|
||||
private void initializeService(final IDsfService service) throws InterruptedException, ExecutionException {
|
||||
Query<Object> initQuery = new Query<Object>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<Object> rm) {
|
||||
rm.setData(new Object());
|
||||
service.initialize(rm);
|
||||
}
|
||||
};
|
||||
fDsfExecutor.execute(initQuery);
|
||||
initQuery.get();
|
||||
}
|
||||
|
||||
abstract protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell);
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
fVMProvider.getNode().setFormattedValuesListener(null);
|
||||
fModel.setTestModelListener(null);
|
||||
|
||||
fVMProvider.getNode().getLabelProvider().removePropertiesUpdateListener(fViewerListener);
|
||||
fVMProvider.getNode().setVMUpdateListener(null);
|
||||
|
||||
fVMAdapter.dispose();
|
||||
|
||||
fVMListener.dispose();
|
||||
fViewerListener.dispose();
|
||||
|
||||
shutdownService(fDummyValuesService);
|
||||
shutdownService(fModel);
|
||||
fViewer.getPresentationContext().dispose();
|
||||
// Close the shell and exit.
|
||||
fShell.close();
|
||||
while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
|
||||
DsfSession.endSession(fDsfSession);
|
||||
fDsfExecutor.shutdown();
|
||||
}
|
||||
|
||||
private void shutdownService(final IDsfService service) throws InterruptedException, ExecutionException {
|
||||
Query<Object> shutdownQuery = new Query<Object>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<Object> rm) {
|
||||
rm.setData(new Object());
|
||||
service.shutdown(rm);
|
||||
}
|
||||
};
|
||||
fDsfExecutor.execute(shutdownQuery);
|
||||
shutdownQuery.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Depth (size) of the test model to be used in the tests. This number allows
|
||||
* the jface based tests to use a small enough model to fit on the screen, and
|
||||
* for the virtual viewer to exercise the content provider to a greater extent.
|
||||
*/
|
||||
abstract protected int getTestModelDepth();
|
||||
|
||||
public void testValidate() {
|
||||
setInput(IFormattedValues.NATURAL_FORMAT);
|
||||
setFormatAndValidate(IFormattedValues.HEX_FORMAT, false, false, false);
|
||||
}
|
||||
|
||||
public void testChangeFormat() {
|
||||
setInput(IFormattedValues.NATURAL_FORMAT);
|
||||
setFormatAndValidate(IFormattedValues.HEX_FORMAT, false, false, false);
|
||||
setFormatAndValidate(IFormattedValues.NATURAL_FORMAT, false, false, false);
|
||||
}
|
||||
|
||||
public void testChangeFormatManualUpdateMode() {
|
||||
setInput(IFormattedValues.NATURAL_FORMAT);
|
||||
setUpdatePolicy(ManualUpdatePolicy.MANUAL_UPDATE_POLICY_ID);
|
||||
|
||||
// Chenge 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.
|
||||
setFormatAndValidate(IFormattedValues.HEX_FORMAT, true, false, false);
|
||||
|
||||
// Change _back_ to natural format. Values should be retrieved from cache.
|
||||
setFormatAndValidate(IFormattedValues.NATURAL_FORMAT, 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(IFormattedValues.HEX_FORMAT, true, true, false);
|
||||
|
||||
// Change to a decimal, which is not cached, values should come with an error.
|
||||
setFormatAndValidate(IFormattedValues.DECIMAL_FORMAT, true, true, true);
|
||||
|
||||
}
|
||||
|
||||
private void postEventInManualUpdateMode() {
|
||||
// Generate an event which will cause all cache entries to be marked dirty.
|
||||
fViewerListener.reset();
|
||||
fViewerListener.addUpdates(TreePath.EMPTY, fModel.getRootElement(), -1, ALL_UPDATES_COMPLETE | PROPERTY_UPDATES);
|
||||
fVMListener.reset();
|
||||
fFormattedValuesListener.reset();
|
||||
fVMProvider.postEvent(new TestEvent(fModel.getRootElement(), IModelDelta.CONTENT));
|
||||
while (!fViewerListener.isFinished(ALL_UPDATES_COMPLETE | PROPERTY_UPDATES))
|
||||
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
|
||||
Assert.assertTrue(fFormattedValuesListener.getFormattedValuesCompleted().isEmpty());
|
||||
}
|
||||
|
||||
public void testInvalidFormat() {
|
||||
setInput(IFormattedValues.NATURAL_FORMAT);
|
||||
|
||||
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);
|
||||
|
||||
// Set the new number format to the viewer.
|
||||
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) + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial format is NATURAL.
|
||||
*/
|
||||
private void setInput(String formatId) {
|
||||
// Set the new number format to the viewer.
|
||||
fViewer.getPresentationContext().setProperty(PROP_FORMATTED_VALUE_FORMAT_PREFERENCE, formatId);
|
||||
|
||||
fViewer.setAutoExpandLevel(-1);
|
||||
TestElementVMContext rootVMC = fVMProvider.getElementVMContext(fViewer.getPresentationContext(), fModel.getRootElement());
|
||||
|
||||
// Create the listener
|
||||
fViewerListener.reset();
|
||||
fViewerListener.addUpdates(TreePath.EMPTY, rootVMC.getElement(), -1, ALL_UPDATES_COMPLETE | PROPERTY_UPDATES);
|
||||
fVMListener.reset();
|
||||
fVMListener.addUpdates(TreePath.EMPTY, rootVMC.getElement(), -1, ALL_UPDATES_COMPLETE | PROPERTY_UPDATES);
|
||||
fFormattedValuesListener.reset();
|
||||
|
||||
fViewer.setInput(rootVMC);
|
||||
while (!fViewerListener.isFinished(ALL_UPDATES_COMPLETE | PROPERTY_UPDATES) || !fVMListener.isFinished(CONTENT_COMPLETE | PROPERTY_UPDATES))
|
||||
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
|
||||
|
||||
Assert.assertTrue(fFormattedValuesListener.isFinished());
|
||||
}
|
||||
|
||||
private void setUpdatePolicy(String policyId) {
|
||||
IVMUpdatePolicy[] policies = fVMProvider.getAvailableUpdatePolicies();
|
||||
IVMUpdatePolicy newPolicy = null;
|
||||
for (IVMUpdatePolicy policy : policies) {
|
||||
if (policyId.equals(policy.getID())) {
|
||||
newPolicy = policy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newPolicy != null) {
|
||||
fVMProvider.setActiveUpdatePolicy(newPolicy);
|
||||
} else {
|
||||
throw new RuntimeException("Update policy " + policyId + " not available");
|
||||
}
|
||||
fViewerListener.reset();
|
||||
fViewerListener.addUpdates(TreePath.EMPTY, fModel.getRootElement(), -1, ALL_UPDATES_COMPLETE | PROPERTY_UPDATES);
|
||||
fVMListener.setFailOnRedundantUpdates(false);
|
||||
while (!fViewerListener.isFinished(ALL_UPDATES_COMPLETE | PROPERTY_UPDATES))
|
||||
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
|
||||
|
||||
fVMListener.setFailOnRedundantUpdates(true);
|
||||
}
|
||||
|
||||
private void setFormatAndValidate(
|
||||
String formatId,
|
||||
boolean expectContentCached,
|
||||
boolean expectFormattedValuesCached,
|
||||
boolean expectCacheMissError)
|
||||
{
|
||||
fViewerListener.reset();
|
||||
fViewerListener.addUpdates(TreePath.EMPTY, ((TestElementVMContext)fViewer.getInput()).getElement(), -1, ALL_UPDATES_COMPLETE | PROPERTY_UPDATES);
|
||||
|
||||
fVMListener.reset();
|
||||
int vmUpdateFlags = PROPERTY_UPDATES;
|
||||
if (!expectContentCached) {
|
||||
vmUpdateFlags |= ALL_UPDATES_COMPLETE;
|
||||
}
|
||||
fVMListener.addUpdates(TreePath.EMPTY, fModel.getRootElement(), -1, vmUpdateFlags);
|
||||
|
||||
fFormattedValuesListener.reset();
|
||||
if (expectFormattedValuesCached && !expectCacheMissError) {
|
||||
fFormattedValuesListener.setCachedFormats(new String[] {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, "");
|
||||
throw new RuntimeException("Expected validateModel to fail");
|
||||
}
|
||||
catch(AssertionFailedError e) {
|
||||
// expected
|
||||
}
|
||||
} else {
|
||||
validateModel(formatId, "");
|
||||
}
|
||||
|
||||
if (expectCacheMissError) {
|
||||
String formatProperty = FormattedValueVMUtil.getPropertyForFormatId(formatId);
|
||||
|
||||
Assert.assertTrue(fFormattedValuesListener.getFormattedValuesCompleted().isEmpty());
|
||||
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(
|
||||
"Cache contains stale data. Refresh view.",
|
||||
status.getStatus(PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE).getMessage());
|
||||
assertEquals(1, status.getChildren().length);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
Assert.assertTrue(fFormattedValuesListener.isFinished());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void validateModel(final String formatId, final String suffix) {
|
||||
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());
|
||||
|
||||
label = fViewer.getElementLabel(viewerPath, TestModelCachingVMProvider.COLUMN_FORMATTED_VALUE);
|
||||
assertEquals(fModel.getFormattedValueText(modelElement, formatId) + suffix, label.getText());
|
||||
|
||||
label = fViewer.getElementLabel(viewerPath, TestModelCachingVMProvider.COLUMN_DUMMY_VALUE);
|
||||
assertEquals(formatId, label.getText());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private TestElement[] makeModelElements(TestModel model, int depth, String prefix) {
|
||||
TestElement[] elements = new TestElement[depth];
|
||||
for (int i = 0; i < depth; i++) {
|
||||
String name = prefix + "." + i;
|
||||
elements[i] = new TestElement(model, name, makeModelElements(model, i, name));
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.vm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdateListener;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModel.TestElement;
|
||||
import org.junit.Assert;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class FormattedValuesListener implements IFormattedValuesListener, IPropertiesUpdateListener {
|
||||
|
||||
private static final String ANY_FORMAT = "ANY_FORMAT";
|
||||
|
||||
private final TestModel fModel;
|
||||
|
||||
private List<IPropertiesUpdate> fPropertiesUpdates = new ArrayList<IPropertiesUpdate>();
|
||||
private List<List<FormattedValueDMContext>> fFormattedValuesInPending = new ArrayList<List<FormattedValueDMContext>>();
|
||||
private List<FormattedValueDMContext> fFormattedValuesInProgress = new LinkedList<FormattedValueDMContext>();
|
||||
private List<FormattedValueDMContext> fFormattedValuesCompleted = new ArrayList<FormattedValueDMContext>();
|
||||
|
||||
private DsfRunnable fProcessUpdatedFormattedValuesRunnable = null;
|
||||
|
||||
private Set<String> fCachedFormats = new HashSet<String>();
|
||||
|
||||
public FormattedValuesListener(TestModel model) {
|
||||
fModel = model;
|
||||
}
|
||||
|
||||
public void setCachedFormats(String[] cachedFormats) {
|
||||
fCachedFormats.clear();
|
||||
fCachedFormats.addAll(Arrays.asList(cachedFormats));
|
||||
}
|
||||
|
||||
public void propertiesUpdatesStarted(IPropertiesUpdate[] updates) {
|
||||
fPropertiesUpdates.addAll(Arrays.asList(updates));
|
||||
List<FormattedValueDMContext> pending = new ArrayList<FormattedValueDMContext>(updates.length);
|
||||
for (IPropertiesUpdate update : updates) {
|
||||
List<String> formatIds = getRequestedFormatIDs(update);
|
||||
for (String formatId : formatIds) {
|
||||
TestElement te = getPropertyUpdateTestElement(update);
|
||||
pending.add(new FormattedValueDMContext(fModel, te, formatId));
|
||||
}
|
||||
}
|
||||
if (!pending.isEmpty()) {
|
||||
fFormattedValuesInPending.add(pending);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getRequestedFormatIDs(IPropertiesUpdate update) {
|
||||
List<String> formatIds = new ArrayList<String>(1);
|
||||
for (String property : update.getProperties()) {
|
||||
if (property.equals(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE)) {
|
||||
formatIds.add(ANY_FORMAT);
|
||||
}
|
||||
if (property.startsWith(IDebugVMConstants.PROP_FORMATTED_VALUE_BASE)) {
|
||||
formatIds.add(FormattedValueVMUtil.getFormatFromProperty(property, null));
|
||||
}
|
||||
}
|
||||
return formatIds;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
reset(new String[0]);
|
||||
}
|
||||
|
||||
public void reset(String[] cachedFormats) {
|
||||
fPropertiesUpdates.clear();
|
||||
fFormattedValuesInPending.clear();
|
||||
fFormattedValuesInProgress.clear();
|
||||
fFormattedValuesCompleted.clear();
|
||||
setCachedFormats(cachedFormats);
|
||||
}
|
||||
|
||||
public List<FormattedValueDMContext> getFormattedValuesCompleted() {
|
||||
return fFormattedValuesCompleted;
|
||||
}
|
||||
|
||||
public List<IPropertiesUpdate> getPropertiesUpdates() {
|
||||
return fPropertiesUpdates;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
if ( !fFormattedValuesInProgress.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fFormattedValuesInPending.isEmpty() && fCachedFormats.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (List<FormattedValueDMContext> pendingList : fFormattedValuesInPending) {
|
||||
for (FormattedValueDMContext pending : pendingList) {
|
||||
String pendingFormat = pending.getFormatID();
|
||||
if (!pendingFormat.equals(ANY_FORMAT) && !fCachedFormats.contains(pendingFormat)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void propertiesUpdateCompleted(IPropertiesUpdate update) {}
|
||||
|
||||
public void formattedValueUpdated(FormattedValueDMContext formattedValueDmc) {
|
||||
Assert.assertFalse("Expected values with formats " + fCachedFormats + " to be cached.",
|
||||
fCachedFormats.contains(formattedValueDmc.getFormatID()));
|
||||
|
||||
if (fProcessUpdatedFormattedValuesRunnable == null) {
|
||||
fProcessUpdatedFormattedValuesRunnable = new DsfRunnable() {
|
||||
public void run() {
|
||||
fProcessUpdatedFormattedValuesRunnable = null;
|
||||
processFormattedValuesInProgress();
|
||||
}
|
||||
};
|
||||
fModel.getExecutor().execute(fProcessUpdatedFormattedValuesRunnable);
|
||||
}
|
||||
fFormattedValuesInProgress.add(formattedValueDmc);
|
||||
}
|
||||
|
||||
private void processFormattedValuesInProgress() {
|
||||
while (!fFormattedValuesInProgress.isEmpty()) {
|
||||
List<FormattedValueDMContext> pendingList = findPendingList(fFormattedValuesInProgress.get(0));
|
||||
|
||||
for (FormattedValueDMContext pending : pendingList) {
|
||||
int progressIdx = indexOfFormattedValueDMContext(fFormattedValuesInProgress, pending);
|
||||
|
||||
if (progressIdx != -1) {
|
||||
// The pending DMC may contain the ANY_FORMAT format ID.
|
||||
// The progress DMC must contain the exact format retrieved.
|
||||
// To have a more accurate record, add the progress DMC to
|
||||
// the completed updates list.
|
||||
FormattedValueDMContext progress = fFormattedValuesInProgress.remove(progressIdx);
|
||||
fFormattedValuesCompleted.add(progress);
|
||||
} else {
|
||||
Assert.fail("Pending Updates not processed in bulk \n " + pendingList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<FormattedValueDMContext> findPendingList(FormattedValueDMContext dmc) {
|
||||
for (Iterator<List<FormattedValueDMContext>> itr = fFormattedValuesInPending.iterator(); itr.hasNext();) {
|
||||
List<FormattedValueDMContext> pendingList = itr.next();
|
||||
int pendingIdx = indexOfFormattedValueDMContext(pendingList, dmc);
|
||||
if (pendingIdx != -1) {
|
||||
itr.remove();
|
||||
return pendingList;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Pending update not found for element: " + dmc);
|
||||
}
|
||||
|
||||
private int indexOfFormattedValueDMContext(List<FormattedValueDMContext> list, FormattedValueDMContext dmc) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (dmc.getParentValueDMContext().equals(list.get(i).getParentValueDMContext())) {
|
||||
if ( ANY_FORMAT.equals(dmc.getFormatID()) ||
|
||||
ANY_FORMAT.equals(list.get(i).getFormatID()) ||
|
||||
dmc.getFormatID().equals(list.get(i).getFormatID()) )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private TestElement getPropertyUpdateTestElement(IPropertiesUpdate update) {
|
||||
Object element = update.getElement();
|
||||
if (element instanceof TestElement) {
|
||||
return (TestElement)element;
|
||||
} else if (element instanceof TestElementVMContext) {
|
||||
return ((TestElementVMContext)element).getElement();
|
||||
}
|
||||
throw new RuntimeException("Invalid element in properties update: " + update.getElement());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.vm;
|
||||
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
*/
|
||||
public interface IFormattedValuesListener {
|
||||
|
||||
public void formattedValueUpdated(FormattedValueDMContext formattedValueDmc);
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.vm;
|
||||
|
||||
/**
|
||||
* Convenience interface with constants used by the test model update listener.
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public interface ITestModelUpdatesListenerConstants {
|
||||
|
||||
public static final int LABEL_UPDATES_COMPLETE = 0X0001;
|
||||
public static final int CONTENT_UPDATES_COMPLETE = 0X0002;
|
||||
public static final int LABEL_UPDATES = 0X0004;
|
||||
public static final int HAS_CHILDREN_UPDATES = 0X0008;
|
||||
public static final int CHILDREN_COUNT_UPDATES = 0X0010;
|
||||
public static final int CHILDREN_UPDATES = 0X0020;
|
||||
public static final int MODEL_CHANGED_COMPLETE = 0X0040;
|
||||
public static final int MODEL_PROXIES_INSTALLED = 0X0080;
|
||||
public static final int STATE_SAVE_COMPLETE = 0X0100;
|
||||
public static final int STATE_RESTORE_COMPLETE = 0X0200;
|
||||
public static final int STATE_UPDATES = 0X0400;
|
||||
|
||||
public static final int VIEWER_UPDATES_RUNNING = 0X0800;
|
||||
public static final int LABEL_UPDATES_RUNNING = 0X1000;
|
||||
|
||||
public static final int LABEL_COMPLETE = LABEL_UPDATES_COMPLETE | LABEL_UPDATES;
|
||||
public static final int CONTENT_COMPLETE =
|
||||
CONTENT_UPDATES_COMPLETE | HAS_CHILDREN_UPDATES | CHILDREN_COUNT_UPDATES | CHILDREN_UPDATES;
|
||||
|
||||
public static final int ALL_UPDATES_COMPLETE = LABEL_COMPLETE | CONTENT_COMPLETE | LABEL_UPDATES_RUNNING | VIEWER_UPDATES_RUNNING;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.vm;
|
||||
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
*/
|
||||
public class JFaceViewerFormattedValueTests extends FormattedValueTests {
|
||||
|
||||
public JFaceViewerFormattedValueTests(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell) {
|
||||
return new TreeModelViewer(fShell, SWT.VIRTUAL, new PresentationContext("TestViewer"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTestModelDepth() {
|
||||
return 5;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,10 @@ package org.eclipse.cdt.tests.dsf.vm;
|
|||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.tests.dsf.IViewerUpdatesListenerConstants;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModel.TestElement;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer;
|
||||
|
@ -28,9 +32,11 @@ import org.eclipse.ui.PlatformUI;
|
|||
/**
|
||||
* Tests to measure the performance of the viewer updates.
|
||||
*/
|
||||
abstract public class PerformanceTests extends TestCase implements ITestModelUpdatesListenerConstants {
|
||||
abstract public class PerformanceTests extends TestCase implements IViewerUpdatesListenerConstants {
|
||||
Display fDisplay;
|
||||
Shell fShell;
|
||||
DsfExecutor fDsfExecutor;
|
||||
DsfSession fDsfSession;
|
||||
ITreeModelViewer fViewer;
|
||||
TestModelUpdatesListener fListener;
|
||||
TestModel fModel;
|
||||
|
@ -46,6 +52,9 @@ abstract public class PerformanceTests extends TestCase implements ITestModelUpd
|
|||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
fDsfExecutor = new DefaultDsfExecutor();
|
||||
fDsfSession = DsfSession.startSession(fDsfExecutor, getClass().getName());
|
||||
|
||||
fDisplay = PlatformUI.getWorkbench().getDisplay();
|
||||
fShell = new Shell(fDisplay/*, SWT.ON_TOP | SWT.SHELL_TRIM*/);
|
||||
fShell.setMaximized(true);
|
||||
|
@ -55,7 +64,7 @@ abstract public class PerformanceTests extends TestCase implements ITestModelUpd
|
|||
|
||||
fListener = new TestModelUpdatesListener(fViewer, false, false);
|
||||
|
||||
fModel = new TestModel();
|
||||
fModel = new TestModel(fDsfSession);
|
||||
fModel.setRoot( new TestElement(fModel, "root", new TestElement[0] ) );
|
||||
fModel.setElementChildren(TreePath.EMPTY, makeModelElements(fModel, getTestModelDepth(), "model"));
|
||||
fVMAdapter = new TestModelVMAdapter();
|
||||
|
@ -78,6 +87,8 @@ abstract public class PerformanceTests extends TestCase implements ITestModelUpd
|
|||
// Close the shell and exit.
|
||||
fShell.close();
|
||||
while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
|
||||
DsfSession.endSession(fDsfSession);
|
||||
fDsfExecutor.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -166,32 +177,31 @@ abstract public class PerformanceTests extends TestCase implements ITestModelUpd
|
|||
}
|
||||
|
||||
public void _x_testRefreshStructReplaceElements() {
|
||||
TestModel model = new TestModel();
|
||||
model.setRoot( new TestElement(model, "root", new TestElement[0] ) );
|
||||
model.setElementChildren(TreePath.EMPTY, makeModelElements(model, getTestModelDepth(), "model"));
|
||||
fModel.setRoot( new TestElement(fModel, "root", new TestElement[0] ) );
|
||||
fModel.setElementChildren(TreePath.EMPTY, makeModelElements(fModel, getTestModelDepth(), "model"));
|
||||
|
||||
fViewer.setAutoExpandLevel(-1);
|
||||
|
||||
// Create the listener
|
||||
fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false);
|
||||
fListener.reset(TreePath.EMPTY, fModel.getRootElement(), -1, true, false);
|
||||
|
||||
// Set the input into the view and update the view.
|
||||
fViewer.setInput(model.getRootElement());
|
||||
fViewer.setInput(fModel.getRootElement());
|
||||
while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
|
||||
model.validateData(fViewer, TreePath.EMPTY);
|
||||
fModel.validateData(fViewer, TreePath.EMPTY);
|
||||
|
||||
Performance perf = Performance.getDefault();
|
||||
PerformanceMeter meter = perf.createPerformanceMeter(perf.getDefaultScenarioId(this));
|
||||
try {
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
// Update the model
|
||||
model.setElementChildren(TreePath.EMPTY, makeModelElements(model, getTestModelDepth(), "pass " + i));
|
||||
fModel.setElementChildren(TreePath.EMPTY, makeModelElements(fModel, getTestModelDepth(), "pass " + i));
|
||||
|
||||
TestElement element = model.getRootElement();
|
||||
TestElement element = fModel.getRootElement();
|
||||
fListener.reset(TreePath.EMPTY, element, -1, false, false);
|
||||
|
||||
meter.start();
|
||||
model.postDelta(new ModelDelta(element, IModelDelta.CONTENT));
|
||||
//fModel.postDelta(new ModelDelta(element, IModelDelta.CONTENT));
|
||||
while (!fListener.isFinished(ALL_UPDATES_COMPLETE | MODEL_CHANGED_COMPLETE))
|
||||
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
|
||||
//model.validateData(fViewer, TreePath.EMPTY);
|
||||
|
|
|
@ -10,17 +10,20 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.vm;
|
||||
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMContext;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModel.TestElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class TestElementVMContext extends AbstractVMContext {
|
||||
public class TestElementVMContext extends AbstractVMContext implements IDMVMContext {
|
||||
|
||||
final private TestElement fElement;
|
||||
|
||||
public TestElementVMContext(TestModelVMNode node, TestElement element) {
|
||||
public TestElementVMContext(IVMNode node, TestElement element) {
|
||||
super(node);
|
||||
fElement = element;
|
||||
}
|
||||
|
@ -38,5 +41,13 @@ public class TestElementVMContext extends AbstractVMContext {
|
|||
public TestElement getElement() {
|
||||
return fElement;
|
||||
}
|
||||
|
||||
public IDMContext getDMContext() {
|
||||
return getElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getDMContext().toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,38 +11,45 @@
|
|||
package org.eclipse.cdt.tests.dsf.vm;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.core.runtime.PlatformObject;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
|
||||
import org.eclipse.cdt.dsf.service.AbstractDsfService;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.tests.dsf.DsfTestPlugin;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelCheckProviderTarget;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ICheckUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
import org.eclipse.jface.viewers.Viewer;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
* Test model for the use in unit tests. This test model contains a set of
|
||||
* elements in a tree structure. It contains utility methods for modifying the
|
||||
* model and for verifying that the viewer content matches the model.
|
||||
*
|
||||
* @since 3.6
|
||||
* @since 2.2
|
||||
*/
|
||||
public class TestModel {
|
||||
public class TestModel extends AbstractDsfService implements IFormattedValues {
|
||||
|
||||
public static class TestElement extends PlatformObject {
|
||||
public interface TestElementValidator {
|
||||
public void validate(TestElement modelElement, TestElement viewerElement, TreePath viewerPath);
|
||||
}
|
||||
|
||||
public static class TestElement extends AbstractDMContext implements IFormattedDataDMContext {
|
||||
private final TestModel fModel;
|
||||
private final String fID;
|
||||
TestElement[] fChildren;
|
||||
|
@ -51,18 +58,37 @@ public class TestModel {
|
|||
boolean fChecked;
|
||||
boolean fGrayed;
|
||||
|
||||
private TestElement[] fParents = new TestElement[1];
|
||||
|
||||
public TestElement(TestModel model, String text, TestElement[] children) {
|
||||
this (model, text, false, false, children);
|
||||
}
|
||||
|
||||
public TestElement(TestModel model, String text, boolean checked, boolean grayed, TestElement[] children) {
|
||||
super(model, EMPTY_PARENTS_ARRAY);
|
||||
fModel = model;
|
||||
fID = text;
|
||||
fChildren = children;
|
||||
for (TestElement child : children) {
|
||||
child.setParent(this);
|
||||
}
|
||||
fChecked = checked;
|
||||
fGrayed = grayed;
|
||||
}
|
||||
|
||||
public void setParent(TestElement parent) {
|
||||
fParents[0] = parent;
|
||||
}
|
||||
|
||||
public TestElement getParent() {
|
||||
return fParents[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDMContext[] getParents() {
|
||||
return fParents;
|
||||
}
|
||||
|
||||
public TestModel getModel() {
|
||||
return fModel;
|
||||
}
|
||||
|
@ -129,39 +155,72 @@ public class TestModel {
|
|||
}
|
||||
}
|
||||
|
||||
private class ModelProxy extends AbstractModelProxy {
|
||||
@Override
|
||||
public void installed(Viewer viewer) {
|
||||
super.installed(viewer);
|
||||
ModelDelta rootDelta = TestModel.this.getBaseDelta(new ModelDelta(fInput, IModelDelta.NO_CHANGE));
|
||||
installSubModelProxies(fRootPath, rootDelta);
|
||||
fireModelChanged(rootDelta);
|
||||
public static final class TestEvent {
|
||||
private final TestElement fElement;
|
||||
private final int fType;
|
||||
|
||||
public TestEvent(TestElement element, int type) {
|
||||
fElement = element;
|
||||
fType = type;
|
||||
}
|
||||
|
||||
private void installSubModelProxies(TreePath path, ModelDelta delta) {
|
||||
TestElement element = getElement(path);
|
||||
if (element.fModel != TestModel.this) {
|
||||
// Found an element from a different model. Install its proxy and return.
|
||||
delta.setFlags(delta.getFlags() | IModelDelta.INSTALL);
|
||||
} else {
|
||||
TestElement[] children = element.getChildren();
|
||||
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
installSubModelProxies(path.createChildPath(children[i]), delta.addNode(children[i], IModelDelta.NO_CHANGE));
|
||||
}
|
||||
}
|
||||
public TestElement getElement() {
|
||||
return fElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IModelDelta#getFlags()
|
||||
*/
|
||||
public int getType() {
|
||||
return fType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final IFormattedValuesListener NULL_LISTENER = new IFormattedValuesListener() {
|
||||
public void formattedValueUpdated(FormattedValueDMContext formattedValueDmc) {}
|
||||
};
|
||||
|
||||
private TestElement fRoot;
|
||||
private Object fInput = null;
|
||||
private TreePath fRootPath = TreePath.EMPTY;
|
||||
private ModelProxy fModelProxy;
|
||||
private IFormattedValuesListener fListener = NULL_LISTENER;
|
||||
|
||||
/**
|
||||
* Constructor private. Use static factory methods instead.
|
||||
*/
|
||||
public TestModel() {}
|
||||
public TestModel(DsfSession session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BundleContext getBundleContext() {
|
||||
return DsfTestPlugin.getBundleContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(RequestMonitor rm) {
|
||||
super.initialize(new RequestMonitor(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
register(new String[0], new Hashtable<String, String>() );
|
||||
super.handleSuccess();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown(RequestMonitor rm) {
|
||||
unregister();
|
||||
super.shutdown(rm);
|
||||
}
|
||||
|
||||
public void setTestModelListener(IFormattedValuesListener listener) {
|
||||
if (listener != null) {
|
||||
fListener = listener;
|
||||
} else {
|
||||
fListener = NULL_LISTENER;
|
||||
}
|
||||
}
|
||||
|
||||
public TestElement getRootElement() {
|
||||
return fRoot;
|
||||
|
@ -197,48 +256,6 @@ public class TestModel {
|
|||
return depth;
|
||||
}
|
||||
|
||||
public void update(IHasChildrenUpdate[] updates) {
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
TestElement element = (TestElement)updates[i].getElement();
|
||||
updates[i].setHasChilren(element.getChildren().length > 0);
|
||||
updates[i].done();
|
||||
}
|
||||
}
|
||||
|
||||
public void update(IChildrenCountUpdate[] updates) {
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
TestElement element = (TestElement)updates[i].getElement();
|
||||
updates[i].setChildCount(element.getChildren().length);
|
||||
updates[i].done();
|
||||
}
|
||||
}
|
||||
|
||||
public void update(IChildrenUpdate[] updates) {
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
TestElement element = (TestElement)updates[i].getElement();
|
||||
int endOffset = updates[i].getOffset() + updates[i].getLength();
|
||||
for (int j = updates[i].getOffset(); j < endOffset; j++) {
|
||||
if (j < element.getChildren().length) {
|
||||
updates[i].setChild(element.getChildren()[j], j);
|
||||
}
|
||||
}
|
||||
updates[i].done();
|
||||
}
|
||||
}
|
||||
|
||||
public void update(ILabelUpdate[] updates) {
|
||||
for (int i = 0; i < updates.length; i++) {
|
||||
TestElement element = (TestElement)updates[i].getElement();
|
||||
updates[i].setLabel(element.fID, 0);
|
||||
if (updates[i] instanceof ICheckUpdate &&
|
||||
Boolean.TRUE.equals(updates[i].getPresentationContext().getProperty(ICheckUpdate.PROP_CHECK)))
|
||||
{
|
||||
((ICheckUpdate)updates[i]).setChecked(element.getChecked(), element.getGrayed());
|
||||
}
|
||||
updates[i].done();
|
||||
}
|
||||
}
|
||||
|
||||
public final static String ELEMENT_MEMENTO_ID = "id";
|
||||
|
||||
public void compareElements(IElementCompareRequest[] updates) {
|
||||
|
@ -259,24 +276,12 @@ public class TestModel {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void elementChecked(IPresentationContext context, Object viewerInput, TreePath path, boolean checked) {
|
||||
TestElement element = getElement(path);
|
||||
Assert.assertFalse(element.getGrayed());
|
||||
element.setChecked(checked, false);
|
||||
}
|
||||
|
||||
public IModelProxy createTreeModelProxy(Object input, TreePath path, IPresentationContext context) {
|
||||
fModelProxy = new ModelProxy();
|
||||
fInput = input;
|
||||
fRootPath = path;
|
||||
return fModelProxy;
|
||||
}
|
||||
|
||||
public IModelProxy getModelProxy() {
|
||||
return fModelProxy;
|
||||
}
|
||||
|
||||
public TestElement getElement(TreePath path) {
|
||||
if (path.getSegmentCount() == 0) {
|
||||
return getRootElement();
|
||||
|
@ -289,6 +294,14 @@ public class TestModel {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public TestElement getElementFromViewer(ITreeModelContentProviderTarget viewer, TreePath parentPath, int index) {
|
||||
Object element = viewer.getChildElement(parentPath, index);
|
||||
if (element instanceof TestElementVMContext) {
|
||||
return ((TestElementVMContext)element).getElement();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setAllExpanded() {
|
||||
doSetExpanded(fRoot);
|
||||
|
@ -314,10 +327,16 @@ public class TestModel {
|
|||
|
||||
public void validateData(ITreeModelViewer viewer, TreePath path) {
|
||||
|
||||
validateData(viewer, path, false);
|
||||
validateData(viewer, path, null, false);
|
||||
}
|
||||
|
||||
public void validateData(ITreeModelViewer _viewer, TreePath path, boolean expandedElementsOnly) {
|
||||
public void validateData(ITreeModelViewer viewer, TreePath path, TestElementValidator validator) {
|
||||
|
||||
validateData(viewer, path, validator, false);
|
||||
}
|
||||
|
||||
public void validateData(ITreeModelViewer _viewer, TreePath path, TestElementValidator validator, boolean expandedElementsOnly) {
|
||||
|
||||
ITreeModelContentProviderTarget viewer = (ITreeModelContentProviderTarget)_viewer;
|
||||
TestElement element = getElement(path);
|
||||
if ( Boolean.TRUE.equals(_viewer.getPresentationContext().getProperty(ICheckUpdate.PROP_CHECK)) ) {
|
||||
|
@ -331,8 +350,17 @@ public class TestModel {
|
|||
Assert.assertEquals(children.length, viewer.getChildCount(path));
|
||||
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
Assert.assertEquals(children[i], viewer.getChildElement(path, i));
|
||||
validateData(viewer, path.createChildPath(children[i]), expandedElementsOnly);
|
||||
Object viewerObject = viewer.getChildElement(path, i);
|
||||
if (viewerObject instanceof TestElementVMContext) {
|
||||
TreePath childPath = path.createChildPath(viewerObject);
|
||||
TestElement viewerElement = ((TestElementVMContext)viewerObject).getElement();
|
||||
Assert.assertEquals(children[i], viewerElement);
|
||||
if (validator != null) {
|
||||
validator.validate(children[i], viewerElement, childPath);
|
||||
}
|
||||
|
||||
validateData(viewer, childPath, validator, expandedElementsOnly);
|
||||
}
|
||||
}
|
||||
} else if (!viewer.getExpandedState(path)) {
|
||||
// If element not expanded, verify the plus sign.
|
||||
|
@ -344,10 +372,6 @@ public class TestModel {
|
|||
fRoot = root;
|
||||
}
|
||||
|
||||
public void postDelta(IModelDelta delta) {
|
||||
fModelProxy.fireModelChanged(delta);
|
||||
}
|
||||
|
||||
/** Create or retrieve delta for given path
|
||||
* @param combine if then new deltas for the given path are created. If false existing ones are reused.
|
||||
*/
|
||||
|
@ -560,6 +584,27 @@ public class TestModel {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void getAvailableFormats(IFormattedDataDMContext dmc, DataRequestMonitor<String[]> rm) {
|
||||
rm.setData(new String[] { HEX_FORMAT, DECIMAL_FORMAT, OCTAL_FORMAT, BINARY_FORMAT, NATURAL_FORMAT });
|
||||
rm.done();
|
||||
}
|
||||
|
||||
public void getFormattedExpressionValue(FormattedValueDMContext dmc, DataRequestMonitor<FormattedValueDMData> rm) {
|
||||
TestElement te = DMContexts.getAncestorOfType(dmc, TestElement.class);
|
||||
rm.setData(new FormattedValueDMData( getFormattedValueText(te, dmc.getFormatID())));
|
||||
rm.done();
|
||||
fListener.formattedValueUpdated(dmc);
|
||||
}
|
||||
|
||||
public FormattedValueDMContext getFormattedValueContext(IFormattedDataDMContext dmc, String formatId) {
|
||||
// Creates a context that can be used to retrieve a formatted value.
|
||||
return new FormattedValueDMContext(this, dmc, formatId);
|
||||
}
|
||||
|
||||
public String getFormattedValueText(TestElement te, String formatId) {
|
||||
return te.getLabel() + " (" + formatId + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getElementString(fRoot, "");
|
||||
|
@ -577,8 +622,7 @@ public class TestModel {
|
|||
return builder.toString();
|
||||
}
|
||||
|
||||
public static TestModel simpleSingleLevel() {
|
||||
TestModel model = new TestModel();
|
||||
public static void simpleSingleLevel(TestModel model) {
|
||||
model.setRoot( new TestElement(model, "root", new TestElement[] {
|
||||
new TestElement(model, "1", true, true, new TestElement[0]),
|
||||
new TestElement(model, "2", true, false, new TestElement[0]),
|
||||
|
@ -587,11 +631,9 @@ public class TestModel {
|
|||
new TestElement(model, "5", new TestElement[0]),
|
||||
new TestElement(model, "6", new TestElement[0])
|
||||
}) );
|
||||
return model;
|
||||
}
|
||||
|
||||
public static TestModel simpleMultiLevel() {
|
||||
TestModel model = new TestModel();
|
||||
public static void simpleMultiLevel(TestModel model) {
|
||||
model.setRoot( new TestElement(model, "root", new TestElement[] {
|
||||
new TestElement(model, "1", new TestElement[0]),
|
||||
new TestElement(model, "2", true, false, new TestElement[] {
|
||||
|
@ -617,53 +659,6 @@ public class TestModel {
|
|||
}),
|
||||
})
|
||||
}) );
|
||||
return model;
|
||||
}
|
||||
|
||||
public static TestModel compositeMultiLevel() {
|
||||
TestModel m2 = new TestModel();
|
||||
m2.setRoot( new TestElement(m2, "m2.root", new TestElement[] {
|
||||
new TestElement(m2, "m2.1", new TestElement[0]),
|
||||
new TestElement(m2, "m2.2", true, false, new TestElement[] {
|
||||
new TestElement(m2, "m2.2.1", true, true, new TestElement[0]),
|
||||
new TestElement(m2, "m2.2.2", false, true, new TestElement[0]),
|
||||
new TestElement(m2, "m2.2.3", true, false, new TestElement[0]),
|
||||
}),
|
||||
}) );
|
||||
|
||||
TestModel m3 = new TestModel();
|
||||
m3.setRoot( new TestElement(m3, "m3.root", new TestElement[] {
|
||||
new TestElement(m3, "m3.1", new TestElement[0]),
|
||||
new TestElement(m3, "m3.2", true, false, new TestElement[] {
|
||||
new TestElement(m3, "m3.2.1", true, true, new TestElement[0]),
|
||||
new TestElement(m3, "m3.2.2", false, true, new TestElement[0]),
|
||||
new TestElement(m3, "m3.2.3", true, false, new TestElement[0]),
|
||||
}),
|
||||
}) );
|
||||
|
||||
TestModel m4 = new TestModel();
|
||||
m4.setRoot( new TestElement(m4, "m4.root", new TestElement[] {
|
||||
new TestElement(m4, "m4.1", new TestElement[0]),
|
||||
new TestElement(m4, "m4.2", true, false, new TestElement[] {
|
||||
new TestElement(m4, "m4.2.1", true, true, new TestElement[0]),
|
||||
new TestElement(m4, "m4.2.2", false, true, new TestElement[0]),
|
||||
new TestElement(m4, "m4.2.3", true, false, new TestElement[0]),
|
||||
}),
|
||||
}) );
|
||||
|
||||
TestModel m1 = new TestModel();
|
||||
m1.setRoot( new TestElement(m1, "m1.root", new TestElement[] {
|
||||
new TestElement(m1, "m1.1", new TestElement[0]),
|
||||
new TestElement(m1, "m1.2", true, false, new TestElement[] {
|
||||
m2.fRoot,
|
||||
m3.fRoot,
|
||||
m4.fRoot,
|
||||
}),
|
||||
}) );
|
||||
|
||||
|
||||
return m1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.vm;
|
||||
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.update.BreakpointHitUpdatePolicy;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.update.DebugManualUpdatePolicy;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.AutomaticUpdatePolicy;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.update.IVMUpdatePolicy;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModel.TestElement;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
import org.eclipse.jface.resource.ImageDescriptor;
|
||||
import org.eclipse.jface.util.IPropertyChangeListener;
|
||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
*/
|
||||
public class TestModelCachingVMProvider extends AbstractDMVMProvider {
|
||||
|
||||
public static final String COLUMN_ID = "COLUMN_ID";
|
||||
public static final String COLUMN_FORMATTED_VALUE = "COLUMN_FORMATTED_VALUE";
|
||||
public static final String COLUMN_DUMMY_VALUE = "COLUMN_DUMMY_VALUE";
|
||||
private static final String[] COLUMNS = new String[] { COLUMN_ID, COLUMN_FORMATTED_VALUE, COLUMN_DUMMY_VALUE };
|
||||
|
||||
private IPropertyChangeListener fPresentationContextListener = new IPropertyChangeListener() {
|
||||
public void propertyChange(PropertyChangeEvent event) {
|
||||
handleEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
private static IColumnPresentation COLUMN_PRESENTATION = new IColumnPresentation() {
|
||||
public void init(IPresentationContext context) {}
|
||||
public void dispose() {};
|
||||
|
||||
public String[] getAvailableColumns() {
|
||||
return COLUMNS;
|
||||
};
|
||||
|
||||
public String getHeader(String id) {
|
||||
return id;
|
||||
};
|
||||
|
||||
public String getId() { return "ID"; }
|
||||
|
||||
public ImageDescriptor getImageDescriptor(String id) {
|
||||
return null;
|
||||
}
|
||||
public String[] getInitialColumns() {
|
||||
return COLUMNS;
|
||||
}
|
||||
public boolean isOptional() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
public TestModelCachingVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
|
||||
super(adapter, context, session);
|
||||
|
||||
setRootNode(new TestModelDMVMNode(this, session));
|
||||
addChildNodes(getRootVMNode(), new IVMNode[] { getRootVMNode() });
|
||||
|
||||
context.addPropertyChangeListener(fPresentationContextListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IVMUpdatePolicy[] createUpdateModes() {
|
||||
return new IVMUpdatePolicy[] {
|
||||
new AutomaticUpdatePolicy(),
|
||||
new DebugManualUpdatePolicy(new String[] { TestModelDMVMNode.PROP_PREFIX_DUMMY }),
|
||||
new BreakpointHitUpdatePolicy() };
|
||||
}
|
||||
|
||||
public TestModelDMVMNode getNode() {
|
||||
return (TestModelDMVMNode)getRootVMNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
getPresentationContext().removePropertyChangeListener(fPresentationContextListener);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public void postEvent(Object event) {
|
||||
super.handleEvent(event);
|
||||
}
|
||||
|
||||
public TestElementVMContext getElementVMContext(IPresentationContext context, TestElement element) {
|
||||
return ((TestModelDMVMNode)getRootVMNode()).createVMContext(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnPresentationId(IPresentationContext context, Object element) {
|
||||
return COLUMN_PRESENTATION.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
|
||||
return COLUMN_PRESENTATION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008, 2010 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.vm;
|
||||
|
||||
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.service.DsfSession;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider;
|
||||
import org.eclipse.cdt.tests.dsf.ViewerUpdatesListener;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModel.TestElement;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModel.TestEvent;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
*/
|
||||
public class TestModelDMVMNode extends AbstractDMVMNode implements IRootVMNode, IElementLabelProvider, IElementPropertiesProvider {
|
||||
|
||||
final public static String PROP_PREFIX_DUMMY = "dummy.";
|
||||
|
||||
final private static String PROP_TEST_ELEMENT_LABEL = "PROP_TEST_ELEMENT_LABEL";
|
||||
|
||||
private ViewerUpdatesListener fViewerUpdateListener = NULL_VIEWER_UPDATE_LISTENER;
|
||||
private FormattedValuesListener fFormattedValuesListener;
|
||||
|
||||
private static final ViewerUpdatesListener NULL_VIEWER_UPDATE_LISTENER = new ViewerUpdatesListener();
|
||||
|
||||
final private static PropertiesBasedLabelProvider fLabelProvider = new PropertiesBasedLabelProvider();
|
||||
{
|
||||
LabelColumnInfo idLabelInfo = new LabelColumnInfo(new LabelAttribute[] {
|
||||
new LabelText("{0}", new String[] { PROP_TEST_ELEMENT_LABEL })
|
||||
});
|
||||
|
||||
fLabelProvider.setColumnInfo(PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS, idLabelInfo);
|
||||
fLabelProvider.setColumnInfo(TestModelCachingVMProvider.COLUMN_ID, idLabelInfo);
|
||||
fLabelProvider.setColumnInfo(
|
||||
TestModelCachingVMProvider.COLUMN_FORMATTED_VALUE,
|
||||
new LabelColumnInfo(new LabelAttribute[] {
|
||||
new FormattedValueLabelText()
|
||||
}));
|
||||
fLabelProvider.setColumnInfo(
|
||||
TestModelCachingVMProvider.COLUMN_DUMMY_VALUE,
|
||||
new LabelColumnInfo(new LabelAttribute[] {
|
||||
new FormattedValueLabelText(PROP_PREFIX_DUMMY)
|
||||
}));
|
||||
}
|
||||
|
||||
private final FormattedValueRetriever fFormattedValueRetriever;
|
||||
private final FormattedValueRetriever fDummyFormattedValueRetriever;
|
||||
|
||||
public TestModelDMVMNode(AbstractDMVMProvider provider, DsfSession session) {
|
||||
super(provider, session, TestElement.class);
|
||||
fFormattedValueRetriever = new FormattedValueRetriever(this, getSession(), TestModel.class, TestElement.class);
|
||||
fDummyFormattedValueRetriever = new FormattedValueRetriever(this, getSession(), DummyFormattedValueService.class, TestElement.class, PROP_PREFIX_DUMMY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
fFormattedValueRetriever.dispose();
|
||||
fDummyFormattedValueRetriever.dispose();
|
||||
}
|
||||
|
||||
public void setVMUpdateListener(ViewerUpdatesListener viewerUpdateListener) {
|
||||
if (viewerUpdateListener != null) {
|
||||
fViewerUpdateListener = viewerUpdateListener;
|
||||
} else {
|
||||
fViewerUpdateListener = NULL_VIEWER_UPDATE_LISTENER;
|
||||
}
|
||||
}
|
||||
|
||||
public void setFormattedValuesListener(FormattedValuesListener formattedValuesListener) {
|
||||
fFormattedValuesListener = formattedValuesListener;
|
||||
}
|
||||
|
||||
public PropertiesBasedLabelProvider getLabelProvider() {
|
||||
return fLabelProvider;
|
||||
}
|
||||
|
||||
public void update(final ILabelUpdate[] updates) {
|
||||
fLabelProvider.update(updates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(IHasChildrenUpdate[] updates) {
|
||||
fViewerUpdateListener.viewerUpdatesBegin();
|
||||
for (IHasChildrenUpdate update : updates) {
|
||||
fViewerUpdateListener.updateStarted(update);
|
||||
if (update.getElement() instanceof TestElementVMContext) {
|
||||
TestElement element = ((TestElementVMContext)update.getElement()).getElement();
|
||||
update.setHasChilren(element.getChildren().length != 0);
|
||||
}
|
||||
update.done();
|
||||
fViewerUpdateListener.updateComplete(update);
|
||||
}
|
||||
fViewerUpdateListener.viewerUpdatesComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(IChildrenCountUpdate[] updates) {
|
||||
fViewerUpdateListener.viewerUpdatesBegin();
|
||||
for (IChildrenCountUpdate update : updates) {
|
||||
fViewerUpdateListener.updateStarted(update);
|
||||
if (update.getElement() instanceof TestElementVMContext) {
|
||||
TestElement element = ((TestElementVMContext)update.getElement()).getElement();
|
||||
update.setChildCount(element.getChildren().length);
|
||||
}
|
||||
update.done();
|
||||
fViewerUpdateListener.updateComplete(update);
|
||||
}
|
||||
fViewerUpdateListener.viewerUpdatesComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(IChildrenUpdate[] updates) {
|
||||
fViewerUpdateListener.viewerUpdatesBegin();
|
||||
for (IChildrenUpdate update : updates) {
|
||||
fViewerUpdateListener.updateStarted(update);
|
||||
if (update.getElement() instanceof TestElementVMContext) {
|
||||
TestElement element = ((TestElementVMContext)update.getElement()).getElement();
|
||||
fillUpdateWithTestElements(update, element.getChildren());
|
||||
}
|
||||
update.done();
|
||||
fViewerUpdateListener.updateComplete(update);
|
||||
}
|
||||
fViewerUpdateListener.viewerUpdatesComplete();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(IChildrenUpdate update) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void update(final IPropertiesUpdate[] updates) {
|
||||
fViewerUpdateListener.propertiesUpdatesStarted(updates);
|
||||
if (fFormattedValuesListener != null) fFormattedValuesListener.propertiesUpdatesStarted(updates);
|
||||
|
||||
CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
for (IPropertiesUpdate update : updates) {
|
||||
if (update.getElement() instanceof TestElementVMContext) {
|
||||
TestElement element = ((TestElementVMContext)update.getElement()).getElement();
|
||||
update.setProperty(PROP_TEST_ELEMENT_LABEL, element.getLabel());
|
||||
}
|
||||
update.done();
|
||||
fViewerUpdateListener.propertiesUpdateCompleted(update);
|
||||
if (fFormattedValuesListener != null) fFormattedValuesListener.propertiesUpdateCompleted(update);
|
||||
}
|
||||
}
|
||||
};
|
||||
int count = 0;
|
||||
|
||||
fFormattedValueRetriever.update(updates, crm);
|
||||
count++;
|
||||
fDummyFormattedValueRetriever.update(updates, crm);
|
||||
count++;
|
||||
crm.setDoneCount(count);
|
||||
}
|
||||
|
||||
private void fillUpdateWithTestElements(IChildrenUpdate update, TestElement[] modelElements) {
|
||||
int updateIdx = update.getOffset() != -1 ? update.getOffset() : 0;
|
||||
int endIdx = updateIdx + (update.getLength() != -1 ? update.getLength() : modelElements.length);
|
||||
while (updateIdx < endIdx && updateIdx < modelElements.length) {
|
||||
update.setChild(createVMContext(modelElements[updateIdx]), updateIdx);
|
||||
updateIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
public TestElementVMContext createVMContext(TestElement element) {
|
||||
return new TestElementVMContext(this, element);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.dsf.ui.viewmodel.IVMNode#getDeltaFlags(java.lang.Object)
|
||||
*/
|
||||
public int getDeltaFlags(Object e) {
|
||||
if ( e instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE)
|
||||
{
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
if (e instanceof TestEvent) {
|
||||
return ((TestEvent)e).getType();
|
||||
}
|
||||
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
public void buildDelta(Object e, VMDelta parent, int nodeOffset, RequestMonitor rm) {
|
||||
if ( e instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE)
|
||||
{
|
||||
parent.setFlags(parent.getFlags() | IModelDelta.CONTENT);
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
|
||||
|
||||
public boolean isDeltaEvent(Object rootObject, Object event) {
|
||||
return getDeltaFlags(event) != IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
public void createRootDelta(Object rootObject, Object event, DataRequestMonitor<VMDelta> rm) {
|
||||
int flags = IModelDelta.NO_CHANGE;
|
||||
if ( event instanceof PropertyChangeEvent &&
|
||||
((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE)
|
||||
{
|
||||
flags |= IModelDelta.CONTENT;
|
||||
}
|
||||
|
||||
// TODO: make more sophisticated to update specific elements.
|
||||
if (event instanceof TestEvent) {
|
||||
flags|= ((TestEvent)event).getType();
|
||||
}
|
||||
|
||||
rm.setData( new VMDelta(rootObject, 0, flags) );
|
||||
rm.done();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -11,34 +11,21 @@
|
|||
package org.eclipse.cdt.tests.dsf.vm;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.cdt.tests.dsf.ViewerUpdatesListener;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModel.TestElement;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ILabelUpdateListener;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IStateUpdateListener;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
|
||||
public class TestModelUpdatesListener
|
||||
implements IViewerUpdateListener, ILabelUpdateListener, IModelChangedListener, ITestModelUpdatesListenerConstants,
|
||||
IStateUpdateListener
|
||||
/**
|
||||
* @since 2.2
|
||||
*/
|
||||
public class TestModelUpdatesListener extends ViewerUpdatesListener
|
||||
{
|
||||
|
||||
private final static Comparator<String> fStringComparator = new Comparator<String>() {
|
||||
|
@ -116,74 +103,28 @@ public class TestModelUpdatesListener
|
|||
|
||||
};
|
||||
|
||||
private final ITreeModelViewer fViewer;
|
||||
@Override
|
||||
protected Set<TreePath> makeTreePathSet() {
|
||||
return new TreeSet<TreePath>(fTestElementVMCComparator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <V> Map<TreePath, V> makeTreePathMap() {
|
||||
return new TreeMap<TreePath, V>(fTestElementVMCComparator);
|
||||
}
|
||||
|
||||
|
||||
public TestModelUpdatesListener() {
|
||||
super();
|
||||
}
|
||||
|
||||
private boolean fFailOnRedundantUpdates;
|
||||
private boolean fFailOnMultipleModelUpdateSequences;
|
||||
private boolean fFailOnMultipleLabelUpdateSequences;
|
||||
|
||||
private Set<TreePath> fHasChildrenUpdates = new TreeSet<TreePath>(fTestElementVMCComparator);
|
||||
private Map<TreePath, Set<Integer>> fChildrenUpdates = new TreeMap<TreePath, Set<Integer>>(fTestElementVMCComparator);
|
||||
private Set<TreePath> fChildCountUpdates = new TreeSet<TreePath>(fTestElementVMCComparator);
|
||||
private Set<TreePath> fLabelUpdates = new TreeSet<TreePath>(fTestElementVMCComparator);
|
||||
private Set<TestModel> fProxyModels = new HashSet<TestModel>();
|
||||
private Set<TreePath> fStateUpdates = new TreeSet<TreePath>(fTestElementVMCComparator);
|
||||
private boolean fViewerUpdatesComplete;
|
||||
private boolean fLabelUpdatesComplete;
|
||||
private boolean fModelChangedComplete;
|
||||
private boolean fStateSaveComplete;
|
||||
private boolean fStateRestoreComplete;
|
||||
private int fViewerUpdatesRunning;
|
||||
private int fLabelUpdatesRunning;
|
||||
private int fTimeoutInterval = 60000;
|
||||
private long fTimeoutTime;
|
||||
|
||||
|
||||
public TestModelUpdatesListener(ITreeModelViewer viewer, boolean failOnRedundantUpdates, boolean failOnMultipleModelUpdateSequences) {
|
||||
setFailOnRedundantUpdates(failOnRedundantUpdates);
|
||||
setFailOnMultipleModelUpdateSequences(failOnMultipleModelUpdateSequences);
|
||||
fViewer = viewer;
|
||||
fViewer.addLabelUpdateListener(this);
|
||||
fViewer.addModelChangedListener(this);
|
||||
fViewer.addStateUpdateListener(this);
|
||||
fViewer.addViewerUpdateListener(this);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
fViewer.removeLabelUpdateListener(this);
|
||||
fViewer.removeModelChangedListener(this);
|
||||
fViewer.removeStateUpdateListener(this);
|
||||
fViewer.removeViewerUpdateListener(this);
|
||||
}
|
||||
|
||||
|
||||
public void setFailOnRedundantUpdates(boolean failOnRedundantUpdates) {
|
||||
fFailOnRedundantUpdates = failOnRedundantUpdates;
|
||||
}
|
||||
|
||||
public void setFailOnMultipleModelUpdateSequences(boolean failOnMultipleLabelUpdateSequences) {
|
||||
fFailOnMultipleModelUpdateSequences = failOnMultipleLabelUpdateSequences;
|
||||
}
|
||||
|
||||
public void setFailOnMultipleLabelUpdateSequences(boolean failOnMultipleLabelUpdateSequences) {
|
||||
fFailOnMultipleLabelUpdateSequences = failOnMultipleLabelUpdateSequences;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the the maximum amount of time (in milliseconds) that the update listener
|
||||
* is going to wait. If set to -1, the listener will wait indefinitely.
|
||||
*/
|
||||
public void setTimeoutInterval(int milis) {
|
||||
fTimeoutInterval = milis;
|
||||
super(viewer, failOnRedundantUpdates, failOnMultipleModelUpdateSequences);
|
||||
}
|
||||
|
||||
public void reset(TreePath path, TestElement element, int levels, boolean failOnRedundantUpdates, boolean failOnMultipleUpdateSequences) {
|
||||
reset();
|
||||
reset(failOnRedundantUpdates, failOnMultipleUpdateSequences);
|
||||
addUpdates(path, element, levels);
|
||||
addProxies(element);
|
||||
setFailOnRedundantUpdates(failOnRedundantUpdates);
|
||||
setFailOnMultipleModelUpdateSequences(failOnMultipleUpdateSequences);
|
||||
setFailOnMultipleLabelUpdateSequences(false);
|
||||
}
|
||||
|
||||
public void reset(boolean failOnRedundantUpdates, boolean failOnMultipleUpdateSequences) {
|
||||
|
@ -193,67 +134,6 @@ public class TestModelUpdatesListener
|
|||
setFailOnMultipleLabelUpdateSequences(false);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
fHasChildrenUpdates.clear();
|
||||
fChildrenUpdates.clear();
|
||||
fChildCountUpdates.clear();
|
||||
fLabelUpdates.clear();
|
||||
fProxyModels.clear();
|
||||
fViewerUpdatesComplete = false;
|
||||
fLabelUpdatesComplete = false;
|
||||
fStateSaveComplete = false;
|
||||
fStateRestoreComplete = false;
|
||||
fTimeoutTime = System.currentTimeMillis() + fTimeoutInterval;
|
||||
resetModelChanged();
|
||||
}
|
||||
|
||||
public void resetModelChanged() {
|
||||
fModelChangedComplete = false;
|
||||
}
|
||||
|
||||
public void addHasChildrenUpdate(TreePath path) {
|
||||
fHasChildrenUpdates.add(path);
|
||||
}
|
||||
|
||||
public void removeHasChildrenUpdate(TreePath path) {
|
||||
fHasChildrenUpdates.remove(path);
|
||||
}
|
||||
|
||||
public void addChildreCountUpdate(TreePath path) {
|
||||
fChildCountUpdates.add(path);
|
||||
}
|
||||
|
||||
public void removeChildreCountUpdate(TreePath path) {
|
||||
fChildCountUpdates.remove(path);
|
||||
}
|
||||
|
||||
public void addChildreUpdate(TreePath path, int index) {
|
||||
Set<Integer> childrenIndexes = fChildrenUpdates.get(path);
|
||||
if (childrenIndexes == null) {
|
||||
childrenIndexes = new TreeSet<Integer>();
|
||||
fChildrenUpdates.put(path, childrenIndexes);
|
||||
}
|
||||
childrenIndexes.add(new Integer(index));
|
||||
}
|
||||
|
||||
public void removeChildrenUpdate(TreePath path, int index) {
|
||||
Set<Integer> childrenIndexes = fChildrenUpdates.get(path);
|
||||
if (childrenIndexes != null) {
|
||||
childrenIndexes.remove(new Integer(index));
|
||||
if (childrenIndexes.isEmpty()) {
|
||||
fChildrenUpdates.remove(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addLabelUpdate(TreePath path) {
|
||||
fLabelUpdates.add(path);
|
||||
}
|
||||
|
||||
public void removeLabelUpdate(TreePath path) {
|
||||
fLabelUpdates.remove(path);
|
||||
}
|
||||
|
||||
public void addUpdates(TreePath path, TestElement element, int levels) {
|
||||
addUpdates(path, element, levels, ALL_UPDATES_COMPLETE);
|
||||
}
|
||||
|
@ -269,29 +149,30 @@ public class TestModelUpdatesListener
|
|||
public void addUpdates(ITreeModelContentProviderTarget viewer, TreePath path, TestElement element, int levels, int flags) {
|
||||
if (!path.equals(TreePath.EMPTY)) {
|
||||
if ((flags & LABEL_UPDATES) != 0) {
|
||||
fLabelUpdates.add(path);
|
||||
addLabelUpdate(path);
|
||||
}
|
||||
if ((flags & PROPERTY_UPDATES) != 0) {
|
||||
addPropertiesUpdate(path);
|
||||
}
|
||||
if ((flags & HAS_CHILDREN_UPDATES) != 0) {
|
||||
fHasChildrenUpdates.add(path);
|
||||
addHasChildrenUpdate(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (levels-- != 0) {
|
||||
TestElement[] children = element.getChildren();
|
||||
if (children.length > 0 && (viewer == null || path.getSegmentCount() == 0 || viewer.getExpandedState(path))) {
|
||||
if ((flags & CHILDREN_COUNT_UPDATES) != 0) {
|
||||
fChildCountUpdates.add(path);
|
||||
if ((flags & CHILD_COUNT_UPDATES) != 0) {
|
||||
addChildCountUpdate(path);
|
||||
}
|
||||
if ((flags & CHILDREN_UPDATES) != 0) {
|
||||
Set<Integer> childrenIndexes = new HashSet<Integer>();
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
childrenIndexes.add(new Integer(i));
|
||||
addChildreUpdate(path, i);
|
||||
}
|
||||
fChildrenUpdates.put(path, childrenIndexes);
|
||||
}
|
||||
|
||||
if ((flags & STATE_UPDATES) != 0 && viewer != null) {
|
||||
fStateUpdates.add(path);
|
||||
addStateUpdate(path);
|
||||
}
|
||||
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
|
@ -301,284 +182,6 @@ public class TestModelUpdatesListener
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
private void addProxies(TestElement element) {
|
||||
TestModel model = element.getModel();
|
||||
if (model.getModelProxy() == null) {
|
||||
fProxyModels.add(element.getModel());
|
||||
}
|
||||
TestElement[] children = element.getChildren();
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
addProxies(children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return isFinished(ALL_UPDATES_COMPLETE);
|
||||
}
|
||||
|
||||
public boolean isFinished(int flags) {
|
||||
if (fTimeoutInterval > 0 && fTimeoutTime < System.currentTimeMillis()) {
|
||||
throw new RuntimeException("Timed Out: " + toString(flags));
|
||||
}
|
||||
|
||||
if ( (flags & LABEL_UPDATES_COMPLETE) != 0) {
|
||||
if (!fLabelUpdatesComplete) return false;
|
||||
}
|
||||
if ( (flags & LABEL_UPDATES) != 0) {
|
||||
if (!fLabelUpdates.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & CONTENT_UPDATES_COMPLETE) != 0) {
|
||||
if (!fViewerUpdatesComplete) return false;
|
||||
}
|
||||
if ( (flags & HAS_CHILDREN_UPDATES) != 0) {
|
||||
if (!fHasChildrenUpdates.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & CHILDREN_COUNT_UPDATES) != 0) {
|
||||
if (!fChildCountUpdates.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & CHILDREN_UPDATES) != 0) {
|
||||
if (!fChildrenUpdates.isEmpty()) return false;
|
||||
}
|
||||
if ( (flags & MODEL_CHANGED_COMPLETE) != 0) {
|
||||
if (!fModelChangedComplete) return false;
|
||||
}
|
||||
if ( (flags & STATE_SAVE_COMPLETE) != 0) {
|
||||
if (!fStateSaveComplete) return false;
|
||||
}
|
||||
if ( (flags & STATE_RESTORE_COMPLETE) != 0) {
|
||||
if (!fStateRestoreComplete) return false;
|
||||
}
|
||||
if ( (flags & MODEL_PROXIES_INSTALLED) != 0) {
|
||||
if (fProxyModels.size() != 0) return false;
|
||||
}
|
||||
if ( (flags & VIEWER_UPDATES_RUNNING) != 0) {
|
||||
if (fViewerUpdatesRunning != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( (flags & LABEL_UPDATES_RUNNING) != 0) {
|
||||
if (fLabelUpdatesRunning != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateStarted(IViewerUpdate update) {
|
||||
synchronized (this) {
|
||||
fViewerUpdatesRunning++;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateComplete(IViewerUpdate update) {
|
||||
synchronized (this) {
|
||||
fViewerUpdatesRunning--;
|
||||
}
|
||||
|
||||
if (!update.isCanceled()) {
|
||||
if (update instanceof IHasChildrenUpdate) {
|
||||
if (!fHasChildrenUpdates.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
|
||||
Assert.fail("Redundant update: " + update);
|
||||
}
|
||||
} if (update instanceof IChildrenCountUpdate) {
|
||||
if (!fChildCountUpdates.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
|
||||
Assert.fail("Redundant update: " + update);
|
||||
}
|
||||
} else if (update instanceof IChildrenUpdate) {
|
||||
int start = ((IChildrenUpdate)update).getOffset();
|
||||
int end = start + ((IChildrenUpdate)update).getLength();
|
||||
|
||||
Set<Integer> childrenIndexes = fChildrenUpdates.get(update.getElementPath());
|
||||
if (childrenIndexes != null) {
|
||||
for (int i = start; i < end; i++) {
|
||||
childrenIndexes.remove(new Integer(i));
|
||||
}
|
||||
if (childrenIndexes.isEmpty()) {
|
||||
fChildrenUpdates.remove(update.getElementPath());
|
||||
}
|
||||
} else if (fFailOnRedundantUpdates) {
|
||||
Assert.fail("Redundant update: " + update);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void viewerUpdatesBegin() {
|
||||
|
||||
}
|
||||
|
||||
public void viewerUpdatesComplete() {
|
||||
if (fFailOnMultipleModelUpdateSequences && fViewerUpdatesComplete) {
|
||||
Assert.fail("Multiple viewer update sequences detected");
|
||||
}
|
||||
fViewerUpdatesComplete = true;
|
||||
}
|
||||
|
||||
public void labelUpdateComplete(ILabelUpdate update) {
|
||||
synchronized (this) {
|
||||
fLabelUpdatesRunning--;
|
||||
}
|
||||
if (!fLabelUpdates.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
|
||||
Assert.fail("Redundant update: " + update);
|
||||
}
|
||||
}
|
||||
|
||||
public void labelUpdateStarted(ILabelUpdate update) {
|
||||
synchronized (this) {
|
||||
fLabelUpdatesRunning++;
|
||||
}
|
||||
}
|
||||
|
||||
public void labelUpdatesBegin() {
|
||||
}
|
||||
|
||||
public void labelUpdatesComplete() {
|
||||
if (fFailOnMultipleLabelUpdateSequences && fLabelUpdatesComplete) {
|
||||
Assert.fail("Multiple label update sequences detected");
|
||||
}
|
||||
fLabelUpdatesComplete = true;
|
||||
}
|
||||
|
||||
public void modelChanged(IModelDelta delta, IModelProxy proxy) {
|
||||
fModelChangedComplete = true;
|
||||
|
||||
for (Iterator<TestModel> itr = fProxyModels.iterator(); itr.hasNext();) {
|
||||
TestModel model = itr.next();
|
||||
if (model.getModelProxy() == proxy) {
|
||||
itr.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stateRestoreUpdatesBegin(Object input) {
|
||||
}
|
||||
|
||||
public void stateRestoreUpdatesComplete(Object input) {
|
||||
fStateRestoreComplete = true;
|
||||
}
|
||||
|
||||
public void stateSaveUpdatesBegin(Object input) {
|
||||
}
|
||||
|
||||
public void stateSaveUpdatesComplete(Object input) {
|
||||
fStateSaveComplete = true;
|
||||
}
|
||||
|
||||
public void stateUpdateComplete(Object input, IViewerUpdate update) {
|
||||
}
|
||||
|
||||
public void stateUpdateStarted(Object input, IViewerUpdate update) {
|
||||
}
|
||||
|
||||
private String toString(int flags) {
|
||||
StringBuffer buf = new StringBuffer("Viewer Update Listener");
|
||||
|
||||
if ( (flags & LABEL_UPDATES_COMPLETE) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fLabelUpdatesComplete = " + fLabelUpdatesComplete);
|
||||
}
|
||||
if ( (flags & LABEL_UPDATES_RUNNING) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fLabelUpdatesRunning = " + fLabelUpdatesRunning);
|
||||
}
|
||||
if ( (flags & LABEL_UPDATES) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fLabelUpdates = ");
|
||||
buf.append( toString(fLabelUpdates) );
|
||||
}
|
||||
if ( (flags & CONTENT_UPDATES_COMPLETE) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fViewerUpdatesComplete = " + fViewerUpdatesComplete);
|
||||
}
|
||||
if ( (flags & VIEWER_UPDATES_RUNNING) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fViewerUpdatesRunning = " + fViewerUpdatesRunning);
|
||||
}
|
||||
if ( (flags & HAS_CHILDREN_UPDATES) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fHasChildrenUpdates = ");
|
||||
buf.append( toString(fHasChildrenUpdates) );
|
||||
}
|
||||
if ( (flags & CHILDREN_COUNT_UPDATES) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fChildCountUpdates = ");
|
||||
buf.append( toString(fChildCountUpdates) );
|
||||
}
|
||||
if ( (flags & CHILDREN_UPDATES) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fChildrenUpdates = ");
|
||||
buf.append( toString(fChildrenUpdates) );
|
||||
}
|
||||
if ( (flags & MODEL_CHANGED_COMPLETE) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fModelChangedComplete = " + fModelChangedComplete);
|
||||
}
|
||||
if ( (flags & STATE_SAVE_COMPLETE) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fStateSaveComplete = " + fStateSaveComplete);
|
||||
}
|
||||
if ( (flags & STATE_RESTORE_COMPLETE) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fStateRestoreComplete = " + fStateRestoreComplete);
|
||||
}
|
||||
if ( (flags & MODEL_PROXIES_INSTALLED) != 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fProxyModels = " + fProxyModels);
|
||||
}
|
||||
if (fTimeoutInterval > 0) {
|
||||
buf.append("\n\t");
|
||||
buf.append("fTimeoutInterval = " + fTimeoutInterval);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String toString(Set<TreePath> set) {
|
||||
if (set.isEmpty()) {
|
||||
return "(EMPTY)";
|
||||
}
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (Iterator<TreePath> itr = set.iterator(); itr.hasNext(); ) {
|
||||
buf.append("\n\t\t");
|
||||
buf.append(toString(itr.next()));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String toString(Map<TreePath, Set<Integer>> map) {
|
||||
if (map.isEmpty()) {
|
||||
return "(EMPTY)";
|
||||
}
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (Iterator<TreePath> itr = map.keySet().iterator(); itr.hasNext(); ) {
|
||||
buf.append("\n\t\t");
|
||||
TreePath path = itr.next();
|
||||
buf.append(toString(path));
|
||||
Set<?> updates = map.get(path);
|
||||
buf.append(" = ");
|
||||
buf.append(updates.toString());
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String toString(TreePath path) {
|
||||
if (path.getSegmentCount() == 0) {
|
||||
return "/";
|
||||
}
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i = 0; i < path.getSegmentCount(); i++) {
|
||||
buf.append("/");
|
||||
buf.append(path.getSegment(i));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(ALL_UPDATES_COMPLETE | MODEL_CHANGED_COMPLETE | STATE_RESTORE_COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
|
|||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class TestModelVMAdapter extends AbstractVMAdapter {
|
||||
|
||||
|
|
|
@ -13,9 +13,10 @@ package org.eclipse.cdt.tests.dsf.vm;
|
|||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueLabelText;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMNode;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate;
|
||||
|
@ -23,6 +24,7 @@ import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute;
|
|||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText;
|
||||
import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider;
|
||||
import org.eclipse.cdt.tests.dsf.DsfTestPlugin;
|
||||
import org.eclipse.cdt.tests.dsf.vm.TestModel.TestElement;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
@ -33,7 +35,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdat
|
|||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class TestModelVMNode extends AbstractVMNode implements IRootVMNode, IElementLabelProvider, IElementPropertiesProvider {
|
||||
|
||||
|
@ -41,10 +43,16 @@ public class TestModelVMNode extends AbstractVMNode implements IRootVMNode, IEle
|
|||
|
||||
final private static PropertiesBasedLabelProvider fLabelProvider = new PropertiesBasedLabelProvider();
|
||||
{
|
||||
LabelColumnInfo idLabelInfo = new LabelColumnInfo(new LabelAttribute[] {
|
||||
new LabelText("{0}", new String[] { PROP_TEST_ELEMENT_LABEL })
|
||||
});
|
||||
|
||||
fLabelProvider.setColumnInfo(PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS, idLabelInfo);
|
||||
fLabelProvider.setColumnInfo(TestModelCachingVMProvider.COLUMN_ID, idLabelInfo);
|
||||
fLabelProvider.setColumnInfo(
|
||||
PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS,
|
||||
new LabelColumnInfo(new LabelAttribute[] {
|
||||
new LabelText("{0}", new String[] { PROP_TEST_ELEMENT_LABEL })
|
||||
TestModelCachingVMProvider.COLUMN_FORMATTED_VALUE,
|
||||
new LabelColumnInfo(new LabelAttribute[] {
|
||||
new FormattedValueLabelText()
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -52,7 +60,7 @@ public class TestModelVMNode extends AbstractVMNode implements IRootVMNode, IEle
|
|||
fLabelProvider.update(updates);
|
||||
}
|
||||
|
||||
public TestModelVMNode(IVMProvider provider) {
|
||||
public TestModelVMNode(AbstractVMProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
|
@ -123,7 +131,7 @@ public class TestModelVMNode extends AbstractVMNode implements IRootVMNode, IEle
|
|||
}
|
||||
|
||||
public void createRootDelta(Object rootObject, Object event, DataRequestMonitor<VMDelta> rm) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, TestDsfVMPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented", null));
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfTestPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented", null));
|
||||
rm.done();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,10 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
|||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public class TestModelVMProvider extends AbstractVMProvider {
|
||||
|
||||
public TestModelVMProvider(AbstractVMAdapter adapter, IPresentationContext context) {
|
||||
super(adapter, context);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import org.eclipse.swt.widgets.Display;
|
|||
import org.eclipse.swt.widgets.Shell;
|
||||
|
||||
/**
|
||||
* @since 3.6
|
||||
* @since 2.2
|
||||
*/
|
||||
public class VirtualViewerPerformanceTests extends PerformanceTests {
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue