srcanaapps/depexplorer/com.nokia.s60tools.appdep/src/com/nokia/s60tools/appdep/ui/dialogs/AppDepSearchDialog.java
author noe\swadi
Tue, 23 Feb 2010 10:27:57 +0530
changeset 3 ec51f72aa69a
parent 0 a02c979e8dfd
permissions -rw-r--r--
Licenses updated to EPL.

/*
* Copyright (c) 2006 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:
*
*/
 
 
package com.nokia.s60tools.appdep.ui.dialogs;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
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.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IWorkbenchActionConstants;

import com.nokia.s60tools.appdep.AppDepHelpContextIDs;
import com.nokia.s60tools.appdep.core.AppDepSettings;
import com.nokia.s60tools.appdep.core.data.CacheDataManager;
import com.nokia.s60tools.appdep.core.data.ComponentParentNode;
import com.nokia.s60tools.appdep.core.data.ICacheDataManager;
import com.nokia.s60tools.appdep.core.model.AbstractFunctionData;
import com.nokia.s60tools.appdep.exceptions.CacheFileDoesNotExistException;
import com.nokia.s60tools.appdep.locatecomponent.SeekParentNodesService;
import com.nokia.s60tools.appdep.plugin.AppDepPlugin;
import com.nokia.s60tools.appdep.resources.Messages;
import com.nokia.s60tools.appdep.search.MatchType;
import com.nokia.s60tools.appdep.search.SearchConstants;
import com.nokia.s60tools.appdep.search.MatchType.MatchTypes;
import com.nokia.s60tools.appdep.search.SearchConstants.SearchType;
import com.nokia.s60tools.appdep.ui.actions.SelectAllFromListAction;
import com.nokia.s60tools.appdep.ui.actions.ShowMethodCallLocationsSearchDialogAction;
import com.nokia.s60tools.appdep.ui.utils.UiUtils;
import com.nokia.s60tools.appdep.ui.views.main.MainView;
import com.nokia.s60tools.appdep.util.AppDepConsole;
import com.nokia.s60tools.ui.ICopyActionHandler;
import com.nokia.s60tools.ui.IStringProvider;
import com.nokia.s60tools.ui.StringArrayClipboardCopyHandler;
import com.nokia.s60tools.ui.actions.CopyFromStringProviderToClipboardAction;
import com.nokia.s60tools.util.debug.DbgUtility;

/**
 * 
 * Implements search dialog for fetching components or
 * imported/exported functions. 
 *
 * Usage example:
 *
 * <code>
 * <pre>
 * 
 * // Parent shell
 * Shell sh = Display.getCurrent().getActiveShell()
 * 
 * ComponentParentNode rootNode = view.getRootComponentNode();
 * AppDepSearchDialog dlg = new AppDepSearchDialog(sh, SearchType.SEARCH_COMPONENTS, rootNode);
 * dlg.create();
 * dlg.open();			
 *  
 * </pre> 
 * </code>
 * 
 * @see org.eclipse.jface.dialogs.Dialog
 */
