|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 package com.nokia.s60tools.appdep.ui.views.main; |
|
20 |
|
21 import java.io.FileNotFoundException; |
|
22 import java.io.IOException; |
|
23 import java.util.ArrayList; |
|
24 import java.util.NoSuchElementException; |
|
25 |
|
26 import org.eclipse.jface.viewers.ISelectionChangedListener; |
|
27 import org.eclipse.jface.viewers.SelectionChangedEvent; |
|
28 |
|
29 import com.nokia.s60tools.appdep.core.AppDepSettings; |
|
30 import com.nokia.s60tools.appdep.core.ITargetPlatform; |
|
31 import com.nokia.s60tools.appdep.core.data.CacheDataConstants; |
|
32 import com.nokia.s60tools.appdep.core.data.ComponentLinkLeafNode; |
|
33 import com.nokia.s60tools.appdep.core.data.ComponentNode; |
|
34 import com.nokia.s60tools.appdep.core.data.ComponentParentNode; |
|
35 import com.nokia.s60tools.appdep.core.model.ComponentPropertiesData; |
|
36 import com.nokia.s60tools.appdep.core.model.ExportFunctionData; |
|
37 import com.nokia.s60tools.appdep.core.model.ImportFunctionData; |
|
38 import com.nokia.s60tools.appdep.exceptions.CacheFileDoesNotExistException; |
|
39 import com.nokia.s60tools.appdep.exceptions.CacheIndexNotReadyException; |
|
40 import com.nokia.s60tools.appdep.resources.Messages; |
|
41 import com.nokia.s60tools.sdk.SdkInformation; |
|
42 |
|
43 /** |
|
44 * Selection change listener for main view. |
|
45 */ |
|
46 public class MainViewSelectionChangedListener implements |
|
47 ISelectionChangedListener { |
|
48 |
|
49 // |
|
50 // Members |
|
51 // |
|
52 private final MainView view; |
|
53 private final ArrayList<ImportFunctionData> importFunctionsArrayList; |
|
54 private final ArrayList<ExportFunctionData> exportFunctionsArrayList; |
|
55 private boolean propertiesFoundSuccessfully; |
|
56 |
|
57 /** |
|
58 * Default constructor. |
|
59 * @param view Reference to main view |
|
60 * @param importFunctionsArrayList Import function list to be updated on selection. |
|
61 * @param exportFunctionsArrayList Export function list to be updated on selection. |
|
62 */ |
|
63 public MainViewSelectionChangedListener(MainView view, |
|
64 ArrayList<ImportFunctionData> importFunctionsArrayList, |
|
65 ArrayList<ExportFunctionData> exportFunctionsArrayList){ |
|
66 this.view = view; |
|
67 this.importFunctionsArrayList = importFunctionsArrayList; |
|
68 this.exportFunctionsArrayList = exportFunctionsArrayList; |
|
69 } |
|
70 |
|
71 /* (non-Javadoc) |
|
72 * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) |
|
73 */ |
|
74 public void selectionChanged(SelectionChangedEvent event) { |
|
75 try { |
|
76 |
|
77 Object obj = view.getComponentTreeSelectedElement(); |
|
78 |
|
79 // By default component properties data reference |
|
80 // is set to null |
|
81 view.setSelectedComponentPropertiesData(null); |
|
82 |
|
83 if(obj == null){ |
|
84 // We might get null-selections when |
|
85 // tree is expanded/collapsed. |
|
86 return; |
|
87 } |
|
88 else{ |
|
89 // Storing the selection for further reference in case |
|
90 // selection is lost because of the user decides |
|
91 // to use 'Go Into' functionality which loses the selection. |
|
92 view.setMostRecentlySelectedComponentNode(obj); |
|
93 } |
|
94 |
|
95 // The object is for sure an instance of ComponentNode |
|
96 ComponentNode node = (ComponentNode) obj; |
|
97 // Storing name of the selected component (that might be name of the concrete component replacing generic one). |
|
98 String selectedComponentName = node.getName(); |
|
99 // Component node instance which is selected or selected leaf node refers to |
|
100 ComponentParentNode componentNodeInstance; |
|
101 // Storing original component name in here, if we are replacing a generic component |
|
102 String selectedComponentOriginalName; |
|
103 if(node instanceof ComponentParentNode){ |
|
104 componentNodeInstance = (ComponentParentNode)node; |
|
105 } |
|
106 else{ |
|
107 // We have leaf node |
|
108 ComponentLinkLeafNode leafNode = (ComponentLinkLeafNode)node; |
|
109 // Getting referred component |
|
110 componentNodeInstance = leafNode.getReferredComponent(); |
|
111 } |
|
112 // Storing name of the original component if needed |
|
113 if(componentNodeInstance.wasGenericComponent()){ |
|
114 selectedComponentOriginalName = componentNodeInstance.getOriginalName(); |
|
115 }else{ |
|
116 // No concrete component replacement done and therefore selected component is the original one. |
|
117 selectedComponentOriginalName = selectedComponentName; |
|
118 } |
|
119 |
|
120 String parentComponentName = node.getParent().getName(); |
|
121 |
|
122 AppDepSettings st = AppDepSettings.getActiveSettings(); |
|
123 SdkInformation sdkInfo = st.getCurrentlyUsedSdk(); |
|
124 |
|
125 //Updating tool bar text if the view is fully populated |
|
126 // i.e. dependency search is finished. |
|
127 if(!MainView.isDependencySearchOngoing()){ |
|
128 String descr = null; |
|
129 if(sdkInfo != null){ |
|
130 descr = |
|
131 Messages.getString("MainViewSelectionChangedListener.SDK_Prefix") //$NON-NLS-1$ |
|
132 + sdkInfo.getSdkId() |
|
133 + " - " //$NON-NLS-1$ |
|
134 + st.getCurrentlyUsedTargetPlatformsAsString() |
|
135 + " " //$NON-NLS-1$ |
|
136 + st.getBuildType().getBuildTypeDescription() |
|
137 + Messages.getString("MainViewSelectionChangedListener.Component_Prefix") //$NON-NLS-1$ |
|
138 + node.getFullName(); |
|
139 |
|
140 view.updateDescription(descr); |
|
141 } |
|
142 } |
|
143 |
|
144 // Fetching property information for the selected component |
|
145 //For properties, cannot use selectedComponentName, because it may point to generic component |
|
146 propertiesFoundSuccessfully = updateComponentPropertyInformation(selectedComponentName, st.getCurrentlyAnalyzedComponentTargetPlatform()); |
|
147 |
|
148 // Clearing old information for imported functions |
|
149 importFunctionsArrayList.clear(); |
|
150 // and also for exported ones |
|
151 exportFunctionsArrayList.clear(); |
|
152 |
|
153 // Is currently used SDK configured? |
|
154 if(sdkInfo != null){ |
|
155 // Export functions array list can be populated |
|
156 // if component is not an EXE file, because there |
|
157 // might exist EXE and DLL files with the same name, |
|
158 // and the export function information is only available |
|
159 // for DLLs. If EXE files were passed further, it would |
|
160 // give the information for the DLL with the same name. |
|
161 if(! isExeFile(selectedComponentName)){ |
|
162 // For exported functions using always concrete component if available |
|
163 updateExportFunctionsArray(selectedComponentName); |
|
164 } |
|
165 } |
|
166 |
|
167 // Checking if root component has been selected |
|
168 ComponentParentNode pNode = null; |
|
169 if(obj instanceof ComponentParentNode){ |
|
170 pNode = (ComponentParentNode) obj; |
|
171 if(pNode.isRootComponent()){ |
|
172 // Disabling action that are not valid for root component |
|
173 view.disableSetAsNewRootAction(); |
|
174 // The showing of parent import functions |
|
175 // is not applicable for the root component |
|
176 // Just refreshing view when old imported |
|
177 // functions information has been cleared. |
|
178 refreshMainView(); |
|
179 return; |
|
180 } |
|
181 } |
|
182 else if(obj instanceof ComponentLinkLeafNode){ |
|
183 ComponentLinkLeafNode linkNode = (ComponentLinkLeafNode) obj; |
|
184 pNode = linkNode.getReferredComponent(); |
|
185 } |
|
186 |
|
187 // Also link node can refer to root component |
|
188 if(pNode.isMissing() || pNode.isRootComponent()){ |
|
189 view.disableSetAsNewRootAction(); |
|
190 view.enableLocateComponentAction(); |
|
191 } |
|
192 else{ |
|
193 view.enableSetAsNewRootAction(); |
|
194 view.disableLocateComponentAction(); |
|
195 } |
|
196 |
|
197 // Import functions can be fetched selected node is not root component |
|
198 updateImportFunctionsArray(selectedComponentOriginalName, parentComponentName); |
|
199 |
|
200 // Checks if there are unresolved import function names and if those can be fetched from export function data |
|
201 checkForUnresolvedImportFunctionNames(); |
|
202 |
|
203 // Finally asking from main view that content providers gets updated data for showing. |
|
204 refreshMainView(); |
|
205 } |
|
206 catch (CacheIndexNotReadyException e) { |
|
207 // |
|
208 // This may happen when no SDK selection has been made and therefore |
|
209 // no cache indexes has been created. |
|
210 // There is only single node in tree view with help text available |
|
211 // for selection that for sure raises this exception. |
|
212 // |
|
213 // => can be ignored safely |
|
214 // |
|
215 } |
|
216 catch (Exception e) { |
|
217 e.printStackTrace(); |
|
218 } |
|
219 |
|
220 } |
|
221 |
|
222 /** |
|
223 * Checks if there are unresolved import function names and if those can be fetched from export function data. |
|
224 * This method does not have any effects if there are no unresolved imported functions, and if there are no |
|
225 * exported function data available. |
|
226 * @precondition if there are unresolved imported function names, there has to be valid exported functions data |
|
227 * available for successful operation. |
|
228 * @postcondition names of unresolved imported function names in <code>importFunctionsArrayList</code> are replaced |
|
229 * by function names got from <code>exportFunctionsArrayList</code>. |
|
230 */ |
|
231 private void checkForUnresolvedImportFunctionNames() { |
|
232 // In case there is no exported data available, there is no use to continue the checking |
|
233 if(exportFunctionsArrayList.size() == 0) return; |
|
234 |
|
235 // Otherwise checking imported functions array for unresolved function names |
|
236 for (int i = 0; i < importFunctionsArrayList.size(); i++) { |
|
237 ImportFunctionData importFunc = importFunctionsArrayList.get(i); |
|
238 if(importFunc.getFunctionName().endsWith(CacheDataConstants.FUNC_NAME_NOT_RESOLVED)){ |
|
239 String funcName = getFuncNameFromExportedFunctions(importFunc.getFunctionOrdinalAsInt()); |
|
240 if(funcName != null){ |
|
241 importFunc.setFunctionName(funcName); |
|
242 } |
|
243 } |
|
244 } |
|
245 } |
|
246 |
|
247 /** |
|
248 * Gets function name from exported function array list with given ordinal. |
|
249 * @param ordinal function ordinal to get name for. |
|
250 * @return Function name or <code>null</code> if cannot be resolved. |
|
251 */ |
|
252 private String getFuncNameFromExportedFunctions(int ordinal) { |
|
253 // If we have valid ordinal that exists also in exported functions data... |
|
254 if(ordinal > 0 && ordinal <= exportFunctionsArrayList.size()){ |
|
255 //...returning the function name for it |
|
256 return exportFunctionsArrayList.get(ordinal-1).getFunctionName(); |
|
257 } |
|
258 // Could not found match from exported function data |
|
259 return null; |
|
260 } |
|
261 |
|
262 /** |
|
263 * Checks is given file name has EXE extension, or not. |
|
264 * @param fileNameStr File name to be checked for. |
|
265 * @return Returns <code>true</code> if file has EXE extension, |
|
266 * otherwise <code>false</code>. |
|
267 */ |
|
268 private boolean isExeFile(String fileNameStr) { |
|
269 int extIndex = fileNameStr.lastIndexOf("."); //$NON-NLS-1$ |
|
270 if(extIndex != -1){ |
|
271 String extStr = fileNameStr.substring(extIndex+1, fileNameStr.length()); |
|
272 if(extStr.equalsIgnoreCase("EXE")){ //$NON-NLS-1$ |
|
273 return true; |
|
274 } |
|
275 } |
|
276 return false; |
|
277 } |
|
278 |
|
279 /** |
|
280 * Performs refresh and other operation needed to |
|
281 * run after refresh. |
|
282 */ |
|
283 private void refreshMainView() { |
|
284 view.refresh(); |
|
285 if(propertiesFoundSuccessfully){ |
|
286 // This resizes value column which enables the seeing |
|
287 // of all the capabilities defined for the component. |
|
288 view.performValueColumnPackToPropertiesTab(); |
|
289 } |
|
290 } |
|
291 |
|
292 /** |
|
293 * Updates importFunctionsArrayList with information that was found |
|
294 * for the selected component. |
|
295 * @param selectedComponentName Name of the component that has been selected. |
|
296 * @param parentComponentName Parent component of the selected component. |
|
297 * @throws FileNotFoundException |
|
298 * @throws IOException |
|
299 * @throws CacheIndexNotReadyException |
|
300 * @throws CacheFileDoesNotExistException |
|
301 */ |
|
302 private void updateImportFunctionsArray(String selectedComponentName, String parentComponentName) throws FileNotFoundException, IOException, CacheIndexNotReadyException, CacheFileDoesNotExistException { |
|
303 |
|
304 importFunctionsArrayList.clear(); // Making sure that array is cleared |
|
305 try { |
|
306 // Non-root component => seeking for the parent imported functions |
|
307 importFunctionsArrayList.addAll( |
|
308 MainViewDataPopulator.getParentImportedFunctionsForComponent( |
|
309 parentComponentName, |
|
310 selectedComponentName) |
|
311 ); |
|
312 } catch (Exception e) { |
|
313 // Catching exceptions here, because throwing them upper level would prevent fetching of component properties. |
|
314 e.printStackTrace(); |
|
315 } |
|
316 } |
|
317 |
|
318 /** |
|
319 * Updates property information for the currently |
|
320 * selected component. |
|
321 * @param selectedComponentName Name of the component that has been selected. |
|
322 * @param targetPlatform Target platform restriction, or <code>null</code> if target platform does not matter. |
|
323 * @return Returns <code>true</code> of component properties was found successfully, |
|
324 * otherwise returns <code>false</code>. |
|
325 * @throws IOException |
|
326 * @throws CacheIndexNotReadyException |
|
327 */ |
|
328 private boolean updateComponentPropertyInformation(String selectedComponentName, ITargetPlatform targetPlatform) throws IOException, CacheIndexNotReadyException { |
|
329 |
|
330 boolean propertiesFound = false; |
|
331 |
|
332 try { |
|
333 |
|
334 ComponentPropertiesData comPropData = MainViewDataPopulator |
|
335 .getComponentPropertyArrayForComponent(selectedComponentName, targetPlatform); |
|
336 propertiesFound = true; |
|
337 view.setSelectedComponentPropertiesData(comPropData); |
|
338 } catch (NoSuchElementException e1) { |
|
339 // This can be ignored because there may be components |
|
340 // that does not exist in cache at all |
|
341 } catch (java.lang.NullPointerException e1) { |
|
342 // This can be ignored because we'll get this if |
|
343 // currently used SDK is not yet configured and we |
|
344 // select the root node that just advices the user |
|
345 // to double-click the root node. |
|
346 } catch (CacheFileDoesNotExistException e2) { |
|
347 // This might happen during dialog to view transitions |
|
348 // When cache file does not exist yet. |
|
349 } catch (Exception e3) { |
|
350 e3.printStackTrace(); |
|
351 } |
|
352 return propertiesFound; |
|
353 } |
|
354 |
|
355 /** |
|
356 * Updates exportFunctionsArrayList with information that was found |
|
357 * for the selected component. |
|
358 * @param selectedComponentName Name of the component that has been selected. |
|
359 * @throws FileNotFoundException |
|
360 * @throws IOException |
|
361 * @throws CacheIndexNotReadyException |
|
362 * @throws CacheFileDoesNotExistException |
|
363 */ |
|
364 private void updateExportFunctionsArray(String selectedComponentName) throws FileNotFoundException, IOException, CacheIndexNotReadyException, CacheFileDoesNotExistException { |
|
365 |
|
366 try { |
|
367 exportFunctionsArrayList.clear(); // Making sure that earlier results are destroyed |
|
368 // Populating with new data |
|
369 exportFunctionsArrayList.addAll(MainViewDataPopulator.getExportedFunctionsForComponent(selectedComponentName)); |
|
370 |
|
371 } catch (NoSuchElementException e) { |
|
372 // The selected component does necessary |
|
373 // have any data about exported functions. |
|
374 // Therefore we can ignore this exception |
|
375 } catch (Exception e) { |
|
376 e.printStackTrace(); |
|
377 } |
|
378 } |
|
379 |
|
380 } |