diff -r ed1c9f64298a -r 5b9d4d8641ce trace/traceviewer/com.nokia.traceviewer/src/com/nokia/traceviewer/dialog/SearchDialog.java --- /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 traces = null; + List 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(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 traces = null; + List 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(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; + } +}