public class AppDepSearchDialog extends TrayDialog implements SelectionListener,
														  ModifyListener,
														  IStringProvider{

	/**
	 * Tooltip shown to user when searching components. This is default message at start up when default values are selected from dialog.
	 */
	private static final String TOOLTIP_MSG_COMPONENT_QUERY = Messages.getString("AppDepSearchDialog.Tooltip_Msg_MatchTypeCombo_ComponentQuery"); //$NON-NLS-1$

	/**
	 * Tooltip shown to user when searching functions and 'StartsWith', 'EndsWith', or 'ExactMatch' is selected from math type selection combo box.
	 */
	private static final String TOOLTIP_MSG_USE_FUNC_BASE_NAME = Messages.getString("AppDepSearchDialog.Tooltip_Msg_MatchTypeCombo_FunctionQuery_UsingBaseName"); //$NON-NLS-1$
	
	/**
	 * Tooltip shown to user when searching functions and 'Contains', or 'RegularExpression' is selected from math type selection combo box.
	 */
	private static final String TOOLTIP_MSG_USE_COMPLETE_FUNC_NAME = Messages.getString("AppDepSearchDialog.Tooltip_Msg_MatchTypeCombo_FunctionQuery_UsingLongName"); //$NON-NLS-1$
	
	/**
	 * Maximum amount of data items that are reasonable to show in search result list without making user wait for too long time.
	 * In case maximum result size is exceeded, an informative message is shown for a user.
	 */
	private static final int MAX_RESULTS_SIZE = 30000;

	//
	// Private types
	//
	private Action actionCompPropertiesDataCopy;
	private Action actionSelectAllFromList;
	private Action actionImportShowMethodLoc;	
	
	/**
	 * Match type is attached with description shown in the UI
	 */	
	private class MatchTypeItem{

		private final MatchTypes matchType;
		private final String matchTypeDescription;

		public MatchTypeItem(MatchTypes matchType, String matchTypeDescription){
			this.matchType = matchType;
			this.matchTypeDescription = matchTypeDescription;
			
		}

		/**
		 * @return the matchType
		 */
		public MatchTypes getMatchType() {
			return matchType;
		}

		/**
		 * @return the matchTypeDescription
		 */
		public String getMatchTypeDescription() {
			return matchTypeDescription;
		}

	}
	
	/**
	 * Single result item object in search result list box. 
	 */
	private class SearchResultItem{
		
		/**
		 * Component name
		 */
		private String componentName = null;
		/**
		 * Function name
		 */
		private String functionName = null;
		/**
		 * Function ordinal
		 */
		private String functionOrdinal = null;
		
		/**
		 * Constructor.
		 */
		public SearchResultItem(){			
		}
		
		/**
		 * Gets component name.
		 * @return component name
		 */
		public String getComponentName() {
			return componentName;
		}

		/**
		 * Sets component name
		 * @param componentName component name
		 */
		public void setComponentName(String componentName) {
			this.componentName = componentName;
		}

		/**
		 * Gets function name
		 * @return function name
		 */
		public String getFunctionName() {
			return functionName;
		}

		/**
		 * Sets function name
		 * @param functionName function name
		 */
		public void setFunctionName(String functionName) {
			this.functionName = functionName;
		}

		/**
		 * Gets function ordinal.
		 * @return function ordinal
		 */
		public String getFunctionOrdinal() {
			return functionOrdinal;
		}

		/**
		 * Sets function ordinal
		 * @param functionOrdinal function ordinal
		 */
		public void setFunctionOrdinal(String functionOrdinal) {
			this.functionOrdinal = functionOrdinal;
		}

	}
	
	//
	// Constants
	//
	
	/**
	 * Default width.
	 */
	private static final int DEFAULT_WIDTH = 500;

	/**
	 * Default height.
	 */
	private static final int DEFAULT_HEIGHT = 350;
	
	/**
	 * Default column count for grid layouts.
	 */
	private final int DEFAULT_COLUMN_COUNT = 1;

	/**
	 * Search button ID
	 */
	private static final int SEARCH_BUTTON_ID = IDialogConstants.CLIENT_ID + 1;
	
	//
	// Members
	//
	
	/**
	 * Possible match types available in search dialog.
	 */
	MatchTypeItem[] matchTypeItemArr = {
											new MatchTypeItem(MatchTypes.CONTAINS, Messages.getString("AppDepSearchDialog.Contains_Msg")),  //$NON-NLS-1$
											new MatchTypeItem(MatchTypes.STARTS_WITH, Messages.getString("AppDepSearchDialog.Starts_With_Msg")),  //$NON-NLS-1$
											new MatchTypeItem(MatchTypes.ENDS_WITH, Messages.getString("AppDepSearchDialog.Ends_With_Msg")),  //$NON-NLS-1$
											new MatchTypeItem(MatchTypes.EXACT_MATCH, Messages.getString("AppDepSearchDialog.Exact_Match_Msg")),  //$NON-NLS-1$											
											new MatchTypeItem(MatchTypes.REGULAR_EXPRESSION, Messages.getString("AppDepSearchDialog.Regular_Expression_Msg")) //$NON-NLS-1$
											};
	
    /**
     * Search button starts the search.
     */
	private Button searchButton;
    
    /**
     * Close button closes the dialog.
     */
	private Button closeButton;
	
	/**
	 * Radio button for components search type 
	 */
	Button searchForComponentsRadioBtn;
	
	/**
	 * Radio button for imported functions search type 
	 */
	Button searchForImportedFunctionsRadioBtn;
	
	/**
	 * Radio button for exported functions search type 
	 */
	Button searchForExportedFunctionsRadioBtn;
	
	/**
	 * Combobox for selecting the used match criterion.
	 */
	private Combo matchTypeSelCombo;
	
	/**
	 * Background color for non-editable widgets. 
	 */
	Color nonEditableFieldBkgColor;

	/**
	 * Case sensitivity selection checkbox
	 */
	Button caseSensitivityOptionCheckbox;
	/**
	 * Search string entering field. 
	 */
	private Text searchStringTxtField;
	
	/**
	 * List item for showing list of APIs 
	 */
	private List searchResultList;	
			
	/**
	 * Search type used for actual search.
	 */
	private SearchType selectedSearchType;	
		
	/**
	 * Reference to main view showing the actual data to search for.
	 */
	private final MainView view;

	/**
	 * Map where is results in list as keys and component name, where result belongs as value.
	 * Really needed when results are exported or imported functions, and item in list is not really 
	 * component name, but "<function name>   [<component name>]".  We need to know component name
	 * when double click is performed. Also we need to . 
	 */
	private Map<String, SearchResultItem> resultsMap;
	
	/**
	 * Keeps track if searchResultList contains data of imported functions.
	 */
	private boolean isImportedFunctionsSearched = false;
		
	/**
	 * Constructor.
	 * @param parentShell Parent shell.
	 * @param searchType Default search type for this dialog instance at start-up.
	 * @param view Reference to main view.
	 */
	public AppDepSearchDialog(Shell parentShell, SearchConstants.SearchType searchType,
			                  MainView view) {
		super(parentShell);
    	int shellStyle = getShellStyle() | SWT.RESIZE;
    	setShellStyle(shellStyle);	
		this.selectedSearchType = searchType;
		this.view = view;
	}	

	/* (non-Javadoc)
	 * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
	 */
	protected Control createDialogArea(Composite parent) {
		
		// Creating dialog area composite
		Composite dialogAreaComposite = (Composite) super.createDialogArea(parent);		
		//
		// Defining dialog area layout
		//
		GridLayout gdl = new GridLayout(DEFAULT_COLUMN_COUNT, false);
		GridData gd = new GridData(GridData.FILL_BOTH);
		gd.widthHint = DEFAULT_WIDTH;
		gd.heightHint = DEFAULT_HEIGHT;
		gd.horizontalIndent = IDialogConstants.HORIZONTAL_MARGIN;
		gd.verticalIndent = IDialogConstants.VERTICAL_MARGIN;
		dialogAreaComposite.setLayout(gdl);
		dialogAreaComposite.setLayoutData(gd);		
		// Allocating new color => should be dispose at close
		nonEditableFieldBkgColor = getShell().getDisplay().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
		
		//
		// Adding search label and search text box
		//
		Composite searchFieldsComposite = new Composite(dialogAreaComposite, SWT.NONE);
		final int searchFieldsColumnCount = 2;
		GridLayout gdlComposite = new GridLayout(searchFieldsColumnCount, false);
		GridData gdComposite = new GridData(GridData.FILL_HORIZONTAL);
		searchFieldsComposite.setLayout(gdlComposite);
		searchFieldsComposite.setLayoutData(gdComposite);
		
		// Search string label
		Label searchStringTxtFieldLabel = new Label(searchFieldsComposite, SWT.HORIZONTAL);		
		searchStringTxtFieldLabel.setText(Messages.getString("AppDepSearchDialog.Search_String_Msg")); //$NON-NLS-1$

		// Search string input fields
		final int textFieldStyleBits = SWT.LEFT | SWT.SINGLE | SWT.BACKGROUND | SWT.BORDER;
		searchStringTxtField = new Text(searchFieldsComposite, textFieldStyleBits);
		searchStringTxtField.setLayoutData((new GridData(GridData.FILL_HORIZONTAL)));
		searchStringTxtField.setEditable(true);
		searchStringTxtField.addModifyListener(this);
		searchStringTxtField.addSelectionListener(this);
		
		//
		// Search type
		//
		Group searchTypeGroup = new Group(dialogAreaComposite, SWT.SHADOW_NONE);
		searchTypeGroup.setText(Messages.getString("AppDepSearchDialog.Search_For_Msg"));				 //$NON-NLS-1$
		GridLayout gdl2 = new GridLayout(DEFAULT_COLUMN_COUNT , false);
		GridData gd2 = new GridData(GridData.FILL_HORIZONTAL);				
		searchTypeGroup.setLayout(gdl2);
		searchTypeGroup.setLayoutData(gd2);

		// Component search radio button
		searchForComponentsRadioBtn = new Button(searchTypeGroup, SWT.RADIO);		
		searchForComponentsRadioBtn.setText(Messages.getString("AppDepSearchDialog.Components_Msg")); //$NON-NLS-1$
		searchForComponentsRadioBtn.addSelectionListener(this);
				
		// Imported functions search radio button
		searchForImportedFunctionsRadioBtn = new Button(searchTypeGroup, SWT.RADIO);		
		searchForImportedFunctionsRadioBtn.setText(Messages.getString("AppDepSearchDialog.Imported_Functions_Msg")); //$NON-NLS-1$
		searchForImportedFunctionsRadioBtn.addSelectionListener(this);
		
		// Exported functions search radio button
		searchForExportedFunctionsRadioBtn = new Button(searchTypeGroup, SWT.RADIO);		
		searchForExportedFunctionsRadioBtn.setText(Messages.getString("AppDepSearchDialog.Exported_Functions_Msg")); //$NON-NLS-1$
		searchForExportedFunctionsRadioBtn.addSelectionListener(this);

		// Updating radio button selection states accoring currenlty selected search type
		updateSearchTypeSelectionBtns();
		
		//
		// Options group
		//
		Group searchOptionsGroup = new Group(dialogAreaComposite, SWT.SHADOW_NONE);
		searchOptionsGroup.setText(Messages.getString("AppDepSearchDialog.Options_Msg"));				 //$NON-NLS-1$
		final int optionsGroupColumnCount = 3;
		GridLayout gdl3 = new GridLayout(optionsGroupColumnCount, false);
		GridData gd3 = new GridData(GridData.FILL_HORIZONTAL);				
		searchOptionsGroup.setLayout(gdl3);
		searchOptionsGroup.setLayoutData(gd3);
		
		// Match type combo label
		Label matchTypeLabel = new Label(searchOptionsGroup, SWT.HORIZONTAL | SWT.LEFT);		
		matchTypeLabel.setText(Messages.getString("AppDepSearchDialog.Match_Type_Msg"));		 //$NON-NLS-1$
		
		// Match type combo 
		matchTypeSelCombo = new Combo(searchOptionsGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
		matchTypeSelCombo.setText(Messages.getString("CacheGenerationOptionsWizardPage.ToolchainSelCombo_Text")); //$NON-NLS-1$
		matchTypeSelCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		matchTypeSelCombo.setBackground(nonEditableFieldBkgColor);		
		
		for (int i = 0; i < matchTypeItemArr.length; i++) {
			MatchTypeItem matchType = matchTypeItemArr[i];
			matchTypeSelCombo.add(matchType.getMatchTypeDescription());			
		}
		matchTypeSelCombo.select(0); // Selecting first match type by default
		matchTypeSelCombo.addSelectionListener(this);
		
		// Case sensitivity selection checbox 
		caseSensitivityOptionCheckbox = new Button(searchOptionsGroup, SWT.CHECK);
		caseSensitivityOptionCheckbox.setText(Messages.getString("AppDepSearchDialog.Case_Sensitive_Msg")); //$NON-NLS-1$
		caseSensitivityOptionCheckbox.setSelection(false);
		caseSensitivityOptionCheckbox.addSelectionListener(this);		
		
		//
		// Search Results 
		//
		Label searchResultsLabel = new Label(dialogAreaComposite, SWT.HORIZONTAL);		
		searchResultsLabel.setText(Messages.getString("AppDepSearchDialog.Search_Results_Msg"));		 //$NON-NLS-1$
		
		// List box for results
		final int listBoxStyleBits = SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL;
		searchResultList = new List(dialogAreaComposite, listBoxStyleBits);
		GridData listData1 = new GridData(GridData.FILL_BOTH);
		searchResultList.setLayoutData(listData1);
		searchResultList.setBackground(nonEditableFieldBkgColor);
		
		// Listening for user selections
		MouseListener searchResultListSelListener = new MouseListener(){
			public void mouseDoubleClick(MouseEvent e) {
				searchListObjectDoubleClicked();
			}
			public void mouseDown(MouseEvent e) {
				// No action				
			}
			public void mouseUp(MouseEvent e) {
				// No action				
			}
		};
		searchResultList.addMouseListener(searchResultListSelListener);
		
		// Listening for list selections to prevent using Show Method Call Location with multiple selections.
		SelectionListener searchResultListSelectionListener = new SelectionListener(){
			public void widgetDefaultSelected(SelectionEvent e) {
				// No action
			}

			public void widgetSelected(SelectionEvent e) {
				// Enabling action if needed.
				boolean enableMethodCallLocationsAction = (searchResultList.getSelectionCount() == 1) && isImportedFunctionsSearched; 
				actionImportShowMethodLoc.setEnabled(enableMethodCallLocationsAction);
			}
		};
		searchResultList.addSelectionListener(searchResultListSelectionListener);

		//Adding context menu to list.
		createActionMenu();
		
		// Updating tooltip texts according the current selection status
		updateToolTipTexts();
		
		//
		// And finally adding separator above the dialog button array
		// 
		Label separatorLine = new Label(dialogAreaComposite, SWT.HORIZONTAL | SWT.SEPARATOR);
		separatorLine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
		
	    // Setting context help IDs		
	    AppDepPlugin.setContextSensitiveHelpID(dialogAreaComposite, AppDepHelpContextIDs.APPDEP_SEARCH_DIALOG);
		
		return dialogAreaComposite;
	}
	

	/**
	 * Creating context menu
	 */
	private void createActionMenu(){

		createActions();
		
		MenuManager menuMgr = new MenuManager("#PopupCopyMenu"); //$NON-NLS-1$
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				AppDepSearchDialog.this.fillViewContextMenu(manager);
			}
		});
		Menu menu = menuMgr.createContextMenu(searchResultList);
		searchResultList.setMenu(menu);
			
	}

	/**
	 * Adds items to context menu.
	 * @param manager Menu manager
	 */
	private void fillViewContextMenu(IMenuManager manager) {
		manager.add(actionCompPropertiesDataCopy);
		manager.add(actionSelectAllFromList);
		manager.add(actionImportShowMethodLoc);
		// Other plug-ins can contribute there actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}	
	
	/**
	 * Creates actions for context menu
	 */
	private void createActions() {
		
		StringArrayClipboardCopyHandler copyHandler = new StringArrayClipboardCopyHandler();		
		actionCompPropertiesDataCopy = new CopyFromStringProviderToClipboardAction(this /* listItemsViewer*/,
                												new ICopyActionHandler[]{ copyHandler }
					                                           );
		actionSelectAllFromList = new SelectAllFromListAction(searchResultList);
		actionImportShowMethodLoc = new ShowMethodCallLocationsSearchDialogAction(this, view);
	}
	
	/**
	 * Updates radio buttons states insided search type group
	 * according the current selection.
	 */
	private void updateSearchTypeSelectionBtns() {
		if(selectedSearchType.equals(SearchType.SEARCH_COMPONENTS)){
			searchForComponentsRadioBtn.setSelection(true);			
		}
		else{
			searchForComponentsRadioBtn.setSelection(false);
		}
		if(selectedSearchType.equals(SearchType.SEARCH_IMPORTED_FUNCTIONS)){
			searchForImportedFunctionsRadioBtn.setSelection(true);			
		}
		else{
			searchForImportedFunctionsRadioBtn.setSelection(false);
		}
		if(selectedSearchType.equals(SearchType.SEARCH_EXPORTED_FUNCTION)){
			searchForExportedFunctionsRadioBtn.setSelection(true);			
		}
		else{
			searchForExportedFunctionsRadioBtn.setSelection(false);
		}
	}

    /* (non-Javadoc)
     * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
     */
    protected void configureShell(Shell shell) {    	
        super.configureShell(shell);
        String dialogTopic = getDialogName();
		shell.setText(dialogTopic);
    }

	/**
	 * Gets the dialog name.
	 * @return dialog name
	 */
	private String getDialogName() {
        AppDepSettings st = AppDepSettings.getActiveSettings();

		String currentlyUsedSDK = st.getCurrentlyUsedSdk().getSdkId();
        String variant = st.getCurrentlyUsedTargetPlatformsAsString();
        String build = st.getBuildType().getBuildTypeName();        
        String usedSDKInfo = currentlyUsedSDK + " - " + variant + " " +build;//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ 
        String dialogTopic = Messages.getString("AppDepSearchDialog.Search_Msg") +" " +usedSDKInfo ;//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		return dialogTopic;
	}

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
     */
    protected void createButtonsForButtonBar(Composite parent) {
        // Creating Search button
		searchButton = createButton(parent, SEARCH_BUTTON_ID, Messages.getString("AppDepSearchDialog.Search_Btn_Msg"),true); //$NON-NLS-1$
		searchButton.setEnabled(false); // By default disabled
		searchButton.addSelectionListener(this);
        //Creating Close button
		closeButton = createButton(parent, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL, false);
		closeButton.addSelectionListener(this);
    }

	/* (non-Javadoc)
	 * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
	 */
	public void widgetDefaultSelected(SelectionEvent e) {
		if(e.widget == searchStringTxtField){
			//  <code>widgetDefaultSelected</code> is typically called 
			// when ENTER is pressed in a single-line text.
			}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
	 */
	public void widgetSelected(SelectionEvent e) {
		Widget w = e.widget;
		
		if(w.equals(searchButton)){
			Runnable performAPIDetailsQueryRunnable = new Runnable(){
				public void run(){
					performSearch();
				}
			};
			
			// Showing busy cursor during operation			
			Display d = getShell().getDisplay();
			BusyIndicator.showWhile(d, performAPIDetailsQueryRunnable);
		}		
		else if(w.equals(closeButton)){
			// Otherwise it must be Close button
			this.close(); // close() method is overridden in the end of the file for making clean-up
			return;
		}
		else if(w.equals(matchTypeSelCombo)){
			int selIndex = matchTypeSelCombo.getSelectionIndex();
			MatchTypes selType = matchTypeItemArr[selIndex].getMatchType();
			// Setting enable/disable state of case sensitivity checkbox according the selected match type 
			if(selType.equals(MatchTypes.REGULAR_EXPRESSION)){
				caseSensitivityOptionCheckbox.setEnabled(false);
				caseSensitivityOptionCheckbox.setSelection(false);
			}
			else{
				caseSensitivityOptionCheckbox.setEnabled(true);				
			}
		}
		else if(w.equals(searchForComponentsRadioBtn)){
			selectedSearchType = SearchType.SEARCH_COMPONENTS;
			updateSearchTypeSelectionBtns();
		}
		else if(w.equals(searchForImportedFunctionsRadioBtn)){
			selectedSearchType = SearchType.SEARCH_IMPORTED_FUNCTIONS;
			updateSearchTypeSelectionBtns();
		}
		else if(w.equals(searchForExportedFunctionsRadioBtn)){
			selectedSearchType = SearchType.SEARCH_EXPORTED_FUNCTION;
			updateSearchTypeSelectionBtns();
		}
		
		// Updating tooltip texts according the current selection status
		// This must be called here because selected search type has 
		// to be set before calling the method.
		updateToolTipTexts();
	}

	/**
	 * Sets tooltip text according the selected match type 
	 * and the used query type.
	 * Calling of this method requires that all the referenced 
	 * widgets are created/initialized properly.
	 */
	private void updateToolTipTexts() {
		int selIndex = matchTypeSelCombo.getSelectionIndex();
		MatchTypes selType = matchTypeItemArr[selIndex].getMatchType();
		// Are we querying function data?
		if(selectedSearchType == SearchType.SEARCH_IMPORTED_FUNCTIONS || selectedSearchType == SearchType.SEARCH_EXPORTED_FUNCTION){
			if(selType.equals(MatchTypes.REGULAR_EXPRESSION) || selType.equals(MatchTypes.CONTAINS)){
				matchTypeSelCombo.setToolTipText(TOOLTIP_MSG_USE_COMPLETE_FUNC_NAME);
				return;
			}
			else{
				matchTypeSelCombo.setToolTipText(TOOLTIP_MSG_USE_FUNC_BASE_NAME);
				return;
				}			
		}
		// Otherwise component data is to be queried
		matchTypeSelCombo.setToolTipText(TOOLTIP_MSG_COMPONENT_QUERY);					
	}
       
	/**
	 * Performs the search based on the current dialog parameters.
	 */
	private void performSearch() {

		String searchString = null;
		try {
			// Clearing old results
			searchResultList.removeAll();
			
			// Disabling Show Method Call Locations functionality when list is cleared.
			actionImportShowMethodLoc.setEnabled(false);
			isImportedFunctionsSearched = false;
			
			ICacheDataManager manager = CacheDataManager.getInstance();
			
			searchString = searchStringTxtField.getText();
			MatchType matchType = new MatchType( matchTypeItemArr[matchTypeSelCombo.getSelectionIndex()].matchType );
			//Adding case sensitive parameters, only when its not regular expression 
			if(matchType.getMatchType() != MatchTypes.REGULAR_EXPRESSION){
				boolean isCaseSensitiveSearch = caseSensitivityOptionCheckbox.getSelection();
				matchType.setCaseSensitiveSearch(isCaseSensitiveSearch);
			}
			
			//Get results from manager
			Map<String, java.util.List<AbstractFunctionData>> results = manager.searchCache(searchString, selectedSearchType, matchType);

			if(results != null){
				//Generate results map, where is list strings and component names
				resultsMap = getResultMap(results, selectedSearchType);
				//check if there is not too much results. Checked with imported functions search "L" 
				//that 200000 results takes way too long to set dialog List items, but "newL" search with 13000 result is ok.
				int size = resultsMap.size();
				DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "Search returned "  //$NON-NLS-1$
									+ size + " data items as result when searching with string '" + searchString + "'."); //$NON-NLS-1$ //$NON-NLS-2$
				if(size > MAX_RESULTS_SIZE){
					showTooManyResultsErrorMsg(size);
				}else{
					Set<String> listItems = resultsMap.keySet();
					String[] resultString = (String[]) listItems.toArray(new String[0]);
					searchResultList.setItems(resultString);
					
					// Enabling Show Method Call Locations functionality if imported functions were successfully searched. 
					if(selectedSearchType == SearchType.SEARCH_IMPORTED_FUNCTIONS){
						actionImportShowMethodLoc.setEnabled(true);
						isImportedFunctionsSearched = true;
					}
				}
			}			
			
		} catch (CacheFileDoesNotExistException e) {
			// write to console, show error
			e.printStackTrace();
			String msg = Messages.getString("AppDepSearchDialog.Search_Console_Err_Msg_Part1")  //$NON-NLS-1$
				+ searchString  //$NON-NLS-1$
				+Messages.getString("AppDepSearchDialog.Search_Console_Err_Msg_Part2") //$NON-NLS-1$
				+ e;
			AppDepConsole.getInstance().println(
					msg, AppDepConsole.MSG_ERROR);
			showErrorDialog();
		} catch (IOException e) {
			//  write to console, show error
			e.printStackTrace();
			String msg = Messages.getString("AppDepSearchDialog.Search_Console_Err_Msg_Part1")  //$NON-NLS-1$
				+ searchString  //$NON-NLS-1$
				+Messages.getString("AppDepSearchDialog.Search_Console_Err_Msg_Part2") //$NON-NLS-1$
				+ e;
			AppDepConsole.getInstance().println(msg, AppDepConsole.MSG_ERROR);
			showErrorDialog();
		}
		catch (Exception e) {
			//  write to console, show error
			e.printStackTrace();
			String msg = Messages.getString("AppDepSearchDialog.Search_Console_Err_Msg_Part1")  //$NON-NLS-1$
				+ searchString  //$NON-NLS-1$
				+Messages.getString("AppDepSearchDialog.Search_Console_Err_Msg_Part2") //$NON-NLS-1$
				+ e;
			AppDepConsole.getInstance().println(msg, AppDepConsole.MSG_ERROR);
			showErrorDialog();
		}		
		
	}

	/**
	 * This message is shown in case query returns too many data items 
	 * that cannot be shown in dialog withouth compromising user experience.
	 * @param resultsSize Amount of data items returned as a results.
	 */
	private void showTooManyResultsErrorMsg(int resultsSize) {
		String msg = Messages.getString("AppDepSearchDialog.TooManyResults_ErrMsg_Part1")//$NON-NLS-1$
			+resultsSize + Messages.getString("AppDepSearchDialog.TooManyResults_ErrMsg_Part2");//$NON-NLS-1$
		AppDepMessageBox msgBox = new AppDepMessageBox(msg , SWT.ICON_INFORMATION | SWT.OK );
		msgBox.open();
	}
	
	/**
	 * Gets search results as map (converts the input data).
	 * @param results Original search results to be converted.
	 * @param searchType Type of search performed.
	 * @return Search results as map (converted from the input data).
	 */
	private Map<String, SearchResultItem> getResultMap(Map<String, java.util.List<AbstractFunctionData>> results, SearchType searchType) {
		
		Set<String> keys = results.keySet();
		Map<String, SearchResultItem> resultsArray = new HashMap<String, SearchResultItem>();
		switch (searchType) {
		case SEARCH_COMPONENTS:
			for (String compName : keys) {
				SearchResultItem compData = new SearchResultItem();
				compData.setComponentName(compName);
				resultsArray.put(compName, compData);					
			}
			break;
		case SEARCH_EXPORTED_FUNCTION:
		case SEARCH_IMPORTED_FUNCTIONS:
			for (String compName : keys) {
				java.util.List<AbstractFunctionData> datas = results.get(compName);
				for (AbstractFunctionData data : datas) {
					String functionNameAndCompName = data.getFunctionName() + "   [" + compName +"]"; //$NON-NLS-1$//$NON-NLS-2$
					SearchResultItem compData = new SearchResultItem();
					compData.setComponentName(compName);
					compData.setFunctionName(data.getFunctionName());
					compData.setFunctionOrdinal(data.getFunctionOrdinal());
					resultsArray.put(functionNameAndCompName, compData);
				}
			}
			break;
		default:
			break;		
		}
		return resultsArray;
		
	}

	/**
	 * Shows an error dialog
	 */
	private void showErrorDialog() {
		String msg = Messages.getString("AppDepSearchDialog.Search_User_Err_Msg"); //$NON-NLS-1$
		AppDepMessageBox msgBox = new AppDepMessageBox(msg , SWT.ICON_ERROR | SWT.OK );
		msgBox.open();
	}

	/**
	 * Checks what is selected object in the search results list
	 * and activates and selects it from the UI.
	 */
	private void searchListObjectDoubleClicked() {

		String selectedComponentName = null;
		//get selected component name
		try {
			
			String [] results = searchResultList.getItems();
			//Get selected component name from List:s object data by selection index
			String listItemId = results[searchResultList.getSelectionIndex()];
			SearchResultItem value = resultsMap.get(listItemId);
			selectedComponentName = value.getComponentName();
			
			//get root node of tree
			ComponentParentNode root = getRootNode();
			
			//Seek all parent nodes of tree to find if we have selected component all ready in tree
			Map<String, ComponentParentNode> parentNodes = SeekParentNodesService.findParentNodes(root);
			
			//If component can be found from current component tree, activating selection
			if(parentNodes.containsKey(selectedComponentName.toLowerCase())){			
				ComponentParentNode selectedNode = parentNodes.get(selectedComponentName.toLowerCase());			
				view.activateTreeViewComponent(selectedNode);		
			}
			else{
				//If component cannot be found from current component tree, setting selection as new root
				UiUtils.setComponentAsNewRootInMainView(view, selectedComponentName, null);
			}
		} catch (Exception e) {
			e.printStackTrace();
			String msg = Messages.getString("AppDepSearchDialog.SetComponent_Console_Err_Msg_Part1")  //$NON-NLS-1$
				+ selectedComponentName  //$NON-NLS-1$
				+Messages.getString("AppDepSearchDialog.SetComponent_Console_Err_Msg_Part2") //$NON-NLS-1$
				+ e;
			AppDepConsole.getInstance().println(msg, AppDepConsole.MSG_ERROR);
			showErrorDialog();			
		}
	}

	/**
	 * Gets current root node
	 * @return root node
	 */
	private ComponentParentNode getRootNode() {		
		//Getting new root node from view, not from start node!
		ComponentParentNode root = view.getRootComponentNode();		
		return root;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
	 */
	public void modifyText(ModifyEvent e) {
		if(searchStringTxtField.getText().length() > 0){
			searchButton.setEnabled(true);
		}else{
			searchButton.setEnabled(false);
		}
	}

	/**
	 * Gets selected String from list.
	 */
	public String getString() {
		String[] selectedItems = searchResultList.getSelection();
		if(selectedItems.length > 0){
			StringBuffer items = new StringBuffer();
			
			// There should be at least one item.
			items.append(selectedItems[0]);
			// Adding rest of the strings with new line.
			for(int i = 1;i < selectedItems.length;i++){
				items.append("\r\n"); //$NON-NLS-1$
				items.append(selectedItems[i]);
			}
			return items.toString();
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.dialogs.TrayDialog#close()
	 */
	@Override
	public boolean close() {
		// clean-up
		nonEditableFieldBkgColor.dispose();
		searchStringTxtField.removeSelectionListener(this);
		searchStringTxtField.removeModifyListener(this);
		// Calling super close
		return super.close();
	}

	/**
	 * Get currently selected function.
	 * @return String or <code>null</code>.
	 */
	public String getSelectedFunction() {
		if(searchResultList.getSelectionIndex() >= 0){
			//Get selected function name from list.
			String listItemId = searchResultList.getItem(searchResultList.getSelectionIndex());
			SearchResultItem value = resultsMap.get(listItemId);
			String functionName = value.getFunctionName();
			return functionName;
		}
		return null;
	}

	/**
	 * Get component for currently selected function.
	 * @return String or<code>null</code>.
	 */
	public String getComponentForSelectedFunction() {
		if(searchResultList.getSelectionIndex() >= 0){
			//Get selected component name from list.
			String listItemId = searchResultList.getItem(searchResultList.getSelectionIndex());
			SearchResultItem value = resultsMap.get(listItemId);
			String componentName = value.getComponentName();
			return componentName;
		}
		return null;
	}

	/**
	 * Gets the ordinal of selected function in search results list.
	 * @return ordinal of selected function in search results list, if 
	 * 					a function is selected, otherwise <code>null</code>
	 * 					(i.e. component has been selected or there is 
	 * 					 no selection made).
	 */
	public String getSelectedFunctionOrdinal() {
		if(searchResultList.getSelectionIndex() >= 0){
			//Get selected function ordinal from list.
			String listItemId = searchResultList.getItem(searchResultList.getSelectionIndex());
			SearchResultItem value = resultsMap.get(listItemId);
			String functionOrdinal = value.getFunctionOrdinal();
			return functionOrdinal;
		}
		return null;
	}
	
}