| /******************************************************************************* |
| * 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. |
| } |
| } |
| } |