diff options
author | Scott Tepavich | 2012-04-05 22:55:05 +0000 |
---|---|---|
committer | Eugene Tarassov | 2012-04-06 14:40:57 +0000 |
commit | 07fd3cb8c028dba668ee4905f76b3a024d950e75 (patch) | |
tree | 4e76bc9a0cfcd43be7a382656b02f870a895a936 /plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse | |
parent | 8cc2f35200a7335e7292f9f6554f0cefa5eb3183 (diff) | |
download | org.eclipse.tcf-07fd3cb8c028dba668ee4905f76b3a024d950e75.tar.gz org.eclipse.tcf-07fd3cb8c028dba668ee4905f76b3a024d950e75.tar.xz org.eclipse.tcf-07fd3cb8c028dba668ee4905f76b3a024d950e75.zip |
Bug [374603] Allow a user to set a BP filter.
Diffstat (limited to 'plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse')
6 files changed, 781 insertions, 36 deletions
diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/Messages.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/Messages.java new file mode 100644 index 000000000..3c8394866 --- /dev/null +++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/Messages.java @@ -0,0 +1,24 @@ +package org.eclipse.tcf.internal.cdt.ui.breakpoints; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.tcf.internal.cdt.ui.breakpoints.messages"; //$NON-NLS-1$ + + public static String TCFThreadFilterQueryExpressionStore; + public static String TCFThreadFilterQueryModeButtonState; + public static String TCFThreadFilterQueryButtonBasic; + public static String TCFThreadFilterQueryButtonAdvanced; + public static String TCFThreadFilterQueryButtonEdit; + public static String TCFThreadFilterQueryAdvancedLabel; + public static String TCFThreadFilterQueryTreeViewLabel; + public static String TCFThreadFilterEditorFormatError; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeExtension.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeExtension.java index e46fe00ca..cb077407f 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeExtension.java +++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeExtension.java @@ -23,6 +23,7 @@ import org.eclipse.tcf.internal.debug.model.TCFBreakpointsModel; public class TCFBreakpointScopeExtension implements ICBreakpointExtension { private String[] fContextIds; + private String fProperties; private ICBreakpoint fBreakpoint; public void initialize(ICBreakpoint breakpoint) throws CoreException { @@ -31,6 +32,7 @@ public class TCFBreakpointScopeExtension implements ICBreakpointExtension { if (m != null && m.exists()) { String contextIdAttr = m.getAttribute(TCFBreakpointsModel.ATTR_CONTEXTIDS, null); if (contextIdAttr != null) fContextIds = contextIdAttr.split(",\\s*"); + fProperties = m.getAttribute(TCFBreakpointsModel.ATTR_CONTEXT_QUERY, null); } } @@ -64,6 +66,23 @@ public class TCFBreakpointScopeExtension implements ICBreakpointExtension { catch (Exception e) { Activator.log(e); } + } + public void setPropertiesFilter(String properties) { + fProperties = properties; + if (fBreakpoint == null) return; + try { + ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + final IMarker m = fBreakpoint.getMarker(); + if (m == null || !m.exists()) return; + if (fProperties.length() != 0) + m.setAttribute(TCFBreakpointsModel.ATTR_CONTEXT_QUERY, fProperties); + } + }, null); + } + catch (Exception e) { + Activator.log(e); + } } public String[] getThreadFilters() { diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointThreadFilterPage.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointThreadFilterPage.java index eec02a39f..c5fc06a52 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointThreadFilterPage.java +++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointThreadFilterPage.java @@ -14,7 +14,6 @@ package org.eclipse.tcf.internal.cdt.ui.breakpoints; import org.eclipse.cdt.debug.core.model.ICBreakpoint; import org.eclipse.core.runtime.CoreException; import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; @@ -31,13 +30,11 @@ public class TCFBreakpointThreadFilterPage extends PropertyPage { @Override protected Control createContents(Composite parent) { noDefaultAndApplyButton(); - Composite mainComposite = new Composite(parent, SWT.NONE); - mainComposite.setFont(parent.getFont()); - mainComposite.setLayout(new GridLayout()); - mainComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); - createThreadFilterEditor(mainComposite); + Composite fieldEditorComposite = new Composite(parent, SWT.NONE); + fieldEditorComposite.setLayout( new GridLayout(1, false)); + createThreadFilterEditor(fieldEditorComposite); setValid(true); - return mainComposite; + return fieldEditorComposite; } protected ICBreakpoint getBreakpoint() { diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFContextQueryExpressionDialog.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFContextQueryExpressionDialog.java new file mode 100644 index 000000000..7518a917c --- /dev/null +++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFContextQueryExpressionDialog.java @@ -0,0 +1,342 @@ +package org.eclipse.tcf.internal.cdt.ui.breakpoints; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ColumnViewer; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.jface.viewers.ICellEditorListener; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableLayout; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Table; + +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.SelectionDialog; + +public class TCFContextQueryExpressionDialog extends SelectionDialog { + + private String expression; + private String[] attributeList; + private ParameterDataModel[] parameterData; + final String[] columnNames = new String[] {"Parameter","Value"}; + + protected TCFContextQueryExpressionDialog(Shell parentShell, String[] attributes, String initialExpression) { + super(parentShell); + setShellStyle(getShellStyle() | SWT.RESIZE); + expression = initialExpression; + attributeList = attributes; + } + + String getParameterInitialValue (String comparator, int initIndex){ + if (expression != null && expression.length() > 0) { + int indexExpr = expression.indexOf (comparator, initIndex); + if (indexExpr != -1){ + // Make sure we didn't partial match to another parameter name. + if (indexExpr != 0) { + String testChar = expression.substring(indexExpr-1, indexExpr); + if (!testChar.equals(",")) { + return getParameterInitialValue(comparator,indexExpr+1); + } + } + int startOfVal = expression.indexOf ('=', indexExpr) + 1; + int endOfVal = -1; + if (startOfVal != 0) { + endOfVal = expression.indexOf (',', startOfVal); + if (endOfVal == -1) { + endOfVal = expression.length(); + } + } + return expression.substring(startOfVal, endOfVal); + } + } + return null; + } + + /** + * + * ParameterDataModel - Data to populate table view. + * + */ + public static class ParameterDataModel { + + private String attribute; + private String value; + + public ParameterDataModel(String label) { + attribute = label; + value =""; + } + + public String getLabel() { + return attribute; + } + + public void setLabel(String label) { + attribute = label; + } + + public String getData() { + return value; + } + + public void setData(Object data) { + if (data != null) { + value = (String)data; + } + else { + value = ""; + } + } + } + + ParameterDataModel[] setupTableList() { + parameterData = new ParameterDataModel[attributeList.length]; + for (int i = 0; i < attributeList.length; i++) { + parameterData[i] = new ParameterDataModel(attributeList[i]); + + String initialValue = getParameterInitialValue((String)attributeList[i], 0); + if (initialValue!= null){ + parameterData[i].setData(initialValue); + } + } + return parameterData; + } + + public final class ParameterTableLabelProvider extends LabelProvider implements ITableLabelProvider { + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + public String getColumnText(Object element, int columnIndex) { + ParameterDataModel data = (ParameterDataModel) element; + switch (columnIndex) { + case 0: + return data.getLabel(); + case 1: + return data.getData(); + default: + return ""; + } + } + } + + public class ValueCellEditor extends TextCellEditor { + private Object tableElement; + public ValueCellEditor(Composite parent) { + super(parent); + tableElement = null; + } + public ValueCellEditor(Composite parent, int style) { + super(parent, style); + tableElement = null; + } + public void setTableElement( Object element) { + tableElement = element; + } + public Object getTableElement() { + return tableElement; + } + } + + int findParameter(String comparator, int initIndex) { + int indexExpr = -1; + if (expression != null && expression.length() > 0) { + indexExpr = expression.indexOf (comparator, initIndex); + if (indexExpr != -1){ + // Make sure we didn't partial match to another parameter name. + if (indexExpr != 0) { + String testChar = expression.substring(indexExpr-1, indexExpr); + if (!testChar.equals(",")) { + return findParameter(comparator,indexExpr+1); + } + } + } + } + return indexExpr; + } + + public final class CellEditorListener implements ICellEditorListener { + private ValueCellEditor fcellEditor; + public CellEditorListener(ValueCellEditor cellEditor) { + fcellEditor = cellEditor; + } + public void applyEditorValue() { + String cellString = null; + Object obj = fcellEditor.getValue(); + ParameterDataModel param = (ParameterDataModel)fcellEditor.getTableElement(); + String paramName = param.getLabel(); + if (obj != null) { + cellString = (String)obj; + } + if (cellString == null) { + return; + } + cellString = cellString.trim(); + if (cellString.length() != 0) { + if (expression == null || expression.length() == 0) { + expression = new String(paramName + "=" + cellString); + } + else { + String nameValuePair = paramName + "=" + cellString ; + if (expression.lastIndexOf(nameValuePair) == -1) { + expression +=","; + expression += nameValuePair; + } + } + param.setData(cellString); + getButton(IDialogConstants.OK_ID).setEnabled(true); + } + else if (expression != null && expression.length() != 0){ + fcellEditor.setValue(cellString); + // Check to remove expression value. + int strIndex = findParameter(paramName, 0); + if (strIndex != -1) { + if (strIndex != 0) { + String testChar = expression.substring(strIndex+paramName.length(), strIndex+1+paramName.length()); + if (!testChar.equals("=")) { + // malformed expression + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } + testChar = expression.substring(strIndex-1, strIndex); + if (!testChar.equals(",")) { + // malformed expression + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } + else { + strIndex-=1; + } + } + int endLocation = expression.indexOf(',', strIndex+1); + if (endLocation == -1) { + endLocation = expression.length(); + } + String removeStr = expression.substring(strIndex, endLocation); + expression = expression.replace(removeStr, ""); + param.setData(""); + } + } + if (expression != null && expression.length() == 0) { + getButton(IDialogConstants.OK_ID).setEnabled(false); + } + else { + getButton(IDialogConstants.OK_ID).setEnabled(true); + } + } + + public void cancelEditor() { + } + public void editorValueChanged(boolean oldValidState, boolean newValidState) { + } + } + + public final class ExpressionEditingSupport extends EditingSupport { + + private ValueCellEditor cellEditor = null; + private ColumnViewer fviewer; + + private ExpressionEditingSupport(ColumnViewer viewer) { + super(viewer); + fviewer = viewer; + cellEditor = new ValueCellEditor((Composite) getViewer().getControl(), SWT.NONE); + cellEditor.addListener(new CellEditorListener(cellEditor)); + } + + @Override + protected CellEditor getCellEditor(Object element) { + cellEditor.setTableElement(element); + return cellEditor; + } + + @Override + protected boolean canEdit(Object element) { + return true; + } + + @Override + protected Object getValue(Object element) { + if (element instanceof ParameterDataModel) { + ParameterDataModel data = (ParameterDataModel)element; + return data.getData(); + } + return null; + } + + @Override + protected void setValue(Object element, Object value) { + if (element instanceof ParameterDataModel) { + ParameterDataModel data = (ParameterDataModel) element; + data.setData(value); + fviewer.update(element, null); + } + } + } + + protected Control createDialogArea(Composite parent) { + Composite page = new Composite(parent, SWT.NONE); + GridLayout gridLayout = new GridLayout(1, true); + page.setLayout(gridLayout); + page.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + TableLayout tableLayout = new TableLayout(); + tableLayout.addColumnData(new ColumnWeightData(1)); + tableLayout.addColumnData(new ColumnWeightData(1)); + Table table = new Table(parent, SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL); + table.setLinesVisible(true); + table.setHeaderVisible(true); + table.setLayout(tableLayout); + TableViewer tableViewer = new TableViewer(table); + tableViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + Control cntrl = tableViewer.getControl(); + cntrl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + TableViewerColumn labelColumn = new TableViewerColumn(tableViewer, SWT.NONE); + labelColumn.getColumn().setText(columnNames[0]); + TableViewerColumn valueColumn = new TableViewerColumn(tableViewer, SWT.Modify); + valueColumn.getColumn().setText(columnNames[1]); + tableViewer.setContentProvider(new ArrayContentProvider()); + tableViewer.setLabelProvider(new ParameterTableLabelProvider()); + valueColumn.setEditingSupport(new ExpressionEditingSupport(valueColumn.getViewer())); + tableViewer.setInput(setupTableList()); + tableViewer.setComparator(new ViewerComparator() { + public int compare(Viewer viewer, Object e1, Object e2) { + ParameterDataModel t1 = (ParameterDataModel) e1; + ParameterDataModel t2 = (ParameterDataModel) e2; + return t1.getLabel().compareTo(t2.getLabel()); + }; + }); + return parent; + } + + public String getExpression() { + return expression; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets + * .Shell) + */ + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Select Expression Parameters"); + } + + public void create() { + super.create(); + getButton(IDialogConstants.OK_ID).setEnabled(false); + } +} diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFThreadFilterEditor.java b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFThreadFilterEditor.java index b32c5e12a..70c694777 100644 --- a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFThreadFilterEditor.java +++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFThreadFilterEditor.java @@ -18,12 +18,20 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.eclipse.cdt.debug.core.model.ICBreakpoint; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; @@ -31,18 +39,35 @@ import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StackLayout; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.internal.cdt.ui.Activator; import org.eclipse.tcf.internal.cdt.ui.ImageCache; +import org.eclipse.tcf.internal.debug.model.TCFBreakpointsModel; import org.eclipse.tcf.internal.debug.model.TCFLaunch; import org.eclipse.tcf.internal.debug.ui.model.TCFChildren; import org.eclipse.tcf.internal.debug.ui.model.TCFModel; import org.eclipse.tcf.internal.debug.ui.model.TCFModelManager; import org.eclipse.tcf.internal.debug.ui.model.TCFNode; import org.eclipse.tcf.internal.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tcf.protocol.IChannel; +import org.eclipse.tcf.protocol.IToken; +import org.eclipse.tcf.services.IContextQuery; import org.eclipse.tcf.services.IRunControl; import org.eclipse.tcf.util.TCFDataCache; import org.eclipse.tcf.util.TCFTask; @@ -227,7 +252,6 @@ public class TCFThreadFilterEditor { } } - private TCFBreakpointThreadFilterPage fPage; private CheckboxTreeViewer fThreadViewer; private final ThreadFilterContentProvider fContentProvider; @@ -235,33 +259,325 @@ public class TCFThreadFilterEditor { private final List<Context> fContexts = new ArrayList<Context>(); private final Map<TCFLaunch, Context[]> fContainersPerLaunch = new HashMap<TCFLaunch, Context[]>(); private final Map<Context, Context[]> fContextsPerContainer = new HashMap<Context, Context[]>(); - + private StackLayout stackLayout; + private Composite basicPage; + private Composite advancedPage; + private Combo scopeExprCombo; + private ControlDecoration scopeExpressionDecoration; + private Button radioBasic; + private Button radioAdvanced; + + public class ScopingModeListener implements SelectionListener { + private Composite fParent; + + public ScopingModeListener(Composite parent) { + fParent = parent; + } + public void widgetSelected(SelectionEvent e) { + if (radioBasic.getSelection()) { + stackLayout.topControl = basicPage; + } + else { + stackLayout.topControl = advancedPage; + } + fParent.layout(); + } + public void widgetDefaultSelected(SelectionEvent e) { + } + } + + /** + * Returns the dialog settings or <code>null</code> if none + * + * @param create + * whether to create the settings + */ + private IDialogSettings getDialogSettings(boolean create) { + IDialogSettings settings = Activator.getDefault() + .getDialogSettings(); + IDialogSettings section = settings.getSection(this.getClass() + .getName()); + if (section == null & create) { + section = settings.addNewSection(this.getClass().getName()); + } + return section; + } + public TCFThreadFilterEditor(Composite parent, TCFBreakpointThreadFilterPage page) { fPage = page; fContentProvider = new ThreadFilterContentProvider(); fCheckHandler = new CheckHandler(); - createThreadViewer(parent); + Composite buttonComposite = new Composite(parent, SWT.NONE); + buttonComposite.setLayout( new GridLayout(3, false)); + buttonComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + Composite mainComposite = new Composite(parent, SWT.NONE); + mainComposite.setFont(parent.getFont()); + stackLayout = new StackLayout(); + mainComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + mainComposite.setLayout(stackLayout); + + radioBasic = new Button(buttonComposite, SWT.RADIO); + radioBasic.setText(Messages.TCFThreadFilterQueryButtonBasic); + radioBasic.addSelectionListener(new ScopingModeListener(mainComposite)); + radioAdvanced = new Button(buttonComposite, SWT.RADIO); + radioAdvanced.setText(Messages.TCFThreadFilterQueryButtonAdvanced); + radioAdvanced.addSelectionListener(new ScopingModeListener(mainComposite)); + + IDialogSettings settings= getDialogSettings(false); + if (settings != null) { + boolean basicSelected = settings.getBoolean(Messages.TCFThreadFilterQueryModeButtonState); + if ( basicSelected ) { + radioBasic.setSelection(true); + } + else { + radioAdvanced.setSelection(true); + } + } + else { + radioBasic.setSelection(true); + } + createThreadViewer(mainComposite); } protected TCFBreakpointThreadFilterPage getPage() { return fPage; } + + private String getBPFilterExpression() { + String expression = null; + ICBreakpoint bp = (ICBreakpoint)fPage.getElement().getAdapter(ICBreakpoint.class); + if (bp != null) { + IMarker marker = bp.getMarker(); + if (marker != null) { + try { + expression = (String)marker.getAttribute(TCFBreakpointsModel.ATTR_CONTEXT_QUERY); + } + catch (CoreException e) { + e.printStackTrace(); + } + } + } + + return expression; + } + + private String[] getAvailableAttributes() { + String[] result = null; + TCFLaunch launch = (TCFLaunch)getAttributeLaunch(); + if (launch == null) { + return result; + } + final IChannel channel = launch.getChannel(); + if (channel == null) { + return result; + } + result = new TCFTask<String[]>() { + public void run() { + IContextQuery service = channel.getRemoteService(IContextQuery.class); + service.getAttrNames(new IContextQuery.DoneGetAttrNames() { + public void doneGetAttrNames(IToken token, Exception error, String[] attributes) { + if (error != null) { + done(null); + } + done(attributes); + } + }); + return; + } + }.getE(); + return result; + } + + boolean missingParameterValue(String expression) { + boolean result = false; + int lastIndex = expression.length(); + int fromIndex = 0; + if (lastIndex != 0) { + fromIndex = expression.indexOf('=', fromIndex); + if (fromIndex == -1) { + result = true; + } + else { + fromIndex = 0; + } + while (fromIndex != -1) { + fromIndex = expression.indexOf('=', fromIndex); + if (fromIndex != -1) { + if (fromIndex == 0 || fromIndex == lastIndex-1) { + result = true; + break; + } + else { + String testChar = expression.substring(fromIndex-1, fromIndex); + String testNextChar = expression.substring(fromIndex+1,fromIndex+2); + int foundComma = expression.indexOf(',', fromIndex); + if (testChar.matches("[,\\s]") || testNextChar.matches("[,\\s]")) { + result = true; + break; + } + else if (foundComma != -1 && expression.indexOf('=', fromIndex) != -1) { + result = true; + } + else { + result = false; + } + fromIndex++; + } + } + } + } + return result; + } + private class ExpressionModifier implements ModifyListener { + public void modifyText(ModifyEvent e) { + String expression = scopeExprCombo.getText(); + if (missingParameterValue(expression)) { + scopeExpressionDecoration.show(); + fPage.setErrorMessage(Messages.TCFThreadFilterEditorFormatError); + fPage.setValid(false); + } + else { + scopeExpressionDecoration.hide(); + fPage.setErrorMessage(null); + fPage.setValid(true); + } + } + } + + private class ExpressionSelectButton implements Listener { + + private Shell parentShell; + + public ExpressionSelectButton(Shell shell) { + parentShell = shell; + } + + public void handleEvent(Event event) { + String[] attrsList = getAvailableAttributes(); + String result = null; + TCFContextQueryExpressionDialog dlg = new TCFContextQueryExpressionDialog(parentShell, attrsList, scopeExprCombo.getText()); + + if (dlg.open() == Window.OK) { + result = dlg.getExpression(); + } + if (result != null) { + scopeExprCombo.setText(result); + } + } + } + + private void setupScopeExpressionCombo(IDialogSettings settings, String bpContextQuery) { + String [] expresionList = null; + if ( settings != null ) { + expresionList = settings.getArray(Messages.TCFThreadFilterQueryExpressionStore); + if ( expresionList != null ) { + int index; + // Find if there is a null entry. + for(index = 0; index < expresionList.length; index++) { + String member = expresionList[index]; + if (member == null || member.length() == 0) { + break; + } + } + String[] copyList = new String[index]; + int found = -1; + for (int loop = 0; loop < index; loop++) { + copyList[loop] = expresionList[loop]; + if (bpContextQuery != null && copyList[loop].equals(bpContextQuery)) { + found = loop; + } + } + if (found != -1) { + scopeExprCombo.setItems(copyList); + scopeExprCombo.select(found); + } + else { + int pad = 0; + if (bpContextQuery != null) { + pad = 1; + } + String[] setList = new String[index+pad]; + if (bpContextQuery != null) { + setList[0] = bpContextQuery; + } + System.arraycopy(copyList, 0, setList, pad, copyList.length); + scopeExprCombo.setItems(setList); + if (bpContextQuery != null) { + scopeExprCombo.select(0); + } + } + } + else if (bpContextQuery != null) { + scopeExprCombo.setItems(new String[]{bpContextQuery}); + scopeExprCombo.select(0); + } + } + else if (bpContextQuery != null) { + scopeExprCombo.setItems(new String[]{bpContextQuery}); + scopeExprCombo.select(0); + } + } + private void createThreadViewer(Composite parent) { - Label label = new Label(parent, SWT.NONE); - label.setText("Restrict to Selected Contexts:"); //$NON-NLS-1$ - label.setFont(parent.getFont()); - label.setLayoutData(new GridData()); + GridData twoColumnLayout = new GridData(SWT.FILL,0, true, false); + twoColumnLayout.horizontalSpan = 2; + advancedPage = new Composite(parent,SWT.NONE); + advancedPage.setLayout(new GridLayout(2,false)); + advancedPage.setFont(parent.getFont()); + Label epressionLabel = new Label(advancedPage, SWT.NONE); + epressionLabel.setText(Messages.TCFThreadFilterQueryAdvancedLabel); + epressionLabel.setFont(advancedPage.getFont()); + epressionLabel.setLayoutData(twoColumnLayout); + scopeExprCombo = new Combo(advancedPage,SWT.DROP_DOWN); + GridData comboGridData = new GridData(SWT.FILL,0, true, false); + comboGridData .horizontalIndent = 5; + scopeExprCombo.setLayoutData(comboGridData); + scopeExprCombo.addModifyListener(new ExpressionModifier()); + scopeExpressionDecoration = new ControlDecoration(scopeExprCombo, SWT.LEFT, advancedPage); + scopeExpressionDecoration.hide(); + scopeExpressionDecoration.setDescriptionText(Messages.TCFThreadFilterEditorFormatError); + FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR); + scopeExpressionDecoration.setImage(fieldDecoration.getImage()); + + String bpContextQuery = getBPFilterExpression(); + IDialogSettings settings= getDialogSettings(false); + setupScopeExpressionCombo(settings, bpContextQuery); + Button selectExpression = new Button(advancedPage, SWT.PUSH); + selectExpression.setText(Messages.TCFThreadFilterQueryButtonEdit); + selectExpression.setLayoutData(new GridData(SWT.RIGHT,0, false, false)); + selectExpression.addListener(SWT.Selection, new ExpressionSelectButton(parent.getShell())); + + basicPage = new Composite(parent, SWT.NONE); + basicPage .setLayout(new GridLayout(1,false)); + basicPage .setFont(parent.getFont()); + Label contextTreeLabel = new Label(basicPage, SWT.NONE); + contextTreeLabel.setText(Messages.TCFThreadFilterQueryTreeViewLabel); //$NON-NLS-1$ + contextTreeLabel.setFont(basicPage.getFont()); + contextTreeLabel.setLayoutData(new GridData(SWT.FILL,0, true, false)); GridData data = new GridData(GridData.FILL_BOTH); data.heightHint = 100; - fThreadViewer = new CheckboxTreeViewer(parent, SWT.BORDER); + fThreadViewer = new CheckboxTreeViewer(basicPage, SWT.BORDER); fThreadViewer.addCheckStateListener(fCheckHandler); fThreadViewer.getTree().setLayoutData(data); - fThreadViewer.getTree().setFont(parent.getFont()); + fThreadViewer.getTree().setFont(basicPage.getFont()); fThreadViewer.setContentProvider(fContentProvider); fThreadViewer.setLabelProvider(new ThreadFilterLabelProvider()); fThreadViewer.setInput(DebugPlugin.getDefault().getLaunchManager()); - setInitialCheckedState(); + setInitialCheckedState(); + + if (radioBasic.getSelection()) { + stackLayout.topControl = basicPage; + } + else { + stackLayout.topControl = advancedPage; + } + parent.layout(); + } + + protected ILaunch getAttributeLaunch() { + IAdaptable dbgContext = DebugUITools.getDebugContext(); + return (ILaunch)dbgContext.getAdapter(ILaunch.class); } protected ILaunch[] getLaunches() { @@ -303,6 +619,10 @@ public class TCFThreadFilterEditor { protected final CheckboxTreeViewer getThreadViewer() { return fThreadViewer; } + + protected final String getScopeExpression() { + return scopeExprCombo.getText(); + } /** * Sets the initial checked state of the tree viewer. The initial state @@ -357,29 +677,64 @@ public class TCFThreadFilterEditor { } return null; } - - protected void doStore() { - CheckboxTreeViewer viewer = getThreadViewer(); - Object[] elements = viewer.getCheckedElements(); - String[] threadIds; - List<String> checkedIds = new ArrayList<String>(); - for (int i = 0; i < elements.length; ++i) { - if (elements[i] instanceof Context) { - Context ctx = (Context) elements[i]; - if (!viewer.getGrayed(ctx)) { - checkedIds.add(ctx.fScopeId); - } + + void updateExpressionsDialogSettings(IDialogSettings settings, String scopedExpression) { + String[] list = settings.getArray(Messages.TCFThreadFilterQueryExpressionStore); + if (list == null) { + list = new String[20]; + } + for(int i=0; i < list.length; i++) { + String member = list[i]; + if (member != null && member.equals(scopedExpression)) { + return; + } + else if (member == null) { + list[i] = scopedExpression; + settings.put(Messages.TCFThreadFilterQueryExpressionStore, list); + return; } } - if (checkedIds.size() == fContexts.size()) { - threadIds = null; + String[] copyList = new String[20]; + copyList[0] = scopedExpression; + System.arraycopy(list, 0, copyList, 1, list.length-1); + settings.put(Messages.TCFThreadFilterQueryExpressionStore, copyList); + } + + protected void doStore() { + IDialogSettings settings= getDialogSettings(true); + if (settings != null) { + settings.put(Messages.TCFThreadFilterQueryModeButtonState, radioBasic.getSelection()); } - else { - threadIds = checkedIds.toArray(new String[checkedIds.size()]); + if (radioAdvanced.getSelection()) { + String scopedExpression = getScopeExpression(); + updateExpressionsDialogSettings(settings, scopedExpression); + TCFBreakpointScopeExtension filterExtension = fPage.getFilterExtension(); + if (filterExtension == null) return; + filterExtension.setPropertiesFilter(scopedExpression); + } + if (radioBasic.getSelection()) { + CheckboxTreeViewer viewer = getThreadViewer(); + Object[] elements = viewer.getCheckedElements(); + String[] threadIds; + List<String> checkedIds = new ArrayList<String>(); + for (int i = 0; i < elements.length; ++i) { + if (elements[i] instanceof Context) { + Context ctx = (Context) elements[i]; + if (!viewer.getGrayed(ctx)) { + checkedIds.add(ctx.fScopeId); + } + } + } + if (checkedIds.size() == fContexts.size()) { + threadIds = null; + } + else { + threadIds = checkedIds.toArray(new String[checkedIds.size()]); + } + TCFBreakpointScopeExtension filterExtension = fPage.getFilterExtension(); + if (filterExtension == null) return; + filterExtension.setThreadFilter(threadIds); } - TCFBreakpointScopeExtension filterExtension = fPage.getFilterExtension(); - if (filterExtension == null) return; - filterExtension.setThreadFilter(threadIds); } private Context[] syncGetContainers(final TCFLaunch launch) { diff --git a/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/messages.properties b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/messages.properties new file mode 100644 index 000000000..9498a74f1 --- /dev/null +++ b/plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/messages.properties @@ -0,0 +1,8 @@ +TCFThreadFilterQueryExpressionStore=TCFThreadFilter.ScopedExpressionList +TCFThreadFilterQueryModeButtonState=TCFThreadFilter.radioBasic.Selection +TCFThreadFilterQueryButtonBasic=Basic +TCFThreadFilterQueryButtonAdvanced=Advanced +TCFThreadFilterQueryButtonEdit=Edit +TCFThreadFilterQueryAdvancedLabel=Breakpoint Scoping Expression: +TCFThreadFilterQueryTreeViewLabel=Restrict to Selected Contexts: +TCFThreadFilterEditorFormatError=Parameters must be name value pairs |