blob: 31ecabfa3aaff13e531345c5a9b003499fcda9cd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2014 Wind River Systems and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.ui.viewmodel.variable;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.DsfCastToTypeSupport;
import org.eclipse.cdt.dsf.debug.service.ICachingService;
import org.eclipse.cdt.dsf.debug.service.IExpressions;
import org.eclipse.cdt.dsf.debug.service.IExpressions2;
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.cdt.dsf.debug.ui.DsfDebugUITools;
import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.AbstractElementVMProvider;
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.internal.ui.DsfUIPlugin;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter;
import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.RootDMVMNode;
import org.eclipse.cdt.dsf.ui.viewmodel.update.AutomaticUpdatePolicy;
import org.eclipse.cdt.dsf.ui.viewmodel.update.IVMUpdatePolicy;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
public class VariableVMProvider extends AbstractElementVMProvider {
private IPropertyChangeListener fPreferencesListener = new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
String property = event.getProperty();
if (property.equals(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE)) {
IPreferenceStore store = DsfDebugUITools.getPreferenceStore();
setDelayEventHandleForViewUpdate(store.getBoolean(property));
}
}
};
private IPropertyChangeListener fPresentationContextListener = new IPropertyChangeListener() {
@Override
public void propertyChange(final PropertyChangeEvent event) {
getExecutor().execute(new DsfRunnable() {
@Override
public void run() {
handleEvent(event);
}
});
}
};
public VariableVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
super(adapter, context, session);
context.addPropertyChangeListener(fPresentationContextListener);
IPreferenceStore store = DsfDebugUITools.getPreferenceStore();
store.addPropertyChangeListener(fPreferencesListener);
setDelayEventHandleForViewUpdate(
store.getBoolean(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE));
configureLayout();
}
@Override
public void dispose() {
DsfDebugUITools.getPreferenceStore().removePropertyChangeListener(fPreferencesListener);
getPresentationContext().removePropertyChangeListener(fPresentationContextListener);
super.dispose();
}
/**
* Configures the nodes of this provider. This method may be over-ridden by
* sub classes to create an alternate configuration in this provider.
*
* @since 2.1
*/
protected void configureLayout() {
// Create the variable data access routines.
SyncVariableDataAccess varAccess = new SyncVariableDataAccess(getSession());
// Create the top level node to deal with the root selection.
IRootVMNode rootNode = new RootDMVMNode(this);
setRootNode(rootNode);
// Create the next level which represents members of structs/unions/enums and elements of arrays.
VariableVMNode subExpressioNode = new VariableVMNode(this, getSession(), varAccess);
addChildNodes(rootNode, new IVMNode[] { subExpressioNode });
// Wire up the casting support if the IExpressions2 service is available.
hookUpCastingSupport(varAccess, subExpressioNode);
// Configure the sub-expression node to be a child of itself. This way the content
// provider will recursively drill-down the variable hierarchy.
addChildNodes(subExpressioNode, new IVMNode[] { subExpressioNode });
}
private void hookUpCastingSupport(final SyncVariableDataAccess syncvarDataAccess,
final VariableVMNode variableNode) {
try {
getSession().getExecutor().execute(new DsfRunnable() {
@Override
public void run() {
DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(),
getSession().getId());
IExpressions2 expressions2 = tracker.getService(IExpressions2.class);
if (expressions2 != null) {
variableNode.setCastToTypeSupport(
new DsfCastToTypeSupport(getSession(), VariableVMProvider.this, syncvarDataAccess));
}
tracker.dispose();
}
});
} catch (RejectedExecutionException e) {
// Session disposed, ignore.
}
}
@Override
public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
return new VariableColumnPresentation();
}
@Override
public String getColumnPresentationId(IPresentationContext context, Object element) {
return VariableColumnPresentation.ID;
}
@Override
protected IVMUpdatePolicy[] createUpdateModes() {
return new IVMUpdatePolicy[] { new AutomaticUpdatePolicy(), new DebugManualUpdatePolicy(),
new BreakpointHitUpdatePolicy() };
}
@Override
protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
// To optimize the performance of the view when stepping rapidly, skip all
// other events when a suspended event is received, including older suspended
// events.
return newEvent instanceof ISuspendedDMEvent;
}
@Override
public void refresh() {
super.refresh();
try {
getSession().getExecutor().execute(new DsfRunnable() {
@Override
public void run() {
DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(),
getSession().getId());
IExpressions expressionsService = tracker.getService(IExpressions.class);
if (expressionsService instanceof ICachingService) {
((ICachingService) expressionsService).flushCache(null);
}
tracker.dispose();
}
});
} catch (RejectedExecutionException e) {
// Session disposed, ignore.
}
}
}