diff -r 000000000000 -r a02c979e8dfd srcanaapps/depexplorer/com.nokia.s60tools.appdep/src/com/nokia/s60tools/appdep/ui/views/main/MainViewSelectionChangedListener.java --- /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 importFunctionsArrayList; + private final ArrayList 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 importFunctionsArrayList, + ArrayList 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 importFunctionsArrayList are replaced + * by function names got from exportFunctionsArrayList. + */ + 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 null 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 true if file has EXE extension, + * otherwise false. + */ + 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 null if target platform does not matter. + * @return Returns true of component properties was found successfully, + * otherwise returns false. + * @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(); + } + } + +}