diff -r ed1c9f64298a -r 5b9d4d8641ce trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/dialog/FilterAdvancedDialog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/dialog/FilterAdvancedDialog.java Wed Jun 23 14:49:59 2010 +0300 @@ -0,0 +1,1063 @@ +/* + * Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Nokia Corporation - initial contribution. + * + * Contributors: + * + * Description: + * + * Advanced filter dialog + * + */ +package com.nokia.traceviewer.dialog; + +import java.net.URL; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; +import org.eclipse.swt.widgets.Tree; + +import com.nokia.traceviewer.TraceViewerPlugin; +import com.nokia.traceviewer.dialog.treeitem.FilterTreeBaseItem; +import com.nokia.traceviewer.dialog.treeitem.FilterTreeComponentItem; +import com.nokia.traceviewer.dialog.treeitem.FilterTreeTextItem; +import com.nokia.traceviewer.dialog.treeitem.TreeItem; +import com.nokia.traceviewer.dialog.treeitem.TreeItemContentProvider; +import com.nokia.traceviewer.dialog.treeitem.TreeItemLabelProvider; +import com.nokia.traceviewer.engine.TraceViewerGlobals; +import com.nokia.traceviewer.engine.dataprocessor.FilterRuleObject; +import com.nokia.traceviewer.engine.dataprocessor.FilterRuleSet; +import com.nokia.traceviewer.engine.dataprocessor.FilterRuleSet.LogicalOperator; + +/** + * Advanced filter dialog + * + */ +public final class FilterAdvancedDialog extends BaseDialog { + + /** + * Indicates how this dialog was exited + */ + public enum ExitStatus { + + /** + * Initial state + */ + NORMAL, + + /** + * Exited through apply button + */ + APPLYBUTTON, + + /** + * Exited through cancel button + */ + CANCELBUTTON, + + /** + * Exited through simple button + */ + SIMPLEBUTTON; + } + + /** + * Error message to show when there is multiple operators inside same set + */ + private static final String MULTIPLE_OPERATORS_ERROR_MSG = Messages + .getString("FilterAdvancedDialog.MultipleOperatorsErrorMsg"); //$NON-NLS-1$ + + /** + * Error message to show when there is extra characters inside same set + */ + private static final String EXTRA_CHARS_ERROR_MSG = Messages + .getString("FilterAdvancedDialog.InvalidSyntaxErrorMsg"); //$NON-NLS-1$ + + /** + * Tree + */ + private Tree tree; + + /** + * TreeViewer + */ + private TreeViewer treeViewer; + + /** + * Styled Text rule field + */ + private StyledText ruleTextfield; + + /** + * Button + */ + private Button showButton; + + /** + * Content provider + */ + private final TreeItemContentProvider contentProvider; + + /** + * Tree root + */ + private final TreeItem treeRoot; + + /** + * Start set tool item + */ + private ToolItem startSetToolItem; + + /** + * Start set image location + */ + private static final String startSetImageLocation = "/icons/startset.gif"; //$NON-NLS-1$ + + /** + * Start set image + */ + private Image startSetImage; + + /** + * End set tool item + */ + private ToolItem endSetToolItem; + + /** + * End set image location + */ + private static final String endSetImageLocation = "/icons/endset.gif"; //$NON-NLS-1$ + + /** + * End set image + */ + private Image endSetImage; + + /** + * AND tool item + */ + private ToolItem andToolItem; + + /** + * AND image location + */ + private static final String andImageLocation = "/icons/logicaland.gif"; //$NON-NLS-1$ + + /** + * AND image + */ + private Image andImage; + + /** + * OR tool item + */ + private ToolItem orToolItem; + + /** + * OR image location + */ + private static final String orImageLocation = "/icons/logicalor.gif"; //$NON-NLS-1$ + + /** + * OR image + */ + private Image orImage; + + /** + * NOT tool item + */ + private ToolItem notToolItem; + + /** + * NOT image location + */ + private static final String notImageLocation = "/icons/logicalnot.gif"; //$NON-NLS-1$ + + /** + * NOT image + */ + private Image notImage; + + /** + * Back tool item + */ + private ToolItem backToolItem; + + /** + * Back image location + */ + private static final String backImageLocation = "/icons/backarrow.gif"; //$NON-NLS-1$ + + /** + * Clear tool item + */ + private ToolItem clearToolItem; + + /** + * Clear image location + */ + private static final String clearImageLocation = "/icons/clear.gif"; //$NON-NLS-1$ + + /** + * Simple tool item + */ + private ToolItem simpleToolItem; + + /** + * Simple image location + */ + private static final String simpleImageLocation = "/icons/simplefilter.gif"; //$NON-NLS-1$ + + /** + * Simple image + */ + private Image simpleImage; + + /** + * Indicates to show traces containing the rule. Otherwise they're hidden + */ + private boolean showTracesContainingRule = true; + + /** + * Rule parser + */ + private FilterAdvancedParser ruleParser; + + /** + * Filter rule set to create from the rule text + */ + private FilterRuleObject ruleSet; + + /** + * Indicates that the dialog can be closed + */ + private boolean canBeClosed = true; + + /** + * Selection menu that opens when user clicks a group in the Tree + */ + private Menu menu; + + /** + * Indicates the exit status of this dialog + */ + public ExitStatus exitStatus; + + /** + * Constructor + * + * @param parent + * parent shell + * @param contentProvider + * contentprovider for the tree + * @param treeRoot + * tree root + */ + public FilterAdvancedDialog(Shell parent, + TreeItemContentProvider contentProvider, TreeItem treeRoot) { + super(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL | SWT.RESIZE); + this.contentProvider = contentProvider; + this.treeRoot = treeRoot; + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.dialog.BaseDialog#close() + */ + @Override + public boolean close() { + // If closing dialog by clicking X, do as in Cancel button + if (exitStatus == ExitStatus.NORMAL) { + exitStatus = ExitStatus.CANCELBUTTON; + saveSettings(); + dispose(); + } else if (exitStatus == ExitStatus.SIMPLEBUTTON) { + saveSettings(); + } + + return super.close(); + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.dialog.BaseDialog#createShell() + */ + @Override + protected void createDialogContents() { + // Shell + GridLayout shellGridLayout = new GridLayout(); + shellGridLayout.numColumns = 3; + shellGridLayout.makeColumnsEqualWidth = false; + getShell().setText("Advanced Filter Rules"); //$NON-NLS-1$ + composite.setLayout(shellGridLayout); + getShell().setMinimumSize(new Point(435, 515)); + + // Tree + GridData treeGridData = new GridData(); + treeGridData.horizontalAlignment = GridData.FILL; + treeGridData.grabExcessHorizontalSpace = true; + treeGridData.grabExcessVerticalSpace = true; + treeGridData.horizontalSpan = 2; + treeGridData.verticalAlignment = GridData.FILL; + treeGridData.widthHint = 250; + tree = new Tree(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); + tree.setLayoutData(treeGridData); + + // Tree viewer + treeViewer = new TreeViewer(tree); + treeViewer.setLabelProvider(new TreeItemLabelProvider()); + treeViewer.setContentProvider(contentProvider); + + // Set root and expand all items + treeViewer.setInput(treeRoot); + treeViewer.expandAll(); + + // Select the root item + if (tree.getItem(0) != null) { + tree.setSelection(tree.getItem(0)); + } + + // Create toolbar + createToolBar(); + + // Rule text field + GridData ruleTextFieldGridData = new GridData(); + ruleTextFieldGridData.grabExcessHorizontalSpace = true; + ruleTextFieldGridData.horizontalAlignment = GridData.FILL; + ruleTextFieldGridData.verticalAlignment = GridData.FILL; + ruleTextFieldGridData.heightHint = 70; + ruleTextFieldGridData.horizontalSpan = 2; + ruleTextFieldGridData.grabExcessVerticalSpace = false; + ruleTextFieldGridData.minimumHeight = 100; + ruleTextFieldGridData.horizontalIndent = 5; + ruleTextfield = new StyledText(composite, SWT.BORDER | SWT.WRAP + | SWT.V_SCROLL); + ruleTextfield.setLayoutData(ruleTextFieldGridData); + + // Create new rule parser to this rule text field + ruleParser = new FilterAdvancedParser(ruleTextfield, tree.getItems()[0] + .getItems()); + // Set parser to be the key, mouse and focus listener + ruleTextfield.addKeyListener(ruleParser); + ruleTextfield.addMouseListener(ruleParser); + ruleTextfield.addFocusListener(ruleParser); + + // Set text from previous visit + ruleTextfield.setText(FilterAdvancedParser.SPACE_STR + + TraceViewerGlobals.getTraceViewer().getDataProcessorAccess() + .getFilterProcessor().getAdvancedFilterString() + + FilterAdvancedParser.SPACE_STR); + ruleTextfield.setCaretOffset(ruleTextfield.getCharCount()); + + // Create Group + createGroup(); + } + + /** + * Creates the toolbar containing pushable buttons to the right side of the + * dialog. + */ + private void createToolBar() { + // Create the toolBar + GridData toolBarGridData = new GridData(); + toolBarGridData.horizontalAlignment = GridData.FILL; + toolBarGridData.grabExcessVerticalSpace = true; + toolBarGridData.verticalSpan = 2; + toolBarGridData.verticalAlignment = GridData.FILL; + ToolBar toolBar = new ToolBar(composite, SWT.VERTICAL); + toolBar.setLayoutData(toolBarGridData); + + // Create "Start set" item + startSetToolItem = new ToolItem(toolBar, SWT.PUSH); + startSetToolItem.setText(Messages + .getString("FilterAdvancedDialog.StartSetButtonText")); //$NON-NLS-1$ + startSetToolItem.setToolTipText(Messages + .getString("FilterAdvancedDialog.StartSetToolTip")); //$NON-NLS-1$ + // Set image to the "Start set" item + URL url = TraceViewerPlugin.getDefault().getBundle().getEntry( + startSetImageLocation); + startSetImage = ImageDescriptor.createFromURL(url).createImage(); + startSetToolItem.setImage(startSetImage); + + // Create "End set" item + endSetToolItem = new ToolItem(toolBar, SWT.PUSH); + endSetToolItem.setText(Messages + .getString("FilterAdvancedDialog.EndSetButtonText")); //$NON-NLS-1$ + endSetToolItem.setToolTipText(Messages + .getString("FilterAdvancedDialog.EndSetToolTip")); //$NON-NLS-1$ + // Set image to the "End set" item + url = TraceViewerPlugin.getDefault().getBundle().getEntry( + endSetImageLocation); + endSetImage = ImageDescriptor.createFromURL(url).createImage(); + endSetToolItem.setImage(endSetImage); + + // Create "And" item + andToolItem = new ToolItem(toolBar, SWT.PUSH); + andToolItem.setText(FilterAdvancedParser.AND); + andToolItem.setToolTipText(Messages + .getString("FilterAdvancedDialog.ANDToolTip")); //$NON-NLS-1$ + // Set image to the "And" item + url = TraceViewerPlugin.getDefault().getBundle().getEntry( + andImageLocation); + andImage = ImageDescriptor.createFromURL(url).createImage(); + andToolItem.setImage(andImage); + + // Create "Or" item + orToolItem = new ToolItem(toolBar, SWT.PUSH); + orToolItem.setText(FilterAdvancedParser.OR); + orToolItem.setToolTipText(Messages + .getString("FilterAdvancedDialog.ORToolTip")); //$NON-NLS-1$ + // Set image to the "Or" item + url = TraceViewerPlugin.getDefault().getBundle().getEntry( + orImageLocation); + orImage = ImageDescriptor.createFromURL(url).createImage(); + orToolItem.setImage(orImage); + + // Create "Not" item + notToolItem = new ToolItem(toolBar, SWT.PUSH); + notToolItem.setText(FilterAdvancedParser.NOT); + notToolItem.setToolTipText(Messages + .getString("FilterAdvancedDialog.NOTToolTip")); //$NON-NLS-1$ + // Set image to the "Not" item + url = TraceViewerPlugin.getDefault().getBundle().getEntry( + notImageLocation); + notImage = ImageDescriptor.createFromURL(url).createImage(); + notToolItem.setImage(notImage); + + // Create "Back" item + backToolItem = new ToolItem(toolBar, SWT.PUSH); + backToolItem.setText(Messages + .getString("FilterAdvancedDialog.BackButtonText")); //$NON-NLS-1$ + backToolItem.setToolTipText(Messages + .getString("FilterAdvancedDialog.BackToolTip")); //$NON-NLS-1$ + // Set image to the "Back" item + url = TraceViewerPlugin.getDefault().getBundle().getEntry( + backImageLocation); + Image backImage = ImageDescriptor.createFromURL(url).createImage(); + backToolItem.setImage(backImage); + + // Create "Clear" item + clearToolItem = new ToolItem(toolBar, SWT.PUSH); + clearToolItem.setText(Messages + .getString("FilterAdvancedDialog.ClearButtonText")); //$NON-NLS-1$ + clearToolItem.setToolTipText(Messages + .getString("FilterAdvancedDialog.ClearToolTip")); //$NON-NLS-1$ + // Set image to the "Clear" item + url = TraceViewerPlugin.getDefault().getBundle().getEntry( + clearImageLocation); + Image clearImage = ImageDescriptor.createFromURL(url).createImage(); + clearToolItem.setImage(clearImage); + + // Create "Simple" item + simpleToolItem = new ToolItem(toolBar, SWT.PUSH); + simpleToolItem.setText(Messages + .getString("FilterAdvancedDialog.SimpleButtonText")); //$NON-NLS-1$ + simpleToolItem.setToolTipText(Messages + .getString("FilterAdvancedDialog.SimpleViewToolTip")); //$NON-NLS-1$ + // Set image to the "Simple" item + url = TraceViewerPlugin.getDefault().getBundle().getEntry( + simpleImageLocation); + simpleImage = ImageDescriptor.createFromURL(url).createImage(); + simpleToolItem.setImage(simpleImage); + } + + /** + * This method initializes group + */ + private void createGroup() { + // Settings group + GridData settingsGroupGridData = new GridData(); + settingsGroupGridData.horizontalAlignment = GridData.BEGINNING; + settingsGroupGridData.grabExcessHorizontalSpace = false; + settingsGroupGridData.grabExcessVerticalSpace = false; + settingsGroupGridData.verticalAlignment = GridData.FILL; + GridLayout settingsGroupGridLayout = new GridLayout(); + settingsGroupGridLayout.verticalSpacing = 5; + settingsGroupGridLayout.marginWidth = 5; + settingsGroupGridLayout.marginHeight = 5; + settingsGroupGridLayout.numColumns = 2; + settingsGroupGridLayout.horizontalSpacing = 5; + Group settingsGroup = new Group(composite, SWT.NONE); + settingsGroup.setLayout(settingsGroupGridLayout); + settingsGroup.setLayoutData(settingsGroupGridData); + settingsGroup.setText(Messages + .getString("FilterAdvancedDialog.SettingsGroupName")); //$NON-NLS-1$ + + // Show button + showButton = new Button(settingsGroup, SWT.RADIO); + showButton.setText(Messages + .getString("FilterAdvancedDialog.ShowButtonText")); //$NON-NLS-1$ + showButton.setToolTipText(Messages + .getString("FilterAdvancedDialog.ShowButtonToolTip")); //$NON-NLS-1$ + showButton.setSelection(showTracesContainingRule); + + // Hide button + Button hideButton = new Button(settingsGroup, SWT.RADIO); + hideButton.setText(Messages + .getString("FilterAdvancedDialog.HideButtonText")); //$NON-NLS-1$ + hideButton.setToolTipText(Messages + .getString("FilterAdvancedDialog.HideButtonToolTip")); //$NON-NLS-1$ + hideButton.setSelection(!showTracesContainingRule); + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.dialog.BaseDialog#restoreSettings() + */ + @Override + protected void restoreSettings() { + super.restoreSettings(); + exitStatus = ExitStatus.NORMAL; + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.dialog.BaseDialog#saveSettings() + */ + @Override + protected void saveSettings() { + super.saveSettings(); + + if (exitStatus == ExitStatus.APPLYBUTTON) { + // Save advanced filter string + TraceViewerGlobals.getTraceViewer().getDataProcessorAccess() + .getFilterProcessor().setAdvancedFilterString( + ruleTextfield.getText()); + + showTracesContainingRule = showButton.getSelection(); + + // Create the rule set + String ruleText = ruleTextfield.getText(); + ruleSet = null; + if (ruleText.length() > 0 + && ruleParser.containsFilterRule(ruleText, tree.getItems())) { + ruleSet = createRuleSet(ruleText, false); + } + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.dialogs.Dialog#okPressed() + */ + @Override + protected void okPressed() { + exitStatus = ExitStatus.APPLYBUTTON; + boolean valid = checkWrittenRules(ruleTextfield.getText()); + if (valid) { + saveSettings(); + } else { + TraceViewerGlobals.getTraceViewer().getDialogs().showErrorMessage( + EXTRA_CHARS_ERROR_MSG); + canBeClosed = false; + } + + if (canBeClosed) { + super.okPressed(); + dispose(); + } else { + canBeClosed = true; + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.dialogs.Dialog#cancelPressed() + */ + @Override + protected void cancelPressed() { + exitStatus = ExitStatus.CANCELBUTTON; + saveSettings(); + + super.cancelPressed(); + + dispose(); + } + + /* + * (non-Javadoc) + * + * @see com.nokia.traceviewer.dialog.BaseDialog#createActionListeners() + */ + @Override + protected void createActionListeners() { + + // Add selection listener to start Set button + startSetToolItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + TraceViewerGlobals.postUiEvent("StartSetButton", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + updateRuleTextField(FilterAdvancedParser.START_BRACKET_STR); + TraceViewerGlobals.postUiEvent("StartSetButton", "0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + }); + + // Add selection listener to end Set button + endSetToolItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + TraceViewerGlobals.postUiEvent("EndSetButton", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + updateRuleTextField(FilterAdvancedParser.END_BRACKET_STR); + TraceViewerGlobals.postUiEvent("EndSetButton", "0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + }); + + // Add selection listener to and button + andToolItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + TraceViewerGlobals.postUiEvent("AndButton", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + updateRuleTextField(FilterAdvancedParser.AND); + TraceViewerGlobals.postUiEvent("AndButton", "0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + }); + + // Add selection listener to or button + orToolItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + TraceViewerGlobals.postUiEvent("OrButton", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + updateRuleTextField(FilterAdvancedParser.OR); + TraceViewerGlobals.postUiEvent("OrButton", "0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + }); + + // Add selection listener to not button + notToolItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + TraceViewerGlobals.postUiEvent("NotButton", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + updateRuleTextField(FilterAdvancedParser.NOT); + TraceViewerGlobals.postUiEvent("NotButton", "0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + }); + + // Add selection listener to back button + backToolItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + TraceViewerGlobals.postUiEvent("BackButton", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + removeLastWord(); + TraceViewerGlobals.postUiEvent("BackButton", "0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + }); + + // Add selection listener to clear button + clearToolItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + TraceViewerGlobals.postUiEvent("ClearButton", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + ruleTextfield.setText(""); //$NON-NLS-1$ + setButtonStates(); + TraceViewerGlobals.postUiEvent("ClearButton", "0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + }); + + // Add selection listener to simple button + simpleToolItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + TraceViewerGlobals.postUiEvent("SimpleButton", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + + // Save exit status and advanced filter string + exitStatus = ExitStatus.SIMPLEBUTTON; + TraceViewerGlobals.getTraceViewer().getDataProcessorAccess() + .getFilterProcessor().setAdvancedFilterString( + ruleTextfield.getText()); + close(); + dispose(); + TraceViewerGlobals.postUiEvent("SimpleButton", "0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + }); + + // Add selection listener to Tree + tree.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent event) { + TraceViewerGlobals.postUiEvent("TreeSelected", "1"); //$NON-NLS-1$ //$NON-NLS-2$ + // Get selection + Object selection = ((IStructuredSelection) treeViewer + .getSelection()).getFirstElement(); + + if (selection != null) { + // If group selected, add all rules to the list + if (((TreeItem) selection).isGroup()) { + processGroupSelection(); + + } else { + // Dispose menu if it exists + if (menu != null && !menu.isDisposed()) { + menu.dispose(); + } + updateRuleTextField(tree.getSelection()[0].getText()); + } + } + TraceViewerGlobals.postUiEvent("TreeSelected", "0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Processes group item selection + */ + private void processGroupSelection() { + // Add menu to Tree + menu = new Menu(composite); + + MenuItem orItem = new MenuItem(menu, SWT.CASCADE); + if (orImage != null && !orImage.isDisposed()) { + orItem.setImage(orImage); + } + orItem.setEnabled(ruleParser.canOrBeInserted() + || ruleTextfield.getCharCount() < 4); + orItem.setText(FilterAdvancedParser.OR); + + // Add selection listener to OR button + orItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + processSelection(FilterAdvancedParser.OR); + } + }); + + // And item + MenuItem andItem = new MenuItem(menu, SWT.CASCADE); + if (andImage != null && !andImage.isDisposed()) { + andItem.setImage(andImage); + } + andItem.setEnabled(ruleParser.canAndBeInserted() + || ruleTextfield.getCharCount() < 3); + andItem.setText(FilterAdvancedParser.AND); + + // Add selection listener to AND button + andItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + processSelection(FilterAdvancedParser.AND); + } + }); + + tree.setMenu(menu); + menu.setVisible(true); + } + }); + + // Validate and set button states + ruleParser.validate(); + setButtonStates(); + } + + /** + * Checks written rules from the rule field + * + * @param text + * text to check + * @return true if rules are ok, false otherwise + */ + public boolean checkWrittenRules(String text) { + boolean ok = false; + if (ruleParser != null) { + ok = ruleParser.checkWrittenRules(text); + } + return ok; + } + + /** + * Process selection of AND or OR + * + * @param operator + * operator String + */ + private void processSelection(String operator) { + StringBuffer buf = new StringBuffer(); + + // Get selection + Object selection = ((IStructuredSelection) treeViewer.getSelection()) + .getFirstElement(); + if (selection != null) { + Object[] children = ((TreeItem) selection).getChildren(); + + // If previous word is a rule, add the operator + String prevWord = ruleParser.getPreviousWord(ruleTextfield + .getText(), ruleTextfield.getText().length() - 1); + if (ruleParser.containsFilterRule(prevWord, tree.getItems())) { + buf.append(" " + operator + " "); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Loop through children and append them to the string buffer + for (int i = 0; i < children.length; i++) { + if (!((TreeItem) children[i]).isGroup()) { + + // If previous word is a rule, add the operator + prevWord = ruleParser.getPreviousWord(buf.toString(), buf + .length() - 1); + if (ruleParser + .containsFilterRule(prevWord, tree.getItems())) { + buf.append(" " + operator + " "); //$NON-NLS-1$ //$NON-NLS-2$ + } + + buf.append(((TreeItem) children[i]).getName()); + if (i < children.length - 1 + && !((TreeItem) children[i + 1]).isGroup()) { + buf.append(" " + operator + " "); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + } + updateRuleTextField(buf.toString()); + } + } + + /** + * Disposes UI resources if they exist. Is called when the shell is closed + * or user clicks apply, cancel of simple buttons + */ + private void dispose() { + if (startSetImage != null) { + startSetImage.dispose(); + } + if (endSetImage != null) { + endSetImage.dispose(); + } + if (orImage != null) { + orImage.dispose(); + } + if (andImage != null) { + andImage.dispose(); + } + if (notImage != null) { + notImage.dispose(); + } + if (simpleImage != null) { + simpleImage.dispose(); + } + } + + /** + * Updates rule text field + * + * @param text + * text to add to text field + */ + private void updateRuleTextField(String text) { + ruleTextfield.insert(FilterAdvancedParser.SPACE_STR + text + + FilterAdvancedParser.SPACE_STR); + ruleTextfield.setCaretOffset(ruleTextfield.getCaretOffset() + + text.length() + 2); + ruleParser.validate(); + setButtonStates(); + } + + /** + * Removes last word from the rule text field + */ + private void removeLastWord() { + + // Get caret offset and text from the text field + int caretPos = ruleTextfield.getCaretOffset(); + StringBuffer text = new StringBuffer(ruleTextfield.getText()); + int startPos = 0; + if (caretPos == ruleTextfield.getCharCount()) { + caretPos--; + } + + // Go through characters starting from the last one + for (int i = caretPos; i > 0; i--) { + char c = text.charAt(i); + + // When space is found, set start position for deleting + if (c == FilterAdvancedParser.SPACE && i != caretPos) { + startPos = i; + break; + } + } + + // Replace the last word from the text field and set button states + if (startPos < caretPos) { + ruleTextfield.replaceTextRange(startPos, caretPos - startPos, ""); //$NON-NLS-1$ + setButtonStates(); + } + } + + /** + * Sets button states + */ + public void setButtonStates() { + + // Get different statuses from rule parser and set button states + // according to those + startSetToolItem.setEnabled(ruleParser.canNewSetBeStarted()); + endSetToolItem.setEnabled(ruleParser.canSetBeEnded()); + Button okButton = getButton(IDialogConstants.OK_ID); + if (okButton != null) { + getButton(OK).setEnabled(ruleParser.canApplyBeClicked()); + } + andToolItem.setEnabled(ruleParser.canAndBeInserted()); + orToolItem.setEnabled(ruleParser.canOrBeInserted()); + backToolItem.setEnabled(ruleTextfield.getCaretOffset() > 1); + clearToolItem.setEnabled(ruleTextfield.getCharCount() > 1); + } + + /** + * Creates a rule set out of the rule String + * + * @param text + * text to create the rule set from + * @param notRule + * indicates if a rule is a NOT rule + * @return rule object + */ + public FilterRuleObject createRuleSet(String text, boolean notRule) { + // Tells that NOT status has changed + boolean notHasChanged = false; + + // New Filter rule object to be created + FilterRuleObject object = null; + + // Trim the text + text = text.trim(); + + // Check if result is a basic rule + boolean isBasicRule = ruleParser.isBasicRule(text); + + // Basic rule + if (isBasicRule) { + // Get the rule from the tree + object = getRuleWithName(text, treeRoot.getChildren()); + + // Rule set + } else { + object = new FilterRuleSet(); + + // Get and set Logical Operator for this rule set + LogicalOperator op = ruleParser.getLogicalOperator(text); + ((FilterRuleSet) object).setOperator(op); + + // Both or non operators in the set, show error + if (op == null) { + canBeClosed = false; + TraceViewerGlobals.getTraceViewer().getDialogs() + .showErrorMessage(MULTIPLE_OPERATORS_ERROR_MSG); + } + + // Get children and loop through them + String[] children = ruleParser.getChildren(text); + for (int i = 0; canBeClosed && children != null + && i < children.length; i++) { + + // Check if child is NOT. If yes, it means that the next child + // will have modified NOT status + if (children[i].trim().equals(FilterAdvancedParser.NOT)) { + notHasChanged = true; + } else { + FilterRuleObject child; + if (notHasChanged) { + child = createRuleSet(children[i], !notRule); + } else { + child = createRuleSet(children[i], notRule); + } + + ((FilterRuleSet) object).addObject(child); + notHasChanged = false; + } + } + + } + + // Set NOT rule status + object.setLogicalNotRule(notRule); + return object; + } + + /** + * Gets rule with a name + * + * @param name + * name text + * @param items + * items array + * @return true if rule is found from the items + */ + private FilterRuleObject getRuleWithName(String name, Object[] items) { + FilterRuleObject ret = null; + for (int i = 0; i < items.length; i++) { + FilterTreeBaseItem item = (FilterTreeBaseItem) items[i]; + + // Contains children, recurse + if ((item.getChildren().length > 0)) { + ret = getRuleWithName(name, item.getChildren()); + + // Check item + } else { + if (name.equals(item.getName())) { + + // Create new objects from the existing ones + // Text item + if (item instanceof FilterTreeTextItem) { + FilterTreeTextItem item2 = (FilterTreeTextItem) item; + ret = new FilterTreeTextItem(null, null, name, item2 + .getRule(), item2.getText(), item2 + .isMatchCase()); + + // Component item + } else if (item instanceof FilterTreeComponentItem) { + FilterTreeComponentItem item2 = (FilterTreeComponentItem) item; + ret = new FilterTreeComponentItem(null, null, name, + item2.getRule(), item2.getComponentId(), item2 + .getGroupId()); + } + break; + } + } + } + return ret; + } + + /** + * Checks if traces hitting filter should be displayed or not. + * + * @return true if traces hitting filter should be displayed. + */ + public boolean isShowTracesContainingRule() { + return showTracesContainingRule; + } + + /** + * Gets the rule set created + * + * @return the ruleSet created + */ + public FilterRuleObject getRuleSet() { + return ruleSet; + } + +}