/******************************************************************************* * Copyright (c) 2009 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 API and implementation *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.breakpoints; 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.ICFunctionBreakpoint; import org.eclipse.cdt.debug.core.model.ICTracepoint; import org.eclipse.cdt.debug.ui.preferences.ReadOnlyFieldEditor; import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; import org.eclipse.core.resources.IMarker; 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 GDB tracepoint as preferences. * A TracepointPreferenceStore is used to interface between this page and the tracepoint. */ public class GDBTracepointPropertyPage extends FieldEditorPreferencePage implements IWorkbenchPropertyPage { class TracepointIntegerFieldEditor extends IntegerFieldEditor { public TracepointIntegerFieldEditor(String name, String labelText, Composite parent) { super(name, labelText, parent); setErrorMessage(Messages.TracepointPropertyPage_integer_negative); } /** * @see IntegerFieldEditor#checkState() */ @Override protected boolean checkState() { Text control = getTextControl(); if (!control.isEnabled()) { clearErrorMessage(); return true; } return super.checkState(); } /** * Only store if the text control is enabled * * @see FieldEditor#doStore() */ @Override 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. */ @Override protected void clearErrorMessage() { if (getPage() != null) { String message = getPage().getErrorMessage(); if ( message != null ) { if (getErrorMessage().equals(message)) { super.clearErrorMessage(); } } else { super.clearErrorMessage(); } } } } class TracepointStringFieldEditor extends StringFieldEditor { public TracepointStringFieldEditor(String name, String labelText, Composite parent) { super(name, labelText, parent); } /** * @see StringFieldEditor#checkState() */ @Override protected boolean checkState() { Text control = getTextControl(); if (!control.isEnabled()) { clearErrorMessage(); return true; } return super.checkState(); } @Override 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. */ @Override 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 TracepointStringFieldEditor fCondition; private Text fIgnoreCountTextControl; private TracepointIntegerFieldEditor fIgnoreCount; private Text fPassCountTextControl; private TracepointIntegerFieldEditor fPassCount; private IAdaptable fElement; /** * The "fake" preference store used to interface between * the tracepoint and the tracepoint preference page. */ private TracepointPreferenceStore fTracepointPreferenceStore; /** * Constructor for GDBTracepointPropertyPage. * */ public GDBTracepointPropertyPage() { super( GRID ); noDefaultAndApplyButton(); fTracepointPreferenceStore = new TracepointPreferenceStore(); } /* * (non-Javadoc) * * @see org.eclipse.jface.preference.FieldEditorPreferencePage#createFieldEditors() */ @Override protected void createFieldEditors() { ICTracepoint tracepoint = getTracepoint(); createMainLabel(tracepoint); createTypeSpecificLabelFieldEditors(tracepoint); createEnabledField(getFieldEditorParent()); IPreferenceStore store = getPreferenceStore(); try { String condition = tracepoint.getCondition(); if ( condition == null ) { condition = ""; //$NON-NLS-1$ } store.setValue(TracepointPreferenceStore.CONDITION, condition); createConditionEditor(getFieldEditorParent()); store.setValue(TracepointPreferenceStore.ENABLED, tracepoint.isEnabled()); // GDB does not support ignore count right now // int ignoreCount = tracepoint.getIgnoreCount(); // store.setValue(TracepointPreferenceStore.IGNORE_COUNT, (ignoreCount >= 0) ? ignoreCount : 0); // createIgnoreCountEditor(getFieldEditorParent()); int passCount = tracepoint.getPassCount(); store.setValue(TracepointPreferenceStore.PASS_COUNT, (passCount >= 0) ? passCount : 0); createPassCountEditor(getFieldEditorParent()); } catch( CoreException ce ) { GdbUIPlugin.log(ce); } } private void createMainLabel(ICTracepoint tracepoint) { addField(createLabelEditor(getFieldEditorParent(), Messages.TracepointPropertyPage_Class, getTracepointMainLabel(tracepoint))); } /** * Method createTypeSpecificLabelFieldEditors. * * @param tracepoint */ private void createTypeSpecificLabelFieldEditors(ICTracepoint tracepoint) { if (tracepoint instanceof ICFunctionBreakpoint) { ICFunctionBreakpoint ftrpt = (ICFunctionBreakpoint)tracepoint; String function = Messages.TracepointPropertyPage_NotAvailable; try { function = ftrpt.getFunction(); } catch(CoreException e) { GdbUIPlugin.log(e); } if (function != null) { addField(createLabelEditor(getFieldEditorParent(), Messages.TracepointPropertyPage_FunctionName, function)); } } else if (tracepoint instanceof ICAddressBreakpoint) { ICAddressBreakpoint atrpt = (ICAddressBreakpoint)tracepoint; String address = Messages.TracepointPropertyPage_NotAvailable; try { address = atrpt.getAddress(); } catch(CoreException e) { GdbUIPlugin.log(e); } if (address != null) { addField(createLabelEditor(getFieldEditorParent(), Messages.TracepointPropertyPage_Address, address)); } } else { // LineTracepoint String fileName = null; try { fileName = tracepoint.getSourceHandle(); } catch(CoreException e) { GdbUIPlugin.log(e); } if (fileName != null) { addField(createLabelEditor(getFieldEditorParent(), Messages.TracepointPropertyPage_File, fileName)); } ILineBreakpoint ltrpt = tracepoint; int lNumber = 0; try { lNumber = ltrpt.getLineNumber(); } catch (CoreException e) { GdbUIPlugin.log(e); } if (lNumber > 0) { getPreferenceStore().setValue(TracepointPreferenceStore.LINE, lNumber); createLineNumberEditor(getFieldEditorParent()); } } } private String getTracepointMainLabel(ICTracepoint tracepoint) { if (tracepoint instanceof ICFunctionBreakpoint) return Messages.TracepointPropertyPage_FunctionTracepoint; if (tracepoint instanceof ICAddressBreakpoint) return Messages.TracepointPropertyPage_AddressTracepoint; return Messages.TracepointPropertyPage_LineTracepoint; } protected void createLineNumberEditor(Composite parent) { String title = Messages.TracepointPropertyPage_LineNumber; TracepointIntegerFieldEditor labelFieldEditor = new TracepointIntegerFieldEditor(TracepointPreferenceStore.LINE ,title, parent); labelFieldEditor.setValidRange(1, Integer.MAX_VALUE); addField(labelFieldEditor); } protected void createEnabledField(Composite parent) { fEnabled = new BooleanFieldEditor(TracepointPreferenceStore.ENABLED, Messages.TracepointPropertyPage_Enabled, parent); addField(fEnabled); } protected void createConditionEditor( Composite parent ) { fCondition = new TracepointStringFieldEditor(TracepointPreferenceStore.CONDITION, Messages.TracepointPropertyPage_Condition, parent); fCondition.setEmptyStringAllowed(true); fCondition.setErrorMessage(Messages.TracepointPropertyPage_InvalidCondition); addField(fCondition); } protected void createIgnoreCountEditor(Composite parent) { fIgnoreCount = new TracepointIntegerFieldEditor(TracepointPreferenceStore.IGNORE_COUNT, Messages.TracepointPropertyPage_IgnoreCount, parent); fIgnoreCount.setValidRange(0, Integer.MAX_VALUE); fIgnoreCountTextControl = fIgnoreCount.getTextControl(parent); try { fIgnoreCountTextControl.setEnabled(getTracepoint().getIgnoreCount() >= 0); } catch(CoreException ce) { GdbUIPlugin.log(ce); } addField(fIgnoreCount); } protected void createPassCountEditor(Composite parent) { fPassCount = new TracepointIntegerFieldEditor(TracepointPreferenceStore.PASS_COUNT, Messages.TracepointPropertyPage_PassCount, parent); fPassCount.setValidRange(0, Integer.MAX_VALUE); fPassCountTextControl = fPassCount.getTextControl(parent); try { fPassCountTextControl.setEnabled(getTracepoint().getPassCount() >= 0); } catch(CoreException ce) { GdbUIPlugin.log(ce); } addField(fPassCount); } protected FieldEditor createLabelEditor(Composite parent, String title, String value) { return new LabelFieldEditor(parent, title, value); } protected ICTracepoint getTracepoint() { IAdaptable element = getElement(); return (element instanceof ICTracepoint) ? (ICTracepoint)element : (ICTracepoint)element.getAdapter(ICTracepoint.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; } @Override public IPreferenceStore getPreferenceStore() { return fTracepointPreferenceStore; } @Override public boolean performOk() { final List<String> changedProperties = new ArrayList<String>(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<String> changedProperties) { IWorkspaceRunnable wr = new IWorkspaceRunnable() { public void run( IProgressMonitor monitor ) throws CoreException { ICTracepoint tracepoint = getTracepoint(); Iterator<String> changed = changedProperties.iterator(); while(changed.hasNext()) { String property = changed.next(); if (property.equals(TracepointPreferenceStore.ENABLED)) { tracepoint.setEnabled(getPreferenceStore().getBoolean(TracepointPreferenceStore.ENABLED)); } else if (property.equals(TracepointPreferenceStore.IGNORE_COUNT)) { tracepoint.setIgnoreCount(getPreferenceStore().getInt(TracepointPreferenceStore.IGNORE_COUNT)); } else if (property.equals(TracepointPreferenceStore.PASS_COUNT)) { tracepoint.setPassCount(getPreferenceStore().getInt(TracepointPreferenceStore.PASS_COUNT)); } else if (property.equals(TracepointPreferenceStore.CONDITION)) { tracepoint.setCondition(getPreferenceStore().getString(TracepointPreferenceStore.CONDITION)); } else if (property.equals(TracepointPreferenceStore.LINE)) { // already workspace runnable, setting markers are safe tracepoint.getMarker().setAttribute(IMarker.LINE_NUMBER, getPreferenceStore().getInt(TracepointPreferenceStore.LINE)); } else { // this allow set attributes contributed by other plugins String value = getPropertyAsString(property); tracepoint.getMarker().setAttribute(property, value); } } } }; try { ResourcesPlugin.getWorkspace().run(wr, null); } catch(CoreException ce) { GdbUIPlugin.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; } }