/*******************************************************************************
* 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.ui.viewmodel.register;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.ICachingService;
import org.eclipse.cdt.dsf.debug.service.IRegisters;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
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.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.AbstractVMContext;
import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
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.debug.internal.ui.viewers.model.provisional.IViewerInputUpdate;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
/**
* Provides the VIEW MODEL for the DEBUG MODEL REGISTER view.
*/
public class RegisterVMProvider extends AbstractDMVMProvider
{
private IPropertyChangeListener fPreferencesListener = new IPropertyChangeListener() {
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() {
public void propertyChange(PropertyChangeEvent event) {
handleEvent(event);
}
};
/*
* Current default for register formatting.
*/
public RegisterVMProvider(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));
/*
* Create the register data access routines.
*/
SyncRegisterDataAccess regAccess = new SyncRegisterDataAccess(session) ;
/*
* Create the top level node to deal with the root selection.
*/
IRootVMNode rootNode = new RegisterRootDMVMNode(this);
/*
* Create the Group nodes next. They represent the first level shown in the view.
*/
IVMNode registerGroupNode = new RegisterGroupVMNode(this, getSession(), regAccess);
addChildNodes(rootNode, new IVMNode[] { registerGroupNode });
/*
* Create the next level which is the registers themselves.
*/
IVMNode registerNode = new RegisterVMNode(this, getSession(), regAccess);
addChildNodes(registerGroupNode, new IVMNode[] { registerNode });
/*
* Create the next level which is the bitfield level.
*/
IVMNode bitFieldNode = new RegisterBitFieldVMNode(this, getSession(), regAccess);
addChildNodes(registerNode, new IVMNode[] { bitFieldNode });
/*
* Now set this schema set as the layout set.
*/
setRootNode(rootNode);
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.dsf.ui.viewmodel.update.AbstractCachingVMProvider#createUpdateModes()
*/
@Override
protected IVMUpdatePolicy[] createUpdateModes() {
return new IVMUpdatePolicy[] { new AutomaticUpdatePolicy(), new DebugManualUpdatePolicy(), new BreakpointHitUpdatePolicy() };
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider#dispose()
*/
@Override
public void dispose() {
DsfDebugUITools.getPreferenceStore().removePropertyChangeListener(fPreferencesListener);
getPresentationContext().removePropertyChangeListener(fPresentationContextListener);
super.dispose();
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider#createColumnPresentation(org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, java.lang.Object)
*/
@Override
public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
return new RegisterColumnPresentation();
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider#getColumnPresentationId(org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, java.lang.Object)
*/
@Override
public String getColumnPresentationId(IPresentationContext context, Object element) {
return RegisterColumnPresentation.ID;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider#canSkipHandlingEvent(java.lang.Object, java.lang.Object)
*/
@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;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider#update(org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputUpdate)
*/
@Override
public void update(IViewerInputUpdate update) {
/*
* Use the execution context in the current selection as the input provider.
* This insures that the REGISTER VIEW will not collapse and expand on stepping or on
* re-selection in the DEBUG VIEW. Currently the register content is not stack frame
* specific. If it were to become so then we would need to modify this policy.
*/
Object element = update.getElement();
if (element instanceof IDMVMContext) {
IDMContext ctx = ((IDMVMContext) element).getDMContext();
IExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IExecutionDMContext.class);
if ( execDmc != null ) {
/*
* This tells the Flexible Hierarchy that element driving this view has not changed
* and there is no need to redraw the view. Since this is a somewhat fake VMContext
* we provide our Root Layout node as the representative VM node.
*/
update.setInputElement(new ViewInputElement(RegisterVMProvider.this.getRootVMNode(), execDmc));
update.done();
return;
}
}
/*
* If we reach here, then we did not override the standard behavior. Invoke the
* super class and this will provide the default standard behavior.
*/
super.update(update);
}
/*
* Provides a local implementation of the IDMVMContext. This allows us to return one
* of our own making, representing the DMContext we want to use as selection criteria.
*/
private class ViewInputElement extends AbstractVMContext implements IDMVMContext {
final private IDMContext fDMContext;
public ViewInputElement(IVMNode node, IDMContext dmc) {
super(node);
fDMContext = dmc;
}
public IDMContext getDMContext() {
return fDMContext;
}
/**
* The IAdaptable implementation. If the adapter is the DM context,
* return the context, otherwise delegate to IDMContext.getAdapter().
*/
@Override
@SuppressWarnings("rawtypes")
public Object getAdapter(Class adapter) {
Object superAdapter = super.getAdapter(adapter);
if (superAdapter != null) {
return superAdapter;
} else {
// Delegate to the Data Model to find the context.
if (adapter.isInstance(fDMContext)) {
return fDMContext;
} else {
return fDMContext.getAdapter(adapter);
}
}
}
@Override
public boolean equals(Object obj) {
if ( obj instanceof ViewInputElement && ((ViewInputElement) obj).fDMContext.equals(fDMContext) ) {
return true;
}
return false;
}
@Override
public int hashCode() {
return fDMContext.hashCode();
}
}
@Override
public void refresh() {
super.refresh();
try {
getSession().getExecutor().execute(new DsfRunnable() {
public void run() {
DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), getSession().getId());
IRegisters registerService = tracker.getService(IRegisters.class);
if (registerService instanceof ICachingService) {
((ICachingService)registerService).flushCache(null);
}
tracker.dispose();
}
});
} catch (RejectedExecutionException e) {
// Session disposed, ignore.
}
}
}