srcanaapps/depexplorer/com.nokia.s60tools.appdep/src/com/nokia/s60tools/appdep/ui/views/main/MainViewSelectionChangedListener.java
changeset 0 a02c979e8dfd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srcanaapps/depexplorer/com.nokia.s60tools.appdep/src/com/nokia/s60tools/appdep/ui/views/main/MainViewSelectionChangedListener.java	Sat Jan 09 10:04:11 2010 +0530
@@ -0,0 +1,380 @@
+/*
+* 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.views.main;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.NoSuchElementException;
+
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+
+import com.nokia.s60tools.appdep.core.AppDepSettings;
+import com.nokia.s60tools.appdep.core.ITargetPlatform;
+import com.nokia.s60tools.appdep.core.data.CacheDataConstants;
+import com.nokia.s60tools.appdep.core.data.ComponentLinkLeafNode;
+import com.nokia.s60tools.appdep.core.data.ComponentNode;
+import com.nokia.s60tools.appdep.core.data.ComponentParentNode;
+import com.nokia.s60tools.appdep.core.model.ComponentPropertiesData;
+import com.nokia.s60tools.appdep.core.model.ExportFunctionData;
+import com.nokia.s60tools.appdep.core.model.ImportFunctionData;
+import com.nokia.s60tools.appdep.exceptions.CacheFileDoesNotExistException;
+import com.nokia.s60tools.appdep.exceptions.CacheIndexNotReadyException;
+import com.nokia.s60tools.appdep.resources.Messages;
+import com.nokia.s60tools.sdk.SdkInformation;
+
+/**
+ * Selection change listener for main view.
+ */
+public class MainViewSelectionChangedListener implements
+		ISelectionChangedListener {
+
+	//
+	// Members
+	//
+	private final MainView view;
+	private final ArrayList<ImportFunctionData> importFunctionsArrayList;
+	private final ArrayList<ExportFunctionData> exportFunctionsArrayList;
+	private boolean propertiesFoundSuccessfully;
+	
+	/**
+	 * Default constructor.
+	 * @param view Reference to main view
+	 * @param importFunctionsArrayList Import function list to be updated on selection.
+	 * @param exportFunctionsArrayList Export function list to be updated on selection.
+	 */
+	public MainViewSelectionChangedListener(MainView view, 
+										    ArrayList<ImportFunctionData> importFunctionsArrayList,
+										    ArrayList<ExportFunctionData> exportFunctionsArrayList){
+		this.view = view;
+		this.importFunctionsArrayList = importFunctionsArrayList;
+		this.exportFunctionsArrayList = exportFunctionsArrayList;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+	 */
+	public void selectionChanged(SelectionChangedEvent event) {
+		try {			
+			
+			Object obj = view.getComponentTreeSelectedElement();
+			
+			// By default component properties data reference
+			// is set to null
+			view.setSelectedComponentPropertiesData(null);
+						
+			if(obj == null){
+				// We might get null-selections when
+				// tree is expanded/collapsed.
+				return;
+			}
+			else{
+				// Storing the selection for further reference in case 
+				// selection is lost because of the user decides
+				// to use 'Go Into' functionality which loses the selection.
+				view.setMostRecentlySelectedComponentNode(obj);
+			}
+						
+			// The object is for sure an instance of ComponentNode
+			ComponentNode node = (ComponentNode) obj;
+			// Storing name of the selected component (that might be name of the concrete component replacing generic one).
+			String selectedComponentName = node.getName();
+			// Component node instance which is selected or selected leaf node refers to
+			ComponentParentNode componentNodeInstance;
+			// Storing original component name in here, if we are replacing a generic component
+			String selectedComponentOriginalName;
+			if(node instanceof ComponentParentNode){
+				componentNodeInstance = (ComponentParentNode)node;
+			}
+			else{
+				// We have leaf node 
+				ComponentLinkLeafNode leafNode = (ComponentLinkLeafNode)node;
+				// Getting referred component
+				componentNodeInstance = leafNode.getReferredComponent();
+			}
+			// Storing name of the original component if needed
+			if(componentNodeInstance.wasGenericComponent()){
+				selectedComponentOriginalName = componentNodeInstance.getOriginalName();	
+			}else{
+				// No concrete component replacement done and therefore selected component is the original one.
+				selectedComponentOriginalName = selectedComponentName;		
+			}
+			
+			String parentComponentName = node.getParent().getName();
+			
+			AppDepSettings st = AppDepSettings.getActiveSettings();
+			SdkInformation sdkInfo = st.getCurrentlyUsedSdk();
+
+			//Updating tool bar text if the view is fully populated
+			// i.e. dependency search is finished.
+			if(!MainView.isDependencySearchOngoing()){
+				String descr = null;
+				if(sdkInfo != null){
+					descr = 
+							Messages.getString("MainViewSelectionChangedListener.SDK_Prefix") //$NON-NLS-1$
+							+ sdkInfo.getSdkId()
+							+ " - " //$NON-NLS-1$
+							+  st.getCurrentlyUsedTargetPlatformsAsString()
+							+ " " //$NON-NLS-1$
+							+  st.getBuildType().getBuildTypeDescription()
+							+ Messages.getString("MainViewSelectionChangedListener.Component_Prefix") //$NON-NLS-1$
+							+ node.getFullName();
+							
+					view.updateDescription(descr);
+				}
+			}
+			
+			// Fetching property information for the selected component
+			//For properties, cannot use selectedComponentName, because it may point to generic component
+			propertiesFoundSuccessfully = updateComponentPropertyInformation(selectedComponentName, st.getCurrentlyAnalyzedComponentTargetPlatform());
+			
+			// Clearing old information for imported functions
+			importFunctionsArrayList.clear();
+			// and also for exported ones
+			exportFunctionsArrayList.clear();
+
+			// Is currently used SDK configured?
+			if(sdkInfo != null){
+				// Export functions array list can be populated
+				// if component is not an EXE file, because there
+				// might exist EXE and DLL files with the same name,
+				// and the export function information is only available
+				// for DLLs. If EXE files were passed further, it would
+				// give the information for the DLL with the same name.
+				if(! isExeFile(selectedComponentName)){
+					// For exported functions using always concrete component if available
+					updateExportFunctionsArray(selectedComponentName);
+				}				
+			}
+			
+			// Checking if root component has been selected
+			ComponentParentNode pNode = null;
+			if(obj instanceof ComponentParentNode){
+				pNode = (ComponentParentNode) obj;
+				if(pNode.isRootComponent()){
+					// Disabling action that are not valid for root component
+					view.disableSetAsNewRootAction();
+					// The showing of parent import functions
+					// is not applicable for the root component
+					// Just refreshing view when old imported
+					// functions information has been cleared.
+					refreshMainView();
+					return;
+				}
+			}
+			else if(obj instanceof ComponentLinkLeafNode){
+				ComponentLinkLeafNode linkNode = (ComponentLinkLeafNode) obj;
+				pNode = linkNode.getReferredComponent();
+			}
+
+			// Also link node can refer to root component
+			if(pNode.isMissing() || pNode.isRootComponent()){
+				view.disableSetAsNewRootAction();							
+				view.enableLocateComponentAction();
+			}
+			else{
+				view.enableSetAsNewRootAction();
+				view.disableLocateComponentAction();
+			}
+			
+			// Import functions can be fetched selected node is not root component
+			updateImportFunctionsArray(selectedComponentOriginalName, parentComponentName);
+			
+			// Checks if there are unresolved import function names and if those can be fetched from export function data
+			checkForUnresolvedImportFunctionNames();
+			
+			// Finally asking from main view that content providers gets updated data for showing.
+			refreshMainView();
+		}
+		catch (CacheIndexNotReadyException e) {
+			//
+			// This may happen when no SDK selection has been made and therefore
+			// no cache indexes has been created.
+			// There is only single node in tree view with help text available
+			// for selection that for sure raises this exception.
+			//
+			// => can be ignored safely
+			//
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+
+	}
+
+	/**
+	 * Checks if there are unresolved import function names and if those can be fetched from export function data.
+	 * This method does not have any effects if there are no unresolved imported functions, and if there are no
+	 * exported function data available.
+	 * @precondition if there are unresolved imported function names, there has to be valid exported functions data 
+	 *               available for successful operation.
+	 * @postcondition names of unresolved imported function names in <code>importFunctionsArrayList</code> are replaced 
+	 *                by function names got from <code>exportFunctionsArrayList</code>.
+	 */
+	private void checkForUnresolvedImportFunctionNames() {
+		// In case there is no exported data available, there is no use to continue the checking
+		if(exportFunctionsArrayList.size() == 0) return;
+		
+		// Otherwise checking imported functions array for unresolved function names
+		for (int i = 0; i < importFunctionsArrayList.size(); i++) {
+			ImportFunctionData importFunc = importFunctionsArrayList.get(i);
+			if(importFunc.getFunctionName().endsWith(CacheDataConstants.FUNC_NAME_NOT_RESOLVED)){
+				String funcName = getFuncNameFromExportedFunctions(importFunc.getFunctionOrdinalAsInt()); 
+				if(funcName !=  null){
+					importFunc.setFunctionName(funcName);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Gets function name from exported function array list with given ordinal. 
+	 * @param ordinal function ordinal to get name for.
+	 * @return Function name or <code>null</code> if cannot be resolved.
+	 */
+	private String getFuncNameFromExportedFunctions(int ordinal) {
+		// If we have valid ordinal that exists also in exported functions data...
+		if(ordinal > 0 && ordinal <= exportFunctionsArrayList.size()){
+			//...returning the function name for it
+			return exportFunctionsArrayList.get(ordinal-1).getFunctionName();
+		}
+		//  Could not found match from exported function data 
+		return null;
+	}
+
+	/**
+	 * Checks is given file name has EXE extension, or not.
+	 * @param fileNameStr File name to be checked for.
+	 * @return Returns <code>true</code> if file has EXE extension, 
+	 *         otherwise <code>false</code>.
+	 */
+	private boolean isExeFile(String fileNameStr) {
+		int extIndex = fileNameStr.lastIndexOf("."); //$NON-NLS-1$
+		if(extIndex != -1){
+			String extStr = fileNameStr.substring(extIndex+1, fileNameStr.length());
+			if(extStr.equalsIgnoreCase("EXE")){ //$NON-NLS-1$
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Performs refresh and other operation needed to
+	 * run after refresh. 
+	 */
+	private void refreshMainView() {
+		view.refresh();
+		if(propertiesFoundSuccessfully){
+			// This resizes value column which enables the seeing
+			// of all the capabilities defined for the component.
+			view.performValueColumnPackToPropertiesTab();			
+		}
+	}
+
+	/**
+	 * Updates importFunctionsArrayList with information that was found
+	 * for the selected component.
+	 * @param selectedComponentName Name of the component that has been selected.
+	 * @param parentComponentName Parent component of the selected component.
+	 * @throws FileNotFoundException
+	 * @throws IOException
+	 * @throws CacheIndexNotReadyException
+	 * @throws CacheFileDoesNotExistException 
+	 */
+	private void updateImportFunctionsArray(String selectedComponentName, String parentComponentName) throws FileNotFoundException, IOException, CacheIndexNotReadyException, CacheFileDoesNotExistException {
+		
+		importFunctionsArrayList.clear(); // Making sure that array is cleared
+		try {
+			// Non-root component => seeking for the parent imported functions
+			importFunctionsArrayList.addAll(
+											MainViewDataPopulator.getParentImportedFunctionsForComponent(
+																	parentComponentName,
+																	selectedComponentName)
+											);												             												
+		} catch (Exception e) {
+			// Catching exceptions here, because throwing them upper level would prevent fetching of component properties.
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Updates property information for the currently
+	 * selected component.
+	 * @param selectedComponentName Name of the component that has been selected.
+	 * @param targetPlatform Target platform restriction, or <code>null</code> if target platform does not matter.
+	 * @return Returns <code>true</code> of component properties was found successfully, 
+	 *         otherwise returns <code>false</code>.
+	 * @throws IOException
+	 * @throws CacheIndexNotReadyException
+	 */
+	private boolean updateComponentPropertyInformation(String selectedComponentName, ITargetPlatform targetPlatform) throws IOException, CacheIndexNotReadyException {
+		
+		boolean propertiesFound = false;
+		
+		try {
+			
+			ComponentPropertiesData comPropData = MainViewDataPopulator
+														.getComponentPropertyArrayForComponent(selectedComponentName, targetPlatform);
+			propertiesFound = true;
+			view.setSelectedComponentPropertiesData(comPropData);
+		} catch (NoSuchElementException e1) {
+			// This can be ignored because there may be components 
+			// that does not exist in cache at all
+		} catch (java.lang.NullPointerException e1) {
+			// This can be ignored because we'll get this if
+			// currently used SDK is not yet configured and we
+			// select the root node that just advices the user
+			// to double-click the root node.
+		} catch (CacheFileDoesNotExistException e2) {
+			// This might happen during dialog to view transitions
+			// When cache file does not exist yet.
+		} catch (Exception e3) {
+			e3.printStackTrace();
+		}
+		return propertiesFound;
+	}
+
+	/**
+	 * Updates exportFunctionsArrayList with information that was found
+	 * for the selected component.
+	 * @param selectedComponentName Name of the component that has been selected.
+	 * @throws FileNotFoundException
+	 * @throws IOException
+	 * @throws CacheIndexNotReadyException
+	 * @throws CacheFileDoesNotExistException 
+	 */
+	private void updateExportFunctionsArray(String selectedComponentName) throws FileNotFoundException, IOException, CacheIndexNotReadyException, CacheFileDoesNotExistException {
+
+		try {
+			exportFunctionsArrayList.clear(); // Making sure that earlier results are destroyed
+			// Populating with new data
+			exportFunctionsArrayList.addAll(MainViewDataPopulator.getExportedFunctionsForComponent(selectedComponentName));
+
+		} catch (NoSuchElementException e) {
+			// The selected component does necessary
+			// have any data about exported functions.
+			// Therefore we can ignore this exception
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}	
+	
+}