trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/dialog/SearchDialog.java
changeset 11 5b9d4d8641ce
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/dialog/SearchDialog.java	Wed Jun 23 14:49:59 2010 +0300
@@ -0,0 +1,1116 @@
+/*
+ * 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:
+ *
+ * Search Dialog class
+ *
+ */
+package com.nokia.traceviewer.dialog;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.PatternSyntaxException;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.FindReplaceDocumentAdapter;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ProgressBar;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.traceviewer.TraceViewerHelpContextIDs;
+import com.nokia.traceviewer.engine.StateHolder;
+import com.nokia.traceviewer.engine.TraceInformation;
+import com.nokia.traceviewer.engine.TraceProperties;
+import com.nokia.traceviewer.engine.TraceViewerGlobals;
+import com.nokia.traceviewer.engine.TraceViewerTraceViewInterface;
+import com.nokia.traceviewer.engine.dataprocessor.SearchProperties;
+import com.nokia.traceviewer.engine.dataprocessor.SearchUtils;
+import com.nokia.traceviewer.engine.dataprocessor.TimestampParser;
+
+/**
+ * Search Dialog class
+ * 
+ */
+public final class SearchDialog extends BaseDialog {
+
+	/**
+	 * Display used to get UI thread
+	 */
+	private final Display display;
+
+	/**
+	 * UI Label for line count field
+	 */
+	private Label lineCountLabel;
+
+	/**
+	 * UI Combo box for find texts
+	 */
+	private Combo findCombo;
+
+	/**
+	 * UI Find button
+	 */
+	private Button searchButton;
+
+	/**
+	 * UI Checkbox for match whole word
+	 */
+	private Button matchWholeWordCheckBox;
+
+	/**
+	 * UI Checkbox for match case
+	 */
+	private Button matchCaseCheckBox;
+
+	/**
+	 * UI Checkbox for regular expression search
+	 */
+	private Button regularExpressionCheckBox;
+
+	/**
+	 * UI Radio button for up direction
+	 */
+	private Button upDirectionRadioButton;
+
+	/**
+	 * UI Radio button for down direction
+	 */
+	private Button downDirectionRadioButton;
+
+	/**
+	 * UI Button for stop search
+	 */
+	private Button stopSearchButton;
+
+	/**
+	 * Progressbar showing file position
+	 */
+	private ProgressBar progressBar;
+
+	/**
+	 * Reference to View
+	 */
+	private final TraceViewerTraceViewInterface view;
+
+	/**
+	 * Search properties used when searching
+	 */
+	private final SearchProperties searchProperties;
+
+	/**
+	 * Widget used in searching
+	 */
+	private StyledText widget;
+
+	/**
+	 * Document used by viewer
+	 */
+	private IDocument document;
+
+	/**
+	 * Contains combo list items that are saved and restored
+	 */
+	private String[] comboList;
+
+	/**
+	 * Finder object
+	 */
+	private FindReplaceDocumentAdapter finder;
+
+	/**
+	 * Checks if DataReader was paused when we entered dialog -> Don't pause
+	 * again and don't unpause in exit
+	 */
+	private boolean wasPausedWhenEntered;
+
+	/**
+	 * Key listener for this dialog
+	 */
+	private KeyAdapter searchDialogKeyListener;
+
+	/**
+	 * Constructor
+	 * 
+	 * @param parent
+	 *            parent shell
+	 * @param view
+	 *            view reference
+	 */
+	public SearchDialog(Shell parent, TraceViewerTraceViewInterface view) {
+		// Pass the default styles here
+		super(parent, SWT.DIALOG_TRIM | SWT.MODELESS | SWT.MIN);
+		this.view = view;
+		this.display = view.getViewer().getControl().getDisplay();
+		searchProperties = new SearchProperties();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.traceviewer.dialog.BaseDialog#close()
+	 */
+	@Override
+	public boolean close() {
+		boolean close = super.close();
+
+		// Stop the search and kill the search data reader
+		TraceViewerGlobals.getTraceViewer().getDataProcessorAccess()
+				.getSearchProcessor().stopSearch(true);
+		TraceViewerGlobals.getTraceViewer().getDataProcessorAccess()
+				.getSearchProcessor().shutdownSearchReader();
+
+		// Unpause
+		if (!wasPausedWhenEntered) {
+			TraceViewerGlobals.getTraceViewer().getView().getActionFactory()
+					.getPauseAction().run();
+		}
+
+		return close;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.traceviewer.dialog.BaseDialog#saveSettings()
+	 */
+	@Override
+	protected void saveSettings() {
+
+		// Save position
+		super.saveSettings();
+
+		// Save combo list items if dialog is not disposed
+		if (findCombo != null && !findCombo.isDisposed()) {
+			comboList = new String[findCombo.getItemCount()];
+			for (int i = 0; i < findCombo.getItemCount(); i++) {
+				comboList[i] = findCombo.getItem(i);
+			}
+			searchProperties
+					.setWholeWord(matchWholeWordCheckBox.getSelection());
+			searchProperties.setCaseSensitive(matchCaseCheckBox.getSelection());
+			searchProperties
+					.setRegExp(regularExpressionCheckBox.getSelection());
+			if (upDirectionRadioButton.getSelection()) {
+				searchProperties.setSearchingForward(false);
+			} else {
+				searchProperties.setSearchingForward(true);
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.traceviewer.dialog.BaseDialog#restoreSettings()
+	 */
+	@Override
+	protected void restoreSettings() {
+		super.restoreSettings();
+
+		// Restore other settings
+		if (comboList != null) {
+			findCombo.setItems(comboList);
+		}
+		matchWholeWordCheckBox.setSelection(searchProperties.isWholeWord());
+		if (searchProperties.isWholeWord()) {
+			regularExpressionCheckBox.setEnabled(false);
+		}
+		matchCaseCheckBox.setSelection(searchProperties.isCaseSensitive());
+		regularExpressionCheckBox.setSelection(searchProperties.isRegExp());
+		if (searchProperties.isRegExp()) {
+			matchWholeWordCheckBox.setEnabled(false);
+		}
+		upDirectionRadioButton.setSelection(!searchProperties
+				.isSearchingForward());
+		downDirectionRadioButton.setSelection(searchProperties
+				.isSearchingForward());
+
+		// Set text to be what was last searched for
+		if (comboList != null && comboList.length > 0) {
+			findCombo.setText(comboList[0]);
+		}
+
+		// Set default button
+		getShell().setDefaultButton(searchButton);
+
+		// Set processor not to stop when next search is started
+		TraceViewerGlobals.getTraceViewer().getDataProcessorAccess()
+				.getSearchProcessor().stopSearch(false);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.traceviewer.dialog.BaseDialog#createShell()
+	 */
+	@Override
+	protected void createDialogContents() {
+		// Pause the datareader if it's not paused already
+		wasPausedWhenEntered = TraceViewerGlobals.getTraceViewer()
+				.getDataReaderAccess().getMainDataReader().isPaused();
+		if (!wasPausedWhenEntered) {
+			TraceViewerGlobals.getTraceViewer().getView().getActionFactory()
+					.getPauseAction().run();
+		}
+
+		// Create needed items
+		TextViewer viewer = view.getViewer();
+		widget = viewer.getTextWidget();
+		document = viewer.getDocument();
+		finder = new FindReplaceDocumentAdapter(document);
+
+		// Shell and Composite
+		GridLayout shellGridLayout = new GridLayout();
+		shellGridLayout.numColumns = 3;
+		getShell().setText(Messages.getString("SearchDialog.DialogTitle")); //$NON-NLS-1$
+		composite.setLayout(shellGridLayout);
+		Label findLabel = new Label(composite, SWT.NONE);
+		findLabel.setText(Messages.getString("SearchDialog.FindText")); //$NON-NLS-1$
+
+		// Create key listener
+		createKeyListener();
+
+		// Create find combo
+		GridData findComboGridData = new GridData();
+		findComboGridData.widthHint = 280;
+		findCombo = new Combo(composite, SWT.NONE);
+		findCombo.setLayoutData(findComboGridData);
+		findCombo.setToolTipText(Messages
+				.getString("SearchDialog.FindComboToolTip")); //$NON-NLS-1$
+		findCombo.addKeyListener(searchDialogKeyListener);
+
+		// Search Button
+		GridData searchButtonGridData = new GridData();
+		searchButtonGridData.widthHint = 75;
+		searchButtonGridData.heightHint = 25;
+		searchButtonGridData.horizontalAlignment = GridData.END;
+		searchButton = new Button(composite, SWT.NONE);
+		searchButton.setText(Messages
+				.getString("SearchDialog.SearchButtonText")); //$NON-NLS-1$
+		searchButton.setToolTipText(Messages
+				.getString("SearchDialog.SearchButtonToolTip")); //$NON-NLS-1$
+		searchButton.setLayoutData(searchButtonGridData);
+
+		// Match whole word Checkbox
+		GridData matchWholeWordGridData = new GridData();
+		matchWholeWordGridData.horizontalSpan = 2;
+		matchWholeWordGridData.verticalAlignment = GridData.END;
+		matchWholeWordGridData.horizontalAlignment = GridData.BEGINNING;
+		matchWholeWordCheckBox = new Button(composite, SWT.CHECK);
+		matchWholeWordCheckBox.setText(Messages
+				.getString("SearchDialog.MatchWholeWordText")); //$NON-NLS-1$
+		matchWholeWordCheckBox.setToolTipText(Messages
+				.getString("SearchDialog.MatchWholeWordToolTip")); //$NON-NLS-1$
+		matchWholeWordCheckBox.setLayoutData(matchWholeWordGridData);
+
+		// Stop Search Button
+		GridData stopSeachButtonGridData = new GridData();
+		stopSeachButtonGridData.widthHint = 75;
+		stopSeachButtonGridData.heightHint = 25;
+		stopSeachButtonGridData.horizontalAlignment = GridData.END;
+		stopSearchButton = new Button(composite, SWT.NONE);
+		stopSearchButton.setText(Messages
+				.getString("SearchDialog.StopButtonText")); //$NON-NLS-1$
+		stopSearchButton.setToolTipText(Messages
+				.getString("SearchDialog.StopButtonToolTip")); //$NON-NLS-1$
+		stopSearchButton.setLayoutData(stopSeachButtonGridData);
+		stopSearchButton.setEnabled(false);
+
+		// Match Case Checkbox
+		GridData matchCaseCheckBoxGridData = new GridData();
+		matchCaseCheckBoxGridData.horizontalSpan = 2;
+		matchCaseCheckBox = new Button(composite, SWT.CHECK);
+		matchCaseCheckBox.setText(Messages
+				.getString("SearchDialog.MatchCaseText")); //$NON-NLS-1$
+		matchCaseCheckBox.setToolTipText(Messages
+				.getString("SearchDialog.MatchCaseToolTip")); //$NON-NLS-1$
+		matchCaseCheckBox.setLayoutData(matchCaseCheckBoxGridData);
+
+		// Regular Expression CheckBox
+		GridData regularExpressionCheckBoxGridData = new GridData();
+		regularExpressionCheckBoxGridData.horizontalSpan = 2;
+		regularExpressionCheckBoxGridData.verticalAlignment = GridData.BEGINNING;
+		regularExpressionCheckBoxGridData.horizontalAlignment = GridData.BEGINNING;
+		regularExpressionCheckBox = new Button(composite, SWT.CHECK);
+		regularExpressionCheckBox.setText(Messages
+				.getString("SearchDialog.RegExpText")); //$NON-NLS-1$
+		regularExpressionCheckBox.setToolTipText(Messages
+				.getString("SearchDialog.RegExpToolTip")); //$NON-NLS-1$
+		regularExpressionCheckBox
+				.setLayoutData(regularExpressionCheckBoxGridData);
+		createDirectionGroup();
+
+		// Spacer label
+		new Label(composite, SWT.NONE);
+
+		// Line Count Label
+		GridData lineCountLabelGridData = new GridData();
+		lineCountLabelGridData.horizontalSpan = 2;
+		lineCountLabelGridData.widthHint = 300;
+		lineCountLabel = new Label(composite, SWT.NONE);
+
+		// Get the trace count for the label and set it
+		int traceCount = 0;
+		if (TraceViewerGlobals.getTraceViewer().getDataReaderAccess()
+				.getCurrentDataReader() != null) {
+			traceCount = TraceViewerGlobals.getTraceViewer()
+					.getDataReaderAccess().getCurrentDataReader()
+					.getTraceCount();
+		}
+		lineCountLabel.setText(Messages.getString("SearchDialog.LineViewText") //$NON-NLS-1$
+				+ traceCount);
+		lineCountLabel.setLayoutData(lineCountLabelGridData);
+
+		// ProgressBar
+		GridData progressBarGridData = new GridData();
+		progressBarGridData.heightHint = 22;
+		progressBarGridData.grabExcessVerticalSpace = false;
+		progressBarGridData.grabExcessHorizontalSpace = true;
+		progressBarGridData.horizontalAlignment = SWT.FILL;
+		progressBarGridData.horizontalSpan = 3;
+		progressBar = new ProgressBar(composite, SWT.SMOOTH);
+		progressBar.setLayoutData(progressBarGridData);
+		updateSearchProgressBar(view.getShowingTracesFrom()
+				+ widget.getLineAtOffset(widget.getCaretOffset()));
+
+		// Set help
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(getShell(),
+				TraceViewerHelpContextIDs.SEARCHING);
+	}
+
+	/**
+	 * This method initializes findCombo
+	 */
+	private void createKeyListener() {
+		searchDialogKeyListener = new KeyAdapter() {
+
+			@Override
+			public void keyPressed(KeyEvent e) {
+
+				// ALT + d changes search direction
+				if (e.stateMask == SWT.ALT
+						&& (e.character == 'd' || e.character == 'D')) {
+					upDirectionRadioButton.setSelection(!upDirectionRadioButton
+							.getSelection());
+					downDirectionRadioButton
+							.setSelection(!downDirectionRadioButton
+									.getSelection());
+
+					// ALT + c changes "match case" value
+				} else if (e.stateMask == SWT.ALT
+						&& (e.character == 'c' || e.character == 'C')) {
+					matchCaseCheckBox.setSelection(!matchCaseCheckBox
+							.getSelection());
+
+					// ALT + w changes "whole word" value
+				} else if (e.stateMask == SWT.ALT
+						&& (e.character == 'w' || e.character == 'W')) {
+					matchWholeWordCheckBox.setSelection(!matchWholeWordCheckBox
+							.getSelection());
+
+					// Search again
+				} else if (e.keyCode == SWT.F3) {
+					findCombo.setText(getPreviousSearchString());
+					searchString();
+				}
+			}
+		};
+	}
+
+	/**
+	 * This method initializes directionGroup
+	 */
+	private void createDirectionGroup() {
+
+		// Direction Group
+		GridData directionGroupGridData = new GridData();
+		directionGroupGridData.horizontalSpan = 2;
+		GridLayout gridLayout1 = new GridLayout();
+		gridLayout1.numColumns = 2;
+		Group directionGroup = new Group(composite, SWT.NONE);
+		directionGroup.setText(Messages
+				.getString("SearchDialog.DirectionGroupName")); //$NON-NLS-1$
+		directionGroup.setLayoutData(directionGroupGridData);
+		directionGroup.setLayout(gridLayout1);
+		directionGroup.setText(Messages
+				.getString("SearchDialog.DirectionGroupName")); //$NON-NLS-1$
+		directionGroup.setToolTipText(Messages
+				.getString("SearchDialog.DirectionToolTip")); //$NON-NLS-1$
+
+		// Up direction Button
+		upDirectionRadioButton = new Button(directionGroup, SWT.RADIO);
+		upDirectionRadioButton.setText(Messages
+				.getString("SearchDialog.UpDirectionText")); //$NON-NLS-1$
+		upDirectionRadioButton.setToolTipText(Messages
+				.getString("SearchDialog.UpDirectionToolTip")); //$NON-NLS-1$
+
+		// Down direction Button
+		downDirectionRadioButton = new Button(directionGroup, SWT.RADIO);
+		downDirectionRadioButton.setText(Messages
+				.getString("SearchDialog.DownDirectionText")); //$NON-NLS-1$
+		downDirectionRadioButton.setToolTipText(Messages
+				.getString("SearchDialog.DownDirectionToolTip")); //$NON-NLS-1$
+		downDirectionRadioButton.setSelection(true);
+
+		// Add key listeners
+		downDirectionRadioButton.addKeyListener(searchDialogKeyListener);
+		upDirectionRadioButton.addKeyListener(searchDialogKeyListener);
+	}
+
+	/**
+	 * Starts searching with given string
+	 * 
+	 * @param searchString
+	 *            search string
+	 */
+	public void startSearch(String searchString) {
+		if (TraceViewerGlobals.getTraceViewer().getStateHolder().getState() != StateHolder.State.SEARCHING) {
+			TraceViewerGlobals.getTraceViewer().getStateHolder().setState(
+					StateHolder.State.SEARCHING);
+
+			// Has to be before search button is disabled because will
+			// enable it in modify listener
+			insertTextToComboBox(searchString);
+
+			searchButton.setEnabled(false);
+			stopSearchButton.setEnabled(true);
+
+			searchString();
+		}
+
+		// Save settings
+		saveSettings();
+	}
+
+	/**
+	 * Inserts text to combo box if necessary
+	 * 
+	 * @param newString
+	 *            new string to add to combo box
+	 */
+	private void insertTextToComboBox(String newString) {
+		// Insert new items to combo
+
+		int nIndex = findCombo.indexOf(newString);
+		if (nIndex > -1) {
+			findCombo.remove(nIndex);
+		}
+		findCombo.setText(newString);
+		findCombo.add(newString, 0);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.nokia.traceviewer.dialog.BaseDialog#createActionListeners()
+	 */
+	@Override
+	protected void createActionListeners() {
+		// Add selection listener to search button
+		searchButton.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent event) {
+				TraceViewerGlobals.postUiEvent("SearchButton", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+				if (widget.getLineCount() > 1) {
+					startSearch(findCombo.getText());
+				}
+				TraceViewerGlobals.postUiEvent("SearchButton", "0"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		});
+
+		// Add selection listener to stop find button
+		stopSearchButton.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent event) {
+				TraceViewerGlobals.postUiEvent("StopSearchButton", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+				TraceViewerGlobals.getTraceViewer().getDataProcessorAccess()
+						.getSearchProcessor().stopSearch(true);
+				searchButton.setEnabled(true);
+				stopSearchButton.setEnabled(false);
+				getButton(IDialogConstants.OK_ID).setEnabled(true);
+				TraceViewerGlobals.postUiEvent("StopSearchButton", "0"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		});
+
+		// Add selection listener to match whole word checkbox
+		matchWholeWordCheckBox.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent event) {
+				TraceViewerGlobals.postUiEvent("MatchWholeWordCheckBox" //$NON-NLS-1$
+						+ matchWholeWordCheckBox.getSelection(), "1"); //$NON-NLS-1$
+				if (matchWholeWordCheckBox.getSelection()) {
+					regularExpressionCheckBox.setEnabled(false);
+				} else {
+					regularExpressionCheckBox.setEnabled(true);
+				}
+				TraceViewerGlobals.postUiEvent("MatchWholeWordCheckBox" //$NON-NLS-1$
+						+ matchWholeWordCheckBox.getSelection(), "0"); //$NON-NLS-1$
+			}
+		});
+
+		// Add selection listener to regular expression checkbox
+		regularExpressionCheckBox.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent event) {
+				TraceViewerGlobals.postUiEvent("RegularExpressionCheckBox" //$NON-NLS-1$
+						+ regularExpressionCheckBox.getSelection(), "1"); //$NON-NLS-1$
+				if (regularExpressionCheckBox.getSelection()) {
+					matchWholeWordCheckBox.setEnabled(false);
+				} else {
+					matchWholeWordCheckBox.setEnabled(true);
+				}
+				TraceViewerGlobals.postUiEvent("RegularExpressionCheckBox" //$NON-NLS-1$
+						+ regularExpressionCheckBox.getSelection(), "0"); //$NON-NLS-1$
+			}
+		});
+
+		// Add selection listener to match case checkbox
+		matchCaseCheckBox.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent event) {
+				TraceViewerGlobals.postUiEvent("MatchCaseCheckBox" //$NON-NLS-1$
+						+ matchCaseCheckBox.getSelection(), "1"); //$NON-NLS-1$
+				TraceViewerGlobals.postUiEvent("MatchCaseCheckBox" //$NON-NLS-1$
+						+ matchCaseCheckBox.getSelection(), "0"); //$NON-NLS-1$
+			}
+		});
+
+		// Add modify listener to find combo box
+		findCombo.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				if (findCombo.getText().length() > 0) {
+					searchButton.setEnabled(true);
+				} else {
+					searchButton.setEnabled(false);
+				}
+			}
+
+		});
+	}
+
+	/**
+	 * Gets progressBar
+	 * 
+	 * @return progressBar
+	 */
+	public ProgressBar getProgressBar() {
+		return progressBar;
+	}
+
+	/**
+	 * Sets search properties
+	 */
+	private void setVariablesToProperties() {
+
+		// Get variable statuses from the ui components
+		searchProperties.setSearchString(findCombo.getText());
+		searchProperties.setSearchingForward(!upDirectionRadioButton
+				.getSelection());
+		searchProperties.setCaseSensitive(matchCaseCheckBox.getSelection());
+		searchProperties.setWholeWord(matchWholeWordCheckBox.getSelection());
+		searchProperties.setRegExp(regularExpressionCheckBox.getSelection());
+		searchProperties.setOriginalSearchStartLine(TraceViewerGlobals
+				.getTraceViewer().getView().getShowingTracesFrom()
+				+ widget.getLineAtOffset(widget.getCaretOffset()));
+	}
+
+	/**
+	 * Searchs the occurrence of the String value and shows it in view
+	 */
+	private void searchString() {
+
+		// Set search variables
+		setVariablesToProperties();
+
+		// Check if this is a timestamp range search, jump straight to
+		// SearchProcessor
+		if (SearchUtils.containsTimestampQuery(searchProperties
+				.getSearchString())
+				&& SearchUtils.containsTimestampRangeQuery(searchProperties
+						.getSearchString())) {
+
+			// Do a timestamp range search
+			TraceViewerGlobals.getTraceViewer().getDataProcessorAccess()
+					.getSearchProcessor().doTimestampRangeSearch(
+							searchProperties.getSearchString());
+
+			// Other searchs
+		} else {
+
+			try {
+
+				// Get the search start offset
+				int cursorOffset = getCursorOffset(searchProperties
+						.isSearchingForward());
+
+				// Find the trace and get the offset of it
+				int offset = findTrace(cursorOffset);
+
+				// String found
+				if (offset != SearchUtils.NOT_FOUND) {
+					processStringFound(offset);
+
+					// String was not found
+				} else {
+
+					// Start the search after or before this view
+					if (searchProperties.isSearchingForward()) {
+						processSearchingForward();
+					} else {
+						processSearchingBackward();
+					}
+
+				}
+
+			} catch (BadLocationException e) {
+				e.printStackTrace();
+				enableSearchButton();
+			} catch (PatternSyntaxException e) {
+				e.printStackTrace();
+				enableSearchButton();
+			}
+		}
+	}
+
+	/**
+	 * Finds the trace using search properties
+	 * 
+	 * @param searchStartOffset
+	 *            start offset where to start the search
+	 * @return offset of the trace found or -1 if not found
+	 * @throws BadLocationException
+	 */
+	private int findTrace(int searchStartOffset) throws BadLocationException {
+		int offset = SearchUtils.NOT_FOUND;
+
+		// Search using component, group and trace ID's
+		if (SearchUtils.containsIdQuery(searchProperties.getSearchString())) {
+			offset = findTraceIDSearch(searchStartOffset);
+
+			// Timestamp search
+		} else if (SearchUtils.containsTimestampQuery(searchProperties
+				.getSearchString())) {
+			offset = findTraceTimestampSearch(searchStartOffset);
+
+			// Create a normal text search
+		} else {
+			IRegion region = finder.find(searchStartOffset, searchProperties
+					.getSearchString(), searchProperties.isSearchingForward(),
+					searchProperties.isCaseSensitive(), searchProperties
+							.isWholeWord(), searchProperties.isRegExp());
+
+			if (region != null) {
+				offset = region.getOffset();
+			}
+		}
+
+		return offset;
+	}
+
+	/**
+	 * Finds the trace using ID search
+	 * 
+	 * @param searchStartOffset
+	 *            search start offset
+	 * @return found offset
+	 * @throws BadLocationException
+	 */
+	private int findTraceIDSearch(int searchStartOffset)
+			throws BadLocationException {
+		int offset;
+
+		// Parse ID's from the search string
+		TraceInformation inf = SearchUtils.parseIDsFromString(searchProperties
+				.getSearchString());
+
+		int startTrace = document.getLineOfOffset(searchStartOffset);
+
+		// Check which way we are searching and modify the start trace
+		// accordingly
+		boolean forward = searchProperties.isSearchingForward();
+		if (forward) {
+			startTrace++;
+		} else {
+			startTrace--;
+		}
+
+		List<TraceProperties> traces = null;
+		List<TraceInformation> informations = null;
+
+		// Get properties from the traces in the view. -2 comes from empty
+		// line in the end of widget and because traces start from offset 0,
+		// not 1
+		traces = TraceViewerGlobals.getTraceViewer().getTraces(
+				view.getShowingTracesFrom(),
+				view.getShowingTracesFrom() + widget.getLineCount() - 2);
+
+		// Get the informations array
+		if (traces != null) {
+			informations = new ArrayList<TraceInformation>(traces.size());
+			for (int i = 0; i < traces.size(); i++) {
+				informations.add(traces.get(i).information);
+			}
+		}
+
+		// Get the trace number that matches the ID's
+		int foundTrace = SearchUtils.findTraceOffsetFromInformations(
+				startTrace, inf, informations, forward);
+
+		if (foundTrace == SearchUtils.NOT_FOUND) {
+			offset = SearchUtils.NOT_FOUND;
+		} else {
+			offset = document.getLineOffset(foundTrace);
+		}
+		return offset;
+	}
+
+	/**
+	 * Finds the trace using timestamp search
+	 * 
+	 * @param searchStartOffset
+	 *            search start offset
+	 * @return found offset
+	 * @throws BadLocationException
+	 */
+	private int findTraceTimestampSearch(int searchStartOffset)
+			throws BadLocationException {
+		int offset;
+
+		// Parse timestamp from the search string
+		String timestamp = SearchUtils.parseTimestampFromString(
+				searchProperties.getSearchString(), true);
+
+		List<TraceProperties> traces = null;
+		List<String> timestamps = null;
+
+		// Get properties from the traces in the view. -2 comes from empty
+		// line in the end of widget and because traces start from offset 0,
+		// not 1
+		traces = TraceViewerGlobals.getTraceViewer().getTraces(
+				view.getShowingTracesFrom(),
+				view.getShowingTracesFrom() + widget.getLineCount() - 2);
+
+		int startTrace = document.getLineOfOffset(searchStartOffset);
+		String currentTraceTimestamp = null;
+
+		// Get the informations array
+		if (traces != null) {
+			TimestampParser parser = TraceViewerGlobals.getTraceViewer()
+					.getDataProcessorAccess().getTimestampParser();
+			timestamps = new ArrayList<String>(traces.size());
+			for (int i = 0; i < traces.size(); i++) {
+				TraceProperties trace = traces.get(i);
+				parser.processData(trace);
+				timestamps.add(trace.timestampString);
+			}
+
+			if (timestamps.size() >= startTrace) {
+				currentTraceTimestamp = timestamps.get(startTrace);
+			}
+		}
+
+		boolean forward = true;
+
+		// Check which way we are searching and modify the start trace
+		// accordingly
+		if (currentTraceTimestamp != null) {
+			if (currentTraceTimestamp.compareTo(timestamp) <= 0) {
+				startTrace++;
+			} else {
+				startTrace--;
+				forward = false;
+			}
+		} else {
+			startTrace++;
+		}
+		upDirectionRadioButton.setSelection(!forward);
+		downDirectionRadioButton.setSelection(forward);
+		searchProperties.setSearchingForward(forward);
+
+		// Get the trace number that matches the timestamp
+		int foundTrace = SearchUtils.findTraceOffsetFromTimestamps(startTrace,
+				timestamp, timestamps, forward);
+
+		if (foundTrace == SearchUtils.NOT_FOUND) {
+			offset = SearchUtils.NOT_FOUND;
+		} else {
+			offset = document.getLineOffset(foundTrace);
+		}
+		return offset;
+	}
+
+	/**
+	 * Processes searching forward
+	 */
+	private void processSearchingForward() {
+		// There is traces below this block
+		int traceCount = TraceViewerGlobals.getTraceViewer()
+				.getDataReaderAccess().getCurrentDataReader().getTraceCount();
+		if (view.getShowingTracesFrom() + widget.getLineCount() < traceCount) {
+
+			searchProperties.setCurrentSearchStartLine(view
+					.getShowingTracesFrom()
+					+ widget.getLineCount()
+					+ (TraceViewerGlobals.blockSize / 2));
+
+			TraceViewerGlobals.getTraceViewer().getDataProcessorAccess()
+					.getSearchProcessor()
+					.processSearch(searchProperties, false);
+		} else { // End Of File
+			// Say EOF to searchProcessor
+			updateSearchProgressBar(traceCount);
+			searchHitEOF();
+		}
+	}
+
+	/**
+	 * Processes searching backwards
+	 */
+	private void processSearchingBackward() {
+		// There is traces above this block
+		if (view.getShowingTracesFrom() > 0) {
+			searchProperties.setCurrentSearchStartLine(view
+					.getShowingTracesFrom()
+					- (TraceViewerGlobals.blockSize / 2));
+			TraceViewerGlobals.getTraceViewer().getDataProcessorAccess()
+					.getSearchProcessor()
+					.processSearch(searchProperties, false);
+		} else { // End (beginning) Of File
+			updateSearchProgressBar(0);
+			searchHitEOF();
+		}
+	}
+
+	/**
+	 * Processes situation where result is found
+	 * 
+	 * @param offset
+	 *            offset of result
+	 */
+	private void processStringFound(int offset) {
+		int line = widget.getLineAtOffset(offset);
+
+		// Update progressBar and linecount label
+		updateSearchProgressBar(view.getShowingTracesFrom() + line);
+
+		// Set search result line to the view
+		TraceViewerGlobals.getTraceViewer().getView().highlightLines(
+				view.getShowingTracesFrom() + line, 0, false);
+	}
+
+	/**
+	 * Gets cursor offset
+	 * 
+	 * @param searchingForward
+	 *            tells which way the search is going
+	 * @return cursor offset
+	 * @throws BadLocationException
+	 */
+	private int getCursorOffset(boolean searchingForward)
+			throws BadLocationException {
+		int cursorOffset;
+
+		if (searchingForward) {
+			cursorOffset = widget.getCaretOffset();
+		} else {
+			int lineNumber = widget.getLineAtOffset(widget.getCaretOffset());
+			int lineLength = document.getLineLength(lineNumber);
+			cursorOffset = widget.getCaretOffset() - lineLength + 1;
+		}
+		// To make sure cursor offset isn't anything stupid
+		if (cursorOffset < 0) {
+			cursorOffset = 0;
+		} else if (cursorOffset >= widget.getCharCount()) {
+			cursorOffset = widget.getCharCount() - 1;
+		}
+		return cursorOffset;
+	}
+
+	/**
+	 * Invokes search from EOF. Is called from view in EOF
+	 */
+	public void endOfFile() {
+		TraceViewerGlobals.getTraceViewer().getDataProcessorAccess()
+				.getSearchProcessor().setHitEOFAlready(true);
+
+		setVariablesToProperties();
+
+		if (searchProperties.isSearchingForward()) { // Down
+			// Start new search from beginning of the file
+			searchProperties.setCurrentSearchStartLine(0);
+			TraceViewerGlobals.getTraceViewer().getDataProcessorAccess()
+					.getSearchProcessor()
+					.processSearch(searchProperties, false);
+		} else { // Searching up
+			searchProperties.setCurrentSearchStartLine(TraceViewerGlobals
+					.getTraceViewer().getDataReaderAccess()
+					.getCurrentDataReader().getTraceCount());
+			TraceViewerGlobals.getTraceViewer().getDataProcessorAccess()
+					.getSearchProcessor()
+					.processSearch(searchProperties, false);
+		}
+	}
+
+	/**
+	 * Enables search button
+	 */
+	public void enableSearchButton() {
+		display.asyncExec(new Runnable() {
+
+			public void run() {
+				if (getShell() != null && !getShell().isDisposed()) {
+
+					// Enable find button
+					if (!findCombo.getText().equals(SearchUtils.EMPTY)) {
+						searchButton.setEnabled(true);
+					}
+
+					// Disable stop button
+					stopSearchButton.setEnabled(false);
+
+					// Set state back to normal
+					TraceViewerGlobals.getTraceViewer().getStateHolder()
+							.setState(StateHolder.State.NORMAL);
+
+					TraceViewerGlobals.getTraceViewer()
+							.getDataProcessorAccess().getSearchProcessor()
+							.setHitEOFAlready(false);
+
+					getShell().setFocus();
+				}
+			}
+
+		});
+	}
+
+	/**
+	 * Sets search text to dialog. Must be called from UI thread!
+	 * 
+	 * @param findStr
+	 *            search text
+	 */
+	public void setSearchText(String findStr) {
+		findCombo.setText(findStr);
+	}
+
+	/**
+	 * Updates search progressBar
+	 * 
+	 * @param selectionPoint
+	 *            selection point where to update
+	 */
+	public void updateSearchProgressBar(int selectionPoint) {
+		display.asyncExec(new SearchDialogProgressBarUpdater(selectionPoint,
+				lineCountLabel));
+	}
+
+	/**
+	 * Search hit full round
+	 */
+	public void searchHitFullRound() {
+		display.asyncExec(new SearchHitFullRoundUpdater());
+	}
+
+	/**
+	 * Search hit EOF
+	 */
+	public void searchHitEOF() {
+		display.asyncExec(new SearchHitEOFUpdater());
+	}
+
+	/**
+	 * Tells is the search dialog open
+	 * 
+	 * @return true if dialog is open
+	 */
+	public boolean isOpen() {
+		boolean isOpen = false;
+		if (getShell() != null && !getShell().isDisposed()) {
+			isOpen = true;
+		}
+		return isOpen;
+	}
+
+	/**
+	 * Tells is the search dialog visible
+	 * 
+	 * @return true if dialog is visible
+	 */
+	public boolean isVisible() {
+		boolean isVisible = false;
+		if (isOpen() && getShell().isVisible()) {
+			isVisible = true;
+		}
+		return isVisible;
+	}
+
+	/**
+	 * Sets focus
+	 */
+	public void setFocus() {
+		Shell shell = getShell();
+		if (shell != null && !shell.isDisposed()) {
+			shell.setFocus();
+		}
+	}
+
+	/**
+	 * Check if dialog is open. If yes, close it
+	 * 
+	 * @return true if dialog was open and was now closed
+	 */
+	public boolean forceClose() {
+		boolean closed = false;
+		Shell shell = getShell();
+		if (shell != null && !shell.isDisposed()) {
+			shell.close();
+			closed = true;
+		}
+		return closed;
+	}
+
+	/**
+	 * Gets previous search string
+	 * 
+	 * @return previous search string or empty String if doesn't exist
+	 */
+	public String getPreviousSearchString() {
+		String previous = ""; //$NON-NLS-1$
+
+		if (comboList != null && comboList.length > 0) {
+			previous = comboList[0];
+		}
+		return previous;
+	}
+}