summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorScott Tepavich2012-04-05 18:55:05 (EDT)
committer Eugene Tarassov2012-04-06 10:40:57 (EDT)
commit07fd3cb8c028dba668ee4905f76b3a024d950e75 (patch)
tree4e76bc9a0cfcd43be7a382656b02f870a895a936
parent8cc2f35200a7335e7292f9f6554f0cefa5eb3183 (diff)
downloadorg.eclipse.tcf-07fd3cb8c028dba668ee4905f76b3a024d950e75.zip
org.eclipse.tcf-07fd3cb8c028dba668ee4905f76b3a024d950e75.tar.gz
org.eclipse.tcf-07fd3cb8c028dba668ee4905f76b3a024d950e75.tar.bz2
Bug [374603] Allow a user to set a BP filter.
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/Messages.java24
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointScopeExtension.java19
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFBreakpointThreadFilterPage.java11
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFContextQueryExpressionDialog.java342
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/TCFThreadFilterEditor.java413
-rw-r--r--plugins/org.eclipse.tcf.cdt.ui/src/org/eclipse/tcf/internal/cdt/ui/breakpoints/messages.properties8
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 0000000..3c83948
--- /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 e46fe00..cb07740 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 eec02a3..c5fc06a 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 0000000..7518a91
--- /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 b32c5e1..70c6947 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 0000000..9498a74
--- /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