trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/dialog/FilterAdvancedDialog.java
author Matti Laitinen <matti.t.laitinen@nokia.com>
Wed, 23 Jun 2010 14:49:59 +0300
changeset 11 5b9d4d8641ce
permissions -rw-r--r--
TraceViewer 2.6.0

/*
 * 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;
	}

}