/*******************************************************************************
* Copyright (c) 2004, 2008 QNX Software 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:
* QNX Software Systems - Initial API and implementation
* Nokia - https://bugs.eclipse.org/bugs/show_bug.cgi?id=145606
* QNX Software Systems - Catchpoints support https://bugs.eclipse.org/bugs/show_bug.cgi?id=226689
*******************************************************************************/
package org.eclipse.cdt.debug.internal.ui.propertypages;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.cdt.debug.core.model.ICAddressBreakpoint;
import org.eclipse.cdt.debug.core.model.ICBreakpoint;
import org.eclipse.cdt.debug.core.model.ICEventBreakpoint;
import org.eclipse.cdt.debug.core.model.ICFunctionBreakpoint;
import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
import org.eclipse.cdt.debug.core.model.ICWatchpoint;
import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
import org.eclipse.cdt.debug.ui.breakpoints.CBreakpointUIContributionFactory;
import org.eclipse.cdt.debug.ui.breakpoints.ICBreakpointsUIContribution;
import org.eclipse.cdt.debug.ui.preferences.ReadOnlyFieldEditor;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.model.ILineBreakpoint;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchPropertyPage;
/**
* The preference page used to present the properties of a breakpoint as preferences. A CBreakpointPreferenceStore is used to interface between this page and
* the breakpoint.
*/
public class CBreakpointPropertyPage extends FieldEditorPreferencePage implements IWorkbenchPropertyPage {
class BreakpointIntegerFieldEditor extends IntegerFieldEditor {
public BreakpointIntegerFieldEditor( String name, String labelText, Composite parent ) {
super( name, labelText, parent );
setErrorMessage( PropertyPageMessages.getString( "CBreakpointPropertyPage.0" ) ); //$NON-NLS-1$
}
/**
* @see IntegerFieldEditor#checkState()
*/
protected boolean checkState() {
Text control = getTextControl();
if ( !control.isEnabled() ) {
clearErrorMessage();
return true;
}
return super.checkState();
}
/**
* Overrode here to be package visible.
*/
protected void refreshValidState() {
super.refreshValidState();
}
/**
* Only store if the text control is enabled
*
* @see FieldEditor#doStore()
*/
protected void doStore() {
Text text = getTextControl();
if ( text.isEnabled() ) {
super.doStore();
}
}
/**
* Clears the error message from the message line if the error message is the error message from this field editor.
*/
protected void clearErrorMessage() {
if ( getPage() != null ) {
String message = getPage().getErrorMessage();
if ( message != null ) {
if ( getErrorMessage().equals( message ) ) {
super.clearErrorMessage();
}
}
else {
super.clearErrorMessage();
}
}
}
}
class BreakpointStringFieldEditor extends StringFieldEditor {
public BreakpointStringFieldEditor( String name, String labelText, Composite parent ) {
super( name, labelText, parent );
}
/**
* @see StringFieldEditor#checkState()
*/
protected boolean checkState() {
Text control = getTextControl();
if ( !control.isEnabled() ) {
clearErrorMessage();
return true;
}
return super.checkState();
}
protected void doStore() {
Text text = getTextControl();
if ( text.isEnabled() ) {
super.doStore();
}
}
/**
* @see FieldEditor#refreshValidState()
*/
protected void refreshValidState() {
super.refreshValidState();
}
/**
* Clears the error message from the message line if the error message is the error message from this field editor.
*/
protected void clearErrorMessage() {
if ( getPage() != null ) {
String message = getPage().getErrorMessage();
if ( message != null ) {
if ( getErrorMessage().equals( message ) ) {
super.clearErrorMessage();
}
}
else {
super.clearErrorMessage();
}
}
}
}
class LabelFieldEditor extends ReadOnlyFieldEditor {
private String fValue;
public LabelFieldEditor( Composite parent, String title, String value ) {
super(title, title, parent);
fValue = value;
}
@Override
protected void doLoad() {
if (textField != null) {
textField.setText(fValue);
}
}
@Override
protected void doLoadDefault() {
// nothing
}
}
private BooleanFieldEditor fEnabled;
private BreakpointStringFieldEditor fCondition;
private Text fIgnoreCountTextControl;
private BreakpointIntegerFieldEditor fIgnoreCount;
private IAdaptable fElement;
/**
* The "fake" preference store used to interface between
* the breakpoint and the breakpoint preference page.
*/
private CBreakpointPreferenceStore fCBreakpointPreferenceStore;
/**
* Constructor for CBreakpointPropertyPage.
*
* @param breakpoint
*/
public CBreakpointPropertyPage() {
super( GRID );
noDefaultAndApplyButton();
fCBreakpointPreferenceStore = new CBreakpointPreferenceStore();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.preference.FieldEditorPreferencePage#createFieldEditors()
*/
protected void createFieldEditors() {
ICBreakpoint breakpoint = getBreakpoint();
createMainLabel(breakpoint);
createContributetedFieldEditors(breakpoint);
createTypeSpecificLabelFieldEditors( breakpoint );
createEnabledField( getFieldEditorParent() );
IPreferenceStore store = getPreferenceStore();
try {
String condition = breakpoint.getCondition();
if ( condition == null ) {
condition = ""; //$NON-NLS-1$
}
store.setValue( CBreakpointPreferenceStore.CONDITION, condition );
createConditionEditor( getFieldEditorParent() );
store.setValue( CBreakpointPreferenceStore.ENABLED, breakpoint.isEnabled() );
int ignoreCount = breakpoint.getIgnoreCount();
store.setValue( CBreakpointPreferenceStore.IGNORE_COUNT, (ignoreCount >= 0) ? ignoreCount : 0 );
createIgnoreCountEditor( getFieldEditorParent() );
}
catch( CoreException ce ) {
CDebugUIPlugin.log( ce );
}
}
private void createMainLabel(ICBreakpoint breakpoint) {
addField( createLabelEditor( getFieldEditorParent(), PropertyPageMessages.getString( "CBreakpointPropertyPage.18" ), //$NON-NLS-1$
getBreakpointMainLabel(breakpoint) ) );
}
/**
* Method createTypeSpecificLabelFieldEditors.
*
* @param breakpoint
*/
private void createTypeSpecificLabelFieldEditors( ICBreakpoint breakpoint ) {
if ( breakpoint instanceof ICFunctionBreakpoint ) {
ICFunctionBreakpoint fbrkpt = (ICFunctionBreakpoint)breakpoint;
String function = PropertyPageMessages.getString( "CBreakpointPropertyPage.1" ); //$NON-NLS-1$
try {
function = fbrkpt.getFunction();
}
catch( CoreException e ) {
}
catch( NumberFormatException e ) {
}
if ( function != null ) {
addField( createLabelEditor( getFieldEditorParent(), PropertyPageMessages.getString( "CBreakpointPropertyPage.2" ), function ) ); //$NON-NLS-1$
}
}
else if ( breakpoint instanceof ICAddressBreakpoint ) {
ICAddressBreakpoint abrkpt = (ICAddressBreakpoint)breakpoint;
String address = PropertyPageMessages.getString( "CBreakpointPropertyPage.4" ); //$NON-NLS-1$
try {
address = abrkpt.getAddress();
}
catch( CoreException e ) {
}
if ( address != null ) {
addField( createLabelEditor( getFieldEditorParent(), PropertyPageMessages.getString( "CBreakpointPropertyPage.5" ), address ) ); //$NON-NLS-1$
}
}
else if ( breakpoint instanceof ICWatchpoint ) {
ICWatchpoint watchpoint = (ICWatchpoint)breakpoint;
String expression = ""; //$NON-NLS-1$
try {
expression = watchpoint.getExpression();
}
catch( CoreException ce ) {
CDebugUIPlugin.log( ce );
}
IProject project = breakpoint.getMarker().getResource().getProject();
if ( project != null ) {
addField( createLabelEditor( getFieldEditorParent(), PropertyPageMessages.getString( "CBreakpointPropertyPage.10" ), project.getName() ) ); //$NON-NLS-1$
}
IResource resource = breakpoint.getMarker().getResource();
if ( resource instanceof IFile ) {
String filename = resource.getLocation().toOSString();
if ( filename != null ) {
addField( createLabelEditor( getFieldEditorParent(), PropertyPageMessages.getString( "CBreakpointPropertyPage.20" ), filename ) ); //$NON-NLS-1$
}
}
addField( createLabelEditor( getFieldEditorParent(), PropertyPageMessages.getString( "CBreakpointPropertyPage.14" ), expression ) ); //$NON-NLS-1$
}
else if ( breakpoint instanceof ILineBreakpoint ) {
String fileName = null;
try {
fileName = breakpoint.getSourceHandle();
}
catch( CoreException e ) {
}
if ( fileName != null ) {
addField( createLabelEditor( getFieldEditorParent(), PropertyPageMessages.getString( "CBreakpointPropertyPage.7" ), fileName ) ); //$NON-NLS-1$
}
ILineBreakpoint lBreakpoint = (ILineBreakpoint) breakpoint;
int lNumber = 0;
try {
lNumber = lBreakpoint.getLineNumber();
} catch (CoreException e) {
CDebugUIPlugin.log(e);
}
if (lNumber > 0) {
getPreferenceStore().setValue( CBreakpointPreferenceStore.LINE, lNumber);
createLineNumberEditor(getFieldEditorParent());
}
}
}
private String getBreakpointMainLabel(ICBreakpoint breakpoint) {
if (breakpoint instanceof ICFunctionBreakpoint)
return PropertyPageMessages.getString("CBreakpointPropertyPage.3"); //$NON-NLS-1$
if (breakpoint instanceof ICAddressBreakpoint)
return PropertyPageMessages.getString("CBreakpointPropertyPage.4"); //$NON-NLS-1$
if (breakpoint instanceof ICLineBreakpoint)
return PropertyPageMessages.getString("CBreakpointPropertyPage.8"); //$NON-NLS-1$
if (breakpoint instanceof ICEventBreakpoint)
return PropertyPageMessages.getString("CBreakpointPropertyPage.21"); //$NON-NLS-1$
if (breakpoint instanceof ICWatchpoint) {
ICWatchpoint watchpoint = (ICWatchpoint) breakpoint;
String type = ""; //$NON-NLS-1$
try {
if (watchpoint.isReadType() && !watchpoint.isWriteType())
type = PropertyPageMessages.getString("CBreakpointPropertyPage.11"); //$NON-NLS-1$
else if (!watchpoint.isReadType() && watchpoint.isWriteType())
type = PropertyPageMessages.getString("CBreakpointPropertyPage.12"); //$NON-NLS-1$
else
type = PropertyPageMessages.getString("CBreakpointPropertyPage.13"); //$NON-NLS-1$
} catch (CoreException ce) {
CDebugUIPlugin.log(ce);
}
return type;
}
// default main label is the label of marker type for the breakpoint
String type = ""; //$NON-NLS-1$
try {
type = breakpoint.getMarker().getType(); // TODO: how to get label?
} catch (CoreException ce) {
CDebugUIPlugin.log(ce);
}
return type;
}
protected void createLineNumberEditor( Composite parent ) {
String title = PropertyPageMessages.getString( "CBreakpointPropertyPage.9" ); //$NON-NLS-1$
BreakpointIntegerFieldEditor labelFieldEditor =new BreakpointIntegerFieldEditor( CBreakpointPreferenceStore.LINE ,title, parent);
labelFieldEditor.setValidRange( 1, Integer.MAX_VALUE );
addField( labelFieldEditor );
}
protected void createEnabledField( Composite parent ) {
fEnabled = new BooleanFieldEditor( CBreakpointPreferenceStore.ENABLED, PropertyPageMessages.getString( "CBreakpointPropertyPage.19" ), parent ); //$NON-NLS-1$
addField( fEnabled );
}
protected void createConditionEditor( Composite parent ) {
fCondition = new BreakpointStringFieldEditor( CBreakpointPreferenceStore.CONDITION, PropertyPageMessages.getString( "CBreakpointPropertyPage.15" ), parent ); //$NON-NLS-1$
fCondition.setEmptyStringAllowed( true );
fCondition.setErrorMessage( PropertyPageMessages.getString( "CBreakpointPropertyPage.16" ) ); //$NON-NLS-1$
addField( fCondition );
}
protected void createIgnoreCountEditor( Composite parent ) {
fIgnoreCount = new BreakpointIntegerFieldEditor( CBreakpointPreferenceStore.IGNORE_COUNT, PropertyPageMessages.getString( "CBreakpointPropertyPage.17" ), parent ); //$NON-NLS-1$
fIgnoreCount.setValidRange( 0, Integer.MAX_VALUE );
fIgnoreCountTextControl = fIgnoreCount.getTextControl( parent );
try {
fIgnoreCountTextControl.setEnabled( getBreakpoint().getIgnoreCount() >= 0 );
}
catch( CoreException ce ) {
CDebugUIPlugin.log( ce );
}
addField( fIgnoreCount );
}
protected FieldEditor createLabelEditor( Composite parent, String title, String value ) {
return new LabelFieldEditor( parent, title, value );
}
protected ICBreakpoint getBreakpoint() {
IAdaptable element = getElement();
return ( element instanceof ICBreakpoint ) ? (ICBreakpoint)element : (ICBreakpoint)element.getAdapter(ICBreakpoint.class);
}
/* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPropertyPage#getElement()
*/
public IAdaptable getElement() {
return fElement;
}
/* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPropertyPage#setElement(org.eclipse.core.runtime.IAdaptable)
*/
public void setElement( IAdaptable element ) {
fElement = element;
}
public IPreferenceStore getPreferenceStore() {
return fCBreakpointPreferenceStore;
}
public boolean performOk() {
final List changedProperties = new ArrayList( 5 );
getPreferenceStore().addPropertyChangeListener( new IPropertyChangeListener() {
/**
* @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
*/
public void propertyChange( PropertyChangeEvent event ) {
changedProperties.add( event.getProperty() );
}
} );
boolean result = super.performOk();
setBreakpointProperties( changedProperties );
return result;
}
protected void setBreakpointProperties( final List changedProperties ) {
IWorkspaceRunnable wr = new IWorkspaceRunnable() {
public void run( IProgressMonitor monitor ) throws CoreException {
ICBreakpoint breakpoint = getBreakpoint();
Iterator changed = changedProperties.iterator();
while( changed.hasNext() ) {
String property = (String)changed.next();
if ( property.equals( CBreakpointPreferenceStore.ENABLED ) ) {
breakpoint.setEnabled( getPreferenceStore().getBoolean( CBreakpointPreferenceStore.ENABLED ) );
}
else if ( property.equals( CBreakpointPreferenceStore.IGNORE_COUNT ) ) {
breakpoint.setIgnoreCount( getPreferenceStore().getInt( CBreakpointPreferenceStore.IGNORE_COUNT ) );
}
else if ( property.equals( CBreakpointPreferenceStore.CONDITION ) ) {
breakpoint.setCondition( getPreferenceStore().getString( CBreakpointPreferenceStore.CONDITION ) );
}
else if ( property.equals( CBreakpointPreferenceStore.LINE ) ) {
// already workspace runnable, setting markers are safe
breakpoint.getMarker().setAttribute(IMarker.LINE_NUMBER, getPreferenceStore().getInt(CBreakpointPreferenceStore.LINE));
} else {
// this allow set attributes contributed by other plugins
String value = getPropertyAsString(property);
breakpoint.getMarker().setAttribute(property, value);
}
}
}
};
try {
ResourcesPlugin.getWorkspace().run( wr, null );
}
catch( CoreException ce ) {
CDebugUIPlugin.log( ce );
}
}
/**
* Creates field editors contributed using breakpointUIContribution extension point
* @param breakpoint
*/
private void createContributetedFieldEditors(ICBreakpoint breakpoint) {
Composite parent = getFieldEditorParent();
try {
ICBreakpointsUIContribution cons[] = CBreakpointUIContributionFactory.getInstance()
.getBreakpointUIContributions(breakpoint);
for (ICBreakpointsUIContribution con : cons) {
FieldEditor fieldEditor = con.getFieldEditor(con.getId(), con.getLabel()+":", parent); //$NON-NLS-1$
if (fieldEditor != null)
addField(fieldEditor);
Object o = breakpoint.getMarker().getAttribute(con.getId());
String value = o==null?"":o.toString(); //$NON-NLS-1$
getPreferenceStore().setValue(con.getId(), value);
}
} catch (CoreException ce) {
CDebugUIPlugin.log(ce);
}
}
/**
* Return string value of given property or null.
*/
protected String getPropertyAsString(String property) {
// currently only supports String and Integer
IPreferenceStore store = getPreferenceStore();
if (store.contains(property)) {
String value = store.getString(property);
return value;
} else return null;
}
}