Initial version of Performance Investigator under EPL
authorMatti Laitinen <matti.t.laitinen@nokia.com>
Thu, 11 Feb 2010 15:32:31 +0200
changeset 2 b9ab3b238396
parent 1 1050670c6980
child 3 431bbaccaec8
Initial version of Performance Investigator under EPL
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/Carbide_Image.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/feature.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/feature.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/license.txt
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/profilerbuild.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/sourceTemplateFeature/Carbide_Image.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/sourceTemplateFeature/feature.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/sourceTemplateFeature/license.txt
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/.settings/org.eclipse.core.resources.prefs
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/BarGraphDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/DrawBinariesDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/DrawThreadsDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/ExportDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/FillAllDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/FillNoneDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/FillSelectedDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/VisualFunctionsDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddrBinaryTable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddrDataPerTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddrFunctionTable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddrThreadTable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddressPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddressReturnPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GenericAddrTable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppFunction.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppProcess.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppSample.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTableSorter.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppThread.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTraceCsvPrinter.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTraceGraph.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTraceGraphActionListener.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTraceParser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppVisualiserPanel.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/SomMapping.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/data/default.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/icons/PI_Meter_16x16.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/icons/PI_Meter_20x20.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/plugin.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupMapAddDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupMapEditDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupMapTableViewer.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupPreferenceConstants.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupProfileDuplicateDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupProfileEditDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupProfileTreeViewer.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ButtonPreferencePage.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ButtonTabPage.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ExportBupMapGetXmlTask.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ExportBupMapWizard.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ExportBupMapWizardDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ImportBupMapGetXmlTask.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ImportBupMapShowOverLapTask.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ImportBupMapWizard.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ImportBupMapWizardDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ModifyCachedBupEventMap.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/SwitchBupMapDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupEventDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupEventMapManager.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupMapSwitchAction.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupSample.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupTraceGraph.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupTraceParser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupUpdater.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/ButtonPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/ButtonReturnPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/ComNokiaCarbidePiButtonHelpIDs.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/IBupEventMap.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/IBupEventMapEditable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/IBupEventMapProfile.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/.settings/org.eclipse.core.resources.prefs
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/CallPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/CallReturnPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/CallTraceGraph.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/CallVisualiser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/GfcFunctionItem.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/GfcSample.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/GfcTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/GfcTraceParser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/.settings/org.eclipse.core.resources.prefs
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/src/com/nokia/carbide/cpp/pi/core/PICorePlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/src/com/nokia/carbide/cpp/pi/core/PIProjectNature.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/src/com/nokia/carbide/cpp/pi/core/SessionPreferences.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/book.css
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/build_index.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/Getting_Started/GS_index.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/Getting_Started/example_project.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/Getting_Started/tour.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/bugs_fixed.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/cheatsheets/getStarted_pi_cs.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/abbrev.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/analyser.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/basic_operation.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/button_press_capture.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/dll_support.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/func_level_load.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/images/con_memory_usage.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/images/view_button_markers.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/learn_prof.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/memory_usage_capture.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/methods.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/overview/overview.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/overview/sw_performance.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/perfanalysis/perf_basic_procedures.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/perfanalysis/perf_other_dynamic_mem.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/perfanalysis/perf_other_server_threads.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/perfanalysis/perf_other_subjects.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/perfanalysis/perfanalysis.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/power_usage_capture.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/com_nokia_carbide_pi_address.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/com_nokia_carbide_pi_button.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/com_nokia_carbide_pi_call.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/com_nokia_carbide_pi_wizards.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/org_eclipse_ui.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/pi.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_fig1.jpg
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_fig1.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_fig2.jpg
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_fig2.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_figure1.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_figure2.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_figure3.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_figure4.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/N73device.jpg
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/about_cpp.jpg
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/about_cpp.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/background_carbide.jpg
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/brandmark_cpp.gif
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/command_link.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/concpt_thread_analysis.jpg
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/concpt_thread_analysis.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/copy_drilldown_table.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/fig3_rslv_func_offset.jpg
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/fig3_rslv_func_offset.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/fig4_prin_lnkd_func.jpg
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/fig4_prin_lnkd_func.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/figure5.jpg
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/figure5.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/figure6.jpg
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/figure6.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/gold_header.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/icons/pi.gif
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/icons/pi_hov.gif
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/overview.jpg
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/overview.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/wnd_import_rom_build_files.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/index.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/legal.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/profiler.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/abbrev.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/GUI_tour.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/an_installation.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/an_use_case_features.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/analyser.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/analyzing_table_data.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/binary_load.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/context_menu.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/function_calls.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/function_load.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/analyzer_mainview.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/analz_graphitem.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/analz_loads_tabs.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/analz_plugins.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/analz_startend.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/binary_mode_graph.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/chng_threshold.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/chng_threshold1.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/function_call_info.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/function_mode_graph.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/icon_select_time_interval.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/icon_show_entire_graph.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/icon_zoom_in.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/icon_zoom_out.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/icon_zoom_to_selected_int.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/investigator_menu.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/memory_usage_stats.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/menu_memory_usage.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/menu_power_usage.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/savetable1.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/savetable2.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/savetable3.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/thread_mode_graph.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/view_memory_usage.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/view_power_usage.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/wnd_memory_usage_stats.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/wnd_power_usage_settings.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/wnd_power_usage_stats.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/wnd_select_time_interval.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/import_rom_build_files.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/investigator_menu.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/main_view.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/menu_memory_graph.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/menu_power_graph.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/save_table.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/thread_load.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/threshold.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/view_memory_usage.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/view_power_usage.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/wnd_memory_usage_statistics.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/wnd_power_graph_settings.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/wnd_power_usage_statistics.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/banked_registers.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/compile_time.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/cpu_timer.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/curr_pgm_status_reg.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/delayed_fn_call.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/dynamic_bin_res.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/file_sys_storing.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/int_stack.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/kernel_containers.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/kernel_hook.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/link_register.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/os_thread.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/periodic_int.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/pgm_counter.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/proc_mode.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/read_write_load.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/rofs.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/saved_pgm_status_reg.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/serial_output.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/sw_interrupt.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/swi_interrupt.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/tcpip.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/BUP_trace.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/DSP_trace.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/GFC_trace.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/GPP_trace.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/IRQ_trace.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/ITT_trace.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/MEM_trace.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/PRI_trace.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/PWR_trace.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/SWI_trace.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/TIP_trace.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/Trace_Items.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/advanced_options.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/cmd_line_overview.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/AdvancedOptionsEditBox.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/AdvancedOptionsEditBox_uiq.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/AdvancedOptionsWindow.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/OutputOptionsWindow_DebugPort.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/OutputOptionsWindow_FileSystem.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/S60GUI.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/S80GUI.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/S90GUI.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/SamplingProfilerMainWindow.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/SamplingProfilerMainWindow_uiq.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptions.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptionsList.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptionsList2.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptionsList3.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptionsList3_uiq.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptionsList_uiq.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptions_uiq.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/cmd_line_eshell_example.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/gpp_bargraph.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/profiler_button_press_option.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/profiler_configuration.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/profiler_install.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/profiler_start_profiler.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/profiler_start_profiler_uiq.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/screen_output_settings.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/screen_output_settings_02.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/sw_root_directory.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/uiq_setting_advanced_settings.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/uiq_setting_output_settings.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/uiq_setting_tracing_options.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/uiq_using_the_profiler.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/output_settings.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/prof_using.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/profiler.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/tracing_options.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/settings.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/release_notes.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/an_load_trace_files.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/btn_press_change.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/btn_press_show.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/chng_graphcolor.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step1.PNG
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step2.PNG
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step3.PNG
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step4.PNG
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step5.PNG
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step6.PNG
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/exportkeyprofile.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/import_dat_file_step3.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/import_dat_file_step4.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/import_dat_file_step5.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_keyprofile.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_selectkeymap.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step1.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step2.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step3.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step4.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step5.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step6.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step7.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importkeyprofile.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importkeyprofileoverlap.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/menu_open_src_for_function.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/npi_prop.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_pref.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_pref_add.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_pref_edit.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_pref_edit_entry.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_pref_new.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_thread_load_01.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_thread_load_02.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_thread_load_03.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/recolor_graphitem.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/set_threshold.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/start_end.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/switch_key_profile.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/time_interval.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/key_profile_exp.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/key_profile_imp.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/key_profile_pref.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/key_profile_select.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/key_profile_switch.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/set_thresholds.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/source_lookup.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/time_interval.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/images/wizard_new_connection.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/images/wnd_bluetooth_config.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/images/wnd_bluetooth_config_services.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/bluetooth_connection.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/btn_press_enable.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/exp_keyprofile.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/exp_keyprofile2.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/imp_keyprofile.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/imp_keyprofile2.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/imp_keyprofile3.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/srch_devices.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/key_profile_exp.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/key_profile_imp.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/prof_installation.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/serial_connection.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/usb_connection.htm
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/intro/overviewProfilerExtContent.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/intro/pi.css
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/intro/pi.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/intro/tutorialsProfilerExtContent.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/intro/whatsnewProfilerExtContent.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/tocAnalyzer.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/tocConcepts.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/tocPI.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/tocProfiler.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/tocRelease.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/.settings/org.eclipse.core.resources.prefs
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/FunctionPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/FunctionReturnPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/GfcTraceVisualiser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/NewFunctionAnalyse.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/.settings/org.eclipse.core.resources.prefs
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/AdvancedMemoryMap.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/BinaryReader.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/BinaryReader122.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/BinaryReaderResult.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/DecidedPool.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/InstrPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/InstrReturnPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/IttEvent122.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/IttSample.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/IttTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/IttTrace122.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/IttTraceParser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/MapFile.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/PiInstrFunctionResolver.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/ProcessedBinary.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/UndecidedPool.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/internal/pi/memory/actions/DynamicScaleDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/internal/pi/memory/actions/MemoryStatisticsDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/internal/pi/memory/actions/ShowHeapDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/internal/pi/memory/actions/ShowStackDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/internal/pi/memory/actions/ShowTotalDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MaxMemoryItem.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemSample.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemSampleByTime.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemThread.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemThreadTable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemTraceGraph.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemTraceParser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemoryPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemoryReturnPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/internal/pi/power/actions/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/internal/pi/power/actions/PowerSettingsDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/internal/pi/power/actions/PowerStatisticsDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/internal/pi/power/actions/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PowerPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PowerReturnPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PowerTraceGraph.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PwrSample.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PwrTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PwrTraceGraph.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PwrTraceParser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/.settings/org.eclipse.core.resources.prefs
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriSample.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriThread.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriTraceParser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriorityPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriorityReturnPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/NewPriSample.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/NewPriThread.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/NewPriTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/NewPriTraceParser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/Priority2Plugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/Priority2ReturnPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/toc.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/.settings/org.eclipse.core.resources.prefs
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/Carbide_c_icon_16x16.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/Carbide_c_icon_24x24.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/Carbide_c_icon_32x32.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/Carbide_c_icon_48x48.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/about.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/about_cpp.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/pi_ovr.gif
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/src/com/nokia/carbide/cpp/internal/pi/ui/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/src/com/nokia/carbide/cpp/internal/pi/ui/PIUiPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/src/com/nokia/carbide/cpp/internal/pi/ui/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.update/site.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/.settings/org.eclipse.core.resources.prefs
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/plugin.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/schema/PIConfig.ecore
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/schema/PIConfig.genmodel
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/schema/PIConfig.xsd
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/schema/PIConfig.xsd2ecore
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/PIConfigXMLLoader.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/ButtonEventProfileListType.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/ButtonEventProfileType.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/DocumentRoot.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/MappingType.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/PIConfigFactory.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/PIConfigPackage.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/ButtonEventProfileListTypeImpl.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/ButtonEventProfileTypeImpl.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/DocumentRootImpl.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/MappingTypeImpl.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/PIConfigFactoryImpl.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/PIConfigPackageImpl.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/util/PIConfigAdapterFactory.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/util/PIConfigResourceFactoryImpl.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/util/PIConfigResourceImpl.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/util/PIConfigSwitch.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/util/PIConfigXMLProcessor.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/AWTColorPalette.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/BinaryColorPalette.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/CacheMap.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/ColorPalette.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/DataMiningPalette.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/FunctionColorPalette.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/GeneralMessages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/GuessAndFixPath.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/IDisposable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/ITableColorPalette.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/PIExceptionRuntime.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/PIUtilPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/SourceLookup.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/SourceLookupFileChooserDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/TableColorPalette.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/TestDataMiningPalette.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/TestTableColorPalette.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/ThreadColorPalette.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/.settings/org.eclipse.core.resources.prefs
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/icons/PI_Meter_16x16.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/icons/PI_Meter_20x20.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/log/Logfile.1
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/log/Snapshot.1
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/log/Version_Number
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/INewPIWizardSettings.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizard.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardObySymbolPairDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPage.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageBupMapTask.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageConfigSelectorTask.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageCustomTask.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageInputTask.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageOutputTask.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPagePkgListTask.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPagePkgSdkDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageRomSdkSubTask.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageRomSubTask.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardRemovePkgDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardSettings.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/UiFileFilter.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/CarbidePiWizardHelpIds.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/IPkgEntry.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgEntryList.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgListBaseCustomItem.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgListTree.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgListTreeContentProvider.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgListTreeLabelProvider.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgListTreeViewer.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/RofsObySymbolPair.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/SdkChooserBase.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/pi/wizards/WizardsPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/.classpath
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/.settings/org.eclipse.core.resources.prefs
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/META-INF/MANIFEST.MF
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/build.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Carbide_c_icon_16x16.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Carbide_c_icon_24x24.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Carbide_c_icon_32x32.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Carbide_c_icon_48x48.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/PI_Meter_16x16.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/PI_Meter_20x20.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Set_current_time_interval.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Set_current_time_interval_16.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/about.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/about_cpp.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/show_entire_graph.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/show_entire_graph_16.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_in.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_in_16.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_out.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_out_16.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_to_time_interval.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_to_time_interval_16.png
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/plugin.xml
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/schema/piPluginData.exsd
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ActionDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/AnalysisDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/AnalysisInfoDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/EventDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/SaveListScreenShot.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/SaveSamples.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/SaveScreenShotDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/SetThresholdsDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ShowEndDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ShowStartDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/SynchronizeDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/TimeSetAction.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/TimeSetDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/TooltipsDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ViewDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ZoomInDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ZoomOutDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ZoomToSelectionDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ZoomToTraceDelegate.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/AnalyserDataProcessor.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/AnalyserException.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/CancelException.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/EventHandler.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/NpiInstanceRepository.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/PIChangeEvent.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/ParserRepository.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/ProfileReader.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/ProfileVisualiser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/StreamFileParser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/TestGUI.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/IPiItem.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/IReturnPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/ISaveSamples.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/ISaveTable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/IToolBarActionListener.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/BackgroundLoader.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/PluginInitialiser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/PluginRegisterer.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/PluginRegistry.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/RegisterEntry.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/TraceTypePreviewer.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/Binary.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/CusSample.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/Function.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/FunctionResolver.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GUITooltips.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericEvent.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericEventTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericSample.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericSampleWithFunctions.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericSampledTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericSampledTraceWithFunctions.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericThread.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ParsedTraceData.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/Parser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/PiItemType.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/PiManager.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/PiManagerEvent.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/PiManagerListener.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledBinary.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledDspHook.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledFunction.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledGeneric.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledThread.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledThreshold.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProgressBar.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/RefinableTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/TraceDataContainer.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/TraceDataRepository.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/TraceTimeWindow.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/TraceWithThreads.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/perspectives/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/perspectives/PiPerspectiveFactory.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/perspectives/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/AbstractPiPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IAnalysisItem.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IAnalysisSpecificMenu.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IClassReplacer.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IContextMenu.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IEventListener.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IExportItem.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IFinalizeTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IImportMenu.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IImportableTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IMenu.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IOpenOtherMenu.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IOpenOtherTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IRecordable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IReportable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/ITrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IViewMenu.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IVisualizable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/properties/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/properties/PIPropertyPage.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/properties/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/resolvers/CachedFunctionResolver.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/resolvers/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/resolvers/RofsSymbolFileFunctionResolver.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/resolvers/SymbolFileFunctionResolver.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/resolvers/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/SaveSamplesPage.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/SaveSamplesWizard.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/SaveTableWizard.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/SaveTableWizardPage.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/AnalysisInfoHandler.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/BappeaAnalysisInfo.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/EnabledTrace.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/IProvideTraceAdditionalInfo.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/PIAnalyser.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/PIAnalysisInfo.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/TraceAdditionalInfo.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/AlphabeticItem.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/AlphabeticValueGenerator.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/DebugDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/JarClassLoader.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/PIFileFilter.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/PIUtilities.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/PluginClassLoader.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/QuickSortImpl.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/Sortable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/AnalyserVisualState.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/AnalysisInfoPanel.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/Defines.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/GenericTable.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/GenericTraceGraph.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/GraphComposite.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/GraphDrawRequest.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/PICompositePanel.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/PIEvent.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/PIEventListener.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/PIVisualSharedData.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/SynchroniseDialog.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/ComNokiaCarbidePiHelpIDs.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/PiPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/PiReturnPlugin.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/editors/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/editors/PIPageEditor.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/editors/PIPageEditorContributor.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/editors/messages.properties
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/importer/Messages.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/importer/SampleImporter.java
sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/importer/messages.properties
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/Carbide_Image.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,5 @@
+bin.includes = feature.xml,\
+               Carbide_Image.png,\
+               license.txt,\
+	       feature.properties
+generate.feature@com.nokia.carbide.cpp.pi.source=com.nokia.carbide.cpp.pi
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/feature.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2 @@
+# "featureName" property - name of the feature
+featureName=Carbide.c++ Performance Investigator
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/feature.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,434 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="com.nokia.carbide.cpp.pi"
+      label="%featureName"
+      version="2.1.0.qualifier"
+      provider-name="Nokia"
+      plugin="com.nokia.carbide.cpp"
+      image="Carbide_Image.png">
+
+   <description>
+      The Carbide.c++ Performance Investigator lets the user
+analyze performance data gathered on a handheld device by
+the Carbide.c++ Profiler application.
+   </description>
+
+   <copyright>
+      Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
+   </copyright>
+
+   <license url="license.txt">
+      COPYRIGHT LICENSE
+
+      NOKIA CORPORATION END-USER SOFTWARE AGREEMENT FOR
+      CARBIDE.C++ AND ASSOCIATED ON-DEVICE APPLICATIONS
+
+This Software Agreement (&quot;Agreement&quot;) is between You (either an
+individual or an entity), the End User, and Nokia Corporation
+(&quot;Nokia&quot;). The Agreement authorizes You to use the Software specified
+in Clause 1 below, which may be stored on a CD-ROM, sent to You by
+electronic mail, or downloaded from Nokia&apos;s Web pages or Servers or
+from other sources under the terms and conditions set forth below.
+This is an agreement on end-user rights and not an agreement for sale.
+Nokia continues to own the copy of the Software and the physical media
+contained in the sales package and any other copy that You are
+authorized to make pursuant to this Agreement.
+
+Read this Agreement carefully before installing, downloading, or using
+the Software. By clicking on the &quot;I Accept&quot; button while installing,
+downloading, and/or using the Software, You agree to the terms and
+conditions of this Agreement. If You do not agree to all of the terms
+and conditions of this Agreement, promptly click the &quot;Decline&quot; or
+&quot;I Do Not Accept&quot; button, cancel the installation or downloading, or
+destroy or return the Software and accompanying documentation to
+Nokia. YOU AGREE THAT YOUR USE OF THE SOFTWARE ACKNOWLEDGES THAT YOU
+HAVE READ THIS AGREEMENT, UNDERSTAND IT, AND AGREE TO BE BOUND BY ITS
+TERMS AND CONDITIONS.
+
+
+1. SOFTWARE.
+
+As used in this Agreement, the term &quot;Software&quot; means, collectively:
+(i) the software product identified above (ii) all the contents of the
+disk(s), CD-ROM(s), electronic mail and its file attachments, or other
+media with which this Agreement is provided, including the object code
+form of the software delivered via a CD-ROM, electronic mail, or Web
+page (iii) digital images, stock photographs, clip art, or other
+artistic works (&quot;Stock Files&quot;) (iv) related explanatory written
+materials and any other possible documentation related thereto
+(&quot;Documentation&quot;); (v) fonts, and (vi) upgrades, modified versions,
+updates, additions, and copies of the Software (collectively
+&quot;Updates&quot;), if any, licensed to You by Nokia under this Agreement.
+
+
+2. END USER RIGHTS AND USE.
+
+Nokia grants to You non-exclusive, non-transferable end-user rights to
+install the Software on the local hard disk(s) or other permanent
+storage media of one computer and use the Software on a single
+computer or terminal at a time.
+
+You acknowledge that the use of the Software may require licenses to
+third party patents and that Nokia does not grant any licenses to such
+third party patents under this Agreement to You.  Also, any and
+all standards related licenses with respect to Essential Patents (as
+defined below) are specifically excluded from the scope of this
+Agreement, and those licenses need to be acquired separately from
+Nokia or the respective right holders, as the case may be. &quot;Essential
+Patent&quot; means any patent claiming a feature necessarily and
+unavoidably required for compliance with industry standards (usually
+GSM, WCDMA or other similar mobile communications standard), to the
+limited extent only that infringement or use of such claims of a
+patent cannot be avoided in remaining compliant with industry standard
+either for technological reasons or for lack of commercially viable
+technical alternatives.
+
+No patent licenses to any patents of Nokia and/ or its Affiliates are
+granted under this Agreement.
+
+
+3. LIMITATIONS ON END USER RIGHTS.
+
+You may not copy, distribute, or make derivative works of the Software
+except as follows:
+
+(a) You may make one copy of the Software on magnetic media as an
+archival backup copy, provided Your archival backup copy is not
+installed or used on any computer. Any other copies You make of the
+Software are in violation of this Agreement.
+
+(b) You may not use, modify, translate, reproduce, or transfer the
+right to use the Software or copy the Software except as expressly
+provided in this Agreement.
+
+(c) You may not resell, sublicense, rent, lease, or lend the Software.
+
+(d) You may not reverse engineer, reverse compile, disassemble, or
+otherwise attempt to discover the source code of the Software (except
+to the extent that this restriction is expressly prohibited by law) or
+create derivative works based on the Software.
+
+(e) Unless stated otherwise in the Documentation, You shall not
+display, modify, reproduce, or distribute any of the Stock Files
+included with the Software. In the event that the Documentation allows
+You to display the Stock Files, You shall not distribute the Stock
+Files on a stand-alone basis, i.e., in circumstances in which the
+Stock Files constitute the primary value of the product being
+distributed. You should review the &quot;Readme&quot; files associated with the
+Stock Files that You use to ascertain what rights You have with
+respect to such materials. Stock Files may not be used in the
+production of libelous, defamatory, fraudulent, infringing, lewd,
+obscene, or pornographic material or in any otherwise illegal manner.
+You may not register or claim any rights in the Stock Files or
+derivative works thereof.
+
+(f) You agree that You shall only use the Software in a manner that
+complies with all applicable laws in the jurisdiction in which You use
+the Software, including, but not limited to, applicable restrictions
+concerning copyright and other intellectual property rights.
+
+
+4. INTELLECTUAL PROPERTY RIGHTS.
+
+The Software and all rights, without limitation including title and
+intellectual property rights therein, are owned by Nokia and/or its
+licensors and affiliates and are protected by international treaty
+provisions and all other applicable national laws of the country in
+which it is being used. The structure, organization, and code of the
+Software are the valuable trade secrets and confidential information
+of Nokia and/or its licensors and affiliates. You must not copy the
+Software, except as set forth in clause 3 (Limitations On End-User
+Rights). Any copies which You are permitted to make pursuant to this
+Agreement must contain the same copyright and other proprietary
+notices that appear on the Software.
+
+
+5. MULTIPLE ENVIRONMENT SOFTWARE / MULTIPLE LANGUAGE SOFTWARE /
+DUAL MEDIA SOFTWARE / MULTIPLE COPIES / UPDATES.
+
+If the Software supports multiple platforms or languages, if You
+receive the Software on multiple media, or if You otherwise receive
+multiple copies of the Software, the number of computers on which all
+versions of the Software are installed shall be one computer. You may
+not rent, lease, sublicense, lend, or transfer versions or copies of
+the Software You do not use. If the Software is an Update to a
+previous version of the Software, You must possess valid end-user
+rights to such a previous version in order to use the Update, and You
+may use the previous version for ninety (90) days after You receive
+the Update in order to assist You in the transition to the Update.
+After such time You no longer have a right to use the previous
+version, except for the sole purpose of enabling You to install the
+Update.
+
+
+6. COMMENCEMENT AND TERMINATION.
+
+This Agreement is effective from the first date You install the
+Software. You may terminate this Agreement at any time by permanently
+deleting, destroying, and returning, at Your own cost, the Software,
+all backup copies, and all related materials provided by Nokia. Your
+end-user rights automatically and immediately terminate without notice
+from Nokia if You fail to comply with any provision of this Agreement.
+In such an event, You must immediately delete, destroy, or return at
+Your own cost, the Software, all backup copies, and all related
+material to Nokia.
+
+
+7. YOU ACKNOWLEDGE THAT THE SOFTWARE IS PROVIDED &quot;AS IS&quot; WITHOUT
+WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, AND TO THE MAXIMUM EXTENT
+PERMITTED BY APPLICABLE LAW NEITHER NOKIA, ITS LICENSORS OR
+AFFILIATES, NOR THE COPYRIGHT HOLDERS MAKE ANY REPRESENTATIONS OR
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR
+THAT THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY PATENTS,
+COPYRIGHTS, TRADEMARKS, OR OTHER RIGHTS. THERE IS NO WARRANTY BY NOKIA
+OR BY ANY OTHER PARTY THAT THE FUNCTIONS CONTAINED IN THE SOFTWARE
+WILL MEET YOUR REQUIREMENTS OR THAT THE OPERATION OF THE SOFTWARE WILL
+BE UNINTERRUPTED OR ERROR-FREE. YOU ASSUME ALL RESPONSIBILITY AND RISK
+FOR THE SELECTION OF THE SOFTWARE TO ACHIEVE YOUR INTENDED RESULTS AND
+FOR THE INSTALLATION, USE, AND RESULTS OBTAINED FROM IT.
+
+
+8. NO OTHER OBLIGATIONS.
+
+This Agreement creates no obligations on the part of Nokia other than
+as specifically set forth herein.
+
+
+9. LIMITATION OF LIABILITY.
+
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
+NOKIA, ITS EMPLOYEES OR LICENSORS OR AFFILIATES BE LIABLE FOR ANY LOST
+PROFITS, REVENUE, SALES, DATA, OR COSTS OF PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES, PROPERTY DAMAGE, PERSONAL INJURY, INTERRUPTION OF
+BUSINESS, LOSS OF BUSINESS INFORMATION, OR FOR ANY SPECIAL, DIRECT,
+INDIRECT, INCIDENTAL, ECONOMIC, COVER, PUNITIVE, SPECIAL, OR
+CONSEQUENTIAL DAMAGES, HOWEVER CAUSED AND WHETHER ARISING UNDER
+CONTRACT, TORT, NEGLIGENCE, OR OTHER THEORY OF LIABILITY ARISING OUT
+OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF NOKIA OR ITS
+LICENSORS OR AFFILIATES ARE ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES. BECAUSE SOME COUNTRIES/STATES/JURISDICTIONS DO NOT ALLOW THE
+EXCLUSION OF LIABILITY, BUT MAY ALLOW LIABILITY TO BE LIMITED, IN SUCH
+CASES, NOKIA, ITS EMPLOYEES OR LICENSORS OR AFFILIATES&apos; LIABILITY
+SHALL BE LIMITED TO U.S. $50.
+
+Nothing contained in this Agreement shall prejudice the statutory
+rights of any party dealing as a consumer.
+
+Nothing contained in this Agreement limits Nokia&apos;s liability to You in
+the event of death or personal injury resulting from Nokia&apos;s
+negligence. Nokia is acting on behalf of its employees and licensors
+or affiliates for the purpose of disclaiming, excluding, and/or
+restricting obligations, warranties, and liability as provided in this
+clause 9, but in no other respects and for no other purpose.
+
+
+10. TECHNICAL SUPPORT.
+
+Nokia has no obligation to furnish You with technical support unless
+separately agreed in writing between You and Nokia.
+
+
+
+11. EXPORT CONTROL.
+
+The Software, including technical data, includes cryptographic
+software subject to export controls under the U.S. Export
+Administration Regulations (&quot;EAR&quot;) and may be subject to import or
+export controls in other countries. The EAR prohibits the use of the
+Software and technical data by a Government End User, as defined
+hereafter, without a license from the U.S. government. A Government
+End User is defined in Part 772 of the EAR as &quot;any foreign central,
+regional, or local government department, agency, or other entity
+performing governmental functions; including governmental research
+institutions, governmental corporations, or their separate business
+units (as defined in part 772 of the EAR) which are engaged in the
+manufacture or distribution of items or services controlled on the
+Wassenaar Munitions List, and international governmental
+organizations. This term does not include: utilities
+(telecommunications companies and Internet service providers; banks
+and financial institutions; transportation; broadcast or
+entertainment; educational organizations; civil health and medical
+organizations; retail or wholesale firms; and manufacturing or
+industrial entities not engaged in the manufacture or distribution of
+items or services controlled on the Wassenaar Munitions List.)&quot; You
+agree to strictly comply with all applicable import and export
+regulations and acknowledge that You have the responsibility to obtain
+licenses to export, re-export, transfer, or import the Software. You
+further represent that You are not a Government End User as defined
+above, and You will not transfer the Software to any Government End
+User without a license.
+
+
+12. NOTICES.
+
+All notices and return of the Software and Documentation should be
+delivered to:
+
+NOKIA CORPORATION
+P.O. Box 100
+FIN-00045 NOKIA GROUP
+FINLAND
+
+
+13. APPLICABLE LAW AND GENERAL PROVISIONS.
+
+This Agreement is governed by the laws of Finland. All disputes
+arising from or relating to this Agreement shall be settled by a
+single arbitrator appointed by the Central Chamber of Commerce of
+Finland. The arbitration procedure shall take place in Helsinki,
+Finland in the English language. If any part of this Agreement is
+found void and unenforceable, it will not affect the validity of the
+balance of the Agreement, which shall remain valid and enforceable
+according to its terms. This Agreement may only be modified in writing
+signed by an authorized officer of Nokia.
+
+This is the entire agreement between Nokia and You relating to the
+Software, and it supersedes any prior representations, discussions,
+undertakings, end-user agreements, communications, or advertising
+relating to the Software.
+
+PLEASE SUBMIT ANY ACCOMPANYING REGISTRATION FORMS TO RECEIVE
+REGISTRATION BENEFITS WHERE APPLICABLE.
+
+
+14. COPYRIGHT NOTICES
+
+This product includes certain open source or other software 
+originating from third parties that may be subject to the GNU 
+General Public License (GPL) and different and/oradditional 
+copyright licenses, disclaimers and notices. The exact terms 
+of GPL and some other licenses, disclaimers and notices are 
+reproduced in the materials provided with this product and are 
+also available at http://tools.ext.nokia.com/oss/ .  Please refer 
+to the exact terms of the GPL regarding your rights under said 
+license. You may obtain a complete corresponding machine-readable 
+copy of the source code of such software under GPL and some other 
+open source licenses allowing source code distribution at  
+http://tools.ext.nokia.com/oss/ .  Alternatively, Nokia offers 
+to provide such source code to you on CD-ROM for a charge covering 
+the cost of performing such distribution, such as the cost of media, 
+shipping and handling, upon written request to Nokia at 701 Brazos St., 
+Suite 1000, Austin, TX 78701. This offer is valid for a period of 
+three (3) years from the date of the distribution of this product by Nokia.
+   </license>
+
+   <url>
+      <update label="Carbide.c++ Update Site" url="http://tools.ext.nokia.com/updates/carbide203"/>
+      <discovery label="Carbide.c++ Update Site" url="http://tools.ext.nokia.com/updates/carbide203"/>
+   </url>
+
+   <requires>
+      <import plugin="org.eclipse.ui"/>
+      <import plugin="org.eclipse.core.resources"/>
+      <import plugin="org.eclipse.core.runtime"/>
+      <import plugin="org.eclipse.ui.ide"/>
+      <import plugin="org.eclipse.swt"/>
+   </requires>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.address"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.button"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.call"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.core"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.function"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.instr"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.memory"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.power"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.priority"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.priority2"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.ui"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.util"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.wizards"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="com.nokia.carbide.cpp.pi.doc.user"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/license.txt	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,293 @@
+                      COPYRIGHT LICENSE
+
+      NOKIA CORPORATION END-USER SOFTWARE AGREEMENT FOR
+      CARBIDE.C++ AND ASSOCIATED ON-DEVICE APPLICATIONS
+
+This Software Agreement ("Agreement") is between You (either an
+individual or an entity), the End User, and Nokia Corporation
+("Nokia"). The Agreement authorizes You to use the Software specified
+in Clause 1 below, which may be stored on a CD-ROM, sent to You by
+electronic mail, or downloaded from Nokia's Web pages or Servers or
+from other sources under the terms and conditions set forth below.
+This is an agreement on end-user rights and not an agreement for sale.
+Nokia continues to own the copy of the Software and the physical media
+contained in the sales package and any other copy that You are
+authorized to make pursuant to this Agreement.
+
+Read this Agreement carefully before installing, downloading, or using
+the Software. By clicking on the "I Accept" button while installing,
+downloading, and/or using the Software, You agree to the terms and
+conditions of this Agreement. If You do not agree to all of the terms
+and conditions of this Agreement, promptly click the "Decline" or
+"I Do Not Accept" button, cancel the installation or downloading, or
+destroy or return the Software and accompanying documentation to
+Nokia. YOU AGREE THAT YOUR USE OF THE SOFTWARE ACKNOWLEDGES THAT YOU
+HAVE READ THIS AGREEMENT, UNDERSTAND IT, AND AGREE TO BE BOUND BY ITS
+TERMS AND CONDITIONS.
+
+
+1. SOFTWARE.
+
+As used in this Agreement, the term "Software" means, collectively:
+(i) the software product identified above (ii) all the contents of the
+disk(s), CD-ROM(s), electronic mail and its file attachments, or other
+media with which this Agreement is provided, including the object code
+form of the software delivered via a CD-ROM, electronic mail, or Web
+page (iii) digital images, stock photographs, clip art, or other
+artistic works ("Stock Files") (iv) related explanatory written
+materials and any other possible documentation related thereto
+("Documentation"); (v) fonts, and (vi) upgrades, modified versions,
+updates, additions, and copies of the Software (collectively
+"Updates"), if any, licensed to You by Nokia under this Agreement.
+
+
+2. END USER RIGHTS AND USE.
+
+Nokia grants to You non-exclusive, non-transferable end-user rights to
+install the Software on the local hard disk(s) or other permanent
+storage media of one computer and use the Software on a single
+computer or terminal at a time.
+
+You acknowledge that the use of the Software may require licenses to
+third party patents and that Nokia does not grant any licenses to such
+third party patents under this Agreement to You.  Also, any and
+all standards related licenses with respect to Essential Patents (as
+defined below) are specifically excluded from the scope of this
+Agreement, and those licenses need to be acquired separately from
+Nokia or the respective right holders, as the case may be. "Essential
+Patent" means any patent claiming a feature necessarily and
+unavoidably required for compliance with industry standards (usually
+GSM, WCDMA or other similar mobile communications standard), to the
+limited extent only that infringement or use of such claims of a
+patent cannot be avoided in remaining compliant with industry standard
+either for technological reasons or for lack of commercially viable
+technical alternatives.
+
+No patent licenses to any patents of Nokia and/ or its Affiliates are
+granted under this Agreement.
+
+
+3. LIMITATIONS ON END USER RIGHTS.
+
+You may not copy, distribute, or make derivative works of the Software
+except as follows:
+
+(a) You may make one copy of the Software on magnetic media as an
+archival backup copy, provided Your archival backup copy is not
+installed or used on any computer. Any other copies You make of the
+Software are in violation of this Agreement.
+
+(b) You may not use, modify, translate, reproduce, or transfer the
+right to use the Software or copy the Software except as expressly
+provided in this Agreement.
+
+(c) You may not resell, sublicense, rent, lease, or lend the Software.
+
+(d) You may not reverse engineer, reverse compile, disassemble, or
+otherwise attempt to discover the source code of the Software (except
+to the extent that this restriction is expressly prohibited by law) or
+create derivative works based on the Software.
+
+(e) Unless stated otherwise in the Documentation, You shall not
+display, modify, reproduce, or distribute any of the Stock Files
+included with the Software. In the event that the Documentation allows
+You to display the Stock Files, You shall not distribute the Stock
+Files on a stand-alone basis, i.e., in circumstances in which the
+Stock Files constitute the primary value of the product being
+distributed. You should review the "Readme" files associated with the
+Stock Files that You use to ascertain what rights You have with
+respect to such materials. Stock Files may not be used in the
+production of libelous, defamatory, fraudulent, infringing, lewd,
+obscene, or pornographic material or in any otherwise illegal manner.
+You may not register or claim any rights in the Stock Files or
+derivative works thereof.
+
+(f) You agree that You shall only use the Software in a manner that
+complies with all applicable laws in the jurisdiction in which You use
+the Software, including, but not limited to, applicable restrictions
+concerning copyright and other intellectual property rights.
+
+
+4. INTELLECTUAL PROPERTY RIGHTS.
+
+The Software and all rights, without limitation including title and
+intellectual property rights therein, are owned by Nokia and/or its
+licensors and affiliates and are protected by international treaty
+provisions and all other applicable national laws of the country in
+which it is being used. The structure, organization, and code of the
+Software are the valuable trade secrets and confidential information
+of Nokia and/or its licensors and affiliates. You must not copy the
+Software, except as set forth in clause 3 (Limitations On End-User
+Rights). Any copies which You are permitted to make pursuant to this
+Agreement must contain the same copyright and other proprietary
+notices that appear on the Software.
+
+
+5. MULTIPLE ENVIRONMENT SOFTWARE / MULTIPLE LANGUAGE SOFTWARE /
+DUAL MEDIA SOFTWARE / MULTIPLE COPIES / UPDATES.
+
+If the Software supports multiple platforms or languages, if You
+receive the Software on multiple media, or if You otherwise receive
+multiple copies of the Software, the number of computers on which all
+versions of the Software are installed shall be one computer. You may
+not rent, lease, sublicense, lend, or transfer versions or copies of
+the Software You do not use. If the Software is an Update to a
+previous version of the Software, You must possess valid end-user
+rights to such a previous version in order to use the Update, and You
+may use the previous version for ninety (90) days after You receive
+the Update in order to assist You in the transition to the Update.
+After such time You no longer have a right to use the previous
+version, except for the sole purpose of enabling You to install the
+Update.
+
+
+6. COMMENCEMENT AND TERMINATION.
+
+This Agreement is effective from the first date You install the
+Software. You may terminate this Agreement at any time by permanently
+deleting, destroying, and returning, at Your own cost, the Software,
+all backup copies, and all related materials provided by Nokia. Your
+end-user rights automatically and immediately terminate without notice
+from Nokia if You fail to comply with any provision of this Agreement.
+In such an event, You must immediately delete, destroy, or return at
+Your own cost, the Software, all backup copies, and all related
+material to Nokia.
+
+
+7. YOU ACKNOWLEDGE THAT THE SOFTWARE IS PROVIDED "AS IS" WITHOUT
+WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, AND TO THE MAXIMUM EXTENT
+PERMITTED BY APPLICABLE LAW NEITHER NOKIA, ITS LICENSORS OR
+AFFILIATES, NOR THE COPYRIGHT HOLDERS MAKE ANY REPRESENTATIONS OR
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR
+THAT THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY PATENTS,
+COPYRIGHTS, TRADEMARKS, OR OTHER RIGHTS. THERE IS NO WARRANTY BY NOKIA
+OR BY ANY OTHER PARTY THAT THE FUNCTIONS CONTAINED IN THE SOFTWARE
+WILL MEET YOUR REQUIREMENTS OR THAT THE OPERATION OF THE SOFTWARE WILL
+BE UNINTERRUPTED OR ERROR-FREE. YOU ASSUME ALL RESPONSIBILITY AND RISK
+FOR THE SELECTION OF THE SOFTWARE TO ACHIEVE YOUR INTENDED RESULTS AND
+FOR THE INSTALLATION, USE, AND RESULTS OBTAINED FROM IT.
+
+
+8. NO OTHER OBLIGATIONS.
+
+This Agreement creates no obligations on the part of Nokia other than
+as specifically set forth herein.
+
+
+9. LIMITATION OF LIABILITY.
+
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
+NOKIA, ITS EMPLOYEES OR LICENSORS OR AFFILIATES BE LIABLE FOR ANY LOST
+PROFITS, REVENUE, SALES, DATA, OR COSTS OF PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES, PROPERTY DAMAGE, PERSONAL INJURY, INTERRUPTION OF
+BUSINESS, LOSS OF BUSINESS INFORMATION, OR FOR ANY SPECIAL, DIRECT,
+INDIRECT, INCIDENTAL, ECONOMIC, COVER, PUNITIVE, SPECIAL, OR
+CONSEQUENTIAL DAMAGES, HOWEVER CAUSED AND WHETHER ARISING UNDER
+CONTRACT, TORT, NEGLIGENCE, OR OTHER THEORY OF LIABILITY ARISING OUT
+OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF NOKIA OR ITS
+LICENSORS OR AFFILIATES ARE ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES. BECAUSE SOME COUNTRIES/STATES/JURISDICTIONS DO NOT ALLOW THE
+EXCLUSION OF LIABILITY, BUT MAY ALLOW LIABILITY TO BE LIMITED, IN SUCH
+CASES, NOKIA, ITS EMPLOYEES OR LICENSORS OR AFFILIATES' LIABILITY
+SHALL BE LIMITED TO U.S. $50.
+
+Nothing contained in this Agreement shall prejudice the statutory
+rights of any party dealing as a consumer.
+
+Nothing contained in this Agreement limits Nokia's liability to You in
+the event of death or personal injury resulting from Nokia's
+negligence. Nokia is acting on behalf of its employees and licensors
+or affiliates for the purpose of disclaiming, excluding, and/or
+restricting obligations, warranties, and liability as provided in this
+clause 9, but in no other respects and for no other purpose.
+
+
+10. TECHNICAL SUPPORT.
+
+Nokia has no obligation to furnish You with technical support unless
+separately agreed in writing between You and Nokia.
+
+
+
+11. EXPORT CONTROL.
+
+The Software, including technical data, includes cryptographic
+software subject to export controls under the U.S. Export
+Administration Regulations ("EAR") and may be subject to import or
+export controls in other countries. The EAR prohibits the use of the
+Software and technical data by a Government End User, as defined
+hereafter, without a license from the U.S. government. A Government
+End User is defined in Part 772 of the EAR as "any foreign central,
+regional, or local government department, agency, or other entity
+performing governmental functions; including governmental research
+institutions, governmental corporations, or their separate business
+units (as defined in part 772 of the EAR) which are engaged in the
+manufacture or distribution of items or services controlled on the
+Wassenaar Munitions List, and international governmental
+organizations. This term does not include: utilities
+(telecommunications companies and Internet service providers; banks
+and financial institutions; transportation; broadcast or
+entertainment; educational organizations; civil health and medical
+organizations; retail or wholesale firms; and manufacturing or
+industrial entities not engaged in the manufacture or distribution of
+items or services controlled on the Wassenaar Munitions List.)" You
+agree to strictly comply with all applicable import and export
+regulations and acknowledge that You have the responsibility to obtain
+licenses to export, re-export, transfer, or import the Software. You
+further represent that You are not a Government End User as defined
+above, and You will not transfer the Software to any Government End
+User without a license.
+
+
+12. NOTICES.
+
+All notices and return of the Software and Documentation should be
+delivered to:
+
+NOKIA CORPORATION
+P.O. Box 100
+FIN-00045 NOKIA GROUP
+FINLAND
+
+
+13. APPLICABLE LAW AND GENERAL PROVISIONS.
+
+This Agreement is governed by the laws of Finland. All disputes
+arising from or relating to this Agreement shall be settled by a
+single arbitrator appointed by the Central Chamber of Commerce of
+Finland. The arbitration procedure shall take place in Helsinki,
+Finland in the English language. If any part of this Agreement is
+found void and unenforceable, it will not affect the validity of the
+balance of the Agreement, which shall remain valid and enforceable
+according to its terms. This Agreement may only be modified in writing
+signed by an authorized officer of Nokia.
+
+This is the entire agreement between Nokia and You relating to the
+Software, and it supersedes any prior representations, discussions,
+undertakings, end-user agreements, communications, or advertising
+relating to the Software.
+
+PLEASE SUBMIT ANY ACCOMPANYING REGISTRATION FORMS TO RECEIVE
+REGISTRATION BENEFITS WHERE APPLICABLE.
+
+
+14. COPYRIGHT NOTICES
+
+This product includes certain open source or other software 
+originating from third parties that may be subject to the GNU 
+General Public License (GPL) and different and/oradditional 
+copyright licenses, disclaimers and notices. The exact terms 
+of GPL and some other licenses, disclaimers and notices are 
+reproduced in the materials provided with this product and are 
+also available at http://tools.ext.nokia.com/oss/ .  Please refer 
+to the exact terms of the GPL regarding your rights under said 
+license. You may obtain a complete corresponding machine-readable 
+copy of the source code of such software under GPL and some other 
+open source licenses allowing source code distribution at  
+http://tools.ext.nokia.com/oss/ .  Alternatively, Nokia offers 
+to provide such source code to you on CD-ROM for a charge covering 
+the cost of performing such distribution, such as the cost of media, 
+shipping and handling, upon written request to Nokia at 701 Brazos St., 
+Suite 1000, Austin, TX 78701. This offer is valid for a period of 
+three (3) years from the date of the distribution of this product by Nokia.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/profilerbuild.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="build" default="feature_export">
+	<target name="feature_export">
+		<pde.exportFeatures features="com.nokia.carbide.cpp.profiler" destination="C:\rudy-build" filename="rudy.zip" exportType="zip" exportSource="false"/>
+	</target>
+</project>
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/sourceTemplateFeature/Carbide_Image.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/sourceTemplateFeature/feature.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2 @@
+# "featureName" property - name of the feature
+featureName=Carbide.c++ Performance Investigator Source
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi-feature/sourceTemplateFeature/license.txt	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,293 @@
+                      COPYRIGHT LICENSE
+
+      NOKIA CORPORATION END-USER SOFTWARE AGREEMENT FOR
+      CARBIDE.C++ AND ASSOCIATED ON-DEVICE APPLICATIONS
+
+This Software Agreement ("Agreement") is between You (either an
+individual or an entity), the End User, and Nokia Corporation
+("Nokia"). The Agreement authorizes You to use the Software specified
+in Clause 1 below, which may be stored on a CD-ROM, sent to You by
+electronic mail, or downloaded from Nokia's Web pages or Servers or
+from other sources under the terms and conditions set forth below.
+This is an agreement on end-user rights and not an agreement for sale.
+Nokia continues to own the copy of the Software and the physical media
+contained in the sales package and any other copy that You are
+authorized to make pursuant to this Agreement.
+
+Read this Agreement carefully before installing, downloading, or using
+the Software. By clicking on the "I Accept" button while installing,
+downloading, and/or using the Software, You agree to the terms and
+conditions of this Agreement. If You do not agree to all of the terms
+and conditions of this Agreement, promptly click the "Decline" or
+"I Do Not Accept" button, cancel the installation or downloading, or
+destroy or return the Software and accompanying documentation to
+Nokia. YOU AGREE THAT YOUR USE OF THE SOFTWARE ACKNOWLEDGES THAT YOU
+HAVE READ THIS AGREEMENT, UNDERSTAND IT, AND AGREE TO BE BOUND BY ITS
+TERMS AND CONDITIONS.
+
+
+1. SOFTWARE.
+
+As used in this Agreement, the term "Software" means, collectively:
+(i) the software product identified above (ii) all the contents of the
+disk(s), CD-ROM(s), electronic mail and its file attachments, or other
+media with which this Agreement is provided, including the object code
+form of the software delivered via a CD-ROM, electronic mail, or Web
+page (iii) digital images, stock photographs, clip art, or other
+artistic works ("Stock Files") (iv) related explanatory written
+materials and any other possible documentation related thereto
+("Documentation"); (v) fonts, and (vi) upgrades, modified versions,
+updates, additions, and copies of the Software (collectively
+"Updates"), if any, licensed to You by Nokia under this Agreement.
+
+
+2. END USER RIGHTS AND USE.
+
+Nokia grants to You non-exclusive, non-transferable end-user rights to
+install the Software on the local hard disk(s) or other permanent
+storage media of one computer and use the Software on a single
+computer or terminal at a time.
+
+You acknowledge that the use of the Software may require licenses to
+third party patents and that Nokia does not grant any licenses to such
+third party patents under this Agreement to You.  Also, any and
+all standards related licenses with respect to Essential Patents (as
+defined below) are specifically excluded from the scope of this
+Agreement, and those licenses need to be acquired separately from
+Nokia or the respective right holders, as the case may be. "Essential
+Patent" means any patent claiming a feature necessarily and
+unavoidably required for compliance with industry standards (usually
+GSM, WCDMA or other similar mobile communications standard), to the
+limited extent only that infringement or use of such claims of a
+patent cannot be avoided in remaining compliant with industry standard
+either for technological reasons or for lack of commercially viable
+technical alternatives.
+
+No patent licenses to any patents of Nokia and/ or its Affiliates are
+granted under this Agreement.
+
+
+3. LIMITATIONS ON END USER RIGHTS.
+
+You may not copy, distribute, or make derivative works of the Software
+except as follows:
+
+(a) You may make one copy of the Software on magnetic media as an
+archival backup copy, provided Your archival backup copy is not
+installed or used on any computer. Any other copies You make of the
+Software are in violation of this Agreement.
+
+(b) You may not use, modify, translate, reproduce, or transfer the
+right to use the Software or copy the Software except as expressly
+provided in this Agreement.
+
+(c) You may not resell, sublicense, rent, lease, or lend the Software.
+
+(d) You may not reverse engineer, reverse compile, disassemble, or
+otherwise attempt to discover the source code of the Software (except
+to the extent that this restriction is expressly prohibited by law) or
+create derivative works based on the Software.
+
+(e) Unless stated otherwise in the Documentation, You shall not
+display, modify, reproduce, or distribute any of the Stock Files
+included with the Software. In the event that the Documentation allows
+You to display the Stock Files, You shall not distribute the Stock
+Files on a stand-alone basis, i.e., in circumstances in which the
+Stock Files constitute the primary value of the product being
+distributed. You should review the "Readme" files associated with the
+Stock Files that You use to ascertain what rights You have with
+respect to such materials. Stock Files may not be used in the
+production of libelous, defamatory, fraudulent, infringing, lewd,
+obscene, or pornographic material or in any otherwise illegal manner.
+You may not register or claim any rights in the Stock Files or
+derivative works thereof.
+
+(f) You agree that You shall only use the Software in a manner that
+complies with all applicable laws in the jurisdiction in which You use
+the Software, including, but not limited to, applicable restrictions
+concerning copyright and other intellectual property rights.
+
+
+4. INTELLECTUAL PROPERTY RIGHTS.
+
+The Software and all rights, without limitation including title and
+intellectual property rights therein, are owned by Nokia and/or its
+licensors and affiliates and are protected by international treaty
+provisions and all other applicable national laws of the country in
+which it is being used. The structure, organization, and code of the
+Software are the valuable trade secrets and confidential information
+of Nokia and/or its licensors and affiliates. You must not copy the
+Software, except as set forth in clause 3 (Limitations On End-User
+Rights). Any copies which You are permitted to make pursuant to this
+Agreement must contain the same copyright and other proprietary
+notices that appear on the Software.
+
+
+5. MULTIPLE ENVIRONMENT SOFTWARE / MULTIPLE LANGUAGE SOFTWARE /
+DUAL MEDIA SOFTWARE / MULTIPLE COPIES / UPDATES.
+
+If the Software supports multiple platforms or languages, if You
+receive the Software on multiple media, or if You otherwise receive
+multiple copies of the Software, the number of computers on which all
+versions of the Software are installed shall be one computer. You may
+not rent, lease, sublicense, lend, or transfer versions or copies of
+the Software You do not use. If the Software is an Update to a
+previous version of the Software, You must possess valid end-user
+rights to such a previous version in order to use the Update, and You
+may use the previous version for ninety (90) days after You receive
+the Update in order to assist You in the transition to the Update.
+After such time You no longer have a right to use the previous
+version, except for the sole purpose of enabling You to install the
+Update.
+
+
+6. COMMENCEMENT AND TERMINATION.
+
+This Agreement is effective from the first date You install the
+Software. You may terminate this Agreement at any time by permanently
+deleting, destroying, and returning, at Your own cost, the Software,
+all backup copies, and all related materials provided by Nokia. Your
+end-user rights automatically and immediately terminate without notice
+from Nokia if You fail to comply with any provision of this Agreement.
+In such an event, You must immediately delete, destroy, or return at
+Your own cost, the Software, all backup copies, and all related
+material to Nokia.
+
+
+7. YOU ACKNOWLEDGE THAT THE SOFTWARE IS PROVIDED "AS IS" WITHOUT
+WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, AND TO THE MAXIMUM EXTENT
+PERMITTED BY APPLICABLE LAW NEITHER NOKIA, ITS LICENSORS OR
+AFFILIATES, NOR THE COPYRIGHT HOLDERS MAKE ANY REPRESENTATIONS OR
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR
+THAT THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY PATENTS,
+COPYRIGHTS, TRADEMARKS, OR OTHER RIGHTS. THERE IS NO WARRANTY BY NOKIA
+OR BY ANY OTHER PARTY THAT THE FUNCTIONS CONTAINED IN THE SOFTWARE
+WILL MEET YOUR REQUIREMENTS OR THAT THE OPERATION OF THE SOFTWARE WILL
+BE UNINTERRUPTED OR ERROR-FREE. YOU ASSUME ALL RESPONSIBILITY AND RISK
+FOR THE SELECTION OF THE SOFTWARE TO ACHIEVE YOUR INTENDED RESULTS AND
+FOR THE INSTALLATION, USE, AND RESULTS OBTAINED FROM IT.
+
+
+8. NO OTHER OBLIGATIONS.
+
+This Agreement creates no obligations on the part of Nokia other than
+as specifically set forth herein.
+
+
+9. LIMITATION OF LIABILITY.
+
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
+NOKIA, ITS EMPLOYEES OR LICENSORS OR AFFILIATES BE LIABLE FOR ANY LOST
+PROFITS, REVENUE, SALES, DATA, OR COSTS OF PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES, PROPERTY DAMAGE, PERSONAL INJURY, INTERRUPTION OF
+BUSINESS, LOSS OF BUSINESS INFORMATION, OR FOR ANY SPECIAL, DIRECT,
+INDIRECT, INCIDENTAL, ECONOMIC, COVER, PUNITIVE, SPECIAL, OR
+CONSEQUENTIAL DAMAGES, HOWEVER CAUSED AND WHETHER ARISING UNDER
+CONTRACT, TORT, NEGLIGENCE, OR OTHER THEORY OF LIABILITY ARISING OUT
+OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF NOKIA OR ITS
+LICENSORS OR AFFILIATES ARE ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES. BECAUSE SOME COUNTRIES/STATES/JURISDICTIONS DO NOT ALLOW THE
+EXCLUSION OF LIABILITY, BUT MAY ALLOW LIABILITY TO BE LIMITED, IN SUCH
+CASES, NOKIA, ITS EMPLOYEES OR LICENSORS OR AFFILIATES' LIABILITY
+SHALL BE LIMITED TO U.S. $50.
+
+Nothing contained in this Agreement shall prejudice the statutory
+rights of any party dealing as a consumer.
+
+Nothing contained in this Agreement limits Nokia's liability to You in
+the event of death or personal injury resulting from Nokia's
+negligence. Nokia is acting on behalf of its employees and licensors
+or affiliates for the purpose of disclaiming, excluding, and/or
+restricting obligations, warranties, and liability as provided in this
+clause 9, but in no other respects and for no other purpose.
+
+
+10. TECHNICAL SUPPORT.
+
+Nokia has no obligation to furnish You with technical support unless
+separately agreed in writing between You and Nokia.
+
+
+
+11. EXPORT CONTROL.
+
+The Software, including technical data, includes cryptographic
+software subject to export controls under the U.S. Export
+Administration Regulations ("EAR") and may be subject to import or
+export controls in other countries. The EAR prohibits the use of the
+Software and technical data by a Government End User, as defined
+hereafter, without a license from the U.S. government. A Government
+End User is defined in Part 772 of the EAR as "any foreign central,
+regional, or local government department, agency, or other entity
+performing governmental functions; including governmental research
+institutions, governmental corporations, or their separate business
+units (as defined in part 772 of the EAR) which are engaged in the
+manufacture or distribution of items or services controlled on the
+Wassenaar Munitions List, and international governmental
+organizations. This term does not include: utilities
+(telecommunications companies and Internet service providers; banks
+and financial institutions; transportation; broadcast or
+entertainment; educational organizations; civil health and medical
+organizations; retail or wholesale firms; and manufacturing or
+industrial entities not engaged in the manufacture or distribution of
+items or services controlled on the Wassenaar Munitions List.)" You
+agree to strictly comply with all applicable import and export
+regulations and acknowledge that You have the responsibility to obtain
+licenses to export, re-export, transfer, or import the Software. You
+further represent that You are not a Government End User as defined
+above, and You will not transfer the Software to any Government End
+User without a license.
+
+
+12. NOTICES.
+
+All notices and return of the Software and Documentation should be
+delivered to:
+
+NOKIA CORPORATION
+P.O. Box 100
+FIN-00045 NOKIA GROUP
+FINLAND
+
+
+13. APPLICABLE LAW AND GENERAL PROVISIONS.
+
+This Agreement is governed by the laws of Finland. All disputes
+arising from or relating to this Agreement shall be settled by a
+single arbitrator appointed by the Central Chamber of Commerce of
+Finland. The arbitration procedure shall take place in Helsinki,
+Finland in the English language. If any part of this Agreement is
+found void and unenforceable, it will not affect the validity of the
+balance of the Agreement, which shall remain valid and enforceable
+according to its terms. This Agreement may only be modified in writing
+signed by an authorized officer of Nokia.
+
+This is the entire agreement between Nokia and You relating to the
+Software, and it supersedes any prior representations, discussions,
+undertakings, end-user agreements, communications, or advertising
+relating to the Software.
+
+PLEASE SUBMIT ANY ACCOMPANYING REGISTRATION FORMS TO RECEIVE
+REGISTRATION BENEFITS WHERE APPLICABLE.
+
+
+14. COPYRIGHT NOTICES
+
+This product includes certain open source or other software 
+originating from third parties that may be subject to the GNU 
+General Public License (GPL) and different and/oradditional 
+copyright licenses, disclaimers and notices. The exact terms 
+of GPL and some other licenses, disclaimers and notices are 
+reproduced in the materials provided with this product and are 
+also available at http://tools.ext.nokia.com/oss/ .  Please refer 
+to the exact terms of the GPL regarding your rights under said 
+license. You may obtain a complete corresponding machine-readable 
+copy of the source code of such software under GPL and some other 
+open source licenses allowing source code distribution at  
+http://tools.ext.nokia.com/oss/ .  Alternatively, Nokia offers 
+to provide such source code to you on CD-ROM for a charge covering 
+the cost of performing such distribution, such as the cost of media, 
+shipping and handling, upon written request to Nokia at 701 Brazos St., 
+Suite 1000, Austin, TX 78701. This offer is valid for a period of 
+three (3) years from the date of the distribution of this product by Nokia.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/.settings/org.eclipse.core.resources.prefs	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,4 @@
+#Mon Feb 09 13:30:33 CST 2009
+eclipse.preferences.version=1
+encoding//src/com/nokia/carbide/cpp/internal/pi/address/actions/messages.properties=8859_1
+encoding//src/com/nokia/carbide/cpp/pi/address/messages.properties=8859_1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,17 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Threads and Addresses
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.address;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.address.AddressPlugin
+Bundle-Vendor: Nokia
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.draw2d,
+ com.nokia.carbide.cpp.pi,
+ com.nokia.carbide.cpp.pi.core,
+ com.nokia.carbide.cpp.pi.util
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.pi.address;x-friends:="com.nokia.carbide.cpp.pi.tests"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,6 @@
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .
+jars.compile.order = .
+source.. = src/
+output.. = bin/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+   <extension
+         point="com.nokia.carbide.cpp.pi.piPluginData">
+      <plugin
+            pluginClass="com.nokia.carbide.cpp.pi.address.AddressReturnPlugin"
+            pluginId="com.nokia.carbide.cpp.pi.address"
+            pluginName="Address Plug-in"
+            pluginProvider="Nokia"
+            pluginVersion="1.0.0"/>
+   </extension>
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/BarGraphDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.address.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.address.AddressPlugin;
+
+public class BarGraphDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+
+		if (action.isChecked()) {
+			AddressPlugin.getDefault().receiveSelectionEvent("setBarOn"); //$NON-NLS-1$
+		}
+		else {
+			AddressPlugin.getDefault().receiveSelectionEvent("setBarOff"); //$NON-NLS-1$
+		}
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/DrawBinariesDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.address.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.address.AddressPlugin;
+
+public class DrawBinariesDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+
+		AddressPlugin.getDefault().receiveSelectionEvent("drawBinaries"); //$NON-NLS-1$
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/DrawThreadsDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.address.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.address.AddressPlugin;
+
+public class DrawThreadsDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+
+		AddressPlugin.getDefault().receiveSelectionEvent("drawThreads"); //$NON-NLS-1$
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/ExportDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.address.actions;
+
+import java.io.File;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
+import com.nokia.carbide.cpp.internal.pi.utils.PIUtilities;
+import com.nokia.carbide.cpp.pi.address.AddressPlugin;
+import com.nokia.carbide.cpp.pi.address.GppTrace;
+import com.nokia.carbide.cpp.pi.address.GppTraceCsvPrinter;
+
+
+public class ExportDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+		
+		ParsedTraceData ptd = TraceDataRepository.getInstance().getTrace(NpiInstanceRepository.getInstance().activeUid(),
+								AddressPlugin.getDefault().getTraceClass());
+		if (ptd != null)
+		{
+			final GppTrace gppTraceTmp = (GppTrace)ptd.traceData;
+							
+			new Thread()
+			{
+				public void run()
+				{   
+				    try 
+					{
+						File report = PIUtilities.getAFile(true,"csv"); //$NON-NLS-1$
+						if (report != null)
+						{
+						    GppTraceCsvPrinter csvPrinter = new GppTraceCsvPrinter(gppTraceTmp);
+						    String csvPrint = csvPrinter.getCsvPrint();
+						    if (csvPrint != null)
+						    {
+						        PIUtilities.saveCsvPrint(report, csvPrint);
+						    }
+						}
+					} 
+					catch (Exception e) 
+					{
+					    e.printStackTrace();
+					}
+				}
+			}.start();
+		}
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/FillAllDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.address.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.address.AddressPlugin;
+import com.nokia.carbide.cpp.pi.core.SessionPreferences;
+
+public class FillAllDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+
+		AddressPlugin.getDefault().receiveSelectionEvent("fillAll"); //$NON-NLS-1$
+		SessionPreferences.getInstance().setFillAllEnabled(true);
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/FillNoneDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.address.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.address.AddressPlugin;
+import com.nokia.carbide.cpp.pi.core.SessionPreferences;
+
+public class FillNoneDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+
+		AddressPlugin.getDefault().receiveSelectionEvent("noFill"); //$NON-NLS-1$
+		SessionPreferences.getInstance().setFillAllEnabled(false);
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/FillSelectedDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.address.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.address.AddressPlugin;
+import com.nokia.carbide.cpp.pi.core.SessionPreferences;
+
+public class FillSelectedDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+		
+		AddressPlugin.getDefault().receiveSelectionEvent("fillSelected"); //$NON-NLS-1$
+		SessionPreferences.getInstance().setFillAllEnabled(false);
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.address.actions;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.address.actions.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/internal/pi/address/actions/VisualFunctionsDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.address.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.address.AddressPlugin;
+
+public class VisualFunctionsDelegate implements
+		IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+
+		if (action.isChecked()) {
+			AddressPlugin.getDefault().receiveSelectionEvent("functionsVisualised"); //$NON-NLS-1$
+		}
+		else {
+			AddressPlugin.getDefault().receiveSelectionEvent("resetToCurrentMode"); //$NON-NLS-1$
+		}
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddrBinaryTable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2319 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.FocusEvent;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Sash;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledBinary;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledFunction;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThreshold;
+import com.nokia.carbide.cpp.internal.pi.visual.Defines;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.internal.pi.visual.PIVisualSharedData;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.TableColorPalette;
+
+
+public class AddrBinaryTable extends GenericAddrTable
+{
+	// local copy of profiled binaries, which we can sort
+	// without affecting the original
+	Vector<ProfiledGeneric> profiledBinaries = new Vector<ProfiledGeneric>();
+
+	public AddrBinaryTable(GppTraceGraph myGraph, Composite parent)
+	{
+		this.myGraph = myGraph;
+		this.parent  = parent;
+	}
+
+	public void createTableViewer(int drawMode)
+	{
+		if (this.parent == null)
+			return;
+
+		// Binary table:
+		//		checkbox + colored or white background
+		//  	percent load
+		//  	binary name
+		//		binary path
+		//		sample count
+
+		// Check the drawMode
+		switch (drawMode)
+		{
+			case Defines.BINARIES:
+			case Defines.THREADS_FUNCTIONS_BINARIES:
+			case Defines.THREADS_BINARIES:
+			case Defines.FUNCTIONS_THREADS_BINARIES:
+			case Defines.FUNCTIONS_BINARIES:
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			case Defines.BINARIES_THREADS:
+			case Defines.BINARIES_THREADS_FUNCTIONS:
+			case Defines.BINARIES_FUNCTIONS:
+			case Defines.BINARIES_FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_BINARIES_THREADS:
+			{
+				break;
+			}
+			default:
+				// no binary table in this draw mode
+				return;
+		}
+
+		// create the table viewer
+		this.tableViewer = CheckboxTableViewer.newCheckList(this.parent,
+  				SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
+
+		// add the check state handler, label provider and content provider
+		tableViewer.addCheckStateListener(new SharedCheckHandler());
+		tableViewer.setLabelProvider(new shownBinariesLabelProvider());
+		tableViewer.setContentProvider(new shownBinariesContentProvider());
+		tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent arg0) {
+				if (copyAction == null)
+					return;
+
+				// when selection changes, the ability to copy may change
+				copyAction.setEnabled(table.getSelectionCount() > 0);
+				PIPageEditor.getActionBars().updateActionBars();
+			}
+		});
+
+		createDefaultActions();
+
+		// make sure the table viewer has a sorter
+		if (this.sorter == null)
+			this.sorter = new GppTableSorter();
+
+		this.table = tableViewer.getTable();
+		this.table.setRedraw(false);
+
+		// give the table a heading for use in copying and exported
+		this.table.setData(Messages.getString("AddrBinaryTable.binaries")); //$NON-NLS-1$
+		
+		// create the columns
+		TableColumn column;
+
+		// data associated with the TableViewer will note which columns contain hex values
+		// Keep this in the order in which columns have been created
+		boolean[] isHex = {false, false, false, false, false};
+		this.table.setData("isHex", isHex); //$NON-NLS-1$
+
+		// select/deselect column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_SHOW);
+		column.setWidth(COLUMN_WIDTH_SHOW);
+		column.setData(new Integer(COLUMN_ID_SHOW));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// percent load column
+		column = new TableColumn(table, SWT.RIGHT);
+		column.setText(COLUMN_HEAD_PERCENT_LOAD);
+		column.setWidth(COLUMN_WIDTH_PERCENT_LOAD);
+		column.setData(new Integer(COLUMN_ID_PERCENT_LOAD));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// binary name column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_BINARY);
+		column.setWidth(COLUMN_WIDTH_BINARY_NAME);
+		column.setData(new Integer(COLUMN_ID_BINARY));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// path column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_PATH);
+		column.setWidth(COLUMN_WIDTH_PATH);
+		column.setData(new Integer(COLUMN_ID_PATH));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// sample count column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_SAMPLE_COUNT);
+		column.setWidth(COLUMN_WIDTH_SAMPLE_COUNT);
+		column.setData(new Integer(COLUMN_ID_SAMPLE_COUNT));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// listen for mouse clicks: to select a row, pop up a menu, etc.
+		table.addMouseListener(new TableMouseListener());
+
+		// listen for key sequences such as Ctrl-A and Ctrl-C
+		table.addKeyListener(new TableKeyListener());		
+		
+		table.addFocusListener(new AddrTableFocusListener());
+
+		// add form data in case later we add a sash to the right
+		FormData viewerData = new FormData();
+		viewerData.top    = new FormAttachment(0);
+		viewerData.bottom = new FormAttachment(100);
+		viewerData.left   = new FormAttachment(0);
+		viewerData.right  = new FormAttachment(100);
+		table.setLayoutData(viewerData);
+		table.setLayout(new FormLayout());
+
+		// make sure the table viewer has a sorter
+		if (this.sorter == null)
+			this.sorter = new GppTableSorter();
+
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+		table.setRedraw(true);
+	}
+
+	public void setTableViewer(CheckboxTableViewer tableViewer)
+	{
+		this.tableViewer = tableViewer;
+
+		if (tableViewer == null)
+			this.table = null;
+	}
+
+	public void setTableViewer(int drawMode)
+	{
+		if (this.parent == null)
+			return;
+
+		createTableViewer(drawMode);
+
+		// sort by sample count
+		this.sortColumn = COLUMN_ID_SAMPLE_COUNT;
+		this.sortAscending = false;
+
+		// profiledBinaries and tableItemData contain one entry per table row
+		updateProfiledAndItemData(false);
+		quickSort(sortColumn, profiledBinaries);
+
+		// initially, all rows are selected
+		this.tableViewer.setAllChecked(true);
+	}
+
+	public void refreshTableViewer()
+	{
+		if (this.tableViewer == null)
+			return;
+
+		this.tableViewer.setInput(tableItemData);
+		
+		addColor(this.myGraph.getDrawMode());
+	}
+	
+	public void addColor(int drawMode)
+	{
+		if (this.tableViewer == null)
+			return;
+
+		// make sure that this table's colors are being shown
+		if (   (drawMode != Defines.BINARIES)
+			&& (drawMode != Defines.THREADS_BINARIES)
+			&& (drawMode != Defines.THREADS_FUNCTIONS_BINARIES)
+			&& (drawMode != Defines.FUNCTIONS_BINARIES)
+			&& (drawMode != Defines.FUNCTIONS_THREADS_BINARIES))
+			return;
+
+		ProfiledGeneric pGeneric;
+
+		TableItem[] items = this.table.getItems();
+
+		for (int i = 0; i < items.length; i++) {
+			pGeneric = (ProfiledGeneric) items[i].getData();
+//			Color color = ((GppTrace)this.myGraph.getTrace()).getBinaryColorPalette().getColor(pGeneric.getNameString());
+			items[i].setBackground(COLOR_COLUMN_INDEX, pGeneric.getColor()); // checkbox and color are always in the first column
+		}
+
+		table.redraw();
+	}
+	
+	public void removeColor(int drawMode)
+	{
+		if (this.tableViewer == null)
+			return;
+
+		// make sure that this table's colors should not be shown
+		if (   (drawMode == Defines.BINARIES)
+			|| (drawMode == Defines.THREADS_BINARIES)
+			|| (drawMode == Defines.THREADS_FUNCTIONS_BINARIES)
+			|| (drawMode == Defines.FUNCTIONS_BINARIES)
+			|| (drawMode == Defines.FUNCTIONS_THREADS_BINARIES))
+			return;
+
+		TableItem[] items = this.table.getItems();
+
+		for (int i = 0; i < items.length; i++) {
+			// checkbox and color are always in the first column
+			items[i].setBackground(COLOR_COLUMN_INDEX, this.parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
+		}
+
+		table.redraw();
+	}
+
+	private static class shownBinariesContentProvider implements IStructuredContentProvider {
+
+		public shownBinariesContentProvider() {
+			super();
+		}
+
+		public Object[] getElements(Object inputElement) {
+			return ((Vector) inputElement).toArray();
+		}
+
+		public void dispose() {
+		}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		}
+	}
+
+	private class shownBinariesLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+		public shownBinariesLabelProvider() {
+			super();
+		}
+
+		public String getColumnText(Object element, int columnIndex) {
+
+			int columnId = ((Integer) table.getColumn(columnIndex).getData()).intValue();
+
+			if (element instanceof ProfiledThreshold) {
+				ProfiledThreshold pThreshold = (ProfiledThreshold) element;
+				switch (columnId)
+				{
+					case COLUMN_ID_SHOW:
+					{
+						return SHOW_ITEM_VALUE;
+					}
+					case COLUMN_ID_PERCENT_LOAD:
+					{
+						// Percent load string
+						double startTime = PIPageEditor.currentPageEditor().getStartTime();
+						double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+						if (   (startTime == -1)
+							|| (endTime   == -1)
+							|| (startTime == endTime)) {
+							pThreshold.setAverageLoadValueString(myGraph.getGraphIndex(), ""); //$NON-NLS-1$
+						} else {
+							float load = (float) (pThreshold.getSampleCount(myGraph.getGraphIndex())/(endTime - startTime)/10.0);
+							
+							if (load < 0.005)
+								pThreshold.setAverageLoadValueString(myGraph.getGraphIndex(), Messages.getString("AddrBinaryTable.zeroFormat")); //$NON-NLS-1$
+							else
+								pThreshold.setAverageLoadValueString(myGraph.getGraphIndex(), load);
+						}
+						return pThreshold.getAverageLoadValueString(myGraph.getGraphIndex());
+					}
+					case COLUMN_ID_BINARY:
+					{
+						DecimalFormat timeFormat = new DecimalFormat(Messages.getString("AddrBinaryTable.decimalFormat")); //$NON-NLS-1$
+						int count = pThreshold.getItemCount(myGraph.getGraphIndex());
+
+						return count + (count > 1 ? Messages.getString("AddrBinaryTable.threshold1") : Messages.getString("AddrBinaryTable.threshold2"))   //$NON-NLS-1$ //$NON-NLS-2$
+								+ timeFormat.format((Double)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdLoadBinary") * 100.0) + Messages.getString("AddrBinaryTable.threshold3") //$NON-NLS-1$ //$NON-NLS-2$ 
+								+ (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary") + Messages.getString("AddrBinaryTable.threshold4"); //$NON-NLS-1$ //$NON-NLS-2$	
+					}
+					case COLUMN_ID_SAMPLE_COUNT:
+					{
+						// Sample count
+						return String.valueOf(pThreshold.getSampleCount(myGraph.getGraphIndex()));
+					}
+					default:
+					{
+						return ""; //$NON-NLS-1$
+					}
+				}
+			}
+			
+			if (!(element instanceof ProfiledBinary))
+				return ""; //$NON-NLS-1$
+
+			ProfiledBinary profiledItem = (ProfiledBinary) element;
+
+			switch (columnId)
+			{
+				case COLUMN_ID_SHOW:
+				{
+					return SHOW_ITEM_VALUE;
+				}
+				case COLUMN_ID_PERCENT_LOAD:
+				{
+					// Percent load string
+					return profiledItem.getAverageLoadValueString(myGraph.getGraphIndex());
+				}
+				case COLUMN_ID_BINARY:
+				{
+					// Binary
+					String binary = profiledItem.getNameString();
+					int index = binary.lastIndexOf('\\');
+					if (index == -1)
+						return binary;
+					else
+						return binary.substring(index + 1);
+				}
+				case COLUMN_ID_PATH:
+				{
+					// Path
+					String binary = profiledItem.getNameString();
+					int index = binary.lastIndexOf('\\');
+					if (index == -1)
+						return ""; //$NON-NLS-1$
+					else
+						return binary.substring(0, index);
+				}
+				case COLUMN_ID_SAMPLE_COUNT:
+				{
+					// Sample count
+					return String.valueOf(profiledItem.getSampleCount(myGraph.getGraphIndex()));
+				}
+				default:
+				{
+					break;
+				}
+			}
+			// should never get here
+			return ""; //$NON-NLS-1$
+		}
+
+		public Image getColumnImage(Object element, int columnIndex) {
+			return null;
+		}
+	}
+
+	public void action(String actionString)
+	{
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (   actionString.equals("add") //$NON-NLS-1$
+			|| actionString.equals("remove")) //$NON-NLS-1$
+	    {
+			actionAddRemove(actionString, graphIndex);
+			return;
+	    }
+		else if (   actionString.equals("addall") //$NON-NLS-1$
+				 || actionString.equals("removeall")) //$NON-NLS-1$
+	    {
+			actionAddRemoveAll(actionString, graphIndex);
+			return;
+	    }
+		else if (actionString.equals("recolor")) //$NON-NLS-1$
+		{
+			actionRecolor();
+			return;
+		}
+	    else if (actionString.equals("copy")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, this.table, CHECKBOX_NO_TEXT, false, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("copyTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, this.table, CHECKBOX_NO_TEXT, true, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("copyDrilldown")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSaveDrilldown(true, "\t"); //$NON-NLS-1$
+	        return;
+	    }
+	    else if (actionString.equals("saveTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(false, this.table, CHECKBOX_NO_TEXT, true, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("saveDrilldown")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSaveDrilldown(false, ","); //$NON-NLS-1$
+	        return;
+	    }
+	    else if (actionString.equals("saveSamples")) //$NON-NLS-1$
+	    {
+	    	SaveSampleString saveSampleString = new SaveSampleString(graphIndex, myGraph.getDrawMode());
+	    	actionSaveSamples(saveSampleString); //$NON-NLS-1$
+	        return;
+	    }
+		else if (actionString.equals("selectAll")) //$NON-NLS-1$
+	    {
+	    	actionSelectAll();
+	        return;
+	    }
+		else if (actionString.equals("doubleClick")) //$NON-NLS-1$
+	    {
+	    	copyAction.setEnabled(false);
+			PIPageEditor.getActionBars().updateActionBars();
+	        return;
+	    }
+		else if (actionString.equals("sortfullpath")) //$NON-NLS-1$
+		{
+            if (this.sortColumn == COLUMN_ID_FULL_PATH)
+            	// sort in other order
+            	sortAscending = !sortAscending;
+            else
+            	// sort in ascending order
+            	sortAscending = true;
+            sortColumn = COLUMN_ID_FULL_PATH;
+            quickSort(sortColumn, profiledBinaries);
+            return;
+		}
+		else if (actionString.equals("binary-only")) //$NON-NLS-1$
+		{
+			actionBinary();
+			return;
+		}
+		else if (actionString.equals("binary-thread")) //$NON-NLS-1$
+		{
+			actionBinaryThread();
+			return;
+		}
+		else if (actionString.equals("binary-thread-function")) //$NON-NLS-1$
+		{
+			actionBinaryThreadFunction();
+			return;
+		}
+		else if (actionString.equals("binary-function")) //$NON-NLS-1$
+		{
+			actionBinaryFunction();
+			return;
+		}
+		else if (actionString.equals("binary-function-thread")) //$NON-NLS-1$
+		{
+			actionBinaryFunctionThread();
+			return;
+		}
+		else if (   (actionString.equals("thread-only")) //$NON-NLS-1$
+				 || (actionString.equals("thread-binary")) //$NON-NLS-1$
+				 || (actionString.equals("thread-binary-function")) //$NON-NLS-1$
+				 || (actionString.equals("thread-function")) //$NON-NLS-1$
+				 || (actionString.equals("thread-function-binary"))) //$NON-NLS-1$
+		{
+			// let the thread page action handler handle it
+			this.myGraph.getThreadTable().action(actionString);
+			return;
+		}
+		else if (   (actionString.equals("function-only")) //$NON-NLS-1$
+				 || (actionString.equals("function-thread")) //$NON-NLS-1$
+				 || (actionString.equals("function-thread-binary")) //$NON-NLS-1$
+				 || (actionString.equals("function-binary")) //$NON-NLS-1$
+				 || (actionString.equals("function-binary-thread"))) //$NON-NLS-1$
+		{
+			// let the function page action handler handle it
+			this.myGraph.getFunctionTable().action(actionString);
+			return;
+		}
+		else if (actionString.equals("changeThresholdBinary")) //$NON-NLS-1$
+		{
+			ProfiledThreshold threshold = this.myGraph.getThresholdBinary();
+			boolean enabled = threshold.isEnabled(graphIndex);
+
+			this.tableItemData.clear();
+			this.profiledBinaries.clear();
+			this.myGraph.getSortedBinaries().clear();
+			if (threshold.getItems(graphIndex) != null)
+				threshold.getItems(graphIndex).clear();
+			threshold.initAll();
+
+			// if this appears, it needs to be the first item, so that it is drawn at the bottom
+			myGraph.getSortedBinaries().add(threshold);
+
+			int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary");	//$NON-NLS-1$
+			for (int i = 0; i < this.myGraph.getGppTrace().getSortedBinaries().size(); i++) {
+				ProfiledGeneric nextElement = (ProfiledGeneric)this.myGraph.getGppTrace().getSortedBinaries().get(i);
+				if (nextElement.getTotalSampleCount() < binaryThreshold) {
+					nextElement.setEnabled(graphIndex, enabled);
+					threshold.addItem(graphIndex, nextElement, 0);
+				} else {
+					tableItemData.add(nextElement);
+					profiledBinaries.add(nextElement);
+					myGraph.getSortedBinaries().add(nextElement);
+				}
+			}
+
+			if (threshold.getItemCount(graphIndex) != 0) {
+				tableItemData.add(threshold);
+				profiledBinaries.add(threshold);
+			} else {
+				// remove the threshold item
+				myGraph.getSortedBinaries().remove(0);
+			}
+			
+			refreshTableViewer();
+			threshold.setEnabled(graphIndex, enabled);
+
+			// make sure that checkboxes shown reflect the actual enabled values
+			TableItem[] tableItems = this.table.getItems();
+			for (int i = 0; i < tableItems.length; i++) {
+				if (tableItems[i].getData() instanceof ProfiledGeneric) {
+					ProfiledGeneric pGeneric = (ProfiledGeneric) tableItems[i].getData();
+					if (tableItems[i].getChecked() != pGeneric.isEnabled(graphIndex))
+						tableItems[i].setChecked(pGeneric.isEnabled(graphIndex));
+				}
+			}
+
+			this.myGraph.genericRefreshCumulativeThreadTable();
+		}
+	    else if (actionString.equals("saveTableTest")) //$NON-NLS-1$
+	    {
+			// copy save file contents to the clipboard for easy viewing
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+			SaveTableString getString = new SaveTableString(this.table, CHECKBOX_NO_TEXT, Messages.getString("AddrBinaryTable.comma"), "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        String copyString = getString.getData();
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+	        return;
+	    }
+	    else if (actionString.equals("saveDrilldownTest")) //$NON-NLS-1$
+	    {
+			// copy save file contents to the clipboard for easy viewing
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+	        Table[] tables = getDrillDownTables();
+	        
+	        int tableCount = 0;
+	        while (tableCount < tables.length && tables[tableCount] != null)
+	        	tableCount++;
+
+	        SaveDrillDownString getString = new SaveDrillDownString(tableCount, tables, Messages.getString("AddrBinaryTable.comma")); //$NON-NLS-1$
+	        String copyString = getString.getData();
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+	        return;
+	    }
+	}
+
+	private void actionAddRemove(String actionString, int graphIndex)
+	{
+		ProfiledGeneric pGeneric;
+		int totalSamples = 0;
+		
+		// true for "add", false for "remove"
+		boolean addIt = actionString.equals("add"); //$NON-NLS-1$
+
+		TableItem[] selectedItems = this.table.getSelection();
+		for (int i = 0; i < selectedItems.length; i++)
+		{
+			selectedItems[i].setChecked(addIt);
+			Object item = ((TableItem)selectedItems[i]).getData();
+			if (item instanceof ProfiledGeneric)
+			{
+				pGeneric = (ProfiledGeneric)item;
+				pGeneric.setEnabled(graphIndex, addIt);
+				totalSamples += pGeneric.getSampleCount(graphIndex);
+   				
+   				if (item instanceof ProfiledThreshold)
+   				{
+   					ProfiledThreshold pThreshold = (ProfiledThreshold)item;
+   					ArrayList<ProfiledGeneric> items = pThreshold.getItems(graphIndex);
+   					for (int j = 0; j < items.size(); j++)
+   						items.get(j).setEnabled(graphIndex, addIt);
+   				}
+			}
+		}
+
+        // this table's set of checkbox-selected rows has changed,
+		// so propagate that information
+		Object[] selectedValues = this.tableViewer.getCheckedElements();
+		String[] nameList = new String[selectedValues.length];
+
+		for (int i = 0; i < selectedValues.length; i++)
+		{
+   			if (selectedValues[i] instanceof ProfiledGeneric)
+   			{
+   				pGeneric = (ProfiledGeneric)selectedValues[i];
+   				nameList[i] = pGeneric.getNameString();
+   			}
+		}
+
+		PIVisualSharedData shared = myGraph.getSharedDataInstance();
+		shared.GPP_SelectedBinaryNames = nameList;
+
+  		if (   (totalSamples != 0)
+      		|| (myGraph.getDrawMode() == Defines.BINARIES))
+      			selectionChangeNotify();
+
+  		this.table.deselectAll();
+	}
+	
+	private void actionAddRemoveAll(String actionString, int graphIndex)
+	{
+		ProfiledGeneric pGeneric;
+
+		// true for "add", false for "remove"
+		boolean addIt = actionString.equals("addall"); //$NON-NLS-1$
+
+		TableItem[] selectedItems = this.table.getItems();
+		String[] nameList = new String[selectedItems.length];
+		for (int i = 0; i < selectedItems.length; i++)
+		{
+			selectedItems[i].setChecked(addIt);
+			Object item = ((TableItem)selectedItems[i]).getData();
+			if (item instanceof ProfiledGeneric)
+			{
+				pGeneric = (ProfiledGeneric)item;
+				pGeneric.setEnabled(graphIndex, addIt);
+   				nameList[i] = pGeneric.getNameString();
+   				
+   				if (item instanceof ProfiledThreshold)
+   				{
+   					ProfiledThreshold pThreshold = (ProfiledThreshold)item;
+   					ArrayList<ProfiledGeneric> items = pThreshold.getItems(graphIndex);
+   					for (int j = 0; j < items.size(); j++)
+   						items.get(j).setEnabled(graphIndex, addIt);
+   				}
+			}
+		}
+
+        // this table's set of checkbox-selected rows has changed,
+		// so propagate that information
+		PIVisualSharedData shared = myGraph.getSharedDataInstance();
+		shared.GPP_SelectedBinaryNames = nameList;
+
+			selectionChangeNotify();
+  		this.table.deselectAll();
+	}
+	
+	private void actionRecolor()
+	{
+		int uid				= this.myGraph.getUid();
+		GppTrace gppTrace = this.myGraph.getGppTrace();
+
+		// recolor selected items
+		boolean didRecolor = false;
+
+		TableItem[] selectedItems = table.getSelection();
+		TableColorPalette palette = ((GppTrace)this.myGraph.getTrace()).getBinaryColorPalette();
+		for (int i = 0; i < selectedItems.length;i++)
+		{
+			if (selectedItems[i].getData() instanceof ProfiledGeneric)
+			{
+				ProfiledGeneric pGeneric = (ProfiledGeneric)selectedItems[i].getData();
+				String nameKey = pGeneric.getNameString();
+				if (palette.recolorEntryDialog(table.getShell(), nameKey))
+				{
+					Color color = palette.getColor(nameKey);
+					Color oldColor = pGeneric.getColor();
+					
+					if (color.equals(oldColor))
+						continue;
+					
+					didRecolor = true;
+					
+					if (!(pGeneric instanceof ProfiledThreshold)) {
+						PIPageEditor.currentPageEditor().setDirty();
+						pGeneric.setColor(color);
+					} else {
+						// for the threshold item, we must change every graph's binary threshold item
+						gppTrace.getGppGraph(PIPageEditor.THREADS_PAGE,   uid).getThresholdBinary().setColor(color);
+						gppTrace.getGppGraph(PIPageEditor.BINARIES_PAGE,  uid).getThresholdBinary().setColor(color);
+						gppTrace.getGppGraph(PIPageEditor.FUNCTIONS_PAGE, uid).getThresholdBinary().setColor(color);
+					}
+				}
+
+				// recoloring should only be done in a draw mode that displays this table's colors
+				selectedItems[i].setBackground(COLOR_COLUMN_INDEX, palette.getColor(nameKey));
+			}
+		}
+		
+		if (!didRecolor)
+			return;
+
+		table.redraw();
+		this.myGraph.repaint();
+		this.myGraph.setGraphImageChanged(true);	// any selection change to drill down will change graph
+		
+		// if any other tabs are displaying this type of graph, they need to be scheduled for redrawing
+		for (int i = 0; i < 3; i++) {
+			GppTraceGraph graph = gppTrace.getGppGraph(i, uid);
+
+			if (graph == this.myGraph)
+				continue;
+
+			int drawMode = graph.getDrawMode();
+			
+			if (   (drawMode == Defines.BINARIES)
+				|| (drawMode == Defines.THREADS_BINARIES)
+				|| (drawMode == Defines.THREADS_FUNCTIONS_BINARIES)
+				|| (drawMode == Defines.FUNCTIONS_BINARIES)
+				|| (drawMode == Defines.FUNCTIONS_THREADS_BINARIES)) {
+				graph.getBinaryTable().addColor(drawMode);
+				graph.setGraphImageChanged(true);	// any selection change to drill down will change graph
+				graph.repaint();
+			}
+		}
+	}
+
+	private void actionBinary()
+	{
+		// current drawMode should be BINARIES, BINARIES_THREADS, BINARIES_THREADS_FUNCTIONS,
+		// BINARIES_FUNCTIONS, or BINARIES_FUNCTIONS_THREADS
+		int drawMode = this.myGraph.getDrawMode();
+
+		if (   (drawMode != Defines.BINARIES_THREADS)
+			&& (drawMode != Defines.BINARIES_THREADS_FUNCTIONS)
+			&& (drawMode != Defines.BINARIES_FUNCTIONS)
+			&& (drawMode != Defines.BINARIES_FUNCTIONS_THREADS))
+		{
+			// this case should be drawMode == Defines.BINARIES
+			return;
+		}
+
+		setIsDrilldown(false);
+
+		// set the page's graph title
+		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+		pV.getTitle().setText(Messages.getString("AddrBinaryTable.binaryLoad"));  //$NON-NLS-1$
+		pV.getTitle2().setText(""); //$NON-NLS-1$
+
+		// get rid of any existing tables and sashes
+		if (this.myGraph.getLeftSash() != null) {
+			this.myGraph.getLeftSash().dispose();
+			this.myGraph.setLeftSash(null);
+
+			// detach the table from the sash
+			try {
+				FormData formData = (FormData) this.table.getLayoutData();
+				formData.right = new FormAttachment(100);
+			} catch (ClassCastException e1) {
+			}
+		}
+		if (this.myGraph.getRightSash() != null) {
+			this.myGraph.getRightSash().dispose();
+			this.myGraph.setRightSash(null);
+		}
+		if (   (this.myGraph.getThreadTable() != null)
+			&& (this.myGraph.getThreadTable().getTable() != null)) {
+			this.myGraph.getThreadTable().getTableViewer().getTable().dispose();
+			this.myGraph.getThreadTable().setTableViewer(null);
+		}
+		if (   (this.myGraph.getFunctionTable() != null)
+			&& (this.myGraph.getFunctionTable().getTable() != null)) {
+			this.myGraph.getFunctionTable().getTableViewer().getTable().dispose();
+			this.myGraph.getFunctionTable().setTableViewer(null);
+		}
+
+		// set the draw mode
+		this.myGraph.setDrawMode(Defines.BINARIES);
+
+		// show colors in the rightmost table
+		addColor(Defines.BINARIES);
+
+		this.parent.layout();
+
+ 		this.myGraph.repaint();
+	}
+
+	private void actionBinaryThread()
+	{
+		// current drawMode should be BINARIES, BINARIES_THREADS, or BINARIES_THREADS_FUNCTIONS
+		int drawMode = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (   drawMode != Defines.BINARIES
+			&& drawMode != Defines.BINARIES_THREADS_FUNCTIONS) {
+			return;
+		}
+
+		setIsDrilldown(true);
+
+		if (drawMode == Defines.BINARIES) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrBinaryTable.threadLoad"));  //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrBinaryTable.binaryTo"));  //$NON-NLS-1$
+
+			// set the draw mode before populating table viewers, since the
+			// color column depends on the draw mode
+			this.myGraph.setDrawMode(Defines.BINARIES_THREADS);
+
+			// create the thread graph table viewer
+			AddrThreadTable threadTable = this.myGraph.getThreadTable();
+			threadTable.createTableViewer(Defines.BINARIES_THREADS);
+			threadTable.setIsDrilldown(true);
+
+			// create a reduced set of thread entries based on enabled binary entries
+			GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+			Vector<ProfiledGeneric> threads = gppTrace.setBinaryThread(graphIndex);
+			this.myGraph.setProfiledThreads(threads);
+
+			// put check marks on all rows, and sort by sample count
+			threadTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledThreads());
+			threadTable.updateProfiledAndItemData(true);
+			threadTable.getTableViewer().setAllChecked(true);
+			threadTable.getTableViewer().refresh();
+			
+			// remove colors where appropriate
+			removeColor(Defines.BINARIES_THREADS);
+
+			// connect the tables with a sash
+			Sash leftSash   = new Sash(this.parent, SWT.VERTICAL);
+
+			final FormData leftSashData = new FormData();
+			leftSashData.top    = new FormAttachment(0);
+			leftSashData.bottom = new FormAttachment(100);
+			leftSashData.left   = new FormAttachment(50); // middle
+			leftSash.setLayoutData(leftSashData);
+
+			final Composite sashParent = this.parent;
+			leftSash.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					if (event.detail != SWT.DRAG) {
+						leftSashData.left = new FormAttachment(0, event.x);
+						sashParent.layout();
+					}
+				}
+			});
+
+			myGraph.setLeftSash(leftSash);
+
+			// attach the thread table to the sash
+			final FormData viewerData = new FormData();
+			viewerData.top    = new FormAttachment(0);
+			viewerData.bottom = new FormAttachment(100);
+			viewerData.left   = new FormAttachment(leftSash);
+			viewerData.right  = new FormAttachment(100);
+			threadTable.getTable().setLayoutData(viewerData);
+
+			// attach the binary table to the sash
+			try {
+				FormData formData = (FormData) this.table.getLayoutData();
+				formData.right = new FormAttachment(leftSash);
+			} catch (ClassCastException e1) {
+			}
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+
+		} else if (drawMode == Defines.BINARIES_THREADS_FUNCTIONS) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrBinaryTable.threadLoad"));  //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrBinaryTable.binaryTo"));  //$NON-NLS-1$
+
+			// get rid of the function table and its sash
+			if (this.myGraph.getRightSash() != null) {
+				this.myGraph.getRightSash().dispose();
+				this.myGraph.setRightSash(null);
+			}
+			if (   (this.myGraph.getFunctionTable() != null)
+				&& (this.myGraph.getFunctionTable().getTable() != null)) {
+				this.myGraph.getFunctionTable().getTableViewer().getTable().dispose();
+				this.myGraph.getFunctionTable().setTableViewer(null);
+			}
+
+			// get rid of the middle table's connection to the sash
+			try {
+				FormData formData = (FormData) this.myGraph.getThreadTable().getTable().getLayoutData();
+				formData.right = new FormAttachment(100);
+			} catch (ClassCastException e1) {
+			}
+
+			// move the left sash to the middle
+			try {
+				FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+				formData.left = new FormAttachment(50); // middle
+			} catch (ClassCastException e1) {
+			}
+
+			// set the draw mode
+			this.myGraph.setDrawMode(Defines.BINARIES_THREADS);
+			
+			// show colors in the rightmost table
+			this.myGraph.getThreadTable().addColor(Defines.BINARIES_THREADS);
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+		}
+
+		// this case should be drawMode == Defines.BINARIES_THREADS
+		return;
+	}
+
+	private void actionBinaryThreadFunction()
+	{
+		// current drawMode should be BINARIES_THREADS or BINARIES_THREADS_FUNCTIONS
+		int drawMode = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (drawMode != Defines.BINARIES_THREADS) {
+			// this case should be drawMode == Defines.BINARIES_THREADS_FUNCTIONS
+			return;
+		}
+
+		setIsDrilldown(true);
+
+		// set the page's graph title
+		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+		pV.getTitle().setText(Messages.getString("AddrBinaryTable.functionLoad"));  //$NON-NLS-1$
+		pV.getTitle2().setText(Messages.getString("AddrBinaryTable.binaryToThreadTo"));  //$NON-NLS-1$
+
+		// set the draw mode before populating table viewers, since the
+		// color column depends on the draw mode
+		this.myGraph.setDrawMode(Defines.BINARIES_THREADS_FUNCTIONS);
+
+		// create the function graph table viewer
+		AddrFunctionTable functionTable = this.myGraph.getFunctionTable();
+		functionTable.createTableViewer(Defines.BINARIES_THREADS_FUNCTIONS);
+		functionTable.setIsDrilldown(true);
+
+		// create a reduced set of function entries based on enabled thread and binary entries
+		GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+		Vector<ProfiledGeneric> functions = gppTrace.setBinaryThreadFunction(graphIndex);
+		this.myGraph.setProfiledFunctions(functions);
+
+		// put check marks on all rows, and sort by sample count
+		functionTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledFunctions());
+		functionTable.updateProfiledAndItemData(true);
+		functionTable.getTableViewer().setAllChecked(true);
+		functionTable.getTableViewer().refresh();
+
+		// remove colors where appropriate
+		this.myGraph.getThreadTable().removeColor(Defines.BINARIES_THREADS_FUNCTIONS);
+
+		// connect the 2nd and 3rd tables with a sash
+		Sash rightSash   = new Sash(this.parent, SWT.VERTICAL);
+
+		final FormData rightSashData = new FormData();
+		rightSashData.top    = new FormAttachment(0);
+		rightSashData.bottom = new FormAttachment(100);
+		rightSashData.left   = new FormAttachment(67); // two thirds
+		rightSash.setLayoutData(rightSashData);
+
+		final Composite sashParent = this.parent;
+		rightSash.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				if (event.detail != SWT.DRAG) {
+					rightSashData.left = new FormAttachment(0, event.x);
+					sashParent.layout();
+				}
+			}
+		});
+
+		myGraph.setRightSash(rightSash);
+
+		// attach the function table to the sash
+		final FormData viewerData = new FormData();
+		viewerData.top    = new FormAttachment(0);
+		viewerData.bottom = new FormAttachment(100);
+		viewerData.left   = new FormAttachment(rightSash);
+		viewerData.right  = new FormAttachment(100);
+		functionTable.getTable().setLayoutData(viewerData);
+
+		// attach the thread table to the sash
+		try {
+			FormData formData = (FormData) this.myGraph.getThreadTable().getTable().getLayoutData();
+			formData.right = new FormAttachment(rightSash);
+		} catch (ClassCastException e1) {
+		}
+
+		// move the left sash to 1/3 from the left
+		try {
+			FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+			formData.left = new FormAttachment(33); // one third
+		} catch (ClassCastException e1) {
+		}
+
+		this.parent.layout();
+
+		this.myGraph.repaint();
+	}
+
+	private void actionBinaryFunction()
+	{
+		// current drawMode should be BINARIES, BINARIES_FUNCTIONS, or BINARIES_FUNCTIONS_THREADS
+		int drawMode = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (   drawMode != Defines.BINARIES
+			&& drawMode != Defines.BINARIES_FUNCTIONS_THREADS) {
+			return;
+		}
+
+		setIsDrilldown(true);
+
+		if (drawMode == Defines.BINARIES) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrBinaryTable.functionLoad"));  //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrBinaryTable.binaryTo"));  //$NON-NLS-1$
+
+			// set the draw mode
+			this.myGraph.setDrawMode(Defines.BINARIES_FUNCTIONS);
+
+			// create the function graph table viewer
+			AddrFunctionTable functionTable = this.myGraph.getFunctionTable();
+			functionTable.createTableViewer(Defines.BINARIES_FUNCTIONS);
+			functionTable.setIsDrilldown(true);
+
+			// create a reduced set of function entries based on enabled binary entries
+			GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+			Vector<ProfiledGeneric> functions = gppTrace.setBinaryFunction(graphIndex);
+			this.myGraph.setProfiledFunctions(functions);
+
+			// put check marks on all rows, and sort by sample count
+			functionTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledFunctions());
+			functionTable.updateProfiledAndItemData(true);
+			functionTable.getTableViewer().setAllChecked(true);
+			functionTable.getTableViewer().refresh();
+
+			// remove colors where appropriate
+			removeColor(Defines.BINARIES_FUNCTIONS);
+
+			// connect the tables with a sash
+			Sash leftSash   = new Sash(this.parent, SWT.VERTICAL);
+
+			final FormData leftSashData = new FormData();
+			leftSashData.top    = new FormAttachment(0);
+			leftSashData.bottom = new FormAttachment(100);
+			leftSashData.left   = new FormAttachment(50); // middle
+			leftSash.setLayoutData(leftSashData);
+
+			final Composite sashParent = this.parent;
+			leftSash.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					if (event.detail != SWT.DRAG) {
+						leftSashData.left = new FormAttachment(0, event.x);
+						sashParent.layout();
+					}
+				}
+			});
+
+			myGraph.setLeftSash(leftSash);
+
+			// attach the function table to the sash
+			final FormData viewerData = new FormData();
+			viewerData.top    = new FormAttachment(0);
+			viewerData.bottom = new FormAttachment(100);
+			viewerData.left   = new FormAttachment(leftSash);
+			viewerData.right  = new FormAttachment(100);
+			functionTable.getTable().setLayoutData(viewerData);
+
+			// attach the binary table to the sash
+			try {
+				FormData formData = (FormData) this.table.getLayoutData();
+				formData.right = new FormAttachment(leftSash);
+			} catch (ClassCastException e1) {
+			}
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+
+		} else if (drawMode == Defines.BINARIES_FUNCTIONS_THREADS) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrBinaryTable.functionLoad"));  //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrBinaryTable.binaryTo"));  //$NON-NLS-1$
+
+			// get rid of the threads table and its sash
+			if (this.myGraph.getRightSash() != null) {
+				this.myGraph.getRightSash().dispose();
+				this.myGraph.setRightSash(null);
+			}
+
+			if (   (this.myGraph.getThreadTable() != null)
+				&& (this.myGraph.getThreadTable().getTable() != null)) {
+				this.myGraph.getThreadTable().getTableViewer().getTable().dispose();
+				this.myGraph.getThreadTable().setTableViewer(null);
+			}
+
+			// get rid of the middle table's connection to the sash
+			try {
+				FormData formData = (FormData) this.myGraph.getFunctionTable().getTable().getLayoutData();
+				formData.right = new FormAttachment(100);
+			} catch (ClassCastException e1) {
+			}
+
+			// move the left sash to the middle
+			try {
+				FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+				formData.left = new FormAttachment(50); // middle
+			} catch (ClassCastException e1) {
+			}
+
+			// set the draw mode
+			this.myGraph.setDrawMode(Defines.BINARIES_FUNCTIONS);
+
+			// show colors in the rightmost table
+			this.myGraph.getFunctionTable().addColor(Defines.BINARIES_FUNCTIONS);
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+		}
+
+		// this case should be drawMode == Defines.BINARIES_THREADS
+		return;
+	}
+
+	private void actionBinaryFunctionThread()
+	{
+		// current drawMode is BINARIES_FUNCTIONS, or BINARIES_FUNCTIONS_THREADS
+		int drawMode = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (drawMode != Defines.BINARIES_FUNCTIONS) {
+			// this case should be drawMode == Defines.BINARIES_FUNCTIONS_THREADS
+			return;
+		}
+
+		setIsDrilldown(true);
+
+		// set the page's graph title
+		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+		pV.getTitle().setText(Messages.getString("AddrBinaryTable.threadLoad"));  //$NON-NLS-1$
+		pV.getTitle2().setText(Messages.getString("AddrBinaryTable.binaryToFunctionTo"));  //$NON-NLS-1$
+
+		// set the draw mode
+		this.myGraph.setDrawMode(Defines.BINARIES_FUNCTIONS_THREADS);
+
+		// create the thread graph table viewer
+		AddrThreadTable threadTable = this.myGraph.getThreadTable();
+		threadTable.createTableViewer(Defines.BINARIES_FUNCTIONS_THREADS);
+		threadTable.setIsDrilldown(true);
+
+		// create a reduced set of thread entries based on enabled binary and function entries
+		GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+		Vector<ProfiledGeneric> threads = gppTrace.setBinaryFunctionThread(graphIndex);
+		this.myGraph.setProfiledThreads(threads);
+
+		// put check marks on all rows, and sort by sample count
+		threadTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledThreads());
+		threadTable.updateProfiledAndItemData(true);
+		threadTable.getTableViewer().setAllChecked(true);
+		threadTable.getTableViewer().refresh();
+
+		// remove colors where appropriate
+		this.myGraph.getFunctionTable().removeColor(Defines.BINARIES_FUNCTIONS_THREADS);
+
+		// connect the 2nd and 3rd tables with a sash
+		Sash rightSash   = new Sash(this.parent, SWT.VERTICAL);
+
+		final FormData rightSashData = new FormData();
+		rightSashData.top    = new FormAttachment(0);
+		rightSashData.bottom = new FormAttachment(100);
+		rightSashData.left   = new FormAttachment(67); // two thirds
+		rightSash.setLayoutData(rightSashData);
+
+		final Composite sashParent = this.parent;
+		rightSash.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				if (event.detail != SWT.DRAG) {
+					rightSashData.left = new FormAttachment(0, event.x);
+					sashParent.layout();
+				}
+			}
+		});
+
+		myGraph.setRightSash(rightSash);
+
+		// attach the thread table to the sash
+		final FormData viewerData = new FormData();
+		viewerData.top    = new FormAttachment(0);
+		viewerData.bottom = new FormAttachment(100);
+		viewerData.left   = new FormAttachment(rightSash);
+		viewerData.right  = new FormAttachment(100);
+		threadTable.getTable().setLayoutData(viewerData);
+
+		// attach the function table to the sash
+		try {
+			FormData formData = (FormData) this.myGraph.getFunctionTable().getTable().getLayoutData();
+			formData.right = new FormAttachment(rightSash);
+		} catch (ClassCastException e1) {
+		}
+
+		// move the left sash to 1/3 from the left
+		try {
+			FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+			formData.left = new FormAttachment(33); // one third
+		} catch (ClassCastException e1) {
+		}
+
+		this.parent.layout();
+
+		this.myGraph.repaint();
+	}
+
+	protected Menu getTableMenu(Decorations parent, int graphIndex, int drawMode) {
+		// get rid of last Menu created so we don't have double menu
+		// on click
+		if (contextMenu != null) {
+			contextMenu.dispose();
+		}
+
+		contextMenu = new Menu(parent, SWT.POP_UP);
+
+		// Use drawMode to determine the drill down items and
+		// whether to show a color column
+		addDrillDownItems(contextMenu, drawMode);
+		
+		// sort by path, then binary
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getSortFullPathItem(contextMenu, this.table.getItemCount() > 0);
+
+		// check and uncheck boxes
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getCheckRows(contextMenu, this.table.getSelectionCount() > 0);
+		
+		// select all, copy, and copy all
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getSelectAllItem(contextMenu, this.table.getItemCount() > 0);
+		getCopyItem(contextMenu, this.table.getSelectionCount() > 0);
+		getCopyTableItem(contextMenu, this.table.getItemCount() > 0);
+		
+		// copy drilldown tables, if in drilldown mode
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES:
+			case Defines.FUNCTIONS:
+				getCopyDrilldownItem(contextMenu, false);
+				break;
+			default:
+				getCopyDrilldownItem(contextMenu, true);
+				break;
+		}
+		
+		
+		// save all and save drilldown tables, if in drilldown mode
+
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getSaveTableItem(contextMenu, this.table.getItemCount() > 0);
+		
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES:
+			case Defines.FUNCTIONS:
+				getSaveDrilldownItem(contextMenu, false);
+				break;
+			default:
+				getSaveDrilldownItem(contextMenu, true);
+				break;
+		}
+		
+		// save raw samples
+		boolean haveSamples = false;
+		for (int i = 0; !haveSamples && i < profiledBinaries.size(); i++) {
+			ProfiledGeneric pg = profiledBinaries.get(i);
+			haveSamples = pg.isEnabled(graphIndex) && pg.getSampleCount(graphIndex) > 0;
+		}
+
+		double startTime = PIPageEditor.currentPageEditor().getStartTime();
+		double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+		if (!haveSamples || (startTime == -1) || (endTime   == -1) || (startTime == endTime))
+			getSaveSamplesItem(contextMenu, Messages.getString("AddrBinaryTable.binaries"), false); //$NON-NLS-1$
+		else
+			getSaveSamplesItem(contextMenu, Messages.getString("AddrBinaryTable.binaries"), true); //$NON-NLS-1$
+
+		// recolor selected threads
+		switch (drawMode)
+		{
+			case Defines.BINARIES:
+			case Defines.THREADS_FUNCTIONS_BINARIES:
+			case Defines.THREADS_BINARIES:
+			case Defines.FUNCTIONS_THREADS_BINARIES:
+			case Defines.FUNCTIONS_BINARIES:
+			{
+				// recolor selected items
+				new MenuItem(contextMenu, SWT.SEPARATOR);
+				getRecolorItem(contextMenu, Messages.getString("AddressPlugin.binaries"),   //$NON-NLS-1$
+								this.table.getSelectionCount() > 0);
+				break;
+			}
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			case Defines.BINARIES_THREADS:
+			case Defines.BINARIES_THREADS_FUNCTIONS:
+			case Defines.BINARIES_FUNCTIONS:
+			case Defines.BINARIES_FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_BINARIES_THREADS:
+			{
+				break;
+			}
+			default:
+				break;
+		}
+		
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getChangeThresholds(contextMenu);
+
+		contextMenu.setVisible(true);
+
+		return contextMenu;
+	}
+
+	public void focusGained(FocusEvent e) {}
+
+	public void focusLost(FocusEvent e) {}
+
+	public void piEventReceived(PIEvent be)
+	{
+		if (be.getType() == PIEvent.SELECTION_AREA_CHANGED3)
+		{
+			// % loads, % load strings, and/or sample counts have been updated
+			// due to a change in the graph area selected, and all table items
+			// need to be checked
+			updateProfiledAndItemData(true);
+
+			Display.getDefault().syncExec(new Runnable() {
+				public void run() {
+					{
+						quickSort(sortColumn, profiledBinaries);
+					}
+
+					// initially, all rows are selected
+					tableViewer.setAllChecked(true);
+
+					table.redraw();
+				}
+			});
+		}
+		else if (   (be.getType() == PIEvent.SELECTION_AREA_CHANGED2)
+				 || (be.getType() == PIEvent.CHANGED_BINARY_TABLE))
+		{
+			int graphIndex = this.myGraph.getGraphIndex();
+
+			// This routine does not change which binaries are enabled, but it enables
+			// all entries in the 2nd and 3rd tables.
+			// It assumes that GppTrace.setSelectedArea(), action("add") or action("remove") has set
+			// the % load and sample counts for binaries, except for the threshold list.
+			if (be.getType() == PIEvent.SELECTION_AREA_CHANGED2) {
+				int thresholdCount = (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+				if (thresholdCount > 0) {
+					Vector<ProfiledGeneric> pGeneric = this.myGraph.getProfiledBinaries();
+					int sampleCount = 0;
+					for (int i = 0; i < pGeneric.size(); i++)
+						if (pGeneric.elementAt(i).getTotalSampleCount() < thresholdCount)
+							sampleCount += pGeneric.elementAt(i).getSampleCount(graphIndex);
+					this.myGraph.getThresholdBinary().setSampleCount(graphIndex, sampleCount);
+				}
+			}
+
+			// redraw this table
+			Display.getDefault().syncExec(new Runnable() {
+				public void run() {
+					if (   (sortColumn == COLUMN_ID_PERCENT_LOAD)
+						|| (sortColumn == COLUMN_ID_SAMPLE_COUNT))
+					{
+						quickSort(sortColumn, profiledBinaries);
+					}
+					else
+						refreshTableViewer();
+
+					table.redraw();
+				}
+			});
+
+			int drawMode = this.myGraph.getDrawMode();
+			if (drawMode == Defines.BINARIES)
+				return;
+
+			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
+			Vector<ProfiledGeneric> traceBinaries  = trace.getIndexedBinaries();
+
+			int startSampleIndex = trace.getStartSampleIndex();
+			int endSampleIndex   = trace.getEndSampleIndex();
+			double percentPerSample;
+			if (startSampleIndex == endSampleIndex)
+				percentPerSample = 0.0;
+			else
+				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
+
+			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
+			
+			switch (drawMode) {
+				case Defines.BINARIES_THREADS:
+				{
+					// get new thread counts and loads
+					Vector<ProfiledGeneric> traceThreads  = trace.getIndexedThreads();
+					Vector<ProfiledGeneric> graphThreads  = this.myGraph.getProfiledThreads();
+					Hashtable<String,String> foundThreads = new Hashtable<String,String>();
+
+					// previous threads are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enu = graphThreads.elements();
+					while (enu.hasMoreElements()) {
+						ProfiledThread pThread = (ProfiledThread) enu.nextElement();
+						pThread.setEnabled(graphIndex, false);
+					}
+					graphThreads.clear();
+
+					ProfiledThreshold thresholdThread = this.myGraph.getThresholdThread();
+
+					if (thresholdThread.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdThread.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find threads below the threshold
+					boolean lowThread;
+					thresholdThread.init(graphIndex);
+
+					int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+						if (pBinary.isEnabled(graphIndex)) {
+							// thread list is based on binaries
+							ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+							String threadName = pThread.getNameString();
+
+							lowThread = pThread.getTotalSampleCount() < threadThreshold; 
+
+							if (!foundThreads.containsKey(threadName)) {
+								foundThreads.put(threadName, threadName);
+								if (lowThread) {
+									thresholdThread.addItem(graphIndex, pThread, 1);
+								} else {
+									pThread.setEnabled(graphIndex, true);
+									pThread.setSampleCount(graphIndex, 1);
+									graphThreads.add(pThread);
+								}
+							} else {
+								if (lowThread)
+									thresholdThread.incSampleCount(graphIndex);
+								else
+									pThread.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphThreads.size(); i++) {
+						ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
+						pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdThread.setLoadAndString(graphIndex,
+							(float)(thresholdThread.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getThreadTable().piEventReceived(be3);
+					break;
+				}
+				case Defines.BINARIES_THREADS_FUNCTIONS:
+				{
+					// get new counts and loads
+					Vector<ProfiledGeneric> traceThreads    = trace.getIndexedThreads();
+					Vector<ProfiledGeneric> traceFunctions  = trace.getIndexedFunctions();
+					Vector<ProfiledGeneric> graphThreads    = this.myGraph.getProfiledThreads();
+					Vector<ProfiledGeneric> graphFunctions  = this.myGraph.getProfiledFunctions();
+					Hashtable<String,String> foundThreads   = new Hashtable<String,String>();
+					Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
+
+					// previous functions are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuFunctions = graphFunctions.elements();
+					while (enuFunctions.hasMoreElements()) {
+						ProfiledFunction pFunction = (ProfiledFunction) enuFunctions.nextElement();
+						pFunction.setEnabled(graphIndex, false);
+					}
+					graphFunctions.clear();
+
+					ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
+
+					if (thresholdFunction.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					// previous threads are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuThreads = graphThreads.elements();
+					while (enuThreads.hasMoreElements()) {
+						ProfiledThread pThread = (ProfiledThread) enuThreads.nextElement();
+						pThread.setEnabled(graphIndex, false);
+					}
+					graphThreads.clear();
+
+					ProfiledThreshold thresholdThread = this.myGraph.getThresholdThread();
+
+					if (thresholdThread.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdThread.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find threads below the threshold
+					boolean lowThread;
+					thresholdThread.init(graphIndex);
+
+					// set up in case we find threads below the threshold
+					boolean lowFunction;
+					thresholdFunction.init(graphIndex);
+
+					int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+						if (pBinary.isEnabled(graphIndex)) {
+							// thread list is based on binaries
+							ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+							String threadName = pThread.getNameString();
+
+							lowThread = pThread.getTotalSampleCount() < threadThreshold;
+
+							if (!foundThreads.containsKey(threadName)) {
+								foundThreads.put(threadName, threadName);
+								if (lowThread) {
+									thresholdThread.addItem(graphIndex, pThread, 1);
+								} else {
+									pThread.setEnabled(graphIndex, true);
+									pThread.setSampleCount(graphIndex, 1);
+									graphThreads.add(pThread);
+								}
+							} else {
+								if (lowThread)
+									thresholdThread.incSampleCount(graphIndex);
+								else
+									pThread.incSampleCount(graphIndex);
+							}
+
+							// function list is based on binaries and threads
+							ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+							String functionName = pFunction.getNameString();
+
+							lowFunction = pFunction.getTotalSampleCount() < (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+
+							if (!foundFunctions.containsKey(functionName)) {
+								foundFunctions.put(functionName, functionName);
+								if (lowFunction) {
+									thresholdFunction.addItem(graphIndex, pFunction, 1);
+								} else {
+									pFunction.setEnabled(graphIndex, true);
+									pFunction.setSampleCount(graphIndex, 1);
+									graphFunctions.add(pFunction);
+								}
+							} else {
+								if (lowFunction)
+									thresholdFunction.incSampleCount(graphIndex);
+								else
+									pFunction.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphThreads.size(); i++) {
+						ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
+						pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdThread.setLoadAndString(graphIndex,
+							(float)(thresholdThread.getSampleCount(graphIndex)*percentPerSample));
+
+					for (int i = 0; i < graphFunctions.size(); i++) {
+						ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
+						pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdFunction.setLoadAndString(graphIndex,
+							(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getThreadTable().piEventReceived(be3);
+					this.myGraph.getFunctionTable().piEventReceived(be3);
+					break;
+				}
+				case Defines.BINARIES_FUNCTIONS:
+				{
+					// get new function counts and loads
+					Vector<ProfiledGeneric> traceFunctions  = trace.getIndexedFunctions();
+					Vector<ProfiledGeneric> graphFunctions  = this.myGraph.getProfiledFunctions();
+					Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
+
+					// previous functions are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enu = graphFunctions.elements();
+					while (enu.hasMoreElements()) {
+						ProfiledFunction pFunction = (ProfiledFunction) enu.nextElement();
+						pFunction.setEnabled(graphIndex, false);
+					}
+					graphFunctions.clear();
+
+					ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
+
+					if (thresholdFunction.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find functions below the threshold
+					boolean lowFunction;
+					thresholdFunction.init(graphIndex);
+
+					int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+						if (pBinary.isEnabled(graphIndex)) {
+							// function list is based on binaries
+							ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+							String functionName = pFunction.getNameString();
+
+							lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
+
+							if (!foundFunctions.containsKey(functionName)) {
+								foundFunctions.put(functionName, functionName);
+								if (lowFunction) {
+									thresholdFunction.addItem(graphIndex, pFunction, 1);
+								} else {
+									pFunction.setEnabled(graphIndex, true);
+									pFunction.setSampleCount(graphIndex, 1);
+									graphFunctions.add(pFunction);
+								}
+							} else {
+								if (lowFunction)
+									thresholdFunction.incSampleCount(graphIndex);
+								else
+									pFunction.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphFunctions.size(); i++) {
+						ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
+						pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdFunction.setLoadAndString(graphIndex,
+							(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getFunctionTable().piEventReceived(be3);
+					break;
+				}
+				case Defines.BINARIES_FUNCTIONS_THREADS:
+				{
+					// get new function and thread counts and loads
+					Vector<ProfiledGeneric> traceThreads    = trace.getIndexedThreads();
+					Vector<ProfiledGeneric> traceFunctions  = trace.getIndexedFunctions();
+					Vector<ProfiledGeneric> graphThreads    = this.myGraph.getProfiledThreads();
+					Vector<ProfiledGeneric> graphFunctions  = this.myGraph.getProfiledFunctions();
+					Hashtable<String,String> foundThreads   = new Hashtable<String,String>();
+					Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
+
+					// previous threads are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuThreads = graphThreads.elements();
+					while (enuThreads.hasMoreElements()) {
+						ProfiledThread pThread = (ProfiledThread) enuThreads.nextElement();
+						pThread.setEnabled(graphIndex, false);
+					}
+					graphThreads.clear();
+
+					ProfiledThreshold thresholdThread = this.myGraph.getThresholdThread();
+
+					if (thresholdThread.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdThread.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					// previous functions are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuFunctions = graphFunctions.elements();
+					while (enuFunctions.hasMoreElements()) {
+						ProfiledFunction pFunction = (ProfiledFunction) enuFunctions.nextElement();
+						pFunction.setEnabled(graphIndex, false);
+					}
+					graphFunctions.clear();
+
+					ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
+
+					if (thresholdFunction.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find threads below the threshold
+					boolean lowThread;
+					thresholdThread.init(graphIndex);
+
+					// set up in case we find functions below the threshold
+					boolean lowFunction;
+					thresholdFunction.init(graphIndex);
+
+					int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+						if (pBinary.isEnabled(graphIndex)) {
+							// function list is based on binaries
+							ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+							String functionName = pFunction.getNameString();
+
+							lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
+
+							if (!foundFunctions.containsKey(functionName)) {
+								foundFunctions.put(functionName, functionName);
+								if (lowFunction) {
+									thresholdFunction.addItem(graphIndex, pFunction, 1);
+								} else {
+									pFunction.setEnabled(graphIndex, true);
+									pFunction.setSampleCount(graphIndex, 1);
+									graphFunctions.add(pFunction);
+								}
+							} else {
+								if (lowFunction)
+									thresholdFunction.incSampleCount(graphIndex);
+								else
+									pFunction.incSampleCount(graphIndex);
+							}
+
+							// thread list is based on binaries and functions
+							ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+							String threadName = pThread.getNameString();
+
+							lowThread = pThread.getTotalSampleCount() < (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+
+							if (!foundThreads.containsKey(threadName)) {
+								foundThreads.put(threadName, threadName);
+								if (lowThread) {
+									thresholdThread.addItem(graphIndex, pThread, 1);
+								} else {
+									pThread.setEnabled(graphIndex, true);
+									pThread.setSampleCount(graphIndex, 1);
+									graphThreads.add(pThread);
+								}
+							} else {
+								if (lowThread)
+									thresholdThread.incSampleCount(graphIndex);
+								else
+									pThread.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphThreads.size(); i++) {
+						ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
+						pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdThread.setLoadAndString(graphIndex,
+							(float)(thresholdThread.getSampleCount(graphIndex)*percentPerSample));
+
+					for (int i = 0; i < graphFunctions.size(); i++) {
+						ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
+						pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdFunction.setLoadAndString(graphIndex,
+							(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getThreadTable().piEventReceived(be3);
+					this.myGraph.getFunctionTable().piEventReceived(be3);
+					break;
+				}
+				default:
+				{
+					break;
+				}
+			}
+		}
+		else if (be.getType() == PIEvent.CHANGED_THREAD_TABLE)
+		{
+			// This routine enables all entries in the next table
+
+			int drawMode = this.myGraph.getDrawMode();
+			if (drawMode != Defines.BINARIES_THREADS_FUNCTIONS)
+				return;
+
+			// we don't need to redraw the binary table, since it has not changed
+
+			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
+			Vector<ProfiledGeneric> traceThreads = trace.getIndexedThreads();
+
+			int graphIndex = this.myGraph.getGraphIndex();
+			int startSampleIndex = trace.getStartSampleIndex();
+			int endSampleIndex   = trace.getEndSampleIndex();
+			double percentPerSample;
+			if (startSampleIndex == endSampleIndex)
+				percentPerSample = 0.0;
+			else
+				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
+
+			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
+
+			// get new function counts and loads
+			Vector<ProfiledGeneric> traceFunctions  = trace.getIndexedFunctions();
+			Vector<ProfiledGeneric> graphFunctions  = this.myGraph.getProfiledFunctions();
+			Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
+
+			// previous functions are not necessarily graphed this time
+			Enumeration<ProfiledGeneric> enu = graphFunctions.elements();
+			while (enu.hasMoreElements()) {
+				ProfiledFunction pFunction = (ProfiledFunction) enu.nextElement();
+				pFunction.setEnabled(graphIndex, false);
+			}
+			graphFunctions.clear();
+
+			ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
+
+			if (thresholdFunction.isEnabled(graphIndex)) {
+				ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
+				// disable all items below the threshold
+				for (int i = 0; i < items.size(); i++) {
+					items.get(i).setEnabled(graphIndex, false);
+				}
+			}
+
+			GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+			// set up in case we find functions below the threshold
+			boolean lowFunction;
+			thresholdFunction.init(graphIndex);
+
+			int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+			for (int i = startSampleIndex; i < endSampleIndex; i++) {
+				GppSample sample = sortedSamples[i];
+
+				ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+				if (pThread.isEnabled(graphIndex)) {
+					// function list is based on threads
+					ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+					String functionName = pFunction.getNameString();
+
+					lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
+
+					if (!foundFunctions.containsKey(functionName)) {
+						foundFunctions.put(functionName, functionName);
+						if (lowFunction) {
+							thresholdFunction.addItem(graphIndex, pFunction, 1);
+						} else {
+							pFunction.setEnabled(graphIndex, true);
+							pFunction.setSampleCount(graphIndex, 1);
+							graphFunctions.add(pFunction);
+						}
+					} else {
+						if (lowFunction)
+							thresholdFunction.incSampleCount(graphIndex);
+						else
+							pFunction.incSampleCount(graphIndex);
+					}
+				}
+			}
+
+			// set the % load
+			for (int i = 0; i < graphFunctions.size(); i++) {
+				ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
+				pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
+			}
+			thresholdFunction.setLoadAndString(graphIndex,
+											(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
+			
+			// update the table items and redraw the table
+			this.myGraph.getFunctionTable().piEventReceived(be3);
+		}
+		else if (be.getType() == PIEvent.CHANGED_FUNCTION_TABLE)
+		{
+			// This routine enables all entries in the next table
+
+			int drawMode = this.myGraph.getDrawMode();
+			if (drawMode != Defines.BINARIES_FUNCTIONS_THREADS)
+				return;
+
+			// we don't need to redraw the binary table, since it has not changed
+
+			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
+			Vector<ProfiledGeneric> traceFunctions = trace.getIndexedFunctions();
+
+			int graphIndex = this.myGraph.getGraphIndex();
+			int startSampleIndex = trace.getStartSampleIndex();
+			int endSampleIndex   = trace.getEndSampleIndex();
+			double percentPerSample;
+			if (startSampleIndex == endSampleIndex)
+				percentPerSample = 0.0;
+			else
+				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
+
+			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
+
+			// get new thread counts and loads
+			Vector<ProfiledGeneric> traceThreads  = trace.getIndexedThreads();
+			Vector<ProfiledGeneric> graphThreads  = this.myGraph.getProfiledThreads();
+			Hashtable<String,String> foundThreads = new Hashtable<String,String>();
+
+			// previous threads are not necessarily graphed this time
+			Enumeration<ProfiledGeneric> enu = graphThreads.elements();
+			while (enu.hasMoreElements()) {
+				ProfiledThread pThread = (ProfiledThread) enu.nextElement();
+				pThread.setEnabled(graphIndex, false);
+			}
+			graphThreads.clear();
+
+			ProfiledThreshold thresholdThread = this.myGraph.getThresholdThread();
+
+			if (thresholdThread.isEnabled(graphIndex)) {
+				ArrayList<ProfiledGeneric> items = thresholdThread.getItems(graphIndex);
+				// disable all items below the threshold
+				for (int i = 0; i < items.size(); i++) {
+					items.get(i).setEnabled(graphIndex, false);
+				}
+			}
+
+			GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+			// set up in case we find threads below the threshold
+			boolean lowThread;
+			thresholdThread.init(graphIndex);
+
+			int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+			for (int i = startSampleIndex; i < endSampleIndex; i++) {
+				GppSample sample = sortedSamples[i];
+
+				ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+				if (pFunction.isEnabled(graphIndex)) {
+					// thread list is based on functions
+					ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+					String threadName = pThread.getNameString();
+
+					lowThread = pThread.getTotalSampleCount() < threadThreshold;
+
+					if (!foundThreads.containsKey(threadName)) {
+						foundThreads.put(threadName, threadName);
+						if (lowThread) {
+							thresholdThread.addItem(graphIndex, pThread, 1);
+						} else {
+							pThread.setEnabled(graphIndex, true);
+							pThread.setSampleCount(graphIndex, 1);
+							graphThreads.add(pThread);
+						}
+					} else {
+						if (lowThread)
+							thresholdThread.incSampleCount(graphIndex);
+						else
+							pThread.incSampleCount(graphIndex);
+					}
+				}
+			}
+
+			// set the % load
+			for (int i = 0; i < graphThreads.size(); i++) {
+				ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
+				pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex)*percentPerSample));
+			}
+			thresholdThread.setLoadAndString(graphIndex,
+					(float)(thresholdThread.getSampleCount(graphIndex)*percentPerSample));
+
+			// update the table items and redraw the table
+			this.myGraph.getThreadTable().piEventReceived(be3);
+		}
+	}
+
+	public void setSelectedNames()
+	{
+		Object[] selectedValues = this.tableViewer.getCheckedElements();
+        String[] binaryNames = new String[selectedValues.length];
+
+        for (int i = 0; i < selectedValues.length; i++)
+		{
+			if (selectedValues[i] instanceof ProfiledBinary)
+			{
+				ProfiledBinary pBinary = (ProfiledBinary)selectedValues[i];
+				binaryNames[i] = pBinary.getNameString();
+			}
+		}
+
+        PIVisualSharedData shared = myGraph.getSharedDataInstance();
+		shared.GPP_SelectedBinaryNames = binaryNames;
+	}
+
+	private class SharedCheckHandler implements ICheckStateListener
+	{
+		public void checkStateChanged(CheckStateChangedEvent event) {
+
+       		if (!(event.getElement() instanceof ProfiledGeneric))
+       			return;
+       		
+       		// set the stored value to the checkbox value
+       		ProfiledGeneric pg = (ProfiledGeneric)event.getElement();
+	        pg.setEnabled(myGraph.getGraphIndex(), event.getChecked());
+ 
+	        // this table's set of checkbox-selected rows has changed, so propagate that information
+       		setSelectedNames();
+
+       		if (   (pg.getSampleCount(myGraph.getGraphIndex()) != 0)
+       			|| (myGraph.getDrawMode() == Defines.BINARIES))
+       			selectionChangeNotify();
+
+       		table.deselectAll();
+		}
+	}
+
+	private void selectionChangeNotify() {
+		PIEvent be = new PIEvent(null, PIEvent.CHANGED_BINARY_TABLE);
+		myGraph.piEventReceived(be);
+    }
+
+	public void sortOnColumnSelection(TableColumn tableColumn) {
+			int columnId = ((Integer) tableColumn.getData()).intValue();
+            if (sortColumn == columnId) {
+            	// sort in other order
+            	sortAscending = !sortAscending;
+            } else {
+            	// sort in the default order
+				switch (columnId)
+				{
+					case COLUMN_ID_SHOW:
+					case COLUMN_ID_PERCENT_LOAD:
+					case COLUMN_ID_SAMPLE_COUNT:
+					{
+		            	// sort in descending order (for checked boxes, this means selected boxes first)
+		            	sortAscending = false;
+		                break;
+					}
+					case COLUMN_ID_BINARY:
+					case COLUMN_ID_PATH:
+					{
+		            	// sort in descending order
+		            	sortAscending = true;
+		                break;
+					}
+					default:
+					{
+						return;
+					}
+	            }
+            }
+			
+			sortColumn = columnId;
+			quickSort(sortColumn, profiledBinaries);
+	}
+
+	private class ColumnSelectionHandler extends SelectionAdapter
+	{
+		public void widgetSelected(SelectionEvent e)
+        {
+        	// wait for the previous sort to finish
+        	if (sorting || !(e.widget instanceof TableColumn))
+        		return;
+
+        	sortOnColumnSelection((TableColumn) e.widget);
+        }
+	}
+
+	public void updateProfiledAndItemData(boolean setInput)
+	{
+		tableItemData.clear();
+		profiledBinaries.clear();
+
+		// profiledBinaries and tableItemData contain one entry per table row
+		Enumeration<ProfiledGeneric> enu = myGraph.getProfiledBinaries().elements();
+		while (enu.hasMoreElements())
+		{
+			ProfiledBinary nextElement = (ProfiledBinary)enu.nextElement();
+			tableItemData.add(nextElement);
+			profiledBinaries.add(nextElement);
+		}
+
+		if (myGraph.getThresholdBinary().getItemCount(myGraph.getGraphIndex()) != 0) {
+			tableItemData.add(myGraph.getThresholdBinary());
+			profiledBinaries.add(myGraph.getThresholdBinary());
+		}
+
+		// now sort the items in increasing total sample count, so that they graph correctly
+		Object[] sorted = myGraph.getProfiledBinaries().toArray();
+		Arrays.sort(sorted, new Comparator<Object>() {
+			
+			public int compare(Object arg0, Object arg1)
+			{
+				if (arg0 instanceof ProfiledGeneric && arg1 instanceof ProfiledGeneric)
+					return ((ProfiledGeneric)arg0).getTotalSampleCount() -
+							((ProfiledGeneric)arg1).getTotalSampleCount();
+				else
+					return 0;
+			}
+		});
+
+		// now create the sorted list used to draw the graph
+		myGraph.getSortedBinaries().clear();
+
+		if (myGraph.getThresholdBinary().getItemCount(myGraph.getGraphIndex()) != 0)
+			myGraph.getSortedBinaries().add(myGraph.getThresholdBinary());
+
+		for (int i = 0; i < sorted.length; i++)
+			myGraph.getSortedBinaries().add((ProfiledGeneric) sorted[i]);
+
+		// refresh the table, if needed
+		if (setInput)
+			refreshTableViewer();
+	}
+
+	public void quickSort(int sortBy, Vector<ProfiledGeneric> profiled)
+	{
+		if (profiled.size() == 0)
+			return;
+
+		this.sorting = true;
+
+		ProfiledGeneric pGeneric = profiled.elementAt(profiled.size() - 1);
+
+		if (pGeneric instanceof ProfiledThreshold) {
+			profiled.removeElementAt(profiled.size() - 1);
+		}
+
+		this.sorter.setupSort(sortBy, this.myGraph.getGraphIndex(), sortAscending);
+
+		switch (sortBy) {
+			case COLUMN_ID_SHOW:
+			{
+			    this.sorter.quickSortByShow(profiled);
+	            break;
+			}
+			case COLUMN_ID_PERCENT_LOAD:
+			{
+			    this.sorter.quickSortByAverageLoad(profiled);
+	            break;
+			}
+			case COLUMN_ID_THREAD:
+			{
+			    this.sorter.quickSortByThread(profiled);
+	            break;
+			}
+			case COLUMN_ID_BINARY:
+			{
+			    this.sorter.quickSortByBinary(profiled);
+	            break;
+			}
+			case COLUMN_ID_FUNCTION:
+			{
+			    this.sorter.quickSortByFunction(profiled);
+	            break;
+			}
+			case COLUMN_ID_SAMPLE_COUNT:
+			{
+			    this.sorter.quickSortBySampleCount(profiled);
+	            break;
+			}
+			case COLUMN_ID_PATH:
+			{
+			    this.sorter.quickSortByBinaryPath(profiled);
+	            break;
+			}
+			case COLUMN_ID_FULL_PATH:
+			{
+			    this.sorter.quickSortByFullBinaryPath(profiled);
+	            break;
+			}
+			default:
+			{
+				break;
+			}
+		}
+ 		
+		Enumeration<ProfiledGeneric> e = this.sorter.getSortedList().elements();
+		tableItemData = setTableItemData(e);
+		if (pGeneric instanceof ProfiledThreshold) {
+			tableItemData.add(pGeneric);
+			profiled.add(pGeneric);
+		}
+		
+		// find the column corresponding to sortBy, and give it a column direction
+		// NOTE: treat sort by binary path then by binary name as sort by path
+		if (sortBy == COLUMN_ID_FULL_PATH)
+			sortBy = COLUMN_ID_PATH;
+		else if (sortBy == COLUMN_ID_FULL_IN_PATH)
+			sortBy = COLUMN_ID_IN_BINARY_PATH;
+
+		TableColumn sortByColumn = null;
+		for (int i = 0; i < this.table.getColumnCount(); i++) {
+			if (this.table.getColumn(i).getData() instanceof Integer) {
+				if (((Integer)this.table.getColumn(i).getData()) == sortBy) {
+					sortByColumn = this.table.getColumn(i);
+					break;
+				}
+			}
+		}
+
+		if (sortByColumn != null) {
+			this.table.setSortColumn(sortByColumn);
+			this.table.setSortDirection(sortAscending ? SWT.UP : SWT.DOWN);
+		}
+
+		refreshTableViewer();
+		this.sorting = false;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddrDataPerTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+
+/**
+ * Contains  
+ */
+public class AddrDataPerTrace {
+	private final GppTrace   trace;
+	
+	public AddrDataPerTrace(GppTrace trace) {
+		this.trace = trace;
+	}
+	
+	public GppTrace getTrace() {
+		return this.trace;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddrFunctionTable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2390 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.FocusEvent;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Sash;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledBinary;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledFunction;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThreshold;
+import com.nokia.carbide.cpp.internal.pi.visual.Defines;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.internal.pi.visual.PIVisualSharedData;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.SourceLookup;
+import com.nokia.carbide.cpp.pi.util.TableColorPalette;
+
+
+public class AddrFunctionTable extends GenericAddrTable
+{
+	// local copy of profiled binaries, which we can sort
+	// without affecting the original
+	Vector<ProfiledGeneric> profiledFunctions = new Vector<ProfiledGeneric>();
+
+	public AddrFunctionTable(GppTraceGraph myGraph, Composite parent)
+	{
+		this.myGraph = myGraph;
+		this.parent  = parent;
+	}
+
+	public void createTableViewer(int drawMode)
+	{
+		if (this.parent == null)
+			return;
+
+		// Function table:
+		//		checkbox + colored or white background
+		//  	percent load
+		//  	function name
+		//		function start address
+		//		binary containing function
+		//		path of binary containing function
+		//		sample count
+
+		// Check the drawMode, and use it to decide whether or not to show a color column
+		// or the number of samples
+		switch (drawMode)
+		{
+			case Defines.FUNCTIONS:
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			case Defines.BINARIES_FUNCTIONS:
+			case Defines.THREADS_FUNCTIONS:
+			case Defines.BINARIES_THREADS_FUNCTIONS:
+			case Defines.THREADS_FUNCTIONS_BINARIES:
+			case Defines.BINARIES_FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_THREADS_BINARIES:
+			case Defines.FUNCTIONS_BINARIES:
+			case Defines.FUNCTIONS_BINARIES_THREADS:
+			{
+				break;
+			}
+			default:
+				// no function table in this draw mode
+				return;
+		}
+
+		// create the table viewer
+		this.tableViewer = CheckboxTableViewer.newCheckList(this.parent,
+  				SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
+
+		// add the check state handler, label provider and content provider
+		tableViewer.addCheckStateListener(new SharedCheckHandler());
+		tableViewer.setLabelProvider(new shownFunctionsLabelProvider());
+		tableViewer.setContentProvider(new shownFunctionsContentProvider());
+		tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent arg0) {
+				if (copyAction == null)
+					return;
+
+				// when selection changes, the ability to copy may change
+				copyAction.setEnabled(table.getSelectionCount() > 0);
+				PIPageEditor.getActionBars().updateActionBars();
+			}
+		});
+
+		createDefaultActions();
+
+		// make sure the table viewer has a sorter
+		if (this.sorter == null)
+			this.sorter = new GppTableSorter();
+
+		this.table = tableViewer.getTable();
+		this.table.setRedraw(false);
+
+		// give the table a heading for use in copying and exported
+		this.table.setData(Messages.getString("AddrFunctionTable.functions")); //$NON-NLS-1$
+		
+		// create the columns
+		TableColumn column;
+
+		// data associated with the TableViewer will note which columns contain hex values
+		// Keep this in the order in which columns have been created
+		boolean[] isHex = {false, false, false, true, false, false, false};
+		this.table.setData("isHex", isHex); //$NON-NLS-1$
+
+		// select/deselect column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_SHOW);
+		column.setWidth(COLUMN_WIDTH_SHOW);
+		column.setData(new Integer(COLUMN_ID_SHOW));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// percent load column
+		column = new TableColumn(table, SWT.RIGHT);
+		column.setText(COLUMN_HEAD_PERCENT_LOAD);
+		column.setWidth(COLUMN_WIDTH_PERCENT_LOAD);
+		column.setData(new Integer(COLUMN_ID_PERCENT_LOAD));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// function name column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_FUNCTION);
+		column.setWidth(COLUMN_WIDTH_FUNCTION_NAME);
+		column.setData(new Integer(COLUMN_ID_FUNCTION));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// function start address column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_START_ADDR);
+		column.setWidth(COLUMN_WIDTH_START_ADDRESS);
+		column.setData(new Integer(COLUMN_ID_START_ADDR));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// binary containing function column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_IN_BINARY);
+		column.setWidth(COLUMN_WIDTH_IN_BINARY);
+		column.setData(new Integer(COLUMN_ID_IN_BINARY));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// path to binary containing function column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_IN_BINARY_PATH);
+		column.setWidth(COLUMN_WIDTH_IN_BINARY_PATH);
+		column.setData(new Integer(COLUMN_ID_IN_BINARY_PATH));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// sample count column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_SAMPLE_COUNT);
+		column.setWidth(COLUMN_WIDTH_SAMPLE_COUNT);
+		column.setData(new Integer(COLUMN_ID_SAMPLE_COUNT));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// listen for mouse clicks: to select a row, pop up a menu, etc.
+		table.addMouseListener(new TableMouseListener());
+
+		// listen for key sequences such as Ctrl-A and Ctrl-C
+		table.addKeyListener(new TableKeyListener());
+
+		table.addFocusListener(new AddrTableFocusListener());
+
+		// add form data in case later we add a sash to the right
+		FormData viewerData = new FormData();
+		viewerData.top    = new FormAttachment(0);
+		viewerData.bottom = new FormAttachment(100);
+		viewerData.left   = new FormAttachment(0);
+		viewerData.right  = new FormAttachment(100);
+		table.setLayoutData(viewerData);
+		table.setLayout(new FormLayout());
+
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+		table.setRedraw(true);
+	}
+
+	public void setTableViewer(CheckboxTableViewer tableViewer)
+	{
+		this.tableViewer = tableViewer;
+
+		if (tableViewer == null)
+			this.table = null;
+	}
+
+	public void setTableViewer(int drawMode)
+	{
+		if (this.parent == null)
+			return;
+
+		createTableViewer(drawMode);
+
+		// sort by sample count
+		this.sortColumn = COLUMN_ID_SAMPLE_COUNT;
+		this.sortAscending = false;
+
+		// profiledFunctions and tableItemData contain one entry per table row
+		updateProfiledAndItemData(false);
+		quickSort(sortColumn, profiledFunctions);
+
+		// initially, all rows are selected
+		this.tableViewer.setAllChecked(true);
+	}
+
+	public void refreshTableViewer()
+	{
+		if (this.tableViewer == null)
+			return;
+
+		this.tableViewer.setInput(tableItemData);
+		
+		addColor(this.myGraph.getDrawMode());
+	}
+	
+	public void addColor(int drawMode)
+	{
+		if (this.tableViewer == null)
+			return;
+
+		// make sure that this table's colors are being shown
+		if (   (drawMode != Defines.FUNCTIONS)
+			&& (drawMode != Defines.THREADS_FUNCTIONS)
+			&& (drawMode != Defines.THREADS_BINARIES_FUNCTIONS)
+			&& (drawMode != Defines.BINARIES_FUNCTIONS)
+			&& (drawMode != Defines.BINARIES_THREADS_FUNCTIONS))
+			return;
+
+		ProfiledGeneric pGeneric;
+
+		TableItem[] items = this.table.getItems();
+
+		for (int i = 0; i < items.length; i++) {
+			pGeneric = (ProfiledGeneric) items[i].getData();
+//			Color color = ((GppTrace)this.myGraph.getTrace()).getFunctionColorPalette().getColor(pGeneric.getNameString());
+			items[i].setBackground(COLOR_COLUMN_INDEX, pGeneric.getColor());
+		}
+
+		table.redraw();
+	}
+	
+	public void removeColor(int drawMode)
+	{
+		if (this.tableViewer == null)
+			return;
+
+		// make sure that this table's colors should not be shown
+		if (   (drawMode == Defines.FUNCTIONS)
+			|| (drawMode == Defines.THREADS_FUNCTIONS)
+			|| (drawMode == Defines.THREADS_BINARIES_FUNCTIONS)
+			|| (drawMode == Defines.BINARIES_FUNCTIONS)
+			|| (drawMode == Defines.BINARIES_THREADS_FUNCTIONS))
+			return;
+
+		TableItem[] items = this.table.getItems();
+
+		for (int i = 0; i < items.length; i++) {
+			items[i].setBackground(COLOR_COLUMN_INDEX, this.parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
+		}
+
+		table.redraw();
+	}
+
+	private static class shownFunctionsContentProvider implements IStructuredContentProvider {
+
+		public shownFunctionsContentProvider() {
+			super();
+		}
+
+		public Object[] getElements(Object inputElement) {
+			return ((Vector) inputElement).toArray();
+		}
+
+		public void dispose() {
+		}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		}
+	}
+
+	private class shownFunctionsLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+		public shownFunctionsLabelProvider() {
+			super();
+		}
+
+		public String getColumnText(Object element, int columnIndex) {
+			int columnId = ((Integer) table.getColumn(columnIndex).getData()).intValue();
+
+			if (element instanceof ProfiledThreshold) {
+				ProfiledThreshold pThreshold = (ProfiledThreshold) element;
+				switch (columnId)
+				{
+					case COLUMN_ID_SHOW:
+					{
+						return SHOW_ITEM_VALUE;
+					}
+					case COLUMN_ID_PERCENT_LOAD:
+					{
+						// Percent load string
+						double startTime = PIPageEditor.currentPageEditor().getStartTime();
+						double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+						if (   (startTime == -1)
+							|| (endTime   == -1)
+							|| (startTime == endTime)) {
+							pThreshold.setAverageLoadValueString(myGraph.getGraphIndex(), ""); //$NON-NLS-1$
+						} else {
+							float load = (float) (pThreshold.getSampleCount(myGraph.getGraphIndex())/(endTime - startTime)/10.0);
+							
+							if (load < 0.005)
+								pThreshold.setAverageLoadValueString(myGraph.getGraphIndex(), Messages.getString("AddrFunctionTable.zeroFormat")); //$NON-NLS-1$
+							else
+								pThreshold.setAverageLoadValueString(myGraph.getGraphIndex(), load);
+						}
+						return pThreshold.getAverageLoadValueString(myGraph.getGraphIndex());
+					}
+					case COLUMN_ID_FUNCTION:
+					{
+						DecimalFormat timeFormat = new DecimalFormat(Messages.getString("AddrFunctionTable.decimalFormat")); //$NON-NLS-1$
+						int count = pThreshold.getItemCount(myGraph.getGraphIndex());
+
+						return count + (count > 1 ? Messages.getString("AddrFunctionTable.threshold1") : Messages.getString("AddrFunctionTable.threshold2"))   //$NON-NLS-1$ //$NON-NLS-2$
+								+ timeFormat.format((Double)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdLoadThread") * 100.0) + Messages.getString("AddrFunctionTable.threshold3")  //$NON-NLS-1$ //$NON-NLS-2$
+								+ (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction") + Messages.getString("AddrFunctionTable.threshold4"); //$NON-NLS-1$ //$NON-NLS-2$	
+					}
+					case COLUMN_ID_SAMPLE_COUNT:
+					{
+						// Sample count
+						return String.valueOf(pThreshold.getSampleCount(myGraph.getGraphIndex()));
+					}
+					default:
+					{
+						return ""; //$NON-NLS-1$
+					}
+				}
+			}
+
+			if (!(element instanceof ProfiledFunction))
+				return ""; //$NON-NLS-1$
+
+			ProfiledFunction profiledItem = (ProfiledFunction) element;
+
+			switch (columnId)
+			{
+				case COLUMN_ID_SHOW:
+				{
+					return SHOW_ITEM_VALUE;
+				}
+				case COLUMN_ID_PERCENT_LOAD:
+				{
+					// Percent load string
+					return profiledItem.getAverageLoadValueString(myGraph.getGraphIndex());
+				}
+				case COLUMN_ID_FUNCTION:
+				{
+					// Function
+					return (profiledItem.getNameString());
+				}
+				case COLUMN_ID_START_ADDR:
+				{
+					// Function start
+					return (Long.toHexString(profiledItem.getFunctionAddress()));
+				}
+				case COLUMN_ID_IN_BINARY:
+				{
+					// Binary
+					String binary = profiledItem.getFunctionBinaryName();
+					int index = binary.lastIndexOf('\\');
+					if (index == -1)
+						return binary;
+					else
+						return binary.substring(index + 1);
+				}
+				case COLUMN_ID_IN_BINARY_PATH:
+				{
+					// Path
+					String binary = profiledItem.getFunctionBinaryName();
+					int index = binary.lastIndexOf('\\');
+					if (index == -1)
+						return ""; //$NON-NLS-1$
+					else
+						return binary.substring(0, index);
+				}
+				case COLUMN_ID_SAMPLE_COUNT:
+				{
+					// Sample count
+					return String.valueOf(profiledItem.getSampleCount(myGraph.getGraphIndex()));
+				}
+				default:
+				{
+					break;
+				}
+			}
+			// should never get here
+			return ""; //$NON-NLS-1$
+		}
+
+		public Image getColumnImage(Object element, int columnIndex) {
+			return null;
+		}
+	}
+
+    public void action(String actionString)
+	{
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (   actionString.equals("add") //$NON-NLS-1$
+			|| actionString.equals("remove")) //$NON-NLS-1$
+	    {
+			actionAddRemove(actionString, graphIndex);
+			return;
+	    }
+		else if (   actionString.equals("addall") //$NON-NLS-1$
+				 || actionString.equals("removeall")) //$NON-NLS-1$
+	    {
+			actionAddRemoveAll(actionString, graphIndex);
+			return;
+	    }
+		else if (actionString.equals("recolor")) //$NON-NLS-1$
+		{
+			actionRecolor();
+			return;
+		}
+	    else if (actionString.equals("copy")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, this.table, CHECKBOX_NO_TEXT, false, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("copyTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, this.table, CHECKBOX_NO_TEXT, true, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("copyDrilldown")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSaveDrilldown(true, "\t"); //$NON-NLS-1$
+	        return;
+	    }
+	    else if (actionString.equals("saveTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(false, this.table, CHECKBOX_NO_TEXT, true, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("saveDrilldown")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSaveDrilldown(false, ","); //$NON-NLS-1$
+	        return;
+	    }
+	    else if (actionString.equals("saveSamples")) //$NON-NLS-1$
+	    {
+	    	SaveSampleString saveSampleString = new SaveSampleString(graphIndex, myGraph.getDrawMode());
+	    	actionSaveSamples(saveSampleString); //$NON-NLS-1$
+	        return;
+	    }
+		else if (actionString.equals("selectAll")) //$NON-NLS-1$
+	    {
+	    	actionSelectAll();
+	        return;
+	    }
+		else if (actionString.equals("doubleClick")) //$NON-NLS-1$
+	    {
+	    	copyAction.setEnabled(false);
+			PIPageEditor.getActionBars().updateActionBars();
+	        return;
+	    }
+		else if (actionString.equals("sortinfullpath")) //$NON-NLS-1$
+		{
+            if (this.sortColumn == COLUMN_ID_FULL_IN_PATH)
+            	// sort in other order
+            	sortAscending = !sortAscending;
+            else
+            	// sort in ascending order
+            	sortAscending = true;
+            sortColumn = COLUMN_ID_FULL_IN_PATH;
+            quickSort(sortColumn, profiledFunctions);
+		}
+		else if (actionString.equals("function-only")) //$NON-NLS-1$
+		{
+			actionFunction();
+			return;
+		}
+		else if (actionString.equals("function-thread")) //$NON-NLS-1$
+		{
+			actionFunctionThread();
+			return;
+		}
+		else if (actionString.equals("function-thread-binary")) //$NON-NLS-1$
+		{
+			actionFunctionThreadBinary();
+			return;
+		}
+		else if (actionString.equals("function-binary")) //$NON-NLS-1$
+		{
+			actionFunctionBinary();
+			return;
+		}
+		else if (actionString.equals("function-binary-thread")) //$NON-NLS-1$
+		{
+			actionFunctionBinaryThread();
+			return;
+		}
+		else if (   (actionString.equals("thread-only")) //$NON-NLS-1$
+				 || (actionString.equals("thread-binary")) //$NON-NLS-1$
+				 || (actionString.equals("thread-binary-function")) //$NON-NLS-1$
+				 || (actionString.equals("thread-function")) //$NON-NLS-1$
+				 || (actionString.equals("thread-function-binary"))) //$NON-NLS-1$
+		{
+			// let the thread page action handler handle it
+			this.myGraph.getThreadTable().action(actionString);
+			return;
+		}
+		else if (   (actionString.equals("binary-only")) //$NON-NLS-1$
+				 || (actionString.equals("binary-thread")) //$NON-NLS-1$
+				 || (actionString.equals("binary-thread-function")) //$NON-NLS-1$
+				 || (actionString.equals("binary-function")) //$NON-NLS-1$
+				 || (actionString.equals("binary-function-thread"))) //$NON-NLS-1$
+		{
+			// let the binary page action handler handle it
+			this.myGraph.getBinaryTable().action(actionString);
+			return;
+		}
+		else if (actionString.equals("changeThresholdFunction")) //$NON-NLS-1$
+		{
+			ProfiledThreshold threshold = this.myGraph.getThresholdFunction();
+			boolean enabled = threshold.isEnabled(graphIndex);
+
+			this.tableItemData.clear();
+			this.profiledFunctions.clear();
+			this.myGraph.getSortedFunctions().clear();
+			if (threshold.getItems(graphIndex) != null)
+				threshold.getItems(graphIndex).clear();
+			threshold.initAll();
+
+			// if this appears, it needs to be the first item, so that it is drawn at the bottom
+			myGraph.getSortedFunctions().add(threshold);
+
+			int functionThreshold = (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+			for (int i = 0; i < this.myGraph.getGppTrace().getSortedFunctions().size(); i++) {
+				ProfiledGeneric nextElement = (ProfiledGeneric)this.myGraph.getGppTrace().getSortedFunctions().get(i);
+				if (nextElement.getTotalSampleCount() < functionThreshold) {
+					nextElement.setEnabled(graphIndex, enabled);
+					threshold.addItem(graphIndex, nextElement, 0);
+				} else {
+					tableItemData.add(nextElement);
+					profiledFunctions.add(nextElement);
+					myGraph.getSortedFunctions().add(nextElement);
+				}
+			}
+
+			if (threshold.getItemCount(graphIndex) != 0) {
+				tableItemData.add(threshold);
+				profiledFunctions.add(threshold);
+			} else {
+				// remove the threshold item
+				myGraph.getSortedFunctions().remove(0);
+			}
+			
+			refreshTableViewer();
+			threshold.setEnabled(graphIndex, enabled);
+
+			// make sure that checkboxes shown reflect the actual enabled values
+			TableItem[] tableItems = this.table.getItems();
+			for (int i = 0; i < tableItems.length; i++) {
+				if (tableItems[i].getData() instanceof ProfiledGeneric) {
+					ProfiledGeneric pGeneric = (ProfiledGeneric) tableItems[i].getData();
+					if (tableItems[i].getChecked() != pGeneric.isEnabled(graphIndex))
+						tableItems[i].setChecked(pGeneric.isEnabled(graphIndex));
+				}
+			}
+
+			this.myGraph.genericRefreshCumulativeThreadTable();
+		}
+		else if (actionString.equals("sourceLookup")) //$NON-NLS-1$
+		{
+			actionSourceLookup();
+			return;
+		}
+	    else if (actionString.equals("saveTableTest")) //$NON-NLS-1$
+	    {
+			// copy save file contents to the clipboard for easy viewing
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+			SaveTableString getString = new SaveTableString(this.table, CHECKBOX_NO_TEXT, Messages.getString("AddrFunctionTable.comma"), "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        String copyString = getString.getData();
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+	        return;
+	    }
+	    else if (actionString.equals("saveDrilldownTest")) //$NON-NLS-1$
+	    {
+			// copy save file contents to the clipboard for easy viewing
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+	        Table[] tables = getDrillDownTables();
+	        
+	        int tableCount = 0;
+	        while (tableCount < tables.length && tables[tableCount] != null)
+	        	tableCount++;
+
+	        SaveDrillDownString getString = new SaveDrillDownString(tableCount, tables, Messages.getString("AddrFunctionTable.comma")); //$NON-NLS-1$
+	        String copyString = getString.getData();
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+	        return;
+	    }
+	}
+
+    private void actionAddRemove(String actionString, int graphIndex)
+	{
+		ProfiledGeneric pGeneric;
+		int totalSamples = 0;
+		
+		// true for "add", false for "remove"
+		boolean addIt = actionString.equals("add"); //$NON-NLS-1$
+
+		TableItem[] selectedItems = this.table.getSelection();
+		for (int i = 0; i < selectedItems.length; i++)
+		{
+			selectedItems[i].setChecked(addIt);
+			Object item = ((TableItem)selectedItems[i]).getData();
+			if (item instanceof ProfiledGeneric)
+			{
+				pGeneric = (ProfiledGeneric)item;
+				pGeneric.setEnabled(graphIndex, addIt);
+				totalSamples += pGeneric.getSampleCount(graphIndex);
+   				
+   				if (item instanceof ProfiledThreshold)
+   				{
+   					ProfiledThreshold pThreshold = (ProfiledThreshold)item;
+   					ArrayList<ProfiledGeneric> items = pThreshold.getItems(graphIndex);
+   					for (int j = 0; j < items.size(); j++)
+   						items.get(j).setEnabled(graphIndex, addIt);
+   				}
+			}
+		}
+
+        // this table's set of checkbox-selected rows has changed,
+		// so propagate that information
+		Object[] selectedValues = this.tableViewer.getCheckedElements();
+		String[] nameList = new String[selectedValues.length];
+
+		for (int i = 0; i < selectedValues.length; i++)
+		{
+   			if (selectedValues[i] instanceof ProfiledGeneric)
+   			{
+   				pGeneric = (ProfiledGeneric)selectedValues[i];
+   				nameList[i] = pGeneric.getNameString();
+   			}
+		}
+
+		PIVisualSharedData shared = myGraph.getSharedDataInstance();
+		shared.GPP_SelectedFunctionNames = nameList;
+
+  		if (   (totalSamples != 0)
+      		|| (myGraph.getDrawMode() == Defines.FUNCTIONS))
+      			selectionChangeNotify();
+
+  		this.table.deselectAll();
+	}
+	
+	private void actionAddRemoveAll(String actionString, int graphIndex)
+	{
+		ProfiledGeneric pGeneric;
+
+		// true for "add", false for "remove"
+		boolean addIt = actionString.equals("addall"); //$NON-NLS-1$
+
+		TableItem[] selectedItems = this.table.getItems();
+		String[] nameList = new String[selectedItems.length];
+		for (int i = 0; i < selectedItems.length; i++)
+		{
+			selectedItems[i].setChecked(addIt);
+			Object item = ((TableItem)selectedItems[i]).getData();
+			if (item instanceof ProfiledGeneric)
+			{
+				pGeneric = (ProfiledGeneric)item;
+				pGeneric.setEnabled(graphIndex, addIt);
+   				nameList[i] = pGeneric.getNameString();
+   				
+   				if (item instanceof ProfiledThreshold)
+   				{
+   					ProfiledThreshold pThreshold = (ProfiledThreshold)item;
+   					ArrayList<ProfiledGeneric> items = pThreshold.getItems(graphIndex);
+   					for (int j = 0; j < items.size(); j++)
+   						items.get(j).setEnabled(graphIndex, addIt);
+   				}
+			}
+		}
+
+        // this table's set of checkbox-selected rows has changed,
+		// so propagate that information
+		PIVisualSharedData shared = myGraph.getSharedDataInstance();
+		shared.GPP_SelectedFunctionNames = nameList;
+
+			selectionChangeNotify();
+  		this.table.deselectAll();
+	}
+	
+	private void actionRecolor()
+	{
+		int uid    			= this.myGraph.getUid();
+		GppTrace gppTrace = this.myGraph.getGppTrace();
+
+		// recolor selected items
+		boolean didRecolor = false;
+
+		TableItem[] selectedItems = table.getSelection();
+		TableColorPalette palette = ((GppTrace)this.myGraph.getTrace()).getFunctionColorPalette();
+		for (int i = 0; i < selectedItems.length;i++)
+		{
+			if (selectedItems[i].getData() instanceof ProfiledGeneric)
+			{
+				ProfiledGeneric pGeneric = (ProfiledGeneric)selectedItems[i].getData();
+				String nameKey = pGeneric.getNameString();
+				if (palette.recolorEntryDialog(table.getShell(), nameKey))
+				{
+					Color color = palette.getColor(nameKey);
+					Color oldColor = pGeneric.getColor();
+					
+					if (color.equals(oldColor))
+						continue;
+					
+					didRecolor = true;
+					
+					if (!(pGeneric instanceof ProfiledThreshold)){
+						PIPageEditor.currentPageEditor().setDirty();
+						pGeneric.setColor(color);
+					}
+					else {
+						// for the threshold item, we must change every graph's function threshold item
+						gppTrace.getGppGraph(PIPageEditor.THREADS_PAGE,   uid).getThresholdFunction().setColor(color);
+						gppTrace.getGppGraph(PIPageEditor.BINARIES_PAGE,  uid).getThresholdFunction().setColor(color);
+						gppTrace.getGppGraph(PIPageEditor.FUNCTIONS_PAGE, uid).getThresholdFunction().setColor(color);
+					}
+				}
+
+				// recoloring should only be done in a draw mode that displays this table's colors
+				selectedItems[i].setBackground(COLOR_COLUMN_INDEX, palette.getColor(nameKey));
+			}
+		}
+		
+		if (!didRecolor)
+			return;
+
+		table.redraw();
+		this.myGraph.repaint();
+		this.myGraph.setGraphImageChanged(true);	// any selection change to drill down will change graph
+		
+		// if any other tabs are displaying this type of graph, they need to be scheduled for redrawing
+		for (int i = 0; i < 3; i++) {
+			GppTraceGraph graph = gppTrace.getGppGraph(i, uid);
+
+			if (graph == this.myGraph)
+				continue;
+
+			int drawMode = graph.getDrawMode();
+			
+			if (   (drawMode == Defines.FUNCTIONS)
+				|| (drawMode == Defines.THREADS_FUNCTIONS)
+				|| (drawMode == Defines.THREADS_BINARIES_FUNCTIONS)
+				|| (drawMode == Defines.BINARIES_FUNCTIONS)
+				|| (drawMode == Defines.BINARIES_THREADS_FUNCTIONS)) {
+				graph.getFunctionTable().addColor(drawMode);
+				graph.setGraphImageChanged(true);	// any selection change to drill down will change graph
+				graph.repaint();
+			}
+		}
+	}
+	
+	private void actionFunction()
+	{
+		// current drawMode should be FUNCTIONS, FUNCTIONS_THREADS, FUNCTIONS_THREADS_BINARIES,
+		// FUNCTIONS_BINARIES, or FUNCTIONS_BINARIES_THREADS
+		int drawMode = this.myGraph.getDrawMode();
+
+		if (   (drawMode != Defines.FUNCTIONS_THREADS)
+			&& (drawMode != Defines.FUNCTIONS_THREADS_BINARIES)
+			&& (drawMode != Defines.FUNCTIONS_BINARIES)
+			&& (drawMode != Defines.FUNCTIONS_BINARIES_THREADS))
+		{
+			// this case should be drawMode == Defines.FUNCTIONS
+			return;
+		}
+
+		setIsDrilldown(false);
+
+		// set the page's graph title
+		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+		pV.getTitle().setText(Messages.getString("AddrFunctionTable.functionLoad"));  //$NON-NLS-1$
+		pV.getTitle2().setText(""); //$NON-NLS-1$
+
+		// get rid of any existing tables and sashes
+		if (this.myGraph.getLeftSash() != null) {
+			this.myGraph.getLeftSash().dispose();
+			this.myGraph.setLeftSash(null);
+
+			// detach the table from the sash
+			try {
+				FormData formData = (FormData) this.table.getLayoutData();
+				formData.right = new FormAttachment(100);
+			} catch (ClassCastException e1) {
+			}
+		}
+		if (this.myGraph.getRightSash() != null) {
+			this.myGraph.getRightSash().dispose();
+			this.myGraph.setRightSash(null);
+		}
+		if (   (this.myGraph.getThreadTable() != null)
+			&& (this.myGraph.getThreadTable().getTable() != null)) {
+			this.myGraph.getThreadTable().getTableViewer().getTable().dispose();
+			this.myGraph.getThreadTable().setTableViewer(null);
+		}
+		if (   (this.myGraph.getBinaryTable() != null)
+			&& (this.myGraph.getBinaryTable().getTable() != null)) {
+			this.myGraph.getBinaryTable().getTableViewer().getTable().dispose();
+			this.myGraph.getBinaryTable().setTableViewer(null);
+		}
+
+		// set the draw mode
+		this.myGraph.setDrawMode(Defines.FUNCTIONS);
+
+		// add colors to the rightmost table
+		addColor(Defines.FUNCTIONS);
+		
+		this.parent.layout();
+
+ 		this.myGraph.repaint();
+	}
+
+	private void actionFunctionBinary()
+	{
+		// current drawMode should be FUNCTIONS, FUNCTIONS_BINARIES, or FUNCTIONS_BINARIES_THREADS
+		int drawMode = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+		
+		if (   drawMode != Defines.FUNCTIONS
+			&& drawMode != Defines.FUNCTIONS_BINARIES_THREADS) {
+			return;
+		}
+
+		setIsDrilldown(true);
+
+		if (drawMode == Defines.FUNCTIONS) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrFunctionTable.binaryLoad"));  //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrFunctionTable.functionTo"));  //$NON-NLS-1$
+
+			// set the draw mode
+			this.myGraph.setDrawMode(Defines.FUNCTIONS_BINARIES);
+
+			// create the binary graph table viewer
+			AddrBinaryTable binaryTable = this.myGraph.getBinaryTable();
+			binaryTable.createTableViewer(Defines.FUNCTIONS_BINARIES);
+			binaryTable.setIsDrilldown(true);
+
+			// create a reduced set of binary entries based on enabled function entries
+			GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+			Vector<ProfiledGeneric> binaries = gppTrace.setFunctionBinary(graphIndex);
+			this.myGraph.setProfiledBinaries(binaries);
+
+			// put check marks on all rows, and sort by sample count
+			binaryTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledBinaries());
+			binaryTable.updateProfiledAndItemData(true);
+			binaryTable.getTableViewer().setAllChecked(true);
+			binaryTable.getTableViewer().refresh();
+
+			// remove colors where appropriate
+			removeColor(Defines.FUNCTIONS_BINARIES);
+
+			// connect the tables with a sash
+			Sash leftSash   = new Sash(this.parent, SWT.VERTICAL);
+
+			final FormData leftSashData = new FormData();
+			leftSashData.top    = new FormAttachment(0);
+			leftSashData.bottom = new FormAttachment(100);
+			leftSashData.left   = new FormAttachment(50); // middle
+			leftSash.setLayoutData(leftSashData);
+
+			final Composite sashParent = this.parent;
+			leftSash.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					if (event.detail != SWT.DRAG) {
+						leftSashData.left = new FormAttachment(0, event.x);
+						sashParent.layout();
+					}
+				}
+			});
+
+			myGraph.setLeftSash(leftSash);
+
+			// attach the binary table to the sash
+			final FormData viewerData = new FormData();
+			viewerData.top    = new FormAttachment(0);
+			viewerData.bottom = new FormAttachment(100);
+			viewerData.left   = new FormAttachment(leftSash);
+			viewerData.right  = new FormAttachment(100);
+			binaryTable.getTable().setLayoutData(viewerData);
+
+			// attach the function table to the sash
+			try {
+				FormData formData = (FormData) this.table.getLayoutData();
+				formData.right = new FormAttachment(leftSash);
+			} catch (ClassCastException e1) {
+			}
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+
+		} else if (drawMode == Defines.FUNCTIONS_BINARIES_THREADS) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrFunctionTable.binaryLoad"));  //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrFunctionTable.functionTo"));  //$NON-NLS-1$
+
+			// get rid of the thread table and its sash
+			if (this.myGraph.getRightSash() != null) {
+				this.myGraph.getRightSash().dispose();
+				this.myGraph.setRightSash(null);
+			}
+			if (   (this.myGraph.getThreadTable() != null)
+				&& (this.myGraph.getThreadTable().getTable() != null)) {
+				this.myGraph.getThreadTable().getTableViewer().getTable().dispose();
+				this.myGraph.getThreadTable().setTableViewer(null);
+			}
+
+			// get rid of the middle table's connection to the sash
+			try {
+				FormData formData = (FormData) this.myGraph.getBinaryTable().getTable().getLayoutData();
+				formData.right = new FormAttachment(100);
+			} catch (ClassCastException e1) {
+			}
+
+			// move the left sash to the middle
+			try {
+				FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+				formData.left = new FormAttachment(50); // middle
+			} catch (ClassCastException e1) {
+			}
+
+			// set the draw mode
+			this.myGraph.setDrawMode(Defines.FUNCTIONS_BINARIES);
+
+			// show colors in the rightmost table
+			this.myGraph.getBinaryTable().addColor(Defines.FUNCTIONS_BINARIES);
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+		}
+
+		// this case should be drawMode == Defines.FUNCTIONS_BINARIES
+		return;
+	}
+
+	private void actionFunctionBinaryThread()
+	{
+		// current drawMode should be FUNCTIONS_BINARIES or FUNCTIONS_BINARIES_THREADS
+		int drawMode = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (drawMode != Defines.FUNCTIONS_BINARIES) {
+			// this case should be drawMode == Defines.FUNCTIONS_BINARIES_THREADS
+			return;
+		}
+
+		setIsDrilldown(true);
+
+		// set the page's graph title
+		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+		pV.getTitle().setText(Messages.getString("AddrFunctionTable.threadLoad"));  //$NON-NLS-1$
+		pV.getTitle2().setText(Messages.getString("AddrFunctionTable.functionToBinaryTo"));  //$NON-NLS-1$
+
+		// set the draw mode
+		this.myGraph.setDrawMode(Defines.FUNCTIONS_BINARIES_THREADS);
+
+		// create the thread graph table viewer
+		AddrThreadTable threadTable = this.myGraph.getThreadTable();
+		threadTable.createTableViewer(Defines.FUNCTIONS_BINARIES_THREADS);
+		threadTable.setIsDrilldown(true);
+
+		// create a reduced set of thread entries based on enabled binary and function entries
+		GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+		Vector<ProfiledGeneric> threads = gppTrace.setFunctionBinaryThread(graphIndex);
+		this.myGraph.setProfiledThreads(threads);
+
+		// put check marks on all rows, and sort by sample count
+		threadTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledThreads());
+		threadTable.updateProfiledAndItemData(true);
+		threadTable.getTableViewer().setAllChecked(true);
+		threadTable.getTableViewer().refresh();
+
+		// remove colors where appropriate
+		this.myGraph.getBinaryTable().removeColor(Defines.FUNCTIONS_BINARIES_THREADS);
+
+		// connect the 2nd and 3rd tables with a sash
+		Sash rightSash   = new Sash(this.parent, SWT.VERTICAL);
+
+		final FormData rightSashData = new FormData();
+		rightSashData.top    = new FormAttachment(0);
+		rightSashData.bottom = new FormAttachment(100);
+		rightSashData.left   = new FormAttachment(67); // two thirds
+		rightSash.setLayoutData(rightSashData);
+
+		final Composite sashParent = this.parent;
+		rightSash.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				if (event.detail != SWT.DRAG) {
+					rightSashData.left = new FormAttachment(0, event.x);
+					sashParent.layout();
+				}
+			}
+		});
+
+		myGraph.setRightSash(rightSash);
+
+		// attach the thread table to the sash
+		final FormData viewerData = new FormData();
+		viewerData.top    = new FormAttachment(0);
+		viewerData.bottom = new FormAttachment(100);
+		viewerData.left   = new FormAttachment(rightSash);
+		viewerData.right  = new FormAttachment(100);
+		threadTable.getTable().setLayoutData(viewerData);
+
+		// attach the binary table to the sash
+		try {
+			FormData formData = (FormData) this.myGraph.getBinaryTable().getTable().getLayoutData();
+			formData.right = new FormAttachment(rightSash);
+		} catch (ClassCastException e1) {
+		}
+
+		// move the left sash to 1/3 from the left
+		try {
+			FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+			formData.left = new FormAttachment(33); // one third
+		} catch (ClassCastException e1) {
+		}
+
+		this.parent.layout();
+
+		this.myGraph.repaint();
+	}
+
+	private void actionFunctionThread()
+	{
+		// current drawMode should be FUNCTIONS, FUNCTIONS_THREADS, or FUNCTIONS_THREADS_BINARIES
+		int drawMode = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (   drawMode != Defines.FUNCTIONS
+			&& drawMode != Defines.FUNCTIONS_THREADS_BINARIES) {
+			return;
+		}
+
+		setIsDrilldown(true);
+
+		if (drawMode == Defines.FUNCTIONS) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrFunctionTable.threadLoad"));  //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrFunctionTable.functionTo"));  //$NON-NLS-1$
+
+			// set the draw mode
+			this.myGraph.setDrawMode(Defines.FUNCTIONS_THREADS);
+
+			// create the thread graph table viewer
+			AddrThreadTable threadTable = this.myGraph.getThreadTable();
+			threadTable.createTableViewer(Defines.FUNCTIONS_THREADS);
+			threadTable.setIsDrilldown(true);
+
+			// create a reduced set of thread entries based on enabled function entries
+			GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+			Vector<ProfiledGeneric> threads = gppTrace.setFunctionThread(graphIndex);
+			this.myGraph.setProfiledThreads(threads);
+
+			// put check marks on all rows, and sort by sample count
+			threadTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledThreads());
+			threadTable.updateProfiledAndItemData(true);
+			threadTable.getTableViewer().setAllChecked(true);
+			threadTable.getTableViewer().refresh();
+
+			// remove colors where appropriate
+			removeColor(Defines.FUNCTIONS_THREADS);
+
+			// connect the tables with a sash
+			Sash leftSash   = new Sash(this.parent, SWT.VERTICAL);
+
+			final FormData leftSashData = new FormData();
+			leftSashData.top    = new FormAttachment(0);
+			leftSashData.bottom = new FormAttachment(100);
+			leftSashData.left   = new FormAttachment(50); // middle
+			leftSash.setLayoutData(leftSashData);
+
+			final Composite sashParent = this.parent;
+			leftSash.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					if (event.detail != SWT.DRAG) {
+						leftSashData.left = new FormAttachment(0, event.x);
+						sashParent.layout();
+					}
+				}
+			});
+
+			myGraph.setLeftSash(leftSash);
+
+			// attach the thread table to the sash
+			final FormData viewerData = new FormData();
+			viewerData.top    = new FormAttachment(0);
+			viewerData.bottom = new FormAttachment(100);
+			viewerData.left   = new FormAttachment(leftSash);
+			viewerData.right  = new FormAttachment(100);
+			threadTable.getTable().setLayoutData(viewerData);
+
+			// attach the function table to the sash
+			try {
+				FormData formData = (FormData) this.table.getLayoutData();
+				formData.right = new FormAttachment(leftSash);
+			} catch (ClassCastException e1) {
+			}
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+
+		} else if (drawMode == Defines.FUNCTIONS_THREADS_BINARIES) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrFunctionTable.threadLoad"));  //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrFunctionTable.functionTo"));  //$NON-NLS-1$
+
+			// get rid of the binary table and its sash
+			if (this.myGraph.getRightSash() != null) {
+				this.myGraph.getRightSash().dispose();
+				this.myGraph.setRightSash(null);
+			}
+			if (   (this.myGraph.getBinaryTable() != null)
+				&& (this.myGraph.getBinaryTable().getTable() != null)) {
+				this.myGraph.getBinaryTable().getTableViewer().getTable().dispose();
+				this.myGraph.getBinaryTable().setTableViewer(null);
+			}
+
+			// get rid of the middle table's connection to the sash
+			try {
+				FormData formData = (FormData) this.myGraph.getThreadTable().getTable().getLayoutData();
+				formData.right = new FormAttachment(100);
+			} catch (ClassCastException e1) {
+			}
+
+			// move the left sash to the middle
+			try {
+				FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+				formData.left = new FormAttachment(50); // middle
+			} catch (ClassCastException e1) {
+			}
+
+			// set the draw mode
+			this.myGraph.setDrawMode(Defines.FUNCTIONS_THREADS);
+
+			// show colors in the rightmost table
+			this.myGraph.getThreadTable().addColor(Defines.FUNCTIONS_THREADS);
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+		}
+
+		// this case should be drawMode == Defines.FUNCTIONS_THREADS
+		return;
+	}
+
+	private void actionFunctionThreadBinary()
+	{
+		// current drawMode is FUNCTIONS_THREADS, or FUNCTIONS_THREADS_BINARIES
+		int drawMode = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (drawMode != Defines.FUNCTIONS_THREADS) {
+			// this case should be drawMode == Defines.FUNCTIONS_THREADS_BINARIES
+			return;
+		}
+
+		setIsDrilldown(true);
+
+		// set the page's graph title
+		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+		pV.getTitle().setText(Messages.getString("AddrFunctionTable.binaryLoad"));  //$NON-NLS-1$
+		pV.getTitle2().setText(Messages.getString("AddrFunctionTable.functionToThreadTo"));  //$NON-NLS-1$
+
+		// set the draw mode
+		this.myGraph.setDrawMode(Defines.FUNCTIONS_THREADS_BINARIES);
+
+		// create the binary graph table viewer
+		AddrBinaryTable binaryTable = this.myGraph.getBinaryTable();
+		binaryTable.createTableViewer(Defines.FUNCTIONS_THREADS_BINARIES);
+		binaryTable.setIsDrilldown(true);
+
+		// create a reduced set of binary entries based on enabled thread entries
+		GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+		Vector<ProfiledGeneric> binaries = gppTrace.setFunctionThreadBinary(graphIndex);
+		this.myGraph.setProfiledBinaries(binaries);
+
+		// put check marks on all rows, and sort by sample count
+		binaryTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledBinaries());
+		binaryTable.updateProfiledAndItemData(true);
+		binaryTable.getTableViewer().setAllChecked(true);
+		binaryTable.getTableViewer().refresh();
+
+		// remove colors where appropriate
+		this.myGraph.getThreadTable().removeColor(Defines.FUNCTIONS_THREADS_BINARIES);
+
+		// connect the 2nd and 3rd tables with a sash
+		Sash rightSash   = new Sash(this.parent, SWT.VERTICAL);
+
+		final FormData rightSashData = new FormData();
+		rightSashData.top    = new FormAttachment(0);
+		rightSashData.bottom = new FormAttachment(100);
+		rightSashData.left   = new FormAttachment(67); // two thirds
+		rightSash.setLayoutData(rightSashData);
+
+		final Composite sashParent = this.parent;
+		rightSash.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				if (event.detail != SWT.DRAG) {
+					rightSashData.left = new FormAttachment(0, event.x);
+					sashParent.layout();
+				}
+			}
+		});
+
+		myGraph.setRightSash(rightSash);
+
+		// attach the binary table to the sash
+		final FormData viewerData = new FormData();
+		viewerData.top    = new FormAttachment(0);
+		viewerData.bottom = new FormAttachment(100);
+		viewerData.left   = new FormAttachment(rightSash);
+		viewerData.right  = new FormAttachment(100);
+		binaryTable.getTable().setLayoutData(viewerData);
+
+		// attach the thread table to the sash
+		try {
+			FormData formData = (FormData) this.myGraph.getThreadTable().getTable().getLayoutData();
+			formData.right = new FormAttachment(rightSash);
+		} catch (ClassCastException e1) {
+		}
+
+		// move the left sash to 1/3 from the left
+		try {
+			FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+			formData.left = new FormAttachment(33); // one third
+		} catch (ClassCastException e1) {
+		}
+
+		this.parent.layout();
+
+		this.myGraph.repaint();
+	}
+	
+	private void actionSourceLookup() {
+		// source look up for selected items
+		TableItem selectedItem = table.getSelection()[0];
+		if (selectedItem.getData() instanceof ProfiledGeneric)
+		{
+			ProfiledGeneric pGeneric = (ProfiledGeneric)selectedItem.getData();
+			
+			if (pGeneric instanceof ProfiledFunction) {
+				ProfiledFunction pFunc = (ProfiledFunction) pGeneric;
+				SourceLookup.getInstance().lookupAndopenEditorWithHighlight (pFunc.getNameString(), pFunc.getFunctionBinaryName());
+			}
+		}
+	}
+
+	public void focusGained(FocusEvent e) {}
+
+	public void focusLost(FocusEvent e) {}
+
+	public void piEventReceived(PIEvent be)
+	{
+		if (be.getType() == PIEvent.SELECTION_AREA_CHANGED3)
+		{
+			// % loads, % load strings, and/or sample counts have been updated
+			// due to a change in the graph area selected, and all table items
+			// need to be checked
+			updateProfiledAndItemData(true);
+
+			Display.getDefault().syncExec(new Runnable() {
+				public void run() {
+					quickSort(sortColumn, profiledFunctions);
+
+					// initially, all rows are selected
+					tableViewer.setAllChecked(true);
+
+					table.redraw();
+				}
+			});
+		}
+		else if (   (be.getType() == PIEvent.SELECTION_AREA_CHANGED2)
+				 || (be.getType() == PIEvent.CHANGED_FUNCTION_TABLE))
+		{
+			int graphIndex = this.myGraph.getGraphIndex();
+
+			// This routine does not change which functions are enabled, but it enables
+			// all entries in the 2nd and 3rd tables.
+			// It assumes that GppTrace.setSelectedArea(), action("add") or action("remove") has set
+			// the % load and sample counts for functions, except for the threshold list.
+			if (be.getType() == PIEvent.SELECTION_AREA_CHANGED2) {
+				int thresholdCount = (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+				if (thresholdCount > 0) {
+					Vector<ProfiledGeneric> pGeneric = this.myGraph.getProfiledFunctions();
+					int sampleCount = 0;
+					for (int i = 0; i < pGeneric.size(); i++)
+						if (pGeneric.elementAt(i).getTotalSampleCount() < thresholdCount)
+							sampleCount += pGeneric.elementAt(i).getSampleCount(graphIndex);
+					this.myGraph.getThresholdFunction().setSampleCount(graphIndex, sampleCount);
+				}
+			}
+
+			// redraw this table
+			Display.getDefault().syncExec(new Runnable() {
+				public void run() {
+					if (   (sortColumn == COLUMN_ID_PERCENT_LOAD)
+						|| (sortColumn == COLUMN_ID_SAMPLE_COUNT))
+					{
+						quickSort(sortColumn, profiledFunctions);
+					}
+					else
+						refreshTableViewer();
+
+					table.redraw();
+				}
+			});
+
+			int drawMode = this.myGraph.getDrawMode();
+			if (drawMode == Defines.FUNCTIONS)
+				return;
+
+			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
+			Vector<ProfiledGeneric> traceFunctions = trace.getIndexedFunctions();
+
+			int startSampleIndex = trace.getStartSampleIndex();
+			int endSampleIndex   = trace.getEndSampleIndex();
+			double percentPerSample;
+			if (startSampleIndex == endSampleIndex)
+				percentPerSample = 0.0;
+			else
+				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
+
+			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
+
+			switch (drawMode) {
+				case Defines.FUNCTIONS_THREADS:
+				{
+					// get new thread counts and loads
+					Vector<ProfiledGeneric> traceThreads  = trace.getIndexedThreads();
+					Vector<ProfiledGeneric> graphThreads  = this.myGraph.getProfiledThreads();
+					Hashtable<String,String> foundThreads = new Hashtable<String,String>();
+
+					// previous threads are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enu = graphThreads.elements();
+					while (enu.hasMoreElements()) {
+						ProfiledThread pThread = (ProfiledThread) enu.nextElement();
+						pThread.setEnabled(graphIndex, false);
+					}
+					graphThreads.clear();
+
+					ProfiledThreshold thresholdThread = this.myGraph.getThresholdThread();
+					if (thresholdThread.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdThread.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find threads below the threshold
+					boolean lowThread;
+					thresholdThread.init(graphIndex);
+
+					int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+						if (pFunction.isEnabled(graphIndex)) {
+							// thread list is based on functions
+							ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+							String threadName = pThread.getNameString();
+
+							lowThread = pThread.getTotalSampleCount() < threadThreshold;
+
+							if (!foundThreads.containsKey(threadName)) {
+								foundThreads.put(threadName, threadName);
+								if (lowThread) {
+									thresholdThread.addItem(graphIndex, pThread, 1);
+								} else {
+									pThread.setEnabled(graphIndex, true);
+									pThread.setSampleCount(graphIndex, 1);
+									graphThreads.add(pThread);
+								}
+							} else {
+								if (lowThread)
+									thresholdThread.incSampleCount(graphIndex);
+								else
+									pThread.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphThreads.size(); i++) {
+						ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
+						pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdThread.setLoadAndString(graphIndex,
+							(float)(thresholdThread.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getThreadTable().piEventReceived(be3);
+					break;
+				}
+				case Defines.FUNCTIONS_THREADS_BINARIES:
+				{
+					// get new thread and binary counts and loads
+					Vector<ProfiledGeneric> traceThreads   = trace.getIndexedThreads();
+					Vector<ProfiledGeneric> traceBinaries  = trace.getIndexedBinaries();
+					Vector<ProfiledGeneric> graphThreads   = this.myGraph.getProfiledThreads();
+					Vector<ProfiledGeneric> graphBinaries  = this.myGraph.getProfiledBinaries();
+					Hashtable<String,String> foundThreads  = new Hashtable<String,String>();
+					Hashtable<String,String> foundBinaries = new Hashtable<String,String>();
+
+					// previous binaries are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuBinary = graphBinaries.elements();
+					while (enuBinary.hasMoreElements()) {
+						ProfiledBinary pBinary = (ProfiledBinary) enuBinary.nextElement();
+						pBinary.setEnabled(graphIndex, false);
+					}
+					graphBinaries.clear();
+
+					ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
+
+					if (thresholdBinary.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					// previous threads are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuThread = graphThreads.elements();
+					while (enuThread.hasMoreElements()) {
+						ProfiledThread pThread = (ProfiledThread) enuThread.nextElement();
+						pThread.setEnabled(graphIndex, false);
+					}
+					graphThreads.clear();
+
+					ProfiledThreshold thresholdThread = this.myGraph.getThresholdThread();
+
+					if (thresholdThread.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdThread.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find binaries below the threshold
+					boolean lowBinary;
+					thresholdBinary.init(graphIndex);
+
+					// set up in case we find threads below the threshold
+					boolean lowThread;
+					thresholdThread.init(graphIndex);
+
+					int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+						if (pFunction.isEnabled(graphIndex)) {
+							// thread list is based on functions
+							ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+							String threadName = pThread.getNameString();
+
+							lowThread = pThread.getTotalSampleCount() < threadThreshold;
+
+							if (!foundThreads.containsKey(threadName)) {
+								foundThreads.put(threadName, threadName);
+								if (lowThread) {
+									thresholdThread.addItem(graphIndex, pThread, 1);
+								} else {
+									pThread.setEnabled(graphIndex, true);
+									pThread.setSampleCount(graphIndex, 1);
+									graphThreads.add(pThread);
+								}
+							} else {
+								if (lowThread)
+									thresholdThread.incSampleCount(graphIndex);
+								else
+									pThread.incSampleCount(graphIndex);
+							}
+
+							// binary list is based on functions and threads
+							ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+							String binaryName = pBinary.getNameString();
+
+							lowBinary = pBinary.getTotalSampleCount() < (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+
+							if (!foundBinaries.containsKey(binaryName)) {
+								foundBinaries.put(binaryName, binaryName);
+								if (lowBinary) {
+									thresholdBinary.addItem(graphIndex, pBinary, 1);
+								} else {
+									pBinary.setEnabled(graphIndex, true);
+									pBinary.setSampleCount(graphIndex, 1);
+									graphBinaries.add(pBinary);
+								}
+							} else {
+								if (lowBinary)
+									thresholdBinary.incSampleCount(graphIndex);
+								else
+									pBinary.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphThreads.size(); i++) {
+						ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
+						pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdThread.setLoadAndString(graphIndex,
+							(float)(thresholdThread.getSampleCount(graphIndex)*percentPerSample));
+
+					for (int i = 0; i < graphBinaries.size(); i++) {
+						ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
+						pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdBinary.setLoadAndString(graphIndex,
+							(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getThreadTable().piEventReceived(be3);
+					this.myGraph.getBinaryTable().piEventReceived(be3);
+					break;
+				}
+				case Defines.FUNCTIONS_BINARIES:
+				{
+					// get new counts and loads
+					Vector<ProfiledGeneric> traceBinaries  = trace.getIndexedBinaries();
+					Vector<ProfiledGeneric> graphBinaries  = this.myGraph.getProfiledBinaries();
+					Hashtable<String,String> foundBinaries = new Hashtable<String,String>();
+
+					// previous binaries are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enu = graphBinaries.elements();
+					while (enu.hasMoreElements()) {
+						ProfiledBinary pBinary = (ProfiledBinary) enu.nextElement();
+						pBinary.setEnabled(graphIndex, false);
+					}
+					graphBinaries.clear();
+
+					ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
+
+					if (thresholdBinary.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find binaries below the threshold
+					boolean lowBinary;
+					thresholdBinary.init(graphIndex);
+
+					int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+						if (pFunction.isEnabled(graphIndex)) {
+							// binary list is based on functions
+							ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+							String binaryName = pBinary.getNameString();
+
+							lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
+
+							if (!foundBinaries.containsKey(binaryName)) {
+								foundBinaries.put(binaryName, binaryName);
+								if (lowBinary) {
+									thresholdBinary.addItem(graphIndex, pBinary, 1);
+								} else {
+									pBinary.setEnabled(graphIndex, true);
+									pBinary.setSampleCount(graphIndex, 1);
+									graphBinaries.add(pBinary);
+								}
+							} else {
+								if (lowBinary)
+									thresholdBinary.incSampleCount(graphIndex);
+								else
+									pBinary.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphBinaries.size(); i++) {
+						ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
+						pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdBinary.setLoadAndString(graphIndex,
+							(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getBinaryTable().piEventReceived(be3);
+					break;
+				}
+				case Defines.FUNCTIONS_BINARIES_THREADS:
+				{
+					// get new binary and thread counts and loads
+					Vector<ProfiledGeneric> traceThreads    = trace.getIndexedThreads();
+					Vector<ProfiledGeneric> traceBinaries   = trace.getIndexedBinaries();
+					Vector<ProfiledGeneric> graphThreads    = this.myGraph.getProfiledThreads();
+					Vector<ProfiledGeneric> graphBinaries   = this.myGraph.getProfiledBinaries();
+					Hashtable<String,String> foundThreads   = new Hashtable<String,String>();
+					Hashtable<String,String> foundBinaries  = new Hashtable<String,String>();
+
+					// previous threads are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuThreads = graphThreads.elements();
+					while (enuThreads.hasMoreElements()) {
+						ProfiledThread pThread = (ProfiledThread) enuThreads.nextElement();
+						pThread.setEnabled(graphIndex, false);
+					}
+					graphThreads.clear();
+
+					ProfiledThreshold thresholdThread = this.myGraph.getThresholdThread();
+
+					if (thresholdThread.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdThread.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					// previous binaries are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuBinary = graphBinaries.elements();
+					while (enuBinary.hasMoreElements()) {
+						ProfiledBinary pBinary = (ProfiledBinary) enuBinary.nextElement();
+						pBinary.setEnabled(graphIndex, false);
+					}
+					graphBinaries.clear();
+
+					ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
+
+					if (thresholdBinary.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find threads below the threshold
+					boolean lowThread;
+					thresholdThread.init(graphIndex);
+
+					// set up in case we find binaries below the threshold
+					boolean lowBinary;
+					thresholdBinary.init(graphIndex);
+
+					int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+						if (pFunction.isEnabled(graphIndex)) {
+							// binary list is based on
+							ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+							String binaryName = pBinary.getNameString();
+
+							lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
+
+							if (!foundBinaries.containsKey(binaryName)) {
+								foundBinaries.put(binaryName, binaryName);
+								if (lowBinary) {
+									thresholdBinary.addItem(graphIndex, pBinary, 1);
+								} else {
+									pBinary.setEnabled(graphIndex, true);
+									pBinary.setSampleCount(graphIndex, 1);
+									graphBinaries.add(pBinary);
+								}
+							} else {
+								if (lowBinary)
+									thresholdBinary.incSampleCount(graphIndex);
+								else
+									pBinary.incSampleCount(graphIndex);
+							}
+
+							// thread list is based on functions and binaries
+							ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+							String threadName = pThread.getNameString();
+
+							lowThread = pThread.getTotalSampleCount() < (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+
+							if (!foundThreads.containsKey(threadName)) {
+								foundThreads.put(threadName, threadName);
+								if (lowThread) {
+									thresholdThread.addItem(graphIndex, pThread, 1);
+								} else {
+									pThread.setEnabled(graphIndex, true);
+									pThread.setSampleCount(graphIndex, 1);
+									graphThreads.add(pThread);
+								}
+							} else {
+								if (lowThread)
+									thresholdThread.incSampleCount(graphIndex);
+								else
+									pThread.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphThreads.size(); i++) {
+						ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
+						pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdThread.setLoadAndString(graphIndex,
+							(float)(thresholdThread.getSampleCount(graphIndex)*percentPerSample));
+
+					for (int i = 0; i < graphBinaries.size(); i++) {
+						ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
+						pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdBinary.setLoadAndString(graphIndex,
+							(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getThreadTable().piEventReceived(be3);
+					this.myGraph.getBinaryTable().piEventReceived(be3);
+					break;
+				}
+				default:
+				{
+					break;
+				}
+			}
+		}
+		else if (be.getType() == PIEvent.CHANGED_THREAD_TABLE)
+		{
+			// This routine enables all entries in the next table
+
+			int drawMode = this.myGraph.getDrawMode();
+			if (drawMode != Defines.FUNCTIONS_THREADS_BINARIES)
+				return;
+
+			// we don't need to redraw the function table, since it has not changed
+
+			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
+			Vector<ProfiledGeneric> traceThreads = trace.getIndexedThreads();
+
+			int graphIndex = this.myGraph.getGraphIndex();
+			int startSampleIndex = trace.getStartSampleIndex();
+			int endSampleIndex   = trace.getEndSampleIndex();
+			double percentPerSample;
+			if (startSampleIndex == endSampleIndex)
+				percentPerSample = 0.0;
+			else
+				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
+
+			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
+
+			// get new binary counts and loads
+			Vector<ProfiledGeneric> traceBinaries  = trace.getIndexedBinaries();
+			Vector<ProfiledGeneric> graphBinaries  = this.myGraph.getProfiledBinaries();
+			Hashtable<String,String> foundBinaries = new Hashtable<String,String>();
+
+			// previous binaries are not necessarily graphed this time
+			Enumeration<ProfiledGeneric> enu = graphBinaries.elements();
+			while (enu.hasMoreElements()) {
+				ProfiledBinary pBinary = (ProfiledBinary) enu.nextElement();
+				pBinary.setEnabled(graphIndex, false);
+			}
+			graphBinaries.clear();
+
+			ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
+
+			if (thresholdBinary.isEnabled(graphIndex)) {
+				ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
+				// disable all items below the threshold
+				for (int i = 0; i < items.size(); i++) {
+					items.get(i).setEnabled(graphIndex, false);
+				}
+			}
+
+			GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+			// set up in case we find binaries below the threshold
+			boolean lowBinary;
+			thresholdBinary.init(graphIndex);
+			
+			int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+			for (int i = startSampleIndex; i < endSampleIndex; i++) {
+				GppSample sample = sortedSamples[i];
+
+				ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+				if (pThread.isEnabled(graphIndex)) {
+					// binary list is based on threads
+					ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+					String binaryName = pBinary.getNameString();
+
+					lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
+
+					if (!foundBinaries.containsKey(binaryName)) {
+						foundBinaries.put(binaryName, binaryName);
+						if (lowBinary) {
+							thresholdBinary.addItem(graphIndex, pBinary, 1);
+						} else {
+							pBinary.setEnabled(graphIndex, true);
+							pBinary.setSampleCount(graphIndex, 1);
+							graphBinaries.add(pBinary);
+						}
+					} else {
+						if (lowBinary)
+							thresholdBinary.incSampleCount(graphIndex);
+						else
+							pBinary.incSampleCount(graphIndex);
+					}
+				}
+			}
+
+			// set the % load
+			for (int i = 0; i < graphBinaries.size(); i++) {
+				ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
+				pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
+			}
+			thresholdBinary.setLoadAndString(graphIndex,
+					(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
+
+			// update the table items and redraw the table
+			this.myGraph.getBinaryTable().piEventReceived(be3);
+		}
+		else if (be.getType() == PIEvent.CHANGED_BINARY_TABLE)
+		{
+			// This routine enables all entries in the next table
+
+			int drawMode = this.myGraph.getDrawMode();
+			if (drawMode != Defines.FUNCTIONS_BINARIES_THREADS)
+				return;
+
+			// we don't need to redraw the function table, since it has not changed
+
+			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
+			Vector<ProfiledGeneric> traceBinaries  = trace.getIndexedBinaries();
+
+			int graphIndex = this.myGraph.getGraphIndex();
+			int startSampleIndex = trace.getStartSampleIndex();
+			int endSampleIndex   = trace.getEndSampleIndex();
+			double percentPerSample;
+			if (startSampleIndex == endSampleIndex)
+				percentPerSample = 0.0;
+			else
+				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
+
+			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
+
+			// get new thread counts and loads
+			Vector<ProfiledGeneric> traceThreads  = trace.getIndexedThreads();
+			Vector<ProfiledGeneric> graphThreads  = this.myGraph.getProfiledThreads();
+			Hashtable<String,String> foundThreads = new Hashtable<String,String>();
+
+			// previous threads are not necessarily graphed this time
+			Enumeration<ProfiledGeneric> enu = graphThreads.elements();
+			while (enu.hasMoreElements()) {
+				ProfiledThread pThread = (ProfiledThread) enu.nextElement();
+				pThread.setEnabled(graphIndex, false);
+			}
+			graphThreads.clear();
+
+			ProfiledThreshold thresholdThread = this.myGraph.getThresholdThread();
+
+			if (thresholdThread.isEnabled(graphIndex)) {
+				ArrayList<ProfiledGeneric> items = thresholdThread.getItems(graphIndex);
+				// disable all items below the threshold
+				for (int i = 0; i < items.size(); i++) {
+					items.get(i).setEnabled(graphIndex, false);
+				}
+			}
+
+			GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+			// set up in case we find threads below the threshold
+			boolean lowThread;
+			thresholdThread.init(graphIndex);
+
+			int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+			for (int i = startSampleIndex; i < endSampleIndex; i++) {
+				GppSample sample = sortedSamples[i];
+
+				ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+				if (pBinary.isEnabled(graphIndex)) {
+					// thread list is based on binaries
+					ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+					String threadName = pThread.getNameString();
+
+					lowThread = pThread.getTotalSampleCount() < threadThreshold;
+
+					if (!foundThreads.containsKey(threadName)) {
+						foundThreads.put(threadName, threadName);
+						if (lowThread) {
+							thresholdThread.addItem(graphIndex, pThread, 1);
+						} else {
+							pThread.setEnabled(graphIndex, true);
+							pThread.setSampleCount(graphIndex, 1);
+							graphThreads.add(pThread);
+						}
+					} else {
+						if (lowThread)
+							thresholdThread.incSampleCount(graphIndex);
+						else
+							pThread.incSampleCount(graphIndex);
+					}
+				}
+			}
+
+			// set the % load
+			for (int i = 0; i < graphThreads.size(); i++) {
+				ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
+				pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex)*percentPerSample));
+			}
+			thresholdThread.setLoadAndString(graphIndex,
+					(float)(thresholdThread.getSampleCount(graphIndex)*percentPerSample));
+
+			// update the table items and redraw the table
+			this.myGraph.getThreadTable().piEventReceived(be3);
+		}
+	}
+
+	public void setSelectedNames()
+	{
+		Object[] selectedValues = this.tableViewer.getCheckedElements();
+        String[] functionNames = new String[selectedValues.length];
+
+        for (int i = 0; i < selectedValues.length; i++)
+		{
+			if (selectedValues[i] instanceof ProfiledFunction)
+			{
+				ProfiledFunction pf = (ProfiledFunction)selectedValues[i];
+				functionNames[i] = pf.getNameString();
+			}
+		}
+
+        PIVisualSharedData shared = myGraph.getSharedDataInstance();
+		shared.GPP_SelectedFunctionNames = functionNames;
+	}
+
+	private class SharedCheckHandler implements ICheckStateListener
+	{
+		public void checkStateChanged(CheckStateChangedEvent event) {
+
+       		if (!(event.getElement() instanceof ProfiledGeneric))
+       			return;
+       		
+       		// set the stored value to the checkbox value
+       		ProfiledGeneric pg = (ProfiledGeneric)event.getElement();
+	        pg.setEnabled(myGraph.getGraphIndex(), event.getChecked());
+ 
+	        // this table's set of checkbox-selected rows has changed, so propagate that information
+       		setSelectedNames();
+
+       		if (   (pg.getSampleCount(myGraph.getGraphIndex()) != 0)
+       			|| (myGraph.getDrawMode() == Defines.FUNCTIONS))
+       			selectionChangeNotify();
+
+       		table.deselectAll();
+		}
+	}
+
+	protected void selectionChangeNotify() {
+		PIEvent be = new PIEvent(null, PIEvent.CHANGED_FUNCTION_TABLE);
+		myGraph.piEventReceived(be);
+    }
+
+	public void sortOnColumnSelection(TableColumn tableColumn) {
+		int columnId = ((Integer) tableColumn.getData()).intValue();
+        if (sortColumn == columnId) {
+        	// sort in other order
+        	sortAscending = !sortAscending;
+        } else {
+        	// sort in the default order
+			switch (columnId)
+			{
+				case COLUMN_ID_SHOW:
+				case COLUMN_ID_PERCENT_LOAD:
+				case COLUMN_ID_SAMPLE_COUNT:
+				{
+	            	// sort in descending order (for checked boxes, this means selected boxes first)
+	            	sortAscending = false;
+	                break;
+				}
+				case COLUMN_ID_FUNCTION:
+				case COLUMN_ID_START_ADDR:
+				case COLUMN_ID_IN_BINARY:
+				case COLUMN_ID_IN_BINARY_PATH:
+				{
+	            	// sort in ascending order
+	            	sortAscending = true;
+	                break;
+				}
+				default:
+				{
+					return;
+				}
+            }
+        }
+		
+		sortColumn = columnId;
+		quickSort(sortColumn, profiledFunctions);
+	}
+
+	private class ColumnSelectionHandler extends SelectionAdapter
+	{
+		public void widgetSelected(SelectionEvent e)
+        {
+        	// wait for the previous sort to finish
+        	if (sorting || !(e.widget instanceof TableColumn))
+        		return;
+
+        	sortOnColumnSelection((TableColumn) e.widget);
+        }
+	}
+
+	public void updateProfiledAndItemData(boolean setInput)
+	{
+		tableItemData.clear();
+		profiledFunctions.clear();
+
+		// profiledFunctions and tableItemData contain one entry per table row
+		Enumeration<ProfiledGeneric> enu = myGraph.getProfiledFunctions().elements();
+		while (enu.hasMoreElements())
+		{
+			ProfiledFunction nextElement = (ProfiledFunction)enu.nextElement();
+			tableItemData.add(nextElement);
+			profiledFunctions.add(nextElement);
+		}
+
+		if (myGraph.getThresholdFunction().getItemCount(myGraph.getGraphIndex()) != 0) {
+			tableItemData.add(myGraph.getThresholdFunction());
+			profiledFunctions.add(myGraph.getThresholdFunction());
+		}
+
+		// now sort the items in increasing total sample count, so that they graph correctly
+		Object[] sorted = myGraph.getProfiledFunctions().toArray();
+		Arrays.sort(sorted, new Comparator<Object>() {
+			
+			public int compare(Object arg0, Object arg1)
+			{
+				if (arg0 instanceof ProfiledGeneric && arg1 instanceof ProfiledGeneric)
+					return ((ProfiledGeneric)arg0).getTotalSampleCount() -
+							((ProfiledGeneric)arg1).getTotalSampleCount();
+				else
+					return 0;
+			}
+		});
+
+		// now create the sorted list used to draw the graph
+		myGraph.getSortedFunctions().clear();
+
+		if (myGraph.getThresholdFunction().getItemCount(myGraph.getGraphIndex()) != 0)
+			myGraph.getSortedFunctions().add(myGraph.getThresholdFunction());
+
+		for (int i = 0; i < sorted.length; i++)
+			myGraph.getSortedFunctions().add((ProfiledGeneric) sorted[i]);
+
+		// refresh the table, if needed
+		if (setInput)
+			refreshTableViewer();
+	}
+	
+	public void quickSort(int sortBy, Vector<ProfiledGeneric> profiled)
+	{
+		if (profiled.size() == 0)
+			return;
+
+		this.sorting = true;
+
+		ProfiledGeneric pGeneric = profiled.elementAt(profiled.size() - 1);
+
+		if (pGeneric instanceof ProfiledThreshold) {
+			profiled.removeElementAt(profiled.size() - 1);
+		}
+
+		this.sorter.setupSort(sortBy, this.myGraph.getGraphIndex(), sortAscending);
+
+		switch (sortBy) {
+			case COLUMN_ID_SHOW:
+			{
+			    this.sorter.quickSortByShow(profiled);
+		        break;
+			}
+			case COLUMN_ID_PERCENT_LOAD:
+			{
+			    this.sorter.quickSortByAverageLoad(profiled);
+		        break;
+			}
+			case COLUMN_ID_THREAD:
+			{
+			    this.sorter.quickSortByThread(profiled);
+	            break;
+			}
+			case COLUMN_ID_BINARY:
+			{
+			    this.sorter.quickSortByBinary(profiled);
+	            break;
+			}
+			case COLUMN_ID_FUNCTION:
+			{
+			    this.sorter.quickSortByFunction(profiled);
+	            break;
+			}
+			case COLUMN_ID_SAMPLE_COUNT:
+			{
+			    this.sorter.quickSortBySampleCount(profiled);
+	            break;
+			}
+			case COLUMN_ID_START_ADDR:
+			{
+			    this.sorter.quickSortByStartAddress(profiled);
+	            break;
+			}
+			case COLUMN_ID_IN_BINARY:
+			{
+			    this.sorter.quickSortByAssocBinary(profiled);
+	            break;
+			}
+			case COLUMN_ID_IN_BINARY_PATH:
+			{
+			    this.sorter.quickSortByAssocBinaryPath(profiled);
+	            break;
+			}
+			case COLUMN_ID_FULL_IN_PATH:
+			{
+			    this.sorter.quickSortByFullAssocBinaryPath(profiled);
+	            break;
+			}
+			default:
+			{
+				break;
+			}
+		}
+ 		
+		Enumeration<ProfiledGeneric> e = this.sorter.getSortedList().elements();
+		tableItemData = setTableItemData(e);
+		if (pGeneric instanceof ProfiledThreshold) {
+			tableItemData.add(pGeneric);
+			profiled.add(pGeneric);
+		}
+		
+		// find the column corresponding to sortBy, and give it a column direction
+		// NOTE: treat sort by binary path then by binary name as sort by path
+		if (sortBy == COLUMN_ID_FULL_PATH)
+			sortBy = COLUMN_ID_PATH;
+		else if (sortBy == COLUMN_ID_FULL_IN_PATH)
+			sortBy = COLUMN_ID_IN_BINARY_PATH;
+
+		TableColumn sortByColumn = null;
+		for (int i = 0; i < this.table.getColumnCount(); i++) {
+			if (this.table.getColumn(i).getData() instanceof Integer) {
+				if (((Integer)this.table.getColumn(i).getData()) == sortBy) {
+					sortByColumn = this.table.getColumn(i);
+					break;
+				}
+			}
+		}
+
+		if (sortByColumn != null) {
+			this.table.setSortColumn(sortByColumn);
+			this.table.setSortDirection(sortAscending ? SWT.UP : SWT.DOWN);
+		}
+
+		refreshTableViewer();
+		this.sorting = false;
+	}
+
+	protected Menu getTableMenu(Decorations parent, int graphIndex, int drawMode) {
+		// get rid of last Menu created so we don't have double menu
+		// in on click
+		if (contextMenu != null) {
+			contextMenu.dispose();
+		}
+		
+		contextMenu = new Menu(parent, SWT.POP_UP);
+
+		// Use drawMode to determine the drill down items and
+		// whether to show a color column
+		addDrillDownItems(contextMenu, drawMode);
+		
+		// sort by path, then binary
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getSortInFullPathItem(contextMenu, this.table.getItemCount() > 0);
+
+		// check and uncheck boxes
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getCheckRows(contextMenu, this.table.getSelectionCount() > 0);
+		
+		// select all, copy, and copy all
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getSelectAllItem(contextMenu, this.table.getItemCount() > 0);
+		getCopyItem(contextMenu, this.table.getSelectionCount() > 0);
+		getCopyTableItem(contextMenu, this.table.getItemCount() > 0);
+		
+		// copy drilldown tables, if in drilldown mode
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES:
+			case Defines.FUNCTIONS:
+				getCopyDrilldownItem(contextMenu, false);
+				break;
+			default:
+				getCopyDrilldownItem(contextMenu, true);
+				break;
+		}
+		
+		// save all and save drilldown tables, if in drilldown mode 
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getSaveTableItem(contextMenu, this.table.getItemCount() > 0);
+		
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES:
+			case Defines.FUNCTIONS:
+				getSaveDrilldownItem(contextMenu, false);
+				break;
+			default:
+				getSaveDrilldownItem(contextMenu, true);
+				break;
+		}
+		
+		// save raw samples
+		boolean haveSamples = false;
+		for (int i = 0; !haveSamples && i < profiledFunctions.size(); i++) {
+			ProfiledGeneric pg = profiledFunctions.get(i);
+			haveSamples = pg.isEnabled(graphIndex) && pg.getSampleCount(graphIndex) > 0;
+		}
+
+		double startTime = PIPageEditor.currentPageEditor().getStartTime();
+		double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+		if (!haveSamples || (startTime == -1) || (endTime   == -1) || (startTime == endTime))
+			getSaveSamplesItem(contextMenu, Messages.getString("AddrFunctionTable.functions"), false); //$NON-NLS-1$
+		else
+			getSaveSamplesItem(contextMenu, Messages.getString("AddrFunctionTable.functions"), true); //$NON-NLS-1$
+
+		// recolor selected threads
+		switch (drawMode)
+		{
+			case Defines.FUNCTIONS:
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			case Defines.BINARIES_FUNCTIONS:
+			case Defines.THREADS_FUNCTIONS:
+			case Defines.BINARIES_THREADS_FUNCTIONS:
+			{
+				// recolor selected items
+				new MenuItem(contextMenu, SWT.SEPARATOR);
+				getRecolorItem(contextMenu, Messages.getString("AddressPlugin.functions"),   //$NON-NLS-1$
+								this.table.getSelectionCount() > 0);
+				break;
+			}
+			case Defines.THREADS_FUNCTIONS_BINARIES:
+			case Defines.BINARIES_FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_THREADS_BINARIES:
+			case Defines.FUNCTIONS_BINARIES:
+			case Defines.FUNCTIONS_BINARIES_THREADS:
+			{
+				break;
+			}
+			default:
+				break;
+		}
+
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getChangeThresholds(contextMenu);
+
+		switch (drawMode) {
+			case Defines.THREADS_FUNCTIONS:
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			case Defines.BINARIES_FUNCTIONS:
+			case Defines.BINARIES_THREADS_FUNCTIONS:	
+			case Defines.FUNCTIONS:
+				new MenuItem(contextMenu, SWT.SEPARATOR);
+				// source look up only when one item is selected
+				if (table.getSelection().length == 1) {
+					getSourceLookUpItem(contextMenu, Messages.getString("AddrFunctionTable.items"));  //$NON-NLS-1$
+				} else {
+					getDisabledSourceLookUpItem(contextMenu, Messages.getString("AddrFunctionTable.items"));  //$NON-NLS-1$
+				}
+			default:
+				break;
+		}
+
+		contextMenu.setVisible(true);
+
+		return contextMenu;
+	}
+
+	public Vector getTableItemData() {
+		return this.tableItemData;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddrThreadTable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2541 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.FocusEvent;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Sash;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledBinary;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledFunction;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThreshold;
+import com.nokia.carbide.cpp.internal.pi.visual.Defines;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.internal.pi.visual.PIVisualSharedData;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.TableColorPalette;
+
+
+public class AddrThreadTable extends GenericAddrTable
+{
+	// local copy of profiled threads, which we can sort
+	// without affecting the original
+	Vector<ProfiledGeneric> profiledThreads = new Vector<ProfiledGeneric>();
+
+	// changes made to support priority plugin
+	private boolean priorityAdded = false;
+	private Hashtable<Integer,String> priorityTable;
+	private Hashtable<Integer,Integer> priorityValues;
+
+	public AddrThreadTable(GppTraceGraph myGraph, Composite parent)
+	{
+		this.myGraph = myGraph;
+		this.parent  = parent;
+	}
+
+	public void createTableViewer(int drawMode)
+	{
+		if (this.parent == null)
+			return;
+
+		// Thread table:
+		//		checkbox + colored or white background
+		//  	percent load
+		//  	thread name
+		//		sample count
+		//		priority (optional)
+
+		// Check the drawMode, and use it to decide whether or not to show a color column
+		// or the number of samples
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES_THREADS:
+			case Defines.BINARIES_FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_BINARIES_THREADS:
+			case Defines.THREADS_FUNCTIONS:
+			case Defines.THREADS_FUNCTIONS_BINARIES:
+			case Defines.THREADS_BINARIES:
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			case Defines.BINARIES_THREADS_FUNCTIONS:
+			case Defines.FUNCTIONS_THREADS_BINARIES:
+			{
+				break;
+			}
+			default:
+				// no thread table in this draw mode
+				return;
+		}
+
+		// create the table viewer
+		this.tableViewer = CheckboxTableViewer.newCheckList(this.parent,
+  				SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
+
+		// add the check state handler, label provider and content provider
+		tableViewer.addCheckStateListener(new SharedCheckHandler());
+		tableViewer.setLabelProvider(new shownThreadsLabelProvider());
+		tableViewer.setContentProvider(new shownThreadsContentProvider());
+		tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent arg0) {
+				if (copyAction == null)
+					return;
+
+				// when selection changes, the ability to copy may change
+				copyAction.setEnabled(table.getSelectionCount() > 0);
+				PIPageEditor.getActionBars().updateActionBars();
+			}
+		});
+
+		createDefaultActions();
+		
+		// make sure the table viewer has a sorter
+		if (this.sorter == null)
+			this.sorter = new GppTableSorter();
+
+		this.table = tableViewer.getTable();
+		this.table.setRedraw(false);
+
+		// give the table a heading for use in copying and exported
+		this.table.setData(Messages.getString("AddrThreadTable.threads")); //$NON-NLS-1$
+		
+		// create the columns
+		TableColumn column;
+
+		// data associated with the TableViewer will note which columns contain hex values
+		// Keep this in the order in which columns have been created
+		// Includes the priority column
+		boolean[] isHex = {false, false, false, false, false};
+		this.table.setData("isHex", isHex); //$NON-NLS-1$
+
+		// select/deselect column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_SHOW);
+		column.setWidth(COLUMN_WIDTH_SHOW);
+		column.setData(new Integer(COLUMN_ID_SHOW));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// percent load column
+		column = new TableColumn(table, SWT.RIGHT);
+		column.setText(COLUMN_HEAD_PERCENT_LOAD);
+		column.setWidth(COLUMN_WIDTH_PERCENT_LOAD);
+		column.setData(new Integer(COLUMN_ID_PERCENT_LOAD));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// thread name column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_THREAD);
+		column.setWidth(COLUMN_WIDTH_THREAD_NAME);
+		column.setData(new Integer(COLUMN_ID_THREAD));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// sample count column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_SAMPLE_COUNT);
+		column.setWidth(COLUMN_WIDTH_SAMPLE_COUNT);
+		column.setData(new Integer(COLUMN_ID_SAMPLE_COUNT));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		// priority column
+		if (priorityAdded)
+			this.addPriorityColumn();
+
+		// listen for mouse clicks: to select a row, pop up a menu, etc.
+		table.addMouseListener(new TableMouseListener());
+
+		// listen for key sequences such as Ctrl-A and Ctrl-C
+		table.addKeyListener(new TableKeyListener());
+		
+		table.addFocusListener(new AddrTableFocusListener());
+		
+		// add form data in case later we add a sash to the right
+		FormData viewerData = new FormData();
+		viewerData.top    = new FormAttachment(0);
+		viewerData.bottom = new FormAttachment(100);
+		viewerData.left   = new FormAttachment(0);
+		viewerData.right  = new FormAttachment(100);
+		table.setLayoutData(viewerData);
+		table.setLayout(new FormLayout());
+
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+		table.setRedraw(true);
+	}
+
+	public void setTableViewer(CheckboxTableViewer tableViewer)
+	{
+		this.tableViewer = tableViewer;
+
+		if (tableViewer == null)
+			this.table = null;
+	}
+
+	public void setTableViewer(int drawMode)
+	{
+		if (this.parent == null)
+			return;
+
+		createTableViewer(drawMode);
+
+		// sort by percent load
+		this.sortColumn = COLUMN_ID_SAMPLE_COUNT;
+		this.sortAscending = false;
+
+		// profiledThreads and tableItemData contain one entry per table row
+		updateProfiledAndItemData(false);
+		quickSort(sortColumn, profiledThreads);
+
+		// initially, all rows are checked
+		this.tableViewer.setAllChecked(true);
+	}
+
+	public void refreshTableViewer()
+	{
+		if (this.tableViewer == null)
+			return;
+
+		this.tableViewer.setInput(tableItemData);
+		
+		addColor(this.myGraph.getDrawMode());
+	}
+	
+	public void addColor(int drawMode)
+	{
+		if (this.tableViewer == null)
+			return;
+
+		// make sure that this table's colors are being shown
+		if (   (drawMode != Defines.THREADS)
+			&& (drawMode != Defines.BINARIES_THREADS)
+			&& (drawMode != Defines.BINARIES_FUNCTIONS_THREADS)
+			&& (drawMode != Defines.FUNCTIONS_THREADS)
+			&& (drawMode != Defines.FUNCTIONS_BINARIES_THREADS))
+			return;
+
+		ProfiledGeneric pGeneric;
+
+		TableItem[] items = this.table.getItems();
+
+		for (int i = 0; i < items.length; i++) {
+			pGeneric = (ProfiledGeneric) items[i].getData();
+//			Color color = ((GppTrace)this.myGraph.getTrace()).getThreadColorPalette().getColor(pGeneric.getNameString());
+			items[i].setBackground(COLOR_COLUMN_INDEX, pGeneric.getColor());
+		}
+
+		table.redraw();
+	}
+	
+	public void removeColor(int drawMode)
+	{
+		if (this.tableViewer == null)
+			return;
+
+		// make sure that this table's colors should not be shown
+		if (   (drawMode == Defines.THREADS)
+			|| (drawMode == Defines.BINARIES_THREADS)
+			|| (drawMode == Defines.BINARIES_FUNCTIONS_THREADS)
+			|| (drawMode == Defines.FUNCTIONS_THREADS)
+			|| (drawMode == Defines.FUNCTIONS_BINARIES_THREADS))
+			return;
+
+		TableItem[] items = this.table.getItems();
+
+		for (int i = 0; i < items.length; i++) {
+			items[i].setBackground(COLOR_COLUMN_INDEX, this.parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
+		}
+
+		table.redraw();
+	}
+
+	private static class shownThreadsContentProvider implements IStructuredContentProvider {
+
+		public shownThreadsContentProvider() {
+			super();
+		}
+
+		public Object[] getElements(Object inputElement) {
+			return ((Vector) inputElement).toArray();
+		}
+
+		public void dispose() {
+		}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		}
+	}
+
+	private class shownThreadsLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+        public shownThreadsLabelProvider() {
+			super();
+		}
+
+		public String getColumnText(Object element, int columnIndex) {
+
+			int graphIndex = myGraph.getGraphIndex();
+	        int columnId = ((Integer) table.getColumn(columnIndex).getData()).intValue();
+
+			if (element instanceof ProfiledThreshold) {
+				ProfiledThreshold pThreshold = (ProfiledThreshold) element;
+
+				switch (columnId)
+				{
+					case COLUMN_ID_SHOW:
+					{
+						return SHOW_ITEM_VALUE;
+					}
+					case COLUMN_ID_PERCENT_LOAD:
+					{
+						// Percent load string
+						double startTime = PIPageEditor.currentPageEditor().getStartTime();
+						double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+						if (   (startTime == -1)
+							|| (endTime   == -1)
+							|| (startTime == endTime)) {
+							pThreshold.setAverageLoadValueString(graphIndex, ""); //$NON-NLS-1$
+						} else {
+							float load = (float) (pThreshold.getSampleCount(graphIndex)/(endTime - startTime)/10.0);
+							
+							if (load < 0.005)
+								pThreshold.setAverageLoadValueString(graphIndex, Messages.getString("AddrThreadTable.zeroFormat")); //$NON-NLS-1$
+							else
+								pThreshold.setAverageLoadValueString(graphIndex, load);
+						}
+						return pThreshold.getAverageLoadValueString(graphIndex);
+					}
+					case COLUMN_ID_THREAD:
+					{
+						DecimalFormat timeFormat = new DecimalFormat(Messages.getString("AddrThreadTable.decimalFormat")); //$NON-NLS-1$
+
+						int count = pThreshold.getItemCount(graphIndex);
+
+						return count + (count > 1 ? Messages.getString("AddrThreadTable.thresholdMsg1") : Messages.getString("AddrThreadTable.thresholdMsg2"))   //$NON-NLS-1$ //$NON-NLS-2$
+								+ timeFormat.format((Double)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdLoadThread") * 100.0) + Messages.getString("AddrThreadTable.thresholdMsg3") //$NON-NLS-1$ //$NON-NLS-2$ 
+								+ (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread") + Messages.getString("AddrThreadTable.thresholdMsg4"); //$NON-NLS-1$ //$NON-NLS-2$ 
+					}
+					case COLUMN_ID_SAMPLE_COUNT:
+					{
+						// Sample count
+						return String.valueOf(pThreshold.getSampleCount(graphIndex));
+					}
+					default:
+					{
+						return ""; //$NON-NLS-1$
+					}
+				}
+			}
+
+			if (!(element instanceof ProfiledThread))
+				return ""; //$NON-NLS-1$
+
+			ProfiledThread profiledItem = (ProfiledThread) element;
+
+			switch (columnId)
+			{
+				case COLUMN_ID_SHOW:
+				{
+					return SHOW_ITEM_VALUE;
+				}
+				case COLUMN_ID_PERCENT_LOAD:
+				{
+					// Percent load string
+					return profiledItem.getAverageLoadValueString(graphIndex);
+				}
+				case COLUMN_ID_THREAD:
+				{
+					// Thread
+					if (profiledItem.getNameString().startsWith("*Native*")) //$NON-NLS-1$
+						return Messages.getString("AddrThreadTable.NOSthreads"); //$NON-NLS-1$
+					else
+						return profiledItem.getNameString();
+				}
+				case COLUMN_ID_SAMPLE_COUNT:
+				{
+					// Sample count
+					return String.valueOf(profiledItem.getSampleCount(graphIndex));
+				}
+				case COLUMN_ID_PRIORITY:
+			    {
+					if (priorityAdded) {
+				        String priority = priorityTable.get(new Integer(profiledItem.getThreadId()));
+				        if (priority == null)
+				        	return Messages.getString("AddrThreadTable.unknownPriority"); //$NON-NLS-1$
+				        else
+				        	return priority;
+					}
+					return ""; //$NON-NLS-1$
+			    }
+				default:
+				{
+					break;
+				}
+			}
+			// should never get here
+			return ""; //$NON-NLS-1$
+		}
+
+		public Image getColumnImage(Object element, int columnIndex) {
+			return null;
+		}
+	}
+
+    public void action(String actionString)
+	{
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (   actionString.equals("add") //$NON-NLS-1$
+			|| actionString.equals("remove")) //$NON-NLS-1$
+	    {
+			actionAddRemove(actionString, graphIndex);
+			return;
+	    }
+		else if (   actionString.equals("addall") //$NON-NLS-1$
+				 || actionString.equals("removeall")) //$NON-NLS-1$
+	    {
+			actionAddRemoveAll(actionString, graphIndex);
+			return;
+	    }
+		else if (actionString.equals("recolor")) //$NON-NLS-1$
+		{
+			actionRecolor();
+			return;
+		}
+	    else if (actionString.equals("copy")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, this.table, CHECKBOX_NO_TEXT, false, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("copyTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, this.table, CHECKBOX_NO_TEXT, true, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("copyDrilldown")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSaveDrilldown(true, "\t"); //$NON-NLS-1$
+	        return;
+	    }
+	    else if (actionString.equals("saveTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(false, this.table, CHECKBOX_NO_TEXT, true, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("saveDrilldown")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSaveDrilldown(false, ","); //$NON-NLS-1$
+	        return;
+	    }
+	    else if (actionString.equals("saveSamples")) //$NON-NLS-1$
+	    {
+	    	SaveSampleString saveSampleString = new SaveSampleString(graphIndex, myGraph.getDrawMode());
+	    	actionSaveSamples(saveSampleString); //$NON-NLS-1$
+	        return;
+	    }
+	    else if (actionString.equals("savePrioritySamples")) //$NON-NLS-1$
+	    {
+	    	SavePrioritySampleString saveSampleString = new SavePrioritySampleString(graphIndex, myGraph.getDrawMode());
+	    	actionSaveSamples(saveSampleString); //$NON-NLS-1$
+	        return;
+	    }
+		else if (actionString.equals("selectAll")) //$NON-NLS-1$
+	    {
+	    	actionSelectAll();
+	        return;
+	    }
+		else if (actionString.equals("doubleClick")) //$NON-NLS-1$
+	    {
+	    	copyAction.setEnabled(false);
+			PIPageEditor.getActionBars().updateActionBars();
+	        return;
+	    }
+		else if (actionString.equals("thread-only")) //$NON-NLS-1$
+		{
+			actionThread();
+			return;
+		}
+		else if (actionString.equals("thread-binary")) //$NON-NLS-1$
+		{
+			actionThreadBinary();
+			return;
+		}
+		else if (actionString.equals("thread-binary-function")) //$NON-NLS-1$
+		{
+			actionThreadBinaryFunction();
+			return;
+		}
+		else if (actionString.equals("thread-function")) //$NON-NLS-1$
+		{
+			actionThreadFunction();
+			return;
+		}
+		else if (actionString.equals("thread-function-binary")) //$NON-NLS-1$
+		{
+			actionThreadFunctionBinary();
+			return;
+		}
+		else if (   (actionString.equals("binary-only")) //$NON-NLS-1$
+				 || (actionString.equals("binary-thread")) //$NON-NLS-1$
+				 || (actionString.equals("binary-thread-function")) //$NON-NLS-1$
+				 || (actionString.equals("binary-function")) //$NON-NLS-1$
+				 || (actionString.equals("binary-function-thread"))) //$NON-NLS-1$
+		{
+			// let the binary page action handler handle it
+			this.myGraph.getBinaryTable().action(actionString);
+			return;
+		}
+		else if (   (actionString.equals("function-only")) //$NON-NLS-1$
+				 || (actionString.equals("function-thread")) //$NON-NLS-1$
+				 || (actionString.equals("function-thread-binary")) //$NON-NLS-1$
+				 || (actionString.equals("function-binary")) //$NON-NLS-1$
+				 || (actionString.equals("function-binary-thread"))) //$NON-NLS-1$
+		{
+			// let the function page action handler handle it
+			this.myGraph.getFunctionTable().action(actionString);
+			return;
+		}
+		else if (actionString.equals("changeThresholdThread")) //$NON-NLS-1$
+		{
+			ProfiledThreshold threshold = this.myGraph.getThresholdThread();
+			boolean enabled = threshold.isEnabled(graphIndex);
+
+			this.tableItemData.clear();
+			this.profiledThreads.clear();
+			this.myGraph.getSortedThreads().clear();
+			if (threshold.getItems(graphIndex) != null)
+				threshold.getItems(graphIndex).clear();
+			threshold.initAll();
+
+			// if this appears, it needs to be the first item, so that it is drawn at the bottom
+			myGraph.getSortedThreads().add(threshold);
+
+			int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+			for (int i = 0; i < this.myGraph.getGppTrace().getSortedThreads().size(); i++) {
+				ProfiledGeneric nextElement = (ProfiledGeneric)this.myGraph.getGppTrace().getSortedThreads().get(i);
+				if (nextElement.getTotalSampleCount() < threadThreshold) {
+					nextElement.setEnabled(graphIndex, enabled);
+					threshold.addItem(graphIndex, nextElement, 0);
+				} else {
+					tableItemData.add(nextElement);
+					profiledThreads.add(nextElement);
+					myGraph.getSortedThreads().add(nextElement);
+				}
+			}
+
+			if (threshold.getItemCount(graphIndex) != 0) {
+				tableItemData.add(threshold);
+				profiledThreads.add(threshold);
+			} else {
+				// remove the threshold item
+				myGraph.getSortedThreads().remove(0);
+			}
+			
+			refreshTableViewer();
+			threshold.setEnabled(graphIndex, enabled);
+			
+			// make sure that checkboxes shown reflect the actual enabled values
+			TableItem[] tableItems = this.table.getItems();
+			for (int i = 0; i < tableItems.length; i++) {
+				if (tableItems[i].getData() instanceof ProfiledGeneric) {
+					ProfiledGeneric pGeneric = (ProfiledGeneric) tableItems[i].getData();
+					if (tableItems[i].getChecked() != pGeneric.isEnabled(graphIndex))
+						tableItems[i].setChecked(pGeneric.isEnabled(graphIndex));
+				}
+			}
+
+			this.myGraph.genericRefreshCumulativeThreadTable();
+		}
+	    else if (actionString.equals("saveTableTest")) //$NON-NLS-1$
+	    {
+			// copy save file contents to the clipboard for easy viewing
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+			SaveTableString getString = new SaveTableString(this.table, CHECKBOX_NO_TEXT, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        String copyString = getString.getData();
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+	        return;
+	    }
+	    else if (actionString.equals("saveDrilldownTest")) //$NON-NLS-1$
+	    {
+			// copy save file contents to the clipboard for easy viewing
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+	        Table[] tables = getDrillDownTables();
+	        
+	        int tableCount = 0;
+	        while (tableCount < tables.length && tables[tableCount] != null)
+	        	tableCount++;
+
+	        SaveDrillDownString getString = new SaveDrillDownString(tableCount, tables, ","); //$NON-NLS-1$
+	        String copyString = getString.getData();
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+	        return;
+	    }
+	}
+
+	private void actionAddRemove(String actionString, int graphIndex)
+	{
+		ProfiledGeneric pGeneric;
+		int totalSamples = 0;
+		
+		// true for "add", false for "remove"
+		boolean addIt = actionString.equals("add"); //$NON-NLS-1$
+
+		TableItem[] selectedItems = this.table.getSelection();
+		for (int i = 0; i < selectedItems.length; i++)
+		{
+			selectedItems[i].setChecked(addIt);
+			Object item = ((TableItem)selectedItems[i]).getData();
+			if (item instanceof ProfiledGeneric)
+			{
+				pGeneric = (ProfiledGeneric)item;
+				pGeneric.setEnabled(graphIndex, addIt);
+				totalSamples += pGeneric.getSampleCount(graphIndex);
+   				
+   				if (item instanceof ProfiledThreshold)
+   				{
+   					ProfiledThreshold pThreshold = (ProfiledThreshold)item;
+   					ArrayList<ProfiledGeneric> items = pThreshold.getItems(graphIndex);
+   					for (int j = 0; j < items.size(); j++)
+   						items.get(j).setEnabled(graphIndex, addIt);
+   				}
+			}
+		}
+
+        // this table's set of checkbox-selected rows has changed,
+		// so propagate that information
+		Object[] selectedValues = this.tableViewer.getCheckedElements();
+		String[] nameList = new String[selectedValues.length];
+
+		for (int i = 0; i < selectedValues.length; i++)
+		{
+   			if (selectedValues[i] instanceof ProfiledGeneric)
+   			{
+   				pGeneric = (ProfiledGeneric)selectedValues[i];
+   				nameList[i] = pGeneric.getNameString();
+   			}
+		}
+
+		PIVisualSharedData shared = myGraph.getSharedDataInstance();
+		shared.GPP_SelectedThreadNames = nameList;
+
+  		if (   (totalSamples != 0)
+      		|| (myGraph.getDrawMode() == Defines.THREADS))
+      			selectionChangeNotify();
+
+  		this.table.deselectAll();
+	}
+	
+	private void actionAddRemoveAll(String actionString, int graphIndex)
+	{
+		ProfiledGeneric pGeneric;
+
+		// true for "add", false for "remove"
+		boolean addIt = actionString.equals("addall"); //$NON-NLS-1$
+
+		TableItem[] selectedItems = this.table.getItems();
+		String[] nameList = new String[selectedItems.length];
+		for (int i = 0; i < selectedItems.length; i++)
+		{
+			selectedItems[i].setChecked(addIt);
+			Object item = ((TableItem)selectedItems[i]).getData();
+			if (item instanceof ProfiledGeneric)
+			{
+				pGeneric = (ProfiledGeneric)item;
+				pGeneric.setEnabled(graphIndex, addIt);
+   				nameList[i] = pGeneric.getNameString();
+   				
+   				if (item instanceof ProfiledThreshold)
+   				{
+   					ProfiledThreshold pThreshold = (ProfiledThreshold)item;
+   					ArrayList<ProfiledGeneric> items = pThreshold.getItems(graphIndex);
+   					for (int j = 0; j < items.size(); j++)
+   						items.get(j).setEnabled(graphIndex, addIt);
+   				}
+			}
+		}
+
+        // this table's set of checkbox-selected rows has changed,
+		// so propagate that information
+		PIVisualSharedData shared = myGraph.getSharedDataInstance();
+		shared.GPP_SelectedThreadNames = nameList;
+
+			selectionChangeNotify();
+  		this.table.deselectAll();
+	}
+	
+	private void actionRecolor()
+	{
+		int uid 			= this.myGraph.getUid();
+		GppTrace gppTrace = this.myGraph.getGppTrace();
+
+		// recolor selected items
+		boolean didRecolor = false;
+
+		TableItem[] selectedItems = table.getSelection();
+		for (int i = 0; i < selectedItems.length;i++)
+		{
+			if (selectedItems[i].getData() instanceof ProfiledGeneric)
+			{
+				ProfiledGeneric pGeneric = (ProfiledGeneric)selectedItems[i].getData();
+				TableColorPalette palette = ((GppTrace)this.myGraph.getTrace()).getThreadColorPalette();
+				String nameKey = pGeneric.getNameString();
+				if (palette.recolorEntryDialog(table.getShell(), nameKey))
+				{
+					Color color = palette.getColor(nameKey);
+					Color oldColor = pGeneric.getColor();
+					
+					if (color.equals(oldColor))
+						continue;
+					
+					didRecolor = true;
+					
+					if (!(pGeneric instanceof ProfiledThreshold)) {
+						PIPageEditor.currentPageEditor().setDirty();
+						pGeneric.setColor(color);
+					} else {
+						// for the threshold item, we must change every graph's thread threshold item
+						gppTrace.getGppGraph(PIPageEditor.THREADS_PAGE,   uid).getThresholdThread().setColor(color);
+						gppTrace.getGppGraph(PIPageEditor.BINARIES_PAGE,  uid).getThresholdThread().setColor(color);
+						gppTrace.getGppGraph(PIPageEditor.FUNCTIONS_PAGE, uid).getThresholdThread().setColor(color);
+					}
+				}
+
+				// recoloring should only be done in a draw mode that displays this table's colors
+				selectedItems[i].setBackground(COLOR_COLUMN_INDEX, palette.getColor(nameKey));
+			}
+		}
+		
+		if (!didRecolor)
+			return;
+
+		table.redraw();
+		this.myGraph.repaint();
+		this.myGraph.setGraphImageChanged(true);	// any selection change to drill down will change graph
+		
+		// if any other tabs are displaying this type of graph, they need to be scheduled for redrawing
+		for (int i = 0; i < 3; i++) {
+			GppTraceGraph graph = gppTrace.getGppGraph(i, uid);
+
+			if (graph == this.myGraph)
+				continue;
+
+			int drawMode = graph.getDrawMode();
+			
+			if (   (drawMode == Defines.THREADS)
+				|| (drawMode == Defines.BINARIES_THREADS)
+				|| (drawMode == Defines.BINARIES_FUNCTIONS_THREADS)
+				|| (drawMode == Defines.FUNCTIONS_THREADS)
+				|| (drawMode == Defines.FUNCTIONS_BINARIES_THREADS)) {
+				graph.getThreadTable().addColor(drawMode);
+				graph.setGraphImageChanged(true);	// any selection change to drill down will change graph
+				graph.repaint();
+			}
+		}
+	}
+
+	private void actionThread()
+	{
+		// current drawMode should be THREADS, THREADS_BINARIES, THREADS_BINARIES_FUNCTIONS,
+		// THREADS_FUNCTIONS, or THREADS_FUNCTIONS_BINARIES
+		int drawMode = this.myGraph.getDrawMode();
+
+		if (   (drawMode != Defines.THREADS_BINARIES)
+			&& (drawMode != Defines.THREADS_BINARIES_FUNCTIONS)
+			&& (drawMode != Defines.THREADS_FUNCTIONS)
+			&& (drawMode != Defines.THREADS_FUNCTIONS_BINARIES))
+		{
+			// this case should be drawMode == Defines.THREADS
+			return;
+		}
+		
+		setIsDrilldown(false);
+
+		// set the page's graph title
+		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+		pV.getTitle().setText(Messages.getString("AddrThreadTable.threadLoad")); //$NON-NLS-1$
+		pV.getTitle2().setText(""); //$NON-NLS-1$
+
+		// get rid of any existing tables and sashes
+		if (this.myGraph.getLeftSash() != null) {
+			this.myGraph.getLeftSash().dispose();
+			this.myGraph.setLeftSash(null);
+
+			// detach the table from the sash
+			try {
+				FormData formData = (FormData) this.table.getLayoutData();
+				formData.right = new FormAttachment(100);
+			} catch (ClassCastException e1) {
+			}
+		}
+		if (this.myGraph.getRightSash() != null) {
+			this.myGraph.getRightSash().dispose();
+			this.myGraph.setRightSash(null);
+		}
+		if (   (this.myGraph.getBinaryTable() != null)
+			&& (this.myGraph.getBinaryTable().getTable() != null)) {
+			this.myGraph.getBinaryTable().getTableViewer().getTable().dispose();
+			this.myGraph.getBinaryTable().setTableViewer(null);
+		}
+		if (   (this.myGraph.getFunctionTable() != null)
+			&& (this.myGraph.getFunctionTable().getTable() != null)) {
+			this.myGraph.getFunctionTable().getTableViewer().getTable().dispose();
+			this.myGraph.getFunctionTable().setTableViewer(null);
+		}
+
+		// set the draw mode
+		this.myGraph.setDrawMode(Defines.THREADS);
+
+		// add colors to the rightmost table
+		addColor(Defines.THREADS);
+
+		this.parent.layout();
+
+		this.myGraph.repaint();
+	}
+
+	private void actionThreadBinary()
+	{
+		// current drawMode should be THREADS, THREADS_BINARIES, or THREADS_BINARIES_FUNCTIONS
+		int drawMode = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (   drawMode != Defines.THREADS
+			&& drawMode != Defines.THREADS_BINARIES_FUNCTIONS) {
+			return;
+		}
+		
+		setIsDrilldown(true);
+
+		if (drawMode == Defines.THREADS) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrThreadTable.binaryLoad")); //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadTo")); //$NON-NLS-1$
+
+			// set the draw mode before populating table viewers, since the
+			// color column depends on the draw mode
+			this.myGraph.setDrawMode(Defines.THREADS_BINARIES);
+
+			// create the binary graph table viewer
+			AddrBinaryTable binaryTable = this.myGraph.getBinaryTable();
+			binaryTable.createTableViewer(Defines.THREADS_BINARIES);
+			binaryTable.setIsDrilldown(true);
+
+			// create a reduced set of binary entries based on enabled thread entries
+			GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+			Vector<ProfiledGeneric> binaries = gppTrace.setThreadBinary(graphIndex);
+			this.myGraph.setProfiledBinaries(binaries);
+
+			// put check marks on all rows, and sort by sample count
+			binaryTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledBinaries());
+			binaryTable.updateProfiledAndItemData(true);
+			binaryTable.getTableViewer().setAllChecked(true);
+			binaryTable.getTableViewer().refresh();
+
+			// put check marks on all enabled thread rows
+			for (int i = 0; i < this.table.getItemCount(); i++) {
+				ProfiledGeneric pThread = (ProfiledGeneric) this.table.getItem(i).getData();
+				if (pThread.isEnabled(graphIndex))
+					this.table.getItem(i).setChecked(true);
+			}
+			
+			// remove colors where appropriate
+			removeColor(Defines.THREADS_BINARIES);
+
+			// connect the tables with a sash
+			Sash leftSash   = new Sash(this.parent, SWT.VERTICAL);
+
+			final FormData leftSashData = new FormData();
+			leftSashData.top    = new FormAttachment(0);
+			leftSashData.bottom = new FormAttachment(100);
+			leftSashData.left   = new FormAttachment(50); // middle
+			leftSash.setLayoutData(leftSashData);
+
+			final Composite sashParent = this.parent;
+			leftSash.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					if (event.detail != SWT.DRAG) {
+						leftSashData.left = new FormAttachment(0, event.x);
+						sashParent.layout();
+					}
+				}
+			});
+
+			myGraph.setLeftSash(leftSash);
+
+			// attach the binary table to the sash
+			final FormData viewerData = new FormData();
+			viewerData.top    = new FormAttachment(0);
+			viewerData.bottom = new FormAttachment(100);
+			viewerData.left   = new FormAttachment(leftSash);
+			viewerData.right  = new FormAttachment(100);
+			binaryTable.getTable().setLayoutData(viewerData);
+
+			// attach the thread table to the sash
+			try {
+				FormData formData = (FormData) this.table.getLayoutData();
+				formData.right = new FormAttachment(leftSash);
+			} catch (ClassCastException e1) {
+			}
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+
+		} else if (drawMode == Defines.THREADS_BINARIES_FUNCTIONS) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrThreadTable.binaryLoad")); //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadTo")); //$NON-NLS-1$
+
+			// get rid of the function table and its sash
+			if (this.myGraph.getRightSash() != null) {
+				this.myGraph.getRightSash().dispose();
+				this.myGraph.setRightSash(null);
+			}
+			if (   (this.myGraph.getFunctionTable() != null)
+				&& (this.myGraph.getFunctionTable().getTable() != null)) {
+				this.myGraph.getFunctionTable().getTableViewer().getTable().dispose();
+				this.myGraph.getFunctionTable().setTableViewer(null);
+			}
+
+			// get rid of the middle table's connection to the sash
+			try {
+				FormData formData = (FormData) this.myGraph.getBinaryTable().getTable().getLayoutData();
+				formData.right = new FormAttachment(100);
+			} catch (ClassCastException e1) {
+			}
+
+			// move the left sash to the middle
+			try {
+				FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+				formData.left = new FormAttachment(50); // middle
+			} catch (ClassCastException e1) {
+			}
+
+			// set the draw mode
+			this.myGraph.setDrawMode(Defines.THREADS_BINARIES);
+
+			// show colors in the rightmost table
+			this.myGraph.getBinaryTable().addColor(Defines.THREADS_BINARIES);
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+		}
+
+		// this case should be drawMode == Defines.THREADS_BINARIES
+		return;
+	}
+
+	private void actionThreadBinaryFunction()
+	{
+		// current drawMode should be THREADS_BINARIES or THREADS_BINARIES_FUNCTIONS
+		int drawMode = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (drawMode != Defines.THREADS_BINARIES) {
+			// this case should be drawMode == Defines.THREADS_BINARIES_FUNCTIONS
+			return;
+		}
+
+		setIsDrilldown(true);
+
+		// set the page's graph title
+		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+		pV.getTitle().setText(Messages.getString("AddrThreadTable.functionLoad")); //$NON-NLS-1$
+		pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadToBinaryTo")); //$NON-NLS-1$
+
+		// set the draw mode before populating table viewers, since the
+		// color column depends on the draw mode
+		this.myGraph.setDrawMode(Defines.THREADS_BINARIES_FUNCTIONS);
+
+		// create the function graph table viewer
+		AddrFunctionTable functionTable = this.myGraph.getFunctionTable();
+		functionTable.createTableViewer(Defines.THREADS_BINARIES_FUNCTIONS);
+		functionTable.setIsDrilldown(true);
+
+		// create a reduced set of function entries based on enabled thread and binary entries
+		GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+		Vector<ProfiledGeneric> functions = gppTrace.setThreadBinaryFunction(graphIndex);
+		this.myGraph.setProfiledFunctions(functions);
+
+		// put check marks on all rows, and sort by sample count
+		functionTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledFunctions());
+		functionTable.updateProfiledAndItemData(true);
+		functionTable.getTableViewer().setAllChecked(true);
+		functionTable.getTableViewer().refresh();
+
+		// remove colors where appropriate
+		this.myGraph.getBinaryTable().removeColor(Defines.THREADS_BINARIES_FUNCTIONS);
+
+		// connect the 2nd and 3rd tables with a sash
+		Sash rightSash   = new Sash(this.parent, SWT.VERTICAL);
+
+		final FormData rightSashData = new FormData();
+		rightSashData.top    = new FormAttachment(0);
+		rightSashData.bottom = new FormAttachment(100);
+		rightSashData.left   = new FormAttachment(67); // two thirds
+		rightSash.setLayoutData(rightSashData);
+
+		final Composite sashParent = this.parent;
+		rightSash.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				if (event.detail != SWT.DRAG) {
+					rightSashData.left = new FormAttachment(0, event.x);
+					sashParent.layout();
+				}
+			}
+		});
+
+		myGraph.setRightSash(rightSash);
+
+		// attach the function table to the sash
+		final FormData viewerData = new FormData();
+		viewerData.top    = new FormAttachment(0);
+		viewerData.bottom = new FormAttachment(100);
+		viewerData.left   = new FormAttachment(rightSash);
+		viewerData.right  = new FormAttachment(100);
+		functionTable.getTable().setLayoutData(viewerData);
+
+		// attach the binary table to the sash
+		try {
+			FormData formData = (FormData) this.myGraph.getBinaryTable().getTable().getLayoutData();
+			formData.right = new FormAttachment(rightSash);
+		} catch (ClassCastException e1) {
+		}
+
+		// move the left sash to 1/3 from the left
+		try {
+			FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+			formData.left = new FormAttachment(33); // one third
+		} catch (ClassCastException e1) {
+		}
+
+		this.parent.layout();
+
+		this.myGraph.repaint();
+	}
+
+	private void actionThreadFunction()
+	{
+		// current drawMode should be THREADS, THREADS_FUNCTIONS, or THREADS_FUNCTIONS_BINARIES
+		int drawMode = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (   drawMode != Defines.THREADS
+			&& drawMode != Defines.THREADS_FUNCTIONS_BINARIES) {
+			return;
+		}
+
+		setIsDrilldown(true);
+
+		if (drawMode == Defines.THREADS) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrThreadTable.functionLoad")); //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadTo")); //$NON-NLS-1$
+
+			// set the draw mode
+			this.myGraph.setDrawMode(Defines.THREADS_FUNCTIONS);
+
+			// create the function graph table viewer
+			AddrFunctionTable functionTable = this.myGraph.getFunctionTable();
+			functionTable.createTableViewer(Defines.THREADS_FUNCTIONS);
+			functionTable.setIsDrilldown(true);
+
+			// create a reduced set of function entries based on enabled thread and binary entries
+			GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+			Vector<ProfiledGeneric> functions = gppTrace.setThreadFunction(graphIndex);
+			this.myGraph.setProfiledFunctions(functions);
+
+			// put check marks on all rows, and sort by sample count
+			functionTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledFunctions());
+			functionTable.updateProfiledAndItemData(true);
+			functionTable.getTableViewer().setAllChecked(true);
+			functionTable.getTableViewer().refresh();
+
+			// remove colors where appropriate
+			removeColor(Defines.THREADS_FUNCTIONS);
+
+			// connect the tables with a sash
+			Sash leftSash   = new Sash(this.parent, SWT.VERTICAL);
+
+			final FormData leftSashData = new FormData();
+			leftSashData.top    = new FormAttachment(0);
+			leftSashData.bottom = new FormAttachment(100);
+			leftSashData.left   = new FormAttachment(50); // middle
+			leftSash.setLayoutData(leftSashData);
+
+			final Composite sashParent = this.parent;
+			leftSash.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					if (event.detail != SWT.DRAG) {
+						leftSashData.left = new FormAttachment(0, event.x);
+						sashParent.layout();
+					}
+				}
+			});
+
+			myGraph.setLeftSash(leftSash);
+
+			// attach the function table to the sash
+			final FormData viewerData = new FormData();
+			viewerData.top    = new FormAttachment(0);
+			viewerData.bottom = new FormAttachment(100);
+			viewerData.left   = new FormAttachment(leftSash);
+			viewerData.right  = new FormAttachment(100);
+			functionTable.getTable().setLayoutData(viewerData);
+
+			// attach the thread table to the sash
+			try {
+				FormData formData = (FormData) this.table.getLayoutData();
+				formData.right = new FormAttachment(leftSash);
+			} catch (ClassCastException e1) {
+			}
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+
+		} else if (drawMode == Defines.THREADS_FUNCTIONS_BINARIES) {
+			// set the page's graph title
+			ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+			pV.getTitle().setText(Messages.getString("AddrThreadTable.functionLoad")); //$NON-NLS-1$
+			pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadTo")); //$NON-NLS-1$
+
+			// get rid of the binary table and its sash
+			if (this.myGraph.getRightSash() != null) {
+				this.myGraph.getRightSash().dispose();
+				this.myGraph.setRightSash(null);
+			}
+			if (   (this.myGraph.getBinaryTable() != null)
+				&& (this.myGraph.getBinaryTable().getTable() != null)) {
+				this.myGraph.getBinaryTable().getTableViewer().getTable().dispose();
+				this.myGraph.getBinaryTable().setTableViewer(null);
+			}
+
+			// get rid of the middle table's connection to the sash
+			try {
+				FormData formData = (FormData) this.myGraph.getFunctionTable().getTable().getLayoutData();
+				formData.right = new FormAttachment(100);
+			} catch (ClassCastException e1) {
+			}
+
+			// move the left sash to the middle
+			try {
+				FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+				formData.left = new FormAttachment(50); // middle
+			} catch (ClassCastException e1) {
+			}
+
+			// set the draw mode
+			this.myGraph.setDrawMode(Defines.THREADS_FUNCTIONS);
+
+			// show colors in the rightmost table
+			this.myGraph.getFunctionTable().addColor(Defines.THREADS_FUNCTIONS);
+
+			this.parent.layout();
+
+			this.myGraph.repaint();
+		}
+
+		// this case should be drawMode == Defines.THREADS_BINARIES
+		return;
+	}
+
+	private void actionThreadFunctionBinary()
+	{
+		// current drawMode is THREADS_FUNCTIONS, or THREADS_FUNCTIONS_BINARIES
+		int drawMode   = this.myGraph.getDrawMode();
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (drawMode != Defines.THREADS_FUNCTIONS) {
+			// this case should be drawMode == Defines.THREADS_FUNCTIONS_BINARIES
+			return;
+		}
+
+		setIsDrilldown(true);
+
+		// set the page's graph title
+		ProfileVisualiser pV =  NpiInstanceRepository.getInstance().getProfilePage(this.myGraph.getUid(), this.myGraph.getGraphIndex());
+		pV.getTitle().setText(Messages.getString("AddrThreadTable.binaryLoad")); //$NON-NLS-1$
+		pV.getTitle2().setText(Messages.getString("AddrThreadTable.threadToFunctionTo")); //$NON-NLS-1$
+
+		// set the draw mode
+		this.myGraph.setDrawMode(Defines.THREADS_FUNCTIONS_BINARIES);
+
+		// create the binary graph table viewer
+		AddrBinaryTable binaryTable = this.myGraph.getBinaryTable();
+		binaryTable.createTableViewer(Defines.THREADS_FUNCTIONS_BINARIES);
+		binaryTable.setIsDrilldown(true);
+
+		// create a reduced set of binary entries based on enabled thread and function entries
+		GppTrace gppTrace = (GppTrace) this.myGraph.getTrace();
+		Vector<ProfiledGeneric> binaries = gppTrace.setThreadFunctionBinary(graphIndex);
+		this.myGraph.setProfiledBinaries(binaries);
+
+		// put check marks on all rows, and sort by sample count
+		binaryTable.quickSort(COLUMN_ID_SAMPLE_COUNT, this.myGraph.getProfiledBinaries());
+		binaryTable.updateProfiledAndItemData(true);
+		binaryTable.getTableViewer().setAllChecked(true);
+		binaryTable.getTableViewer().refresh();
+
+		// remove colors where appropriate
+		this.myGraph.getFunctionTable().removeColor(Defines.THREADS_FUNCTIONS_BINARIES);
+
+		// connect the 2nd and 3rd tables with a sash
+		Sash rightSash   = new Sash(this.parent, SWT.VERTICAL);
+
+		final FormData rightSashData = new FormData();
+		rightSashData.top    = new FormAttachment(0);
+		rightSashData.bottom = new FormAttachment(100);
+		rightSashData.left   = new FormAttachment(67); // two thirds
+		rightSash.setLayoutData(rightSashData);
+
+		final Composite sashParent = this.parent;
+		rightSash.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				if (event.detail != SWT.DRAG) {
+					rightSashData.left = new FormAttachment(0, event.x);
+					sashParent.layout();
+				}
+			}
+		});
+
+		myGraph.setRightSash(rightSash);
+
+		// attach the binary table to the sash
+		final FormData viewerData = new FormData();
+		viewerData.top    = new FormAttachment(0);
+		viewerData.bottom = new FormAttachment(100);
+		viewerData.left   = new FormAttachment(rightSash);
+		viewerData.right  = new FormAttachment(100);
+		binaryTable.getTable().setLayoutData(viewerData);
+
+		// attach the function table to the sash
+		try {
+			FormData formData = (FormData) this.myGraph.getFunctionTable().getTable().getLayoutData();
+			formData.right = new FormAttachment(rightSash);
+		} catch (ClassCastException e1) {
+		}
+
+		// move the left sash to 1/3 from the left
+		try {
+			FormData formData = (FormData) this.myGraph.getLeftSash().getLayoutData();
+			formData.left = new FormAttachment(33); // one third
+		} catch (ClassCastException e1) {
+		}
+
+		this.parent.layout();
+
+		this.myGraph.repaint();
+	}
+
+	public void focusGained(FocusEvent e) {}
+
+	public void focusLost(FocusEvent e) {}
+
+	public void piEventReceived(PIEvent be)
+	{
+		if (be.getType() == PIEvent.SELECTION_AREA_CHANGED3)
+		{
+			// % loads, % load strings, and/or sample counts have been updated
+			// due to a change in the graph area selected, and all table items
+			// need to be checked
+			updateProfiledAndItemData(true);
+
+			Display.getDefault().syncExec(new Runnable() {
+				public void run() {
+					quickSort(sortColumn, profiledThreads);
+
+					// initially, all rows are selected
+					tableViewer.setAllChecked(true);
+
+					table.redraw();
+				}
+			});
+		}
+		else if (   (be.getType() == PIEvent.SELECTION_AREA_CHANGED2)
+				 || (be.getType() == PIEvent.CHANGED_THREAD_TABLE))
+		{
+			int graphIndex = this.myGraph.getGraphIndex();
+
+			// This routine does not change which threads are enabled, but it enables
+			// all entries in the 2nd and 3rd tables.
+			// It assumes that GppTrace.setSelectedArea(), action("add") or action("remove") has set
+			// the % load and sample counts for threads, except for the threshold list.
+			if (be.getType() == PIEvent.SELECTION_AREA_CHANGED2) {
+				int thresholdCount = (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+				if (thresholdCount > 0) {
+					Vector<ProfiledGeneric> pGeneric = this.myGraph.getProfiledThreads();
+					int sampleCount = 0;
+					for (int i = 0; i < pGeneric.size(); i++)
+						if (pGeneric.elementAt(i).getTotalSampleCount() < thresholdCount)
+							sampleCount += pGeneric.elementAt(i).getSampleCount(graphIndex);
+					this.myGraph.getThresholdThread().setSampleCount(graphIndex, sampleCount);
+				}
+			}
+
+			// redraw this table
+			Display.getDefault().syncExec(new Runnable() {
+				public void run() {
+					if (   (sortColumn == COLUMN_ID_PERCENT_LOAD)
+						|| (sortColumn == COLUMN_ID_SAMPLE_COUNT))
+					{
+						quickSort(sortColumn, profiledThreads);
+					}
+					else
+						refreshTableViewer();
+
+					table.redraw();
+				}
+			});
+
+			int drawMode = this.myGraph.getDrawMode();
+			if (drawMode == Defines.THREADS)
+				return;
+
+			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
+			Vector<ProfiledGeneric> traceThreads = trace.getIndexedThreads();
+
+			int startSampleIndex = trace.getStartSampleIndex();
+			int endSampleIndex   = trace.getEndSampleIndex();
+			double percentPerSample;
+			if (startSampleIndex == endSampleIndex)
+				percentPerSample = 0.0;
+			else
+				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
+
+			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
+
+			switch (drawMode) {
+				case Defines.THREADS_BINARIES:
+				{
+					// get new binary counts and loads
+					Vector<ProfiledGeneric> traceBinaries = trace.getIndexedBinaries();
+					Vector<ProfiledGeneric> graphBinaries  = this.myGraph.getProfiledBinaries();
+					Hashtable<String,String> foundBinaries  = new Hashtable<String,String>();
+
+					// previous binaries are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enu = graphBinaries.elements();
+					while (enu.hasMoreElements()) {
+						ProfiledBinary pBinary = (ProfiledBinary) enu.nextElement();
+						pBinary.setEnabled(graphIndex, false);
+					}
+					graphBinaries.clear();
+
+					ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
+
+					if (thresholdBinary.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find binaries below the threshold
+					boolean lowBinary;
+					thresholdBinary.init(graphIndex);
+					
+					int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+						if (pThread.isEnabled(graphIndex)) {
+							// binary list is based on threads
+							ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+							String binaryName = pBinary.getNameString();
+
+							lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
+
+							if (!foundBinaries.containsKey(binaryName)) {
+								foundBinaries.put(binaryName, binaryName);
+								if (lowBinary) {
+									thresholdBinary.addItem(graphIndex, pBinary, 1);
+								} else {
+									pBinary.setEnabled(graphIndex, true);
+									pBinary.setSampleCount(graphIndex, 1);
+									graphBinaries.add(pBinary);
+								}
+							} else {
+								if (lowBinary)
+									thresholdBinary.incSampleCount(graphIndex);
+								else
+									pBinary.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphBinaries.size(); i++) {
+						ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
+						pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdBinary.setLoadAndString(graphIndex,
+							(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getBinaryTable().piEventReceived(be3);
+					break;
+				}
+				case Defines.THREADS_BINARIES_FUNCTIONS:
+				{
+					// get new binary and function counts and loads
+					Vector<ProfiledGeneric> traceBinaries   = trace.getIndexedBinaries();
+					Vector<ProfiledGeneric> traceFunctions  = trace.getIndexedFunctions();
+					Vector<ProfiledGeneric> graphBinaries   = this.myGraph.getProfiledBinaries();
+					Vector<ProfiledGeneric> graphFunctions  = this.myGraph.getProfiledFunctions();
+					Hashtable<String,String> foundBinaries  = new Hashtable<String,String>();
+					Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
+
+					// previous functions are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuFunctions = graphFunctions.elements();
+					while (enuFunctions.hasMoreElements()) {
+						ProfiledFunction pFunction = (ProfiledFunction) enuFunctions.nextElement();
+						pFunction.setEnabled(graphIndex, false);
+					}
+					graphFunctions.clear();
+
+					ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
+
+					if (thresholdFunction.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					// previous binaries are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuBinary = graphBinaries.elements();
+					while (enuBinary.hasMoreElements()) {
+						ProfiledBinary pBinary = (ProfiledBinary) enuBinary.nextElement();
+						pBinary.setEnabled(graphIndex, false);
+					}
+					graphBinaries.clear();
+
+					ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
+
+					if (thresholdBinary.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find functions below the threshold
+					boolean lowFunction;
+					thresholdFunction.init(graphIndex);
+
+					// set up in case we find binaries below the threshold
+					boolean lowBinary;
+					thresholdBinary.init(graphIndex);
+
+					int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+						if (pThread.isEnabled(graphIndex)) {
+							// binary list is based on threads
+							ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+							String binaryName = pBinary.getNameString();
+
+							lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
+
+							if (!foundBinaries.containsKey(binaryName)) {
+								foundBinaries.put(binaryName, binaryName);
+								if (lowBinary) {
+									thresholdBinary.addItem(graphIndex, pBinary, 1);
+								} else {
+									pBinary.setEnabled(graphIndex, true);
+									pBinary.setSampleCount(graphIndex, 1);
+									graphBinaries.add(pBinary);
+								}
+							} else {
+								if (lowBinary)
+									thresholdBinary.incSampleCount(graphIndex);
+								else
+									pBinary.incSampleCount(graphIndex);
+							}
+
+							// function list is based on threads and binaries
+							ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+							String functionName = pFunction.getNameString();
+
+							lowFunction = pFunction.getTotalSampleCount() < (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+
+							if (!foundFunctions.containsKey(functionName)) {
+								foundFunctions.put(functionName, functionName);
+								if (lowFunction) {
+									thresholdFunction.addItem(graphIndex, pFunction, 1);
+								} else {
+									pFunction.setEnabled(graphIndex, true);
+									pFunction.setSampleCount(graphIndex, 1);
+									graphFunctions.add(pFunction);
+								}
+							} else {
+								if (lowFunction)
+									thresholdFunction.incSampleCount(graphIndex);
+								else
+									pFunction.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphBinaries.size(); i++) {
+						ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
+						pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdBinary.setLoadAndString(graphIndex,
+							(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
+
+					for (int i = 0; i < graphFunctions.size(); i++) {
+						ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
+						pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdFunction.setLoadAndString(graphIndex,
+							(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getBinaryTable().piEventReceived(be3);
+					this.myGraph.getFunctionTable().piEventReceived(be3);
+					break;
+				}
+				case Defines.THREADS_FUNCTIONS:
+				{
+					// get new function counts and loads
+					Vector<ProfiledGeneric> traceFunctions  = trace.getIndexedFunctions();
+					Vector<ProfiledGeneric> graphFunctions  = this.myGraph.getProfiledFunctions();
+					Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
+
+					// previous functions are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enu = graphFunctions.elements();
+					while (enu.hasMoreElements()) {
+						ProfiledFunction pFunction = (ProfiledFunction) enu.nextElement();
+						pFunction.setEnabled(graphIndex, false);
+					}
+					graphFunctions.clear();
+
+					ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
+
+					if (thresholdFunction.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find functions below the threshold
+					boolean lowFunction;
+					thresholdFunction.init(graphIndex);
+
+					int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+						if (pThread.isEnabled(graphIndex)) {
+							// function list is based on threads
+							ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+							String functionName = pFunction.getNameString();
+
+							lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
+
+							if (!foundFunctions.containsKey(functionName)) {
+								foundFunctions.put(functionName, functionName);
+								if (lowFunction) {
+									thresholdFunction.addItem(graphIndex, pFunction, 1);
+								} else {
+									pFunction.setEnabled(graphIndex, true);
+									pFunction.setSampleCount(graphIndex, 1);
+									graphFunctions.add(pFunction);
+								}
+							} else {
+								if (lowFunction)
+									thresholdFunction.incSampleCount(graphIndex);
+								else
+									pFunction.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphFunctions.size(); i++) {
+						ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
+						pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdFunction.setLoadAndString(graphIndex,
+							(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getFunctionTable().piEventReceived(be3);
+					break;
+				}
+				case Defines.THREADS_FUNCTIONS_BINARIES:
+				{
+					// get new function and binary counts and loads
+					Vector<ProfiledGeneric> traceBinaries   = trace.getIndexedBinaries();
+					Vector<ProfiledGeneric> traceFunctions  = trace.getIndexedFunctions();
+					Vector<ProfiledGeneric> graphBinaries   = this.myGraph.getProfiledBinaries();
+					Vector<ProfiledGeneric> graphFunctions  = this.myGraph.getProfiledFunctions();
+					Hashtable<String,String> foundBinaries  = new Hashtable<String,String>();
+					Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
+
+					// previous binaries are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuBinaries = graphBinaries.elements();
+					while (enuBinaries.hasMoreElements()) {
+						ProfiledBinary pBinary = (ProfiledBinary) enuBinaries.nextElement();
+						pBinary.setEnabled(graphIndex, false);
+					}
+					graphBinaries.clear();
+
+					ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
+
+					if (thresholdBinary.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					// previous functions are not necessarily graphed this time
+					Enumeration<ProfiledGeneric> enuFunctions = graphFunctions.elements();
+					while (enuFunctions.hasMoreElements()) {
+						ProfiledFunction pFunction = (ProfiledFunction) enuFunctions.nextElement();
+						pFunction.setEnabled(graphIndex, false);
+					}
+					graphFunctions.clear();
+
+					ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
+
+					if (thresholdFunction.isEnabled(graphIndex)) {
+						ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
+						// disable all items below the threshold
+						for (int i = 0; i < items.size(); i++) {
+							items.get(i).setEnabled(graphIndex, false);
+						}
+					}
+
+					GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+					// set up in case we find binaries below the threshold
+					boolean lowBinary;
+					thresholdBinary.init(graphIndex);
+
+					// set up in case we find functions below the threshold
+					boolean lowFunction;
+					thresholdFunction.init(graphIndex);
+
+					int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+					for (int i = startSampleIndex; i < endSampleIndex; i++) {
+						GppSample sample = sortedSamples[i];
+
+						ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+						if (pThread.isEnabled(graphIndex)) {
+							// function list is based on threads
+							ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+							String functionName = pFunction.getNameString();
+
+							lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
+
+							if (!foundFunctions.containsKey(functionName)) {
+								foundFunctions.put(functionName, functionName);
+								if (lowFunction) {
+									thresholdFunction.addItem(graphIndex, pFunction, 1);
+								} else {
+									pFunction.setEnabled(graphIndex, true);
+									pFunction.setSampleCount(graphIndex, 1);
+									graphFunctions.add(pFunction);
+								}
+							} else {
+								if (lowFunction)
+									thresholdFunction.incSampleCount(graphIndex);
+								else
+									pFunction.incSampleCount(graphIndex);
+							}
+
+							// binary list is based on threads and functions
+							ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+							String binaryName = pBinary.getNameString();
+
+							lowBinary = pBinary.getTotalSampleCount() < (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+
+							if (!foundBinaries.containsKey(binaryName)) {
+								foundBinaries.put(binaryName, binaryName);
+								if (lowBinary) {
+									thresholdBinary.addItem(graphIndex, pBinary, 1);
+								} else {
+									pBinary.setEnabled(graphIndex, true);
+									pBinary.setSampleCount(graphIndex, 1);
+									graphBinaries.add(pBinary);
+								}
+							} else {
+								if (lowBinary)
+									thresholdBinary.incSampleCount(graphIndex);
+								else
+									pBinary.incSampleCount(graphIndex);
+							}
+						}
+					}
+
+					// set the % load
+					for (int i = 0; i < graphBinaries.size(); i++) {
+						ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
+						pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdBinary.setLoadAndString(graphIndex,
+							(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
+
+					for (int i = 0; i < graphFunctions.size(); i++) {
+						ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
+						pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
+					}
+					thresholdFunction.setLoadAndString(graphIndex,
+							(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
+
+					// update the table items and redraw the table
+					this.myGraph.getBinaryTable().piEventReceived(be3);
+					this.myGraph.getFunctionTable().piEventReceived(be3);
+					break;
+				}
+				default:
+				{
+					break;
+				}
+			}
+		}
+		else if (be.getType() == PIEvent.CHANGED_BINARY_TABLE)
+		{
+			// This routine enables all entries in the next table
+
+			int drawMode = this.myGraph.getDrawMode();
+			if (drawMode != Defines.THREADS_BINARIES_FUNCTIONS)
+				return;
+
+			// we don't need to redraw the thread table, since it has not changed
+
+			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
+			Vector<ProfiledGeneric> traceBinaries  = trace.getIndexedBinaries();
+
+			int graphIndex = this.myGraph.getGraphIndex();
+			int startSampleIndex = trace.getStartSampleIndex();
+			int endSampleIndex   = trace.getEndSampleIndex();
+			double percentPerSample;
+			if (startSampleIndex == endSampleIndex)
+				percentPerSample = 0.0;
+			else
+				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
+
+			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
+
+			// get new function counts and loads
+			Vector<ProfiledGeneric> traceFunctions = trace.getIndexedFunctions();
+			Vector<ProfiledGeneric> graphFunctions = this.myGraph.getProfiledFunctions();
+			Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
+
+			// previous functions are not necessarily graphed this time
+			Enumeration<ProfiledGeneric> enu = graphFunctions.elements();
+			while (enu.hasMoreElements()) {
+				ProfiledFunction pFunction = (ProfiledFunction) enu.nextElement();
+				pFunction.setEnabled(graphIndex, false);
+			}
+			graphFunctions.clear();
+
+			ProfiledThreshold thresholdFunction = this.myGraph.getThresholdFunction();
+
+			if (thresholdFunction.isEnabled(graphIndex)) {
+				ArrayList<ProfiledGeneric> items = thresholdFunction.getItems(graphIndex);
+				// disable all items below the threshold
+				for (int i = 0; i < items.size(); i++) {
+					items.get(i).setEnabled(graphIndex, false);
+				}
+			}
+
+			GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+			// set up in case we find functions below the threshold
+			boolean lowFunction;
+			thresholdFunction.init(graphIndex);
+
+			for (int i = startSampleIndex; i < endSampleIndex; i++) {
+				GppSample sample = sortedSamples[i];
+
+				ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+				if (pBinary.isEnabled(graphIndex)) {
+					// function list is based on binaries
+					ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+					String functionName = pFunction.getNameString();
+
+					lowFunction = pFunction.getTotalSampleCount() < (Integer)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+
+					if (!foundFunctions.containsKey(functionName)) {
+						foundFunctions.put(functionName, functionName);
+						if (lowFunction) {
+							thresholdFunction.addItem(graphIndex, pFunction, 1);
+						} else {
+							pFunction.setEnabled(graphIndex, true);
+							pFunction.setSampleCount(graphIndex, 1);
+							graphFunctions.add(pFunction);
+						}
+					} else {
+						if (lowFunction)
+							thresholdFunction.incSampleCount(graphIndex);
+						else
+							pFunction.incSampleCount(graphIndex);
+					}
+				}
+			}
+
+			// set the % load
+			for (int i = 0; i < graphFunctions.size(); i++) {
+				ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
+				pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)*percentPerSample));
+			}
+			thresholdFunction.setLoadAndString(graphIndex,
+					(float)(thresholdFunction.getSampleCount(graphIndex)*percentPerSample));
+
+			// update the table items and redraw the table
+			this.myGraph.getFunctionTable().piEventReceived(be3);
+		}
+		else if (be.getType() == PIEvent.CHANGED_FUNCTION_TABLE)
+		{
+			// This routine enables all entries in the next table
+
+			int drawMode = this.myGraph.getDrawMode();
+			if (drawMode != Defines.THREADS_FUNCTIONS_BINARIES)
+				return;
+
+			// we don't need to redraw the thread table, since it has not changed
+
+			GppTrace trace = (GppTrace)(this.myGraph.getTrace());
+			Vector<ProfiledGeneric> traceFunctions = trace.getIndexedFunctions();
+
+			int graphIndex = this.myGraph.getGraphIndex();
+			int startSampleIndex = trace.getStartSampleIndex();
+			int endSampleIndex   = trace.getEndSampleIndex();
+			double percentPerSample;
+			if (startSampleIndex == endSampleIndex)
+				percentPerSample = 0.0;
+			else
+				percentPerSample = 100.0 / ((double)(endSampleIndex - startSampleIndex));
+
+			PIEvent be3 = new PIEvent(be.getValueObject(), PIEvent.SELECTION_AREA_CHANGED3);
+
+			// get new counts and loads
+			Vector<ProfiledGeneric> traceBinaries   = trace.getIndexedBinaries();
+			Vector<ProfiledGeneric> graphBinaries   = this.myGraph.getProfiledBinaries();
+			Hashtable<String,String> foundBinaries  = new Hashtable<String,String>();
+
+			// previous binaries are not necessarily graphed this time
+			Enumeration<ProfiledGeneric> enu = graphBinaries.elements();
+			while (enu.hasMoreElements()) {
+				ProfiledBinary pBinary = (ProfiledBinary) enu.nextElement();
+				pBinary.setEnabled(graphIndex, false);
+			}
+			graphBinaries.clear();
+
+			ProfiledThreshold thresholdBinary = this.myGraph.getThresholdBinary();
+
+			if (thresholdBinary.isEnabled(graphIndex)) {
+				ArrayList<ProfiledGeneric> items = thresholdBinary.getItems(graphIndex);
+				// disable all items below the threshold
+				for (int i = 0; i < items.size(); i++) {
+					items.get(i).setEnabled(graphIndex, false);
+				}
+			}
+
+			GppSample[] sortedSamples = trace.getSortedGppSamples();
+
+			// set up in case we find binaries below the threshold
+			boolean lowBinary;
+			thresholdBinary.init(graphIndex);
+
+			int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+			for (int i = startSampleIndex; i < endSampleIndex; i++) {
+				GppSample sample = sortedSamples[i];
+
+				ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+				if (pFunction.isEnabled(graphIndex)) {
+					// binary list is based on functions
+					ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+					String binaryName = pBinary.getNameString();
+
+					lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
+
+					if (!foundBinaries.containsKey(binaryName)) {
+						foundBinaries.put(binaryName, binaryName);
+						if (lowBinary) {
+							thresholdBinary.addItem(graphIndex, pBinary, 1);
+						} else {
+							pBinary.setEnabled(graphIndex, true);
+							pBinary.setSampleCount(graphIndex, 1);
+							graphBinaries.add(pBinary);
+						}
+					} else {
+						if (lowBinary)
+							thresholdBinary.incSampleCount(graphIndex);
+						else
+							pBinary.incSampleCount(graphIndex);
+					}
+				}
+			}
+
+			// set the % load
+			for (int i = 0; i < graphBinaries.size(); i++) {
+				ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
+				pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex)*percentPerSample));
+			}
+			thresholdBinary.setLoadAndString(graphIndex,
+					(float)(thresholdBinary.getSampleCount(graphIndex)*percentPerSample));
+
+			// update the table items and redraw the table
+			this.myGraph.getBinaryTable().piEventReceived(be3);
+		}
+	}
+
+	public void setSelectedNames()
+	{
+		Object[] selectedValues = this.tableViewer.getCheckedElements();
+        String[] threadNames = new String[selectedValues.length];
+
+        for (int i = 0; i < selectedValues.length; i++)
+		{
+			if (selectedValues[i] instanceof ProfiledThread)
+			{
+				ProfiledThread pt = (ProfiledThread)selectedValues[i];
+				threadNames[i] = pt.getNameString();
+			}
+		}
+
+        PIVisualSharedData shared = myGraph.getSharedDataInstance();
+		shared.GPP_SelectedThreadNames = threadNames;
+	}
+
+	private class SharedCheckHandler implements ICheckStateListener
+	{
+		public void checkStateChanged(CheckStateChangedEvent event) {
+
+       		if (!(event.getElement() instanceof ProfiledGeneric))
+       			return;
+       		
+       		// set the stored value to the checkbox value
+       		ProfiledGeneric pg = (ProfiledGeneric)event.getElement();
+	        pg.setEnabled(myGraph.getGraphIndex(), event.getChecked());
+ 
+	        // this table's set of checkbox-selected rows has changed, so propagate that information
+       		setSelectedNames();
+
+       		if (   (pg.getSampleCount(myGraph.getGraphIndex()) != 0)
+       			|| (myGraph.getDrawMode() == Defines.THREADS))
+       			selectionChangeNotify();
+
+       		table.deselectAll();
+		}
+	}
+
+	protected void selectionChangeNotify() {
+		PIEvent be = new PIEvent(null, PIEvent.CHANGED_THREAD_TABLE);
+		myGraph.piEventReceived(be);
+    }
+	
+	public void sortOnColumnSelection(TableColumn tableColumn) {
+			int columnId = ((Integer) tableColumn.getData()).intValue();
+            if (sortColumn == columnId) {
+            	// sort in other order
+            	sortAscending = !sortAscending;
+            } else {
+            	// sort in the default order
+				switch (columnId)
+				{
+					case COLUMN_ID_SHOW:
+					case COLUMN_ID_PERCENT_LOAD:
+					case COLUMN_ID_SAMPLE_COUNT:
+					case COLUMN_ID_PRIORITY:
+					{
+		            	// sort in descending order (for checked boxes column, this means selected boxes first)
+		            	sortAscending = false;
+		                break;
+					}
+					case COLUMN_ID_THREAD:
+					{
+		            	// sort in ascending order
+		            	sortAscending = true;
+		                break;
+					}
+					default:
+					{
+						return;
+					}
+				}
+            }
+
+			sortColumn = columnId;
+			quickSort(sortColumn, profiledThreads);
+	}
+
+	private class ColumnSelectionHandler extends SelectionAdapter
+	{
+		public void widgetSelected(SelectionEvent e)
+        {
+        	// wait for the previous sort to finish
+        	if (sorting || !(e.widget instanceof TableColumn))
+        		return;
+
+        	sortOnColumnSelection((TableColumn) e.widget);
+        }
+	}
+
+	public void updateProfiledAndItemData(boolean setInput)
+	{
+		tableItemData.clear();
+		profiledThreads.clear();
+
+		// profiledThreads and tableItemData contain one entry per table row
+		Enumeration<ProfiledGeneric> enu = myGraph.getProfiledThreads().elements();
+		while (enu.hasMoreElements())
+		{
+			ProfiledThread nextElement = (ProfiledThread)enu.nextElement();
+			tableItemData.add(nextElement);
+			profiledThreads.add(nextElement);
+		}
+
+		if (myGraph.getThresholdThread().getItemCount(myGraph.getGraphIndex()) != 0) {
+			tableItemData.add(myGraph.getThresholdThread());
+			profiledThreads.add(myGraph.getThresholdThread());
+		}
+		
+		// now sort the items in increasing total sample count, so that they graph correctly
+		Object[] sorted = myGraph.getProfiledThreads().toArray();
+		Arrays.sort(sorted, new Comparator<Object>() {
+			
+			public int compare(Object arg0, Object arg1)
+			{
+				if (arg0 instanceof ProfiledGeneric && arg1 instanceof ProfiledGeneric)
+					return ((ProfiledGeneric)arg0).getTotalSampleCount() -
+							((ProfiledGeneric)arg1).getTotalSampleCount();
+				else
+					return 0;
+			}
+		});
+
+		// now create the sorted list used to draw the graph
+		myGraph.getSortedThreads().clear();
+
+		if (myGraph.getThresholdThread().getItemCount(myGraph.getGraphIndex()) != 0)
+			myGraph.getSortedThreads().add(myGraph.getThresholdThread());
+
+		for (int i = 0; i < sorted.length; i++)
+			myGraph.getSortedThreads().add((ProfiledGeneric) sorted[i]);
+
+		// refresh the table, if needed
+		if (setInput)
+			refreshTableViewer();
+	}
+
+	public void quickSort(int sortBy, Vector<ProfiledGeneric> profiled)
+	{
+		if (profiled.size() == 0)
+			return;
+
+		this.sorting = true;
+
+		ProfiledGeneric pGeneric = profiled.elementAt(profiled.size() - 1);
+
+		if (pGeneric instanceof ProfiledThreshold) {
+			profiled.removeElementAt(profiled.size() - 1);
+		}
+
+		this.sorter.setupSort(sortBy, this.myGraph.getGraphIndex(), sortAscending);
+
+		switch (sortBy) {
+			case COLUMN_ID_SHOW:
+			{
+			    this.sorter.quickSortByShow(profiled);
+	            break;
+			}
+			case COLUMN_ID_PERCENT_LOAD:
+			{
+			    this.sorter.quickSortByAverageLoad(profiled);
+	            break;
+			}
+			case COLUMN_ID_THREAD:
+			{
+			    this.sorter.quickSortByThread(profiled);
+	            break;
+			}
+			case COLUMN_ID_BINARY:
+			{
+			    this.sorter.quickSortByBinary(profiled);
+	            break;
+			}
+			case COLUMN_ID_FUNCTION:
+			{
+			    this.sorter.quickSortByFunction(profiled);
+	            break;
+			}
+			case COLUMN_ID_SAMPLE_COUNT:
+			{
+			    this.sorter.quickSortBySampleCount(profiled);
+	            break;
+			}
+			case COLUMN_ID_PRIORITY:
+			{
+			    this.sorter.quickSortByPriority(profiled, priorityValues);
+	            break;
+			}
+			default:
+			{
+				break;
+			}
+		}
+ 		
+		Enumeration<ProfiledGeneric> e = this.sorter.getSortedList().elements();
+		tableItemData = setTableItemData(e);
+		if (pGeneric instanceof ProfiledThreshold) {
+			tableItemData.add(pGeneric);
+			profiled.add(pGeneric);
+		}
+		
+		// find the column corresponding to sortBy, and give it a column direction
+		// NOTE: treat sort by binary path then by binary name as sort by path
+		if (sortBy == COLUMN_ID_FULL_PATH)
+			sortBy = COLUMN_ID_PATH;
+		else if (sortBy == COLUMN_ID_FULL_IN_PATH)
+			sortBy = COLUMN_ID_IN_BINARY_PATH;
+
+		TableColumn sortByColumn = null;
+		for (int i = 0; i < this.table.getColumnCount(); i++) {
+			if (this.table.getColumn(i).getData() instanceof Integer) {
+				if (((Integer)this.table.getColumn(i).getData()) == sortBy) {
+					sortByColumn = this.table.getColumn(i);
+					break;
+				}
+			}
+		}
+
+		if (sortByColumn != null) {
+			this.table.setSortColumn(sortByColumn);
+			this.table.setSortDirection(sortAscending ? SWT.UP : SWT.DOWN);
+		}
+
+		refreshTableViewer();
+		this.sorting = false;
+	}
+
+	protected MenuItem getSavePrioritySamplesItem(Menu menu, boolean enabled) {
+	    MenuItem saveSamplesItem = new MenuItem(menu, SWT.PUSH);
+
+		saveSamplesItem.setText(Messages.getString("AddrThreadTable.savePrioritySamples")); //$NON-NLS-1$
+		saveSamplesItem.setEnabled(enabled);
+		
+		if (enabled) {
+			saveSamplesItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+					action("savePrioritySamples"); //$NON-NLS-1$
+				}
+			});
+		}
+
+		return saveSamplesItem;
+	}
+
+	protected Menu getTableMenu(Decorations parent, int graphIndex, int drawMode) {
+
+		// get rid of last Menu created so we don't have double menu
+		// in on click
+		if (contextMenu != null) {
+			contextMenu.dispose();
+		}
+		
+		// recreate each time, in case the drawMode has changed since creation
+		contextMenu = new Menu(parent, SWT.POP_UP);
+
+		// Use drawMode to determine the drill down items and
+		// whether to show a color column
+		addDrillDownItems(contextMenu, drawMode);
+		
+		// check and uncheck boxes
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getCheckRows(contextMenu, this.table.getSelectionCount() > 0);
+		
+		// select all, copy, and copy all
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getSelectAllItem(contextMenu, this.table.getItemCount() > 0);
+		getCopyItem(contextMenu, this.table.getSelectionCount() > 0);
+		getCopyTableItem(contextMenu, this.table.getItemCount() > 0);
+		
+		// copy drilldown tables, if in drilldown mode
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES:
+			case Defines.FUNCTIONS:
+				getCopyDrilldownItem(contextMenu, false);
+				break;
+			default:
+				getCopyDrilldownItem(contextMenu, true);
+				break;
+		}
+		
+		// save all and save drilldown tables, if in drilldown mode
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getSaveTableItem(contextMenu, this.table.getItemCount() > 0);
+		
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES:
+			case Defines.FUNCTIONS:
+				getSaveDrilldownItem(contextMenu, false);
+				break;
+			default:
+				getSaveDrilldownItem(contextMenu, true);
+				break;
+		}
+		
+		double startTime = PIPageEditor.currentPageEditor().getStartTime();
+		double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+
+		// save raw samples
+		boolean haveSamples = false;
+		for (int i = 0; !haveSamples && i < profiledThreads.size(); i++) {
+			ProfiledGeneric pg = profiledThreads.get(i);
+			haveSamples = pg.isEnabled(graphIndex) && pg.getSampleCount(graphIndex) > 0;
+		}
+		
+		if (!haveSamples || (startTime == -1) || (endTime   == -1) || (startTime == endTime))
+			getSaveSamplesItem(contextMenu, Messages.getString("AddrThreadTable.threads"), false); //$NON-NLS-1$
+		else
+			getSaveSamplesItem(contextMenu, Messages.getString("AddrThreadTable.threads"), true); //$NON-NLS-1$
+		
+		// save priority samples
+		if (priorityAdded) {
+			if (!haveSamples || (startTime == -1) || (endTime   == -1) || (startTime == endTime))
+				getSavePrioritySamplesItem(contextMenu, false);
+			else
+				getSavePrioritySamplesItem(contextMenu, true);
+		}
+
+		// recolor selected threads
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES_THREADS:
+			case Defines.BINARIES_FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_BINARIES_THREADS:
+			{
+				// recolor selected items
+				new MenuItem(contextMenu, SWT.SEPARATOR);
+				getRecolorItem(contextMenu, Messages.getString("AddressPlugin.threads"),  //$NON-NLS-1$
+								this.table.getSelectionCount() > 0);
+				break;
+			}
+			case Defines.THREADS_FUNCTIONS:
+			case Defines.THREADS_FUNCTIONS_BINARIES:
+			case Defines.THREADS_BINARIES:
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			case Defines.BINARIES_THREADS_FUNCTIONS:
+			case Defines.FUNCTIONS_THREADS_BINARIES:
+			{
+				break;
+			}
+			default:
+				break;
+		}
+
+		new MenuItem(contextMenu, SWT.SEPARATOR);
+		getChangeThresholds(contextMenu);
+
+		contextMenu.setVisible(true);
+		
+		return contextMenu;
+	}
+
+	protected void addPriorityColumn(Hashtable<Integer,String> priorities)
+	{
+		if (priorityAdded)
+			return;
+		
+		// store the priority information
+		this.priorityTable = priorities;
+	    priorityValues = new Hashtable<Integer,Integer>();
+		for (Enumeration<Integer> e = priorityTable.keys(); e.hasMoreElements();)
+		{
+			Integer key = e.nextElement();
+			priorityValues.put(key, parsePriorityValue(this.priorityTable.get(key)));
+		}
+
+		// if the tableViewer already exists, add a column
+		if (   (tableViewer != null)
+			&& (tableViewer.getTable() != null))
+	    {
+			Display.getDefault().syncExec( new Runnable() {
+				public void run() {
+					addPriorityColumn();
+				}
+			});	
+	    }
+
+		priorityAdded = true;
+	}
+	
+	private void addPriorityColumn()
+	{
+		TableColumn column;
+		column = new TableColumn(tableViewer.getTable(), SWT.LEFT);
+		column.setText(COLUMN_HEAD_PRIORITY);
+		column.setWidth(COLUMN_WIDTH_PRIORITY);
+		column.setData(new Integer(COLUMN_ID_PRIORITY));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+	}
+
+	private Integer parsePriorityValue(String priorityString)
+	{
+		if (priorityString == null || priorityString.equals(Messages.getString("AddrThreadTable.unsolvedPriority"))) //$NON-NLS-1$
+			return new Integer(Integer.MIN_VALUE);
+		else
+		{
+			int endIndex = priorityString.indexOf(Messages.getString("AddrThreadTable.priorityStringEnding")); //$NON-NLS-1$
+			int beginIndex = priorityString.indexOf(Messages.getString("AddrThreadTable.priorityStringStart")); //$NON-NLS-1$
+			String value = priorityString.substring(beginIndex+2, endIndex);
+			return new Integer(Integer.parseInt(value));
+		}
+	}
+
+    // class to pass sample data to the save wizard
+    public class SavePrioritySampleString implements ISaveSamples {
+    	int graphIndex;
+    	int drawMode;
+    	boolean done = false;
+    	
+    	public SavePrioritySampleString(int graphIndex, int drawMode) {
+    		this.graphIndex = graphIndex;
+    		this.drawMode   = drawMode;
+		}
+
+    	public String getData() {
+    		if (done)
+    			return null;
+    		
+			String returnString = getPrioritySampleString(graphIndex, drawMode);
+			done = true;
+			return returnString;
+		}
+
+		public String getData(int size) {
+ 			return getData();
+		}
+
+		public int getIndex() {
+			return done ? 1 : 0;
+		}
+
+		public void clear() {
+			done = false;
+		}
+    }
+    
+    protected class PrioritySample {
+    	int time;
+    	ProfiledThread pt;
+    	String priorityString;
+    	
+    	PrioritySample(int time, ProfiledThread pt, String priorityString) {
+    		this.time = time;
+    		this.pt   = pt;
+    		this.priorityString = priorityString;
+    	}
+    }
+
+    protected void createPrioritySample(ArrayList<PrioritySample> prioritySamples, int graphIndex, ProfiledThread pt, int startTime, int endTime) {
+    	PrioritySample localSample = null;
+    	boolean addedLocalSample = false;
+    	String priority = priorityTable.get(new Integer(pt.getThreadId()));
+		
+		if (priority == null) {
+			prioritySamples.add(new PrioritySample(0, pt, Messages.getString("AddrThreadTable.unknownPriority"))); //$NON-NLS-1$
+			return;
+		}
+		
+		localSample = new PrioritySample(0, pt, Messages.getString("AddrThreadTable.unrecordedPriority")); //$NON-NLS-1$
+		addedLocalSample = false;
+		
+		while (priority.indexOf('(') != -1) {
+			while (priority.charAt(0) == ' ')		// remove leading spaces
+				priority = priority.substring(1);
+			
+			int nextMatch = priority.indexOf('(');
+			String priorityStr = priority.substring(0, nextMatch);	// priority is before the open paren
+			priority = priority.substring(nextMatch + 1);			// consume the paren, too 
+			
+			nextMatch = priority.indexOf(')');
+			String timeStr = priority.substring(0, nextMatch - 1);
+			
+			double d = Double.parseDouble(timeStr) * 1000.0; 
+			int time = (int) d;
+			
+			if (time > endTime) {
+				// we're past the end
+				if (!addedLocalSample) {
+					// previous priority was before the start time, but include it anyway
+					prioritySamples.add(localSample);
+					return;
+				}
+			} else if (time < startTime) {
+				// we're before the start
+				// only keep the priority closest to the start time
+				localSample = new PrioritySample(time, pt, priorityStr);
+			} else {
+				// we're in the interval, so add the previous sample, if needed
+				if (!addedLocalSample && time != startTime)
+					prioritySamples.add(localSample);
+
+				localSample = new PrioritySample(time, pt, priorityStr);
+				prioritySamples.add(localSample);
+				addedLocalSample = true;
+			}
+			priority = priority.substring(nextMatch + 1);
+		}
+		
+		if (localSample != null && !addedLocalSample)
+			prioritySamples.add(localSample);
+    }
+    
+    protected class PrioritySampleCompare implements Comparator<PrioritySample> {
+    	public int compare(PrioritySample ps1, PrioritySample ps2) {
+    		try {
+    			if (ps1.time == ps2.time)
+    				return ps1.pt.getNameString().compareToIgnoreCase(ps2.pt.getNameString());
+    			else
+    				return ps1.time - ps2.time;
+    		} catch (Exception e) {
+    			return 0;
+    		}
+    	}
+    }
+    
+	protected String getPrioritySampleString(int graphIndex, int drawMode)
+	{
+		GppTraceGraph graph = (GppTraceGraph)(this.myGraph);
+		GppTrace trace = (GppTrace)(graph.getTrace());
+		
+		int startIndex = trace.getStartSampleIndex();
+		int endIndex   = trace.getEndSampleIndex();
+
+		ArrayList<PrioritySample> prioritySamples = new ArrayList<PrioritySample>();
+		ProfiledThread pt;
+		
+		for (int i = 0; i < profiledThreads.size(); i++) {
+			if (!profiledThreads.get(i).isEnabled(graphIndex) || profiledThreads.get(i).getSampleCount(graphIndex) <= 0)
+				continue;
+
+			if (profiledThreads.get(i) instanceof ProfiledThread) {
+				pt = (ProfiledThread) profiledThreads.get(i);
+
+				createPrioritySample(prioritySamples, graphIndex, pt, startIndex, endIndex); 
+			} else if (profiledThreads.get(i) instanceof ProfiledThreshold) {
+				ProfiledThreshold pth = (ProfiledThreshold) profiledThreads.get(i);
+				for (int j = 0; j < pth.getItems(graphIndex).size(); j++) {
+					pt = (ProfiledThread) pth.getItems(graphIndex).get(j);
+					
+					if (pt.isEnabled(graphIndex) && pt.getSampleCount(graphIndex) > 0)
+						createPrioritySample(prioritySamples, graphIndex, pt, startIndex, endIndex); 
+				}
+			}
+		}
+		
+		Collections.sort(prioritySamples, new PrioritySampleCompare());
+		
+		String returnString = "Time (ms),Thread,Priority\n";  //$NON-NLS-1$
+			
+			for (PrioritySample sample : prioritySamples) {
+				returnString +=   sample.time + "," + sample.pt.getNameString() + "," //$NON-NLS-1$ //$NON-NLS-2$
+								+ sample.priorityString + "\n";  //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		
+		return returnString;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddressPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,960 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.osgi.framework.BundleContext;
+
+import com.nokia.carbide.cpp.internal.pi.actions.SetThresholdsDialog;
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSample;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledBinary;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledFunction;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
+import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IRecordable;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IReportable;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IViewMenu;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable;
+import com.nokia.carbide.cpp.internal.pi.resolvers.SymbolFileFunctionResolver;
+import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
+import com.nokia.carbide.cpp.internal.pi.utils.PIUtilities;
+import com.nokia.carbide.cpp.internal.pi.visual.Defines;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.internal.pi.visual.GraphDrawRequest;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.pi.core.SessionPreferences;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.importer.SampleImporter;
+import com.nokia.carbide.cpp.pi.util.ColorPalette;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class AddressPlugin extends AbstractPiPlugin
+		implements ITrace, IViewMenu, IClassReplacer, //IExportItem,
+					IReportable, IRecordable, IVisualizable, IEventListener
+{
+	private static final String HELP_CONTEXT_ID = PIPageEditor.PI_ID + ".address";  //$NON-NLS-1$
+	
+//	private static HashMap<Integer,Long> uidToAddrThreadPeriod = new HashMap<Integer,Long>();
+
+	// There will be three graphs - one each for editor pages 0, 1, 2
+	// This code assumes that page 0 has the threads graph, 1 the binaries, and 2 the functions
+	private final static int GRAPH_COUNT = 3;
+	private boolean pagesCreated = false;
+
+	// The shared instance.
+	private static AddressPlugin plugin;
+
+	private int functionsShown = 10;
+
+	// string that should contain the maximum number of functions to display
+	private String functionCountString;
+
+	private static void setPlugin(AddressPlugin newPlugin)
+	{
+		plugin = newPlugin;
+	}
+
+	/**
+	 * The constructor.
+	 */
+	public AddressPlugin() {
+		super();
+		setPlugin(this);
+	}
+
+	public Class getTraceClass()
+	{
+		return GppTrace.class;
+	}
+
+	public Class getReplacedClass(String className)
+	{
+		if (   className.indexOf("com.nokia.carbide.cpp.pi.address.GppTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.model.GppTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("com.nokia.carbide.pi.address.GppTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.gppTracePlugin.GppTrace") != -1) //$NON-NLS-1$
+		{
+			return GppTrace.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.address.GppSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.address.GppSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.model.GppSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.gppTracePlugin.GppSample") != -1) //$NON-NLS-1$
+		{
+			return GppSample.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.address.GppThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.address.GppThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.model.GppThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.gppTracePlugin.GppThread") != -1) //$NON-NLS-1$
+		{
+			return GppThread.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.address.GppProcess") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.address.GppProcess") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.model.GppProcess") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.gppTracePlugin.GppProcess") != -1) //$NON-NLS-1$
+		{
+			return GppProcess.class;
+		}
+		else
+		{
+			return null;
+		}
+	}
+
+	public void initialiseTrace(GenericTrace genericTrace)
+	{
+		if (!(genericTrace instanceof GppTrace))
+			return;
+
+		GppTrace trace = (GppTrace)genericTrace;
+		
+		NpiInstanceRepository.getInstance().activeUidAddTrace("com.nokia.carbide.cpp.pi.address", trace); //$NON-NLS-1$
+		
+		// initialize the address/thread base sampling rate
+		int samplingInterval = 1;
+		if (trace.samples.size() > 2) {
+			// because of a problem in older samplers, the first address/thread sample may have been thrown out
+			samplingInterval = (int) (((GppSample) trace.samples.get(1)).sampleSynchTime - ((GppSample) trace.samples.get(0)).sampleSynchTime); 
+		}
+			
+		NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval", new Integer(samplingInterval)); //$NON-NLS-1$
+		
+		// make sure that the sorted samples array exists
+		if (trace.getSortedGppSamples() == null)
+			trace.sortGppSamples();
+
+		GppTraceGraph.refreshDataFromTrace(trace);
+		PIPageEditor.setTime(0.0f, 0.0f);
+		long lastSampleTime = trace.getSample(trace.samples.size() - 1).sampleSynchTime;
+		PIPageEditor.currentPageEditor().setMaxEndTime(((double)lastSampleTime) / 1000.0f);
+	}
+
+	public GppTrace getTrace()
+	{
+		return (GppTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.address"); //$NON-NLS-1$
+	}
+
+	public GenericTraceGraph getTraceGraph(int graphIndex)
+	{
+		GppTrace trace = (GppTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.address"); //$NON-NLS-1$
+		
+		if (trace != null) {
+			int uid = NpiInstanceRepository.getInstance().activeUid();
+			return trace.getTraceGraph(graphIndex, uid);
+		} else
+			return null;
+	}
+
+	public GenericTrace getTrace(int graphIndex)
+	{	
+		return (GenericTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.address"); //$NON-NLS-1$
+	}
+	
+/*
+	public GenericTraceGraph getTraceGraph(int graphIndex, int uid)
+	{	
+		GppTrace trace = (GppTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.address"); //$NON-NLS-1$
+
+		// if we already had it, then we can pass in the formatted trace data
+		return trace.getTraceGraph(graphIndex, uid);
+	}
+*/
+	
+	public Integer getLastSample(int graphIndex)
+	{
+		GppTrace trace = (GppTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.address"); //$NON-NLS-1$
+
+		if (trace == null)
+			return null;
+
+	  	//this sets GPP thread list visible by default
+	  	((GppTraceGraph)trace.getTraceGraph(graphIndex)).piEventReceived(new PIEvent(null, PIEvent.MOUSE_PRESSED));
+
+	  	return new Integer(trace.getLastSampleNumber());
+	}
+
+	public GraphDrawRequest getDrawRequest(int graphIndex) {
+		return null;
+	}
+
+	public void receiveSelectionEvent(String eventString)
+	{
+		if (eventString == null)
+			return;
+
+		int currentPage = PIPageEditor.currentPageIndex();
+
+		if (   (currentPage != PIPageEditor.THREADS_PAGE)
+			&& (currentPage != PIPageEditor.BINARIES_PAGE)
+			&& (currentPage != PIPageEditor.FUNCTIONS_PAGE))
+			  return;
+		
+		GppTrace trace = (GppTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.address"); //$NON-NLS-1$
+		
+		if (eventString.equals("fillSelected")) //$NON-NLS-1$
+	    {
+	    	PIEvent be = new PIEvent(null, PIEvent.SET_FILL_SELECTED_THREAD);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.THREADS_PAGE)).piEventReceived(be);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.BINARIES_PAGE)).piEventReceived(be);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).piEventReceived(be);
+	    	
+	    	NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.fillAll", Boolean.FALSE); //$NON-NLS-1$
+	    }
+		else if (eventString.equals("fillAll")) //$NON-NLS-1$
+		{
+			PIEvent be = new PIEvent(null, PIEvent.SET_FILL_ALL_THREADS);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.THREADS_PAGE)).piEventReceived(be);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.BINARIES_PAGE)).piEventReceived(be);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).piEventReceived(be);
+	    	
+	    	NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.fillAll", Boolean.TRUE); //$NON-NLS-1$
+		}
+		else if (eventString.equals("fillNone")) //$NON-NLS-1$
+		{
+			PIEvent be = new PIEvent(null, PIEvent.SET_FILL_OFF);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.THREADS_PAGE)).piEventReceived(be);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.BINARIES_PAGE)).piEventReceived(be);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).piEventReceived(be);
+	    	
+	    	NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.fillAll", Boolean.FALSE); //$NON-NLS-1$
+		}
+		else if (eventString.equals("setBarOn")) //$NON-NLS-1$
+		{
+			PIEvent be = new PIEvent(null, PIEvent.GPP_SET_BAR_GRAPH_ON);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.THREADS_PAGE)).piEventReceived(be);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.BINARIES_PAGE)).piEventReceived(be);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).piEventReceived(be);
+	    	
+	    	NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.bar", Boolean.TRUE); //$NON-NLS-1$
+		}
+		else if (eventString.equals("setBarOff")) //$NON-NLS-1$
+		{
+			PIEvent be = new PIEvent(null, PIEvent.GPP_SET_BAR_GRAPH_OFF);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.THREADS_PAGE)).piEventReceived(be);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.BINARIES_PAGE)).piEventReceived(be);
+	    	((GppTraceGraph)trace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).piEventReceived(be);
+	    	
+	    	NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.bar", Boolean.FALSE); //$NON-NLS-1$
+		}
+	  	else if (eventString.equals("resetToCurrentMode")) //$NON-NLS-1$
+	  	{
+	  		((GppTraceGraph)trace.getTraceGraph(currentPage)).action(eventString);
+	  	}
+	}
+
+	public String getTraceName() {
+		return "Address/Thread";	//$NON-NLS-1$
+	}
+
+	public int getTraceId() {
+		return 1;
+	}
+
+	public ParsedTraceData parseTraceFile(File file /*, ProgressBar progressBar*/) throws IOException
+	{
+//		progressBar.setString("Parsing address and thread trace");
+
+        GppTraceParser gppParser = new GppTraceParser();
+        ParsedTraceData parsed = gppParser.parse(file);
+        SymbolFileFunctionResolver sffp = this.resolveSymbolFileParser(/*progressBar*/);
+
+        parsed.functionResolvers = new FunctionResolver[]{sffp};
+
+        return parsed;
+	}
+
+	private SymbolFileFunctionResolver resolveSymbolFileParser(/*ProgressBar progressBar*/)
+    {
+        //        	progressBar.setString("Parsing symbol file");
+        //reads the symbol name path from configuration data
+        File symbolFile = new File(
+        		SampleImporter.getInstance().getRomSymbolFile());
+
+        SymbolFileFunctionResolver sffp = new SymbolFileFunctionResolver();
+        sffp.parseAndProcessSymbolFile(symbolFile);
+        return sffp;
+    }
+
+	public Hashtable<Integer,Object> getSummaryTable(double startTime, double endTime)
+	{
+		if (plugin == null)
+			return null;
+
+		// This code relies on currentPage being the same as graphIndex
+		int currentPage = PIPageEditor.currentPageIndex();
+
+		if (   (currentPage != PIPageEditor.THREADS_PAGE)
+			&& (currentPage != PIPageEditor.BINARIES_PAGE)
+			&& (currentPage != PIPageEditor.FUNCTIONS_PAGE))
+			  return null;
+
+		GppTrace trace = (GppTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.address"); //$NON-NLS-1$
+
+		Hashtable<Integer,Object> summary = new Hashtable<Integer,Object>();
+		Enumeration<ProfiledGeneric> e = trace.getSortedThreadsElements();
+		while (e.hasMoreElements())
+		{
+			Vector<Object> data = new Vector<Object>();
+			ProfiledThread pt = (ProfiledThread)e.nextElement();
+			data.add(pt.getNameString());
+			data.add(pt.getAverageLoadValueString(currentPage));
+			summary.put(new Integer(pt.getThreadId()), data);
+		}
+		return summary;
+	}
+
+	public String getGeneralInfo()
+	{
+		return null;
+	}
+
+	public ArrayList<String> getColumnNames()
+	{
+		ArrayList<String> names = new ArrayList<String>();
+		names.add(Messages.getString("AddressPlugin.0"));  //$NON-NLS-1$
+		names.add(Messages.getString("AddressPlugin.1"));  //$NON-NLS-1$
+		return names;
+	}
+
+	public ArrayList<Boolean> getColumnSortTypes()
+	{
+		ArrayList<Boolean> sortTypes = new ArrayList<Boolean>();
+		sortTypes.add(SORT_BY_NAME);
+		sortTypes.add(SORT_BY_NUMBER);
+		return sortTypes;
+	}
+
+	public String getActiveInfo(Object key, double startTime, double endTime)
+	{
+		int threadId;
+		if (key instanceof Integer)
+			threadId = ((Integer)key).intValue();
+		else
+			return null;
+		String threadName = ""; //$NON-NLS-1$
+		Hashtable<Integer,Object> tmpTable = this.getSummaryTable(startTime, endTime);
+		if (tmpTable != null)
+		{
+			threadName = (String)((Vector<Object>)tmpTable.get(key)).elementAt(0);
+		}
+
+		GppTrace trace = (GppTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.address"); //$NON-NLS-1$
+
+		Vector<GenericSample> samples = trace.getSamplesInsideTimePeriod((long)startTime, (long)endTime);
+		Hashtable<String,Integer> functionLoad = new Hashtable<String,Integer>();
+		int threadSampleAmount = 0;
+
+		for (Enumeration<GenericSample> e = samples.elements(); e.hasMoreElements();)
+		{
+			GppSample sample = (GppSample)e.nextElement();
+
+			String functionName = Messages.getString("AddressPlugin.2");  //$NON-NLS-1$
+
+			if (sample.currentFunctionSym != null)
+				functionName = sample.currentFunctionSym.functionName;
+			else if (sample.currentFunctionItt != null)
+				functionName = sample.currentFunctionItt.functionName;
+
+			if (sample.thread.threadId.intValue() == threadId)
+			{
+				Integer load = (Integer)functionLoad.get(functionName);
+				if (load != null)
+				{
+					functionLoad.remove(functionName);
+					functionLoad.put(functionName, new Integer(load.intValue()+1));
+				}
+				else
+				{
+					functionLoad.put(functionName, new Integer(1));
+				}
+				threadSampleAmount++;
+			}
+		}
+		float totalLoad = 0;
+		int functions = 0;
+//		int functionsShown = 10;
+		for (Enumeration<String> e = functionLoad.keys();e.hasMoreElements();)
+		{
+			String testFunction = e.nextElement();
+			float load = ((Integer)functionLoad.get(testFunction)).floatValue()*100/threadSampleAmount;
+			totalLoad += load;
+			functions++;
+		}
+
+		ArrayList<Object> sortedFunctions = new ArrayList<Object>();
+//		functionsShown = new Integer(functionsShownField.getText()).intValue();
+		while (functionLoad.size() != 0 && sortedFunctions.size() <= (functionsShown * 2) - 1)
+		{
+			String maxFunction = null;
+			int maxCount = 0;
+
+			for (Enumeration<String> e = functionLoad.keys(); e.hasMoreElements();)
+			{
+				String testFunction = e.nextElement();
+				int count = functionLoad.get(testFunction).intValue();
+				if (count > maxCount)
+				{
+					maxFunction = testFunction;
+					maxCount = count;
+				}
+			}
+			sortedFunctions.add(maxFunction);
+			sortedFunctions.add(new Integer(maxCount));
+			functionLoad.remove(maxFunction);
+		}
+
+		if (threadSampleAmount > 0)
+		{
+			String finalString = "\r\n" + Messages.getString("AddressPlugin.4")+threadName+"\r\n";   //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+			for (int i = 0; i < sortedFunctions.size(); )
+			{
+				String name = (String)sortedFunctions.get(i++);
+				//String percent = ((Integer)e.nextElement()).floatValue()*100/threadSampleAmount+"%";
+
+				float load = ((Integer)sortedFunctions.get(i++)).floatValue()*100/threadSampleAmount;
+				String percent = new Float(load/totalLoad*100).toString();
+
+				finalString += percent+"% "+name+"\r\n"; //$NON-NLS-1$ //$NON-NLS-2$ 
+			}
+
+			return finalString;
+		}
+		else return "\r\n"  + Messages.getString("AddressPlugin.8")+threadName+"\r\n";   //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+
+	public Action getIncludeAction()
+	{
+		return null;
+	}
+
+
+	public Action getExportAction() {
+		Action action = new Action(Messages.getString("AddressPlugin.10"), Action.AS_PUSH_BUTTON) {  //$NON-NLS-1$
+			public void run() {
+				ParsedTraceData ptd = TraceDataRepository.getInstance().getTrace(NpiInstanceRepository.getInstance().activeUid(), getTraceClass());
+				if (ptd != null) {
+					final GppTrace gppTraceTmp = (GppTrace)ptd.traceData;
+					final FileDialog dlg = new FileDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.SAVE);
+					
+					new Thread()
+					{
+						public void run()
+						{
+							dlg.setFilterNames(new String[] {
+									Messages.getString("AddressPlugin.11") + " (*.csv)"  //$NON-NLS-1$ //$NON-NLS-2$
+							});
+							dlg.setFilterExtensions(new String[] {
+									"*.csv" //$NON-NLS-1$
+							});
+							dlg.setText(Messages.getString("AddressPlugin.13"));  //$NON-NLS-1$
+
+							String fileName = dlg.open();
+							if (fileName == null) {
+								return;
+							}
+							
+							File file = new File(fileName);
+						    GppTraceCsvPrinter csvPrinter = new GppTraceCsvPrinter(gppTraceTmp);
+						    String csvPrint = csvPrinter.getCsvPrint();
+						    if (csvPrint != null)
+						    {
+						    	try {
+							        PIUtilities.saveCsvPrint(file, csvPrint);
+						    	}
+								catch (Exception e) 
+								{
+								    e.printStackTrace();
+								}
+						    }
+						}
+					}.start();
+				}
+			}
+		};
+
+		return action;
+	}
+
+	public MenuManager getReportGeneratorManager()
+	{
+		MenuManager reportManager;
+		Action reportAction;
+		
+		reportAction = new Action(Messages.getString("AddressPlugin.6")) {  //$NON-NLS-1$
+			public void run() {
+				Display display = PIPageEditor.currentPageEditor().getEditorSite().getShell().getDisplay();
+				Shell shell = new Shell(display);
+				shell.setText(Messages.getString("AddressPlugin.15"));  //$NON-NLS-1$
+				shell.setLayout(new FillLayout());
+				Text number = new Text(shell, SWT.BORDER);
+				number.setLayoutData(new FillLayout());
+				final Text numberFinal = number;
+				number.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {
+						functionCountString = numberFinal.getText();
+					}
+				});
+				shell.pack();
+				shell.open();
+				while (!shell.isDisposed()) {
+					if (!display.readAndDispatch()) {
+						display.sleep();
+					}
+				}
+				try {
+					functionsShown = Integer.parseInt(functionCountString);
+				} catch (NumberFormatException e1) {
+		        	GeneralMessages.showErrorMessage(Messages.getString("AddressPlugin.16"));  //$NON-NLS-1$
+				}
+			}
+		};
+		reportAction.setToolTipText(Messages.getString("AddressPlugin.17"));  //$NON-NLS-1$
+
+		// hook up to the PI toplevel menu
+		reportManager = new MenuManager(Messages.getString("AddressPlugin.3"));  //$NON-NLS-1$
+		reportManager.add(reportAction);
+		PIPageEditor.currentMenuManager().add(reportManager);
+
+		return reportManager;
+	}
+
+	public MenuManager getViewOptionManager()
+	{
+		Action action;
+		
+		MenuManager manager = new MenuManager(Messages.getString("AddressPlugin.5"));  //$NON-NLS-1$
+		
+		action = new Action(Messages.getString("AddressPlugin.7"), Action.AS_CHECK_BOX) {  //$NON-NLS-1$
+			public void run() {
+				if (this.isChecked())
+					receiveSelectionEvent("setBarOn"); //$NON-NLS-1$
+				else
+					receiveSelectionEvent("setBarOff"); //$NON-NLS-1$
+			}
+		};
+		
+		Boolean bar = SessionPreferences.getInstance().getBarMode();		// default value to session preference
+
+		Object obj;
+		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.bar"); //$NON-NLS-1$
+		if ((obj != null) && (obj instanceof Boolean))
+			// retrieve the current value
+			bar = (Boolean)obj;
+		else
+			// set the initial value
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.bar", bar); //$NON-NLS-1$
+
+		action.setChecked(bar);
+		action.setToolTipText("Show graph as vertical bars"); //$NON-NLS-1$
+		manager.add(action);
+		
+//		manager.add(new Separator());
+		
+		Boolean fillAll = SessionPreferences.getInstance().getFillAllEnabled();		// default value to session preference
+		
+		// if there is a value associated with the current Analyser tab, then use it
+		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.fillAll"); //$NON-NLS-1$
+		if ((obj != null) && (obj instanceof Boolean))
+			// retrieve the current value
+			fillAll = (Boolean)obj;
+		else
+			// set the initial value
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.fillAll", fillAll); //$NON-NLS-1$
+
+		action = new Action(Messages.getString("AddressPlugin.9"), Action.AS_CHECK_BOX) {  //$NON-NLS-1$
+			public void run() {
+				if (this.isChecked()) {
+					receiveSelectionEvent("fillAll"); //$NON-NLS-1$
+				} else {
+					receiveSelectionEvent("fillNone"); //$NON-NLS-1$
+				}
+			}
+		};
+		action.setChecked(fillAll);
+		action.setToolTipText(Messages.getString("AddressPlugin.22"));  //$NON-NLS-1$
+		manager.add(action);
+		
+//		manager.add(new Separator());
+//		
+//		action = new Action(Messages.getString("AddressPlugin.saveAddressThreadSamples"), Action.AS_PUSH_BUTTON) { //$NON-NLS-1$
+//			public void run() {
+//				new SaveSamplesWizard(Display.getCurrent());
+//			}
+//		};
+//		action.setToolTipText(Messages.getString("AddressPlugin.saveSamplesToolTip")); //$NON-NLS-1$
+//		manager.add(action);
+		
+		manager.add(new Separator());
+		
+		action = new Action(Messages.getString("AddressPlugin.12"), Action.AS_PUSH_BUTTON) {  //$NON-NLS-1$
+			public void run() {
+				new SetThresholdsDialog(Display.getCurrent());
+			}
+		};
+		action.setToolTipText(Messages.getString("AddressPlugin.24"));  //$NON-NLS-1$
+		manager.add(action);
+
+		return manager;
+	}
+
+	public Serializable getAdditionalData()
+	{
+		if (plugin == null)
+			return null;
+
+		GppTrace trace = (GppTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.address"); //$NON-NLS-1$
+		
+		if (trace == null)
+			return null;
+
+		Vector<Object> wrapper = new Vector<Object>();
+		
+		Hashtable<Integer,java.awt.Color> threadColors = new Hashtable<Integer,java.awt.Color>();
+		Hashtable<String,java.awt.Color> binaryColors  = new Hashtable<String,java.awt.Color>();
+		Enumeration<ProfiledGeneric> e = trace.getSortedThreadsElements();
+		while (e.hasMoreElements())
+		{
+			ProfiledThread pt = (ProfiledThread)e.nextElement();
+			// backward compatibility with old Swing Color
+			java.awt.Color tmpAWTColor = new java.awt.Color(pt.getColor().getRed(),pt.getColor().getGreen(),pt.getColor().getBlue());
+			threadColors.put(new Integer(pt.getThreadId()), tmpAWTColor);
+		}
+		e = trace.getSortedBinariesElements();
+		while (e.hasMoreElements())
+		{
+			ProfiledBinary pb = (ProfiledBinary)e.nextElement();
+			// backward compatibility with old Swing Color
+			java.awt.Color tmpAWTColor = new java.awt.Color(pb.getColor().getRed(),pb.getColor().getGreen(),pb.getColor().getBlue());
+			binaryColors.put(pb.getNameString(), tmpAWTColor);
+		}
+
+		e = trace.getSortedFunctionsElements();
+		
+		Hashtable<String,java.awt.Color> functionColors  = new Hashtable<String,java.awt.Color>();
+
+		while (e.hasMoreElements())
+		{
+			ProfiledFunction pb = (ProfiledFunction)e.nextElement();
+			// backward compatibility with old Swing Color
+			java.awt.Color tmpAWTColor = new java.awt.Color(pb.getColor().getRed(),pb.getColor().getGreen(),pb.getColor().getBlue());
+			functionColors.put(pb.getNameString(), tmpAWTColor);
+		}
+		
+		wrapper.add(threadColors);
+		wrapper.add(binaryColors);
+		wrapper.add(functionColors);
+		return wrapper;
+	}
+
+	public void setAdditionalData(int graphIndex, Serializable data)
+	{
+		if (!(data instanceof Vector))
+			return;
+		
+		try {
+			final GppTrace trace = (GppTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.address"); //$NON-NLS-1$
+
+			Vector<Object> tmpData = (Vector<Object>)data;
+			Hashtable<Integer,java.awt.Color> threadColors = (Hashtable<Integer,java.awt.Color>)tmpData.elementAt(0);
+			Hashtable<String,java.awt.Color> binaryColors = (Hashtable<String,java.awt.Color>)tmpData.elementAt(1);
+			Hashtable<String,java.awt.Color> functionColors = (Hashtable<String,java.awt.Color>)tmpData.elementAt(2);
+
+			boolean changed;
+			Enumeration<ProfiledGeneric> e;
+			
+			changed = false;
+			e = trace.getSortedThreadsElements();
+			while (e.hasMoreElements())
+			{
+				ProfiledThread pt = (ProfiledThread)e.nextElement();
+				// backward compatibility with old Swing Color
+				java.awt.Color tmpAWTColor = threadColors.get(new Integer(pt.getThreadId()));
+				if (tmpAWTColor != null) {
+					Color color = ColorPalette.getColor(new RGB(tmpAWTColor.getRed(), tmpAWTColor.getGreen(), tmpAWTColor.getBlue()));
+					if (color != null) {
+						pt.setColor(color);
+						changed = true;
+					}
+				}
+			}
+			
+			final int uid = NpiInstanceRepository.getInstance().activeUid();
+
+			if (changed) {
+				// need to provide new colors for the thread load table
+				trace.getGppGraph(PIPageEditor.THREADS_PAGE, uid).getThreadTable().addColor(Defines.THREADS);
+			}
+
+			changed = false;
+			e = trace.getSortedBinariesElements();
+			while (e.hasMoreElements())
+			{
+				ProfiledBinary pb = (ProfiledBinary)e.nextElement();
+				// backward compatibility with old Swing Color
+				java.awt.Color tmpAWTColor = binaryColors.get(pb.getNameString());
+				if (tmpAWTColor != null) {
+					Color color = ColorPalette.getColor(new RGB(tmpAWTColor.getRed(), tmpAWTColor.getGreen(), tmpAWTColor.getBlue()));
+					if (color != null) {
+						pb.setColor(color);
+						changed = true;
+					}
+				}
+			}
+
+			if (changed) {
+				// need to provide new colors for the binary load table
+				trace.getGppGraph(PIPageEditor.BINARIES_PAGE, uid).getBinaryTable().addColor(Defines.BINARIES);
+			}
+			
+			changed = false;
+			e = trace.getSortedFunctionsElements();
+			while (e.hasMoreElements())
+			{
+				ProfiledFunction pb = (ProfiledFunction)e.nextElement();
+				// backward compatibility with old Swing Color
+				java.awt.Color tmpAWTColor = functionColors.get(pb.getNameString());
+				if (tmpAWTColor != null) {
+					Color color = ColorPalette.getColor(new RGB(tmpAWTColor.getRed(), tmpAWTColor.getGreen(), tmpAWTColor.getBlue()));
+					if (color != null) {
+						pb.setColor(color);
+						changed = true;
+					}
+				}
+			}
+
+			if (changed) {
+				// need to provide new colors for the binary load table
+				trace.getGppGraph(PIPageEditor.FUNCTIONS_PAGE, uid).getFunctionTable().addColor(Defines.FUNCTIONS);
+			}
+			
+		} catch (Exception e) {
+			System.out.println("Could not load additional address/thread data!"); //$NON-NLS-1$
+//			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		setPlugin(null);
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static AddressPlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractPiPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi.address", path); //$NON-NLS-1$
+	}
+
+	// number of graphs supplied by this plugin
+	public int getGraphCount() {
+		return GRAPH_COUNT;
+	}
+
+	// page number of each graph supplied by this plugin
+	public int getPageNumber(int graphIndex) {
+		if (graphIndex == 0)
+			return PIPageEditor.THREADS_PAGE;
+		else if (graphIndex == 1)
+			return PIPageEditor.BINARIES_PAGE;
+		else if (graphIndex == 2)
+			return PIPageEditor.FUNCTIONS_PAGE;
+
+		return PIPageEditor.NEXT_AVAILABLE_PAGE;
+	}
+
+	// return whether this plugin's editor pages have been created
+	public boolean arePagesCreated() {
+		return this.pagesCreated;
+	}
+	
+	// set whether this plugin's editor pages have been created
+	public void setPagesCreated(boolean pagesCreated) {
+		this.pagesCreated = pagesCreated;
+	}
+
+	// number of editor pages to create
+	public int getCreatePageCount() {
+		return GRAPH_COUNT;
+	}
+
+	// editor page index for each created editor page
+	public int getCreatePageIndex(int index) {
+		if (index == 0)
+			return PIPageEditor.THREADS_PAGE;
+		else if (index == 1)
+			return PIPageEditor.BINARIES_PAGE;
+		else if (index == 2)
+			return PIPageEditor.FUNCTIONS_PAGE;
+
+		return PIPageEditor.NEXT_AVAILABLE_PAGE;
+	}
+
+	// page index actually assigned to a created page
+	public void setPageIndex(int index, int pageIndex) {
+		// if we didn't get pages 0, 1, and 2, we're in trouble
+	}
+
+	// create the page(s)
+	public ProfileVisualiser createPage(int index) {
+		String pageName = null;
+		String pageHelp = null;
+		Composite parent = NpiInstanceRepository.getInstance().activeUidGetParentComposite();
+		
+		if (parent == null) {
+			// no parent composite is only for temp instance used by non-GUI importer
+			GeneralMessages.showErrorMessage("Address trace failed to create UI"); //$NON-NLS-1$
+			return null;
+		}
+
+		if (index == 0) {
+			pageName = "Threads"; //$NON-NLS-1$
+			pageHelp = "threadsPageContext"; //$NON-NLS-1$
+		} else if (index == 1) {
+			pageName = "Binaries"; //$NON-NLS-1$
+			pageHelp = "binariesPageContext"; //$NON-NLS-1$
+		} else if (index == 2) {
+			pageName = "Functions"; //$NON-NLS-1$
+			pageHelp = "functionsPageContext"; //$NON-NLS-1$
+		} else {
+			return null;
+		}
+
+		ProfileVisualiser pV = new ProfileVisualiser(ProfileVisualiser.TOP_AND_BOTTOM, parent, pageName);
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+		AnalysisInfoHandler infoHandler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+		pV.getParserRepository().setPIAnalysisInfoHandler(infoHandler);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(pV.getContentPane(), HELP_CONTEXT_ID + "." + pageHelp); //$NON-NLS-1$
+
+		return pV;
+	}
+
+	public void receiveEvent(String action, Event event) {
+		if (action.equals("scroll")) { //$NON-NLS-1$
+			if (   !(event.data instanceof String)
+				|| !((String)event.data).equals("FigureCanvas")) //$NON-NLS-1$
+				return;
+			
+			// the currently visible page has scrolled, so scroll the other pages
+			ArrayList<ProfileVisualiser> pages = NpiInstanceRepository.getInstance().activeUidGetProfilePages();
+			ProfileVisualiser pV;
+
+			int currentPV = PIPageEditor.currentPageIndex();
+			if (currentPV != PIPageEditor.THREADS_PAGE) {
+				pV = pages.get(PIPageEditor.THREADS_PAGE);
+				pV.getTopComposite().setScrolledOrigin(event.x, event.y);
+			}
+			if (currentPV != PIPageEditor.BINARIES_PAGE) {
+				pV = (ProfileVisualiser)pages.get(PIPageEditor.BINARIES_PAGE);
+				pV.getTopComposite().setScrolledOrigin(event.x, event.y);
+			}
+			if (currentPV != PIPageEditor.FUNCTIONS_PAGE) {
+				pV = (ProfileVisualiser)pages.get(PIPageEditor.FUNCTIONS_PAGE);
+				pV.getTopComposite().setScrolledOrigin(event.x, event.y);
+			}
+		} else if (action.equals("priority_init")) { //$NON-NLS-1$
+			// priority trace has been processed, so let the threads page know
+			Hashtable<Integer,String> priStringById = (Hashtable<Integer,String>)event.data;
+			
+			if (getTrace() == null)
+				return;
+
+			GppTraceGraph addressGraph = ((GppTraceGraph) getTrace().getTraceGraph(PIPageEditor.THREADS_PAGE));
+
+			if (addressGraph != null) {
+				addressGraph.updateThreadTablePriorities(priStringById);
+			}
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable#getGraphTitle(int)
+	 */
+	public String getGraphTitle(int graphIndex) {
+		return null;
+	}
+//	
+//	static public void putAddrThreadPeriod(long addrThreadPeriod) {
+//		uidToAddrThreadPeriod.put(NpiInstanceRepository.getInstance().activeUid(), addrThreadPeriod);
+//	}
+//	
+//	static public long getAddrThreadPeriod() {
+//		return uidToAddrThreadPeriod.get(NpiInstanceRepository.getInstance().activeUid());
+//	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/AddressReturnPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IReturnPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+
+
+public class AddressReturnPlugin implements IReturnPlugin {
+	public AbstractPiPlugin getPlugin() {
+		return AddressPlugin.getDefault();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GenericAddrTable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,1156 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.SubMenuManager;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.ide.IIDEActionConstants;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveTable;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledBinary;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledFunction;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
+import com.nokia.carbide.cpp.internal.pi.save.SaveTableWizard;
+import com.nokia.carbide.cpp.internal.pi.visual.Defines;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTable;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+public abstract class GenericAddrTable extends GenericTable
+{
+	protected GppTraceGraph myGraph;
+	protected Composite     parent;
+
+	// sorting column and order
+	protected int     sortColumn = COLUMN_ID_SAMPLE_COUNT;
+	protected boolean sortAscending;
+
+	protected GppTableSorter sorter;
+	protected boolean sorting = false;
+
+	abstract protected Menu getTableMenu(Decorations parent, int graphIndex, int drawMode);
+	
+	protected boolean isDrilldown = false;
+    
+	// menu items
+	protected Action selectAllAction;
+	protected Action copyTableAction;
+	protected Action copyAction;
+	protected Action copyDrilldownAction;
+	protected Action saveTableAction;
+	protected Action saveDrilldownAction;
+	
+	protected static int SAMPLES_AT_ONE_TIME = 1000;
+
+	// class to pass sample data to the save wizard
+    public class SaveSampleString implements ISaveSamples {
+     	int graphIndex;
+    	int drawMode;
+    	int startIndex = 0;
+    	
+    	public SaveSampleString(int graphIndex, int drawMode) {
+    		this.graphIndex = graphIndex;
+    		this.drawMode   = drawMode;
+		}
+
+    	public String getData() {
+    		return getData(SAMPLES_AT_ONE_TIME);
+		}
+
+		public String getData(int size) {
+			String returnString = getSampleString(graphIndex, drawMode, this.startIndex, this.startIndex + size);
+    		if (returnString == null)
+    			this.startIndex = 0;
+    		else
+    			this.startIndex += size;
+			return returnString;
+		}
+		
+		public int getIndex() {
+			return this.startIndex;
+		}
+
+		public void clear() {
+			this.startIndex = 0;
+		}
+    }
+	
+	protected MenuItem getSaveSamplesItem(Menu menu, String sampleType, boolean enabled) {
+	    MenuItem saveSamplesItem = new MenuItem(menu, SWT.PUSH);
+
+		saveSamplesItem.setText(Messages.getString("GenericAddrTable.saveSamples1") + sampleType + Messages.getString("GenericAddrTable.saveSamples2"));   //$NON-NLS-1$ //$NON-NLS-2$
+		saveSamplesItem.setEnabled(enabled);
+		
+		if (enabled) {
+			saveSamplesItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+					action("saveSamples"); //$NON-NLS-1$
+				}
+			});
+		}
+	
+		return saveSamplesItem;
+	}
+
+	public GppTraceGraph getGraph() {
+		return myGraph;
+	}
+
+	protected class TableMouseListener implements MouseListener
+	{
+		public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) {
+			if (e.button == MouseEvent.BUTTON1)
+			{
+				TableItem[] selectedItems = table.getSelection();
+				if (selectedItems.length == 0)
+					return;
+
+				if (selectedItems[0].getData() instanceof ProfiledGeneric)
+				{
+					ProfiledGeneric pg = (ProfiledGeneric)(selectedItems[0].getData());
+				    if (pg.isEnabled(myGraph.getGraphIndex()))
+				        action("remove"); //$NON-NLS-1$
+				    else
+				        action("add"); //$NON-NLS-1$
+				    action("doubleClick");  //$NON-NLS-1$
+				}
+			}
+		}
+
+		public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
+		}
+
+		public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
+			if (e.button == MouseEvent.BUTTON3) {
+				Menu menu = getTableMenu(table.getShell(), myGraph.getGraphIndex(), myGraph.getDrawMode());
+				menu.setLocation(parent.toDisplay(e.x + table.getLocation().x, e.y + table.getLocation().y));
+				table.setMenu(menu);
+			}
+		}
+	}
+
+	public void setVisualisationColumnVisible(boolean flag) {}
+
+	public void valueChanged(SelectionEvent e) {}
+
+	protected Vector<ProfiledGeneric> setTableItemData(Enumeration<ProfiledGeneric> enu) {
+	    Vector<ProfiledGeneric> tmpItems = new Vector<ProfiledGeneric>();
+
+	    while (enu.hasMoreElements())
+		{
+		    tmpItems.add(enu.nextElement());
+		}
+		return tmpItems;
+	}
+
+	protected void addDrillDownItems(Menu tableMenu, int drawMode)
+	{
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			{
+				// thread drill down items
+				threadItem        (tableMenu, true);
+				threadBinaryItem  (tableMenu, false);
+				threadFunctionItem(tableMenu, false);
+				break;
+			}
+			case Defines.THREADS_BINARIES:
+			{
+				// thread drill down items
+				threadItem              (tableMenu, false);
+				threadBinaryItem        (tableMenu, true);
+				threadBinaryFunctionItem(tableMenu, false);
+				break;
+			}
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			{
+				// thread drill down items
+				threadItem              (tableMenu, false);
+				threadBinaryItem        (tableMenu, false);
+				threadBinaryFunctionItem(tableMenu, true);
+				break;
+			}
+			case Defines.THREADS_FUNCTIONS:
+			{
+				// thread drill down items
+				threadItem             (tableMenu, false);
+				threadFunctionItem     (tableMenu, true);
+				newThreadFunctionBinary(tableMenu, false);
+				break;
+			}
+			case Defines.THREADS_FUNCTIONS_BINARIES:
+			{
+				// thread drill down items
+				threadItem             (tableMenu, false);
+				threadFunctionItem     (tableMenu, false);
+				newThreadFunctionBinary(tableMenu, true);
+				break;
+			}
+			case Defines.BINARIES:
+			{
+				// binary drill down items
+				binaryItem        (tableMenu, true);
+				binaryThreadItem  (tableMenu, false);
+				binaryFunctionItem(tableMenu, false);
+				break;
+			}
+			case Defines.BINARIES_THREADS:
+			{
+				// binary drill down items
+				binaryItem              (tableMenu, false);
+				binaryThreadItem        (tableMenu, true);
+				binaryThreadFunctionItem(tableMenu, false);
+				break;
+			}
+			case Defines.BINARIES_THREADS_FUNCTIONS:
+			{
+				// binary drill down items
+				binaryItem              (tableMenu, false);
+				binaryThreadItem        (tableMenu, false);
+				binaryThreadFunctionItem(tableMenu, true);
+				break;
+			}
+			case Defines.BINARIES_FUNCTIONS:
+			{
+				// binary drill down items
+				binaryItem              (tableMenu, false);
+				binaryFunctionItem      (tableMenu, true);
+				binaryFunctionThreadItem(tableMenu, false);
+				break;
+			}
+			case Defines.BINARIES_FUNCTIONS_THREADS:
+			{
+				// binary drill down items
+				binaryItem              (tableMenu, false);
+				binaryFunctionItem      (tableMenu, false);
+				binaryFunctionThreadItem(tableMenu, true);
+				break;
+			}
+			case Defines.FUNCTIONS:
+			{
+				// function drill down items 
+				functionItem      (tableMenu, true);
+				functionThreadItem(tableMenu, false);
+				functionBinaryItem(tableMenu, false);
+				break;
+			}
+			case Defines.FUNCTIONS_THREADS:
+			{
+				// function drill down items 
+				functionItem            (tableMenu, false);
+				functionThreadItem      (tableMenu, true);
+				functionThreadBinaryItem(tableMenu, false);
+				break;
+			}
+			case Defines.FUNCTIONS_THREADS_BINARIES:
+			{
+				// function drill down items 
+				functionItem            (tableMenu, false);
+				functionThreadItem      (tableMenu, false);
+				functionThreadBinaryItem(tableMenu, true);
+				break;
+			}
+			case Defines.FUNCTIONS_BINARIES:
+			{
+				// function drill down items 
+				functionItem            (tableMenu, false);
+				functionBinaryItem      (tableMenu, true);
+				functionBinaryThreadItem(tableMenu, false);
+				break;
+			}
+			case Defines.FUNCTIONS_BINARIES_THREADS:
+			{
+				// function drill down items 
+				functionItem            (tableMenu, false);
+				functionBinaryItem      (tableMenu, false);
+				functionBinaryThreadItem(tableMenu, true);
+				break;
+			}
+			default:
+				break;
+		}
+	}
+
+	/*
+	 * Find if any threads with checkboxes checked
+	 */
+	protected boolean haveCheckedThread(GppTrace trace, int graphIndex)
+	{
+		ProfiledThread pThread;
+		for (ProfiledGeneric pGeneric: trace.getIndexedThreads()) {
+			if (pGeneric instanceof ProfiledThread) {
+				pThread = (ProfiledThread) pGeneric;
+				if (pThread.isEnabled(graphIndex))
+					return true;
+			}
+		}
+		return false;
+	}
+	
+
+	/*
+	 * Find if any binaries with checkboxes checked
+	 */
+	protected boolean haveCheckedBinary(GppTrace trace, int graphIndex)
+	{
+		ProfiledBinary pBinary;
+		for (ProfiledGeneric pGeneric: trace.getIndexedBinaries()) {
+			if (pGeneric instanceof ProfiledBinary) {
+				pBinary = (ProfiledBinary) pGeneric;
+				if (pBinary.isEnabled(graphIndex))
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/*
+	 * Find if any functions with checkboxes checked
+	 */
+	protected boolean haveCheckedFunction(GppTrace trace, int graphIndex)
+	{
+		ProfiledFunction pFunction;
+		for (ProfiledGeneric pGeneric: trace.getIndexedFunctions()) {
+			if (pGeneric instanceof ProfiledFunction) {
+				pFunction = (ProfiledFunction) pGeneric;
+				if (pFunction.isEnabled(graphIndex))
+					return true;
+			}
+		}
+		return false;
+	}
+	
+	/* 
+	 * get list of matching samples based on draw mode 
+	 */
+	private ArrayList<GppSample> getMatchingSamples(int drawMode, GppTrace trace, int startIndex, int endIndex, int graphIndex)
+	{
+		ArrayList<GppSample> samplesArray = new ArrayList<GppSample>(endIndex - startIndex > 1000 ? 1000 : endIndex - startIndex);
+		Vector<ProfiledGeneric> traceThreads   = trace.getIndexedThreads();
+		Vector<ProfiledGeneric> traceBinaries  = trace.getIndexedBinaries();
+		Vector<ProfiledGeneric> traceFunctions = trace.getIndexedFunctions();
+		GppSample[] samples = trace.getSortedGppSamples();
+		GppSample sample;
+
+		switch (drawMode)
+		{
+		case Defines.THREADS:
+			for (int i = startIndex; i < endIndex; i++) {
+				sample = samples[i];
+				ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+				if (pThread.isEnabled(graphIndex))
+					samplesArray.add(sample);
+			}
+			break;
+		case Defines.BINARIES:
+			for (int i = startIndex; i < endIndex; i++) {
+				sample = samples[i];
+				ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+				if (pBinary.isEnabled(graphIndex))
+					samplesArray.add(sample);
+			}
+			break;
+		case Defines.FUNCTIONS:
+			for (int i = startIndex; i < endIndex; i++) {
+				sample = samples[i];
+				ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+				if (pFunction.isEnabled(graphIndex))
+					samplesArray.add(sample);
+			}
+			break;
+		case Defines.THREADS_BINARIES:
+		case Defines.BINARIES_THREADS:
+			for (int i = startIndex; i < endIndex; i++) {
+				sample = samples[i];
+				ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+				if (pThread.isEnabled(graphIndex)) {
+					ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+					if (pBinary.isEnabled(graphIndex)) {
+						samplesArray.add(sample);
+					}
+				}
+			}
+			break;
+		case Defines.THREADS_FUNCTIONS:
+		case Defines.FUNCTIONS_THREADS:
+			for (int i = startIndex; i < endIndex; i++) {
+				sample = samples[i];
+				ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+				if (pThread.isEnabled(graphIndex)) {
+					ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+					if (pFunction.isEnabled(graphIndex)) {
+						samplesArray.add(sample);
+					}
+				}
+			}
+			break;
+		case Defines.BINARIES_FUNCTIONS:
+		case Defines.FUNCTIONS_BINARIES:
+			for (int i = startIndex; i < endIndex; i++) {
+				sample = samples[i];
+				ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+				if (pBinary.isEnabled(graphIndex)) {
+					ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+					if (pFunction.isEnabled(graphIndex)) {
+						samplesArray.add(sample);
+					}
+				}
+			}
+			break;
+		case Defines.THREADS_FUNCTIONS_BINARIES:
+		case Defines.THREADS_BINARIES_FUNCTIONS:
+			for (int i = startIndex; i < endIndex; i++) {
+				sample = samples[i];
+				ProfiledThread pThread = (ProfiledThread) traceThreads.elementAt(sample.threadIndex);
+				if (pThread.isEnabled(graphIndex)) {
+					ProfiledBinary pBinary = (ProfiledBinary) traceBinaries.elementAt(sample.binaryIndex);
+					if (pBinary.isEnabled(graphIndex)) {
+						ProfiledFunction pFunction = (ProfiledFunction) traceFunctions.elementAt(sample.functionIndex);
+						if (pFunction.isEnabled(graphIndex)) {
+							samplesArray.add(sample);
+						}
+					}
+				}
+			}
+			break;
+		}
+		
+		samplesArray.trimToSize();
+		return samplesArray;
+	}
+
+	/*
+	 * return the thread, binary, or function samples selected in the interval 
+	 */
+	protected String getSampleString(int graphIndex, int drawMode, int startIndex, int endIndex)
+	{
+		boolean threads   = false;
+		boolean binaries  = false;
+		boolean functions = false;
+		GppTraceGraph graph = (GppTraceGraph)(this.myGraph);
+		GppTrace trace = (GppTrace)(graph.getTrace());
+
+		// The current graph shows either threads, binaries, or functions
+		switch (drawMode)
+		{
+		case Defines.THREADS:
+		case Defines.BINARIES_THREADS:
+		case Defines.BINARIES_FUNCTIONS_THREADS:
+		case Defines.FUNCTIONS_THREADS:
+		case Defines.FUNCTIONS_BINARIES_THREADS:
+			threads = true;
+			break;
+		case Defines.BINARIES:
+		case Defines.THREADS_BINARIES:
+		case Defines.THREADS_FUNCTIONS_BINARIES:
+		case Defines.FUNCTIONS_BINARIES:
+		case Defines.FUNCTIONS_THREADS_BINARIES:
+			binaries = true;
+			break;
+		case Defines.FUNCTIONS:
+		case Defines.THREADS_FUNCTIONS:
+		case Defines.THREADS_BINARIES_FUNCTIONS:
+		case Defines.BINARIES_FUNCTIONS:
+		case Defines.BINARIES_THREADS_FUNCTIONS:
+			functions = true;
+			break;
+		default:
+			break;
+		}
+
+		int startTime = trace.getStartSampleIndex();
+		int endTime   = trace.getEndSampleIndex();
+		
+		// check if we have returned everything
+		if (startIndex > (endTime - startTime))
+			return null;
+
+		ArrayList<GppSample> matchingSamples = getMatchingSamples(drawMode, trace, startTime, endTime, graphIndex);
+
+		String returnString = ""; //$NON-NLS-1$
+		
+		if (threads) {
+			Vector<ProfiledGeneric> traceThreads   = trace.getIndexedThreads();
+			if (startIndex == 0)
+				returnString = Messages.getString("GenericAddrTable.threadSampleHeading");  //$NON-NLS-1$
+			
+			for (int i = startIndex; i < matchingSamples.size() && i < endIndex; i++) {
+				GppSample sample = matchingSamples.get(i);
+				returnString +=   sample.sampleSynchTime + ",0x" + Long.toHexString(sample.programCounter) + ","	  //$NON-NLS-1$ //$NON-NLS-2$; $NON-NLS-2$;
+								+ traceThreads.get(sample.threadIndex).getNameString() + "\n";  //$NON-NLS-1$
+			}
+		} else if (binaries) {
+			if (startIndex == 0)
+				returnString = Messages.getString("GenericAddrTable.binarySampleHeading");  //$NON-NLS-1$
+			
+			for (int i = startIndex; i < matchingSamples.size() && i < endIndex; i++) {
+				GppSample sample = matchingSamples.get(i);
+				ProfiledBinary binary = (ProfiledBinary) trace.getIndexedBinaries().get(sample.binaryIndex);
+				returnString +=   sample.sampleSynchTime + ",0x" + Long.toHexString(sample.programCounter) + ","	  //$NON-NLS-1$ //$NON-NLS-2$; $NON-NLS-2$;
+								+ binary.getNameString() + "\n";  // $NON-NLS-1$; //$NON-NLS-1$
+			}
+		} else if (functions) {
+			if (startIndex == 0)
+				returnString = Messages.getString("GenericAddrTable.functionSampleHeading");  //$NON-NLS-1$
+			
+			for (int i = startIndex; i < matchingSamples.size() && i < endIndex; i++) {
+				GppSample sample = matchingSamples.get(i);
+				ProfiledFunction function = (ProfiledFunction) trace.getIndexedFunctions().get(sample.functionIndex);
+				returnString +=   sample.sampleSynchTime + ",0x" + Long.toHexString(sample.programCounter) + ",\""	  //$NON-NLS-1$ //$NON-NLS-2$; $NON-NLS-2$;
+								+ function.getNameString() + "\",0x" + Long.toHexString(function.getFunctionAddress()) + "\n";  //$NON-NLS-1$ //$NON-NLS-2$; $NON-NLS-2$;
+			}
+		}
+		
+		return returnString;
+	}
+
+	private void threadItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.threadOnly"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("thread-only"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void threadBinaryItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.threadBinary"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("thread-binary"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void threadBinaryFunctionItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.threadBinaryFunction"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("thread-binary-function"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void threadFunctionItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.threadFunction"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("thread-function"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void newThreadFunctionBinary(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.threadFunctionBinary"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("thread-function-binary"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void binaryItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.binaryOnly"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("binary-only"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void binaryThreadItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.binaryThread"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("binary-thread"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void binaryThreadFunctionItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.binaryThreadFunction"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("binary-thread-function"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void binaryFunctionItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.binaryFunction"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("binary-function"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void binaryFunctionThreadItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.binaryFunctionThread"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("binary-function-thread"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void functionItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.functionOnly"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("function-only"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void functionThreadItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.functionThread"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("function-thread"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void functionThreadBinaryItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.functionThreadBinary"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("function-thread-binary"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void functionBinaryItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.functionBinary"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("function-binary"); //$NON-NLS-1$
+			}
+		});
+	}
+
+	private void functionBinaryThreadItem(Menu menu, boolean chosen) {
+		MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
+		menuItem.setText(Messages.getString("GenericAddrTable.functionBinaryThread"));  //$NON-NLS-1$
+		menuItem.setSelection(chosen);
+		menuItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("function-binary-thread"); //$NON-NLS-1$
+			}
+		});
+	}
+	
+	protected String copyDrilldown(int tableCount, Table[] tables, String separator)
+	{	
+		// make sure it's a valid drilldown
+		if (   (tableCount < 2) || (tableCount > 3)
+			|| (tables[0] == null) || (tables[1] == null)
+			|| (tableCount == 2 && tables[2] != null)
+			|| (tableCount == 3 && tables[2] == null))
+			return ""; //$NON-NLS-1$
+		
+		String copyString = ""; //$NON-NLS-1$
+
+		// create the multiple table heading line (e.g., "Threads     Binaries")
+		// space them out based on how many columns are in their table
+		for (int i = 0; i < tableCount; i++) {
+			if (tables[i].getData() instanceof String) {
+				copyString += (String) (tables[i].getData());
+			}
+			for (int j = 0; j < tables[i].getColumnCount(); j++) {
+				copyString += separator;
+			}
+		}
+		copyString += "\n"; //$NON-NLS-1$
+		
+		// create the multiple table column headings
+		for (int i = 0; i < tableCount; i++) {
+			if (i != tableCount - 1) {
+				copyString += copyHeading(tables[i], CHECKBOX_NO_TEXT, separator, separator); //$NON-NLS-1$
+			} else {
+				copyString += copyHeading(tables[i], CHECKBOX_NO_TEXT, separator, "\n"); //$NON-NLS-1$
+			}
+		}
+		
+		// determine the row, column count, and column ordering in each table
+		int rowCount0      = tables[0].getItemCount();
+		int columnCount0   = tables[0].getColumnCount();
+		int[] columnOrder0 = tables[0].getColumnOrder();
+		boolean[] isHex0   = (boolean[]) tables[0].getData("isHex"); //$NON-NLS-1$
+		String emptyRow0 = ""; //$NON-NLS-1$
+
+		int rowCount1      = tables[1].getItemCount();
+		int columnCount1   = tables[1].getColumnCount();
+		int[] columnOrder1 = tables[1].getColumnOrder();
+		boolean[] isHex1   = (boolean[]) tables[1].getData("isHex"); //$NON-NLS-1$
+		String emptyRow1 = ""; //$NON-NLS-1$
+
+		int rowCount2      = tableCount > 2 ? tables[2].getItemCount() : 0;
+		int columnCount2   = tableCount > 2 ? tables[2].getColumnCount() : 0;
+		int[] columnOrder2 = tableCount > 2 ? tables[2].getColumnOrder() : null;
+		boolean[] isHex2   = tableCount > 2 ? ((boolean[]) tables[2].getData("isHex")) : null; //$NON-NLS-1$
+		String emptyRow2 = ""; //$NON-NLS-1$
+
+		// determine the number of multiple table rows (max of any table's rows) 
+		int rowCount = rowCount0 >= rowCount1 ? rowCount0 : rowCount1;
+		rowCount = rowCount > rowCount2 ? rowCount : rowCount2;
+		
+		// generate empty row strings, to speed things up
+		if (rowCount0 < rowCount) {
+			for (int j = 0; j < columnCount0 - 1; j++) {
+				emptyRow0 += separator;
+			}
+		}
+
+		if (rowCount1 < rowCount) {
+			for (int j = 0; j < columnCount1; j++) {
+				emptyRow1 += separator;
+			}
+		}
+
+		if ((tableCount > 2) && (rowCount2 < rowCount)) {
+			for (int j = 0; j < columnCount2; j++) {
+				emptyRow2 += separator;
+			}
+		}
+
+		// generate the rows
+		for (int i = 0; i < rowCount; i++) {
+			if (i < rowCount0) {
+				copyString += copyRow(isHex0, tables[0].getItem(i), CHECKBOX_NO_TEXT, columnCount0, columnOrder0, separator);
+			} else {
+				copyString += emptyRow0;
+			}
+			
+			if (i < rowCount1) {
+				copyString += separator + copyRow(isHex1, tables[1].getItem(i), CHECKBOX_NO_TEXT, columnCount1, columnOrder1, separator);
+			} else {
+				// NOTE: if this is the last table, or the 3rd table has nothing but empty
+				// rows left, we may not need to fill in these fields
+				copyString += emptyRow1;
+			}
+			
+			if (tableCount > 2) {
+				if (i < rowCount2) {
+					copyString += separator + copyRow(isHex2, tables[2].getItem(i), CHECKBOX_NO_TEXT, columnCount2, columnOrder2, separator);
+				} else {
+					// NOTE: we may not need to fill in the empty fields of the last table
+					copyString += emptyRow2;
+				}
+			}
+			
+			copyString += "\n"; //$NON-NLS-1$
+		}
+		
+		return copyString;
+	}
+	
+	// class to pass drilldown tables to the save wizard
+	class SaveDrillDownString implements ISaveTable {
+		private int tableCount;
+		private Table[] tables;
+		private String separator;
+		
+		public SaveDrillDownString(int tableCount, Table[] tables, String separator) {
+			this.tableCount = tableCount;
+			this.tables     = tables;
+			this.separator  = separator;
+		}
+
+		public String getData() {
+			return copyDrilldown(tableCount, tables, separator);
+		}
+	}
+	
+	public Table[] getDrillDownTables()
+	{
+		// copy all tables in a drilldown to the clipboard or save to a file
+		int drawMode = this.myGraph.getDrawMode();
+
+		int tableCount = 0;
+		Table[] tables = new Table[3];
+		
+		// determine which tables are in the drilldown
+		switch (drawMode)
+		{
+		case Defines.THREADS_BINARIES:
+			tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+			tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+			break;
+		case Defines.THREADS_BINARIES_FUNCTIONS:
+			tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+			tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+			tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+			break;
+		case Defines.THREADS_FUNCTIONS:
+			tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+			tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+			break;
+		case Defines.THREADS_FUNCTIONS_BINARIES:
+			tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+			tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+			tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+			break;
+		case Defines.BINARIES_THREADS:
+			tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+			tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+			break;
+		case Defines.BINARIES_THREADS_FUNCTIONS:
+			tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+			tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+			tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+			break;
+		case Defines.BINARIES_FUNCTIONS:
+			tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+			tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+			break;
+		case Defines.BINARIES_FUNCTIONS_THREADS:
+			tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+			tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+			tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+			break;
+		case Defines.FUNCTIONS_THREADS:
+			tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+			tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+			break;
+		case Defines.FUNCTIONS_THREADS_BINARIES:
+			tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+			tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+			tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+			break;
+		case Defines.FUNCTIONS_BINARIES:
+			tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+			tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+			break;
+		case Defines.FUNCTIONS_BINARIES_THREADS:
+			tables[tableCount++] = this.myGraph.getFunctionTable().getTable();
+			tables[tableCount++] = this.myGraph.getBinaryTable().getTable();
+			tables[tableCount++] = this.myGraph.getThreadTable().getTable();
+			break;
+		default:
+		}
+		
+		return tables;
+	}
+    
+    protected void actionCopyOrSaveDrilldown(boolean doCopy, String separator)
+    {
+		Table[] tables = getDrillDownTables();
+		
+		int tableCount = 0;
+		while ((tableCount < tables.length) && (tables[tableCount] != null))
+			tableCount++;
+		
+		
+		if (doCopy) {
+			// change the clipboard contents
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+			String copyString = copyDrilldown(tableCount, tables, separator);
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+		} else {
+			// save to a file
+			SaveDrillDownString getString = new SaveDrillDownString(tableCount, tables, separator);
+			WizardDialog dialog;
+			Wizard w = new SaveTableWizard(getString);
+			dialog = new WizardDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), w);
+	    	dialog.open();
+		}
+    }
+	
+	protected void createDefaultActions()
+	{
+		selectAllAction = new Action("SelectAll") { //$NON-NLS-1$
+			public void run() {
+				action("selectAll");  //$NON-NLS-1$
+			}
+		};
+		selectAllAction.setEnabled(true);
+
+		copyAction = new Action("Copy") { //$NON-NLS-1$
+			public void run() {
+				action("copy");  //$NON-NLS-1$
+			}
+		};
+		copyAction.setEnabled(false);
+
+		copyTableAction = new Action("CopyTable") { //$NON-NLS-1$
+			public void run() {
+				action("copyTable");  //$NON-NLS-1$
+			}
+		};
+		copyTableAction.setEnabled(true);
+		copyTableAction.setId("PICopyTable");  //$NON-NLS-1$
+		copyTableAction.setText(Messages.getString("GenericAddrTable.copyTable"));  //$NON-NLS-1$
+
+		copyDrilldownAction = new Action("CopyDrilldown") {  //$NON-NLS-1$
+			public void run() {
+				action("copyDrilldown");  //$NON-NLS-1$
+			}
+		};
+		copyDrilldownAction.setEnabled(false);
+		copyDrilldownAction.setId("PICopyDrilldown");  //$NON-NLS-1$
+		copyDrilldownAction.setText(Messages.getString("GenericAddrTable.copyDrilldownTables"));  //$NON-NLS-1$
+
+		saveTableAction = new Action("SaveTable") { //$NON-NLS-1$
+			public void run() {
+				action("saveTable");  //$NON-NLS-1$
+			}
+		};
+		saveTableAction.setEnabled(true);
+		saveTableAction.setId("PISaveTable");  //$NON-NLS-1$
+		saveTableAction.setText(Messages.getString("GenericAddrTable.saveTable")); //$NON-NLS-1$
+
+		saveDrilldownAction = new Action("SaveDrilldown") {  //$NON-NLS-1$
+			public void run() {
+				action("saveDrilldown");  //$NON-NLS-1$
+			}
+		};
+		saveDrilldownAction.setEnabled(false);
+		saveDrilldownAction.setId("PISaveDrilldown");  //$NON-NLS-1$
+		saveDrilldownAction.setText(Messages.getString("GenericAddrTable.saveDrilldownTables"));  //$NON-NLS-1$
+
+//		saveSamplesAction = new Action("SaveSamples") { //$NON-NLS-1$
+//			public void run() {
+//				action("saveSamples");  //$NON-NLS-1$
+//			}
+//		};
+//		saveSamplesAction.setEnabled(true);
+//		saveSamplesAction.setId("PISaveAddressSamples");  //$NON-NLS-1$
+//		saveSamplesAction.setText(Messages.getString("GenericAddrTable.23") + sampleType + Messages.getString("GenericAddrTable.24")); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+	
+	public void setIsDrilldown(boolean isDrilldown)
+	{
+		this.isDrilldown = isDrilldown;
+		copyDrilldownAction.setEnabled(isDrilldown);
+		saveDrilldownAction.setEnabled(isDrilldown);
+
+		// may need to clean up stale Edit & File menu entry for PICopyDrilldown and PISaveDrilldown 
+		if (!isDrilldown) {
+			IMenuManager editMenuManager = PIPageEditor.getActionBars().getMenuManager().findMenuUsingPath(IIDEActionConstants.M_EDIT);
+			
+	        if (editMenuManager instanceof SubMenuManager)
+	        {
+	        	IContributionManager editManager = ((SubMenuManager)editMenuManager).getParent();
+	        	ActionContributionItem item;
+	
+				editMenuManager.remove("PICopyDrilldown");  //$NON-NLS-1$
+	        	item = new ActionContributionItem(copyDrilldownAction);
+	        	item.setVisible(true);
+	        	editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+	
+				editMenuManager.remove("PICopyTable");  //$NON-NLS-1$
+	        	copyTableAction.setEnabled(table.getItemCount() > 0);
+	        	item = new ActionContributionItem(copyTableAction);
+	        	item.setVisible(true);
+	        	editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+	        }
+
+			IMenuManager fileMenuManager = PIPageEditor.getActionBars().getMenuManager().findMenuUsingPath(IIDEActionConstants.M_FILE);
+
+	        if (fileMenuManager instanceof SubMenuManager)
+	        {
+	        	IContributionManager fileManager = ((SubMenuManager)fileMenuManager).getParent();
+	        	ActionContributionItem item;
+	
+				fileMenuManager.remove("PISaveTable");  //$NON-NLS-1$
+	        	saveTableAction.setEnabled(table.getItemCount() > 0);
+	        	item = new ActionContributionItem(saveTableAction);
+	        	item.setVisible(true);
+	        	fileManager.insertAfter("saveAll", item); //$NON-NLS-1$
+	        	
+				fileMenuManager.remove("PISaveDrilldown");  //$NON-NLS-1$
+	        	item = new ActionContributionItem(saveDrilldownAction);
+	        	item.setVisible(true);
+	        	fileManager.insertAfter("PISaveTable", item); //$NON-NLS-1$
+	        	fileManager.update(true);
+	        }
+		}
+	}
+
+	protected MenuItem getCopyDrilldownItem(Menu menu, boolean enabled) {
+	    MenuItem copyDrilldownItem = new MenuItem(menu, SWT.PUSH);
+
+	    copyDrilldownItem.setText(Messages.getString("GenericAddrTable.copyDrilldownTables"));  //$NON-NLS-1$
+		copyDrilldownItem.setEnabled(enabled);
+		
+		if (enabled) {
+			copyDrilldownItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+					action("copyDrilldown"); //$NON-NLS-1$
+				}
+			});
+		}
+
+		return copyDrilldownItem;
+	}
+
+	protected MenuItem getSaveDrilldownItem(Menu menu, boolean enabled) {
+	    MenuItem saveDrilldownItem = new MenuItem(menu, SWT.PUSH);
+
+	    saveDrilldownItem.setText(Messages.getString("GenericAddrTable.saveDrilldownTables"));  //$NON-NLS-1$
+		saveDrilldownItem.setEnabled(enabled);
+		
+		if (enabled) {
+			saveDrilldownItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+					action("saveDrilldown"); //$NON-NLS-1$
+				}
+			});
+		}
+
+		return saveDrilldownItem;
+	}
+
+	protected class AddrTableFocusListener implements FocusListener
+	{
+		IAction oldSelectAllAction = null;
+		IAction oldCopyAction = null;
+
+		public void focusGained(org.eclipse.swt.events.FocusEvent arg0) {
+			IActionBars bars = PIPageEditor.getActionBars();
+			
+			// modify what is executed when Select All and Copy are called from the Edit menu
+			oldSelectAllAction = bars.getGlobalActionHandler(ActionFactory.SELECT_ALL.getId());
+			oldCopyAction = bars.getGlobalActionHandler(ActionFactory.COPY.getId());
+
+			bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
+			bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), selectAllAction);
+
+			copyAction.setEnabled(table.getSelectionCount() > 0);
+			selectAllAction.setEnabled(table.getItemCount() > 0);
+			bars.updateActionBars();
+			
+			// add to the Edit menu
+	        IMenuManager editMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_EDIT);
+
+	        if (editMenuManager instanceof SubMenuManager)
+	        {
+	        	IContributionManager editManager = ((SubMenuManager)editMenuManager).getParent();
+	        	ActionContributionItem item;
+
+				editMenuManager.remove("PICopyDrilldown");  //$NON-NLS-1$
+	        	item = new ActionContributionItem(copyDrilldownAction);
+	        	item.setVisible(true);
+	        	editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+
+				editMenuManager.remove("PICopyTable");  //$NON-NLS-1$
+	        	copyTableAction.setEnabled(table.getItemCount() > 0);
+	        	item = new ActionContributionItem(copyTableAction);
+	        	item.setVisible(true);
+	        	editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+	        }
+			
+			// add to the File menu
+	        IMenuManager fileMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_FILE);
+
+	        if (fileMenuManager instanceof SubMenuManager)
+	        {
+	        	IContributionManager fileManager = ((SubMenuManager)fileMenuManager).getParent();
+	        	ActionContributionItem item;
+
+				fileMenuManager.remove("PISaveTable");  //$NON-NLS-1$
+	        	saveTableAction.setEnabled(table.getItemCount() > 0);
+	        	item = new ActionContributionItem(saveTableAction);
+	        	item.setVisible(true);
+	        	fileManager.insertAfter("saveAll", item); //$NON-NLS-1$
+
+				fileMenuManager.remove("PISaveDrilldown");  //$NON-NLS-1$
+	        	item = new ActionContributionItem(saveDrilldownAction);
+	        	item.setVisible(true);
+	        	fileManager.insertAfter("PISaveTable", item); //$NON-NLS-1$
+	        }
+		}
+
+		public void focusLost(org.eclipse.swt.events.FocusEvent arg0) {
+			IActionBars bars = PIPageEditor.getActionBars();
+			bars.setGlobalActionHandler(ActionFactory.COPY.getId(), oldCopyAction);
+			bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), oldSelectAllAction);
+			bars.updateActionBars();
+
+			SubMenuManager editMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_EDIT);
+			editMenuManager.remove("PICopyTable");  //$NON-NLS-1$
+			editMenuManager.remove("PICopyDrilldown");  //$NON-NLS-1$
+
+			SubMenuManager fileMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_FILE);
+			fileMenuManager.remove("PISaveTable");  //$NON-NLS-1$
+			fileMenuManager.remove("PISaveDrilldown");  //$NON-NLS-1$
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppFunction.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import java.io.Serializable;
+
+public class GppFunction implements Serializable
+  {
+	private static final long serialVersionUID = -4412767529422953949L;
+	
+    public int appearances;
+    public String name;
+    public long address;
+    public String dllName;
+    public int popularityIndex;
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppProcess.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import java.io.Serializable;
+
+public class GppProcess implements Serializable
+  {
+	private static final long serialVersionUID =-6656535243043410817L;
+    public Integer id;
+    public String name;
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppSample.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampleWithFunctions;
+
+public class GppSample extends GenericSampleWithFunctions
+  {
+	private static final long serialVersionUID = -4003790244732811550L;
+
+	public int threadIndex;
+	public int binaryIndex;
+	public int functionIndex;
+	
+    public GppThread   thread;
+    public GppFunction function;
+    public long programCounter;
+    public SomMapping somMapping;
+    
+    public Function currentFunctionSym;    
+    public Function currentFunctionItt;
+    
+    public void resolveFunction(FunctionResolver res)
+    {
+    	if (res.getResolverName().equals("Symbol"))  //$NON-NLS-1$
+    	{
+    		this.currentFunctionSym = res.findFunctionForAddress(programCounter);
+    	}
+    	else if (res.getResolverName().equals("ITT"))  //$NON-NLS-1$
+    	{
+    		if (this.currentFunctionSym == null)
+    			this.currentFunctionItt = res.findFunctionForAddress(programCounter);
+    	}
+    }
+
+    public String toString()
+	  {
+	  	return "Gpp:#" + this.sampleSynchTime + " @0x"   //$NON-NLS-1$ //$NON-NLS-2$
+	  							  + Long.toHexString(this.programCounter) + " fS:"   //$NON-NLS-1$
+	  							  + this.currentFunctionSym != null ? this.currentFunctionSym.functionName : this.currentFunctionItt.functionName
+	  							  + " pr:" + this.thread.process.name + " th:"+ this.thread.threadName;  //$NON-NLS-1$ //$NON-NLS-2$
+	  }
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTableSorter.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,1419 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: 
+ *
+ */
+
+/*
+ * GppTableSorter.java
+ */
+package com.nokia.carbide.cpp.pi.address;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledFunction;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
+
+
+public class GppTableSorter
+{
+	private Vector<ProfiledGeneric> sortedList = null;
+//	private int columnID;
+	private int graphIndex;
+	private boolean sortAscending;
+	
+	public void setupSort(int columnID, int graphIndex, boolean sortAscending)
+	{
+//		this.columnID      = columnID;
+		this.graphIndex    = graphIndex;
+		this.sortAscending = sortAscending;
+	}
+
+    public boolean isSortedByLoad(Vector<ProfiledGeneric> v)
+	{
+    	//	  check if ProfiledGeneric vector is already sorted by load
+	  	int i = 0;
+		ProfiledGeneric tmp1 = null;
+		ProfiledGeneric tmp2 = null;
+		for (Enumeration e = v.elements(); e.hasMoreElements() ;i++)
+		{
+			tmp2 = (ProfiledGeneric)e.nextElement();
+			if (tmp1 != null)
+			{
+	      		float first  = tmp1.getPercentLoad(graphIndex);
+	      		float second = tmp2.getPercentLoad(graphIndex);
+
+	      		if ((first != second) && ((first < second) ^ sortAscending))
+				{
+					return false;
+				}
+			}
+			tmp1 = (ProfiledGeneric)v.elementAt(i);
+		}
+		return true;
+	}
+
+	public void quickSortByShow(Vector<ProfiledGeneric> elements)
+	{
+		Vector<ProfiledGeneric> v = elements;
+
+	  	if (!v.isEmpty())
+	    {
+	  		this.quickSortByShow(v, 0, v.size()-1);
+	    }
+
+	  	sortedList = v;
+	}
+
+	public void quickSortByAverageLoad(Vector<ProfiledGeneric> elements)
+	{
+	  	Vector<ProfiledGeneric> v = elements;
+
+	  	if (!v.isEmpty() & !isSortedByLoad(v))
+	    {
+	  		this.quickSortByAverageLoad(v, 0, v.size()-1);
+	    }
+
+	  	sortedList = v;
+	}
+
+	public void quickSortByName(Vector<ProfiledGeneric> elements, boolean caseSensitive)
+	{
+		Vector<ProfiledGeneric> v = elements;
+	  	if (!v.isEmpty())
+	    {
+	  		this.quickSortByName(v, 0, v.size()-1, caseSensitive);
+	    }
+
+	  	sortedList = v;
+	}
+
+	public void quickSortByThread(Vector<ProfiledGeneric> elements)
+	{
+		quickSortByName(elements, false);
+	}
+
+	public void quickSortByFunction(Vector<ProfiledGeneric> elements)
+	{
+		quickSortByName(elements, false);
+	}
+
+	public void quickSortByBinary(Vector<ProfiledGeneric> elements)
+	{
+		Vector<ProfiledGeneric> v = elements;
+
+	  	if (!v.isEmpty())
+	    {
+	  		this.quickSortByBinary(v, 0, v.size()-1);
+	    }
+
+	  	sortedList = v;
+	}
+
+	public void quickSortByBinaryPath(Vector<ProfiledGeneric> elements)
+	{
+		Vector<ProfiledGeneric> v = elements;
+
+	  	if (!v.isEmpty())
+	    {
+	  		this.quickSortByBinaryPath(v, 0, v.size()-1);
+	    }
+
+	  	sortedList = v;
+	}
+
+	public void quickSortByFullBinaryPath(Vector<ProfiledGeneric> elements)
+	{
+		Vector<ProfiledGeneric> v = elements;
+
+	  	if (!v.isEmpty())
+	    {
+	  		this.quickSortByFullBinaryPath(v, 0, v.size()-1);
+	    }
+
+	  	sortedList = v;
+	}
+
+	public void quickSortByStartAddress(Vector<ProfiledGeneric> elements)
+	{
+		Vector<ProfiledGeneric> v = elements;
+
+	  	if (!v.isEmpty())
+	    {
+	  		this.quickSortByStartAddress(v, 0, v.size()-1);
+	    }
+
+	  	sortedList = v;
+	}
+
+	public void quickSortByAssocBinary(Vector<ProfiledGeneric> elements)
+	{
+		Vector<ProfiledGeneric> v = elements;
+
+	  	if (!v.isEmpty())
+	    {
+	  		this.quickSortByAssocBinary(v, 0, v.size()-1);
+	    }
+
+	  	sortedList = v;
+	}
+
+	public void quickSortByAssocBinaryPath(Vector<ProfiledGeneric> elements)
+	{
+		Vector<ProfiledGeneric> v = elements;
+
+	  	if (!v.isEmpty())
+	    {
+	  		this.quickSortByAssocBinaryPath(v, 0, v.size()-1);
+	    }
+
+	  	sortedList = v;
+	}
+
+	public void quickSortByFullAssocBinaryPath(Vector<ProfiledGeneric> elements)
+	{
+		Vector<ProfiledGeneric> v = elements;
+
+	  	if (!v.isEmpty())
+	    {
+	  		this.quickSortByFullAssocBinaryPath(v, 0, v.size()-1);
+	    }
+
+	  	sortedList = v;
+	}
+
+	public void quickSortBySampleCount(Vector<ProfiledGeneric> elements)
+	{
+	  	Vector<ProfiledGeneric> v = elements;
+
+	  	if (!v.isEmpty())
+	    {
+	  		this.quickSortBySampleCount(v, 0, v.size()-1);
+	    }
+
+	  	sortedList = v;
+	}
+
+	public void quickSortByPriority(Vector<ProfiledGeneric> elements, Hashtable priorities)
+	{
+	    sortedList = new Vector<ProfiledGeneric>();
+	    Vector<ProfiledGeneric> v = elements;
+	  	int i = 0;
+		ProfiledThread tmp1 = null;
+		ProfiledThread tmp2 = null;
+		for (Enumeration e = v.elements(); e.hasMoreElements() ;i++)
+		{
+			tmp2 = (ProfiledThread)e.nextElement();
+			if (tmp1 != null)
+			{
+				Integer p1 = (Integer)priorities.get(new Integer(tmp1.getThreadId()));
+				Integer p2 = (Integer)priorities.get(new Integer(tmp2.getThreadId()));
+				p1 = (p1 == null) ? new Integer(Integer.MIN_VALUE) : p1;
+				p2 = (p2 == null) ? new Integer(Integer.MIN_VALUE) : p2;
+
+				if ((p1.compareTo(p2) != 0) && (p1.compareTo(p2) < 0) ^ sortAscending)
+				{
+					quickSortByPriority(v, 0, v.size()-1, priorities);
+
+					sortedList = v;
+					return;
+				}
+			}
+			tmp1 = (ProfiledThread)v.elementAt(i);
+		}
+		sortedList = v;
+		return;
+	}
+
+	private void quickSortByShow(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex)
+	{
+		int lowToHighIndex;
+	    int highToLowIndex;
+	    int pivotIndex;
+	    ProfiledGeneric pivotValue;  // change the values to suit your application
+	    ProfiledGeneric lowToHighValue;
+	    ProfiledGeneric highToLowValue;
+	    ProfiledGeneric parking;
+	    int newLowIndex;
+	    int newHighIndex;
+
+	    lowToHighIndex = lowIndex;
+	    highToLowIndex = highIndex;
+
+	    pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+	    pivotValue = (ProfiledGeneric)elements.elementAt(pivotIndex);
+
+	    newLowIndex = highIndex + 1;
+	    newHighIndex = lowIndex - 1;
+	    while ((newHighIndex + 1) < newLowIndex)
+	    {
+			lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+			while (lowToHighIndex < newLowIndex)
+			{
+				// chose false is less than true
+				// when sortAscending is true, sort from false to true
+	      		boolean first  = lowToHighValue.isEnabled(graphIndex);
+	      		boolean second = pivotValue.isEnabled(graphIndex);
+
+	      		if ((first == second) || ((!first && second) ^ sortAscending))
+	      			break;
+
+				newHighIndex = lowToHighIndex;
+			    lowToHighIndex ++;
+			    lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+			}
+			highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+			while (newHighIndex <= highToLowIndex)
+			{
+				// chose false is less than true
+				// when sortAscending is true, sort from false to true
+	      		boolean first  = highToLowValue.isEnabled(graphIndex);
+	      		boolean second = pivotValue.isEnabled(graphIndex);
+
+	      		if ((first == second) || ((first && !second) ^ sortAscending))
+	      			break;
+
+				newLowIndex = highToLowIndex;
+			    highToLowIndex --;
+			    highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+			}
+
+			// swap if needed
+			if (lowToHighIndex == highToLowIndex)
+			{
+				newHighIndex = lowToHighIndex;
+			}
+			else if (lowToHighIndex < highToLowIndex)
+			{
+	      		boolean low  = lowToHighValue.isEnabled(graphIndex);
+	      		boolean high = highToLowValue.isEnabled(graphIndex);
+				if ((low == high) || ((!low & high) ^ sortAscending)) // swap even if equal
+				{
+					if (low != high) {
+				    	parking = lowToHighValue;
+				    	elements.setElementAt(highToLowValue, lowToHighIndex);
+				    	elements.setElementAt(parking, highToLowIndex);
+					}
+
+			      	newLowIndex = highToLowIndex;
+			      	newHighIndex = lowToHighIndex;
+
+			      	lowToHighIndex ++;
+			      	highToLowIndex --;
+				}
+			}
+	    }
+
+	    // Continue recursion for parts that have more than one element
+	    if (lowIndex < newHighIndex)
+	    {
+	    	this.quickSortByShow(elements, lowIndex, newHighIndex); // sort lower subpart
+	    }
+	    if (newLowIndex < highIndex)
+	    {
+	    	this.quickSortByShow(elements, newLowIndex, highIndex); // sort higher subpart
+	    }
+	}
+
+	private void quickSortByAverageLoad(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex)
+	{
+		int lowToHighIndex;
+		int highToLowIndex;
+		int pivotIndex;
+		ProfiledGeneric pivotValue;  // change the values to suit your application
+		ProfiledGeneric lowToHighValue;
+		ProfiledGeneric highToLowValue;
+		ProfiledGeneric parking;
+		int newLowIndex;
+		int newHighIndex;
+
+		lowToHighIndex = lowIndex;
+		highToLowIndex = highIndex;
+		pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+		pivotValue = (ProfiledGeneric) elements.elementAt(pivotIndex);
+
+		newLowIndex = highIndex + 1;
+		newHighIndex = lowIndex - 1;
+		// loop until low meets high
+		while ((newHighIndex + 1) < newLowIndex) // loop until partition complete
+		{
+		  	lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+		  	while (lowToHighIndex < newLowIndex)
+		  	{
+		  		float first  = lowToHighValue.getPercentLoad(graphIndex);
+		    	float second = pivotValue.getPercentLoad(graphIndex);
+
+		    	if ((first == second) || ((first < second) ^ sortAscending))
+		    		break;
+
+			    newHighIndex = lowToHighIndex; // add element to lower part
+			    lowToHighIndex ++;
+			    lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+			}
+
+		    highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+		    while (newHighIndex <= highToLowIndex)
+		    {
+		    	float first  = highToLowValue.getPercentLoad(graphIndex);
+		    	float second = pivotValue.getPercentLoad(graphIndex);
+
+			    if ((first == second) || ((first > second) ^ sortAscending))
+			    	break;
+
+			    newLowIndex = highToLowIndex; // add element to higher part
+			    highToLowIndex --;
+			    highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+		    }
+
+		    // swap if needed
+		    if (lowToHighIndex == highToLowIndex) // one last element, may go in either part
+		    {
+				newHighIndex = lowToHighIndex; // move element arbitrary to lower part
+		    }
+		    else if (lowToHighIndex < highToLowIndex) // not last element yet
+		    {
+				float first  = lowToHighValue.getPercentLoad(graphIndex);
+				float second = highToLowValue.getPercentLoad(graphIndex);
+				if ((first == second) || ((first < second) ^ sortAscending))
+			    {
+			       	if (first != second) {
+			       		parking = lowToHighValue;
+				        elements.setElementAt(highToLowValue, lowToHighIndex);
+				        elements.setElementAt(parking, highToLowIndex);
+			       	}
+
+				    newLowIndex = highToLowIndex;
+				    newHighIndex = lowToHighIndex;
+
+				    lowToHighIndex ++;
+				    highToLowIndex --;
+			    }
+		    }
+		}
+
+		// Continue recursion for parts that have more than one element
+		if (lowIndex < newHighIndex)
+		{
+		  	// sort lower subpart
+		  	this.quickSortByAverageLoad(elements, lowIndex, newHighIndex);
+		}
+		if (newLowIndex < highIndex)
+		{
+		  	// sort higher subpart
+		  	this.quickSortByAverageLoad(elements, newLowIndex, highIndex);
+		}
+	}
+
+	private void quickSortByName(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex, boolean caseSensitive)
+	{
+		int lowToHighIndex;
+	    int highToLowIndex;
+	    int pivotIndex;
+	    ProfiledGeneric pivotValue;  // change the values to suit your application
+	    ProfiledGeneric lowToHighValue;
+	    ProfiledGeneric highToLowValue;
+	    ProfiledGeneric parking;
+	    int newLowIndex;
+	    int newHighIndex;
+	    int compareResult;
+
+	    lowToHighIndex = lowIndex;
+	    highToLowIndex = highIndex;
+
+	    pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+	    pivotValue = (ProfiledGeneric)elements.elementAt(pivotIndex);
+
+	    newLowIndex = highIndex + 1;
+	    newHighIndex = lowIndex - 1;
+	    while ((newHighIndex + 1) < newLowIndex)
+	    {
+			lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+			while (lowToHighIndex < newLowIndex)
+			{
+				if (caseSensitive)
+					compareResult = lowToHighValue.getNameString().compareTo(pivotValue.getNameString());
+				else
+					compareResult = lowToHighValue.getNameString().compareToIgnoreCase(pivotValue.getNameString());
+					
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+					break;
+
+				newHighIndex = lowToHighIndex;
+			    lowToHighIndex ++;
+			    lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+			}
+			highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+			while (newHighIndex <= highToLowIndex)
+			{
+				if (caseSensitive)
+					compareResult = highToLowValue.getNameString().compareTo(pivotValue.getNameString());
+				else
+					compareResult = highToLowValue.getNameString().compareToIgnoreCase(pivotValue.getNameString());
+					
+				if ((compareResult == 0) || ((compareResult > 0) ^ sortAscending))
+					break;
+
+				newLowIndex = highToLowIndex;
+			    highToLowIndex --;
+			    highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+			}
+
+			// swap if needed
+			if (lowToHighIndex == highToLowIndex)
+			{
+				newHighIndex = lowToHighIndex;
+			}
+			else if (lowToHighIndex < highToLowIndex)
+			{
+				if (caseSensitive)
+					compareResult = lowToHighValue.getNameString().compareTo(highToLowValue.getNameString());
+				else
+					compareResult = lowToHighValue.getNameString().compareToIgnoreCase(highToLowValue.getNameString());
+					
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+				{
+			    	if (compareResult != 0) {
+			    		parking = lowToHighValue;
+				    	elements.setElementAt(highToLowValue, lowToHighIndex);
+				    	elements.setElementAt(parking, highToLowIndex);
+			    	}
+
+			      	newLowIndex = highToLowIndex;
+			      	newHighIndex = lowToHighIndex;
+
+			      	lowToHighIndex ++;
+			      	highToLowIndex --;
+				}
+			}
+	    }
+
+	    // Continue recursion for parts that have more than one element
+	    if (lowIndex < newHighIndex)
+	    {
+	    	this.quickSortByName(elements, lowIndex, newHighIndex, caseSensitive); // sort lower subpart
+	    }
+	    if (newLowIndex < highIndex)
+	    {
+	    	this.quickSortByName(elements, newLowIndex, highIndex, caseSensitive); // sort higher subpart
+	    }
+	}
+
+	private void quickSortByBinary(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex)
+	{
+		int lowToHighIndex;
+	    int highToLowIndex;
+	    int pivotIndex;
+	    ProfiledGeneric pivotValue;  // change the values to suit your application
+	    ProfiledGeneric lowToHighValue;
+	    ProfiledGeneric highToLowValue;
+	    ProfiledGeneric parking;
+	    int newLowIndex;
+	    int newHighIndex;
+	    int compareResult;
+
+	    lowToHighIndex = lowIndex;
+	    highToLowIndex = highIndex;
+
+	    pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+	    pivotValue = (ProfiledGeneric)elements.elementAt(pivotIndex);
+
+	    String pivotName = pivotValue.getNameString();
+		int index = pivotName.lastIndexOf('\\');
+		if (index != -1)
+			pivotName = pivotName.substring(index);
+
+	    newLowIndex = highIndex + 1;
+	    newHighIndex = lowIndex - 1;
+	    while ((newHighIndex + 1) < newLowIndex)
+	    {
+			lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+			while (lowToHighIndex < newLowIndex)
+			{
+				String lowName = lowToHighValue.getNameString();
+				index = lowName.lastIndexOf('\\');
+				if (index != -1)
+					lowName = lowName.substring(index);
+
+				compareResult = lowName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+					break;
+
+				newHighIndex = lowToHighIndex;
+			    lowToHighIndex ++;
+			    lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+			}
+			highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+			while (newHighIndex <= highToLowIndex)
+			{
+				String highName = highToLowValue.getNameString();
+				index = highName.lastIndexOf('\\');
+				if (index != -1)
+					highName = highName.substring(index);
+
+				compareResult = highName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult > 0) ^ sortAscending))
+					break;
+
+				newLowIndex = highToLowIndex;
+			    highToLowIndex --;
+			    highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+			}
+
+			// swap if needed
+			if (lowToHighIndex == highToLowIndex)
+			{
+				newHighIndex = lowToHighIndex;
+			}
+			else if (lowToHighIndex < highToLowIndex)
+			{
+				String lowName = lowToHighValue.getNameString();
+				index = lowName.lastIndexOf('\\');
+				if (index != -1)
+					lowName = lowName.substring(index);
+
+				String highName = highToLowValue.getNameString();
+				index = highName.lastIndexOf('\\');
+				if (index != -1)
+					highName = highName.substring(index);
+
+				compareResult = lowName.compareToIgnoreCase(highName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+				{
+			    	if (compareResult != 0) {
+			    		parking = lowToHighValue;
+				    	elements.setElementAt(highToLowValue, lowToHighIndex);
+				    	elements.setElementAt(parking, highToLowIndex);
+			    	}
+
+			      	newLowIndex = highToLowIndex;
+			      	newHighIndex = lowToHighIndex;
+
+			      	lowToHighIndex ++;
+			      	highToLowIndex --;
+				}
+			}
+	    }
+
+	    // Continue recursion for parts that have more than one element
+	    if (lowIndex < newHighIndex)
+	    {
+	    	this.quickSortByBinary(elements, lowIndex, newHighIndex); // sort lower subpart
+	    }
+	    if (newLowIndex < highIndex)
+	    {
+	    	this.quickSortByBinary(elements, newLowIndex, highIndex); // sort higher subpart
+	    }
+	}
+
+	private void quickSortByBinaryPath(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex)
+	{
+		int lowToHighIndex;
+	    int highToLowIndex;
+	    int pivotIndex;
+	    ProfiledGeneric pivotValue;  // change the values to suit your application
+	    ProfiledGeneric lowToHighValue;
+	    ProfiledGeneric highToLowValue;
+	    ProfiledGeneric parking;
+	    int newLowIndex;
+	    int newHighIndex;
+	    int compareResult;
+
+	    lowToHighIndex = lowIndex;
+	    highToLowIndex = highIndex;
+
+	    pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+	    pivotValue = (ProfiledGeneric)elements.elementAt(pivotIndex);
+
+		String pivotName = pivotValue.getNameString();
+		int index = pivotName.lastIndexOf('\\');
+		if (index == -1)
+			pivotName = ""; //$NON-NLS-1$
+		else
+			pivotName = pivotName.substring(0, index);
+
+	    newLowIndex = highIndex + 1;
+	    newHighIndex = lowIndex - 1;
+	    while ((newHighIndex + 1) < newLowIndex)
+	    {
+			lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+			while (lowToHighIndex < newLowIndex)
+			{
+				String lowName = lowToHighValue.getNameString();
+				index = lowName.lastIndexOf('\\');
+				if (index == -1)
+					lowName = ""; //$NON-NLS-1$
+				else
+					lowName = lowName.substring(0, index);
+
+				compareResult = lowName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+					break;
+
+				newHighIndex = lowToHighIndex;
+			    lowToHighIndex ++;
+			    lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+			}
+			highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+			while (newHighIndex <= highToLowIndex)
+			{
+				String highName = highToLowValue.getNameString();
+				index = highName.lastIndexOf('\\');
+				if (index == -1)
+					highName = ""; //$NON-NLS-1$
+				else
+					highName = highName.substring(0, index);
+
+				compareResult = highName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult > 0) ^ sortAscending))
+					break;
+
+				newLowIndex = highToLowIndex;
+			    highToLowIndex --;
+			    highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+			}
+
+			// swap if needed
+			if (lowToHighIndex == highToLowIndex)
+			{
+				newHighIndex = lowToHighIndex;
+			}
+			else if (lowToHighIndex < highToLowIndex)
+			{
+				String lowName = lowToHighValue.getNameString();
+				index = lowName.lastIndexOf('\\');
+				if (index == -1)
+					lowName = ""; //$NON-NLS-1$
+				else
+					lowName = lowName.substring(0, index);
+
+				String highName = highToLowValue.getNameString();
+				index = highName.lastIndexOf('\\');
+				if (index == -1)
+					highName = ""; //$NON-NLS-1$
+				else
+					highName = highName.substring(0, index);
+
+				compareResult = lowName.compareToIgnoreCase(highName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+				{
+			    	if (compareResult != 0) {
+			    		parking = lowToHighValue;
+				    	elements.setElementAt(highToLowValue, lowToHighIndex);
+				    	elements.setElementAt(parking, highToLowIndex);
+			    	}
+
+			      	newLowIndex = highToLowIndex;
+			      	newHighIndex = lowToHighIndex;
+
+			      	lowToHighIndex ++;
+			      	highToLowIndex --;
+				}
+			}
+	    }
+
+	    // Continue recursion for parts that have more than one element
+	    if (lowIndex < newHighIndex)
+	    {
+	    	this.quickSortByBinaryPath(elements, lowIndex, newHighIndex); // sort lower subpart
+	    }
+	    if (newLowIndex < highIndex)
+	    {
+	    	this.quickSortByBinaryPath(elements, newLowIndex, highIndex); // sort higher subpart
+	    }
+	}
+
+	private void quickSortByFullBinaryPath(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex)
+	{
+		int lowToHighIndex;
+	    int highToLowIndex;
+	    int pivotIndex;
+	    ProfiledGeneric pivotValue;  // change the values to suit your application
+	    ProfiledGeneric lowToHighValue;
+	    ProfiledGeneric highToLowValue;
+	    ProfiledGeneric parking;
+	    int newLowIndex;
+	    int newHighIndex;
+	    int compareResult;
+
+	    lowToHighIndex = lowIndex;
+	    highToLowIndex = highIndex;
+
+	    pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+	    pivotValue = (ProfiledGeneric)elements.elementAt(pivotIndex);
+
+		String pivotName = pivotValue.getNameString();
+
+	    newLowIndex = highIndex + 1;
+	    newHighIndex = lowIndex - 1;
+	    while ((newHighIndex + 1) < newLowIndex)
+	    {
+			lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+			while (lowToHighIndex < newLowIndex)
+			{
+				String lowName = lowToHighValue.getNameString();
+
+				compareResult = lowName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+					break;
+
+				newHighIndex = lowToHighIndex;
+			    lowToHighIndex ++;
+			    lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+			}
+			highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+			while (newHighIndex <= highToLowIndex)
+			{
+				String highName = highToLowValue.getNameString();
+
+				compareResult = highName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult > 0) ^ sortAscending))
+					break;
+
+				newLowIndex = highToLowIndex;
+			    highToLowIndex --;
+			    highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+			}
+
+			// swap if needed
+			if (lowToHighIndex == highToLowIndex)
+			{
+				newHighIndex = lowToHighIndex;
+			}
+			else if (lowToHighIndex < highToLowIndex)
+			{
+				String lowName = lowToHighValue.getNameString();
+				String highName = highToLowValue.getNameString();
+
+				compareResult = lowName.compareToIgnoreCase(highName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+				{
+			    	if (compareResult != 0) {
+			    		parking = lowToHighValue;
+				    	elements.setElementAt(highToLowValue, lowToHighIndex);
+				    	elements.setElementAt(parking, highToLowIndex);
+			    	}
+
+			      	newLowIndex = highToLowIndex;
+			      	newHighIndex = lowToHighIndex;
+
+			      	lowToHighIndex ++;
+			      	highToLowIndex --;
+				}
+			}
+	    }
+
+	    // Continue recursion for parts that have more than one element
+	    if (lowIndex < newHighIndex)
+	    {
+	    	this.quickSortByFullBinaryPath(elements, lowIndex, newHighIndex); // sort lower subpart
+	    }
+	    if (newLowIndex < highIndex)
+	    {
+	    	this.quickSortByFullBinaryPath(elements, newLowIndex, highIndex); // sort higher subpart
+	    }
+	}
+
+	private void quickSortByStartAddress(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex)
+	{
+		int lowToHighIndex;
+	    int highToLowIndex;
+	    int pivotIndex;
+	    ProfiledFunction pivotValue;  // change the values to suit your application
+	    ProfiledFunction lowToHighValue;
+	    ProfiledFunction highToLowValue;
+	    ProfiledFunction parking;
+	    int newLowIndex;
+	    int newHighIndex;
+
+	    lowToHighIndex = lowIndex;
+	    highToLowIndex = highIndex;
+
+	    pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+	    pivotValue = (ProfiledFunction)elements.elementAt(pivotIndex);
+
+	    newLowIndex = highIndex + 1;
+	    newHighIndex = lowIndex - 1;
+	    while ((newHighIndex + 1) < newLowIndex)
+	    {
+			lowToHighValue = (ProfiledFunction)elements.elementAt(lowToHighIndex);
+			while (lowToHighIndex < newLowIndex)
+			{
+	      		long first  = lowToHighValue.getFunctionAddress();
+	      		long second = pivotValue.getFunctionAddress();
+
+	      		if ((first == second) || ((first < second) ^ sortAscending))
+	      			break;
+
+				newHighIndex = lowToHighIndex;
+			    lowToHighIndex ++;
+			    lowToHighValue = (ProfiledFunction)elements.elementAt(lowToHighIndex);
+			}
+			highToLowValue = (ProfiledFunction)elements.elementAt(highToLowIndex);
+			while (newHighIndex <= highToLowIndex)
+			{
+		      	long first  = highToLowValue.getFunctionAddress();
+		      	long second = pivotValue.getFunctionAddress();
+
+		      	if ((first == second) || ((first > second) ^ sortAscending))
+		      		break;
+
+				newLowIndex = highToLowIndex;
+			    highToLowIndex --;
+			    highToLowValue = (ProfiledFunction)elements.elementAt(highToLowIndex);
+			}
+
+			// swap if needed
+			if (lowToHighIndex == highToLowIndex)
+			{
+				newHighIndex = lowToHighIndex;
+			}
+			else if (lowToHighIndex < highToLowIndex)
+			{
+			    long first  = lowToHighValue.getFunctionAddress();
+			    long second = highToLowValue.getFunctionAddress();
+
+			    if ((first == second) || ((first < second) ^ sortAscending))
+				{
+			    	if (first != second) {
+			    		parking = lowToHighValue;
+				    	elements.setElementAt(highToLowValue, lowToHighIndex);
+				    	elements.setElementAt(parking, highToLowIndex);
+			    	}
+
+			      	newLowIndex = highToLowIndex;
+			      	newHighIndex = lowToHighIndex;
+
+			      	lowToHighIndex ++;
+			      	highToLowIndex --;
+				}
+			}
+	    }
+
+	    // Continue recursion for parts that have more than one element
+	    if (lowIndex < newHighIndex)
+	    {
+	    	this.quickSortByStartAddress(elements, lowIndex, newHighIndex); // sort lower subpart
+	    }
+	    if (newLowIndex < highIndex)
+	    {
+	    	this.quickSortByStartAddress(elements, newLowIndex, highIndex); // sort higher subpart
+	    }
+	}
+
+	private void quickSortByAssocBinary(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex)
+	{
+		int lowToHighIndex;
+	    int highToLowIndex;
+	    int pivotIndex;
+	    ProfiledFunction pivotValue;  // change the values to suit your application
+	    ProfiledFunction lowToHighValue;
+	    ProfiledFunction highToLowValue;
+	    ProfiledFunction parking;
+	    int newLowIndex;
+	    int newHighIndex;
+	    int compareResult;
+
+	    lowToHighIndex = lowIndex;
+	    highToLowIndex = highIndex;
+
+	    pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+	    pivotValue = (ProfiledFunction)elements.elementAt(pivotIndex);
+
+	    String pivotName = pivotValue.getFunctionBinaryName();
+		int index = pivotName.lastIndexOf('\\');
+		if (index != -1)
+			pivotName = pivotName.substring(index);
+
+	    newLowIndex = highIndex + 1;
+	    newHighIndex = lowIndex - 1;
+	    while ((newHighIndex + 1) < newLowIndex)
+	    {
+			lowToHighValue = (ProfiledFunction)elements.elementAt(lowToHighIndex);
+			while (lowToHighIndex < newLowIndex)
+			{
+				String lowName = lowToHighValue.getFunctionBinaryName();
+				index = lowName.lastIndexOf('\\');
+				if (index != -1)
+					lowName = lowName.substring(index);
+
+				compareResult = lowName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+					break;
+
+				newHighIndex = lowToHighIndex;
+			    lowToHighIndex ++;
+			    lowToHighValue = (ProfiledFunction)elements.elementAt(lowToHighIndex);
+			}
+			highToLowValue = (ProfiledFunction)elements.elementAt(highToLowIndex);
+			while (newHighIndex <= highToLowIndex)
+			{
+				String highName = highToLowValue.getFunctionBinaryName();
+				index = highName.lastIndexOf('\\');
+				if (index != -1)
+					highName = highName.substring(index);
+
+				compareResult = highName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult > 0) ^ sortAscending))
+					break;
+
+				newLowIndex = highToLowIndex;
+			    highToLowIndex --;
+			    highToLowValue = (ProfiledFunction)elements.elementAt(highToLowIndex);
+			}
+
+			// swap if needed
+			if (lowToHighIndex == highToLowIndex)
+			{
+				newHighIndex = lowToHighIndex;
+			}
+			else if (lowToHighIndex < highToLowIndex)
+			{
+				String lowName = lowToHighValue.getFunctionBinaryName();
+				index = lowName.lastIndexOf('\\');
+				if (index != -1)
+					lowName = lowName.substring(index);
+
+				String highName = highToLowValue.getFunctionBinaryName();
+				index = highName.lastIndexOf('\\');
+				if (index != -1)
+					highName = highName.substring(index);
+
+				compareResult = lowName.compareToIgnoreCase(highName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+				{
+					if (compareResult != 0) {
+				    	parking = lowToHighValue;
+				    	elements.setElementAt(highToLowValue, lowToHighIndex);
+				    	elements.setElementAt(parking, highToLowIndex);
+					}
+
+			      	newLowIndex = highToLowIndex;
+			      	newHighIndex = lowToHighIndex;
+
+			      	lowToHighIndex ++;
+			      	highToLowIndex --;
+				}
+			}
+	    }
+
+	    // Continue recursion for parts that have more than one element
+	    if (lowIndex < newHighIndex)
+	    {
+	    	this.quickSortByAssocBinary(elements, lowIndex, newHighIndex); // sort lower subpart
+	    }
+	    if (newLowIndex < highIndex)
+	    {
+	    	this.quickSortByAssocBinary(elements, newLowIndex, highIndex); // sort higher subpart
+	    }
+	}
+
+	private void quickSortByAssocBinaryPath(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex)
+	{
+		int lowToHighIndex;
+	    int highToLowIndex;
+	    int pivotIndex;
+	    ProfiledFunction pivotValue;  // change the values to suit your application
+	    ProfiledFunction lowToHighValue;
+	    ProfiledFunction highToLowValue;
+	    ProfiledFunction parking;
+	    int newLowIndex;
+	    int newHighIndex;
+	    int compareResult;
+
+	    lowToHighIndex = lowIndex;
+	    highToLowIndex = highIndex;
+
+	    pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+	    pivotValue = (ProfiledFunction)elements.elementAt(pivotIndex);
+
+		String pivotName = pivotValue.getFunctionBinaryName();
+		int index = pivotName.lastIndexOf('\\');
+		if (index == -1)
+			pivotName = ""; //$NON-NLS-1$
+		else
+			pivotName = pivotName.substring(0, index);
+
+	    newLowIndex = highIndex + 1;
+	    newHighIndex = lowIndex - 1;
+	    while ((newHighIndex + 1) < newLowIndex)
+	    {
+			lowToHighValue = (ProfiledFunction)elements.elementAt(lowToHighIndex);
+			while (lowToHighIndex < newLowIndex)
+			{
+				String lowName = lowToHighValue.getFunctionBinaryName();
+				index = lowName.lastIndexOf('\\');
+				if (index == -1)
+					lowName = ""; //$NON-NLS-1$
+				else
+					lowName = lowName.substring(0, index);
+
+				compareResult = lowName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+					break;
+
+				newHighIndex = lowToHighIndex;
+			    lowToHighIndex ++;
+			    lowToHighValue = (ProfiledFunction)elements.elementAt(lowToHighIndex);
+			}
+			highToLowValue = (ProfiledFunction)elements.elementAt(highToLowIndex);
+			while (newHighIndex <= highToLowIndex)
+			{
+				String highName = highToLowValue.getFunctionBinaryName();
+				index = highName.lastIndexOf('\\');
+				if (index == -1)
+					highName = ""; //$NON-NLS-1$
+				else
+					highName = highName.substring(0, index);
+
+				compareResult = highName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult > 0) ^ sortAscending))
+					break;
+
+				newLowIndex = highToLowIndex;
+			    highToLowIndex --;
+			    highToLowValue = (ProfiledFunction)elements.elementAt(highToLowIndex);
+			}
+
+			// swap if needed
+			if (lowToHighIndex == highToLowIndex)
+			{
+				newHighIndex = lowToHighIndex;
+			}
+			else if (lowToHighIndex < highToLowIndex)
+			{
+				String lowName = lowToHighValue.getFunctionBinaryName();
+				index = lowName.lastIndexOf('\\');
+				if (index == -1)
+					lowName = ""; //$NON-NLS-1$
+				else
+					lowName = lowName.substring(0, index);
+
+				String highName = highToLowValue.getFunctionBinaryName();
+				index = highName.lastIndexOf('\\');
+				if (index == -1)
+					highName = ""; //$NON-NLS-1$
+				else
+					highName = highName.substring(0, index);
+
+				compareResult = lowName.compareToIgnoreCase(highName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+				{
+					if (compareResult != 0) {
+				    	parking = lowToHighValue;
+				    	elements.setElementAt(highToLowValue, lowToHighIndex);
+				    	elements.setElementAt(parking, highToLowIndex);
+					}
+
+			      	newLowIndex = highToLowIndex;
+			      	newHighIndex = lowToHighIndex;
+
+			      	lowToHighIndex ++;
+			      	highToLowIndex --;
+				}
+			}
+	    }
+
+	    // Continue recursion for parts that have more than one element
+	    if (lowIndex < newHighIndex)
+	    {
+	    	this.quickSortByAssocBinaryPath(elements, lowIndex, newHighIndex); // sort lower subpart
+	    }
+	    if (newLowIndex < highIndex)
+	    {
+	    	this.quickSortByAssocBinaryPath(elements, newLowIndex, highIndex); // sort higher subpart
+	    }
+	}
+
+	private void quickSortByFullAssocBinaryPath(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex)
+	{
+		int lowToHighIndex;
+	    int highToLowIndex;
+	    int pivotIndex;
+	    ProfiledFunction pivotValue;  // change the values to suit your application
+	    ProfiledFunction lowToHighValue;
+	    ProfiledFunction highToLowValue;
+	    ProfiledFunction parking;
+	    int newLowIndex;
+	    int newHighIndex;
+	    int compareResult;
+
+	    lowToHighIndex = lowIndex;
+	    highToLowIndex = highIndex;
+
+	    pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+	    pivotValue = (ProfiledFunction)elements.elementAt(pivotIndex);
+
+	    String pivotName = pivotValue.getFunctionBinaryName();
+
+	    newLowIndex = highIndex + 1;
+	    newHighIndex = lowIndex - 1;
+	    while ((newHighIndex + 1) < newLowIndex)
+	    {
+			lowToHighValue = (ProfiledFunction)elements.elementAt(lowToHighIndex);
+			while (lowToHighIndex < newLowIndex)
+			{
+				String lowName = lowToHighValue.getFunctionBinaryName();
+
+				compareResult = lowName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+					break;
+
+				newHighIndex = lowToHighIndex;
+			    lowToHighIndex ++;
+			    lowToHighValue = (ProfiledFunction)elements.elementAt(lowToHighIndex);
+			}
+			highToLowValue = (ProfiledFunction)elements.elementAt(highToLowIndex);
+			while (newHighIndex <= highToLowIndex)
+			{
+				String highName = highToLowValue.getFunctionBinaryName();
+
+				compareResult = highName.compareToIgnoreCase(pivotName);
+				if ((compareResult == 0) || ((compareResult > 0) ^ sortAscending))
+					break;
+
+				newLowIndex = highToLowIndex;
+			    highToLowIndex --;
+			    highToLowValue = (ProfiledFunction)elements.elementAt(highToLowIndex);
+			}
+
+			// swap if needed
+			if (lowToHighIndex == highToLowIndex)
+			{
+				newHighIndex = lowToHighIndex;
+			}
+			else if (lowToHighIndex < highToLowIndex)
+			{
+				String lowName = lowToHighValue.getFunctionBinaryName();
+				String highName = highToLowValue.getFunctionBinaryName();
+
+				compareResult = lowName.compareToIgnoreCase(highName);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+				{
+					if (compareResult != 0) {
+				    	parking = lowToHighValue;
+				    	elements.setElementAt(highToLowValue, lowToHighIndex);
+				    	elements.setElementAt(parking, highToLowIndex);
+					}
+
+			      	newLowIndex = highToLowIndex;
+			      	newHighIndex = lowToHighIndex;
+
+			      	lowToHighIndex ++;
+			      	highToLowIndex --;
+				}
+			}
+	    }
+
+	    // Continue recursion for parts that have more than one element
+	    if (lowIndex < newHighIndex)
+	    {
+	    	this.quickSortByFullAssocBinaryPath(elements, lowIndex, newHighIndex); // sort lower subpart
+	    }
+	    if (newLowIndex < highIndex)
+	    {
+	    	this.quickSortByFullAssocBinaryPath(elements, newLowIndex, highIndex); // sort higher subpart
+	    }
+	}
+
+	private void quickSortByPriority(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex, Hashtable priorities)
+	{
+		int lowToHighIndex;
+		int highToLowIndex;
+		int pivotIndex;
+		ProfiledThread pivotValue;  // change the values to suit your application
+		ProfiledThread lowToHighValue;
+		ProfiledThread highToLowValue;
+		ProfiledThread parking;
+		int newLowIndex;
+		int newHighIndex;
+		int compareResult;
+
+		lowToHighIndex = lowIndex;
+		highToLowIndex = highIndex;
+		pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+		pivotValue = (ProfiledThread)elements.elementAt(pivotIndex);
+		Integer pivot = (Integer)priorities.get(new Integer(pivotValue.getThreadId()));
+		pivot = (pivot == null) ? new Integer(Integer.MIN_VALUE) : pivot;
+
+		newLowIndex = highIndex + 1;
+		newHighIndex = lowIndex - 1;
+
+		// loop until low meets high
+		while ((newHighIndex + 1) < newLowIndex) // loop until partition complete
+		{
+			lowToHighValue = (ProfiledThread)elements.elementAt(lowToHighIndex);
+			Integer low = (Integer)priorities.get(new Integer(lowToHighValue.getThreadId()));
+			low = (low == null) ? new Integer(Integer.MIN_VALUE) : low;
+			while (lowToHighIndex < newLowIndex
+					&& ((low.compareTo(pivot) != 0) && ((low.compareTo(pivot) > 0) ^ sortAscending)))
+			{
+				newHighIndex = lowToHighIndex; // add element to lower part
+				lowToHighIndex ++;
+				lowToHighValue = (ProfiledThread)elements.elementAt(lowToHighIndex);
+				low = (Integer)priorities.get(new Integer(lowToHighValue.getThreadId()));
+				low = (low == null) ? new Integer(Integer.MIN_VALUE) : low;
+			}
+
+			highToLowValue = (ProfiledThread)elements.elementAt(highToLowIndex);
+			Integer high = (Integer)priorities.get(new Integer(highToLowValue.getThreadId()));
+			high = (high == null) ? new Integer(Integer.MIN_VALUE) : high;
+			while (newHighIndex <= highToLowIndex
+					&& ((high.compareTo(pivot) != 0) && ((high.compareTo(pivot) < 0) ^ sortAscending)))
+			{
+				newLowIndex = highToLowIndex; // add element to higher part
+				highToLowIndex --;
+				highToLowValue = (ProfiledThread)elements.elementAt(highToLowIndex);
+				high = (Integer)priorities.get(new Integer(highToLowValue.getThreadId()));
+			  	high = (high == null) ? new Integer(Integer.MIN_VALUE) : high;
+			}
+
+			// swap if needed
+			if (lowToHighIndex == highToLowIndex) // one last element, may go in either part
+			{
+				newHighIndex = lowToHighIndex; // move element arbitrary to lower part
+			}
+			else if (lowToHighIndex < highToLowIndex) // not last element yet
+			{
+				high = (Integer)priorities.get(new Integer(highToLowValue.getThreadId()));
+				high = (high == null) ? new Integer(Integer.MIN_VALUE) : high;
+				low  = (Integer)priorities.get(new Integer(lowToHighValue.getThreadId()));
+				low  = (low == null) ? new Integer(Integer.MIN_VALUE) : low;
+
+				compareResult = low.compareTo(high);
+				if ((compareResult == 0) || ((compareResult < 0) ^ sortAscending))
+				{
+					if (compareResult != 0) {
+						parking = lowToHighValue;
+						elements.setElementAt(highToLowValue, lowToHighIndex);
+						elements.setElementAt(parking, highToLowIndex);
+					}
+
+					newLowIndex = highToLowIndex;
+					newHighIndex = lowToHighIndex;
+
+					lowToHighIndex ++;
+					highToLowIndex --;
+				}
+			}
+		}
+
+		// Continue recursion for parts that have more than one element
+		if (lowIndex < newHighIndex)
+		{
+			this.quickSortByPriority(elements, lowIndex, newHighIndex, priorities); // sort lower subpart
+		}
+		if (newLowIndex < highIndex)
+		{
+			this.quickSortByPriority(elements, newLowIndex, highIndex, priorities); // sort higher subpart
+		}
+	}
+
+	private void quickSortBySampleCount(Vector<ProfiledGeneric> elements, int lowIndex, int highIndex)
+	{
+	  	int lowToHighIndex;
+	    int highToLowIndex;
+	    int pivotIndex;
+	    ProfiledGeneric pivotValue;  // change the values to suit your application
+	    ProfiledGeneric lowToHighValue;
+	    ProfiledGeneric highToLowValue;
+	    ProfiledGeneric parking;
+	    int newLowIndex;
+	    int newHighIndex;
+
+	    lowToHighIndex = lowIndex;
+	    highToLowIndex = highIndex;
+	    pivotIndex = (lowToHighIndex + highToLowIndex) / 2;
+	    pivotValue = (ProfiledGeneric) elements.elementAt(pivotIndex);
+
+	    newLowIndex = highIndex + 1;
+	    newHighIndex = lowIndex - 1;
+	    // loop until low meets high
+	    while ((newHighIndex + 1) < newLowIndex) // loop until partition complete
+	    {
+	    	lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+	      	while (lowToHighIndex < newLowIndex)
+		    {
+	      		int first  = lowToHighValue.getSampleCount(graphIndex);
+	      		int second = pivotValue.getSampleCount(graphIndex);
+
+	      		if ((first == second) || ((first < second) ^ sortAscending))
+	      			break;
+
+		      	newHighIndex = lowToHighIndex; // add element to lower part
+		        lowToHighIndex ++;
+		        lowToHighValue = (ProfiledGeneric)elements.elementAt(lowToHighIndex);
+		    }
+
+	      	highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+		    while (newHighIndex <= highToLowIndex)
+		    {
+		    	int first  = highToLowValue.getSampleCount(graphIndex);
+			    int second = pivotValue.getSampleCount(graphIndex);
+
+			    if ((first == second) || ((first > second) ^ sortAscending))
+			     	break;
+
+			    newLowIndex = highToLowIndex; // add element to higher part
+			    highToLowIndex --;
+			    highToLowValue = (ProfiledGeneric)elements.elementAt(highToLowIndex);
+		   }
+
+		   // swap if needed
+		   if (lowToHighIndex == highToLowIndex) // one last element, may go in either part
+		   {
+			    newHighIndex = lowToHighIndex; // move element arbitrary to lower part
+		   }
+		   else if (lowToHighIndex < highToLowIndex) // not last element yet
+		   {
+				int first  = lowToHighValue.getSampleCount(graphIndex);
+				int second = highToLowValue.getSampleCount(graphIndex);
+				if ((first == second) || ((first < second) ^ sortAscending))
+			    {
+					if (first != second) {
+						parking = lowToHighValue;
+					    elements.setElementAt(highToLowValue, lowToHighIndex);
+					    elements.setElementAt(parking, highToLowIndex);
+					}
+
+				    newLowIndex = highToLowIndex;
+				    newHighIndex = lowToHighIndex;
+
+				    lowToHighIndex ++;
+				    highToLowIndex --;
+			    }
+		   }
+	    }
+
+		// Continue recursion for parts that have more than one element
+		if (lowIndex < newHighIndex)
+		{
+			// sort lower subpart
+		    this.quickSortBySampleCount(elements, lowIndex, newHighIndex);
+		}
+		if (newLowIndex < highIndex)
+		{
+		    // sort higher subpart
+		    this.quickSortBySampleCount(elements, newLowIndex, highIndex);
+	    }
+	}
+
+	public Vector<ProfiledGeneric> getSortedList()
+	{
+		return sortedList;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppThread.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericThread;
+
+public class GppThread extends GenericThread
+  {
+	private static final long serialVersionUID = -8713961049406558270L;
+    public GppProcess process;
+    public int index;
+    public int samples = 0;
+    public int sortOrder = 0;
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,1118 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTraceWithFunctions;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledBinary;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledFunction;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThreshold;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.BinaryColorPalette;
+import com.nokia.carbide.cpp.pi.util.FunctionColorPalette;
+import com.nokia.carbide.cpp.pi.util.ThreadColorPalette;
+
+
+public class GppTrace extends GenericSampledTraceWithFunctions
+{
+	private static final long serialVersionUID = -658505849351283165L;
+	
+	// sample times start at a set interval, monotonically increase by that interval, and end at a
+	// time equal to (number of elements - 1) times the interval
+	private boolean complete;
+	
+	private transient GppSample[] sortedSamples = null;
+
+	// unchanging set of objects in the trace, ordered by total load
+	private transient Vector<ProfiledGeneric> sortedProfiledThreads;
+	private transient Vector<ProfiledGeneric> sortedProfiledBinaries;
+	private transient Vector<ProfiledGeneric> sortedProfiledFunctions;
+	
+	// unchanging set of objects in the trace, sorted by index
+	private transient Vector<ProfiledGeneric> profiledThreads;
+	private transient Vector<ProfiledGeneric> profiledBinaries;
+	private transient Vector<ProfiledGeneric> profiledFunctions;
+	
+	// selection time based objects in the trace
+	private transient int startSampleIndex;	// first sample in the selection
+	private transient int endSampleIndex;		// last sample in the selection
+
+	// sample counts for the currently selected area of the graph 
+	private transient int[] threadSamples;
+	private transient int[] binarySamples;
+	private transient int[] functionSamples;
+
+	private transient GppTraceGraph[] graphs;
+	
+	// tie palette to a trace instead of graph since trace is the data it represents
+	private transient ThreadColorPalette threadColorPalette = null;
+	private transient BinaryColorPalette binaryColorPalette = null;
+	private transient FunctionColorPalette functionColorPalette = null;
+	
+	//protected int uid;
+	
+	public GppTrace() 
+	{
+	}
+	
+	// for fast access, created a sorted array of samples
+	// this will remove duplicate times, find if times are missing, and
+	// find if times are increasing  
+	public void sortGppSamples()
+	{
+		// check if already sorted
+		if (this.sortedSamples != null)
+			return;
+		
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+
+		complete = this.samples.size()*samplingInterval == this.getLastSampleNumber();
+		
+		this.sortedSamples = new GppSample[this.samples.size()];
+	
+		// fill the sorted array, assuming each sample time matches its (index+1)*samplingInterval
+		boolean sorted = true;
+		int arrayIndex = 0;
+		long lastTime = -1;
+		
+		for (int i = 0, sampleTime = 0; i < this.samples.size(); i++) {
+			Object o = this.samples.get(i);
+			if (o instanceof GppSample) {
+				  GppSample sample = (GppSample)o;
+
+				  // don't copy duplicates
+				  if (sample.sampleSynchTime == lastTime)
+					  continue;
+
+				  this.sortedSamples[arrayIndex++] = sample;
+				  sampleTime += samplingInterval;
+				  
+				  // make sure times are in increasing order
+				  if (sample.sampleSynchTime < lastTime)
+					  sorted = false;
+				  
+				  lastTime = sample.sampleSynchTime;
+				  
+				  if (sample.sampleSynchTime != sampleTime) {
+					  this.complete = false;
+					  
+					  // find the time it does match, in case one is missing
+					  while (sample.sampleSynchTime > sampleTime)
+						  sampleTime += samplingInterval;
+				  }
+			} else {
+				// error case
+				this.sortedSamples = new GppSample[1];
+				this.sortedSamples[0].sampleSynchTime = -1;
+				this.complete = false;
+				return;
+			}
+		}
+		
+		// if any duplicates, create a shorter array
+		if (arrayIndex != this.samples.size()) {
+			GppSample[] sampleObjects1 = new GppSample[this.samples.size()];
+			for (int i = 0; i < this.sortedSamples.length; i++)
+				sampleObjects1[i] = this.sortedSamples[i];
+			this.sortedSamples = sampleObjects1;
+		}
+		
+		if (!sorted) {
+			// now we have to actually sort
+			Arrays.sort(this.sortedSamples, new Comparator<Object>() {
+	
+				public int compare(Object arg0, Object arg1)
+				{
+					return (int) (((GppSample)arg0).sampleSynchTime - ((GppSample)arg1).sampleSynchTime);
+				}
+			});
+
+			// get rid of any duplicates and check for completeness
+			for (int i = 0, sampleTime = 0, length = this.sortedSamples.length; i < length; i++) {
+				GppSample sample = this.sortedSamples[i];
+
+				// don't copy duplicates
+				if (sample.sampleSynchTime == lastTime) {
+					for (int j = i; j < length - 1; j++) {
+						this.sortedSamples[j] = this.sortedSamples[j + 1];
+					}
+					length--;
+					this.complete = false;
+					continue;
+				}
+				
+				sampleTime += samplingInterval;
+				
+				if (sample.sampleSynchTime != sampleTime) {
+					  this.complete = false;
+						  
+					  // find the time it does match, in case one is missing
+					  while (sample.sampleSynchTime > sampleTime)
+						  sampleTime += samplingInterval;
+			    }
+			}
+		}
+	}
+	
+	public boolean isGppSampleComplete()
+	{
+		return this.complete;
+	}
+	
+	public GppSample[] getSortedGppSamples()
+	{
+		return this.sortedSamples;
+	}
+	
+	public GppSample getGppSample(int number)
+	{
+		return (GppSample)this.samples.elementAt(number);
+	}
+	
+	public GenericTraceGraph getTraceGraph(int graphIndex, int uid)
+	{	
+		return getGppGraph(graphIndex,uid);
+	}
+	
+	public GppTraceGraph getGppGraph(int graphIndex, int uid)
+	{
+		if (graphs == null) {
+			graphs = new GppTraceGraph[3];
+		}
+			
+		// note that graphIndex needs not match the index sent to GppTraceGraph
+		if (   (graphIndex == PIPageEditor.THREADS_PAGE)
+			|| (graphIndex == PIPageEditor.BINARIES_PAGE)
+			|| (graphIndex == PIPageEditor.FUNCTIONS_PAGE)) {
+			if (graphs[graphIndex] == null)
+				graphs[graphIndex] = new GppTraceGraph(graphIndex, this, uid);
+			return graphs[graphIndex];
+		}
+	
+		return null;
+	}
+	
+	public GenericTraceGraph getTraceGraph(int graphIndex)
+	{
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+		return getTraceGraph(graphIndex, uid);
+	}
+	
+	public void refineTrace(FunctionResolver resolver)
+	{
+		super.refineTrace(resolver);
+	}
+
+	public int getSortedThreadsCount()
+	{
+		return this.sortedProfiledThreads.size();
+	}
+	
+	public Enumeration<ProfiledGeneric> getSortedThreadsElements()
+	{
+		return this.sortedProfiledThreads.elements();
+	}
+
+	public Vector<ProfiledGeneric> getSortedThreads()
+	{
+		if (this.sortedProfiledThreads == null)
+			this.sortedProfiledThreads = new Vector<ProfiledGeneric>();
+		return this.sortedProfiledThreads;
+	}
+
+	public Vector<ProfiledGeneric> getIndexedThreads()
+	{
+		if (this.profiledThreads == null)
+			this.profiledThreads = new Vector<ProfiledGeneric>();
+		return this.profiledThreads;
+	}
+
+	public int getSortedBinariesCount()
+	{
+	    return this.sortedProfiledBinaries.size();
+	}
+	
+	public Enumeration<ProfiledGeneric> getSortedBinariesElements()
+	{
+	    return this.sortedProfiledBinaries.elements();
+	}
+	
+	public Vector<ProfiledGeneric> getSortedBinaries()
+	{
+		if (this.sortedProfiledBinaries == null)
+			this.sortedProfiledBinaries = new Vector<ProfiledGeneric>();
+	    return this.sortedProfiledBinaries;
+	}
+
+	public Vector<ProfiledGeneric> getIndexedBinaries()
+	{
+		if (this.profiledBinaries == null)
+			this.profiledBinaries = new Vector<ProfiledGeneric>();
+	    return this.profiledBinaries;
+	}
+
+	public int getSortedFunctionsCount()
+	{
+	    return this.sortedProfiledFunctions.size();
+	}
+	
+	public Enumeration<ProfiledGeneric> getSortedFunctionsElements()
+	{
+        return this.sortedProfiledFunctions.elements();
+	}
+	
+	public Vector<ProfiledGeneric> getSortedFunctions()
+	{
+		if (this.sortedProfiledFunctions == null)
+			this.sortedProfiledFunctions = new Vector<ProfiledGeneric>();
+		return this.sortedProfiledFunctions;
+	}
+	
+	public Vector<ProfiledGeneric> getIndexedFunctions()
+	{
+		if (this.profiledFunctions == null)
+			this.profiledFunctions = new Vector<ProfiledGeneric>();
+		return this.profiledFunctions;
+	}
+
+	/*
+	 *	Determine the threads, binaries, and functions associated with a time period
+	 *  from the start time up to and including the end time. If the times are equal,
+	 *  do not include any samples.
+	 */
+	public void setSelectedArea() {
+		// create empty arrays to hold sample counts
+		this.threadSamples   = new int[this.profiledThreads.size()];
+		this.binarySamples   = new int[this.profiledBinaries.size()];
+		this.functionSamples = new int[this.profiledFunctions.size()];
+
+		double doubleStartTime = PIPageEditor.currentPageEditor().getStartTime();
+		double doubleEndTime   = PIPageEditor.currentPageEditor().getEndTime();
+
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+
+		GppSample[] sortedGppSamples = this.getSortedGppSamples();
+
+		// get the sample start time in integer multiples of milliseconds
+		startSampleIndex = ((int) ((doubleStartTime + 0.0005f)* 1000.0f))/samplingInterval;
+		if (startSampleIndex*samplingInterval < this.getFirstSampleNumber()) {
+			startSampleIndex = 0;
+		} else if (startSampleIndex > sortedGppSamples.length) {
+			startSampleIndex = sortedGppSamples.length - 1;
+		}
+			
+		// get the sample end time in integer multiples of milliseconds
+		// NOTE: endSampleIndex is one past the last allowed index, so that when no time
+		// is selected startSampleIndex will equal end sample index
+		endSampleIndex = ((int) ((doubleEndTime + 0.0005f) * 1000.0f))/samplingInterval;
+		if (endSampleIndex*samplingInterval < this.getFirstSampleNumber()) {
+			endSampleIndex = 0;
+		} else if (endSampleIndex > sortedGppSamples.length) {
+			endSampleIndex = sortedGppSamples.length - 1;
+		}
+
+		if (this.isGppSampleComplete()) {
+			// find the sample counts in each category
+			// just use the start and end times as indices
+			for (int i = startSampleIndex; i < endSampleIndex; i++) {
+				threadSamples[sortedGppSamples[i].threadIndex]++;
+				binarySamples[sortedGppSamples[i].binaryIndex]++;
+				functionSamples[sortedGppSamples[i].functionIndex]++;
+			}
+		} else {
+			// use a binary search to find the first sample
+			int startIndex = 0;
+			GppSample sample = null;
+			int lowerBound = 0;
+			int upperBound = sortedGppSamples.length;
+		    while (lowerBound <= upperBound) {
+		    	startIndex = (lowerBound + upperBound)/2;
+				sample = sortedGppSamples[startIndex];
+				if (startSampleIndex*samplingInterval == sample.sampleSynchTime) {
+		            break;
+				} else if (sample.sampleSynchTime > startSampleIndex*samplingInterval)
+		            upperBound = startIndex - 1;
+		        else
+		        	lowerBound = startIndex + 1;
+		    }
+		    
+		    // if there is no match, it's okay if the sample's time is larger than the
+		    // startTime, but not if the startTime is less
+		    if (sample.sampleSynchTime < startSampleIndex*samplingInterval)
+		    	startIndex++;
+	    	endSampleIndex = startIndex;
+		    
+			// find the sample counts in each category
+	    	// use comparisons to find the end sample
+		    if (startIndex < this.samples.size()) {
+				while (sample.sampleSynchTime < endSampleIndex*samplingInterval) {
+					threadSamples[sample.threadIndex]++;
+					binarySamples[sample.binaryIndex]++;
+					functionSamples[sample.functionIndex]++;
+	
+					endSampleIndex++;
+					if (endSampleIndex == sortedGppSamples.length)
+						break;
+	
+					sample = sortedGppSamples[endSampleIndex];
+				}
+				
+				if (   (endSampleIndex == this.samples.size())
+					|| (sample.sampleSynchTime > endSampleIndex*samplingInterval))
+					endSampleIndex--;
+		    }
+		    endSampleIndex++;
+		}
+		
+		// set the sample counts and loads for all the trace-related graphs
+		// set the % load strings only for a tab's base table
+		// To optimise this, we could just set the main sample count and load per graph (e.g., thread stuff for page 0)
+		// To ptimise this, we could check drawMode and ignore sample counts when tables don't show them
+		// requires sample counts, a
+		double percentPerSample;
+		if (startSampleIndex == endSampleIndex)
+			percentPerSample = 0.0;
+		else
+			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
+
+		// NOTE: For slightly better performance, might have other functions rely on this one zeroing out sample counts
+		for (int i = 0; i < this.profiledThreads.size(); i++) {
+			ProfiledGeneric pThread = this.profiledThreads.elementAt(i);
+			pThread.setSampleCount(PIPageEditor.THREADS_PAGE, this.threadSamples[i]);
+			pThread.setLoadAndString(PIPageEditor.THREADS_PAGE, (float)(this.threadSamples[i] * percentPerSample));
+		}
+
+		for (int i = 0; i < this.profiledBinaries.size(); i++) {
+			ProfiledGeneric pBinary = this.profiledBinaries.elementAt(i);
+			pBinary.setSampleCount(PIPageEditor.BINARIES_PAGE, this.binarySamples[i]);
+			pBinary.setLoadAndString(PIPageEditor.BINARIES_PAGE, (float)(this.binarySamples[i] * percentPerSample));
+		}
+
+		for (int i = 0; i < this.profiledFunctions.size(); i++) {
+			ProfiledGeneric pFunction = this.profiledFunctions.elementAt(i);
+			pFunction.setSampleCount(PIPageEditor.FUNCTIONS_PAGE, this.functionSamples[i]);
+			pFunction.setLoadAndString(PIPageEditor.FUNCTIONS_PAGE, (float)(this.functionSamples[i] * percentPerSample));
+		}		
+	}
+
+	/*
+	 * Based on a graph's set of enabled threads, produce a set of binaries, and
+	 * disable all other binaries for that graph
+	 */
+	public Vector<ProfiledGeneric> setThreadBinary(int graphIndex)
+	{
+		Vector<ProfiledGeneric>  graphBinaries = new Vector<ProfiledGeneric>();
+		Hashtable<String,String> foundBinaries = new Hashtable<String,String>();
+		
+		// disable all binaries for the given graph
+		for (int i = 0; i < this.profiledBinaries.size(); i++) {
+			ProfiledGeneric pBinary = this.profiledBinaries.elementAt(i);
+			pBinary.setEnabled(graphIndex, false);
+		}
+
+		// set up in case we find binaries below the threshold
+		boolean lowBinary;
+		ProfiledThreshold thresholdBinary = this.graphs[graphIndex].getThresholdBinary();
+		thresholdBinary.init(graphIndex);
+
+		// for each binary in the selected sample range, if its thread is enabled, add the binary
+		int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
+			GppSample sample = this.sortedSamples[i];
+			ProfiledThread pThread = (ProfiledThread)
+							this.profiledThreads.elementAt(sample.threadIndex);
+
+			if (pThread.isEnabled(graphIndex)) {
+				ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
+				String binaryName = pBinary.getNameString();
+
+				lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
+
+				if (!foundBinaries.containsKey(binaryName)) {
+					pBinary.setEnabled(graphIndex, true);
+					foundBinaries.put(binaryName, binaryName);
+					if (lowBinary) {
+						thresholdBinary.addItem(graphIndex, pBinary, 1);
+					} else {
+						pBinary.setSampleCount(graphIndex, 1);
+						graphBinaries.add(pBinary);
+					}
+				} else {
+					if (lowBinary)
+						thresholdBinary.incSampleCount(graphIndex);
+					else
+						pBinary.incSampleCount(graphIndex);
+				}
+			}
+		}
+		
+		// since we are not converting float % load to string % load inside the table viewers, do it here
+		double percentPerSample;
+		if (startSampleIndex == endSampleIndex)
+			percentPerSample = 0.0;
+		else
+			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
+
+		for (int i = 0; i < graphBinaries.size(); i++) {
+			ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
+			pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex) * percentPerSample));
+		}
+
+		return graphBinaries;
+	}
+
+	/*
+	 * Based on a graph's set of enabled threads and binaries, produce a set of functions, and
+	 * disable all other functions for that graph
+	 */
+	public Vector<ProfiledGeneric> setThreadBinaryFunction(int graphIndex)
+	{
+		Vector<ProfiledGeneric>  graphFunctions = new Vector<ProfiledGeneric>();
+		Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
+		
+		// disable all functions for the given graph
+		for (int i = 0; i < this.profiledFunctions.size(); i++) {
+			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(i);
+			pFunction.setEnabled(graphIndex, false);
+		}
+
+		// set up in case we find functions below the threshold
+		boolean lowFunction;
+		ProfiledThreshold thresholdFunction = this.graphs[graphIndex].getThresholdFunction();
+		thresholdFunction.init(graphIndex);
+
+		// for each function in the selected sample range, if its thread and binary are enabled,
+		// add the function
+		int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
+			GppSample sample = this.sortedSamples[i];
+			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
+			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
+
+			if (pThread.isEnabled(graphIndex) && pBinary.isEnabled(graphIndex)) {
+				ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
+				String functionName = pFunction.getNameString();
+
+				lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
+
+				if (!foundFunctions.containsKey(functionName)) {
+					pFunction.setEnabled(graphIndex, true);
+					foundFunctions.put(functionName, functionName);
+					if (lowFunction) {
+						thresholdFunction.addItem(graphIndex, pFunction, 1);
+					} else {
+						pFunction.setSampleCount(graphIndex, 1);
+						graphFunctions.add(pFunction);
+					}
+				} else {
+					if (lowFunction)
+						thresholdFunction.incSampleCount(graphIndex);
+					else
+						pFunction.incSampleCount(graphIndex);
+				}
+			}
+		}
+		
+		// since we are not converting float % load to string % load inside the table viewers, do it here
+		double percentPerSample;
+		if (startSampleIndex == endSampleIndex)
+			percentPerSample = 0.0;
+		else
+			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
+
+		for (int i = 0; i < graphFunctions.size(); i++) {
+			ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
+			pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex)* percentPerSample));
+		}		
+
+		return graphFunctions;
+	}
+
+	public Vector<ProfiledGeneric> setBinaryThreadFunction(int graphIndex)
+	{
+		return setThreadBinaryFunction(graphIndex);
+	}
+	
+	/*
+	 * Based on a graph's set of enabled threads, produce a set of functions, and
+	 * disable all other functions for that graph
+	 */
+	public Vector<ProfiledGeneric> setThreadFunction(int graphIndex)
+	{
+		Vector<ProfiledGeneric>  graphFunctions = new Vector<ProfiledGeneric>();
+		Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
+		
+		// disable all functions for the given graph
+		for (int i = 0; i < this.profiledFunctions.size(); i++) {
+			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(i);
+			pFunction.setEnabled(graphIndex, false);
+		}
+
+		// set up in case we find functions below the threshold
+		boolean lowFunction;
+		ProfiledThreshold thresholdFunction = this.graphs[graphIndex].getThresholdFunction();
+		thresholdFunction.init(graphIndex);
+
+		// for each function in the selected sample range, if its thread is enabled, add the function
+		int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
+			GppSample sample = this.sortedSamples[i];
+			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
+
+			if (pThread.isEnabled(graphIndex)) {
+				ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
+				String functionName = pFunction.getNameString();
+
+				lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
+
+				if (!foundFunctions.containsKey(functionName)) {
+					pFunction.setEnabled(graphIndex, true);
+					foundFunctions.put(functionName, functionName);
+					if (lowFunction) {
+						thresholdFunction.addItem(graphIndex, pFunction, 1);
+					} else {
+						pFunction.setSampleCount(graphIndex, 1);
+						graphFunctions.add(pFunction);
+					}
+				} else {
+					if (lowFunction)
+						thresholdFunction.incSampleCount(graphIndex);
+					else
+						pFunction.incSampleCount(graphIndex);
+				}
+			}
+		}
+		
+		// since we are not converting float % load to string % load inside the table viewers, do it here
+		double percentPerSample;
+		if (startSampleIndex == endSampleIndex)
+			percentPerSample = 0.0;
+		else
+			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
+
+		for (int i = 0; i < graphFunctions.size(); i++) {
+			ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
+			pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex) * percentPerSample));
+		}		
+		
+		return graphFunctions;
+	}
+
+	/*
+	 * Based on a graph's set of enabled threads and functions, produce a set of binaries, and
+	 * disable all other binaries for that graph
+	 */
+	public Vector<ProfiledGeneric> setThreadFunctionBinary(int graphIndex)
+	{
+		Vector<ProfiledGeneric>  graphBinaries = new Vector<ProfiledGeneric>();
+		Hashtable<String,String> foundBinaries = new Hashtable<String,String>();
+		
+		// disable all binaries for the given graph
+		for (int i = 0; i < this.profiledBinaries.size(); i++) {
+			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(i);
+			pBinary.setEnabled(graphIndex, false);
+		}
+
+		// set up in case we find binaries below the threshold
+		boolean lowBinary;
+		ProfiledThreshold thresholdBinary = this.graphs[graphIndex].getThresholdBinary();
+		thresholdBinary.init(graphIndex);
+
+		// for each binary in the selected sample range, if its thread and function are enabled,
+		// add the binary
+		int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
+			GppSample sample = this.sortedSamples[i];
+			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
+			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
+
+			if (pThread.isEnabled(graphIndex) && pFunction.isEnabled(graphIndex)) {
+				ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
+				String binaryName = pBinary.getNameString();
+
+				lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
+
+				if (!foundBinaries.containsKey(binaryName)) {
+					pBinary.setEnabled(graphIndex, true);
+					foundBinaries.put(binaryName, binaryName);
+					if (lowBinary) {
+						thresholdBinary.addItem(graphIndex, pBinary, 1);
+					} else {
+						pBinary.setSampleCount(graphIndex, 1);
+						graphBinaries.add(pBinary);
+					}
+				} else {
+					if (lowBinary)
+						thresholdBinary.incSampleCount(graphIndex);
+					else
+						pBinary.incSampleCount(graphIndex);
+				}
+			}
+		}
+		
+		// since we are not converting float % load to string % load inside the table viewers, do it here
+		double percentPerSample;
+		if (startSampleIndex == endSampleIndex)
+			percentPerSample = 0.0;
+		else
+			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
+
+		for (int i = 0; i < graphBinaries.size(); i++) {
+			ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
+			pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex) * percentPerSample));
+		}
+		
+		return graphBinaries;
+	}
+
+	public Vector<ProfiledGeneric> setFunctionThreadBinary(int graphIndex)
+	{
+		return setThreadFunctionBinary(graphIndex);
+	}
+
+	/*
+	 * Based on a graph's set of enabled binaries, produce a set of threads, and
+	 * disable all other threads for that graph
+	 */
+	public Vector<ProfiledGeneric> setBinaryThread(int graphIndex)
+	{
+		Vector<ProfiledGeneric>  graphThreads = new Vector<ProfiledGeneric>();
+		Hashtable<String,String> foundThreads = new Hashtable<String,String>();
+		
+		// disable all threads for the given graph
+		for (int i = 0; i < this.profiledThreads.size(); i++) {
+			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(i);
+			pThread.setEnabled(graphIndex, false);
+		}
+
+		// set up in case we find threads below the threshold
+		boolean lowThread;
+		ProfiledThreshold thresholdThread = this.graphs[graphIndex].getThresholdThread();
+		thresholdThread.init(graphIndex);
+
+		// for each thread in the selected sample range, if its binary is enabled, add the thread
+		int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
+			GppSample sample = this.sortedSamples[i];
+			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
+
+			if (pBinary.isEnabled(graphIndex)) {
+				ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
+				String threadName = pThread.getNameString();
+
+				lowThread = pThread.getTotalSampleCount() < threadThreshold;
+
+				if (!foundThreads.containsKey(threadName)) {
+					pThread.setEnabled(graphIndex, true);
+					foundThreads.put(threadName, threadName);
+					if (lowThread) {
+						thresholdThread.addItem(graphIndex, pThread, 1);
+					} else {
+						pThread.setSampleCount(graphIndex, 1);
+						graphThreads.add(pThread);
+					}
+				} else {
+					if (lowThread)
+						thresholdThread.incSampleCount(graphIndex);
+					else
+						pThread.incSampleCount(graphIndex);
+				}
+			}
+		}
+		
+		// since we are not converting float % load to string % load inside the table viewers, do it here
+		double percentPerSample;
+		if (startSampleIndex == endSampleIndex)
+			percentPerSample = 0.0;
+		else
+			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
+
+		for (int i = 0; i < graphThreads.size(); i++) {
+			ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
+			pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex) * percentPerSample));
+		}
+		
+		return graphThreads;
+	}
+
+	/*
+	 * Based on a graph's set of enabled functions, produce a set of threads, and
+	 * disable all other threads for that graph
+	 */
+	public Vector<ProfiledGeneric> setFunctionThread(int graphIndex)
+	{
+		Vector<ProfiledGeneric>  graphThreads = new Vector<ProfiledGeneric>();
+		Hashtable<String,String> foundThreads = new Hashtable<String,String>();
+		
+		// disable all threads for the given graph
+		for (int i = 0; i < this.profiledThreads.size(); i++) {
+			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(i);
+			pThread.setEnabled(graphIndex, false);
+		}
+
+		// set up in case we find threads below the threshold
+		boolean lowThread;
+		ProfiledThreshold thresholdThread = this.graphs[graphIndex].getThresholdThread();
+		thresholdThread.init(graphIndex);
+
+		// for each thread in the selected sample range, if its function is enabled, add the thread
+		int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
+			GppSample sample = this.sortedSamples[i];
+			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
+
+			if (pFunction.isEnabled(graphIndex)) {
+				ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
+				String threadName = pThread.getNameString();
+
+				lowThread = pThread.getTotalSampleCount() < threadThreshold;
+
+				if (!foundThreads.containsKey(threadName)) {
+					pThread.setEnabled(graphIndex, true);
+					foundThreads.put(threadName, threadName);
+					if (lowThread) {
+						thresholdThread.addItem(graphIndex, pThread, 1);
+					} else {
+						pThread.setSampleCount(graphIndex, 1);
+						graphThreads.add(pThread);
+					}
+				} else {
+					if (lowThread)
+						thresholdThread.incSampleCount(graphIndex);
+					else
+						pThread.incSampleCount(graphIndex);
+				}
+			}
+		}
+		
+		// since we are not converting float % load to string % load inside the table viewers, do it here
+		double percentPerSample;
+		if (startSampleIndex == endSampleIndex)
+			percentPerSample = 0.0;
+		else
+			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
+
+		for (int i = 0; i < graphThreads.size(); i++) {
+			ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
+			pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex) * percentPerSample));
+		}
+		
+		return graphThreads;
+	}
+
+	/*
+	 * Based on a graph's set of enabled binaries and functions, produce a set of threads, and
+	 * disable all other threads for that graph
+	 */
+	public Vector<ProfiledGeneric> setBinaryFunctionThread(int graphIndex)
+	{
+		Vector<ProfiledGeneric>  graphThreads = new Vector<ProfiledGeneric>();
+		Hashtable<String,String> foundThreads = new Hashtable<String,String>();
+		
+		// disable all threads for the given graph
+		for (int i = 0; i < this.profiledThreads.size(); i++) {
+			ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(i);
+			pThread.setEnabled(graphIndex, false);
+		}
+
+		// set up in case we find threads below the threshold
+		boolean lowThread;
+		ProfiledThreshold thresholdThread = this.graphs[graphIndex].getThresholdThread();
+		thresholdThread.init(graphIndex);
+
+		// for each thread in the selected sample range, if its binary and function are enabled,
+		// add the thread
+		int threadThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
+			GppSample sample = this.sortedSamples[i];
+			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
+			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
+
+			if (pBinary.isEnabled(graphIndex)
+	 		    && (pFunction.isEnabled(graphIndex))) {
+				ProfiledThread pThread = (ProfiledThread) this.profiledThreads.elementAt(sample.threadIndex);
+				String threadName = pThread.getNameString();
+
+				lowThread = pThread.getTotalSampleCount() < threadThreshold;
+
+				if (!foundThreads.containsKey(threadName)) {
+					pThread.setEnabled(graphIndex, true);
+					foundThreads.put(threadName, threadName);
+					if (lowThread) {
+						thresholdThread.addItem(graphIndex, pThread, 1);
+					} else {
+						pThread.setSampleCount(graphIndex, 1);
+						graphThreads.add(pThread);
+					}
+				} else {
+					if (lowThread)
+						thresholdThread.incSampleCount(graphIndex);
+					else
+						pThread.incSampleCount(graphIndex);
+				}
+			}
+		}
+		
+		// since we are not converting float % load to string % load inside the table viewers, do it here
+		double percentPerSample;
+		if (startSampleIndex == endSampleIndex)
+			percentPerSample = 0.0;
+		else
+			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
+
+		for (int i = 0; i < graphThreads.size(); i++) {
+			ProfiledThread pThread = (ProfiledThread) graphThreads.elementAt(i);
+			pThread.setLoadAndString(graphIndex, (float)(pThread.getSampleCount(graphIndex) * percentPerSample));
+		}
+		
+		return graphThreads;
+	}
+
+	public Vector<ProfiledGeneric> setFunctionBinaryThread(int graphIndex)
+	{
+		return setBinaryFunctionThread(graphIndex);
+	}
+
+	/*
+	 * Based on a graph's set of enabled functions, produce a set of binaries, and
+	 * disable all other binaries for that graph
+	 */
+	public Vector<ProfiledGeneric> setFunctionBinary(int graphIndex)
+	{
+		Vector<ProfiledGeneric>  graphBinaries = new Vector<ProfiledGeneric>();
+		Hashtable<String,String> foundBinaries = new Hashtable<String,String>();
+		
+		// disable all binaries for the given graph
+		for (int i = 0; i < this.profiledBinaries.size(); i++) {
+			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(i);
+			pBinary.setEnabled(graphIndex, false);
+		}
+
+		// set up in case we find binaries below the threshold
+		boolean lowBinary;
+		ProfiledThreshold thresholdBinary = this.graphs[graphIndex].getThresholdBinary();
+		thresholdBinary.init(graphIndex);
+
+		// for each binary in the selected sample range, if its function is enabled, add the binary
+		int binaryThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
+			GppSample sample = this.sortedSamples[i];
+			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
+
+			if (pFunction.isEnabled(graphIndex)) {
+				ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
+				String binaryName = pBinary.getNameString();
+
+				lowBinary = pBinary.getTotalSampleCount() < binaryThreshold;
+
+				if (!foundBinaries.containsKey(binaryName)) {
+					pBinary.setEnabled(graphIndex, true);
+					foundBinaries.put(binaryName, binaryName);
+					if (lowBinary) {
+						thresholdBinary.addItem(graphIndex, pBinary, 1);
+					} else {
+						pBinary.setSampleCount(graphIndex, 1);
+						graphBinaries.add(pBinary);
+					}
+				} else {
+					if (lowBinary)
+						thresholdBinary.incSampleCount(graphIndex);
+					else
+						pBinary.incSampleCount(graphIndex);
+				}
+			}
+		}
+		
+		// since we are not converting float % load to string % load inside the table viewers, do it here
+		double percentPerSample;
+		if (startSampleIndex == endSampleIndex)
+			percentPerSample = 0.0;
+		else
+			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
+
+		for (int i = 0; i < graphBinaries.size(); i++) {
+			ProfiledBinary pBinary = (ProfiledBinary) graphBinaries.elementAt(i);
+			pBinary.setLoadAndString(graphIndex, (float)(pBinary.getSampleCount(graphIndex) * percentPerSample));
+		}
+		
+		return graphBinaries;
+	}
+
+	/*
+	 * Based on a graph's set of enabled binaries, produce a set of functions, and
+	 * disable all other functions for that graph
+	 */
+	public Vector<ProfiledGeneric> setBinaryFunction(int graphIndex)
+	{
+		Vector<ProfiledGeneric>  graphFunctions = new Vector<ProfiledGeneric>();
+		Hashtable<String,String> foundFunctions = new Hashtable<String,String>();
+		
+		// disable all functions for the given graph
+		for (int i = 0; i < this.profiledFunctions.size(); i++) {
+			ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(i);
+			pFunction.setEnabled(graphIndex, false);
+		}
+
+		// set up in case we find functions below the threshold
+		boolean lowFunction;
+		ProfiledThreshold thresholdFunction = this.graphs[graphIndex].getThresholdFunction();
+		thresholdFunction.init(graphIndex);
+
+		// for each function in the selected sample range, if its binary is enabled, add the function
+		int functionThreshold = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+		for (int i = this.startSampleIndex; i < this.endSampleIndex; i++) {
+			GppSample sample = this.sortedSamples[i];
+			ProfiledBinary pBinary = (ProfiledBinary) this.profiledBinaries.elementAt(sample.binaryIndex);
+
+			if (pBinary.isEnabled(graphIndex)) {
+				ProfiledFunction pFunction = (ProfiledFunction) this.profiledFunctions.elementAt(sample.functionIndex);
+				String functionName = pFunction.getNameString();
+
+				lowFunction = pFunction.getTotalSampleCount() < functionThreshold;
+
+				if (!foundFunctions.containsKey(functionName)) {
+					pFunction.setEnabled(graphIndex, true);
+					foundFunctions.put(functionName, functionName);
+					if (lowFunction) {
+						thresholdFunction.addItem(graphIndex, pFunction, 1);
+					} else {
+						pFunction.setSampleCount(graphIndex, 1);
+						graphFunctions.add(pFunction);
+					}
+				} else {
+					if (lowFunction)
+						thresholdFunction.incSampleCount(graphIndex);
+					else
+						pFunction.incSampleCount(graphIndex);
+				}
+			}
+		}
+		
+		// since we are not converting float % load to string % load inside the table viewers, do it here
+		double percentPerSample;
+		if (startSampleIndex == endSampleIndex)
+			percentPerSample = 0.0;
+		else
+			percentPerSample = 100.0 / ((double)(this.endSampleIndex - this.startSampleIndex));
+
+		for (int i = 0; i < graphFunctions.size(); i++) {
+			ProfiledFunction pFunction = (ProfiledFunction) graphFunctions.elementAt(i);
+			pFunction.setLoadAndString(graphIndex, (float)(pFunction.getSampleCount(graphIndex) * percentPerSample));
+		}		
+		
+		return graphFunctions;
+	}
+	
+	public int getStartSampleIndex()
+	{
+		return this.startSampleIndex;
+	}
+	
+	public int getEndSampleIndex()
+	{
+		return this.endSampleIndex;
+	}
+	
+	public int[] getThreadSampleCounts()
+	{
+		return this.threadSamples;
+	}
+	
+	public int[] getBinarySampleCounts()
+	{
+		return this.binarySamples;
+	}
+	
+	public int[] getFunctionSampleCounts()
+	{
+		return this.functionSamples;
+	}
+
+	public void setThreadSampleCounts(int[] sampleCounts)
+	{
+		this.threadSamples = sampleCounts;
+	}
+	
+	public void setBinarySampleCounts(int[] sampleCounts)
+	{
+		this.binarySamples = sampleCounts;
+	}
+	
+	public void setFunctionSampleCounts(int[] sampleCounts)
+	{
+		this.functionSamples = sampleCounts;
+	}
+	
+	public void setThreadColorPalette(ThreadColorPalette tableColorPalette) {
+		this.threadColorPalette = tableColorPalette;
+	}
+
+	public ThreadColorPalette getThreadColorPalette() {
+		if (this.threadColorPalette == null) {
+			this.threadColorPalette = new ThreadColorPalette();
+		}
+		return this.threadColorPalette;
+	}
+
+	public void setBinaryColorPalette(BinaryColorPalette tableColorPalette) {
+		this.binaryColorPalette = tableColorPalette;
+	}
+
+	public BinaryColorPalette getBinaryColorPalette() {
+		if (this.binaryColorPalette == null) {
+			this.binaryColorPalette = new BinaryColorPalette();
+		}
+		return this.binaryColorPalette;
+	}
+
+	public void setFunctionColorPalette(FunctionColorPalette tableColorPalette) {
+		this.functionColorPalette = tableColorPalette;
+	}
+
+	public FunctionColorPalette getFunctionColorPalette() {
+		if (this.functionColorPalette == null) {
+			this.functionColorPalette = new FunctionColorPalette();
+		}
+		return this.functionColorPalette;
+	}
+
+	@Override
+	public void finalizeTrace() {
+		samples.trimToSize();
+		for (int i = 0; i < samples.size(); i++) {
+			GppSample sample = (GppSample) samples.get(i);
+			
+			if (sample.currentFunctionItt == null && sample.currentFunctionSym == null) {
+				sample.currentFunctionItt = new Function(Messages.getString("GppTrace.functionNotFound1") + Long.toHexString(sample.programCounter) + Messages.getString("GppTrace.functionNotFound2"), //$NON-NLS-1$ //$NON-NLS-2$
+						new Long(sample.programCounter),
+						Messages.getString("GppTrace.binaryNotFound1") +  Long.toHexString(sample.programCounter) + Messages.getString("GppTrace.binarynotFound2")); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTraceCsvPrinter.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
+
+
+public class GppTraceCsvPrinter
+{
+    private StringWriter csvWriter;
+    
+    // directory for the address trace plugin
+    private String directory = System.getProperty("user.dir") + File.separator   //$NON-NLS-1$
+    						+ "plugins" + File.separator  //$NON-NLS-1$
+    						+ AddressPlugin.getDefault().getBundle().getSymbolicName() + "_"  //$NON-NLS-1$
+    						+ AddressPlugin.getDefault().getBundle().getHeaders().get("Bundle-Version");  //$NON-NLS-1$
+    private String eka1 = "fixed_thread_list_eka1_for_csv_print.txt"; //$NON-NLS-1$
+    private String eka2 = "fixed_thread_list_eka2_for_csv_print.txt"; //$NON-NLS-1$
+    private static final int eka1Mode = 1;
+    private static final int eka2Mode = 2;
+    
+    public String getCsvPrint()
+    {
+        if (csvWriter == null)
+        	return null;
+        else
+        	return csvWriter.toString();
+    }
+    
+    public GppTraceCsvPrinter(GppTrace trace)
+    {
+    	String threadListFile;
+    	File f;
+
+    	int mode = solveMode(trace);
+    	if (mode == eka1Mode)
+    		threadListFile = directory + File.separator + eka1;
+    	else if (mode == eka2Mode)
+    		threadListFile = directory + File.separator + eka2;
+    	else
+    	{
+    		System.out.println(Messages.getString("GppTraceCsvPrinter.1"));  //$NON-NLS-1$
+    		return;
+    	}
+    	
+    	f = new File(threadListFile);
+    	if (!f.exists())
+    	{
+    		System.out.println(Messages.getString("GppTraceCsvPrinter.2") + threadListFile + Messages.getString("GppTraceCsvPrinter.3"));   //$NON-NLS-1$ //$NON-NLS-2$
+    		return;
+    	}
+    	csvWriter = new StringWriter();
+    	
+    	Enumeration pts = trace.getSortedThreadsElements();
+    	if (pts == null)
+    		return;
+    	formCsvPrint(pts, f);
+    }
+    
+    private Vector getFixedThreadTable(File fixedThreadFile)
+    {
+    	try 
+    	{
+    		BufferedReader br = new BufferedReader(new FileReader(fixedThreadFile));
+			String line;
+			Vector v = new Vector();
+			while ((line = br.readLine()) != null)
+			{
+				String threadName;
+				String mappedName = ""; //$NON-NLS-1$
+    			int mappedNameStart = line.indexOf('{');
+				int mappedNameEnd = line.indexOf('}');
+				if (mappedNameStart != -1 && mappedNameEnd != -1)
+				{
+					mappedName = line.substring(mappedNameStart + 1, mappedNameEnd);
+					threadName = line.substring(0, mappedNameStart).trim();
+				}
+				else
+					threadName = line.trim();
+				v.add(new ObjectMap(threadName, mappedName));
+			}
+			br.close();
+			return v;
+		} catch (FileNotFoundException e) 
+		{
+			e.printStackTrace();
+		} catch(IOException e1)
+		{
+			e1.printStackTrace();
+		}
+		return null;
+    	
+    }
+    
+    private void formCsvPrint(Enumeration profiledThreads, File threadFile)
+    {
+    	Hashtable<String,int[]> activityByName = new Hashtable<String,int[]>();
+    	Vector fixedThreads = getFixedThreadTable(threadFile);
+    	Vector<ObjectMap> resultVector = new Vector<ObjectMap>();
+    	boolean nullListFormed = false;
+    	int[] nullList = null;
+    	
+    	while (profiledThreads.hasMoreElements())
+    	{
+    		ProfiledThread pt = (ProfiledThread)profiledThreads.nextElement();
+    		if (!nullListFormed)
+    		{
+    			nullList = new int[pt.getActivityList().length];
+    			nullListFormed = true;
+    		}
+    		String name = formatThreadName(pt.getNameString());
+    		if (activityByName.containsKey(name))
+    		{
+    			int[] existingList = activityByName.get(name);
+    			int[] combinedList = combineLists(pt.getActivityList(), existingList);
+    			activityByName.put(name, combinedList);
+    		}
+    		else
+    			activityByName.put(name, pt.getActivityList());
+    	}
+    	
+    	for (Enumeration e = fixedThreads.elements(); e.hasMoreElements();)
+    	{
+    		ObjectMap om = (ObjectMap)e.nextElement();
+    		boolean threadFound = false;
+    		for (Enumeration<String> enu = activityByName.keys(); enu.hasMoreElements();)
+    		{
+    			String threadName = enu.nextElement();
+    			if (threadName.startsWith((String)om.object))
+    			{
+    				threadFound = true;
+    				String mappedName = (String)om.mappedObject;
+    				if (mappedName != "") //$NON-NLS-1$
+    					resultVector.add(new ObjectMap(mappedName, activityByName.get(threadName)));
+    				else
+    					resultVector.add(new ObjectMap((String)om.object, activityByName.get(threadName)));
+    				break;
+    			}
+    		}
+    		if (!threadFound)
+    		{
+    			String mappedName = (String)om.mappedObject;
+				if (mappedName != "") //$NON-NLS-1$
+					resultVector.add(new ObjectMap(mappedName, nullList));
+				else
+					resultVector.add(new ObjectMap((String)om.object, nullList));
+    		}
+    	}
+    	if (resultVector.size() != 0)
+    		writeCsvPrint(resultVector);
+    }
+    
+    private void writeCsvPrint(Vector<ObjectMap> resultVector)
+    {
+    	csvWriter.write(",Time"); //$NON-NLS-1$
+    	int csvTableHeight = ((int[])(resultVector.elementAt(0)).mappedObject).length;
+    	int csvTableWidth = 0;
+    	for (Enumeration<ObjectMap> e = resultVector.elements(); e.hasMoreElements();)
+    	{
+    		String key = (String)(e.nextElement()).object;
+    		csvWriter.write("," + key); //$NON-NLS-1$
+    	}
+    	csvWriter.write("\r\n"); //$NON-NLS-1$
+    	csvTableWidth = resultVector.size();
+    	
+    	for (int i = 0; i < csvTableHeight; i++)
+    	{
+    		csvWriter.write("R" + (i + 1) + "," + i/10f); //$NON-NLS-1$ //$NON-NLS-2$
+    		for (int j = 0; j < csvTableWidth; j++)
+    		{
+    			ObjectMap om = resultVector.elementAt(j);
+    			int[] tmp = (int[])om.mappedObject;
+    			csvWriter.write("," + tmp[i]/100d); //$NON-NLS-1$
+    		}
+    		csvWriter.write("\r\n"); //$NON-NLS-1$
+    	}
+    }
+    
+    private String formatThreadName(String name)
+    {
+    	int firstPartEnd = name.indexOf('[');
+    	int lastPartStart = name.indexOf(':');
+    	int lastPartEnd = name.lastIndexOf('_');
+    	if (firstPartEnd == -1 || lastPartStart == -1 || lastPartEnd == -1)
+    		return name;
+    	String firstPart = name.substring(0, firstPartEnd);
+    	String lastPart = name.substring(lastPartStart, lastPartEnd);
+    	return firstPart + lastPart;
+    	
+    }
+    
+    private int[] combineLists(int[] p1List, int[] p2List)
+    {
+    	if (p1List.length < p2List.length)
+    		return null;
+    	int[] combinedList = new int[p2List.length];
+    	for (int i = 0; i < p2List.length; i++)
+    	{
+    		combinedList[i] = p2List[i] + p1List[i];
+    	}
+    	return combinedList;
+    }
+    
+    private int solveMode(GppTrace trace)
+    {
+    	String processName = ((GppSample)trace.samples.elementAt(0)).thread.process.name;
+    	if (processName == null)
+    		return -1;
+    	int start = processName.indexOf('[');
+    	int end = processName.indexOf(']');
+    	String processId = processName.substring(start + 1, end);
+    	if (start == -1 || end == -1)
+    		return -1;
+    	if (processId.length() > 3)
+    		return 1;
+    	else
+    		return 2;
+    }
+    
+    static private class ObjectMap
+    {	
+    	public Object object;
+    	public Object mappedObject;
+    	public ObjectMap (Object object, Object mappedObject)
+    	{
+    		this.object = object;
+    		this.mappedObject = mappedObject;
+    	}
+    }  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTraceGraph.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2355 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: 
+ *
+ */
+
+/*
+ * GppTraceGraph.java
+ */
+package com.nokia.carbide.cpp.pi.address;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Vector;
+
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.MouseEvent;
+import org.eclipse.draw2d.MouseListener;
+import org.eclipse.draw2d.MouseMotionListener;
+import org.eclipse.draw2d.Panel;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Sash;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledBinary;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledFunction;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThreshold;
+import com.nokia.carbide.cpp.internal.pi.visual.Defines;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTable;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.internal.pi.visual.GraphComposite;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEventListener;
+import com.nokia.carbide.cpp.internal.pi.visual.PIVisualSharedData;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.ColorPalette;
+
+
+public class GppTraceGraph extends GenericTraceGraph implements ActionListener, 
+																FocusListener, 
+																PIEventListener,
+																MouseMotionListener,
+																MouseListener,
+																MouseMoveListener
+{
+	private GppTraceGraph thisTraceGraph;
+	
+	// amount of space at bottom of graph to contain things like x-axis units and button icons
+	public static final int xLegendHeight = 50;
+	
+	// When the graph is drawn, this is the finest granularity drawn. E.g., assume
+	// a granularity of 100, and a sample every ms. If the 1st function draw appears
+	// in 5 samples from 101ms to 200ms and 10 samples from 200ms to 300ms then the
+	// graph will show a point at height 5 at time 200 connected by a line to a
+	// point at height 10 at time 300.
+	private static int granularityValue = 100;
+	
+	private GppVisualiserPanel vPanel;
+
+	/*
+	 *  Depending on this trace graph's graphIndex, one of these will be
+	 *  the base table, and others will be derived from its selections.
+	 *  The other tables will appear and disappear based on drawMode.
+	 *  
+	 *  E.g., say that for graphIndex = 0, the base table is threadTable.
+	 *  Then this graph can represent the draw modes of:
+	 *  	THREADS
+	 *  	THREADS_BINARIES
+	 *  	THREADS_BINARIES_FUNCTIONS
+	 *  	THREADS_FUNCTIONS
+	 *  	THREADS_FUNCTIONS_BINARIES
+	 */
+	private AddrThreadTable   threadTable;
+	private AddrBinaryTable   binaryTable;
+	private AddrFunctionTable functionTable;
+
+	/*
+	 *	Depending on this trace graph's graphIndex, one of these will match
+	 *	the entire trace's profiled vector, while the others will be derived
+	 *	from drilldown selections. The other vectors will only be meaningful
+	 *  depending on the drawMode.
+	 */
+	private Vector<ProfiledGeneric> profiledThreads   = new Vector<ProfiledGeneric>();
+	private Vector<ProfiledGeneric> profiledBinaries  = new Vector<ProfiledGeneric>();
+	private Vector<ProfiledGeneric> profiledFunctions = new Vector<ProfiledGeneric>();
+	
+	private Vector<ProfiledGeneric> sortedProfiledThreads   = new Vector<ProfiledGeneric>();
+	private Vector<ProfiledGeneric> sortedProfiledBinaries  = new Vector<ProfiledGeneric>();
+	private Vector<ProfiledGeneric> sortedProfiledFunctions = new Vector<ProfiledGeneric>();
+	
+	private ProfiledThreshold thresholdThread   = new ProfiledThreshold("dummy[0]::dummy_0"); //$NON-NLS-1$
+	private ProfiledThreshold thresholdBinary   = new ProfiledThreshold("\\dummy"); //$NON-NLS-1$
+	private ProfiledThreshold thresholdFunction = new ProfiledThreshold("dummy::dummy()"); //$NON-NLS-1$
+
+	// when multiple tables are visible, they are separated by sashes
+	private Sash leftSash;
+	private Sash rightSash;
+
+	public static final int NOFILL       = 0;
+	public static final int FILLSELECTED = 1;
+	public static final int FILLALL      = 2;
+	public static final int BAR_MODE_ON  = 3;
+	public static final int BAR_MODE_OFF = 4;
+		
+	private int drawMode = Defines.THREADS;
+	public int barMode   = BAR_MODE_OFF;
+	
+	private int uid;
+	
+	private static class BarGraphData
+	{
+		public int x;
+		public Color color;
+	}
+	
+	private Vector<BarGraphData> barGraphData;
+	
+	public GppTraceGraph(int graphIndex, GppTrace trace, int uid)
+	{
+		super((GenericSampledTrace)trace);
+		
+		int granularityValue = trace.samples.size() > GppTraceGraph.granularityValue ? GppTraceGraph.granularityValue : trace.samples.size();  
+		
+		this.thisTraceGraph = this;
+		this.graphIndex     = graphIndex;
+		
+		// create the graph's 3 table objects - without any table items yet
+		ProfileVisualiser pV = NpiInstanceRepository.getInstance().getProfilePage(uid, graphIndex);
+		Composite holdTables = new Composite(pV.getBottomComposite(), SWT.NONE);
+		holdTables.setLayout(new FormLayout());
+
+		this.threadTable   = new AddrThreadTable(this, holdTables);
+		this.binaryTable   = new AddrBinaryTable(this, holdTables);
+		this.functionTable = new AddrFunctionTable(this, holdTables);
+		
+		this.uid = uid;
+
+		Label graphTitle = pV.getTitle();
+		Label graphTitle2 = pV.getTitle2();
+		if 	(graphTitle2 != null)
+			graphTitle2.setText(""); //$NON-NLS-1$
+
+		// initialize the threshold counts
+		int totalSampleCount = trace.getSampleAmount();
+		NpiInstanceRepository.getInstance().setPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdCountThread", new Integer(new Double(totalSampleCount * (Double)NpiInstanceRepository.getInstance().getPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdLoadThread") + 0.5).intValue())); //$NON-NLS-1$ //$NON-NLS-2$
+		NpiInstanceRepository.getInstance().setPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdCountBinary", new Integer(new Double(totalSampleCount * (Double)NpiInstanceRepository.getInstance().getPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdLoadBinary") + 0.5).intValue())); //$NON-NLS-1$ //$NON-NLS-2$
+		NpiInstanceRepository.getInstance().setPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdCountFunction", new Integer(new Double(totalSampleCount * (Double)NpiInstanceRepository.getInstance().getPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdLoadFunction") + 0.5).intValue())); //$NON-NLS-1$ //$NON-NLS-2$
+		
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+
+		// initialize the threshold items
+		thresholdThread.setColor(trace.getThreadColorPalette().getColor(thresholdThread.getNameString()));
+		thresholdThread.setActivityMarkCount((trace.samples.size() + granularityValue) / granularityValue + 1);
+		for (int i = 0; i < trace.samples.size() + granularityValue; i += granularityValue)
+		{
+			thresholdThread.zeroActivityMarkValues(i * samplingInterval);
+		}
+		thresholdBinary.setColor(trace.getBinaryColorPalette().getColor(thresholdBinary.getNameString()));
+		thresholdBinary.setActivityMarkCount((trace.samples.size() + granularityValue) / granularityValue + 1);
+		for (int i = 0; i < trace.samples.size() + granularityValue; i += granularityValue)
+		{
+			thresholdBinary.zeroActivityMarkValues(i * samplingInterval);
+		}
+		thresholdFunction.setColor(trace.getFunctionColorPalette().getColor(thresholdFunction.getNameString()));
+		thresholdFunction.setActivityMarkCount((trace.samples.size() + granularityValue) / granularityValue + 1);
+		for (int i = 0; i < trace.samples.size() + granularityValue; i += granularityValue)
+		{
+			thresholdFunction.zeroActivityMarkValues(i * samplingInterval);
+		}
+
+		// all the trace data is known, and you have it sorted 3 different ways
+		// so set the drawmode, create the page's base table, and set the graph title
+		if (graphIndex == PIPageEditor.THREADS_PAGE) {
+			this.drawMode = Defines.THREADS;
+
+			// tables will show threads in decreasing total sample order, but
+			// then put them back in increasing sample order so that the graph
+			// shows most common (e.g., EKern) threads on top
+			this.profiledThreads.clear();
+			for (int i = trace.getSortedThreads().size() - 1; i >= 0; i--)
+				this.profiledThreads.add(trace.getSortedThreads().get(i));
+			filterSortedByThreshold(graphIndex, 
+									(Integer)NpiInstanceRepository.getInstance().getPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdCountThread"), //$NON-NLS-1$
+									thresholdThread, this.profiledThreads);
+			this.threadTable.setTableViewer(Defines.THREADS);
+
+			this.profiledThreads = trace.getSortedThreads();
+			graphTitle.setText(Messages.getString("GppTraceGraph.threadLoad"));  //$NON-NLS-1$
+		} else
+		if (graphIndex == PIPageEditor.BINARIES_PAGE) {
+			this.drawMode = Defines.BINARIES;
+
+			// tables will show binaries in decreasing total sample order, but
+			// then put them back in increasing sample order so that the graph
+			// shows most common (e.g., EKern) binaries on top
+			this.profiledBinaries.clear();
+			for (int i = trace.getSortedBinaries().size() - 1; i >= 0; i--)
+				this.profiledBinaries.add(trace.getSortedBinaries().get(i));
+			filterSortedByThreshold(graphIndex, (Integer)NpiInstanceRepository.getInstance().getPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdCountBinary"), //$NON-NLS-1$
+								thresholdBinary, this.profiledBinaries);
+			this.binaryTable.setTableViewer(Defines.BINARIES);
+
+			this.profiledBinaries = trace.getSortedBinaries();
+			graphTitle.setText(Messages.getString("GppTraceGraph.binaryLoad"));  //$NON-NLS-1$
+		} else
+		if (graphIndex == PIPageEditor.FUNCTIONS_PAGE) {
+			this.drawMode = Defines.FUNCTIONS;
+
+			// tables will show functions in decreasing total sample order, but
+			// then put them back in increasing sample order so that the graph
+			// shows most common (e.g., EKern) functions on top
+			this.profiledFunctions.clear();
+			for (int i = trace.getSortedFunctions().size() - 1; i >= 0; i--)
+				this.profiledFunctions.add(trace.getSortedFunctions().get(i));
+			filterSortedByThreshold(graphIndex, (Integer)NpiInstanceRepository.getInstance().getPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdCountFunction"), //$NON-NLS-1$
+								thresholdFunction, this.profiledFunctions);
+			this.functionTable.setTableViewer(Defines.FUNCTIONS);
+
+			this.profiledFunctions = trace.getSortedFunctions();
+			graphTitle.setText(Messages.getString("GppTraceGraph.FunctionLoad"));  //$NON-NLS-1$
+		} else
+		{
+			try {
+				throw new Exception(Messages.getString("GppTraceGraph.traceGraphInternalErrorIn"));  //$NON-NLS-1$
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+		
+		// since the trace can be shown any of 3 ways (by thread, by binary, or
+		// by function), make sure that all 3 are ready for display
+		// Sse sorted vector to be consistent with other call to genericRefreshCumulativeThreadTable()
+		// fix issue with wrong color on newly opened npi file before a change in the table
+		if (this.profiledThreads.size() > 0) {
+			genericRefreshCumulativeThreadTable(this.profiledThreads.elements());
+			genericRefreshCumulativeThreadTable(this.sortedProfiledThreads.elements());
+		}
+		if (this.profiledBinaries.size() > 0) {
+			genericRefreshCumulativeThreadTable(this.profiledBinaries.elements());
+			genericRefreshCumulativeThreadTable(this.sortedProfiledBinaries.elements());
+		}
+		if (this.profiledFunctions.size() > 0) {
+			genericRefreshCumulativeThreadTable(this.profiledFunctions.elements());
+			genericRefreshCumulativeThreadTable(this.sortedProfiledFunctions.elements());
+		}
+		
+		if (   this.profiledThreads.size() <= 0
+			&& this.profiledBinaries.size() <= 0
+			&& this.profiledFunctions.size() <= 0) {
+			try {
+				throw new Exception(Messages.getString("GppTraceGraph.traceGraphInternalErrorAt"));  //$NON-NLS-1$
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+
+		this.vPanel = new GppVisualiserPanel(this);
+	}
+	
+	/*
+	 * Combine all vectors elements that are below the threshold into a single
+	 * vector element. Assumes that the input vector is sorted by decreasing sample count.
+	 */
+	private void filterSortedByThreshold(int graphIndex, int thresholdCount, ProfiledThreshold pThreshold, Vector<ProfiledGeneric> pGenerics)
+	{
+		// count and remove items below the threshold 
+		for (int i = pGenerics.size() - 1; i >= 0; i--) {
+			if (pGenerics.elementAt(i).getTotalSampleCount() < thresholdCount) {
+				pThreshold.addItem(graphIndex, pGenerics.elementAt(i), 0);
+				pGenerics.removeElementAt(i);
+			} else {
+				break;
+			}
+		}
+	}
+
+	public GppTrace getGppTrace() {
+		return (GppTrace)this.getTrace();
+	}
+
+	public int getGraphIndex()
+	{
+		return this.graphIndex;
+	}
+
+	public void piEventReceived(PIEvent be)
+	{
+		switch (be.getType())
+		{
+			// determine the threads that can be shown, and get rid of all drilldowns
+			case PIEvent.THRESHOLD_THREAD_CHANGED:
+				if (this.getGraphIndex() == PIPageEditor.THREADS_PAGE)
+					this.getThreadTable().action("changeThresholdThread"); //$NON-NLS-1$
+				switch (this.drawMode) {
+				case Defines.THREADS:
+				case Defines.THREADS_FUNCTIONS:
+				case Defines.THREADS_FUNCTIONS_BINARIES:
+				case Defines.THREADS_BINARIES:
+				case Defines.THREADS_BINARIES_FUNCTIONS:
+				case Defines.BINARIES_THREADS:
+				case Defines.BINARIES_THREADS_FUNCTIONS:
+				case Defines.BINARIES_FUNCTIONS_THREADS:
+				case Defines.FUNCTIONS_THREADS:
+				case Defines.FUNCTIONS_THREADS_BINARIES:
+				case Defines.FUNCTIONS_BINARIES_THREADS:
+					this.setGraphImageChanged(true);
+				default:
+					break;
+			}
+				break;
+			case PIEvent.THRESHOLD_BINARY_CHANGED:
+				if (this.getGraphIndex() == PIPageEditor.BINARIES_PAGE)
+					this.getBinaryTable().action("changeThresholdBinary"); //$NON-NLS-1$
+				switch (this.drawMode) {
+				case Defines.THREADS_FUNCTIONS_BINARIES:
+				case Defines.THREADS_BINARIES:
+				case Defines.THREADS_BINARIES_FUNCTIONS:
+				case Defines.BINARIES:
+				case Defines.BINARIES_THREADS:
+				case Defines.BINARIES_THREADS_FUNCTIONS:
+				case Defines.BINARIES_FUNCTIONS:
+				case Defines.BINARIES_FUNCTIONS_THREADS:
+				case Defines.FUNCTIONS_THREADS_BINARIES:
+				case Defines.FUNCTIONS_BINARIES:
+				case Defines.FUNCTIONS_BINARIES_THREADS:
+					this.setGraphImageChanged(true);
+				default:
+					break;
+			}
+				break;
+			case PIEvent.THRESHOLD_FUNCTION_CHANGED:
+				if (this.getGraphIndex() == PIPageEditor.FUNCTIONS_PAGE)
+					this.getFunctionTable().action("changeThresholdFunction"); //$NON-NLS-1$
+				switch (this.drawMode) {
+				case Defines.THREADS_FUNCTIONS:
+				case Defines.THREADS_FUNCTIONS_BINARIES:
+				case Defines.THREADS_BINARIES_FUNCTIONS:
+				case Defines.BINARIES_THREADS_FUNCTIONS:
+				case Defines.BINARIES_FUNCTIONS:
+				case Defines.BINARIES_FUNCTIONS_THREADS:
+				case Defines.FUNCTIONS:
+				case Defines.FUNCTIONS_THREADS:
+				case Defines.FUNCTIONS_THREADS_BINARIES:
+				case Defines.FUNCTIONS_BINARIES:
+				case Defines.FUNCTIONS_BINARIES_THREADS:
+					this.setGraphImageChanged(true);
+				default:
+					break;
+			}
+				break;
+			// when the selection area changes, change the percent loads
+			// and the sample counts in all tables of this GPP graph
+			case PIEvent.SELECTION_AREA_CHANGED:
+				// this is the first GPP graph to be told of the selection area change,
+				// so it gathers the overall trace information
+				GppTrace trace = (GppTrace)this.getTrace();
+				trace.setSelectedArea();
+				
+				// take care of the threshold members
+				int sampleCount = 0;
+				int thresholdCount;
+				
+				if (graphIndex == PIPageEditor.THREADS_PAGE) {
+					thresholdCount = (Integer)NpiInstanceRepository.getInstance().getPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdCountThread"); //$NON-NLS-1$
+					if (thresholdCount > 0) {
+						for (int i = 0; i < profiledThreads.size(); i++)
+							if (profiledThreads.elementAt(i).getTotalSampleCount() < thresholdCount)
+								sampleCount += profiledThreads.elementAt(i).getSampleCount(graphIndex);
+						thresholdThread.setSampleCount(this.graphIndex, sampleCount);
+					}
+				} else if (graphIndex == PIPageEditor.BINARIES_PAGE) {
+					thresholdCount = (Integer)NpiInstanceRepository.getInstance().getPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdCountBinary"); //$NON-NLS-1$
+					if (thresholdCount > 0) {
+						for (int i = 0; i < profiledBinaries.size(); i++)
+							if (profiledBinaries.elementAt(i).getTotalSampleCount() < thresholdCount)
+								sampleCount += profiledBinaries.elementAt(i).getSampleCount(graphIndex);
+						thresholdBinary.setSampleCount(this.graphIndex, sampleCount);
+					}
+				} else if (graphIndex == PIPageEditor.FUNCTIONS_PAGE) {
+					thresholdCount = (Integer)NpiInstanceRepository.getInstance().getPersistState(uid, "com.nokia.carbide.cpp.pi.address.thresholdCountFunction"); //$NON-NLS-1$
+					if (thresholdCount > 0) {
+						for (int i = 0; i < profiledFunctions.size(); i++)
+							if (profiledFunctions.elementAt(i).getTotalSampleCount() < thresholdCount)
+								sampleCount += profiledFunctions.elementAt(i).getSampleCount(graphIndex);
+						thresholdFunction.setSampleCount(this.graphIndex, sampleCount);
+					}
+				}
+
+				double startTime = PIPageEditor.currentPageEditor().getStartTime();
+				double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+				
+				// send this message to the 2 other GPP graphs
+				PIEvent be2 = new PIEvent(be.getValueObject(),
+						PIEvent.SELECTION_AREA_CHANGED2);
+				
+				// update the selection area shown
+				for (int i = 0; i < 3; i++)
+				{
+					GppTraceGraph graph = trace.getGppGraph(i, getUid());
+
+					if (graph != this) {
+						graph.piEventReceived(be2);
+						// once per graph, update the selection interval shown
+						graph.getCompositePanel().getVisualiser().getTimeString().setText(ProfileVisualiser.getTimeInterval(startTime, endTime));
+					}
+					
+					// change the graph's selected time interval
+					graph.setSelectionStart((double) startTime * 1000);
+					graph.setSelectionEnd((double) endTime * 1000);
+					graph.parentComponent.setSelectionFields((int)(startTime * 1000), (int)(endTime * 1000));
+				}
+
+				this.parentComponent.getSashForm().redraw();
+				be = be2;
+				// FALL THROUGH
+			case PIEvent.SELECTION_AREA_CHANGED2:
+			{
+				// this code lets each graph's base thread/binary/function table update the other tables
+				switch (drawMode)
+				{
+					case Defines.THREADS:
+					case Defines.THREADS_FUNCTIONS:
+					case Defines.THREADS_FUNCTIONS_BINARIES:
+					case Defines.THREADS_BINARIES:
+					case Defines.THREADS_BINARIES_FUNCTIONS:
+				    {
+				        this.threadTable.piEventReceived(be);
+				        break;
+				    }
+					case Defines.BINARIES:
+					case Defines.BINARIES_THREADS:
+					case Defines.BINARIES_THREADS_FUNCTIONS:
+					case Defines.BINARIES_FUNCTIONS:
+					case Defines.BINARIES_FUNCTIONS_THREADS:
+					{
+				        this.binaryTable.piEventReceived(be);
+						break;
+					}
+					case Defines.FUNCTIONS:
+					case Defines.FUNCTIONS_THREADS:
+					case Defines.FUNCTIONS_THREADS_BINARIES:
+					case Defines.FUNCTIONS_BINARIES:
+					case Defines.FUNCTIONS_BINARIES_THREADS:
+					{
+				        this.functionTable.piEventReceived(be);
+						break;
+					}
+				}
+
+				this.vPanel.refreshCumulativeThreadTable();
+				this.setGraphImageChanged(true);	// any selection change to drill down will change graph
+				this.repaint();
+				break;
+			}
+			
+			// in the graph, show all values from the rightmost table
+			case PIEvent.SET_FILL_ALL_THREADS:
+				this.setGraphImageChanged(true);	// any selection change to drill down will change graph
+				this.vPanel.piEventReceived(be);
+				break;
+
+			// in the graph, don't fill between the lines will the color of
+			// the line above
+			case PIEvent.SET_FILL_OFF:
+				this.setGraphImageChanged(true);	// any selection change to drill down will change graph
+				this.vPanel.piEventReceived(be);
+				break;
+
+			// in the graph, show bars
+			case PIEvent.GPP_SET_BAR_GRAPH_ON:
+				this.vPanel.piEventReceived(be);
+				break;
+
+			// in the graph, show polylines 
+			case PIEvent.GPP_SET_BAR_GRAPH_OFF:
+				this.vPanel.piEventReceived(be);
+				break;
+
+			// in the graph, show only the values from selected rows in the
+			// rightmost table
+			case PIEvent.SET_FILL_SELECTED_THREAD:
+				this.setGraphImageChanged(true);	// any selection change to drill down will change graph
+				this.vPanel.piEventReceived(be);
+				break;
+
+			// Redraw the graph because the thread table's selected values have changed.
+			// The thread table is handled (setting of array of selected threads
+			// and table redraw) by the table selection listener or mouse listener.
+			case PIEvent.CHANGED_THREAD_TABLE:
+				switch (drawMode)
+				{
+					case Defines.THREADS_BINARIES:
+					case Defines.THREADS_BINARIES_FUNCTIONS:
+					case Defines.THREADS_FUNCTIONS:
+					case Defines.THREADS_FUNCTIONS_BINARIES:
+					{
+						this.threadTable.piEventReceived(be);
+						break;
+					}
+					case Defines.BINARIES_THREADS_FUNCTIONS:
+					{
+						this.binaryTable.piEventReceived(be);
+						break;
+					}
+					case Defines.FUNCTIONS_THREADS_BINARIES:
+					{
+						this.functionTable.piEventReceived(be);
+						break;
+					}
+					case Defines.THREADS:
+					case Defines.BINARIES:
+					case Defines.BINARIES_THREADS:
+					case Defines.BINARIES_FUNCTIONS:
+					case Defines.BINARIES_FUNCTIONS_THREADS:
+					case Defines.FUNCTIONS:
+					case Defines.FUNCTIONS_THREADS:
+					case Defines.FUNCTIONS_BINARIES:
+					case Defines.FUNCTIONS_BINARIES_THREADS:
+					default:
+						break;
+				}
+
+				this.vPanel.refreshCumulativeThreadTable();
+				this.repaint();
+			    //if fill selected, the graph is drawn again
+				this.vPanel.piEventReceived(be);
+				break;
+
+			// Redraw the graph because the binary table's selected values have changed.
+			// The binary table is handled (setting of array of selected binaries
+			// and table redraw) by the table selection listener or mouse listener.
+			case PIEvent.CHANGED_BINARY_TABLE:
+				switch(drawMode)
+				{
+					case Defines.BINARIES_THREADS:
+					case Defines.BINARIES_THREADS_FUNCTIONS:
+					case Defines.BINARIES_FUNCTIONS:
+					case Defines.BINARIES_FUNCTIONS_THREADS:
+					{
+						this.binaryTable.piEventReceived(be);
+						break;
+					}
+					case Defines.THREADS_BINARIES_FUNCTIONS:
+					{
+						this.threadTable.piEventReceived(be);
+						break;
+					}
+					case Defines.FUNCTIONS_BINARIES_THREADS:
+					{
+						this.functionTable.piEventReceived(be);
+						break;
+					}
+					case Defines.THREADS:
+					case Defines.THREADS_BINARIES:
+					case Defines.THREADS_FUNCTIONS:
+					case Defines.THREADS_FUNCTIONS_BINARIES:
+					case Defines.BINARIES:
+					case Defines.FUNCTIONS:
+					case Defines.FUNCTIONS_THREADS:
+					case Defines.FUNCTIONS_THREADS_BINARIES:
+					case Defines.FUNCTIONS_BINARIES:
+					default:
+						break;
+				}
+
+				this.vPanel.refreshCumulativeThreadTable();
+				this.repaint();
+			    //if fill selected, the graph is drawn again
+				this.vPanel.piEventReceived(be);
+				break;
+
+			// Redraw the graph because the function table's selected values have changed.
+			// The function table is handled (setting of array of selected functions
+			// and table redraw) by the table selection listener or mouse listener.
+			case PIEvent.CHANGED_FUNCTION_TABLE:
+				switch(drawMode)
+				{
+					case Defines.FUNCTIONS_THREADS:
+					case Defines.FUNCTIONS_THREADS_BINARIES:
+					case Defines.FUNCTIONS_BINARIES:
+					case Defines.FUNCTIONS_BINARIES_THREADS:
+					{
+						this.functionTable.piEventReceived(be);
+						break;
+					}
+					case Defines.THREADS_FUNCTIONS_BINARIES:
+					{
+						this.threadTable.piEventReceived(be);
+						break;
+					}
+					case Defines.BINARIES_FUNCTIONS_THREADS:
+					{
+						this.binaryTable.piEventReceived(be);
+						break;
+					}
+					case Defines.THREADS:
+					case Defines.THREADS_BINARIES:
+					case Defines.THREADS_BINARIES_FUNCTIONS:
+					case Defines.THREADS_FUNCTIONS:
+					case Defines.BINARIES:
+					case Defines.BINARIES_THREADS:
+					case Defines.BINARIES_THREADS_FUNCTIONS:
+					case Defines.BINARIES_FUNCTIONS:
+					case Defines.FUNCTIONS:
+					default:
+						break;
+				}
+
+				this.vPanel.refreshCumulativeThreadTable();
+				this.repaint();
+				this.vPanel.piEventReceived(be);
+				break;
+
+			case PIEvent.MOUSE_PRESSED:
+				switch (drawMode) {
+					case Defines.THREADS:
+					{
+						break;
+					}
+					case Defines.BINARIES:
+					{
+						break;
+					}
+					case Defines.FUNCTIONS:
+					{
+						break;
+					}
+					default:
+					{
+						break;
+					}
+				}
+			    this.parentComponent.setActive(this);
+				break;
+				
+			default:
+				break;
+		}
+	}
+	
+	public void actionPerformed(ActionEvent ae)
+	{
+	}
+	
+	public void action(String actionString)
+	{
+	    System.out.println(Messages.getString("GppTraceGraph.actionString")+actionString);  //$NON-NLS-1$
+	    
+	    if (actionString.equals("resetToCurrentMode")) //$NON-NLS-1$
+	    {
+	        if (drawMode == Defines.THREADS_FUNCTIONS)
+	            this.setDrawMode(Defines.THREADS);
+	        else if (drawMode == Defines.BINARIES_FUNCTIONS)
+	            this.setDrawMode(Defines.BINARIES);
+	        else
+	            System.out.println(Messages.getString("GppTraceGraph.drawMode") + drawMode); //should not print this ever  //$NON-NLS-1$
+	    }
+	    else
+	    {
+			switch (drawMode)
+			{
+				case Defines.THREADS:
+				case Defines.THREADS_FUNCTIONS:
+				case Defines.THREADS_FUNCTIONS_BINARIES:
+				case Defines.THREADS_BINARIES:
+				case Defines.THREADS_BINARIES_FUNCTIONS:
+			    {
+					this.threadTable.action(actionString);
+			        break;
+			    }
+				case Defines.BINARIES:
+				case Defines.BINARIES_THREADS:
+				case Defines.BINARIES_THREADS_FUNCTIONS:
+				case Defines.BINARIES_FUNCTIONS:
+				case Defines.BINARIES_FUNCTIONS_THREADS:
+				{
+					this.binaryTable.action(actionString);
+					break;
+				}
+				case Defines.FUNCTIONS:
+				case Defines.FUNCTIONS_THREADS:
+				case Defines.FUNCTIONS_THREADS_BINARIES:
+				case Defines.FUNCTIONS_BINARIES:
+				case Defines.FUNCTIONS_BINARIES_THREADS:
+				{
+					this.functionTable.action(actionString);
+					break;
+				}
+			}
+	    }
+	}
+	
+	public void focusGained(FocusEvent fe)
+	{
+	}
+
+	public void focusLost(FocusEvent fe)
+	{
+	}
+
+	public void mouseDragged(MouseEvent me) {
+	}
+
+	public void mouseEntered(MouseEvent me) {
+	}
+
+	public void mouseExited(MouseEvent me) {
+	}
+
+	public void mouseHover(MouseEvent me) {
+	}
+
+	public void mousePressed(MouseEvent me) {
+	}
+
+	public void mouseReleased(MouseEvent me) {
+	}
+
+	public void mouseDoubleClicked(MouseEvent me)
+	{
+	    Object[] result = this.getProfiledGenericUnderMouse(me);
+		if ((result == null)) 
+		{
+			return;
+		}
+		
+		ProfiledGeneric pg = (ProfiledGeneric)result[0];
+		GenericTable gtu = null;
+
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES_THREADS:
+			case Defines.FUNCTIONS_THREADS:
+			case Defines.BINARIES_FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_BINARIES_THREADS:
+			{
+			    gtu = this.threadTable;
+			    break;
+			}
+			case Defines.BINARIES:
+			case Defines.THREADS_BINARIES:
+			case Defines.THREADS_FUNCTIONS_BINARIES:
+			case Defines.FUNCTIONS_BINARIES:
+			case Defines.FUNCTIONS_THREADS_BINARIES:
+			{
+			    gtu = this.binaryTable;
+				break;
+			}
+			case Defines.FUNCTIONS:
+			case Defines.THREADS_FUNCTIONS:
+			case Defines.BINARIES_FUNCTIONS:
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			case Defines.BINARIES_THREADS_FUNCTIONS:
+			{
+			    gtu = this.functionTable;
+			    break;
+			}
+			default:
+				break;
+		}
+
+		if (pg != null)
+		{
+			if (gtu.getIndex(pg) == null)
+				return;
+			int[] index = new int[1];
+			index[0] = gtu.getIndex(pg).intValue();
+			gtu.setSelectedIndicesXOR(index);
+		}
+	}
+
+	private Object[] getProfiledGenericUnderMouse(MouseEvent me)
+	{		
+		Object[] result = new Object[2];
+		double x = me.x * this.getScale();
+		double y = me.y;
+		
+		y = y * 100 / (this.getVisualSize().height - GppTraceGraph.xLegendHeight);
+		y = 100 - y;
+		if (y <= 0)
+			return null;
+		
+		// mouse event may return out of range X, that may 
+		// crash when we use it to index data array
+		x = x >= 0 ? x : 0;
+		
+		if (x > PIPageEditor.currentPageEditor().getMaxEndTime() * 1000)
+			return null;
+
+		if (me.x >= (int)(this.getSize().width)) {
+			x = (this.getSize().width - 1) * this.getScale();
+		}
+		
+		GppTrace gppTrace = (GppTrace) (this.getTrace());
+
+		Enumeration<ProfiledGeneric> enumer = null;
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES_THREADS:
+			case Defines.FUNCTIONS_THREADS:
+			case Defines.BINARIES_FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_BINARIES_THREADS:
+			{
+				enumer = gppTrace.getSortedThreadsElements();
+			    break;
+			}
+			case Defines.BINARIES:
+			case Defines.THREADS_BINARIES:
+			case Defines.THREADS_FUNCTIONS_BINARIES:
+			case Defines.FUNCTIONS_BINARIES:
+			case Defines.FUNCTIONS_THREADS_BINARIES:
+			{
+				enumer = gppTrace.getSortedBinariesElements();
+				break;
+			}
+			case Defines.FUNCTIONS:
+			case Defines.THREADS_FUNCTIONS:
+			case Defines.BINARIES_FUNCTIONS:
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			case Defines.BINARIES_THREADS_FUNCTIONS:
+			{
+		        enumer = gppTrace.getSortedFunctionsElements();
+			    break;
+			}
+			default:
+				break;
+		}
+
+		if (enumer == null)
+			return null;
+
+		Vector<ProfiledGeneric> activeThreads = new Vector<ProfiledGeneric>();
+		while(enumer.hasMoreElements())
+		{
+			ProfiledGeneric pg = (ProfiledGeneric)enumer.nextElement();
+			if (pg.isEnabled(this.graphIndex))		
+			{		
+				activeThreads.add(pg);
+			}
+		}
+		
+		int cumPrev = 0;
+		int cumNext = 0;
+		
+		int topPrev = 0;
+		int topNext = 0;
+
+		double cumDiff = 0;
+		double topDiff = 0;
+		
+		ProfiledGeneric currentProfiled = null;
+		
+		enumer = activeThreads.elements();
+		if (enumer.hasMoreElements())
+		    currentProfiled = enumer.nextElement();
+		
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+		int granularityValue = gppTrace.samples.size() > GppTraceGraph.granularityValue ? GppTraceGraph.granularityValue : gppTrace.samples.size();  
+
+		while (true)
+		{
+			if (currentProfiled != null)
+			{
+				int[] cum = currentProfiled.getCumulativeList(graphIndex);
+				int[] val = currentProfiled.getActivityList();
+				if (cum == null || val == null)
+					return null;
+				
+				int current = ((int)(x / samplingInterval)) / granularityValue;
+				
+				if ((current >= cum.length) || (current + 1 >= cum.length)) 
+					return null;
+					
+				cumPrev = cum[current];	
+				cumNext = cum[current + 1];
+
+				topPrev = val[current];
+				topNext = val[current + 1];
+
+				cumDiff = (cumNext - cumPrev) * ((double)((x / samplingInterval) % granularityValue) / (granularityValue * 1d));
+				topDiff = (topNext - topPrev) * ((double)((x / samplingInterval) % granularityValue) / (granularityValue * 1d));
+			}
+			else
+			{
+				if (y >= cumPrev + topPrev + topDiff + cumDiff) 
+				{
+				    currentProfiled = null;
+					break;
+				}
+				else
+				{
+					break;
+				}
+			}
+			
+			if (y >= cumPrev + cumDiff && y < cumPrev + topPrev + topDiff + cumDiff ) 
+			{
+				break;
+			}
+			else
+			{
+				if (enumer.hasMoreElements())
+				{
+				    currentProfiled = (ProfiledGeneric)enumer.nextElement();
+				}
+				else
+				{
+				    currentProfiled = null;
+				}
+			}
+		}
+		
+		if (currentProfiled != null)
+		{
+			String loadString = "" + (topPrev + topDiff); //$NON-NLS-1$
+			int index = loadString.indexOf('.');
+			
+			if (index > 0 && ((index + 2) < loadString.length()))
+				loadString = loadString.substring(0, index + 2); 
+			
+			result[0] = currentProfiled;
+			result[1] = loadString;				
+		}
+		else
+		{
+			String totalString = "" + (100 - (cumPrev + topPrev + topDiff + cumDiff)); //$NON-NLS-1$
+			int index = totalString.indexOf('.');
+			
+			if (index > 0 && ((index + 2) < totalString.length()))
+				totalString = totalString.substring(0, index + 2);
+
+			result[0] = null;
+			result[1] = totalString;
+		}
+		return result;
+	}
+
+	public void mouseMoved(MouseEvent me)
+	{
+		double x = me.x * this.getScale();
+		double y = me.y;
+		
+		// mouse event may return out of range X, that may 
+		// crash when we use it to index data array
+		x = x >= 0 ? x : 0;
+		
+		if (   y >= this.getVisualSizeY() - GppTraceGraph.xLegendHeight
+			|| x >= PIPageEditor.currentPageEditor().getMaxEndTime() * 1000)
+		{
+			this.setToolTipText(null);
+			return;
+		}
+
+		if (   NpiInstanceRepository.getInstance() == null
+			|| NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval") == null) //$NON-NLS-1$)
+			return;
+		
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+
+		if (this.barMode == GppTraceGraph.BAR_MODE_ON) {
+			GppSample samp = (GppSample)((GenericSampledTrace)this.getTrace()).getSample(((int)(x + .0005))/samplingInterval);
+			switch (drawMode)
+			{
+				case Defines.THREADS:
+				case Defines.BINARIES_THREADS:
+				case Defines.FUNCTIONS_THREADS:
+				case Defines.BINARIES_FUNCTIONS_THREADS:
+				case Defines.FUNCTIONS_BINARIES_THREADS:
+				{
+					try {
+						this.setToolTipText(samp.sampleSynchTime+"ms @"+  //$NON-NLS-1$
+											Long.toHexString(samp.programCounter)+" "+  //$NON-NLS-1$
+											samp.thread.process.name+"::"+  //$NON-NLS-1$
+											samp.thread.threadName+"_"+  //$NON-NLS-1$
+											samp.thread.threadId);}
+					catch (NullPointerException e2)
+					{
+						this.setToolTipText(Messages.getString("GppTraceGraph.cannotResolveThreadName"));  //$NON-NLS-1$
+					}
+					break;
+				}
+				case Defines.BINARIES:
+				case Defines.THREADS_BINARIES:
+				case Defines.THREADS_FUNCTIONS_BINARIES:
+				case Defines.FUNCTIONS_BINARIES:
+				case Defines.FUNCTIONS_THREADS_BINARIES:
+				{
+					try {
+						if (samp.currentFunctionSym.functionBinary.binaryName.endsWith(Messages.getString("GppTraceGraph.NotFound")))  //$NON-NLS-1$
+							throw new NullPointerException();
+						this.setToolTipText(samp.sampleSynchTime+"ms @"+  //$NON-NLS-1$
+											Long.toHexString(samp.programCounter)+" "+  //$NON-NLS-1$
+											samp.currentFunctionSym.functionBinary.binaryName);
+					} catch (NullPointerException e)
+					{
+						try {
+							this.setToolTipText(samp.sampleSynchTime+"ms @"+  //$NON-NLS-1$
+												Long.toHexString(samp.programCounter)+" "+  //$NON-NLS-1$
+												samp.currentFunctionItt.functionBinary.binaryName);}
+						catch (NullPointerException e2)
+						{
+							this.setToolTipText(Messages.getString("GppTraceGraph.cannotResolveBinaryName"));  //$NON-NLS-1$
+						}
+					}
+					break;
+				}
+				case Defines.FUNCTIONS:
+				case Defines.THREADS_FUNCTIONS:
+				case Defines.BINARIES_FUNCTIONS:
+				case Defines.THREADS_BINARIES_FUNCTIONS:
+				case Defines.BINARIES_THREADS_FUNCTIONS:
+				{
+					try {
+						if (samp.currentFunctionSym.functionBinary.binaryName.endsWith(Messages.getString("GppTraceGraph.notFound")))  //$NON-NLS-1$
+							throw new NullPointerException();
+						
+						this.setToolTipText(samp.sampleSynchTime+"ms @"+  //$NON-NLS-1$
+											Long.toHexString(samp.programCounter)+" "+  //$NON-NLS-1$
+											samp.currentFunctionSym.functionName);}
+					catch (NullPointerException e)
+					{
+						try{this.setToolTipText(samp.sampleSynchTime+"ms @"+  //$NON-NLS-1$
+												Long.toHexString(samp.programCounter)+" "+  //$NON-NLS-1$
+												samp.currentFunctionItt.functionName);}
+						catch (NullPointerException e2)
+						{
+							this.setToolTipText(Messages.getString("GppTraceGraph.cannotResolveFunctionName"));  //$NON-NLS-1$
+						}
+					}
+					break;
+				}
+				default:
+					return;
+			}
+
+			return;  // return for barMode == GppTraceGraph.BAR_MODE_ON
+		}
+
+		// barMode == GppTraceGraph.BAR_MODE_OFF
+
+    	Object[] result = this.getProfiledGenericUnderMouse(me);
+		if (result == null)
+		{
+			this.setToolTipText(null);
+			return;
+		}
+		
+		if (me.x >= (int)(this.getSize().width)) {
+			x = (this.getSize().width - 1) * this.getScale();
+		}
+		
+		ProfiledGeneric pg = null;
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES_THREADS:
+			case Defines.FUNCTIONS_THREADS:
+			case Defines.BINARIES_FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_BINARIES_THREADS:
+			{
+			    pg = (ProfiledThread)result[0];
+			    break;
+			}
+			case Defines.BINARIES:
+			case Defines.THREADS_BINARIES:
+			case Defines.THREADS_FUNCTIONS_BINARIES:
+			case Defines.FUNCTIONS_BINARIES:
+			case Defines.FUNCTIONS_THREADS_BINARIES:
+			{
+			    pg = (ProfiledBinary)result[0];
+				break;
+			}
+			case Defines.FUNCTIONS:
+			case Defines.THREADS_FUNCTIONS:
+			case Defines.BINARIES_FUNCTIONS:
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			case Defines.BINARIES_THREADS_FUNCTIONS:
+			{
+			    pg = (ProfiledFunction)result[0];
+			    break;
+			}
+			default:
+				break;
+		}
+
+		String string = (String)result[1];
+		if (pg == null)
+		{
+			switch (drawMode)
+			{
+				case Defines.THREADS:
+				case Defines.BINARIES_THREADS:
+				case Defines.FUNCTIONS_THREADS:
+				case Defines.BINARIES_FUNCTIONS_THREADS:
+				case Defines.FUNCTIONS_BINARIES_THREADS:
+				{
+				    this.setToolTipText(string + "% " + Messages.getString("GppTraceGraph.unknownOrExcludedThreads"));  //$NON-NLS-1$ //$NON-NLS-2$
+				    break;
+				}
+				case Defines.BINARIES:
+				case Defines.THREADS_BINARIES:
+				case Defines.THREADS_FUNCTIONS_BINARIES:
+				case Defines.FUNCTIONS_BINARIES:
+				case Defines.FUNCTIONS_THREADS_BINARIES:
+				{
+				    this.setToolTipText(string + "% " + Messages.getString("GppTraceGraph.unknownOrExcludedBinaries"));  //$NON-NLS-1$ //$NON-NLS-2$
+					break;
+				}
+				case Defines.FUNCTIONS:
+				case Defines.THREADS_FUNCTIONS:
+				case Defines.BINARIES_FUNCTIONS:
+				case Defines.THREADS_BINARIES_FUNCTIONS:
+				case Defines.BINARIES_THREADS_FUNCTIONS:
+				{
+				    this.setToolTipText(string + "% " + Messages.getString("GppTraceGraph.unknownOrExcludedFunctions"));  //$NON-NLS-1$ //$NON-NLS-2$
+				    break;
+				}
+				default:
+					break;
+			}
+		}
+		else
+		{
+			this.setToolTipText(string + "% " + pg.getNameString());  //$NON-NLS-1$
+		}
+	}
+	
+	public GenericTable getTableUtils()
+	{
+		switch (drawMode)
+		{
+			case Defines.THREADS:
+			case Defines.BINARIES_THREADS:
+			case Defines.FUNCTIONS_THREADS:
+			case Defines.BINARIES_FUNCTIONS_THREADS:
+			case Defines.FUNCTIONS_BINARIES_THREADS:
+			{
+			    return this.threadTable;
+			}
+			case Defines.BINARIES:
+			case Defines.THREADS_BINARIES:
+			case Defines.THREADS_FUNCTIONS_BINARIES:
+			case Defines.FUNCTIONS_BINARIES:
+			case Defines.FUNCTIONS_THREADS_BINARIES:
+			{
+			    return this.binaryTable;
+			}
+			case Defines.FUNCTIONS:
+			case Defines.THREADS_FUNCTIONS:
+			case Defines.BINARIES_FUNCTIONS:
+			case Defines.THREADS_BINARIES_FUNCTIONS:
+			case Defines.BINARIES_THREADS_FUNCTIONS:
+			{
+			    return this.functionTable;
+			}
+			default:
+				break;
+		}
+
+		System.out.println(Messages.getString("GppTraceGraph.debugDrawMode") + drawMode);  //$NON-NLS-1$
+	    return null;
+	}
+	
+	public GppVisualiserPanel getVisualiserPanel()
+	{
+		return this.vPanel;
+	}
+	
+	public AddrThreadTable  getThreadTable() {
+		return this.threadTable;
+	}
+	
+	public AddrBinaryTable getBinaryTable() {
+		return this.binaryTable;
+	}
+	
+	public AddrFunctionTable getFunctionTable() {
+		return this.functionTable;
+	}
+
+	public void setThreadTableViewer(CheckboxTableViewer tableViewer) {
+		this.threadTable.setTableViewer(tableViewer);
+	}
+	
+	public void setBinaryTableViewer(CheckboxTableViewer tableViewer) {
+		this.binaryTable.setTableViewer(tableViewer);;
+	}
+	
+	public void setFunctionTableViewer(CheckboxTableViewer tableViewer) {
+		this.functionTable.setTableViewer(tableViewer);
+	}
+
+	public void paint(Panel panel, Graphics graphics)
+	{
+		this.setSize(panel.getClientArea().width, panel.getClientArea().height);
+		this.vPanel.paintComponent(panel, graphics);
+	}
+
+	public void paintLeftLegend(FigureCanvas figureCanvas, GC gc)
+	{
+		GC localGC = gc;
+		
+		if (gc == null)
+			gc = new GC(PIPageEditor.currentPageEditor().getSite().getShell());
+
+		Rectangle rect = ((GraphComposite) figureCanvas.getParent()).figureCanvas.getClientArea();
+		
+		int visY = rect.height;
+		
+		float visYfloat = visY - GppTraceGraph.xLegendHeight;
+		
+		if (visYfloat < 0f)
+			visYfloat = 0f;
+		
+		gc.setForeground(ColorPalette.getColor(new RGB(100, 100, 100)));
+		gc.setBackground(ColorPalette.getColor(new RGB(255, 255, 255)));
+		
+		// write each next number if there is space
+		// float values will be slightly smaller than the actual result
+		// and they will be incremented by one, since rounding to int
+		// discards the remaining decimals
+		int percent = 100;
+		int previousBottom = 0;		// bottom of the previous legend drawn
+		for (float y = 0f; percent >= 0; y += visYfloat * 10000f / 100001f, percent -= 10)
+		{
+			String legend = "" + percent + "%"; //$NON-NLS-1$ //$NON-NLS-2$
+			Point extent = gc.stringExtent(legend);
+			
+			gc.drawLine(GenericTraceGraph.yLegendWidth - 3, (int)y + 1, GenericTraceGraph.yLegendWidth, (int)y + 1);
+
+			if ((int)y >= previousBottom)
+			{
+				gc.drawString(legend, GenericTraceGraph.yLegendWidth - extent.x - 4, (int)y);
+				previousBottom = (int)y + extent.y;
+			}
+		}
+		
+		if (localGC == null) {
+			gc.dispose();
+			figureCanvas.redraw();
+		}
+	}
+	
+	public void repaint()
+	{
+		this.parentComponent.repaintComponent();
+	}
+	
+	public void drawBarsGpp(Vector<ProfiledGeneric> profiledGenerics, Graphics graphics, Object[] selection)
+	{
+		if (   this.updateCumulativeThreadTableIsNeeded
+			|| this.barGraphData == null)
+		{
+			this.updateBarGraphData(profiledGenerics);
+		}
+		
+		this.updateIfNeeded(profiledGenerics);
+		
+		Enumeration<BarGraphData> barEnum = this.barGraphData.elements();
+
+		int drawX = -1;
+		int lastDrawX = -10;
+		double scale = this.getScale();
+		int y = this.getVisualSizeY() - 51;
+		org.eclipse.draw2d.geometry.Rectangle visibleArea = this.getVisibleArea(graphics);
+
+		while(barEnum.hasMoreElements())
+		{
+			BarGraphData bgd = barEnum.nextElement();
+			drawX = (int)(((double)bgd.x) / scale);
+			
+			if (   drawX >= visibleArea.x
+				&& drawX < visibleArea.x + visibleArea.width )
+			{
+				if (debug)
+					System.out.println(Messages.getString("GppTraceGraph.draw") + drawX + " " + scale + " " + bgd.x);    //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				if (drawX != lastDrawX)
+				{
+					graphics.setForegroundColor(bgd.color);
+					graphics.drawLine(drawX, 0, drawX, y);
+					lastDrawX = drawX;
+				}
+			}
+		}
+	}
+
+	public void updateBarGraphData(Vector profiledGenerics)
+	{
+		if (this.barGraphData == null)
+			this.barGraphData = new Vector<BarGraphData>();
+		this.barGraphData.clear();
+
+		int x = 0;
+		
+		// find the first enabled profiled generic
+		int firstEnabled;
+		for (firstEnabled = 0; firstEnabled < profiledGenerics.size(); firstEnabled++)
+			if (((ProfiledGeneric)profiledGenerics.get(firstEnabled)).isEnabled(this.graphIndex))
+				break;
+		
+		// return if there are no enabled profiled generics
+		if (firstEnabled == profiledGenerics.size())
+			return;
+		
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+		Enumeration samples = ((GenericSampledTrace)this.getTrace()).getSamples();
+		while (samples.hasMoreElements())
+		{
+			GppSample gs = (GppSample)samples.nextElement();
+			
+			// for each of the tens of thousands of samples, loop through each of the
+			// perhaps thousands of functions, hundreds of binaries, or tens of threads
+			for (int i = firstEnabled; i < profiledGenerics.size(); i++)
+			{
+				// find the next enabled profiled generic, if any
+				while (   (i < profiledGenerics.size()
+					   && !((ProfiledGeneric)profiledGenerics.get(i)).isEnabled(this.graphIndex)))
+					i++;
+				if (i >= profiledGenerics.size())
+					break;
+
+				ProfiledGeneric pg = (ProfiledGeneric)profiledGenerics.get(i);
+
+				if (   ((pg instanceof ProfiledThread)   && (pg.getIndex() == gs.threadIndex))
+				    || ((pg instanceof ProfiledBinary)   && (pg.getIndex() == gs.binaryIndex))
+				    || ((pg instanceof ProfiledFunction) && (pg.getIndex() == gs.functionIndex))) {
+					BarGraphData bgd = new BarGraphData();
+					bgd.color = pg.getColor();
+					bgd.x = x;
+					this.barGraphData.add(bgd);
+					break;
+				}
+			}
+			x += samplingInterval;
+		}
+	}	
+
+	public void refreshDataFromTrace()
+	{
+		refreshDataFromTrace((GppTrace)this.getTrace());
+
+	    if (this.vPanel != null)
+		{
+			this.vPanel.refreshCumulativeThreadTable();
+		}
+	}
+
+	public static void refreshDataFromTrace(GppTrace gppTrace)
+	{
+		Enumeration enumer = gppTrace.getSamples();
+		
+		int granularityValue = gppTrace.samples.size() > GppTraceGraph.granularityValue ? GppTraceGraph.granularityValue : gppTrace.samples.size();  
+
+		Hashtable<String,ProfiledGeneric> profiledThreads   = new Hashtable<String,ProfiledGeneric>();
+		Hashtable<String,ProfiledGeneric> profiledBinaries  = new Hashtable<String,ProfiledGeneric>();
+		Hashtable<String,ProfiledGeneric> profiledFunctions = new Hashtable<String,ProfiledGeneric>();
+		
+		Hashtable<ProfiledGeneric,Integer> threadPercentages   = new Hashtable<ProfiledGeneric,Integer>();
+		Hashtable<ProfiledGeneric,Integer> binaryPercentages   = new Hashtable<ProfiledGeneric,Integer>();
+		Hashtable<ProfiledGeneric,Integer> functionPercentages = new Hashtable<ProfiledGeneric,Integer>();
+		
+		int threadCount = 0;
+		int binaryCount = 0;
+		int functionCount = 0;
+		int count = 0;
+		int timeStamp = 0;
+		int stepValue = granularityValue;
+		char threadSymbol = 'A';
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+
+		Vector<ProfiledGeneric> sortedProfiledThreads   = gppTrace.getSortedThreads();
+		Vector<ProfiledGeneric> sortedProfiledBinaries  = gppTrace.getSortedBinaries();
+		Vector<ProfiledGeneric> sortedProfiledFunctions = gppTrace.getSortedFunctions();
+
+		Vector<ProfiledGeneric> unsortedProfiledThreads   = gppTrace.getIndexedThreads();
+		Vector<ProfiledGeneric> unsortedProfiledBinaries  = gppTrace.getIndexedBinaries();
+		Vector<ProfiledGeneric> unsortedProfiledFunctions = gppTrace.getIndexedFunctions();
+		
+		// reset these list so we can call refreshDataFromTrace mulitple times (e.g. import) while keeping size consistent
+		sortedProfiledThreads.clear();
+		sortedProfiledBinaries.clear();
+		sortedProfiledFunctions.clear();
+
+		unsortedProfiledThreads.clear();
+		unsortedProfiledBinaries.clear();
+		unsortedProfiledFunctions.clear();
+
+		boolean exit = false;
+		while (exit == false)
+		{
+			exit = !enumer.hasMoreElements();
+			if (exit == true) 
+			{
+				// for the final samples, modify the step value
+				// so that they will also be included
+				// now there are no new samples, so proceed directly to
+				// adding the final values to the percent list
+				stepValue = count;
+			}
+			else
+			{
+				count++;
+				
+				// there is at least one new sample in the enumeration, so resolve it 
+				GppSample sample = (GppSample)enumer.nextElement();
+				String threadName   = sample.thread.process.name + "::" + sample.thread.threadName + "_" + sample.thread.threadId;   //$NON-NLS-1$ //$NON-NLS-2$
+				String binaryName   = getBinaryName(sample);
+				String functionName = getFunctionName(sample);
+
+				ProfiledThread   pThread = null;
+				ProfiledBinary   pBinary = null;
+				ProfiledFunction pFunction = null;
+				
+				// handle new thread names
+				if (profiledThreads.containsKey(threadName))
+				{
+					pThread = (ProfiledThread)profiledThreads.get(threadName);
+					if (pThread.getThreadId() != sample.thread.threadId.intValue())
+					{
+						// this was not the same thread, even though the
+						// name was the same
+						pThread = null;
+					}
+				}
+			
+				if (pThread == null)
+				{
+					pThread = new ProfiledThread();
+					
+					pThread.setIndex(threadCount++);
+					pThread.setNameValues(threadSymbol++, threadName);
+					pThread.setColor(gppTrace.getThreadColorPalette().getColor(threadName));
+					
+					pThread.setThreadId(sample.thread.threadId.intValue());
+					
+					pThread.setActivityMarkCount((gppTrace.samples.size() + granularityValue) / granularityValue + 1);
+					for (int i = 0; i < timeStamp + stepValue * samplingInterval; i += stepValue * samplingInterval)
+					{
+						pThread.zeroActivityMarkValues(i);
+					}
+					profiledThreads.put(threadName, pThread);
+					sortedProfiledThreads.add((ProfiledGeneric)pThread);			
+					unsortedProfiledThreads.add((ProfiledGeneric)pThread);			
+				}
+				
+				pThread.incTotalSampleCount();
+				sample.threadIndex = pThread.getIndex();
+
+				if (threadPercentages.containsKey(pThread))
+				{
+					Integer value = (Integer)threadPercentages.get(pThread);
+					value = new Integer(value.intValue()+1);
+					threadPercentages.remove(pThread);
+					threadPercentages.put(pThread, value);
+				}
+				else
+				{
+					threadPercentages.put(pThread, new Integer(1));
+				}
+				
+				// handle new binary names
+				if (profiledBinaries.containsKey(binaryName))
+				{
+					pBinary = (ProfiledBinary)profiledBinaries.get(binaryName);
+				}
+			
+				if (pBinary == null)
+				{
+					pBinary = new ProfiledBinary();
+
+					pBinary.setIndex(binaryCount++);
+					pBinary.setNameString(binaryName);
+					pBinary.setColor(gppTrace.getBinaryColorPalette().getColor(binaryName));
+					
+					pBinary.setActivityMarkCount((gppTrace.samples.size() + granularityValue) / granularityValue + 1);
+					for (int i = 0; i < timeStamp + stepValue * samplingInterval; i += stepValue * samplingInterval)
+					{
+						pBinary.zeroActivityMarkValues(i);
+					}
+					profiledBinaries.put(binaryName,pBinary);
+					sortedProfiledBinaries.add((ProfiledGeneric)pBinary);			
+					unsortedProfiledBinaries.add((ProfiledGeneric)pBinary);			
+				}
+				
+				pBinary.incTotalSampleCount();
+				sample.binaryIndex = pBinary.getIndex();
+
+				if (binaryPercentages.containsKey(pBinary))
+				{
+					Integer value = (Integer)binaryPercentages.get(pBinary);
+					value = new Integer(value.intValue()+1);
+					binaryPercentages.remove(pBinary);
+					binaryPercentages.put(pBinary,value);
+				}
+				else
+				{
+					binaryPercentages.put(pBinary, new Integer(1));
+				}														
+				
+				// handle new function names
+				if (profiledFunctions.containsKey(functionName))
+				{
+					pFunction = (ProfiledFunction)profiledFunctions.get(functionName);
+				}
+			
+				if (pFunction == null)
+				{
+					pFunction = new ProfiledFunction();
+
+					pFunction.setIndex(functionCount++);
+					pFunction.setNameString(functionName);
+					pFunction.setFunctionAddress(getFunctionAddress(sample));
+					pFunction.setFunctionBinaryName(binaryName);
+					pFunction.setColor(gppTrace.getFunctionColorPalette().getColor(functionName));
+					
+					pFunction.setActivityMarkCount((gppTrace.samples.size() + granularityValue) / granularityValue + 1);
+					for (int i = 0; i < timeStamp + stepValue * samplingInterval; i += stepValue * samplingInterval)
+					{
+						pFunction.zeroActivityMarkValues(i);
+					}
+					profiledFunctions.put(functionName,pFunction);
+					sortedProfiledFunctions.add((ProfiledGeneric)pFunction);			
+					unsortedProfiledFunctions.add((ProfiledGeneric)pFunction);			
+				}
+
+				pFunction.incTotalSampleCount();
+				sample.functionIndex = pFunction.getIndex();
+
+				if (functionPercentages.containsKey(pFunction))
+				{
+					Integer value = (Integer)functionPercentages.get(pFunction);
+					value = new Integer(value.intValue()+1);
+					functionPercentages.remove(pFunction);
+					functionPercentages.put(pFunction,value);
+				}
+				else
+				{
+					functionPercentages.put(pFunction, new Integer(1));
+				}														
+			}
+			
+			// for each stepValue (or final values) samples
+			// add the data to the profiled threads, binaries, functions
+			if (stepValue != 0 && count == stepValue)
+			{
+				Vector<ProfiledGeneric> tmpVector;
+				
+				tmpVector = new Vector<ProfiledGeneric>(profiledThreads.values());
+				Enumeration<ProfiledGeneric> ptEnum = tmpVector.elements();
+				while (ptEnum.hasMoreElements())
+				{
+					ProfiledThread updatePt = (ProfiledThread)ptEnum.nextElement();
+					if (threadPercentages.containsKey(updatePt))
+					{
+						int samples = ((Integer)(threadPercentages.get(updatePt))).intValue();
+						int finalPerc = (samples * 100) / stepValue;
+						updatePt.addActivityMarkValues(timeStamp + stepValue * samplingInterval, finalPerc, samples);
+					}
+					else
+					{
+						updatePt.zeroActivityMarkValues(timeStamp + stepValue * samplingInterval);
+					}					
+				}
+				
+				tmpVector = new Vector<ProfiledGeneric>(profiledBinaries.values());
+				Enumeration<ProfiledGeneric> pbEnum = tmpVector.elements();
+				while (pbEnum.hasMoreElements())
+				{
+					ProfiledBinary updatePb = (ProfiledBinary)pbEnum.nextElement();
+					if (binaryPercentages.containsKey(updatePb))
+					{
+						int samples = ((Integer)(binaryPercentages.get(updatePb))).intValue();
+						int finalPerc = (samples * 100) / stepValue;
+						updatePb.addActivityMarkValues(timeStamp + stepValue * samplingInterval, finalPerc, samples);
+					}
+					else
+					{
+						updatePb.zeroActivityMarkValues(timeStamp + stepValue * samplingInterval);
+					}					
+				}
+				
+				tmpVector = new Vector<ProfiledGeneric>(profiledFunctions.values());
+				Enumeration<ProfiledGeneric> pfEnum = tmpVector.elements();
+				while (pfEnum.hasMoreElements())
+				{
+					ProfiledFunction updatePf = (ProfiledFunction)pfEnum.nextElement();
+					if (functionPercentages.containsKey(updatePf))
+					{
+						int samples = ((Integer)(functionPercentages.get(updatePf))).intValue();
+						int finalPerc = (samples * 100) / stepValue;
+						updatePf.addActivityMarkValues(timeStamp + stepValue * samplingInterval, finalPerc, samples);
+					}
+					else
+					{
+						updatePf.zeroActivityMarkValues(timeStamp + stepValue * samplingInterval);
+					}					
+				}
+
+				threadPercentages.clear();
+				binaryPercentages.clear();
+				functionPercentages.clear();
+				count = 0;
+				timeStamp += stepValue * samplingInterval;
+			}
+		}
+		
+		// if there is no end point for a profiled element with samples, set the end to the last sample in the trace 
+		for (Enumeration<ProfiledGeneric> e = profiledThreads.elements(); e.hasMoreElements(); ) {
+			ProfiledGeneric pg = e.nextElement();
+			
+			if (pg.getRealLastSample() == -1 && pg.getTotalSampleCount() != 0)
+				pg.setLastSample(gppTrace.samples.size() * samplingInterval);
+		}
+
+		for (Enumeration<ProfiledGeneric> e = profiledBinaries.elements(); e.hasMoreElements(); ) {
+			ProfiledGeneric pg = e.nextElement();
+			
+			if (pg.getRealLastSample() == -1 && pg.getTotalSampleCount() != 0)
+				pg.setLastSample(gppTrace.samples.size() * samplingInterval);
+		}
+
+		for (Enumeration<ProfiledGeneric> e = profiledFunctions.elements(); e.hasMoreElements(); ) {
+			ProfiledGeneric pg = e.nextElement();
+			
+			if (pg.getRealLastSample() == -1 && pg.getTotalSampleCount() != 0)
+				pg.setLastSample(gppTrace.samples.size() * samplingInterval);
+		}
+
+		// sort the thread, binary, and function vectors by load
+		sortProfiledGenerics(profiledThreads, gppTrace);
+		sortProfiledGenerics(profiledBinaries, gppTrace);
+		sortProfiledGenerics(profiledFunctions, gppTrace);
+		
+		// the trace-level count arrays are initialized to 0
+		gppTrace.setThreadSampleCounts(new int[profiledThreads.size()]);
+		gppTrace.setBinarySampleCounts(new int[profiledBinaries.size()]);
+		gppTrace.setFunctionSampleCounts(new int[profiledFunctions.size()]);
+	}
+	
+	/*
+	 * Because a table to the left of a function table has changed, update
+	 * the function table.
+	 * If there is no table to the right of this one, redraw the graph based
+	 * on the changed data.
+	 */
+	public void refreshProfiledThreadData(int drawMode)
+	{
+		// Must have a table to its left
+	    if (   (drawMode != Defines.BINARIES_THREADS)
+	    	&& (drawMode != Defines.BINARIES_THREADS_FUNCTIONS)
+	    	&& (drawMode != Defines.BINARIES_FUNCTIONS_THREADS)
+	    	&& (drawMode != Defines.FUNCTIONS_THREADS)
+	    	&& (drawMode != Defines.FUNCTIONS_THREADS_BINARIES)
+	    	&& (drawMode != Defines.FUNCTIONS_BINARIES_THREADS)
+	    	)
+	    {
+	        System.out.println(Messages.getString("GppTraceGraph.wrongDrawMode"));  //$NON-NLS-1$
+	        return;
+	    }
+
+	    // boolean to use inside loops (should trust a compiler to optimize this out of the loop...)
+	    boolean basedOnBinaries = (drawMode == Defines.BINARIES_THREADS)
+	    					   || (drawMode == Defines.BINARIES_THREADS_FUNCTIONS)
+	    					   || (drawMode == Defines.FUNCTIONS_BINARIES_THREADS); 
+
+	    Hashtable<String,ProfiledThread> profiledThreads = new Hashtable<String,ProfiledThread>();
+		
+	    GenericSampledTrace trace = (GenericSampledTrace)this.getTrace();
+		int granularityValue = trace.samples.size() > GppTraceGraph.granularityValue ? GppTraceGraph.granularityValue : trace.samples.size();  
+		
+	    String[] selectedItems;
+		int[] selectedFunctionHashCodes = null;
+		int[] selectedBinaryHashCodes   = null;
+		int count = 0;
+		int timeStamp = 0;
+		int stepValue = granularityValue;
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+		boolean exit = false;
+		
+		Hashtable<ProfiledThread,Integer> percentages = new Hashtable<ProfiledThread,Integer>();
+		PIVisualSharedData shared = this.getSharedDataInstance();
+		
+	    if (basedOnBinaries)
+		{
+		    selectedItems = shared.GPP_SelectedBinaryNames;
+		    if (selectedItems == null) 
+	        {
+		        selectedItems = new String[0];
+	        }
+		    int[] tmpHashCodes = new int[selectedItems.length];
+		    for (int i = 0; i < selectedItems.length; i++)
+		    {
+		        String tmp = selectedItems[i];
+		        tmpHashCodes[i] = tmp.hashCode();
+		    }
+		    selectedBinaryHashCodes = tmpHashCodes;
+		}
+		else
+		{
+		    selectedItems = shared.GPP_SelectedFunctionNames;
+		    if (selectedItems == null) 
+	        {
+		        selectedItems = new String[0];
+	        }
+		    int[] tmpHashCodes = new int[selectedItems.length];
+		    for (int i = 0; i < selectedItems.length; i++)
+		    {
+		        String tmp = selectedItems[i];
+		        tmpHashCodes[i] = tmp.hashCode();
+		    }
+		    selectedFunctionHashCodes = tmpHashCodes;
+		}
+		
+		for (Enumeration enumer = trace.getSamples(); !exit;)
+		{
+		    exit = !enumer.hasMoreElements();
+			if (exit)
+			{
+				// for the final samples, modify the step value
+				// so that they will also be included
+				// now there are no new samples, so proceed directly to
+				// adding the final values to the percent list
+				stepValue = count;
+			}
+			else
+			{
+			    count++;
+			    int compareValue = 0;
+			    boolean match = false;
+			    GppSample sample = (GppSample)enumer.nextElement();
+			    if (basedOnBinaries)
+				{
+				    compareValue = getBinaryName(sample).hashCode();
+				    for (int i = 0; i < selectedBinaryHashCodes.length; i++)
+				    {
+				        if (compareValue == selectedBinaryHashCodes[i])
+				        {
+				            match = true;
+				            break;
+				        }
+				    }
+				}
+			    else
+			    {
+				    compareValue = getFunctionName(sample).hashCode();
+				    for (int i = 0; i < selectedFunctionHashCodes.length; i++)
+				    {
+				        if (compareValue == selectedFunctionHashCodes[i])
+				        {
+				            match = true;
+				            break;
+				        }
+				    }
+			    }
+			    
+			    if (match)
+			    {
+			        ProfiledThread pt = null;
+			        String name = sample.thread.threadName;
+					if (profiledThreads.containsKey(name))
+					{
+						pt = (ProfiledThread)profiledThreads.get(name);
+					}
+				
+					if (pt == null)
+					{
+						pt = new ProfiledThread();
+					
+						pt.setNameString(name);
+						pt.setColor(((GppTrace)this.getTrace()).getThreadColorPalette().getColor(name));
+						pt.setThreadId(sample.thread.threadId.intValue());
+						
+						pt.setActivityMarkCount((trace.samples.size() + granularityValue) / granularityValue + 1);
+						for (int i = 0; i < timeStamp + stepValue * samplingInterval; i += stepValue * samplingInterval)
+						{
+							pt.zeroActivityMarkValues(i);
+						}
+						pt.setEnabled(this.graphIndex, true);
+						profiledThreads.put(name, pt);
+					}
+	
+					if (percentages.containsKey(pt))
+					{
+						Integer value = (Integer)percentages.get(pt);
+						value = new Integer(value.intValue()+1);
+						percentages.remove(pt);
+						percentages.put(pt,value);
+					}
+					else
+					{
+						percentages.put(pt,new Integer(1));
+					}
+			    }
+			}
+
+			if (stepValue != 0 && count == stepValue)
+			{	
+				Vector<ProfiledGeneric> v = new Vector<ProfiledGeneric>(profiledThreads.values());
+				Enumeration<ProfiledGeneric> pfEnum = v.elements();
+				while (pfEnum.hasMoreElements())
+				{
+					ProfiledThread updatePt = (ProfiledThread)pfEnum.nextElement();
+					if (percentages.containsKey(updatePt))
+					{
+						int samples = ((Integer)(percentages.get(updatePt))).intValue();
+						int finalPerc = (samples * 100) / stepValue;
+						updatePt.addActivityMarkValues(timeStamp + stepValue * samplingInterval, finalPerc, samples);
+					}
+					else
+					{
+						updatePt.zeroActivityMarkValues(timeStamp + stepValue * samplingInterval);
+					}					
+				}
+				
+				percentages.clear();
+				count = 0;
+				timeStamp += stepValue * samplingInterval;
+			}
+		}
+
+		this.threadTable.getTable().deselectAll();
+		this.threadTable.updateProfiledAndItemData(true);
+		this.threadTable.getTable().redraw();
+
+		// if this is not the last table, set the selected names to set up
+		// the next table
+	    if (   (drawMode == Defines.BINARIES_THREADS_FUNCTIONS)
+	    	|| (drawMode == Defines.FUNCTIONS_THREADS_BINARIES))
+	    {
+	    	this.threadTable.setSelectedNames();
+	    }
+	    else
+	    {
+	    	// This may not be needed needed
+			shared.GPP_SelectedThreadNames = new String[0];
+	    }
+	}
+
+	/*
+	 * Because a table to the left of a binary table has changed, update
+	 * the binary table.
+	 * If there is no table to the right of this one, redraw the graph based
+	 * on the changed data.
+	 */
+	public void refreshProfiledBinaryData(int drawMode)
+	{
+		// Must have a table to its left
+	    if (   (drawMode != Defines.THREADS_BINARIES)
+	    	&& (drawMode != Defines.THREADS_BINARIES_FUNCTIONS)
+	    	&& (drawMode != Defines.THREADS_FUNCTIONS_BINARIES)
+	    	&& (drawMode != Defines.FUNCTIONS_BINARIES)
+	    	&& (drawMode != Defines.FUNCTIONS_BINARIES_THREADS)
+	    	&& (drawMode != Defines.FUNCTIONS_THREADS_BINARIES)
+	       )
+	    {
+	        System.out.println(Messages.getString("GppTraceGraph.wrongDrawMode"));  //$NON-NLS-1$
+	        return;
+	    }
+
+	    // boolean to use inside loops (never trust a compiler...)
+	    boolean basedOnThreads = (drawMode == Defines.THREADS_BINARIES)
+	    					  || (drawMode == Defines.THREADS_BINARIES_FUNCTIONS)
+	    					  || (drawMode == Defines.FUNCTIONS_THREADS_BINARIES); 
+
+	    Hashtable<String,ProfiledBinary> profiledBinaries = new Hashtable<String,ProfiledBinary>();
+		
+	    GenericSampledTrace trace = (GenericSampledTrace)this.getTrace();
+		int granularityValue = trace.samples.size() > GppTraceGraph.granularityValue ? GppTraceGraph.granularityValue : trace.samples.size();  
+
+		String[] selectedItems;
+		int[] selectedThreadIds = null;
+		int[] selectedFunctionHashCodes = null;
+		int count = 0;
+		int timeStamp = 0;
+		int stepValue = granularityValue;
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+		boolean exit = false;
+		
+		Hashtable<ProfiledBinary,Integer> percentages = new Hashtable<ProfiledBinary,Integer>();
+		PIVisualSharedData shared = this.getSharedDataInstance();
+		
+	    if (basedOnThreads)
+	    {
+	    	selectedItems = shared.GPP_SelectedThreadNames;
+		    if (selectedItems == null)
+		    {
+		        selectedItems = new String[0];
+		    }
+		    int[] tmpThreadIds = new int[selectedItems.length];
+		    for (int i = 0; i < selectedItems.length; i++)
+		    {
+		        String tmp = selectedItems[i].substring(selectedItems[i].lastIndexOf('_') + 1,
+		                selectedItems[i].length());
+		        tmpThreadIds[i] = Integer.parseInt(tmp);
+		    }
+		    selectedThreadIds = tmpThreadIds;
+		}
+		else
+		{
+		    selectedItems = shared.GPP_SelectedFunctionNames;
+		    if (selectedItems == null) 
+	        {
+		        selectedItems = new String[0];
+	        }
+		    int[] tmpHashCodes = new int[selectedItems.length];
+		    for (int i = 0; i < selectedItems.length; i++)
+		    {
+		        String tmp = selectedItems[i];
+		        tmpHashCodes[i] = tmp.hashCode();
+		    }
+		    selectedFunctionHashCodes = tmpHashCodes;
+		}
+		
+		for (Enumeration enumer = trace.getSamples(); !exit;)
+		{
+		    exit = !enumer.hasMoreElements();
+			if (exit) 
+			{
+				// for the final samples, modify the step value
+				// so that they will also be included
+				// now there are no new samples, so proceed directly to
+				// adding the final values to the percent list
+				stepValue = count;
+			}
+			else
+			{
+			    count++;
+			    int compareValue = 0;
+			    boolean match = false;
+			    GppSample sample = (GppSample)enumer.nextElement();
+			    if (basedOnThreads)
+			    {
+				    compareValue = sample.thread.threadId.intValue();
+				    for (int i = 0; i < selectedThreadIds.length; i++)
+				    {
+				        if (compareValue == selectedThreadIds[i])
+				        {
+				            match = true;
+				            break;
+				        }
+				    }
+			    }
+				else
+				{
+				    compareValue = getFunctionName(sample).hashCode();
+				    for (int i = 0; i < selectedFunctionHashCodes.length; i++)
+				    {
+				        if (compareValue == selectedFunctionHashCodes[i])
+				        {
+				            match = true;
+				            break;
+				        }
+				    }
+				}
+			    
+			    if (match)
+			    {
+			        ProfiledBinary pb = null;
+			        String name = getFunctionName(sample);
+					if (profiledBinaries.containsKey(name))
+					{
+						pb = (ProfiledBinary)profiledBinaries.get(name);
+					}
+				
+					if (pb == null)
+					{
+						pb = new ProfiledBinary();
+						
+						pb.setNameString(name);
+						pb.setColor(((GppTrace)this.getTrace()).getBinaryColorPalette().getColor(name));
+						
+						pb.setActivityMarkCount((trace.samples.size() + granularityValue) / granularityValue + 1);
+						for (int i = 0; i < timeStamp + stepValue * samplingInterval; i += stepValue * samplingInterval)
+						{
+							pb.zeroActivityMarkValues(i);
+						}
+						profiledBinaries.put(name, pb);
+					}
+	
+					if (percentages.containsKey(pb))
+					{
+						Integer value = (Integer)percentages.get(pb);
+						value = new Integer(value.intValue()+1);
+						percentages.remove(pb);
+						percentages.put(pb,value);
+					}
+					else
+					{
+						percentages.put(pb,new Integer(1));
+					}
+			    }
+			}
+
+			if (stepValue != 0 && count == stepValue)
+			{	
+				Vector<ProfiledGeneric> v = new Vector<ProfiledGeneric>(profiledBinaries.values());
+				Enumeration<ProfiledGeneric> pfEnum = v.elements();
+				while (pfEnum.hasMoreElements())
+				{
+					ProfiledFunction updatePf = (ProfiledFunction)pfEnum.nextElement();
+					if (percentages.containsKey(updatePf))
+					{
+						int samples = ((Integer)(percentages.get(updatePf))).intValue();
+						int finalPerc = (samples * 100) / stepValue;
+						updatePf.addActivityMarkValues(timeStamp + stepValue * samplingInterval, finalPerc, samples);
+					}
+					else
+					{
+						updatePf.zeroActivityMarkValues(timeStamp + stepValue * samplingInterval);
+					}					
+				}
+				
+				percentages.clear();
+				count = 0;
+				timeStamp += stepValue * samplingInterval;
+			}
+		}
+
+		this.binaryTable.getTable().deselectAll();
+		this.binaryTable.updateProfiledAndItemData(true);
+		this.binaryTable.getTable().redraw();
+
+		// if this is not the last table, set the selected names to set up
+		// the next table
+	    if (   (drawMode == Defines.THREADS_BINARIES_FUNCTIONS)
+	    	|| (drawMode == Defines.FUNCTIONS_BINARIES_THREADS))
+	    {
+	    	this.binaryTable.setSelectedNames();
+	    }
+	    else
+	    {
+	    	// This may not be needed
+			shared.GPP_SelectedBinaryNames = new String[0];
+	    }
+	}
+	
+	// sort profiled generics by decreasing total sample count
+	private static void sortProfiledGenerics(Hashtable<String,ProfiledGeneric> prof, GppTrace gppTrace)
+	{
+		// use an insertion sort to create a sorted linked list
+		// from the hashtable values
+		Collection<ProfiledGeneric> values = prof.values();
+		Vector<ProfiledGeneric> unsorted =   new Vector<ProfiledGeneric>(values);
+		LinkedList<ProfiledGeneric> sorted = new LinkedList<ProfiledGeneric>();
+
+		Enumeration<ProfiledGeneric> prEnum = unsorted.elements();
+		while (prEnum.hasMoreElements())
+		{
+			ProfiledGeneric pg = prEnum.nextElement();
+			if (sorted.size() == 0)
+			{
+				sorted.addFirst(pg);
+			}
+			else 
+			{
+				Iterator i = sorted.iterator();
+				boolean ok = false;
+				while (i.hasNext())
+				{
+					ProfiledGeneric next = (ProfiledGeneric)i.next();
+					if (next.getTotalSampleCount() < pg.getTotalSampleCount())
+					{
+						sorted.add(sorted.indexOf(next), pg);
+						ok = true;
+						break;
+					}
+				}
+				if (!ok)
+					sorted.addLast(pg);
+			}
+		}
+		
+		// Add the sorted data 
+		Iterator<ProfiledGeneric> iterator = sorted.iterator();
+		if (sorted.size() > 0)
+		{
+			Vector<ProfiledGeneric> v = null;
+			if (sorted.get(0) instanceof ProfiledThread)
+			{
+				v = gppTrace.getSortedThreads();
+			}
+			else if (sorted.get(0) instanceof ProfiledBinary)
+			{
+				v = gppTrace.getSortedBinaries();
+			}
+			else if (sorted.get(0) instanceof ProfiledFunction)
+			{
+				v = gppTrace.getSortedFunctions();
+			}
+			if (v != null)
+			{
+				v.clear();
+				while (iterator.hasNext())
+					v.add(0, iterator.next());
+			}
+		}
+	}
+	
+	public void updateGraph()
+	{
+	    if (drawMode == Defines.BINARIES)
+	    {
+	        vPanel.refreshCumulativeThreadTable();
+	    }
+	    else if (drawMode == Defines.THREADS)
+	    {
+	        vPanel.refreshCumulativeThreadTable();
+	    }
+
+		this.repaint();
+	}
+	
+	public void updateThreadTablePriorities(Hashtable<Integer,String> priorities)
+	{
+		this.threadTable.addPriorityColumn(priorities);
+	}
+	
+	static private String stringNotFound = Messages.getString("GppTraceGraph.notFound");  //$NON-NLS-1$
+
+	static private String stringBinaryAt         = Messages.getString("GppTraceGraph.binaryAt");  //$NON-NLS-1$
+	static private String stringBinaryForAddress = Messages.getString("GppTraceGraph.binaryForAddress");  //$NON-NLS-1$
+	static private String stringBinaryNotFound   = Messages.getString("GppTraceGraph.binaryNotFound");  //$NON-NLS-1$
+
+	static private String stringFunctionAt         = Messages.getString("GppTraceGraph.functionAt"); //$NON-NLS-1$
+	static private String stringFunctionForAddress = Messages.getString("GppTraceGraph.functionForAddress"); //$NON-NLS-1$
+	static private String stringFunctionNotFound   = Messages.getString("GppTraceGraph.functionNotFound"); //$NON-NLS-1$
+	
+	public static String getBinaryName(GppSample s)
+	{
+	    String name = null;
+	    
+	    if (s.currentFunctionSym != null)
+	    	name = s.currentFunctionSym.functionBinary.binaryName;
+
+        if (   (s.currentFunctionItt != null)
+           	&& ((name == null) || name.endsWith(stringNotFound)))
+        {
+            name = s.currentFunctionItt.functionBinary.binaryName;
+        }
+	    
+	    if (   name == null
+	    	|| name.startsWith(stringBinaryAt)
+	    	|| name.startsWith(stringBinaryForAddress))
+	    {
+	        name = stringBinaryNotFound;
+	    }
+	    return name;
+	}
+	
+	public static String getFunctionName(GppSample s)
+	{
+	    String name = null;
+	    if (s.currentFunctionSym != null)
+	    	name = s.currentFunctionSym.functionName;
+	    
+        if (   (s.currentFunctionItt != null)
+        	&& ((name == null) || name.endsWith(stringNotFound)))
+        {
+        	name = s.currentFunctionItt.functionName;
+        }
+
+	    if (   (name == null)
+	    	|| (name.startsWith(stringFunctionAt))
+	    	|| (name.startsWith(stringFunctionForAddress)))
+	    {
+	        name = stringFunctionNotFound;
+	    }
+	    
+	    return name;
+	}
+	
+	public static long getFunctionAddress(GppSample s)
+	{
+	    if (s.currentFunctionSym != null)
+	    {
+	        String name = s.currentFunctionSym.functionName;
+	        if (   (s.currentFunctionItt != null)
+	        	&& (name == null || name.endsWith(Messages.getString("GppTraceGraph.notFound"))))  //$NON-NLS-1$
+	        {
+        		return s.currentFunctionItt.startAddress.longValue();
+	        }
+	        else
+	        {
+	        	return s.currentFunctionSym.startAddress.longValue();
+	        }
+	    }
+	    else if (s.currentFunctionItt != null)
+	    {
+	        if (s.currentFunctionItt.functionName == null)
+	        {
+	        	if (s.currentFunctionSym != null)
+	        		return s.currentFunctionSym.startAddress.longValue();
+	        }
+	        else
+	        {
+        		return s.currentFunctionItt.startAddress.longValue();
+	        }
+	    }
+
+	    return 0;
+	}
+
+	public int getDrawMode()
+    {
+        return drawMode;
+    }
+
+    public void setDrawMode(int drawMode)
+    {
+    	if (
+    		   (drawMode == Defines.THREADS)
+    		|| (drawMode == Defines.THREADS_FUNCTIONS)
+    		|| (drawMode == Defines.THREADS_FUNCTIONS_BINARIES)
+    		|| (drawMode == Defines.THREADS_BINARIES)
+    		|| (drawMode == Defines.THREADS_BINARIES_FUNCTIONS)
+    		|| (drawMode == Defines.BINARIES)
+    		|| (drawMode == Defines.BINARIES_THREADS)
+    		|| (drawMode == Defines.BINARIES_THREADS_FUNCTIONS)
+    		|| (drawMode == Defines.BINARIES_FUNCTIONS)
+    		|| (drawMode == Defines.BINARIES_FUNCTIONS_THREADS)
+    		|| (drawMode == Defines.FUNCTIONS)
+    		|| (drawMode == Defines.FUNCTIONS_THREADS)
+    		|| (drawMode == Defines.FUNCTIONS_THREADS_BINARIES)
+    		|| (drawMode == Defines.FUNCTIONS_BINARIES)
+    		|| (drawMode == Defines.FUNCTIONS_BINARIES_THREADS))
+    	{
+    		if (this.drawMode != drawMode) {
+    			this.setGraphImageChanged(true);
+    		}
+	        this.drawMode = drawMode;
+	        refreshMode();
+        }
+        else
+        {
+            System.out.println(Messages.getString("GppTraceGraph.unknownDrawMode"));  //$NON-NLS-1$
+            this.drawMode = Defines.THREADS;
+            refreshMode();
+        }
+    }
+    
+    private void refreshMode()
+    {
+    	this.vPanel.refreshCumulativeThreadTable();
+    }
+
+	public int getUid() {
+		return this.uid;
+	}
+	
+	public GppTraceGraph getTraceGraph() {
+		return this.thisTraceGraph;
+	}
+	
+	public void setLeftSash(Sash leftSash) {
+		this.leftSash = leftSash;
+	}
+	
+	public Sash getLeftSash() {
+		return this.leftSash;
+	}
+	
+	public void setRightSash(Sash rightSash) {
+		this.rightSash = rightSash;
+	}
+	
+	public Sash getRightSash() {
+		return this.rightSash;
+	}
+
+	public void setProfiledThreads(Vector<ProfiledGeneric> profiledThreads) {
+		this.profiledThreads = profiledThreads;
+	}
+	
+	public Vector<ProfiledGeneric> getProfiledThreads() {
+		return this.profiledThreads;
+	}
+	
+	public Vector<ProfiledGeneric> getSortedThreads() {
+		return this.sortedProfiledThreads;
+	}
+
+	public void setProfiledBinaries(Vector<ProfiledGeneric> profiledBinaries) {
+		this.profiledBinaries = profiledBinaries;
+	}
+	
+	public Vector<ProfiledGeneric> getProfiledBinaries() {
+		return this.profiledBinaries;
+	}
+	
+	public Vector<ProfiledGeneric> getSortedBinaries() {
+		return this.sortedProfiledBinaries;
+	}
+
+	public void setProfiledFunctions(Vector<ProfiledGeneric> profiledFunctions) {
+		this.profiledFunctions = profiledFunctions;
+	}
+	
+	public Vector<ProfiledGeneric> getProfiledFunctions() {
+		return this.profiledFunctions;
+	}
+	
+	public Vector<ProfiledGeneric> getSortedFunctions() {
+		return this.sortedProfiledFunctions;
+	}
+	
+	public ProfiledThreshold getThresholdThread() {
+		return thresholdThread;
+	}
+	
+	public ProfiledThreshold getThresholdBinary() {
+		return thresholdBinary;
+	}
+	
+	public ProfiledThreshold getThresholdFunction() {
+		return thresholdFunction;
+	}
+
+	public void mouseMove(org.eclipse.swt.events.MouseEvent e) {
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTraceGraphActionListener.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: 
+ *
+ */
+
+/*
+ * GppTraceGraphActionListener.java
+ */
+package com.nokia.carbide.cpp.pi.address;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+
+public class GppTraceGraphActionListener implements ActionListener
+{
+	public void actionPerformed(ActionEvent ae)
+	{
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTraceParser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.Parser;
+import com.nokia.carbide.cpp.internal.pi.model.TraceDataContainer;
+
+
+public class GppTraceParser extends Parser
+{
+//  private String traceVersion;
+  private boolean debug = false;
+  private String profilerVersion;
+  private String samplerVersion;
+  private Hashtable<Integer,GppProcess> processes;
+  private Hashtable<Integer,GppThread> threads;
+  private GppSample[] traceData;
+  private GppThread[] sortedThreads;
+  private TraceDataContainer container; 
+  private Hashtable<Long,String> threadAddressToName;
+
+  public GppTraceParser() throws IOException
+  {
+    this.processes = new Hashtable<Integer,GppProcess>();
+    this.threads   = new Hashtable<Integer,GppThread>();
+    this.threadAddressToName = new Hashtable<Long,String>();
+  }
+
+  public ParsedTraceData parse(File traceInput) throws IOException
+  {
+    if (!traceInput.exists())
+    	throw new IOException(Messages.getString("GppTraceParser.0"));  //$NON-NLS-1$
+
+    DataInputStream dis = new DataInputStream(new FileInputStream(traceInput));
+	  
+    if (validate(dis) == false)
+    	throw new IOException(Messages.getString("GppTraceParser.1"));  //$NON-NLS-1$
+
+    long pc = 0;
+    GppThread thread = null;
+    int threadIndexer = 0;
+    int count = 1;
+    int samples = 0;
+    long time = 0;
+
+    Vector<GppSample> intermediateTraceData = new Vector<GppSample>();
+    
+    // determine the base sampling period (address/thread sampling period) 
+    int addrThreadPeriod = 1;
+    
+    if (traceVersion.indexOf("V2.01") != -1) { //$NON-NLS-1$
+    	addrThreadPeriod =   (dis.readUnsignedByte() << 24)
+			    		   | (dis.readUnsignedByte() << 16)
+			    		   | (dis.readUnsignedByte() <<  8)
+			    		   |  dis.readUnsignedByte();
+    }
+
+	// initialize the address/thread base sampling rate
+	NpiInstanceRepository.getInstance().activeUidSetPersistState(
+								"com.nokia.carbide.cpp.pi.address.samplingInterval", //$NON-NLS-1$
+								new Integer(addrThreadPeriod)); //$NON-NLS-1$
+    
+    while (dis.available() > 0)
+    {
+      try
+      {
+        count = 1;
+        int diff = (int)decodeInt(dis);
+ 
+        if ((diff & 1) == 1)
+        {
+          diff &= ~1;
+          thread = decodeThread(dis);
+        }
+        else if (diff == 0)
+        {
+          count = (int)decodeUInt(dis);
+        }
+
+        pc += diff;
+
+        while (--count >= 0)
+        {
+          samples++;
+          time += addrThreadPeriod;
+          
+          if (samples == 1 && thread == null)
+          {
+	       	// the first sample may be recorded before its thread's name
+
+        	// create a new sample object for this sample
+            GppSample gppSample = new GppSample();
+            long pcMod = pc << 32;
+            pcMod = pcMod >>> 32;
+           	gppSample.programCounter = pcMod;
+            gppSample.sampleSynchTime = time;
+              
+            GppThread unknownThread = new GppThread();
+            unknownThread.threadId = -1;
+            unknownThread.threadName = Messages.getString("GppTraceParser.unknown"); //$NON-NLS-1$
+              
+            GppProcess unknownProcess = new GppProcess();
+            unknownProcess.id = -1;
+            unknownProcess.name = Messages.getString("GppTraceParser.unknown"); //$NON-NLS-1$
+            this.processes.put(-1,unknownProcess);
+ 
+            unknownThread.process = unknownProcess;
+            unknownThread.index = threadIndexer++;
+              
+            gppSample.thread = unknownThread;
+
+            this.threads.put(-1,unknownThread);
+
+            gppSample.thread = unknownThread;
+            intermediateTraceData.add(gppSample);
+          }
+          else if (thread.index >= -1)
+	      {
+            if (thread.index == -1) thread.index = threadIndexer++;
+
+            // create a new sample object for this sample
+
+            GppSample gppSample = new GppSample();
+           	long pcMod = pc << 32;
+           	pcMod = pcMod >>> 32;
+           	
+           	if (thread.threadName.equals("*Native*")) //$NON-NLS-1$
+           		gppSample.programCounter = 0;
+           	else
+           		gppSample.programCounter = pcMod;
+            
+            //System.out.println("PC value:"+pc+" "+Long.toHexString(pc));
+            
+            gppSample.sampleSynchTime = time;
+            gppSample.thread = thread;
+            thread.samples++;
+            intermediateTraceData.add(gppSample);
+          }
+        }
+      }
+      catch (EOFException e) {}
+    }
+    if (debug) System.out.println(Messages.getString("GppTraceParser.2"));  //$NON-NLS-1$
+    // all samples have been parsed
+    this.traceData = new GppSample[intermediateTraceData.size()];
+
+    // store the trace data into an array
+    intermediateTraceData.toArray(this.traceData);
+
+    // sort the threads into an ordered array
+    this.sortThreads();
+    
+    container = new TraceDataContainer("GPP_address2threadname",new String[]{"address","threadname"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    Enumeration<Long> ke = this.threadAddressToName.keys();
+    Iterator<String>  vi = this.threadAddressToName.values().iterator();
+    
+    while(ke.hasMoreElements())
+    {
+    	Long address = ke.nextElement();
+    	String name = vi.next();
+    	container.addDataToColumn("threadname",name); //$NON-NLS-1$
+    	container.addDataToColumn("address",address); //$NON-NLS-1$
+    }
+    this.threadAddressToName.clear();
+    this.threadAddressToName = null;
+    
+    ParsedTraceData pd = new ParsedTraceData();
+    pd.traceData = this.getTrace();
+        
+    return pd;
+  }
+  
+  private void sortThreads()
+  {
+    if (this.threads != null)
+    {
+      boolean sorted = false;
+
+      GppThread[] tArray = new GppThread[this.threads.size()];
+      Collection<GppThread> threadCollection = this.threads.values();
+      threadCollection.toArray(tArray);
+
+      // set initial sort order to the order in which
+      // the threads appear in the array
+      for (int i = 0; i < tArray.length; i++)
+      {
+        tArray[i].sortOrder = i;
+      }
+
+      // sort threads using bubble sort
+      while (sorted == false)
+      {
+        sorted = true;
+        for (int i = 0; i < tArray.length - 1; i++)
+        {
+          if (tArray[i].samples < tArray[i + 1].samples)
+          {
+              // switch the sort order
+              GppThread store = tArray[i];
+              tArray[i] = tArray[i + 1];
+              tArray[i + 1] = store;
+              sorted = false;
+          }
+        }
+      }
+
+      // finally, store the ordered array
+      this.sortedThreads = tArray;
+      for (int i=0;i<this.sortedThreads.length;i++)
+      {
+        this.sortedThreads[i].sortOrder = i;
+      }
+
+    }
+  }
+
+  private boolean validate(DataInputStream dis) throws IOException
+  {
+    String data = decodeName(dis);
+    if (debug) System.out.println(Messages.getString("GppTraceParser.3")+data);  //$NON-NLS-1$
+    if (data.equals("profile")) //pre 1.10 //$NON-NLS-1$
+    if (decodeUInt(dis) == 1) return true;
+        
+    if (data.startsWith("Bappea_GPP_V")) //version 1.20 //$NON-NLS-1$
+    {
+        try
+        {
+        	int separatorIndex = data.indexOf("#"); //$NON-NLS-1$
+	        this.traceVersion = data.substring(data.indexOf("_")+1,separatorIndex); //$NON-NLS-1$
+	    }
+	    catch (Exception e)
+	    {
+	    	return false;
+	    }
+    
+    	StringTokenizer st = new StringTokenizer(data,"#"); //$NON-NLS-1$
+      	while(st.hasMoreElements())
+    	{
+    		String id = st.nextToken();
+    		if (id.equals("Prof")) //$NON-NLS-1$
+    		{
+    			this.profilerVersion = st.nextToken();
+    		}
+    		else if (id.equals("Samp"))  //$NON-NLS-1$
+    		{
+    			this.samplerVersion = st.nextToken();
+    		}
+    	}
+               
+        System.out.println(Messages.getString("GppTraceParser.4")+traceVersion+Messages.getString("GppTraceParser.5")+profilerVersion+Messages.getString("GppTraceParser.6")+samplerVersion);    //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		
+		if (   (traceVersion.indexOf("V1.10") != -1)	//$NON-NLS-1$
+			|| (traceVersion.indexOf("V1.64") != -1)	//$NON-NLS-1$
+			|| (traceVersion.indexOf("V2.01") != -1))	//$NON-NLS-1$
+            return true;
+      	else
+      		return false;
+    }
+    
+    return false;
+  }
+
+  	public static void encodeInt(int number, DataOutputStream dos) throws IOException
+	{
+		int digit;
+		for (;;) {
+			digit = number & 0x7f;
+			if ((number >> 6) == (number >> 7))
+				break;
+			number >>= 7;
+			dos.write(digit);
+		}
+		dos.write(digit | 0x80);
+		
+		dos.flush();
+	}
+	
+	public static void encodeUInt(int number, DataOutputStream dos) throws IOException
+	{
+		int digit;
+		for (;;) {
+			digit = number & 0x7f;
+			number >>= 7;
+			if (number <= 0)
+				break;
+			dos.write(digit);
+		}
+		dos.write(digit | 0x80);		
+	}
+  
+  public static long decodeInt(DataInputStream dis) throws IOException
+  {
+    //System.out.println("DECODING INT");
+
+	int val = 0;
+    int shift = 0;
+    int data;
+    do
+    {
+      data = dis.readUnsignedByte();
+      //System.out.print(":"+Integer.toHexString(data));
+      if (data < 0)
+    	  throw new IOException(Messages.getString("GppTraceParser.7"));  //$NON-NLS-1$
+      val |= (data & 0x7f) << shift;
+      shift += 7;
+    } while ((data & 0x80) == 0);
+
+    if (shift < 32)
+    {
+      shift = 32 - shift;
+      val = val << shift >> shift;
+    }
+    //System.out.println("read int"+(val & 0xffffffff));
+
+    return (val);
+  }
+
+
+  public static long decodeUInt(DataInputStream dis) throws IOException
+  {
+    //System.out.println("DECODING UINT");
+    long val = 0;
+    int shift = 0;
+    int data;
+    do
+    {
+      data = dis.readUnsignedByte();
+      //System.out.println("read byte:"+Integer.toHexString(data));
+      if (data < 0)
+    	  throw new IOException(Messages.getString("GppTraceParser.8"));  //$NON-NLS-1$
+      val |= (data & 0x7f) << shift;
+      shift += 7;
+    } while ((data & 0x80) == 0);
+
+    //System.out.println("read unsigned int"+val);
+    return val;
+  }
+
+
+  private String decodeName(DataInputStream dis) throws IOException
+  {
+    //System.out.println("DECODING NAME");
+
+    int length = dis.readUnsignedByte();
+    //System.out.println("name length "+Integer.toHexString(length));
+    byte[] data = new byte[length];
+    dis.read(data);
+    //System.out.println("Read name:"+new String(data));
+    return new String(data);
+  }
+
+  private GppProcess decodeProcess(DataInputStream dis) throws IOException
+  {
+    //System.out.println("DECODING PROCESS");
+    Integer pid = new Integer((int)decodeUInt(dis));
+
+    if (this.processes.containsKey(pid))
+    {
+      return (GppProcess)this.processes.get(pid);
+    }
+    else
+    {
+      GppProcess np = new GppProcess();
+      np.id = pid;
+      np.name = decodeName(dis);
+      this.processes.put(pid,np);
+      return np;
+    }
+  }
+
+  private GppThread decodeThread(DataInputStream dis) throws IOException
+  {
+    //System.out.println("DECODING THREAD");
+    Integer tid = new Integer((int)decodeUInt(dis));
+
+    if (this.threads.containsKey(tid))
+    {
+      return (GppThread)this.threads.get(tid);
+    }
+
+    GppProcess p = decodeProcess(dis);
+    String name = decodeName(dis);
+    
+    try
+	{
+    	if (name.endsWith("]")) //$NON-NLS-1$
+    	{
+    		String l = name.substring(name.lastIndexOf("[")+1,name.lastIndexOf("]")); //$NON-NLS-1$ //$NON-NLS-2$
+    		Long threadAddress = Long.decode("0x"+l); //$NON-NLS-1$
+    		this.threadAddressToName.put(threadAddress,name);
+    		name = name.substring(0,name.lastIndexOf("[")); //$NON-NLS-1$
+    	}
+	}
+    catch (Exception e)
+	{
+    	e.printStackTrace();
+	}
+
+    GppThread nt = new GppThread();
+    nt.threadId = tid;
+    nt.threadName = name;
+    nt.process = p;
+    nt.index = -1;
+
+    this.threads.put(tid,nt);
+
+    return nt;
+  }
+  
+  private GenericTrace getTrace()
+  {
+  	GppTrace trace = new GppTrace();
+  	for (int i = 0; i < traceData.length; i++)
+  	{
+  		trace.addSample(this.traceData[i]);
+  	}
+  	return trace;
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppVisualiserPanel.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: 
+ *
+ */
+
+/*
+ * GppVisualiserPanel.java
+ */
+package com.nokia.carbide.cpp.pi.address;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Panel;
+
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.internal.pi.visual.Defines;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEventListener;
+import com.nokia.carbide.cpp.pi.core.SessionPreferences;
+
+
+public class GppVisualiserPanel implements PIEventListener 
+{
+	private static final long serialVersionUID = 8984025640418406715L;
+	public GppTraceGraph myGppGraph;
+	public GppVisualiserPanel myGppVisualiser;
+
+	public GppVisualiserPanel(GppTraceGraph myGppGraphIn)
+	{  	
+		this.myGppGraph = myGppGraphIn;
+	      
+	     //sets the percentage scale for y-coordinates
+	    this.myGppGraph.setScale(0,100);
+	    this.myGppGraph.fillFlag = SessionPreferences.getInstance().getFillAllEnabled();
+	    
+	  	this.myGppVisualiser = myGppGraphIn.getVisualiserPanel();
+	} //constructor
+  
+	public void refreshCumulativeThreadTable()
+	{	
+		this.myGppGraph.genericRefreshCumulativeThreadTable();
+	}
+
+	public void piEventReceived(PIEvent be)
+	{
+		switch (be.getType())
+		{
+			case PIEvent.SET_FILL_ALL_THREADS:
+				this.myGppGraph.fillSelected = false;
+				this.myGppGraph.fillFlag     = true;
+				this.myGppGraph.repaint();
+				break;
+			
+			case PIEvent.SET_FILL_OFF:
+				this.myGppGraph.fillSelected = false;
+				this.myGppGraph.fillFlag     = false;
+				this.myGppGraph.repaint();
+				break;
+			
+			case PIEvent.SET_FILL_SELECTED_THREAD:
+				this.myGppGraph.fillSelected = true;
+				this.myGppGraph.fillFlag     = true;
+				this.myGppGraph.repaint();
+				break;
+				
+			case PIEvent.GPP_SET_BAR_GRAPH_ON:
+				this.myGppGraph.barMode = GppTraceGraph.BAR_MODE_ON;
+				this.myGppGraph.repaint();
+				break;
+	
+			case PIEvent.GPP_SET_BAR_GRAPH_OFF:
+				this.myGppGraph.barMode = GppTraceGraph.BAR_MODE_OFF;
+				this.myGppGraph.repaint();
+				break;
+				
+			case PIEvent.CHANGED_THREAD_TABLE:
+				this.myGppGraph.setGraphImageChanged(true);
+				if (this.myGppGraph.fillFlag && this.myGppGraph.fillSelected)
+				{
+				    this.myGppGraph.repaint();
+				}
+				break;
+				
+			case PIEvent.CHANGED_BINARY_TABLE:
+				this.myGppGraph.setGraphImageChanged(true);
+			    if (this.myGppGraph.fillFlag)
+			    {
+			        this.myGppGraph.repaint();
+			    }
+			    break;
+				
+			case PIEvent.CHANGED_FUNCTION_TABLE:
+				this.myGppGraph.setGraphImageChanged(true);
+			    if (this.myGppGraph.fillFlag)
+			    {
+			        this.myGppGraph.repaint();
+			    }
+			    break;
+				
+			default:
+				break;
+		}
+	}
+  
+	private Vector getItemsInVector(int drawMode)
+	{
+		Vector v = null;
+		
+		if (   (drawMode == Defines.THREADS)
+			|| (drawMode == Defines.BINARIES_THREADS)
+			|| (drawMode == Defines.BINARIES_FUNCTIONS_THREADS)
+			|| (drawMode == Defines.FUNCTIONS_THREADS)
+			|| (drawMode == Defines.FUNCTIONS_BINARIES_THREADS))
+		{
+		    v = this.myGppGraph.getSortedThreads();
+		}
+		else if ((drawMode == Defines.BINARIES)
+			  || (drawMode == Defines.THREADS_BINARIES)
+			  || (drawMode == Defines.THREADS_FUNCTIONS_BINARIES)
+			  || (drawMode == Defines.FUNCTIONS_BINARIES)
+			  || (drawMode == Defines.FUNCTIONS_THREADS_BINARIES))
+		{
+		    v = this.myGppGraph.getSortedBinaries();
+		}
+		else if ((drawMode == Defines.FUNCTIONS)
+			  || (drawMode == Defines.THREADS_FUNCTIONS)
+			  || (drawMode == Defines.THREADS_BINARIES_FUNCTIONS)
+			  || (drawMode == Defines.BINARIES_FUNCTIONS)
+			  || (drawMode == Defines.BINARIES_THREADS_FUNCTIONS))
+		{
+			v = this.myGppGraph.getSortedFunctions();
+		}
+		
+		return v;
+	}
+
+	// draw the graph based on the rightmost table displayed
+  	private void drawCumulativeGraphLines(Graphics graphics)
+	{	
+		Vector v = getItemsInVector(this.myGppGraph.getDrawMode());
+		
+		if (v == null) 
+		    return;
+
+		this.myGppGraph.drawGraphsGeneric(v, graphics, myGppGraph.getTableUtils().getSelectedValues());	  	
+	}
+	
+	private void drawBarGraph(Graphics graphics)
+	{
+		Vector v = getItemsInVector(this.myGppGraph.getDrawMode());
+		
+		if (v == null) 
+		    return;
+	    
+		this.myGppGraph.drawBarsGpp(v, graphics, myGppGraph.getTableUtils().getSelectedValues());	  			
+	}
+
+	//updates values in current profiled generic items
+	public void updateThreadAverages()
+	{
+	    //System.out.println("Refreshing average values");
+		Enumeration enumer = null;
+		int drawMode   = this.myGppGraph.getDrawMode();
+		int graphIndex = this.myGppGraph.getGraphIndex();
+
+		if (   (drawMode == Defines.THREADS)
+				|| (drawMode == Defines.BINARIES_THREADS)
+				|| (drawMode == Defines.BINARIES_FUNCTIONS_THREADS)
+				|| (drawMode == Defines.FUNCTIONS_THREADS)
+				|| (drawMode == Defines.FUNCTIONS_BINARIES_THREADS))
+		{
+		    enumer = ((GppTrace) (this.myGppGraph.getTrace())).getSortedThreadsElements();
+		}
+		else if ((drawMode == Defines.BINARIES)
+			  || (drawMode == Defines.THREADS_BINARIES)
+			  || (drawMode == Defines.THREADS_FUNCTIONS_BINARIES)
+			  || (drawMode == Defines.FUNCTIONS_BINARIES)
+			  || (drawMode == Defines.FUNCTIONS_THREADS_BINARIES))
+		{
+		    enumer = ((GppTrace) (this.myGppGraph.getTrace())).getSortedBinariesElements();
+		}
+		else if ((drawMode == Defines.FUNCTIONS)
+			  || (drawMode == Defines.THREADS_FUNCTIONS)
+			  || (drawMode == Defines.THREADS_BINARIES_FUNCTIONS)
+			  || (drawMode == Defines.BINARIES_FUNCTIONS)
+			  || (drawMode == Defines.BINARIES_THREADS_FUNCTIONS))
+		{
+		    enumer = ((GppTrace) (this.myGppGraph.getTrace())).getSortedFunctionsElements();
+		}
+
+		if (enumer == null) 
+		    return;
+
+	  	// update the average load strings
+		if (   (myGppGraph.getSelectionStart() == -1)
+			|| (myGppGraph.getSelectionEnd()   == -1))
+		{
+		  	while(enumer.hasMoreElements())
+		  		((ProfiledGeneric) enumer.nextElement()).
+		  				setAverageLoadValueString(graphIndex, "  0.000"); //$NON-NLS-1$
+		} else {
+		  	while(enumer.hasMoreElements())
+		  	{
+		  	    updateThreadAverage(graphIndex, (ProfiledGeneric) enumer.nextElement());
+		  	}
+		}
+	}
+	
+	private void updateThreadAverage(int graphIndex, ProfiledGeneric pg)
+	{
+        float averageLoad = pg.getAverageLoad(
+				myGppGraph.getSelectionStart(),
+				myGppGraph.getSelectionEnd());
+			
+		if (averageLoad >= 0.001)
+		{
+			pg.setAverageLoadValueString(graphIndex, averageLoad);
+		}
+	  	else
+	  	{
+			pg.setAverageLoadValueString(graphIndex, "  0.000"); //$NON-NLS-1$
+	  	}
+	}
+  
+	public void paintComponent(Panel panel, Graphics graphics)
+	{		
+		// lay down the cumulative graphs first, then grid, and last with selection
+		// so the "effects" shows on the top layer
+		if (this.myGppGraph.barMode == GppTraceGraph.BAR_MODE_OFF)
+		{
+			this.drawCumulativeGraphLines(graphics);
+		}
+		else
+		{
+			this.drawBarGraph(graphics);
+		}
+		
+		this.myGppGraph.drawDottedLineBackground(graphics, GppTraceGraph.xLegendHeight);
+		this.myGppGraph.drawSelectionSection(graphics, GppTraceGraph.xLegendHeight);
+	}
+ 
+} //class VisualiserPanel
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.address.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/SomMapping.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.address;
+
+public class SomMapping
+  {
+    public int x;
+    public int y;
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,137 @@
+GppTrace.binaryNotFound1=Binary at 0x
+GppTrace.binarynotFound2=\ not found
+GppTrace.functionNotFound1=Function at 0x
+GppTrace.functionNotFound2=\ not found
+GppTraceParser.0=Address/thread trace file not found
+GppTraceGraph.cannotResolveThreadName=Cannot resolve thread name
+GppTraceGraph.cannotResolveBinaryName=Cannot resolve binary name
+GppTraceCsvPrinter.1=CSV print mode couldn't be solved
+GppTraceGraph.cannotResolveFunctionName=Cannot resolve function name
+GppTraceParser.1=Address/thread trace file invalid
+GppTraceCsvPrinter.2=Thread list file 
+GppTraceCsvPrinter.3=\ not found\!
+GppTraceParser.2=Finished reading
+GppTraceGraph.unknownOrExcludedBinaries=unknown or excluded binaries
+GppTraceGraph.unknownOrExcludedFunctions=unknown or excluded functions
+GppTraceGraph.NotFound=not found
+GppTraceGraph.notFound=not found
+GppTraceGraph.FunctionLoad=Function Load
+GppTraceGraph.debugDrawMode=Debug-> drawMode: 
+GppTraceGraph.draw=Draw 
+GppTraceGraph.traceGraphInternalErrorIn=internal error in GppTraceGraph
+GppTraceGraph.wrongDrawMode=Wrong draw mode\!
+GppTraceGraph.binaryAt=Binary at
+GppTraceGraph.binaryForAddress=Binary for address
+GppTraceGraph.binaryNotFound=Binary not found
+GppTraceGraph.threadLoad=Thread Load
+GppTraceGraph.binaryLoad=Binary Load
+GppTraceParser.4=Trace: 
+GppTraceGraph.functionAt=Function at
+GppTraceGraph.traceGraphInternalErrorAt=internal error at GppTraceGraph
+GppTraceGraph.functionForAddress=Function for address
+GppTraceGraph.functionNotFound=Function not found
+GppTraceGraph.unknownDrawMode=Internal Error: Unknown drawMode
+GppTraceGraph.actionString=Action string: 
+GppTraceGraph.drawMode=Draw mode: 
+GppTraceGraph.unknownOrExcludedThreads=unknown or excluded threads
+GppTraceParser.3=Data: 
+GppTraceParser.5=\ profiler:
+GppTraceParser.6=\ sampler:
+GppTraceParser.7=Unexpected end of file
+GppTraceParser.8=Unexpected end of file
+GppTraceParser.unknown=Unknown
+AddrBinaryTable.threshold1=\ binaries < 
+AddrBinaryTable.threshold2=\ binary < 
+AddrBinaryTable.binaryToThreadTo=\ Binary -> Thread ->
+AddrBinaryTable.binaryToFunctionTo=\ Binary -> Function ->
+AddrBinaryTable.comma=,
+AddrBinaryTable.binaries=Binaries
+AddrBinaryTable.zeroFormat=0.00
+AddrBinaryTable.decimalFormat=\#\#0.00
+AddrBinaryTable.threshold3=% load (< 
+AddrBinaryTable.threshold4=\ samples) in graph
+AddrBinaryTable.binaryLoad=Binary Load
+AddrBinaryTable.threadLoad=Thread Load
+AddrBinaryTable.binaryTo=\ Binary ->
+AddrBinaryTable.functionLoad=Function Load
+AddressPlugin.binaries=Binaries
+AddressPlugin.threads=Threads
+AddressPlugin.functions=Functions
+AddressPlugin.0=Thread
+AddressPlugin.1=Average Load
+AddressPlugin.10=Save CPU Load as comma-separated values
+AddressPlugin.11=Comma-Separated Value Files
+AddressPlugin.12=Change Threshold Limits...
+AddressPlugin.13=Save CPU Load as comma-separated values
+AddressPlugin.15=Maximum number of functions to display
+AddressPlugin.16=Not an integer number\!\!
+AddressPlugin.17=Maximum number of functions to display
+AddressPlugin.2=Unknown
+AddressPlugin.22=Fill in all graph loads
+AddressPlugin.24=Set minimum CPU load or sample count a thread, binary, or function needs so it is displayed
+AddressPlugin.3=CPU load graph
+AddressPlugin.4=Most Utilised Functions in 
+AddressPlugin.5=CPU Load Graphs
+AddressPlugin.6=Number of Functions
+AddressPlugin.7=Show Individual Samples
+AddressPlugin.8=No functions in the time period for 
+AddressPlugin.9=Fill in Graph Loads
+AddrFunctionTable.threshold1=\ functions < 
+AddrFunctionTable.threshold2=\ function < 
+AddrFunctionTable.threshold3=% load (< 
+AddrFunctionTable.threshold4=\ samples) in graph
+AddrFunctionTable.binaryLoad=Binary Load
+AddrFunctionTable.threadLoad=Thread Load
+AddrFunctionTable.functionToBinaryTo=\ Function -> Binary ->
+AddrFunctionTable.functionToThreadTo=\ Function -> Thread ->
+AddrFunctionTable.functions=Functions
+AddrFunctionTable.zeroFormat=0.00
+AddrFunctionTable.decimalFormat=\#\#0.00
+AddrFunctionTable.comma=,
+AddrFunctionTable.items=Items
+AddrFunctionTable.functionLoad=Function Load
+AddrFunctionTable.functionTo=\ Function ->
+AddrThreadTable.zeroFormat=0.00
+AddrThreadTable.decimalFormat=\#\#0.00
+AddrThreadTable.thresholdMsg1=\ threads < 
+AddrThreadTable.thresholdMsg2=\ thread < 
+AddrThreadTable.thresholdMsg3=% load (< 
+AddrThreadTable.thresholdMsg4=\ samples) in graph
+AddrThreadTable.threadLoad=Thread Load
+AddrThreadTable.functionLoad=Function Load
+AddrThreadTable.binaryLoad=Binary Load
+AddrThreadTable.threadTo=\ Thread ->
+AddrThreadTable.threadToBinaryTo=\ Thread -> Binary ->
+AddrThreadTable.threadToFunctionTo=\ Thread -> Function ->
+AddrThreadTable.threads=Threads
+AddrThreadTable.unsolvedPriority=Unsolved
+AddrThreadTable.NOSthreads=* NOS threads *
+AddrThreadTable.unknownPriority=Unknown
+AddrThreadTable.unrecordedPriority=*not recorded*
+AddrThreadTable.priorityStringEnding=(
+AddrThreadTable.priorityStringStart=i
+AddrThreadTable.savePrioritySamples=Save Priority Samples for Checked Threads...
+GenericAddrTable.binaryThreadFunction=Binary -> Thread -> Function
+GenericAddrTable.binaryFunction=Binary -> Function
+GenericAddrTable.binaryFunctionThread=Binary -> Function -> Thread
+GenericAddrTable.functionOnly=Function Only
+GenericAddrTable.functionThread=Function -> Thread
+GenericAddrTable.functionThreadBinary=Function -> Thread -> Binary
+GenericAddrTable.functionBinary=Function -> Binary
+GenericAddrTable.functionBinaryThread=Function -> Binary -> Thread
+GenericAddrTable.copyTable=Copy Table
+GenericAddrTable.copyDrilldownTables=Copy Drilldown Tables
+GenericAddrTable.saveDrilldownTables=Save Drilldown Tables...
+GenericAddrTable.saveTable=Save Table...
+GenericAddrTable.threadOnly=Thread Only
+GenericAddrTable.threadBinary=Thread -> Binary
+GenericAddrTable.threadBinaryFunction=Thread -> Binary -> Function
+GenericAddrTable.threadFunction=Thread -> Function
+GenericAddrTable.threadFunctionBinary=Thread -> Function -> Binary
+GenericAddrTable.binaryOnly=Binary Only
+GenericAddrTable.binaryThread=Binary -> Thread
+GenericAddrTable.saveSamples1=Save Samples for Checked 
+GenericAddrTable.saveSamples2=...
+GenericAddrTable.threadSampleHeading=Time (ms),Hex Address,Thread\n
+GenericAddrTable.binarySampleHeading=Time (ms),Hex Address,Binary\n
+GenericAddrTable.functionSampleHeading=Time (ms),Hex Address,Function,Hex Function Start\n
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Buttons
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.button;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.button.ButtonPlugin
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ com.nokia.carbide.cpp.sdk.core,
+ com.nokia.carbide.cpp.pi,
+ com.nokia.carbide.cpp.pi.util,
+ org.eclipse.draw2d,
+ org.eclipse.emf.common;bundle-version="2.4.0",
+ com.nokia.carbide.cpp.ui,
+ org.eclipse.ui.ide;bundle-version="3.4.0",
+ org.eclipse.ui.editors;bundle-version="3.4.0",
+ org.eclipse.emf.ecore;bundle-version="2.5.0"
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.internal.pi.button.ui;x-friends:="com.nokia.carbide.cpp.pi.wizards,com.nokia.carbide.cpp.pi.button.tests",
+ com.nokia.carbide.cpp.pi.button;x-friends:="com.nokia.carbide.cpp.pi.wizards,com.nokia.carbide.cpp.pi.button.tests"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,8 @@
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .,\
+               data/,\
+               icons/
+jars.compile.order = .
+source.. = src/
+output.. = bin/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/data/default.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,1268 @@
+<?xml version="1.0" encoding="ASCII"?>
+<buttonEventProfileList buttonEventProfileVersion="1.0">
+  <buttonEventProfile profileId="Symbian_TechView">
+    <mapping enumString="EKeyNull" keyCode="0" label="NUL"/>
+    <mapping enumString="" keyCode="1" label="SOH"/>
+    <mapping enumString="" keyCode="2" label="STX"/>
+    <mapping enumString="" keyCode="3" label="ETX"/>
+    <mapping enumString="" keyCode="4" label="EOT"/>
+    <mapping enumString="" keyCode="5" label="ENQ"/>
+    <mapping enumString="" keyCode="6" label="ACK"/>
+    <mapping enumString="EKeyBell" keyCode="7" label="BEL"/>
+    <mapping enumString="EKeyBackspace" keyCode="8" label="BS"/>
+    <mapping enumString="EKeyTab" keyCode="9" label="TAB"/>
+    <mapping enumString="EKeyLineFeed" keyCode="10" label="LF"/>
+    <mapping enumString="EKeyVerticalTab" keyCode="11" label="VT"/>
+    <mapping enumString="EKeyFormFeed" keyCode="12" label="FF"/>
+    <mapping enumString="EKeyEnter" keyCode="13" label="CR"/>
+    <mapping enumString="" keyCode="14" label="SO"/>
+    <mapping enumString="" keyCode="15" label="SI"/>
+    <mapping enumString="" keyCode="16" label="DLE"/>
+    <mapping enumString="" keyCode="17" label="DC1"/>
+    <mapping enumString="" keyCode="18" label="DC2"/>
+    <mapping enumString="" keyCode="19" label="DC3"/>
+    <mapping enumString="" keyCode="20" label="DC4"/>
+    <mapping enumString="" keyCode="21" label="NAK"/>
+    <mapping enumString="" keyCode="22" label="SYN"/>
+    <mapping enumString="" keyCode="23" label="ETB"/>
+    <mapping enumString="" keyCode="24" label="CAN"/>
+    <mapping enumString="" keyCode="25" label="EM"/>
+    <mapping enumString="" keyCode="26" label="SUB"/>
+    <mapping enumString="EKeyEscape" keyCode="27" label="ESC"/>
+    <mapping enumString="" keyCode="28" label="FS"/>
+    <mapping enumString="" keyCode="29" label="GS"/>
+    <mapping enumString="" keyCode="30" label="RS"/>
+    <mapping enumString="" keyCode="31" label="US"/>
+    <mapping enumString="EKeySpace" keyCode="32" label="Space"/>
+    <mapping enumString="" keyCode="33" label="!"/>
+    <mapping enumString="" keyCode="34" label="&quot;"/>
+    <mapping enumString="" keyCode="35" label="#"/>
+    <mapping enumString="" keyCode="36" label="$"/>
+    <mapping enumString="" keyCode="37" label="%"/>
+    <mapping enumString="" keyCode="38" label="&amp;"/>
+    <mapping enumString="" keyCode="39" label="'"/>
+    <mapping enumString="" keyCode="40" label="("/>
+    <mapping enumString="" keyCode="41" label=")"/>
+    <mapping enumString="" keyCode="42" label="*"/>
+    <mapping enumString="" keyCode="43" label="+"/>
+    <mapping enumString="" keyCode="44" label=","/>
+    <mapping enumString="" keyCode="45" label="-"/>
+    <mapping enumString="" keyCode="46" label="."/>
+    <mapping enumString="" keyCode="47" label="/"/>
+    <mapping enumString="" keyCode="48" label="0"/>
+    <mapping enumString="" keyCode="49" label="1"/>
+    <mapping enumString="" keyCode="50" label="2"/>
+    <mapping enumString="" keyCode="51" label="3"/>
+    <mapping enumString="" keyCode="52" label="4"/>
+    <mapping enumString="" keyCode="53" label="5"/>
+    <mapping enumString="" keyCode="54" label="6"/>
+    <mapping enumString="" keyCode="55" label="7"/>
+    <mapping enumString="" keyCode="56" label="8"/>
+    <mapping enumString="" keyCode="57" label="9"/>
+    <mapping enumString="" keyCode="58" label=":"/>
+    <mapping enumString="" keyCode="59" label=";"/>
+    <mapping enumString="" keyCode="60" label="&lt;"/>
+    <mapping enumString="" keyCode="61" label="="/>
+    <mapping enumString="" keyCode="62" label=">"/>
+    <mapping enumString="" keyCode="63" label="?"/>
+    <mapping enumString="" keyCode="64" label="@"/>
+    <mapping enumString="" keyCode="65" label="A"/>
+    <mapping enumString="" keyCode="66" label="B"/>
+    <mapping enumString="" keyCode="67" label="C"/>
+    <mapping enumString="" keyCode="68" label="D"/>
+    <mapping enumString="" keyCode="69" label="E"/>
+    <mapping enumString="" keyCode="70" label="F"/>
+    <mapping enumString="" keyCode="71" label="G"/>
+    <mapping enumString="" keyCode="72" label="H"/>
+    <mapping enumString="" keyCode="73" label="I"/>
+    <mapping enumString="" keyCode="74" label="J"/>
+    <mapping enumString="" keyCode="75" label="K"/>
+    <mapping enumString="" keyCode="76" label="L"/>
+    <mapping enumString="" keyCode="77" label="M"/>
+    <mapping enumString="" keyCode="78" label="N"/>
+    <mapping enumString="" keyCode="79" label="O"/>
+    <mapping enumString="" keyCode="80" label="P"/>
+    <mapping enumString="" keyCode="81" label="Q"/>
+    <mapping enumString="" keyCode="82" label="R"/>
+    <mapping enumString="" keyCode="83" label="S"/>
+    <mapping enumString="" keyCode="84" label="T"/>
+    <mapping enumString="" keyCode="85" label="U"/>
+    <mapping enumString="" keyCode="86" label="V"/>
+    <mapping enumString="" keyCode="87" label="W"/>
+    <mapping enumString="" keyCode="88" label="X"/>
+    <mapping enumString="" keyCode="89" label="Y"/>
+    <mapping enumString="" keyCode="90" label="Z"/>
+    <mapping enumString="" keyCode="91" label="["/>
+    <mapping enumString="" keyCode="92" label="\"/>
+    <mapping enumString="" keyCode="93" label="]"/>
+    <mapping enumString="" keyCode="94" label="^"/>
+    <mapping enumString="" keyCode="95" label="_"/>
+    <mapping enumString="" keyCode="96" label="`"/>
+    <mapping enumString="" keyCode="97" label="a"/>
+    <mapping enumString="" keyCode="98" label="b"/>
+    <mapping enumString="" keyCode="99" label="c"/>
+    <mapping enumString="" keyCode="100" label="d"/>
+    <mapping enumString="" keyCode="101" label="e"/>
+    <mapping enumString="" keyCode="102" label="f"/>
+    <mapping enumString="" keyCode="103" label="g"/>
+    <mapping enumString="" keyCode="104" label="h"/>
+    <mapping enumString="" keyCode="105" label="i"/>
+    <mapping enumString="" keyCode="106" label="j"/>
+    <mapping enumString="" keyCode="107" label="k"/>
+    <mapping enumString="" keyCode="108" label="l"/>
+    <mapping enumString="" keyCode="109" label="m"/>
+    <mapping enumString="" keyCode="110" label="n"/>
+    <mapping enumString="" keyCode="111" label="o"/>
+    <mapping enumString="" keyCode="112" label="p"/>
+    <mapping enumString="" keyCode="113" label="q"/>
+    <mapping enumString="" keyCode="114" label="r"/>
+    <mapping enumString="" keyCode="115" label="s"/>
+    <mapping enumString="" keyCode="116" label="t"/>
+    <mapping enumString="" keyCode="117" label="u"/>
+    <mapping enumString="" keyCode="118" label="v"/>
+    <mapping enumString="" keyCode="119" label="w"/>
+    <mapping enumString="" keyCode="120" label="x"/>
+    <mapping enumString="" keyCode="121" label="y"/>
+    <mapping enumString="" keyCode="122" label="z"/>
+    <mapping enumString="" keyCode="123" label="{"/>
+    <mapping enumString="" keyCode="124" label="|"/>
+    <mapping enumString="" keyCode="125" label="}"/>
+    <mapping enumString="" keyCode="126" label="~"/>
+    <mapping enumString="" keyCode="127" label="DEL"/>
+    <mapping enumString="EKeyPrintScreen" keyCode="63488" label="PrintScreen"/>
+    <mapping enumString="EKeyPause" keyCode="63489" label="Pause"/>
+    <mapping enumString="EKeyHome" keyCode="63490" label="Home"/>
+    <mapping enumString="EKeyEnd" keyCode="63491" label="End"/>
+    <mapping enumString="EKeyPageUp" keyCode="63492" label="PageUp"/>
+    <mapping enumString="EKeyPageDown" keyCode="63493" label="PageDown"/>
+    <mapping enumString="EKeyInsert" keyCode="63494" label="Insert"/>
+    <mapping enumString="EKeyLeftArrow" keyCode="63495" label="Left"/>
+    <mapping enumString="EKeyRightArrow" keyCode="63496" label="Right"/>
+    <mapping enumString="EKeyUpArrow" keyCode="63497" label="Up"/>
+    <mapping enumString="EKeyDownArrow" keyCode="63498" label="Down"/>
+    <mapping enumString="EKeyLeftShift" keyCode="63499" label="LeftShift"/>
+    <mapping enumString="EKeyRightShift" keyCode="63500" label="RightShift"/>
+    <mapping enumString="EKeyLeftAlt" keyCode="63501" label="LeftAlt"/>
+    <mapping enumString="EKeyRightAlt" keyCode="63502" label="RightAlt"/>
+    <mapping enumString="EKeyLeftCtrl" keyCode="63503" label="LeftCtrl"/>
+    <mapping enumString="EKeyRightCtrl" keyCode="63504" label="RightCtrl"/>
+    <mapping enumString="EKeyLeftFunc" keyCode="63505" label="LeftFunc"/>
+    <mapping enumString="EKeyRightFunc" keyCode="63506" label="RightFunc"/>
+    <mapping enumString="EKeyCapsLock" keyCode="63507" label="CapsLock"/>
+    <mapping enumString="EKeyNumLock" keyCode="63508" label="NumLock"/>
+    <mapping enumString="EKeyScrollLock" keyCode="63509" label="ScrollLock"/>
+    <mapping enumString="EKeyF1" keyCode="63510" label="F1"/>
+    <mapping enumString="EKeyF2" keyCode="63511" label="F2"/>
+    <mapping enumString="EKeyF3" keyCode="63512" label="F3"/>
+    <mapping enumString="EKeyF4" keyCode="63513" label="F4"/>
+    <mapping enumString="EKeyF5" keyCode="63514" label="F5"/>
+    <mapping enumString="EKeyF6" keyCode="63515" label="F6"/>
+    <mapping enumString="EKeyF7" keyCode="63516" label="F7"/>
+    <mapping enumString="EKeyF8" keyCode="63517" label="F8"/>
+    <mapping enumString="EKeyF9" keyCode="63518" label="F9"/>
+    <mapping enumString="EKeyF10" keyCode="63519" label="F10"/>
+    <mapping enumString="EKeyF11" keyCode="63520" label="F11"/>
+    <mapping enumString="EKeyF12" keyCode="63521" label="F12"/>
+    <mapping enumString="EKeyF13" keyCode="63522" label="F13"/>
+    <mapping enumString="EKeyF14" keyCode="63523" label="F14"/>
+    <mapping enumString="EKeyF15" keyCode="63524" label="F15"/>
+    <mapping enumString="EKeyF16" keyCode="63525" label="F16"/>
+    <mapping enumString="EKeyF17" keyCode="63526" label="F17"/>
+    <mapping enumString="EKeyF18" keyCode="63527" label="F18"/>
+    <mapping enumString="EKeyF19" keyCode="63528" label="F19"/>
+    <mapping enumString="EKeyF20" keyCode="63529" label="F20"/>
+    <mapping enumString="EKeyF21" keyCode="63530" label="F21"/>
+    <mapping enumString="EKeyF22" keyCode="63531" label="F22"/>
+    <mapping enumString="EKeyF23" keyCode="63532" label="F23"/>
+    <mapping enumString="EKeyF24" keyCode="63533" label="F24"/>
+    <mapping enumString="EKeyOff" keyCode="63534" label="Off"/>
+    <mapping enumString="EKeyIncContrast" keyCode="63535" label="IncContrast"/>
+    <mapping enumString="EKeyDecContrast" keyCode="63536" label="DecContrast"/>
+    <mapping enumString="EKeyBacklightOn" keyCode="63537" label="BacklightOn"/>
+    <mapping enumString="EKeyBacklightOff" keyCode="63538" label="BacklightOff"/>
+    <mapping enumString="EKeyBacklightToggle" keyCode="63539" label="BacklightToggle"/>
+    <mapping enumString="EKeySliderDown" keyCode="63540" label="SliderDown"/>
+    <mapping enumString="EKeySliderUp" keyCode="63541" label="SliderUp"/>
+    <mapping enumString="EKeyMenu" keyCode="63542" label="Menu"/>
+    <mapping enumString="EKeyDictaphonePlay" keyCode="63543" label="DictaphonePlay"/>
+    <mapping enumString="EKeyDictaphoneStop" keyCode="63544" label="DictaphoneStop"/>
+    <mapping enumString="EKeyDictaphoneRecord" keyCode="63545" label="DictaphoneRecord"/>
+    <mapping enumString="EKeyHelp" keyCode="63546" label="Help"/>
+    <mapping enumString="EKeyDial" keyCode="63547" label="Dial"/>
+    <mapping enumString="EKeyScreenDimension0" keyCode="63548" label="ScreenDimension0"/>
+    <mapping enumString="EKeyScreenDimension1" keyCode="63549" label="ScreenDimension1"/>
+    <mapping enumString="EKeyScreenDimension2" keyCode="63550" label="ScreenDimension2"/>
+    <mapping enumString="EKeyScreenDimension3" keyCode="63551" label="ScreenDimension3"/>
+    <mapping enumString="EKeyIncVolume" keyCode="63552" label="IncVolume"/>
+    <mapping enumString="EKeyDecVolume" keyCode="63553" label="DecVolume"/>
+    <mapping enumString="EKeyDevice0" keyCode="63554" label="Device0"/>
+    <mapping enumString="EKeyDevice1" keyCode="63555" label="Device1"/>
+    <mapping enumString="EKeyDevice2" keyCode="63556" label="Device2"/>
+    <mapping enumString="EKeyDevice3" keyCode="63557" label="Device3"/>
+    <mapping enumString="EKeyDevice4" keyCode="63558" label="Device4"/>
+    <mapping enumString="EKeyDevice5" keyCode="63559" label="Device5"/>
+    <mapping enumString="EKeyDevice6" keyCode="63560" label="Device6"/>
+    <mapping enumString="EKeyDevice7" keyCode="63561" label="Device7"/>
+    <mapping enumString="EKeyDevice8" keyCode="63562" label="Device8"/>
+    <mapping enumString="EKeyDevice9" keyCode="63563" label="Device9"/>
+    <mapping enumString="EKeyDeviceA" keyCode="63564" label="DeviceA"/>
+    <mapping enumString="EKeyDeviceB" keyCode="63565" label="DeviceB"/>
+    <mapping enumString="EKeyDeviceC" keyCode="63566" label="DeviceC"/>
+    <mapping enumString="EKeyDeviceD" keyCode="63567" label="DeviceD"/>
+    <mapping enumString="EKeyDeviceE" keyCode="63568" label="DeviceE"/>
+    <mapping enumString="EKeyDeviceF" keyCode="63569" label="DeviceF"/>
+    <mapping enumString="EKeyApplication0" keyCode="63570" label="Application0"/>
+    <mapping enumString="EKeyApplication1" keyCode="63571" label="Application1"/>
+    <mapping enumString="EKeyApplication2" keyCode="63572" label="Application2"/>
+    <mapping enumString="EKeyApplication3" keyCode="63573" label="Application3"/>
+    <mapping enumString="EKeyApplication4" keyCode="63574" label="Application4"/>
+    <mapping enumString="EKeyApplication5" keyCode="63575" label="Application5"/>
+    <mapping enumString="EKeyApplication6" keyCode="63576" label="Application6"/>
+    <mapping enumString="EKeyApplication7" keyCode="63577" label="Application7"/>
+    <mapping enumString="EKeyApplication8" keyCode="63578" label="Application8"/>
+    <mapping enumString="EKeyApplication9" keyCode="63579" label="Application9"/>
+    <mapping enumString="EKeyApplicationA" keyCode="63580" label="ApplicationA"/>
+    <mapping enumString="EKeyApplicationB" keyCode="63581" label="ApplicationB"/>
+    <mapping enumString="EKeyApplicationC" keyCode="63582" label="ApplicationC"/>
+    <mapping enumString="EKeyApplicationD" keyCode="63583" label="ApplicationD"/>
+    <mapping enumString="EKeyApplicationE" keyCode="63584" label="ApplicationE"/>
+    <mapping enumString="EKeyApplicationF" keyCode="63585" label="ApplicationF"/>
+    <mapping enumString="EKeyYes" keyCode="63586" label="Yes"/>
+    <mapping enumString="EKeyNo" keyCode="63587" label="No"/>
+    <mapping enumString="EKeyIncBrightness" keyCode="63588" label="IncBrightness"/>
+    <mapping enumString="EKeyDecBrightness" keyCode="63589" label="DecBrightness"/>
+    <mapping enumString="EKeyKeyboardExtend" keyCode="63590" label="KeyboardExtend"/>
+    <mapping enumString="EKeyDevice10" keyCode="63591" label="Device10"/>
+    <mapping enumString="EKeyDevice11" keyCode="63592" label="Device11"/>
+    <mapping enumString="EKeyDevice12" keyCode="63593" label="Device12"/>
+    <mapping enumString="EKeyDevice13" keyCode="63594" label="Device13"/>
+    <mapping enumString="EKeyDevice14" keyCode="63595" label="Device14"/>
+    <mapping enumString="EKeyDevice15" keyCode="63596" label="Device15"/>
+    <mapping enumString="EKeyDevice16" keyCode="63597" label="Device16"/>
+    <mapping enumString="EKeyDevice17" keyCode="63598" label="Device17"/>
+    <mapping enumString="EKeyDevice18" keyCode="63599" label="Device18"/>
+    <mapping enumString="EKeyDevice19" keyCode="63600" label="Device19"/>
+    <mapping enumString="EKeyDevice1A" keyCode="63601" label="Device1A"/>
+    <mapping enumString="EKeyDevice1B" keyCode="63602" label="Device1B"/>
+    <mapping enumString="EKeyDevice1C" keyCode="63603" label="Device1C"/>
+    <mapping enumString="EKeyDevice1D" keyCode="63604" label="Device1D"/>
+    <mapping enumString="EKeyDevice1E" keyCode="63605" label="Device1E"/>
+    <mapping enumString="EKeyDevice1F" keyCode="63606" label="Device1F"/>
+    <mapping enumString="EKeyApplication10" keyCode="63607" label="Application10"/>
+    <mapping enumString="EKeyApplication11" keyCode="63608" label="Application11"/>
+    <mapping enumString="EKeyApplication12" keyCode="63609" label="Application12"/>
+    <mapping enumString="EKeyApplication13" keyCode="63610" label="Application13"/>
+    <mapping enumString="EKeyApplication14" keyCode="63611" label="Application14"/>
+    <mapping enumString="EKeyApplication15" keyCode="63612" label="Application15"/>
+    <mapping enumString="EKeyApplication16" keyCode="63613" label="Application16"/>
+    <mapping enumString="EKeyApplication17" keyCode="63614" label="Application17"/>
+    <mapping enumString="EKeyApplication18" keyCode="63615" label="Application18"/>
+    <mapping enumString="EKeyApplication19" keyCode="63616" label="Application19"/>
+    <mapping enumString="EKeyApplication1A" keyCode="63617" label="Application1A"/>
+    <mapping enumString="EKeyApplication1B" keyCode="63618" label="Application1B"/>
+    <mapping enumString="EKeyApplication1C" keyCode="63619" label="Application1C"/>
+    <mapping enumString="EKeyApplication1D" keyCode="63620" label="Application1D"/>
+    <mapping enumString="EKeyApplication1E" keyCode="63621" label="Application1E"/>
+    <mapping enumString="EKeyApplication1F" keyCode="63622" label="Application1F"/>
+    <mapping enumString="EKeyDevice20" keyCode="63623" label="Device20"/>
+    <mapping enumString="EKeyDevice21" keyCode="63624" label="Device21"/>
+    <mapping enumString="EKeyDevice22" keyCode="63625" label="Device22"/>
+    <mapping enumString="EKeyDevice23" keyCode="63626" label="Device23"/>
+    <mapping enumString="EKeyDevice24" keyCode="63627" label="Device24"/>
+    <mapping enumString="EKeyDevice25" keyCode="63628" label="Device25"/>
+    <mapping enumString="EKeyDevice26" keyCode="63629" label="Device26"/>
+    <mapping enumString="EKeyDevice27" keyCode="63630" label="Device27"/>
+    <mapping enumString="EKeyApplication20" keyCode="63631" label="Application20"/>
+    <mapping enumString="EKeyApplication21" keyCode="63632" label="Application21"/>
+    <mapping enumString="EKeyApplication22" keyCode="63633" label="Application22"/>
+    <mapping enumString="EKeyApplication23" keyCode="63634" label="Application23"/>
+    <mapping enumString="EKeyApplication24" keyCode="63635" label="Application24"/>
+    <mapping enumString="EKeyApplication25" keyCode="63636" label="Application25"/>
+    <mapping enumString="EKeyApplication26" keyCode="63637" label="Application26"/>
+    <mapping enumString="EKeyApplication27" keyCode="63638" label="Application27"/>
+  </buttonEventProfile>
+  <buttonEventProfile profileId="S60">
+    <mapping enumString="EKeyNull" keyCode="0" label="NUL"/>
+    <mapping enumString="" keyCode="1" label="SOH"/>
+    <mapping enumString="" keyCode="2" label="STX"/>
+    <mapping enumString="" keyCode="3" label="ETX"/>
+    <mapping enumString="" keyCode="4" label="EOT"/>
+    <mapping enumString="" keyCode="5" label="ENQ"/>
+    <mapping enumString="" keyCode="6" label="ACK"/>
+    <mapping enumString="EKeyBell" keyCode="7" label="BEL"/>
+    <mapping enumString="EKeyBackspace" keyCode="8" label="BS"/>
+    <mapping enumString="EKeyTab" keyCode="9" label="TAB"/>
+    <mapping enumString="EKeyLineFeed" keyCode="10" label="LF"/>
+    <mapping enumString="EKeyVerticalTab" keyCode="11" label="VT"/>
+    <mapping enumString="EKeyFormFeed" keyCode="12" label="FF"/>
+    <mapping enumString="EKeyEnter" keyCode="13" label="CR"/>
+    <mapping enumString="" keyCode="14" label="SO"/>
+    <mapping enumString="" keyCode="15" label="SI"/>
+    <mapping enumString="" keyCode="16" label="DLE"/>
+    <mapping enumString="" keyCode="17" label="DC1"/>
+    <mapping enumString="" keyCode="18" label="DC2"/>
+    <mapping enumString="" keyCode="19" label="DC3"/>
+    <mapping enumString="" keyCode="20" label="DC4"/>
+    <mapping enumString="" keyCode="21" label="NAK"/>
+    <mapping enumString="" keyCode="22" label="SYN"/>
+    <mapping enumString="" keyCode="23" label="ETB"/>
+    <mapping enumString="" keyCode="24" label="CAN"/>
+    <mapping enumString="" keyCode="25" label="EM"/>
+    <mapping enumString="" keyCode="26" label="SUB"/>
+    <mapping enumString="EKeyEscape" keyCode="27" label="ESC"/>
+    <mapping enumString="" keyCode="28" label="FS"/>
+    <mapping enumString="" keyCode="29" label="GS"/>
+    <mapping enumString="" keyCode="30" label="RS"/>
+    <mapping enumString="" keyCode="31" label="US"/>
+    <mapping enumString="EKeySpace" keyCode="32" label="Space"/>
+    <mapping enumString="" keyCode="33" label="!"/>
+    <mapping enumString="" keyCode="34" label="&quot;"/>
+    <mapping enumString="" keyCode="35" label="#"/>
+    <mapping enumString="" keyCode="36" label="$"/>
+    <mapping enumString="" keyCode="37" label="%"/>
+    <mapping enumString="" keyCode="38" label="&amp;"/>
+    <mapping enumString="" keyCode="39" label="'"/>
+    <mapping enumString="" keyCode="40" label="("/>
+    <mapping enumString="" keyCode="41" label=")"/>
+    <mapping enumString="" keyCode="42" label="*"/>
+    <mapping enumString="" keyCode="43" label="+"/>
+    <mapping enumString="" keyCode="44" label=","/>
+    <mapping enumString="" keyCode="45" label="-"/>
+    <mapping enumString="" keyCode="46" label="."/>
+    <mapping enumString="" keyCode="47" label="/"/>
+    <mapping enumString="" keyCode="48" label="0"/>
+    <mapping enumString="" keyCode="49" label="1"/>
+    <mapping enumString="" keyCode="50" label="2"/>
+    <mapping enumString="" keyCode="51" label="3"/>
+    <mapping enumString="" keyCode="52" label="4"/>
+    <mapping enumString="" keyCode="53" label="5"/>
+    <mapping enumString="" keyCode="54" label="6"/>
+    <mapping enumString="" keyCode="55" label="7"/>
+    <mapping enumString="" keyCode="56" label="8"/>
+    <mapping enumString="" keyCode="57" label="9"/>
+    <mapping enumString="" keyCode="58" label=":"/>
+    <mapping enumString="" keyCode="59" label=";"/>
+    <mapping enumString="" keyCode="60" label="&lt;"/>
+    <mapping enumString="" keyCode="61" label="="/>
+    <mapping enumString="" keyCode="62" label=">"/>
+    <mapping enumString="" keyCode="63" label="?"/>
+    <mapping enumString="" keyCode="64" label="@"/>
+    <mapping enumString="" keyCode="65" label="A"/>
+    <mapping enumString="" keyCode="66" label="B"/>
+    <mapping enumString="" keyCode="67" label="C"/>
+    <mapping enumString="" keyCode="68" label="D"/>
+    <mapping enumString="" keyCode="69" label="E"/>
+    <mapping enumString="" keyCode="70" label="F"/>
+    <mapping enumString="" keyCode="71" label="G"/>
+    <mapping enumString="" keyCode="72" label="H"/>
+    <mapping enumString="" keyCode="73" label="I"/>
+    <mapping enumString="" keyCode="74" label="J"/>
+    <mapping enumString="" keyCode="75" label="K"/>
+    <mapping enumString="" keyCode="76" label="L"/>
+    <mapping enumString="" keyCode="77" label="M"/>
+    <mapping enumString="" keyCode="78" label="N"/>
+    <mapping enumString="" keyCode="79" label="O"/>
+    <mapping enumString="" keyCode="80" label="P"/>
+    <mapping enumString="" keyCode="81" label="Q"/>
+    <mapping enumString="" keyCode="82" label="R"/>
+    <mapping enumString="" keyCode="83" label="S"/>
+    <mapping enumString="" keyCode="84" label="T"/>
+    <mapping enumString="" keyCode="85" label="U"/>
+    <mapping enumString="" keyCode="86" label="V"/>
+    <mapping enumString="" keyCode="87" label="W"/>
+    <mapping enumString="" keyCode="88" label="X"/>
+    <mapping enumString="" keyCode="89" label="Y"/>
+    <mapping enumString="" keyCode="90" label="Z"/>
+    <mapping enumString="" keyCode="91" label="["/>
+    <mapping enumString="" keyCode="92" label="\"/>
+    <mapping enumString="" keyCode="93" label="]"/>
+    <mapping enumString="" keyCode="94" label="^"/>
+    <mapping enumString="" keyCode="95" label="_"/>
+    <mapping enumString="" keyCode="96" label="`"/>
+    <mapping enumString="" keyCode="97" label="a"/>
+    <mapping enumString="" keyCode="98" label="b"/>
+    <mapping enumString="" keyCode="99" label="c"/>
+    <mapping enumString="" keyCode="100" label="d"/>
+    <mapping enumString="" keyCode="101" label="e"/>
+    <mapping enumString="" keyCode="102" label="f"/>
+    <mapping enumString="" keyCode="103" label="g"/>
+    <mapping enumString="" keyCode="104" label="h"/>
+    <mapping enumString="" keyCode="105" label="i"/>
+    <mapping enumString="" keyCode="106" label="j"/>
+    <mapping enumString="" keyCode="107" label="k"/>
+    <mapping enumString="" keyCode="108" label="l"/>
+    <mapping enumString="" keyCode="109" label="m"/>
+    <mapping enumString="" keyCode="110" label="n"/>
+    <mapping enumString="" keyCode="111" label="o"/>
+    <mapping enumString="" keyCode="112" label="p"/>
+    <mapping enumString="" keyCode="113" label="q"/>
+    <mapping enumString="" keyCode="114" label="r"/>
+    <mapping enumString="" keyCode="115" label="s"/>
+    <mapping enumString="" keyCode="116" label="t"/>
+    <mapping enumString="" keyCode="117" label="u"/>
+    <mapping enumString="" keyCode="118" label="v"/>
+    <mapping enumString="" keyCode="119" label="w"/>
+    <mapping enumString="" keyCode="120" label="x"/>
+    <mapping enumString="" keyCode="121" label="y"/>
+    <mapping enumString="" keyCode="122" label="z"/>
+    <mapping enumString="" keyCode="123" label="{"/>
+    <mapping enumString="" keyCode="124" label="|"/>
+    <mapping enumString="" keyCode="125" label="}"/>
+    <mapping enumString="" keyCode="126" label="~"/>
+    <mapping enumString="" keyCode="127" label="DEL"/>
+    <mapping enumString="EKeyPrintScreen" keyCode="63488" label="PrintScreen"/>
+    <mapping enumString="EKeyPause" keyCode="63489" label="Pause"/>
+    <mapping enumString="EKeyHome" keyCode="63490" label="Home"/>
+    <mapping enumString="EKeyEnd" keyCode="63491" label="End"/>
+    <mapping enumString="EKeyPageUp" keyCode="63492" label="PageUp"/>
+    <mapping enumString="EKeyPageDown" keyCode="63493" label="PageDown"/>
+    <mapping enumString="EKeyInsert" keyCode="63494" label="Insert"/>
+    <mapping enumString="EKeyLeftArrow" keyCode="63495" label="Left"/>
+    <mapping enumString="EKeyRightArrow" keyCode="63496" label="Right"/>
+    <mapping enumString="EKeyUpArrow" keyCode="63497" label="Up"/>
+    <mapping enumString="EKeyDownArrow" keyCode="63498" label="Down"/>
+    <mapping enumString="EKeyLeftShift" keyCode="63499" label="LeftShift"/>
+    <mapping enumString="EKeyRightShift" keyCode="63500" label="RightShift"/>
+    <mapping enumString="EKeyLeftAlt" keyCode="63501" label="LeftAlt"/>
+    <mapping enumString="EKeyRightAlt" keyCode="63502" label="RightAlt"/>
+    <mapping enumString="EKeyLeftCtrl" keyCode="63503" label="LeftCtrl"/>
+    <mapping enumString="EKeyRightCtrl" keyCode="63504" label="RightCtrl"/>
+    <mapping enumString="EKeyLeftFunc" keyCode="63505" label="LeftFunc"/>
+    <mapping enumString="EKeyRightFunc" keyCode="63506" label="RightFunc"/>
+    <mapping enumString="EKeyCapsLock" keyCode="63507" label="CapsLock"/>
+    <mapping enumString="EKeyNumLock" keyCode="63508" label="NumLock"/>
+    <mapping enumString="EKeyScrollLock" keyCode="63509" label="ScrollLock"/>
+    <mapping enumString="EKeyF1" keyCode="63510" label="F1"/>
+    <mapping enumString="EKeyF2" keyCode="63511" label="F2"/>
+    <mapping enumString="EKeyF3" keyCode="63512" label="F3"/>
+    <mapping enumString="EKeyF4" keyCode="63513" label="F4"/>
+    <mapping enumString="EKeyF5" keyCode="63514" label="F5"/>
+    <mapping enumString="EKeyF6" keyCode="63515" label="F6"/>
+    <mapping enumString="EKeyF7" keyCode="63516" label="F7"/>
+    <mapping enumString="EKeyF8" keyCode="63517" label="F8"/>
+    <mapping enumString="EKeyF9" keyCode="63518" label="F9"/>
+    <mapping enumString="EKeyF10" keyCode="63519" label="F10"/>
+    <mapping enumString="EKeyF11" keyCode="63520" label="F11"/>
+    <mapping enumString="EKeyF12" keyCode="63521" label="F12"/>
+    <mapping enumString="EKeyF13" keyCode="63522" label="F13"/>
+    <mapping enumString="EKeyF14" keyCode="63523" label="F14"/>
+    <mapping enumString="EKeyF15" keyCode="63524" label="F15"/>
+    <mapping enumString="EKeyF16" keyCode="63525" label="F16"/>
+    <mapping enumString="EKeyF17" keyCode="63526" label="F17"/>
+    <mapping enumString="EKeyF18" keyCode="63527" label="F18"/>
+    <mapping enumString="EKeyF19" keyCode="63528" label="F19"/>
+    <mapping enumString="EKeyF20" keyCode="63529" label="F20"/>
+    <mapping enumString="EKeyF21" keyCode="63530" label="F21"/>
+    <mapping enumString="EKeyF22" keyCode="63531" label="F22"/>
+    <mapping enumString="EKeyF23" keyCode="63532" label="F23"/>
+    <mapping enumString="EKeyF24" keyCode="63533" label="F24"/>
+    <mapping enumString="EKeyOff" keyCode="63534" label="Off"/>
+    <mapping enumString="EKeyIncContrast" keyCode="63535" label="IncContrast"/>
+    <mapping enumString="EKeyDecContrast" keyCode="63536" label="DecContrast"/>
+    <mapping enumString="EKeyBacklightOn" keyCode="63537" label="BacklightOn"/>
+    <mapping enumString="EKeyBacklightOff" keyCode="63538" label="BacklightOff"/>
+    <mapping enumString="EKeyBacklightToggle" keyCode="63539" label="BacklightToggle"/>
+    <mapping enumString="EKeySliderDown" keyCode="63540" label="SliderDown"/>
+    <mapping enumString="EKeySliderUp" keyCode="63541" label="SliderUp"/>
+    <mapping enumString="EKeyMenu" keyCode="63542" label="Menu"/>
+    <mapping enumString="EKeyDictaphonePlay" keyCode="63543" label="DictaphonePlay"/>
+    <mapping enumString="EKeyDictaphoneStop" keyCode="63544" label="DictaphoneStop"/>
+    <mapping enumString="EKeyDictaphoneRecord" keyCode="63545" label="DictaphoneRecord"/>
+    <mapping enumString="EKeyHelp" keyCode="63546" label="Help"/>
+    <mapping enumString="EKeyDial" keyCode="63547" label="Dial"/>
+    <mapping enumString="EKeyScreenDimension0" keyCode="63548" label="ScreenDimension0"/>
+    <mapping enumString="EKeyScreenDimension1" keyCode="63549" label="ScreenDimension1"/>
+    <mapping enumString="EKeyScreenDimension2" keyCode="63550" label="ScreenDimension2"/>
+    <mapping enumString="EKeyScreenDimension3" keyCode="63551" label="ScreenDimension3"/>
+    <mapping enumString="EKeyIncVolume" keyCode="63552" label="IncVolume"/>
+    <mapping enumString="EKeyDecVolume" keyCode="63553" label="DecVolume"/>
+    <mapping enumString="EKeyDevice0" keyCode="63554" label="CBA1"/>
+    <mapping enumString="EKeyDevice1" keyCode="63555" label="CBA2"/>
+    <mapping enumString="EKeyDevice2" keyCode="63556" label="PowerOff"/>
+    <mapping enumString="EKeyDevice3" keyCode="63557" label="OK"/>
+    <mapping enumString="EKeyDevice4" keyCode="63558" label="GripOpen"/>
+    <mapping enumString="EKeyDevice5" keyCode="63559" label="GripClose"/>
+    <mapping enumString="EKeyDevice6" keyCode="63560" label="Side"/>
+    <mapping enumString="EKeyDevice7" keyCode="63561" label="TwistOpen"/>
+    <mapping enumString="EKeyDevice8" keyCode="63562" label="TwisClose"/>
+    <mapping enumString="EKeyDevice9" keyCode="63563" label="FlipOpen"/>
+    <mapping enumString="EKeyDeviceA" keyCode="63564" label="FlipClose"/>
+    <mapping enumString="EKeyDeviceB" keyCode="63565" label="DeviceB"/>
+    <mapping enumString="EKeyDeviceC" keyCode="63566" label="DeviceC"/>
+    <mapping enumString="EKeyDeviceD" keyCode="63567" label="DeviceD"/>
+    <mapping enumString="EKeyDeviceE" keyCode="63568" label="DeviceE"/>
+    <mapping enumString="EKeyDeviceF" keyCode="63569" label="DeviceF"/>
+    <mapping enumString="EKeyApplication0" keyCode="63570" label="PoC"/>
+    <mapping enumString="EKeyApplication1" keyCode="63571" label="Play"/>
+    <mapping enumString="EKeyApplication2" keyCode="63572" label="Stop"/>
+    <mapping enumString="EKeyApplication3" keyCode="63573" label="Forward"/>
+    <mapping enumString="EKeyApplication4" keyCode="63574" label="Rewind"/>
+    <mapping enumString="EKeyApplication5" keyCode="63575" label="Operator"/>
+    <mapping enumString="EKeyApplication6" keyCode="63576" label="QwertyOn"/>
+    <mapping enumString="EKeyApplication7" keyCode="63577" label="QwertyOff"/>
+    <mapping enumString="EKeyApplication8" keyCode="63578" label="Next"/>
+    <mapping enumString="EKeyApplication9" keyCode="63579" label="Previous"/>
+    <mapping enumString="EKeyApplicationA" keyCode="63580" label="HoldSwitch"/>
+    <mapping enumString="EKeyApplicationB" keyCode="63581" label="ZoomIn"/>
+    <mapping enumString="EKeyApplicationC" keyCode="63582" label="ZoomOut"/>
+    <mapping enumString="EKeyApplicationD" keyCode="63583" label="ApplicationD"/>
+    <mapping enumString="EKeyApplicationE" keyCode="63584" label="ApplicationE"/>
+    <mapping enumString="EKeyApplicationF" keyCode="63585" label="ApplicationF"/>
+    <mapping enumString="EKeyYes" keyCode="63586" label="PhoneSend"/>
+    <mapping enumString="EKeyNo" keyCode="63587" label="PhoneEnd"/>
+    <mapping enumString="EKeyIncBrightness" keyCode="63588" label="VolumeUp"/>
+    <mapping enumString="EKeyDecBrightness" keyCode="63589" label="VolumeDown"/>
+    <mapping enumString="EKeyKeyboardExtend" keyCode="63590" label="KeyboardExtend"/>
+    <mapping enumString="EKeyDevice10" keyCode="63591" label="Device10"/>
+    <mapping enumString="EKeyDevice11" keyCode="63592" label="Device11"/>
+    <mapping enumString="EKeyDevice12" keyCode="63593" label="Device12"/>
+    <mapping enumString="EKeyDevice13" keyCode="63594" label="Device13"/>
+    <mapping enumString="EKeyDevice14" keyCode="63595" label="Device14"/>
+    <mapping enumString="EKeyDevice15" keyCode="63596" label="Device15"/>
+    <mapping enumString="EKeyDevice16" keyCode="63597" label="Device16"/>
+    <mapping enumString="EKeyDevice17" keyCode="63598" label="Device17"/>
+    <mapping enumString="EKeyDevice18" keyCode="63599" label="Device18"/>
+    <mapping enumString="EKeyDevice19" keyCode="63600" label="Device19"/>
+    <mapping enumString="EKeyDevice1A" keyCode="63601" label="Device1A"/>
+    <mapping enumString="EKeyDevice1B" keyCode="63602" label="Device1B"/>
+    <mapping enumString="EKeyDevice1C" keyCode="63603" label="Device1C"/>
+    <mapping enumString="EKeyDevice1D" keyCode="63604" label="Device1D"/>
+    <mapping enumString="EKeyDevice1E" keyCode="63605" label="Device1E"/>
+    <mapping enumString="EKeyDevice1F" keyCode="63606" label="Device1F"/>
+    <mapping enumString="EKeyApplication10" keyCode="63607" label="Application10"/>
+    <mapping enumString="EKeyApplication11" keyCode="63608" label="Application11"/>
+    <mapping enumString="EKeyApplication12" keyCode="63609" label="Application12"/>
+    <mapping enumString="EKeyApplication13" keyCode="63610" label="Application13"/>
+    <mapping enumString="EKeyApplication14" keyCode="63611" label="Application14"/>
+    <mapping enumString="EKeyApplication15" keyCode="63612" label="Application15"/>
+    <mapping enumString="EKeyApplication16" keyCode="63613" label="Application16"/>
+    <mapping enumString="EKeyApplication17" keyCode="63614" label="Application17"/>
+    <mapping enumString="EKeyApplication18" keyCode="63615" label="Application18"/>
+    <mapping enumString="EKeyApplication19" keyCode="63616" label="Application19"/>
+    <mapping enumString="EKeyApplication1A" keyCode="63617" label="Application1A"/>
+    <mapping enumString="EKeyApplication1B" keyCode="63618" label="Application1B"/>
+    <mapping enumString="EKeyApplication1C" keyCode="63619" label="Application1C"/>
+    <mapping enumString="EKeyApplication1D" keyCode="63620" label="Application1D"/>
+    <mapping enumString="EKeyApplication1E" keyCode="63621" label="Application1E"/>
+    <mapping enumString="EKeyApplication1F" keyCode="63622" label="Application1F"/>
+    <mapping enumString="EKeyDevice20" keyCode="63623" label="Device20"/>
+    <mapping enumString="EKeyDevice21" keyCode="63624" label="Device21"/>
+    <mapping enumString="EKeyDevice22" keyCode="63625" label="Device22"/>
+    <mapping enumString="EKeyDevice23" keyCode="63626" label="Device23"/>
+    <mapping enumString="EKeyDevice24" keyCode="63627" label="Device24"/>
+    <mapping enumString="EKeyDevice25" keyCode="63628" label="Device25"/>
+    <mapping enumString="EKeyDevice26" keyCode="63629" label="Device26"/>
+    <mapping enumString="EKeyDevice27" keyCode="63630" label="Device27"/>
+    <mapping enumString="EKeyApplication20" keyCode="63631" label="Application20"/>
+    <mapping enumString="EKeyApplication21" keyCode="63632" label="Application21"/>
+    <mapping enumString="EKeyApplication22" keyCode="63633" label="Application22"/>
+    <mapping enumString="EKeyApplication23" keyCode="63634" label="Application23"/>
+    <mapping enumString="EKeyApplication24" keyCode="63635" label="Application24"/>
+    <mapping enumString="EKeyApplication25" keyCode="63636" label="Application25"/>
+    <mapping enumString="EKeyApplication26" keyCode="63637" label="Application26"/>
+    <mapping enumString="EKeyApplication27" keyCode="63638" label="Application27"/>
+  </buttonEventProfile>
+  <buttonEventProfile profileId="MOAP">
+    <mapping enumString="EKeyNull" keyCode="0" label="NUL"/>
+    <mapping enumString="" keyCode="1" label="SOH"/>
+    <mapping enumString="" keyCode="2" label="STX"/>
+    <mapping enumString="" keyCode="3" label="ETX"/>
+    <mapping enumString="" keyCode="4" label="EOT"/>
+    <mapping enumString="" keyCode="5" label="ENQ"/>
+    <mapping enumString="" keyCode="6" label="ACK"/>
+    <mapping enumString="EKeyBell" keyCode="7" label="BEL"/>
+    <mapping enumString="EKeyBackspace" keyCode="8" label="BS"/>
+    <mapping enumString="EKeyTab" keyCode="9" label="TAB"/>
+    <mapping enumString="EKeyLineFeed" keyCode="10" label="LF"/>
+    <mapping enumString="EKeyVerticalTab" keyCode="11" label="VT"/>
+    <mapping enumString="EKeyFormFeed" keyCode="12" label="FF"/>
+    <mapping enumString="EKeyEnter" keyCode="13" label="Select"/>
+    <mapping enumString="" keyCode="14" label="SO"/>
+    <mapping enumString="" keyCode="15" label="SI"/>
+    <mapping enumString="" keyCode="16" label="DLE"/>
+    <mapping enumString="" keyCode="17" label="DC1"/>
+    <mapping enumString="" keyCode="18" label="DC2"/>
+    <mapping enumString="" keyCode="19" label="DC3"/>
+    <mapping enumString="" keyCode="20" label="DC4"/>
+    <mapping enumString="" keyCode="21" label="NAK"/>
+    <mapping enumString="" keyCode="22" label="SYN"/>
+    <mapping enumString="" keyCode="23" label="ETB"/>
+    <mapping enumString="" keyCode="24" label="CAN"/>
+    <mapping enumString="" keyCode="25" label="EM"/>
+    <mapping enumString="" keyCode="26" label="SUB"/>
+    <mapping enumString="EKeyEscape" keyCode="27" label="ESC"/>
+    <mapping enumString="" keyCode="28" label="FS"/>
+    <mapping enumString="" keyCode="29" label="GS"/>
+    <mapping enumString="" keyCode="30" label="RS"/>
+    <mapping enumString="" keyCode="31" label="US"/>
+    <mapping enumString="EKeySpace" keyCode="32" label="Space"/>
+    <mapping enumString="" keyCode="33" label="!"/>
+    <mapping enumString="" keyCode="34" label="&quot;"/>
+    <mapping enumString="" keyCode="35" label="#"/>
+    <mapping enumString="" keyCode="36" label="$"/>
+    <mapping enumString="" keyCode="37" label="%"/>
+    <mapping enumString="" keyCode="38" label="&amp;"/>
+    <mapping enumString="" keyCode="39" label="'"/>
+    <mapping enumString="" keyCode="40" label="("/>
+    <mapping enumString="" keyCode="41" label=")"/>
+    <mapping enumString="" keyCode="42" label="*"/>
+    <mapping enumString="" keyCode="43" label="+"/>
+    <mapping enumString="" keyCode="44" label=","/>
+    <mapping enumString="" keyCode="45" label="-"/>
+    <mapping enumString="" keyCode="46" label="."/>
+    <mapping enumString="" keyCode="47" label="/"/>
+    <mapping enumString="" keyCode="48" label="0"/>
+    <mapping enumString="" keyCode="49" label="1"/>
+    <mapping enumString="" keyCode="50" label="2"/>
+    <mapping enumString="" keyCode="51" label="3"/>
+    <mapping enumString="" keyCode="52" label="4"/>
+    <mapping enumString="" keyCode="53" label="5"/>
+    <mapping enumString="" keyCode="54" label="6"/>
+    <mapping enumString="" keyCode="55" label="7"/>
+    <mapping enumString="" keyCode="56" label="8"/>
+    <mapping enumString="" keyCode="57" label="9"/>
+    <mapping enumString="" keyCode="58" label=":"/>
+    <mapping enumString="" keyCode="59" label=";"/>
+    <mapping enumString="" keyCode="60" label="&lt;"/>
+    <mapping enumString="" keyCode="61" label="="/>
+    <mapping enumString="" keyCode="62" label=">"/>
+    <mapping enumString="" keyCode="63" label="?"/>
+    <mapping enumString="" keyCode="64" label="@"/>
+    <mapping enumString="" keyCode="65" label="A"/>
+    <mapping enumString="" keyCode="66" label="B"/>
+    <mapping enumString="" keyCode="67" label="C"/>
+    <mapping enumString="" keyCode="68" label="D"/>
+    <mapping enumString="" keyCode="69" label="E"/>
+    <mapping enumString="" keyCode="70" label="F"/>
+    <mapping enumString="" keyCode="71" label="G"/>
+    <mapping enumString="" keyCode="72" label="H"/>
+    <mapping enumString="" keyCode="73" label="I"/>
+    <mapping enumString="" keyCode="74" label="J"/>
+    <mapping enumString="" keyCode="75" label="K"/>
+    <mapping enumString="" keyCode="76" label="L"/>
+    <mapping enumString="" keyCode="77" label="M"/>
+    <mapping enumString="" keyCode="78" label="N"/>
+    <mapping enumString="" keyCode="79" label="O"/>
+    <mapping enumString="" keyCode="80" label="P"/>
+    <mapping enumString="" keyCode="81" label="Q"/>
+    <mapping enumString="" keyCode="82" label="R"/>
+    <mapping enumString="" keyCode="83" label="S"/>
+    <mapping enumString="" keyCode="84" label="T"/>
+    <mapping enumString="" keyCode="85" label="U"/>
+    <mapping enumString="" keyCode="86" label="V"/>
+    <mapping enumString="" keyCode="87" label="W"/>
+    <mapping enumString="" keyCode="88" label="X"/>
+    <mapping enumString="" keyCode="89" label="Y"/>
+    <mapping enumString="" keyCode="90" label="Z"/>
+    <mapping enumString="" keyCode="91" label="["/>
+    <mapping enumString="" keyCode="92" label="\"/>
+    <mapping enumString="" keyCode="93" label="]"/>
+    <mapping enumString="" keyCode="94" label="^"/>
+    <mapping enumString="" keyCode="95" label="_"/>
+    <mapping enumString="" keyCode="96" label="`"/>
+    <mapping enumString="" keyCode="97" label="a"/>
+    <mapping enumString="" keyCode="98" label="b"/>
+    <mapping enumString="" keyCode="99" label="c"/>
+    <mapping enumString="" keyCode="100" label="d"/>
+    <mapping enumString="" keyCode="101" label="e"/>
+    <mapping enumString="" keyCode="102" label="f"/>
+    <mapping enumString="" keyCode="103" label="g"/>
+    <mapping enumString="" keyCode="104" label="h"/>
+    <mapping enumString="" keyCode="105" label="i"/>
+    <mapping enumString="" keyCode="106" label="j"/>
+    <mapping enumString="" keyCode="107" label="k"/>
+    <mapping enumString="" keyCode="108" label="l"/>
+    <mapping enumString="" keyCode="109" label="m"/>
+    <mapping enumString="" keyCode="110" label="n"/>
+    <mapping enumString="" keyCode="111" label="o"/>
+    <mapping enumString="" keyCode="112" label="p"/>
+    <mapping enumString="" keyCode="113" label="q"/>
+    <mapping enumString="" keyCode="114" label="r"/>
+    <mapping enumString="" keyCode="115" label="s"/>
+    <mapping enumString="" keyCode="116" label="t"/>
+    <mapping enumString="" keyCode="117" label="u"/>
+    <mapping enumString="" keyCode="118" label="v"/>
+    <mapping enumString="" keyCode="119" label="w"/>
+    <mapping enumString="" keyCode="120" label="x"/>
+    <mapping enumString="" keyCode="121" label="y"/>
+    <mapping enumString="" keyCode="122" label="z"/>
+    <mapping enumString="" keyCode="123" label="{"/>
+    <mapping enumString="" keyCode="124" label="|"/>
+    <mapping enumString="" keyCode="125" label="}"/>
+    <mapping enumString="" keyCode="126" label="~"/>
+    <mapping enumString="" keyCode="127" label="Clear"/>
+    <mapping enumString="EKeyPrintScreen" keyCode="63488" label="PrintScreen"/>
+    <mapping enumString="EKeyPause" keyCode="63489" label="Pause"/>
+    <mapping enumString="EKeyHome" keyCode="63490" label="Home"/>
+    <mapping enumString="EKeyEnd" keyCode="63491" label="End"/>
+    <mapping enumString="EKeyPageUp" keyCode="63492" label="PageUp"/>
+    <mapping enumString="EKeyPageDown" keyCode="63493" label="PageDown"/>
+    <mapping enumString="EKeyInsert" keyCode="63494" label="Insert"/>
+    <mapping enumString="EKeyLeftArrow" keyCode="63495" label="Left"/>
+    <mapping enumString="EKeyRightArrow" keyCode="63496" label="Right"/>
+    <mapping enumString="EKeyUpArrow" keyCode="63497" label="Up"/>
+    <mapping enumString="EKeyDownArrow" keyCode="63498" label="Down"/>
+    <mapping enumString="EKeyLeftShift" keyCode="63499" label="LeftShift"/>
+    <mapping enumString="EKeyRightShift" keyCode="63500" label="RightShift"/>
+    <mapping enumString="EKeyLeftAlt" keyCode="63501" label="LeftAlt"/>
+    <mapping enumString="EKeyRightAlt" keyCode="63502" label="RightAlt"/>
+    <mapping enumString="EKeyLeftCtrl" keyCode="63503" label="LeftCtrl"/>
+    <mapping enumString="EKeyRightCtrl" keyCode="63504" label="RightCtrl"/>
+    <mapping enumString="EKeyLeftFunc" keyCode="63505" label="LeftFunc"/>
+    <mapping enumString="EKeyRightFunc" keyCode="63506" label="RightFunc"/>
+    <mapping enumString="EKeyCapsLock" keyCode="63507" label="CapsLock"/>
+    <mapping enumString="EKeyNumLock" keyCode="63508" label="NumLock"/>
+    <mapping enumString="EKeyScrollLock" keyCode="63509" label="ScrollLock"/>
+    <mapping enumString="EKeyF1" keyCode="63510" label="F1"/>
+    <mapping enumString="EKeyF2" keyCode="63511" label="F2"/>
+    <mapping enumString="EKeyF3" keyCode="63512" label="F3"/>
+    <mapping enumString="EKeyF4" keyCode="63513" label="F4"/>
+    <mapping enumString="EKeyF5" keyCode="63514" label="F5"/>
+    <mapping enumString="EKeyF6" keyCode="63515" label="F6"/>
+    <mapping enumString="EKeyF7" keyCode="63516" label="F7"/>
+    <mapping enumString="EKeyF8" keyCode="63517" label="F8"/>
+    <mapping enumString="EKeyF9" keyCode="63518" label="F9"/>
+    <mapping enumString="EKeyF10" keyCode="63519" label="F10"/>
+    <mapping enumString="EKeyF11" keyCode="63520" label="F11"/>
+    <mapping enumString="EKeyF12" keyCode="63521" label="F12"/>
+    <mapping enumString="EKeyF13" keyCode="63522" label="F13"/>
+    <mapping enumString="EKeyF14" keyCode="63523" label="F14"/>
+    <mapping enumString="EKeyF15" keyCode="63524" label="F15"/>
+    <mapping enumString="EKeyF16" keyCode="63525" label="F16"/>
+    <mapping enumString="EKeyF17" keyCode="63526" label="F17"/>
+    <mapping enumString="EKeyF18" keyCode="63527" label="F18"/>
+    <mapping enumString="EKeyF19" keyCode="63528" label="F19"/>
+    <mapping enumString="EKeyF20" keyCode="63529" label="HeadSet"/>
+    <mapping enumString="EKeyF21" keyCode="63530" label="F21"/>
+    <mapping enumString="EKeyF22" keyCode="63531" label="F22"/>
+    <mapping enumString="EKeyF23" keyCode="63532" label="F23"/>
+    <mapping enumString="EKeyF24" keyCode="63533" label="F24"/>
+    <mapping enumString="EKeyOff" keyCode="63534" label="Off"/>
+    <mapping enumString="EKeyIncContrast" keyCode="63535" label="IncContrast"/>
+    <mapping enumString="EKeyDecContrast" keyCode="63536" label="DecContrast"/>
+    <mapping enumString="EKeyBacklightOn" keyCode="63537" label="BacklightOn"/>
+    <mapping enumString="EKeyBacklightOff" keyCode="63538" label="BacklightOff"/>
+    <mapping enumString="EKeyBacklightToggle" keyCode="63539" label="BacklightToggle"/>
+    <mapping enumString="EKeySliderDown" keyCode="63540" label="SliderDown"/>
+    <mapping enumString="EKeySliderUp" keyCode="63541" label="SliderUp"/>
+    <mapping enumString="EKeyMenu" keyCode="63542" label="Menu"/>
+    <mapping enumString="EKeyDictaphonePlay" keyCode="63543" label="DictaphonePlay"/>
+    <mapping enumString="EKeyDictaphoneStop" keyCode="63544" label="DictaphoneStop"/>
+    <mapping enumString="EKeyDictaphoneRecord" keyCode="63545" label="DictaphoneRecord"/>
+    <mapping enumString="EKeyHelp" keyCode="63546" label="Help"/>
+    <mapping enumString="EKeyDial" keyCode="63547" label="Dial"/>
+    <mapping enumString="EKeyScreenDimension0" keyCode="63548" label="ScreenDimension0"/>
+    <mapping enumString="EKeyScreenDimension1" keyCode="63549" label="ScreenDimension1"/>
+    <mapping enumString="EKeyScreenDimension2" keyCode="63550" label="ScreenDimension2"/>
+    <mapping enumString="EKeyScreenDimension3" keyCode="63551" label="ScreenDimension3"/>
+    <mapping enumString="EKeyIncVolume" keyCode="63552" label="IncVolume"/>
+    <mapping enumString="EKeyDecVolume" keyCode="63553" label="DecVolume"/>
+    <mapping enumString="EKeyDevice0" keyCode="63554" label="AutoFocus"/>
+    <mapping enumString="EKeyDevice1" keyCode="63555" label="RearUp"/>
+    <mapping enumString="EKeyDevice2" keyCode="63556" label="RearDown"/>
+    <mapping enumString="EKeyDevice3" keyCode="63557" label="SoftKey1"/>
+    <mapping enumString="EKeyDevice4" keyCode="63558" label="SoftKey2"/>
+    <mapping enumString="EKeyDevice5" keyCode="63559" label="Device5"/>
+    <mapping enumString="EKeyDevice6" keyCode="63560" label="Device6"/>
+    <mapping enumString="EKeyDevice7" keyCode="63561" label="Device7"/>
+    <mapping enumString="EKeyDevice8" keyCode="63562" label="Device8"/>
+    <mapping enumString="EKeyDevice9" keyCode="63563" label="Device9"/>
+    <mapping enumString="EKeyDeviceA" keyCode="63564" label="DeviceA"/>
+    <mapping enumString="EKeyDeviceB" keyCode="63565" label="DeviceB"/>
+    <mapping enumString="EKeyDeviceC" keyCode="63566" label="Ptt"/>
+    <mapping enumString="EKeyDeviceD" keyCode="63567" label="DeviceD"/>
+    <mapping enumString="EKeyDeviceE" keyCode="63568" label="DeviceE"/>
+    <mapping enumString="EKeyDeviceF" keyCode="63569" label="RTC_Adjustment"/>
+    <mapping enumString="EKeyApplication0" keyCode="63570" label="Imode"/>
+    <mapping enumString="EKeyApplication1" keyCode="63571" label="Mail"/>
+    <mapping enumString="EKeyApplication2" keyCode="63572" label="AppChange"/>
+    <mapping enumString="EKeyApplication3" keyCode="63573" label="Application3"/>
+    <mapping enumString="EKeyApplication4" keyCode="63574" label="Application4"/>
+    <mapping enumString="EKeyApplication5" keyCode="63575" label="OnHook"/>
+    <mapping enumString="EKeyApplication6" keyCode="63576" label="OffHook"/>
+    <mapping enumString="EKeyApplication7" keyCode="63577" label="Application7"/>
+    <mapping enumString="EKeyApplication8" keyCode="63578" label="Application8"/>
+    <mapping enumString="EKeyApplication9" keyCode="63579" label="Application9"/>
+    <mapping enumString="EKeyApplicationA" keyCode="63580" label="ApplicationA"/>
+    <mapping enumString="EKeyApplicationB" keyCode="63581" label="ApplicationB"/>
+    <mapping enumString="EKeyApplicationC" keyCode="63582" label="ApplicationC"/>
+    <mapping enumString="EKeyApplicationD" keyCode="63583" label="ApplicationD"/>
+    <mapping enumString="EKeyApplicationE" keyCode="63584" label="ApplicationE"/>
+    <mapping enumString="EKeyApplicationF" keyCode="63585" label="ApplicationF"/>
+    <mapping enumString="EKeyYes" keyCode="63586" label="Yes"/>
+    <mapping enumString="EKeyNo" keyCode="63587" label="No"/>
+    <mapping enumString="EKeyIncBrightness" keyCode="63588" label="IncBrightness"/>
+    <mapping enumString="EKeyDecBrightness" keyCode="63589" label="DecBrightness"/>
+    <mapping enumString="EKeyKeyboardExtend" keyCode="63590" label="KeyboardExtend"/>
+    <mapping enumString="EKeyDevice10" keyCode="63591" label="Device10"/>
+    <mapping enumString="EKeyDevice11" keyCode="63592" label="Device11"/>
+    <mapping enumString="EKeyDevice12" keyCode="63593" label="Device12"/>
+    <mapping enumString="EKeyDevice13" keyCode="63594" label="Device13"/>
+    <mapping enumString="EKeyDevice14" keyCode="63595" label="Device14"/>
+    <mapping enumString="EKeyDevice15" keyCode="63596" label="Device15"/>
+    <mapping enumString="EKeyDevice16" keyCode="63597" label="Device16"/>
+    <mapping enumString="EKeyDevice17" keyCode="63598" label="Device17"/>
+    <mapping enumString="EKeyDevice18" keyCode="63599" label="Device18"/>
+    <mapping enumString="EKeyDevice19" keyCode="63600" label="Device19"/>
+    <mapping enumString="EKeyDevice1A" keyCode="63601" label="Device1A"/>
+    <mapping enumString="EKeyDevice1B" keyCode="63602" label="Device1B"/>
+    <mapping enumString="EKeyDevice1C" keyCode="63603" label="Device1C"/>
+    <mapping enumString="EKeyDevice1D" keyCode="63604" label="Device1D"/>
+    <mapping enumString="EKeyDevice1E" keyCode="63605" label="Device1E"/>
+    <mapping enumString="EKeyDevice1F" keyCode="63606" label="Device1F"/>
+    <mapping enumString="EKeyApplication10" keyCode="63607" label="Application10"/>
+    <mapping enumString="EKeyApplication11" keyCode="63608" label="Application11"/>
+    <mapping enumString="EKeyApplication12" keyCode="63609" label="Application12"/>
+    <mapping enumString="EKeyApplication13" keyCode="63610" label="Application13"/>
+    <mapping enumString="EKeyApplication14" keyCode="63611" label="Application14"/>
+    <mapping enumString="EKeyApplication15" keyCode="63612" label="Application15"/>
+    <mapping enumString="EKeyApplication16" keyCode="63613" label="Application16"/>
+    <mapping enumString="EKeyApplication17" keyCode="63614" label="Application17"/>
+    <mapping enumString="EKeyApplication18" keyCode="63615" label="Application18"/>
+    <mapping enumString="EKeyApplication19" keyCode="63616" label="Application19"/>
+    <mapping enumString="EKeyApplication1A" keyCode="63617" label="Application1A"/>
+    <mapping enumString="EKeyApplication1B" keyCode="63618" label="Application1B"/>
+    <mapping enumString="EKeyApplication1C" keyCode="63619" label="Application1C"/>
+    <mapping enumString="EKeyApplication1D" keyCode="63620" label="Application1D"/>
+    <mapping enumString="EKeyApplication1E" keyCode="63621" label="Application1E"/>
+    <mapping enumString="EKeyApplication1F" keyCode="63622" label="Application1F"/>
+    <mapping enumString="EKeyDevice20" keyCode="63623" label="Device20"/>
+    <mapping enumString="EKeyDevice21" keyCode="63624" label="Device21"/>
+    <mapping enumString="EKeyDevice22" keyCode="63625" label="Device22"/>
+    <mapping enumString="EKeyDevice23" keyCode="63626" label="Device23"/>
+    <mapping enumString="EKeyDevice24" keyCode="63627" label="Device24"/>
+    <mapping enumString="EKeyDevice25" keyCode="63628" label="Device25"/>
+    <mapping enumString="EKeyDevice26" keyCode="63629" label="Device26"/>
+    <mapping enumString="EKeyDevice27" keyCode="63630" label="Device27"/>
+    <mapping enumString="EKeyApplication20" keyCode="63631" label="Application20"/>
+    <mapping enumString="EKeyApplication21" keyCode="63632" label="Application21"/>
+    <mapping enumString="EKeyApplication22" keyCode="63633" label="Application22"/>
+    <mapping enumString="EKeyApplication23" keyCode="63634" label="Application23"/>
+    <mapping enumString="EKeyApplication24" keyCode="63635" label="Application24"/>
+    <mapping enumString="EKeyApplication25" keyCode="63636" label="Application25"/>
+    <mapping enumString="EKeyApplication26" keyCode="63637" label="Application26"/>
+    <mapping enumString="EKeyApplication27" keyCode="63638" label="Application27"/>
+  </buttonEventProfile>
+  <buttonEventProfile profileId="UIQ">
+    <mapping enumString="EKeyNull" keyCode="0" label="NUL"/>
+    <mapping enumString="" keyCode="1" label="SOH"/>
+    <mapping enumString="" keyCode="2" label="STX"/>
+    <mapping enumString="" keyCode="3" label="ETX"/>
+    <mapping enumString="" keyCode="4" label="EOT"/>
+    <mapping enumString="" keyCode="5" label="ENQ"/>
+    <mapping enumString="" keyCode="6" label="ACK"/>
+    <mapping enumString="EKeyBell" keyCode="7" label="BEL"/>
+    <mapping enumString="EKeyBackspace" keyCode="8" label="Clear"/>
+    <mapping enumString="EKeyTab" keyCode="9" label="TAB"/>
+    <mapping enumString="EKeyLineFeed" keyCode="10" label="LF"/>
+    <mapping enumString="EKeyVerticalTab" keyCode="11" label="VT"/>
+    <mapping enumString="EKeyFormFeed" keyCode="12" label="FF"/>
+    <mapping enumString="EKeyEnter" keyCode="13" label="CR"/>
+    <mapping enumString="" keyCode="14" label="SO"/>
+    <mapping enumString="" keyCode="15" label="SI"/>
+    <mapping enumString="" keyCode="16" label="DLE"/>
+    <mapping enumString="" keyCode="17" label="DC1"/>
+    <mapping enumString="" keyCode="18" label="DC2"/>
+    <mapping enumString="" keyCode="19" label="DC3"/>
+    <mapping enumString="" keyCode="20" label="DC4"/>
+    <mapping enumString="" keyCode="21" label="NAK"/>
+    <mapping enumString="" keyCode="22" label="SYN"/>
+    <mapping enumString="" keyCode="23" label="ETB"/>
+    <mapping enumString="" keyCode="24" label="CAN"/>
+    <mapping enumString="" keyCode="25" label="EM"/>
+    <mapping enumString="" keyCode="26" label="SUB"/>
+    <mapping enumString="EKeyEscape" keyCode="27" label="Cancel"/>
+    <mapping enumString="" keyCode="28" label="FS"/>
+    <mapping enumString="" keyCode="29" label="GS"/>
+    <mapping enumString="" keyCode="30" label="RS"/>
+    <mapping enumString="" keyCode="31" label="US"/>
+    <mapping enumString="EKeySpace" keyCode="32" label="Space"/>
+    <mapping enumString="" keyCode="33" label="!"/>
+    <mapping enumString="" keyCode="34" label="&quot;"/>
+    <mapping enumString="" keyCode="35" label="#"/>
+    <mapping enumString="" keyCode="36" label="$"/>
+    <mapping enumString="" keyCode="37" label="%"/>
+    <mapping enumString="" keyCode="38" label="&amp;"/>
+    <mapping enumString="" keyCode="39" label="'"/>
+    <mapping enumString="" keyCode="40" label="("/>
+    <mapping enumString="" keyCode="41" label=")"/>
+    <mapping enumString="" keyCode="42" label="*"/>
+    <mapping enumString="" keyCode="43" label="+"/>
+    <mapping enumString="" keyCode="44" label=","/>
+    <mapping enumString="" keyCode="45" label="-"/>
+    <mapping enumString="" keyCode="46" label="."/>
+    <mapping enumString="" keyCode="47" label="/"/>
+    <mapping enumString="" keyCode="48" label="0"/>
+    <mapping enumString="" keyCode="49" label="1"/>
+    <mapping enumString="" keyCode="50" label="2"/>
+    <mapping enumString="" keyCode="51" label="3"/>
+    <mapping enumString="" keyCode="52" label="4"/>
+    <mapping enumString="" keyCode="53" label="5"/>
+    <mapping enumString="" keyCode="54" label="6"/>
+    <mapping enumString="" keyCode="55" label="7"/>
+    <mapping enumString="" keyCode="56" label="8"/>
+    <mapping enumString="" keyCode="57" label="9"/>
+    <mapping enumString="" keyCode="58" label=":"/>
+    <mapping enumString="" keyCode="59" label=";"/>
+    <mapping enumString="" keyCode="60" label="&lt;"/>
+    <mapping enumString="" keyCode="61" label="="/>
+    <mapping enumString="" keyCode="62" label=">"/>
+    <mapping enumString="" keyCode="63" label="?"/>
+    <mapping enumString="" keyCode="64" label="@"/>
+    <mapping enumString="" keyCode="65" label="A"/>
+    <mapping enumString="" keyCode="66" label="B"/>
+    <mapping enumString="" keyCode="67" label="C"/>
+    <mapping enumString="" keyCode="68" label="D"/>
+    <mapping enumString="" keyCode="69" label="E"/>
+    <mapping enumString="" keyCode="70" label="F"/>
+    <mapping enumString="" keyCode="71" label="G"/>
+    <mapping enumString="" keyCode="72" label="H"/>
+    <mapping enumString="" keyCode="73" label="I"/>
+    <mapping enumString="" keyCode="74" label="J"/>
+    <mapping enumString="" keyCode="75" label="K"/>
+    <mapping enumString="" keyCode="76" label="L"/>
+    <mapping enumString="" keyCode="77" label="M"/>
+    <mapping enumString="" keyCode="78" label="N"/>
+    <mapping enumString="" keyCode="79" label="O"/>
+    <mapping enumString="" keyCode="80" label="P"/>
+    <mapping enumString="" keyCode="81" label="Q"/>
+    <mapping enumString="" keyCode="82" label="R"/>
+    <mapping enumString="" keyCode="83" label="S"/>
+    <mapping enumString="" keyCode="84" label="T"/>
+    <mapping enumString="" keyCode="85" label="U"/>
+    <mapping enumString="" keyCode="86" label="V"/>
+    <mapping enumString="" keyCode="87" label="W"/>
+    <mapping enumString="" keyCode="88" label="X"/>
+    <mapping enumString="" keyCode="89" label="Y"/>
+    <mapping enumString="" keyCode="90" label="Z"/>
+    <mapping enumString="" keyCode="91" label="["/>
+    <mapping enumString="" keyCode="92" label="\"/>
+    <mapping enumString="" keyCode="93" label="]"/>
+    <mapping enumString="" keyCode="94" label="^"/>
+    <mapping enumString="" keyCode="95" label="_"/>
+    <mapping enumString="" keyCode="96" label="`"/>
+    <mapping enumString="" keyCode="97" label="a"/>
+    <mapping enumString="" keyCode="98" label="b"/>
+    <mapping enumString="" keyCode="99" label="c"/>
+    <mapping enumString="" keyCode="100" label="d"/>
+    <mapping enumString="" keyCode="101" label="e"/>
+    <mapping enumString="" keyCode="102" label="f"/>
+    <mapping enumString="" keyCode="103" label="g"/>
+    <mapping enumString="" keyCode="104" label="h"/>
+    <mapping enumString="" keyCode="105" label="i"/>
+    <mapping enumString="" keyCode="106" label="j"/>
+    <mapping enumString="" keyCode="107" label="k"/>
+    <mapping enumString="" keyCode="108" label="l"/>
+    <mapping enumString="" keyCode="109" label="m"/>
+    <mapping enumString="" keyCode="110" label="n"/>
+    <mapping enumString="" keyCode="111" label="o"/>
+    <mapping enumString="" keyCode="112" label="p"/>
+    <mapping enumString="" keyCode="113" label="q"/>
+    <mapping enumString="" keyCode="114" label="r"/>
+    <mapping enumString="" keyCode="115" label="s"/>
+    <mapping enumString="" keyCode="116" label="t"/>
+    <mapping enumString="" keyCode="117" label="u"/>
+    <mapping enumString="" keyCode="118" label="v"/>
+    <mapping enumString="" keyCode="119" label="w"/>
+    <mapping enumString="" keyCode="120" label="x"/>
+    <mapping enumString="" keyCode="121" label="y"/>
+    <mapping enumString="" keyCode="122" label="z"/>
+    <mapping enumString="" keyCode="123" label="{"/>
+    <mapping enumString="" keyCode="124" label="|"/>
+    <mapping enumString="" keyCode="125" label="}"/>
+    <mapping enumString="" keyCode="126" label="~"/>
+    <mapping enumString="" keyCode="127" label="DEL"/>
+    <mapping enumString="EKeyPrintScreen" keyCode="63488" label="PrintScreen"/>
+    <mapping enumString="EKeyPause" keyCode="63489" label="Pause"/>
+    <mapping enumString="EKeyHome" keyCode="63490" label="Home"/>
+    <mapping enumString="EKeyEnd" keyCode="63491" label="End"/>
+    <mapping enumString="EKeyPageUp" keyCode="63492" label="PageUp"/>
+    <mapping enumString="EKeyPageDown" keyCode="63493" label="PageDown"/>
+    <mapping enumString="EKeyInsert" keyCode="63494" label="Insert"/>
+    <mapping enumString="EKeyLeftArrow" keyCode="63495" label="Left"/>
+    <mapping enumString="EKeyRightArrow" keyCode="63496" label="Right"/>
+    <mapping enumString="EKeyUpArrow" keyCode="63497" label="Up"/>
+    <mapping enumString="EKeyDownArrow" keyCode="63498" label="Down"/>
+    <mapping enumString="EKeyLeftShift" keyCode="63499" label="LeftShift"/>
+    <mapping enumString="EKeyRightShift" keyCode="63500" label="RightShift"/>
+    <mapping enumString="EKeyLeftAlt" keyCode="63501" label="LeftAlt"/>
+    <mapping enumString="EKeyRightAlt" keyCode="63502" label="RightAlt"/>
+    <mapping enumString="EKeyLeftCtrl" keyCode="63503" label="LeftCtrl"/>
+    <mapping enumString="EKeyRightCtrl" keyCode="63504" label="RightCtrl"/>
+    <mapping enumString="EKeyLeftFunc" keyCode="63505" label="LeftFunc"/>
+    <mapping enumString="EKeyRightFunc" keyCode="63506" label="RightFunc"/>
+    <mapping enumString="EKeyCapsLock" keyCode="63507" label="CapsLock"/>
+    <mapping enumString="EKeyNumLock" keyCode="63508" label="NumLock"/>
+    <mapping enumString="EKeyScrollLock" keyCode="63509" label="ScrollLock"/>
+    <mapping enumString="EKeyF1" keyCode="63510" label="F1"/>
+    <mapping enumString="EKeyF2" keyCode="63511" label="F2"/>
+    <mapping enumString="EKeyF3" keyCode="63512" label="F3"/>
+    <mapping enumString="EKeyF4" keyCode="63513" label="F4"/>
+    <mapping enumString="EKeyF5" keyCode="63514" label="F5"/>
+    <mapping enumString="EKeyF6" keyCode="63515" label="F6"/>
+    <mapping enumString="EKeyF7" keyCode="63516" label="F7"/>
+    <mapping enumString="EKeyF8" keyCode="63517" label="F8"/>
+    <mapping enumString="EKeyF9" keyCode="63518" label="F9"/>
+    <mapping enumString="EKeyF10" keyCode="63519" label="F10"/>
+    <mapping enumString="EKeyF11" keyCode="63520" label="F11"/>
+    <mapping enumString="EKeyF12" keyCode="63521" label="F12"/>
+    <mapping enumString="EKeyF13" keyCode="63522" label="F13"/>
+    <mapping enumString="EKeyF14" keyCode="63523" label="F14"/>
+    <mapping enumString="EKeyF15" keyCode="63524" label="F15"/>
+    <mapping enumString="EKeyF16" keyCode="63525" label="F16"/>
+    <mapping enumString="EKeyF17" keyCode="63526" label="F17"/>
+    <mapping enumString="EKeyF18" keyCode="63527" label="F18"/>
+    <mapping enumString="EKeyF19" keyCode="63528" label="GameA"/>
+    <mapping enumString="EKeyF20" keyCode="63529" label="GameB"/>
+    <mapping enumString="EKeyF21" keyCode="63530" label="F21"/>
+    <mapping enumString="EKeyF22" keyCode="63531" label="F22"/>
+    <mapping enumString="EKeyF23" keyCode="63532" label="F23"/>
+    <mapping enumString="EKeyF24" keyCode="63533" label="F24"/>
+    <mapping enumString="EKeyOff" keyCode="63534" label="Power"/>
+    <mapping enumString="EKeyIncContrast" keyCode="63535" label="IncContrast"/>
+    <mapping enumString="EKeyDecContrast" keyCode="63536" label="DecContrast"/>
+    <mapping enumString="EKeyBacklightOn" keyCode="63537" label="BacklightOn"/>
+    <mapping enumString="EKeyBacklightOff" keyCode="63538" label="BacklightOff"/>
+    <mapping enumString="EKeyBacklightToggle" keyCode="63539" label="BacklightToggle"/>
+    <mapping enumString="EKeySliderDown" keyCode="63540" label="SliderDown"/>
+    <mapping enumString="EKeySliderUp" keyCode="63541" label="SliderUp"/>
+    <mapping enumString="EKeyMenu" keyCode="63542" label="Menu"/>
+    <mapping enumString="EKeyDictaphonePlay" keyCode="63543" label="DictaphonePlay"/>
+    <mapping enumString="EKeyDictaphoneStop" keyCode="63544" label="DictaphoneStop"/>
+    <mapping enumString="EKeyDictaphoneRecord" keyCode="63545" label="DictaphoneRecord"/>
+    <mapping enumString="EKeyHelp" keyCode="63546" label="Help"/>
+    <mapping enumString="EKeyDial" keyCode="63547" label="Dial"/>
+    <mapping enumString="EKeyScreenDimension0" keyCode="63548" label="ScreenDimension0"/>
+    <mapping enumString="EKeyScreenDimension1" keyCode="63549" label="ScreenDimension1"/>
+    <mapping enumString="EKeyScreenDimension2" keyCode="63550" label="ScreenDimension2"/>
+    <mapping enumString="EKeyScreenDimension3" keyCode="63551" label="ScreenDimension3"/>
+    <mapping enumString="EKeyIncVolume" keyCode="63552" label="IncVolume"/>
+    <mapping enumString="EKeyDecVolume" keyCode="63553" label="DecVolume"/>
+    <mapping enumString="EKeyDevice0" keyCode="63554" label="Device0"/>
+    <mapping enumString="EKeyDevice1" keyCode="63555" label="TwoWayUp"/>
+    <mapping enumString="EKeyDevice2" keyCode="63556" label="TwoWayDown"/>
+    <mapping enumString="EKeyDevice3" keyCode="63557" label="Device3"/>
+    <mapping enumString="EKeyDevice4" keyCode="63558" label="FourWayUp"/>
+    <mapping enumString="EKeyDevice5" keyCode="63559" label="FourWayDown"/>
+    <mapping enumString="EKeyDevice6" keyCode="63560" label="FourWayLeft"/>
+    <mapping enumString="EKeyDevice7" keyCode="63561" label="FourWayRight"/>
+    <mapping enumString="EKeyDevice8" keyCode="63562" label="Action"/>
+    <mapping enumString="EKeyDevice9" keyCode="63563" label="EightWayUpLeft"/>
+    <mapping enumString="EKeyDeviceA" keyCode="63564" label="EightWayUpRight"/>
+    <mapping enumString="EKeyDeviceB" keyCode="63565" label="EightWayDownLeft"/>
+    <mapping enumString="EKeyDeviceC" keyCode="63566" label="EightWayDownRight"/>
+    <mapping enumString="EKeyDeviceD" keyCode="63567" label="Lock"/>
+    <mapping enumString="EKeyDeviceE" keyCode="63568" label="Done"/>
+    <mapping enumString="EKeyDeviceF" keyCode="63569" label="DeviceF"/>
+    <mapping enumString="EKeyApplication0" keyCode="63570" label="Launcher"/>
+    <mapping enumString="EKeyApplication1" keyCode="63571" label="HomeSecreen"/>
+    <mapping enumString="EKeyApplication2" keyCode="63572" label="Browser"/>
+    <mapping enumString="EKeyApplication3" keyCode="63573" label="VideoCall"/>
+    <mapping enumString="EKeyApplication4" keyCode="63574" label="Application4"/>
+    <mapping enumString="EKeyApplication5" keyCode="63575" label="Multimedia"/>
+    <mapping enumString="EKeyApplication6" keyCode="63576" label="Application6"/>
+    <mapping enumString="EKeyApplication7" keyCode="63577" label="Application7"/>
+    <mapping enumString="EKeyApplication8" keyCode="63578" label="Application8"/>
+    <mapping enumString="EKeyApplication9" keyCode="63579" label="Application9"/>
+    <mapping enumString="EKeyApplicationA" keyCode="63580" label="ApplicationA"/>
+    <mapping enumString="EKeyApplicationB" keyCode="63581" label="ApplicationB"/>
+    <mapping enumString="EKeyApplicationC" keyCode="63582" label="ApplicationC"/>
+    <mapping enumString="EKeyApplicationD" keyCode="63583" label="ApplicationD"/>
+    <mapping enumString="EKeyApplicationE" keyCode="63584" label="ApplicationE"/>
+    <mapping enumString="EKeyApplicationF" keyCode="63585" label="ApplicationF"/>
+    <mapping enumString="EKeyYes" keyCode="63586" label="Yes"/>
+    <mapping enumString="EKeyNo" keyCode="63587" label="No"/>
+    <mapping enumString="EKeyIncBrightness" keyCode="63588" label="IncBrightness"/>
+    <mapping enumString="EKeyDecBrightness" keyCode="63589" label="DecBrightness"/>
+    <mapping enumString="EKeyKeyboardExtend" keyCode="63590" label="KeyboardExtend"/>
+    <mapping enumString="EKeyDevice10" keyCode="63591" label="Device10"/>
+    <mapping enumString="EKeyDevice11" keyCode="63592" label="Device11"/>
+    <mapping enumString="EKeyDevice12" keyCode="63593" label="Device12"/>
+    <mapping enumString="EKeyDevice13" keyCode="63594" label="Softkey1"/>
+    <mapping enumString="EKeyDevice14" keyCode="63595" label="Softkey2"/>
+    <mapping enumString="EKeyDevice15" keyCode="63596" label="Softkey3"/>
+    <mapping enumString="EKeyDevice16" keyCode="63597" label="Softkey4"/>
+    <mapping enumString="EKeyDevice17" keyCode="63598" label="CameraFocusLock"/>
+    <mapping enumString="EKeyDevice18" keyCode="63599" label="CameraShutter"/>
+    <mapping enumString="EKeyDevice19" keyCode="63600" label="Device19"/>
+    <mapping enumString="EKeyDevice1A" keyCode="63601" label="Device1A"/>
+    <mapping enumString="EKeyDevice1B" keyCode="63602" label="Device1B"/>
+    <mapping enumString="EKeyDevice1C" keyCode="63603" label="Device1C"/>
+    <mapping enumString="EKeyDevice1D" keyCode="63604" label="Device1D"/>
+    <mapping enumString="EKeyDevice1E" keyCode="63605" label="Device1E"/>
+    <mapping enumString="EKeyDevice1F" keyCode="63606" label="Device1F"/>
+    <mapping enumString="EKeyApplication10" keyCode="63607" label="Application10"/>
+    <mapping enumString="EKeyApplication11" keyCode="63608" label="Application11"/>
+    <mapping enumString="EKeyApplication12" keyCode="63609" label="Application12"/>
+    <mapping enumString="EKeyApplication13" keyCode="63610" label="Application13"/>
+    <mapping enumString="EKeyApplication14" keyCode="63611" label="Application14"/>
+    <mapping enumString="EKeyApplication15" keyCode="63612" label="Application15"/>
+    <mapping enumString="EKeyApplication16" keyCode="63613" label="Application16"/>
+    <mapping enumString="EKeyApplication17" keyCode="63614" label="Application17"/>
+    <mapping enumString="EKeyApplication18" keyCode="63615" label="Application18"/>
+    <mapping enumString="EKeyApplication19" keyCode="63616" label="Application19"/>
+    <mapping enumString="EKeyApplication1A" keyCode="63617" label="Application1A"/>
+    <mapping enumString="EKeyApplication1B" keyCode="63618" label="Application1B"/>
+    <mapping enumString="EKeyApplication1C" keyCode="63619" label="Application1C"/>
+    <mapping enumString="EKeyApplication1D" keyCode="63620" label="Application1D"/>
+    <mapping enumString="EKeyApplication1E" keyCode="63621" label="Application1E"/>
+    <mapping enumString="EKeyApplication1F" keyCode="63622" label="Application1F"/>
+    <mapping enumString="EKeyDevice20" keyCode="63623" label="Device20"/>
+    <mapping enumString="EKeyDevice21" keyCode="63624" label="Device21"/>
+    <mapping enumString="EKeyDevice22" keyCode="63625" label="Device22"/>
+    <mapping enumString="EKeyDevice23" keyCode="63626" label="Device23"/>
+    <mapping enumString="EKeyDevice24" keyCode="63627" label="Device24"/>
+    <mapping enumString="EKeyDevice25" keyCode="63628" label="Device25"/>
+    <mapping enumString="EKeyDevice26" keyCode="63629" label="Device26"/>
+    <mapping enumString="EKeyDevice27" keyCode="63630" label="Device27"/>
+    <mapping enumString="EKeyApplication20" keyCode="63631" label="Application20"/>
+    <mapping enumString="EKeyApplication21" keyCode="63632" label="Application21"/>
+    <mapping enumString="EKeyApplication22" keyCode="63633" label="Application22"/>
+    <mapping enumString="EKeyApplication23" keyCode="63634" label="Application23"/>
+    <mapping enumString="EKeyApplication24" keyCode="63635" label="Application24"/>
+    <mapping enumString="EKeyApplication25" keyCode="63636" label="Application25"/>
+    <mapping enumString="EKeyApplication26" keyCode="63637" label="Application26"/>
+    <mapping enumString="EKeyApplication27" keyCode="63638" label="Application27"/>
+  </buttonEventProfile>
+  <buttonEventProfile profileId="PI pre-2.0">
+    <mapping enumString="EKeyNull" keyCode="0" label="NUL"/>
+    <mapping enumString="" keyCode="1" label="SOH"/>
+    <mapping enumString="" keyCode="2" label="STX"/>
+    <mapping enumString="" keyCode="3" label="ETX"/>
+    <mapping enumString="" keyCode="4" label="EOT"/>
+    <mapping enumString="" keyCode="5" label="ENQ"/>
+    <mapping enumString="" keyCode="6" label="ACK"/>
+    <mapping enumString="EKeyBell" keyCode="7" label="BEL"/>
+    <mapping enumString="EKeyBackspace" keyCode="8" label="Cancel"/>
+    <mapping enumString="EKeyTab" keyCode="9" label="Tab"/>
+    <mapping enumString="EKeyLineFeed" keyCode="10" label="LF"/>
+    <mapping enumString="EKeyVerticalTab" keyCode="11" label="VT"/>
+    <mapping enumString="EKeyFormFeed" keyCode="12" label="FF"/>
+    <mapping enumString="EKeyEnter" keyCode="13" label="Enter"/>
+    <mapping enumString="" keyCode="14" label="SO"/>
+    <mapping enumString="" keyCode="15" label="SI"/>
+    <mapping enumString="" keyCode="16" label="DLE"/>
+    <mapping enumString="" keyCode="17" label="DC1"/>
+    <mapping enumString="" keyCode="18" label="DC2"/>
+    <mapping enumString="" keyCode="19" label="DC3"/>
+    <mapping enumString="" keyCode="20" label="DC4"/>
+    <mapping enumString="" keyCode="21" label="NAK"/>
+    <mapping enumString="" keyCode="22" label="SYN"/>
+    <mapping enumString="" keyCode="23" label="ETB"/>
+    <mapping enumString="" keyCode="24" label="CAN"/>
+    <mapping enumString="" keyCode="25" label="EM"/>
+    <mapping enumString="" keyCode="26" label="SUB"/>
+    <mapping enumString="EKeyEscape" keyCode="27" label="ESC"/>
+    <mapping enumString="" keyCode="28" label="FS"/>
+    <mapping enumString="" keyCode="29" label="GS"/>
+    <mapping enumString="" keyCode="30" label="RS"/>
+    <mapping enumString="" keyCode="31" label="US"/>
+    <mapping enumString="EKeySpace" keyCode="32" label="Space"/>
+    <mapping enumString="" keyCode="33" label="!"/>
+    <mapping enumString="" keyCode="34" label="&quot;"/>
+    <mapping enumString="" keyCode="35" label="#"/>
+    <mapping enumString="" keyCode="36" label="$"/>
+    <mapping enumString="" keyCode="37" label="%"/>
+    <mapping enumString="" keyCode="38" label="&amp;"/>
+    <mapping enumString="" keyCode="39" label="'"/>
+    <mapping enumString="" keyCode="40" label="("/>
+    <mapping enumString="" keyCode="41" label=")"/>
+    <mapping enumString="" keyCode="42" label="*"/>
+    <mapping enumString="" keyCode="43" label="+"/>
+    <mapping enumString="" keyCode="44" label=","/>
+    <mapping enumString="" keyCode="45" label="-"/>
+    <mapping enumString="" keyCode="46" label="."/>
+    <mapping enumString="" keyCode="47" label="/"/>
+    <mapping enumString="" keyCode="48" label="0"/>
+    <mapping enumString="" keyCode="49" label="1"/>
+    <mapping enumString="" keyCode="50" label="2"/>
+    <mapping enumString="" keyCode="51" label="3"/>
+    <mapping enumString="" keyCode="52" label="4"/>
+    <mapping enumString="" keyCode="53" label="5"/>
+    <mapping enumString="" keyCode="54" label="6"/>
+    <mapping enumString="" keyCode="55" label="7"/>
+    <mapping enumString="" keyCode="56" label="8"/>
+    <mapping enumString="" keyCode="57" label="9"/>
+    <mapping enumString="" keyCode="58" label=":"/>
+    <mapping enumString="" keyCode="59" label=";"/>
+    <mapping enumString="" keyCode="60" label="&lt;"/>
+    <mapping enumString="" keyCode="61" label="="/>
+    <mapping enumString="" keyCode="62" label=">"/>
+    <mapping enumString="" keyCode="63" label="?"/>
+    <mapping enumString="" keyCode="64" label="@"/>
+    <mapping enumString="" keyCode="65" label="A"/>
+    <mapping enumString="" keyCode="66" label="B"/>
+    <mapping enumString="" keyCode="67" label="C"/>
+    <mapping enumString="" keyCode="68" label="D"/>
+    <mapping enumString="" keyCode="69" label="E"/>
+    <mapping enumString="" keyCode="70" label="F"/>
+    <mapping enumString="" keyCode="71" label="G"/>
+    <mapping enumString="" keyCode="72" label="H"/>
+    <mapping enumString="" keyCode="73" label="I"/>
+    <mapping enumString="" keyCode="74" label="J"/>
+    <mapping enumString="" keyCode="75" label="K"/>
+    <mapping enumString="" keyCode="76" label="L"/>
+    <mapping enumString="" keyCode="77" label="M"/>
+    <mapping enumString="" keyCode="78" label="N"/>
+    <mapping enumString="" keyCode="79" label="O"/>
+    <mapping enumString="" keyCode="80" label="P"/>
+    <mapping enumString="" keyCode="81" label="Q"/>
+    <mapping enumString="" keyCode="82" label="R"/>
+    <mapping enumString="" keyCode="83" label="S"/>
+    <mapping enumString="" keyCode="84" label="T"/>
+    <mapping enumString="" keyCode="85" label="U"/>
+    <mapping enumString="" keyCode="86" label="V"/>
+    <mapping enumString="" keyCode="87" label="W"/>
+    <mapping enumString="" keyCode="88" label="X"/>
+    <mapping enumString="" keyCode="89" label="Y"/>
+    <mapping enumString="" keyCode="90" label="Z"/>
+    <mapping enumString="" keyCode="91" label="["/>
+    <mapping enumString="" keyCode="92" label="\"/>
+    <mapping enumString="" keyCode="93" label="]"/>
+    <mapping enumString="" keyCode="94" label="^"/>
+    <mapping enumString="" keyCode="95" label="_"/>
+    <mapping enumString="" keyCode="96" label="`"/>
+    <mapping enumString="" keyCode="97" label="a"/>
+    <mapping enumString="" keyCode="98" label="b"/>
+    <mapping enumString="" keyCode="99" label="c"/>
+    <mapping enumString="" keyCode="100" label="d"/>
+    <mapping enumString="" keyCode="101" label="e"/>
+    <mapping enumString="" keyCode="102" label="f"/>
+    <mapping enumString="" keyCode="103" label="g"/>
+    <mapping enumString="" keyCode="104" label="h"/>
+    <mapping enumString="" keyCode="105" label="i"/>
+    <mapping enumString="" keyCode="106" label="j"/>
+    <mapping enumString="" keyCode="107" label="k"/>
+    <mapping enumString="" keyCode="108" label="l"/>
+    <mapping enumString="" keyCode="109" label="m"/>
+    <mapping enumString="" keyCode="110" label="n"/>
+    <mapping enumString="" keyCode="111" label="o"/>
+    <mapping enumString="" keyCode="112" label="p"/>
+    <mapping enumString="" keyCode="113" label="q"/>
+    <mapping enumString="" keyCode="114" label="r"/>
+    <mapping enumString="" keyCode="115" label="s"/>
+    <mapping enumString="" keyCode="116" label="t"/>
+    <mapping enumString="" keyCode="117" label="u"/>
+    <mapping enumString="" keyCode="118" label="v"/>
+    <mapping enumString="" keyCode="119" label="w"/>
+    <mapping enumString="" keyCode="120" label="x"/>
+    <mapping enumString="" keyCode="121" label="y"/>
+    <mapping enumString="" keyCode="122" label="z"/>
+    <mapping enumString="" keyCode="123" label="{"/>
+    <mapping enumString="" keyCode="124" label="|"/>
+    <mapping enumString="" keyCode="125" label="}"/>
+    <mapping enumString="" keyCode="126" label="~"/>
+    <mapping enumString="" keyCode="127" label="DEL"/>
+    <mapping enumString="EKeyLeftArrow" keyCode="63495" label="Left"/>
+    <mapping enumString="EKeyRightArrow" keyCode="63496" label="Right"/>
+    <mapping enumString="EKeyUpArrow" keyCode="63497" label="Up"/>
+    <mapping enumString="EKeyDownArrow" keyCode="63498" label="Down"/>
+    <mapping enumString="EKeyLeftShift" keyCode="63499" label="Pencil"/>
+    <mapping enumString="EKeyDevice0" keyCode="63554" label="LSK"/>
+    <mapping enumString="EKeyDevice1" keyCode="63555" label="RSK"/>
+    <mapping enumString="EKeyDevice3" keyCode="63557" label="Rocker"/>
+    <mapping enumString="EKeyApplication0" keyCode="63570" label="Application"/>
+    <mapping enumString="EKeyYes" keyCode="63586" label="Call"/>
+    <mapping enumString="EKeyNo" keyCode="63587" label="Terminate"/>
+  </buttonEventProfile>
+</buttonEventProfileList>
\ No newline at end of file
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/icons/PI_Meter_16x16.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/icons/PI_Meter_20x20.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/plugin.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,4 @@
+
+#Keywords for PI preferences
+piPreference.common=carbide symbian c cpp cplusplus
+piPreference.keyButtons=key press trace profile map mapping tkeycode copy
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+   <extension
+         point="com.nokia.carbide.cpp.pi.piPluginData">
+      <plugin pluginClass="com.nokia.carbide.cpp.pi.button.ButtonReturnPlugin"/>
+   </extension>
+	<extension
+       point="org.eclipse.ui.preferencePages">
+		<page
+            name="Performance Investigator"
+            category="com.nokia.carbide.cpp.project.ui.preferences.CarbidePreferencePage"
+            class="com.nokia.carbide.cpp.internal.pi.button.ui.ButtonPreferencePage"
+            id="com.nokia.carbide.cpp.pi.button.ui.ButtonPreferencePage">
+     <keywordReference
+           id="com.nokia.carbide.pi.common">
+     </keywordReference>
+     <keywordReference
+           id="com.nokia.carbide.pi.keybuttons">
+     </keywordReference>
+		</page>
+	</extension>
+ <extension
+       point="org.eclipse.ui.importWizards">
+       <wizard
+            category="com.nokia.carbide.cpp.importWizards.pi"
+            class="com.nokia.carbide.cpp.internal.pi.button.ui.ImportBupMapWizard"
+            icon="icons/PI_Meter_16x16.png"
+            id="com.nokia.carbide.cpp.pi.button.ui.ImportBupMapWizard"
+            name="Performance Investigator Key Press Profile">
+         <description>
+            Import Carbide.c++ Profiler Key Press Profile.
+         </description>
+      </wizard>
+ </extension>
+ <extension
+       point="org.eclipse.ui.exportWizards">
+       <wizard
+            category="com.nokia.carbide.cpp.exportWizards.pi"
+            class="com.nokia.carbide.cpp.internal.pi.button.ui.ExportBupMapWizard"
+            icon="icons/PI_Meter_16x16.png"
+            id="com.nokia.carbide.cpp.pi.button.ui.ExportBupMapWizard"
+            name="Performance Investigator Key Press Profile">
+         <description>
+            Export Carbide.c++ Profiler Key Press Profile.
+         </description>
+      </wizard>
+ </extension>
+ <extension
+       point="org.eclipse.ui.popupMenus">
+		<objectContribution
+        adaptable="true"
+        id="com.nokia.carbide.cpp.pi.button.BupMapSwitchAction"
+        nameFilter="*.npi"
+        objectClass="org.eclipse.core.resources.IResource">
+			<action
+				class="com.nokia.carbide.cpp.pi.button.BupMapSwitchAction"
+				definitionId="com.nokia.carbide.cpp.pi.button.BupMapSwitchAction"
+				enablesFor="1"
+				icon="icons/PI_Meter_16x16.png"
+				id="com.nokia.carbide.cpp.pi.button.BupMapSwitchAction"
+				label="Switch Key Press Profile"
+				menubarPath="buildGroup">
+			</action>
+		</objectContribution>
+ </extension>
+ <extension
+       point="org.eclipse.ui.keywords">
+    <keyword
+          id="com.nokia.carbide.pi.common"
+          label="%piPreference.common">
+    </keyword>
+    <keyword
+          id="com.nokia.carbide.pi.keybuttons"
+          label="%piPreference.keyButtons">
+    </keyword>
+ </extension>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupMapAddDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+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.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.pi.button.ComNokiaCarbidePiButtonHelpIDs;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+public class BupMapAddDialog extends TrayDialog {
+
+	private int			oldEventKeyCode;
+	private String		oldEventEnumString;
+	private String		oldEventLabel;
+	private int			eventKeyCode;
+	private String		eventEnumString;
+	private String		eventLabel;
+	private ModifyCachedBupEventMap map;
+	
+	// control
+	private Composite composite = null;
+	private Composite labelAndValueComposite = null;
+	
+	private Label keyCodeLabel = null;
+	private Text keyCodeValueText = null;
+	
+	private Label enumLabel = null;
+	private Text enumValueText = null;
+	
+	private Label labelLabel = null;
+	private Text labelText = null;
+	
+	private Label messageLabel = null;
+	
+	private Label hexNeeds0x = null;
+	
+	public BupMapAddDialog(Shell shell, ModifyCachedBupEventMap cachedMap, int keyCode, String enumString, String label) {
+		super(shell);
+		
+		// store original values
+		oldEventKeyCode = eventKeyCode = keyCode;
+		oldEventEnumString = eventEnumString = enumString;
+		oldEventLabel = eventLabel = label;
+		map = cachedMap;
+	}
+	
+	public Control createDialogArea(Composite parent) {
+		getShell().setText(Messages.getString("BupMapAddDialog.addMapping"));  //$NON-NLS-1$
+		
+		composite = new Composite(parent, SWT.NONE);
+		GridDataFactory.fillDefaults().applyTo(composite);
+		GridLayoutFactory.fillDefaults().margins(5, 5).applyTo(composite);
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ComNokiaCarbidePiButtonHelpIDs.PI_BUTTON_ADD_DIALOG);
+
+		labelAndValueComposite = new Composite(composite, SWT.NONE);
+		GridDataFactory.fillDefaults().applyTo(labelAndValueComposite);
+		GridLayoutFactory.fillDefaults().numColumns(2).applyTo(labelAndValueComposite);
+		
+		messageLabel = new Label(composite, SWT.NONE);
+		GridDataFactory.fillDefaults().indent(15,0).grab(true, true).hint(200, 15).applyTo(messageLabel);
+		messageLabel.setFont(PIPageEditor.helvetica_9);
+		
+		hexNeeds0x = new Label(composite, SWT.NONE);
+		GridDataFactory.fillDefaults().indent(15,0).grab(true, true).hint(200, 15).applyTo(hexNeeds0x);
+		hexNeeds0x.setText(Messages.getString("BupMapAddDialog.startHexWith0x")); //$NON-NLS-1$
+		hexNeeds0x.setFont(PIPageEditor.helvetica_9);
+		
+		keyCodeLabel = new Label(labelAndValueComposite, SWT.NONE);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(keyCodeLabel);
+		keyCodeLabel.setFont(PIPageEditor.helvetica_9);
+		keyCodeLabel.setText(Messages.getString("BupMapAddDialog.value")); //$NON-NLS-1$
+		
+		keyCodeValueText = new Text(labelAndValueComposite, SWT.BORDER);
+		GridDataFactory.fillDefaults().grab(true, true).hint(200, 15).applyTo(keyCodeValueText);
+		keyCodeValueText.setFont(PIPageEditor.helvetica_9);
+		keyCodeValueText.setText(""); //$NON-NLS-1$
+		// add the listener(s)
+		keyCodeValueText.addModifyListener(new ModifyListener(){
+			public void modifyText(ModifyEvent arg0) {
+				validateKeyCode();
+			}
+		});
+		
+		enumLabel = new Label(labelAndValueComposite, SWT.NONE);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(enumLabel);
+		enumLabel.setFont(PIPageEditor.helvetica_9);
+		enumLabel.setText(Messages.getString("BupMapAddDialog.tKeyCode")); //$NON-NLS-1$
+		
+		enumValueText = new Text(labelAndValueComposite, SWT.BORDER);
+		enumValueText.setFont(PIPageEditor.helvetica_9);
+		GridDataFactory.fillDefaults().grab(true, true).hint(200, 15).applyTo(enumValueText);
+		// add the listener(s)
+		enumValueText.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				eventEnumString = enumValueText.getText();
+			}
+		});
+		enumValueText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				eventEnumString = enumValueText.getText();
+			}
+		});
+		enumValueText.setText(eventEnumString);
+		
+		labelLabel = new Label(labelAndValueComposite, SWT.NONE);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(labelLabel);
+		labelLabel.setFont(PIPageEditor.helvetica_9);
+		labelLabel.setText(Messages.getString("BupMapAddDialog.label")); //$NON-NLS-1$
+		
+		labelText = new Text(labelAndValueComposite, SWT.BORDER);
+		GridDataFactory.fillDefaults().grab(true, true).hint(200, 15).applyTo(labelText);
+		labelText.setFont(PIPageEditor.helvetica_9);
+		// add the listener(s)
+		labelText.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				eventLabel = labelText.getText();
+			}
+		});
+		labelText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				eventLabel = labelText.getText();
+			}
+		});
+		labelText.setText(eventLabel);
+				
+		return composite;
+	}
+	
+	/**
+	 * 
+	 */
+	protected void validateKeyCode() {
+		int keyCode = -1;
+		String message = ""; //$NON-NLS-1$
+		String keyCodeString = keyCodeValueText.getText();
+		messageLabel.setForeground(getShell().getDisplay().getSystemColor(SWT.COLOR_BLACK));
+		
+		if (keyCodeString.length() == 0)
+			message = " "; //$NON-NLS-1$
+		else {
+			try {
+				keyCode = Integer.parseInt(keyCodeString);
+			} catch (NumberFormatException e) {
+				try {
+					if (keyCodeString.startsWith("0x")) { //$NON-NLS-1$
+						keyCode = Integer.parseInt(keyCodeString.substring(2), 16);
+					} else {
+						Integer.parseInt(keyCodeString, 16);
+						message = Messages.getString("BupMapAddDialog.hexNeeds0x") + keyCodeValueText.getText(); //$NON-NLS-1$
+						messageLabel.setForeground(getShell().getDisplay().getSystemColor(SWT.COLOR_RED));
+					}
+				} catch (NumberFormatException e2) {
+					message = keyCodeValueText.getText() + Messages.getString("BupMapAddDialog.invalidNumber"); //$NON-NLS-1$
+					messageLabel.setForeground(getShell().getDisplay().getSystemColor(SWT.COLOR_RED));
+				}
+			}
+			if (keyCode >= 0) {
+				eventKeyCode = keyCode;
+				if (map.getKeyCodeSet().contains(keyCode)) {
+					message = keyCode + Messages.getString("BupMapAddDialog.existsInMap1") //$NON-NLS-1$
+							+ Integer.toHexString(keyCode) + Messages.getString("BupMapAddDialog.existsInMap2"); //$NON-NLS-1$
+					messageLabel.setForeground(getShell().getDisplay().getSystemColor(SWT.COLOR_RED));
+				}
+			}
+		}
+		messageLabel.setText(message);
+		messageLabel.setVisible(!message.equals("")); //$NON-NLS-1$
+		getButton(IDialogConstants.OK_ID).setEnabled(message.equals("")); //$NON-NLS-1$
+	}
+
+	public int getKeyCode() {
+		return eventKeyCode;
+	}
+	
+	public String getEnumString() {
+		if (eventEnumString == null) {
+			return ""; //$NON-NLS-1$
+		}
+		return eventEnumString;
+	}
+	
+	public String getLabel() {
+		if (eventLabel == null) {
+			return ""; //$NON-NLS-1$
+		}
+		return eventLabel;
+	}
+
+	protected void okPressed() {
+		super.okPressed();
+	}
+	
+	protected void cancelPressed() {
+		eventKeyCode = oldEventKeyCode;
+		eventEnumString = oldEventEnumString;
+		eventLabel = oldEventLabel;
+		super.cancelPressed();
+	}
+	
+	protected void createButtonsForButtonBar(Composite parent) {
+		super.createButtonsForButtonBar(parent);
+		// now buttons are there, we can  disable key
+		getButton(IDialogConstants.OK_ID).setEnabled(false);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupMapEditDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.pi.button.ComNokiaCarbidePiButtonHelpIDs;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+public class BupMapEditDialog extends TrayDialog {
+
+	private String		oldEventEnumString;
+	private String		oldEventLabel;
+	private int			eventKeyCode;
+	private String		eventEnumString;
+	private String		eventLabel;
+	
+	// control
+	private Composite composite = null;
+	private Composite labelAndValueComposite = null;
+	
+	private Label keyCodeLabel = null;
+	private Label keyCodeValueLabel = null;
+	
+	private Label enumLabel = null;
+	private Text enumValueText = null;
+	
+	private Label labelLabel = null;
+	private Text labelText = null;
+	
+	public BupMapEditDialog(Shell shell, int keyCode, String enumString, String label) {
+		super(shell);
+		
+		// store original values
+		eventKeyCode = keyCode;
+		oldEventEnumString = eventEnumString = enumString;
+		oldEventLabel = eventLabel = label;
+	}
+	
+	public Control createDialogArea(Composite parent) {
+		getShell().setText(Messages.getString("BupMapEditDialog.editMappingForKey") + "0x" + Integer.toHexString(eventKeyCode));  //$NON-NLS-1$ //$NON-NLS-2$
+		
+		composite = new Composite(parent, SWT.NONE);
+		GridDataFactory.fillDefaults().applyTo(composite);
+		GridLayoutFactory.fillDefaults().margins(5, 5).applyTo(composite);
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ComNokiaCarbidePiButtonHelpIDs.PI_BUTTON_EDIT_DIALOG);
+
+		labelAndValueComposite = new Composite(composite, SWT.NONE);
+		GridDataFactory.fillDefaults().applyTo(labelAndValueComposite);
+		GridLayoutFactory.fillDefaults().numColumns(2).applyTo(labelAndValueComposite);
+		
+		keyCodeLabel = new Label(labelAndValueComposite, SWT.NONE);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(keyCodeLabel);
+		keyCodeLabel.setFont(PIPageEditor.helvetica_9);
+		keyCodeLabel.setText(Messages.getString("BupMapEditDialog.hexValue")); //$NON-NLS-1$
+		
+		keyCodeValueLabel = new Label(labelAndValueComposite, SWT.NONE);
+		GridDataFactory.fillDefaults().grab(true, true).hint(200, 15).applyTo(keyCodeValueLabel);
+		keyCodeValueLabel.setFont(PIPageEditor.helvetica_9);
+		keyCodeValueLabel.setText("0x" + Integer.toHexString(eventKeyCode)); //$NON-NLS-1$
+		// add the listener(s)
+		
+		enumLabel = new Label(labelAndValueComposite, SWT.NONE);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(enumLabel);
+		enumLabel.setFont(PIPageEditor.helvetica_9);
+		enumLabel.setText(Messages.getString("BupMapEditDialog.tKeyCode")); //$NON-NLS-1$
+		
+		enumValueText = new Text(labelAndValueComposite, SWT.BORDER);
+		enumValueText.setFont(PIPageEditor.helvetica_9);
+		GridDataFactory.fillDefaults().grab(true, true).hint(200, 15).applyTo(enumValueText);
+		// add the listener(s)
+		enumValueText.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				eventEnumString = enumValueText.getText();
+			}
+		});
+		enumValueText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				eventEnumString = enumValueText.getText();
+			}
+		});
+		enumValueText.setText(eventEnumString);
+		
+		labelLabel = new Label(labelAndValueComposite, SWT.NONE);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(labelLabel);
+		labelLabel.setFont(PIPageEditor.helvetica_9);
+		labelLabel.setText(Messages.getString("BupMapEditDialog.label")); //$NON-NLS-1$
+		
+		labelText = new Text(labelAndValueComposite, SWT.BORDER);
+		GridDataFactory.fillDefaults().grab(true, true).hint(200, 15).applyTo(labelText);
+		labelText.setFont(PIPageEditor.helvetica_9);
+		// add the listener(s)
+		labelText.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				eventLabel = labelText.getText();
+			}
+		});
+		labelText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				eventLabel = labelText.getText();
+			}
+		});
+		labelText.setText(eventLabel);
+				
+		return composite;
+	}
+	
+	public String getEnumString() {
+		if (eventEnumString == null) {
+			return ""; //$NON-NLS-1$
+		}
+		return eventEnumString;
+	}
+	
+	public String getLabel() {
+		if (eventLabel == null) {
+			return ""; //$NON-NLS-1$
+		}
+		return eventLabel;
+	}
+
+	protected void okPressed() {
+		super.okPressed();
+	}
+	
+	protected void cancelPressed() {
+		eventEnumString = oldEventEnumString;
+		eventLabel = oldEventLabel;
+		super.cancelPressed();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupMapTableViewer.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.resource.FontRegistry;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+import com.nokia.carbide.cpp.pi.button.IBupEventMap;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapEditable;
+
+public class BupMapTableViewer extends TableViewer {
+	// Set the table column property names
+	private final String KEY_CODE_COLUMN 		= Messages.getString("BupMapTableViewer.keycode"); //$NON-NLS-1$
+	private final String ENUM_COLUMN 			= Messages.getString("BupMapTableViewer.enum"); //$NON-NLS-1$
+	private final String LABEL_COLUMN 			= Messages.getString("BupMapTableViewer.label"); //$NON-NLS-1$
+	private static final FontRegistry fontRegistry = new FontRegistry();
+	private static Font regularFont = fontRegistry.get(""); //$NON-NLS-1$
+	private static Font boldFont = fontRegistry.getBold(""); //$NON-NLS-1$
+	private TableColumn columnKeyCode;
+	private TableColumn columnEnum;
+	private TableColumn columnLabel;
+	
+	// Set column names
+	private String[] columnNames = new String[] { 
+			KEY_CODE_COLUMN, 
+			ENUM_COLUMN,
+			LABEL_COLUMN
+			};
+	
+	public class BupMapEntry {
+		public int keyCode;
+		public String enumString;
+		public String label;
+		public boolean modified;
+	}
+
+	private ArrayList<BupMapEntry> mapList = new ArrayList<BupMapEntry>();
+	private BupMapEntrySorter mapEntrySorter = new BupMapEntrySorter();
+	public BupMapTableViewer mapTableViewer = this;
+	boolean modifible = false;
+	
+	public class BupMapEntrySorter extends ViewerSorter {
+		// public constants indicating sorting type
+		public final static int SORT_BY_KEYCODE = 0;
+		public final static int SORT_BY_ENUM = 1;
+		public final static int SORT_BY_LABEL = 2;
+		
+		TableColumn columnCurrentSort = columnKeyCode;
+		int dirKeyCode = SWT.UP;
+		int dirEnum = SWT.UP;
+		int dirLabel = SWT.UP;
+		
+		public BupMapEntrySorter () {
+			super();
+		}
+		
+		// only sort by keyCode
+		public int compare(Viewer viewer, Object o1, Object o2) {
+			if (!(o1 instanceof BupMapEntry) ||
+					!(o2 instanceof BupMapEntry)) {
+				return 0;
+			}
+			
+			// ask table for sorting column criterion
+			TableColumn tableColumn = ((TableViewer)viewer).getTable().getSortColumn();
+			int result = 0;
+			if (tableColumn == columnKeyCode) {
+				result = new Integer(((BupMapEntry)o1).keyCode).compareTo(((BupMapEntry)o2).keyCode);
+				if (dirKeyCode != SWT.UP) {
+					result *= -1;
+				}
+			} else if (tableColumn == columnEnum) {
+				result = ((BupMapEntry)o1).enumString.compareTo(((BupMapEntry)o2).enumString);
+				if (dirEnum != SWT.UP) {
+					result *= -1;
+				}
+			}else if (tableColumn == columnLabel) {
+				result = ((BupMapEntry)o1).label.compareTo(((BupMapEntry)o2).label);
+				if (dirLabel != SWT.UP) {
+					result *= -1;
+				}
+			}
+
+			return result;
+		}
+
+		/**
+		 * @param currentSortColumn
+		 */
+		public void setSortCriteria(TableColumn columnNewSort) {
+
+			if (columnCurrentSort != columnNewSort) {
+				// update sorting column criterion to table
+				mapTableViewer.getTable().setSortColumn(columnNewSort);
+				columnCurrentSort = columnNewSort;
+			} else {
+				// update sorting order we keep locally, I wish there was getSortDirection(TableColumn)
+				if (columnNewSort == columnKeyCode) {
+					dirKeyCode = dirKeyCode == SWT.UP ? SWT.DOWN : SWT.UP;
+				} else if (columnNewSort == columnEnum) {
+					dirEnum = dirEnum == SWT.UP ? SWT.DOWN : SWT.UP;
+				}else if (columnNewSort == columnLabel) {
+					dirLabel = dirLabel == SWT.UP ? SWT.DOWN : SWT.UP;
+				}
+			}
+			if (columnNewSort == columnKeyCode) {
+				mapTableViewer.getTable().setSortDirection(dirKeyCode);
+			} else if (columnNewSort == columnEnum) {
+				mapTableViewer.getTable().setSortDirection(dirEnum);
+			}else if (columnNewSort == columnLabel) {
+				mapTableViewer.getTable().setSortDirection(dirLabel);
+			}
+		}
+		
+	}
+	
+	public class BupMapTableLabelProvider extends LabelProvider implements ITableLabelProvider, IFontProvider {
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
+		 */
+		public Image getColumnImage(Object arg0, int arg1) {
+			return null;
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
+		 */
+		public String getColumnText(Object element, int columnIndex) {
+			String result = ""; //$NON-NLS-1$
+			BupMapEntry mapEntry = (BupMapEntry) element;
+			
+			switch(columnIndex) {
+				case 0:
+					result = Integer.toHexString(mapEntry.keyCode);
+					break;
+				case 1:
+					result = mapEntry.enumString;
+					break;
+				case 2:
+					result = mapEntry.label;
+					break;
+			}
+			return result;
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.IFontProvider#getFont(java.lang.Object)
+		 */
+		public Font getFont(Object element) {
+			if (((BupMapEntry)element).modified) {
+				return boldFont;
+			}
+			return regularFont;
+		}
+	}
+
+	/**
+	 * @param parent
+	 */
+	public BupMapTableViewer(Composite parent, boolean modify) {
+		super(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | (modify ? SWT.FULL_SELECTION | SWT.SINGLE : SWT.NONE));
+		final int KEYCODE_WIDTH = 60;
+		final int ENUM_WIDTH = 150;
+		final int LABEL_WIDTH = 200;
+		
+		modifible = modify;
+		
+		setSorter(mapEntrySorter);
+		
+		SelectionListener columnSelectinListener = new SelectionListener () {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+		        // determine new sort column and direction
+		        TableColumn currentSortColumn = (TableColumn) arg0.widget;
+		        
+		        mapEntrySorter.setSortCriteria(currentSortColumn);
+		        
+		        // sort the data based on column and direction criteria, sort well pick that up from table
+		        mapTableViewer.getSorter().sort(mapTableViewer, mapList.toArray());
+		        mapTableViewer.setInput(mapList.toArray());
+		    }
+		};
+		
+		columnKeyCode = new TableColumn(getTable(), SWT.LEFT, 0);	
+		columnKeyCode.setText(Messages.getString("BupMapTableViewer.hex")); //$NON-NLS-1$
+		columnKeyCode.setWidth(60);
+		columnKeyCode.addSelectionListener (columnSelectinListener);
+
+		columnEnum = new TableColumn(getTable(), SWT.LEFT, 1);	
+		columnEnum.setText(Messages.getString("BupMapTableViewer.tKeyCode")); //$NON-NLS-1$
+		columnEnum.setWidth(150);
+		columnEnum.addSelectionListener (columnSelectinListener);
+		
+		columnLabel = new TableColumn(getTable(), SWT.LEFT, 2);	
+		columnLabel.setText(Messages.getString("BupMapTableViewer.Label")); //$NON-NLS-1$
+		columnLabel.setWidth(200);
+		columnLabel.addSelectionListener (columnSelectinListener);
+		
+		setColumnProperties(columnNames);
+
+		Table mappingTable = getTable();
+		// initial size, so scroll bar show up
+		GridDataFactory.fillDefaults().grab(true, true).hint(KEYCODE_WIDTH + ENUM_WIDTH + LABEL_WIDTH - 15, 200).applyTo(mappingTable);
+		mappingTable.setHeaderVisible(true);
+		mappingTable.setLinesVisible(true);
+		
+		setContentProvider(new ArrayContentProvider());
+		setLabelProvider(new BupMapTableLabelProvider());
+		
+		setInput(mapList.toArray(new BupMapEntry[mapList.size()]));
+	}
+	
+	public void loadMap(IBupEventMap map) {
+		mapList.clear();
+		Set<Integer> keyCodeSet = map.getKeyCodeSet();
+		BupMapEntry entry;
+		for (Integer keyCode : keyCodeSet) {
+			entry = new BupMapEntry();
+			entry.keyCode = keyCode.intValue();
+			entry.enumString = map.getEnum(keyCode);
+			entry.label = map.getLabel(keyCode);
+			if (map instanceof IBupEventMapEditable) {
+				entry.modified = ((IBupEventMapEditable)map).isModified(keyCode);
+			} else {
+				entry.modified = false;
+			}
+			mapList.add(entry);
+		}
+		setInput(mapList.toArray(new BupMapEntry[mapList.size()]));
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupPreferenceConstants.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+public class BupPreferenceConstants {
+
+	public static final String KEY_MAP_PROFILE_STRING = "KeyPressProfileString"; //$NON-NLS-1$
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupProfileDuplicateDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.resource.FontRegistry;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+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.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.pi.button.BupEventMapManager;
+import com.nokia.carbide.cpp.pi.button.ComNokiaCarbidePiButtonHelpIDs;
+import com.nokia.carbide.cpp.pi.button.IBupEventMap;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapProfile;
+
+public class BupProfileDuplicateDialog extends TrayDialog {
+	private static final FontRegistry fontRegistry = new FontRegistry();
+
+	private String profileId = null;
+	private IBupEventMapProfile excludeProfile = null;
+	private IBupEventMapProfile selectedProfileHint = null;
+	
+	// control
+	private Composite composite = null;
+	
+	private Label profileLabel = null;
+	private Text profileText = null;
+	private Label messageLabel = null;
+	private Label duplicateWithLabel = null;
+	private Combo profileCombo = null;
+	
+	public BupProfileDuplicateDialog(Shell shell, IBupEventMapProfile profile) {
+		super(shell);
+		selectedProfileHint = profile;
+	}
+	
+	public Control createDialogArea(Composite parent) {
+		getShell().setText(Messages.getString("BupProfileDuplicateDialog.duplicateProfile"));   //$NON-NLS-1$
+		
+		composite = new Composite(parent, SWT.NONE);
+		GridDataFactory.fillDefaults().applyTo(composite);
+		GridLayoutFactory.fillDefaults().margins(5, 5).applyTo(composite);
+		
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ComNokiaCarbidePiButtonHelpIDs.PI_PROFILE_ADD_DIALOG);
+		
+		profileLabel = new Label(composite, SWT.NONE);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(profileLabel);
+		profileLabel.setText(Messages.getString("BupProfileDuplicateDialog.enterNewNameHeading"));  //$NON-NLS-1$
+		
+		profileText = new Text(composite, SWT.BORDER);
+		GridDataFactory.fillDefaults().grab(true, true).hint(200, 15).applyTo(profileText);
+		
+		profileText.setText(""); //$NON-NLS-1$
+		profileText.addModifyListener(new ModifyListener(){
+			public void modifyText(ModifyEvent arg0) {
+				validateKeyCode();
+			}
+		});
+		
+		messageLabel = new Label(composite, SWT.NONE);
+		messageLabel.setFont(fontRegistry.getBold(""));	//$NON-NLS-1$
+		GridDataFactory.fillDefaults().grab(true, true).hint(350, 15).applyTo(messageLabel);
+		
+		duplicateWithLabel = new Label(composite, SWT.NONE);
+		duplicateWithLabel.setText(Messages.getString("BupProfileDuplicateDialog.duplicateWith"));  //$NON-NLS-1$
+		
+		profileCombo = new Combo(composite, SWT.READ_ONLY);
+		profileCombo.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent arg0) {
+				validateKeyCode();
+			}			
+		});
+
+
+		
+		ArrayList<IBupEventMapProfile> myList = new ArrayList<IBupEventMapProfile>();
+		ArrayList<IBupEventMapProfile> globalPrefProfile = BupEventMapManager.getInstance().getProfilesFromWorkspacePref();
+		myList.addAll(globalPrefProfile);
+		myList.addAll(BupEventMapManager.getInstance().getProfilesFromBuiltin());
+		
+		for (IBupEventMapProfile profile : myList) {
+			if (!profile.equals(excludeProfile)) {
+				profileCombo.add(profile.toString());
+				profileCombo.setData(profile.toString(), profile);
+			}
+		}
+		
+		for (int i = 0; i < profileCombo.getItemCount(); i++) {
+			if (selectedProfileHint.toString().equals(profileCombo.getItem(i))) {
+				profileCombo.select(i);		// select the item from tab page
+			}
+		}
+				
+		return composite;
+	}
+	
+	/**
+	 * 
+	 */
+	protected void validateKeyCode() {
+		Button buttonOK = getButton(IDialogConstants.OK_ID);
+		if (buttonOK == null)
+			return;
+		
+		String message = ""; //$NON-NLS-1$
+		if (profileCombo.getSelectionIndex() < 0) {
+			message = Messages.getString("BupProfileDuplicateDialog.selectProfileToDuplicate"); //$NON-NLS-1$
+			buttonOK.setEnabled(false);
+		}
+		if (message.equals("")) { //$NON-NLS-1$
+			profileId = profileText.getText();
+			buttonOK.setEnabled(true);
+			if (profileId.equals("")) { //$NON-NLS-1$
+				message = ""; //$NON-NLS-1$
+				buttonOK.setEnabled(false);
+			} else {
+				ArrayList<IBupEventMapProfile> workspacePrefs = BupEventMapManager.getInstance().getProfilesFromWorkspacePref();
+				for (IBupEventMapProfile pref : workspacePrefs) {
+					if (profileId.equals(pref.getProfileId())) {
+						message = Messages.getString("BupProfileDuplicateDialog.profileName") + profileId + Messages.getString("BupProfileDuplicateDialog.alreadyExists");   //$NON-NLS-1$ //$NON-NLS-2$
+						buttonOK.setEnabled(false);
+					}
+				}
+			}
+		}
+
+		messageLabel.setText(message);
+		messageLabel.setVisible(!message.equals("")); //$NON-NLS-1$
+		messageLabel.setForeground(messageLabel.getDisplay().getSystemColor(SWT.COLOR_RED));
+	}
+	
+	protected void createButtonsForButtonBar(Composite parent) {
+		super.createButtonsForButtonBar(parent);
+		// now buttons are there, we can  disable key
+		getButton(IDialogConstants.OK_ID).setEnabled(false);
+	}
+
+	protected Button createButton(Composite parent, int id, String label, boolean defaultButton) {
+		Button result = super.createButton(parent, id, label, defaultButton);
+		if (id == IDialogConstants.OK_ID) {
+			result.setText(Messages.getString("BupProfileDuplicateDialog.duplicate"));  //$NON-NLS-1$
+		}
+		return result;
+	}
+	
+	public void okPressed() {
+		BupEventMapManager.getInstance().addToWorkspace(profileId);
+		ArrayList<IBupEventMapProfile> profiles = BupEventMapManager.getInstance().getProfilesFromWorkspacePref();
+		IBupEventMapProfile newProfile = null;
+		for (IBupEventMapProfile profile : profiles) {
+			if (profileId.equals(profile.getProfileId())) {
+				newProfile = profile;
+				break;
+			}
+		}
+		if (newProfile != null) {
+			IBupEventMap newProfileMap = BupEventMapManager.getInstance().captureMap(newProfile);
+			ModifyCachedBupEventMap tempMapForWrite = new ModifyCachedBupEventMap(newProfileMap);
+			BupEventMapManager.getInstance().releaseMap(newProfileMap);
+			IBupEventMapProfile loadedProfile = (IBupEventMapProfile)profileCombo.getData(profileCombo.getItem(profileCombo.getSelectionIndex()));
+			IBupEventMap loadedMap = BupEventMapManager.getInstance().captureMap(loadedProfile);
+			tempMapForWrite.initializeFromMap(loadedMap);
+			BupEventMapManager.getInstance().releaseMap(loadedMap);
+			BupEventMapManager.getInstance().commitEditToWorkspace(tempMapForWrite);
+		}
+		super.okPressed();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupProfileEditDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import java.util.Set;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.pi.button.BupEventMapManager;
+import com.nokia.carbide.cpp.pi.button.ComNokiaCarbidePiButtonHelpIDs;
+import com.nokia.carbide.cpp.pi.button.IBupEventMap;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapProfile;
+import com.nokia.carbide.cpp.ui.CarbideUIPlugin;
+import com.nokia.carbide.cpp.ui.ICarbideSharedImages;
+
+public class BupProfileEditDialog extends TitleAreaDialog {
+	
+	private Composite content = null;
+	private Group localeMappingGroup = null;
+	private Composite mappingComposite = null;
+	private BupMapTableViewer mappingTableViewer = null;
+	private Composite buttonComposite = null;
+	private Button addButton = null;
+	private Button removeButton = null;
+	private Button editButton = null;
+	private Button clearButton = null;
+	
+	class BupEditEntry {
+		public String enumString = null;
+		public String label = null;
+		boolean changed = false;
+	};
+
+	private IBupEventMapProfile profileForThisEdit = null;
+	private IBupEventMap mapForThisEdit = null;
+	private ModifyCachedBupEventMap cachedMap = null;
+	protected BupProfileEditDialog(Shell shell, IBupEventMapProfile myProfile) {
+		super(shell);
+		super.setShellStyle(super.getShellStyle() | SWT.RESIZE);
+		profileForThisEdit = myProfile;
+		mapForThisEdit = BupEventMapManager.getInstance().captureMap(profileForThisEdit);
+		cachedMap = new ModifyCachedBupEventMap(mapForThisEdit);
+	}
+	
+	private void cleanUp() {
+		BupEventMapManager.getInstance().releaseMap(mapForThisEdit);
+	}
+	
+	public Control createDialogArea(Composite parent) {
+		getShell().setText(Messages.getString("BupProfileEditDialog.editingProfile") + profileForThisEdit.getProfileId()); //$NON-NLS-1$
+		setTitleImage(CarbideUIPlugin.getSharedImages().getImageDescriptor(ICarbideSharedImages.IMG_PI_METER_20_20).createImage());
+		setTitle(Messages.getString("BupProfileEditDialog.profile") + profileForThisEdit.getProfileId()); //$NON-NLS-1$
+				
+		GridLayoutFactory layoutExpandBoth = GridLayoutFactory.fillDefaults();
+		GridDataFactory gridDataExpandBoth = GridDataFactory.fillDefaults().grab(true, true);
+				
+		GridLayoutFactory gridLayoutButton = GridLayoutFactory.swtDefaults();
+		GridDataFactory gridDataButton = GridDataFactory.swtDefaults();
+		
+		content = new Composite(parent, SWT.NONE);
+		layoutExpandBoth.applyTo(content);
+		gridDataExpandBoth.applyTo(content);
+		
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(content, ComNokiaCarbidePiButtonHelpIDs.PI_PROFILE_EDIT_DIALOG);
+		
+		localeMappingGroup = new Group (content, SWT.NONE);
+		layoutExpandBoth.applyTo(localeMappingGroup);
+		gridDataExpandBoth.applyTo(localeMappingGroup);
+		
+		mappingComposite = new Composite (localeMappingGroup, SWT.NONE);
+		layoutExpandBoth.copy().numColumns(2).applyTo(mappingComposite);
+		gridDataExpandBoth.applyTo(mappingComposite);
+		mappingTableViewer = new BupMapTableViewer(mappingComposite, true);
+		Table mappingTable = mappingTableViewer.getTable();
+		// enable the edit button only when a single file filter is selected
+		mappingTable.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent arg0) {
+				handleViewerSelection();
+			}
+		});	
+
+		int maxWidth;
+		buttonComposite = new Composite (mappingComposite, SWT.NONE);
+		gridLayoutButton.applyTo(buttonComposite);
+		gridDataButton.copy().align(SWT.CENTER, SWT.FILL).grab(false, true).applyTo(buttonComposite);
+		addButton = new Button (buttonComposite, SWT.NONE);
+		addButton.setText(Messages.getString("BupProfileEditDialog.add")); //$NON-NLS-1$
+		addButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent arg0) {
+				handleAdd();
+			}
+		});	
+		maxWidth = buttonComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+		editButton = new Button (buttonComposite, SWT.NONE);
+		editButton.setText(Messages.getString("BupProfileEditDialog.edit")); //$NON-NLS-1$
+		editButton.addSelectionListener(new SelectionAdapter() {	
+			public void widgetSelected(SelectionEvent arg0) {
+				handleEdit();
+			}	
+		});
+		maxWidth = Math.max(maxWidth, editButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
+		removeButton = new Button (buttonComposite, SWT.NONE);
+		removeButton.setText(Messages.getString("BupProfileEditDialog.remove")); //$NON-NLS-1$
+		removeButton.addSelectionListener(new SelectionAdapter() {	
+			public void widgetSelected(SelectionEvent arg0) {
+				handleRemove();
+			}	
+		});
+		maxWidth = Math.max(maxWidth, removeButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
+		//dummy label as divider
+		new Label(buttonComposite, SWT.NONE);
+		new Label(buttonComposite, SWT.NONE);
+		new Label(buttonComposite, SWT.NONE);
+		new Label(buttonComposite, SWT.NONE);
+		new Label(buttonComposite, SWT.NONE);
+		clearButton = new Button(buttonComposite, SWT.NONE);
+		clearButton.setText(Messages.getString("BupProfileEditDialog.clearProfile")); //$NON-NLS-1$
+		clearButton.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				if (MessageDialog.openQuestion(getShell(), Messages.getString("BupProfileEditDialog.clearProfile"), Messages.getString("BupProfileEditDialog.clearAllConfirm"))) { //$NON-NLS-1$ //$NON-NLS-2$
+					Set<Integer> keySet = cachedMap.getKeyCodeSet();
+					Integer [] keyCodes = keySet.toArray(new Integer[keySet.size()]);
+					for (Integer keyCode : keyCodes) {
+						cachedMap.removeMapping(keyCode);
+					}
+					refreshTable();
+				}
+			}
+		});
+		maxWidth = Math.max(maxWidth, clearButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
+		
+		gridDataButton.hint(maxWidth, addButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).y).applyTo(addButton);
+		gridDataButton.hint(maxWidth, removeButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).y).applyTo(removeButton);
+		gridDataButton.hint(maxWidth, editButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).y).applyTo(editButton);
+		gridDataButton.hint(maxWidth, clearButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).y).applyTo(clearButton);
+		
+		initialize();
+
+		return content;
+	}
+
+	/**
+	 * 
+	 */
+	protected void handleViewerSelection() {
+		boolean enableEdit = (mappingTableViewer.getTable().getSelectionCount() == 1);
+		editButton.setEnabled(enableEdit);
+		boolean enableRemove = (mappingTableViewer.getTable().getSelectionCount() > 0);
+		removeButton.setEnabled(enableRemove);
+	}
+	
+	/**
+	 * 
+	 */
+	protected void handleRemove() {
+		ISelection selection = mappingTableViewer.getSelection();
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection ss = (IStructuredSelection) selection;
+			Object element = ss.getFirstElement();
+			if (element instanceof BupMapTableViewer.BupMapEntry) {
+				BupMapTableViewer.BupMapEntry entry = (BupMapTableViewer.BupMapEntry)element;
+				cachedMap.removeMapping(entry.keyCode);
+				refreshTable();
+			}
+		}
+		removeButton.setEnabled(false);	// selection is gone, let next selection re-enable it
+		refreshTable();
+	}
+
+	/**
+	 * 
+	 */
+	protected void handleAdd() {
+		BupMapAddDialog dialog = new BupMapAddDialog(getShell(), cachedMap, 0, "", ""); //$NON-NLS-1$ //$NON-NLS-2$
+		if (dialog.open() == OK) {
+			cachedMap.addMapping(dialog.getKeyCode(), dialog.getEnumString(), dialog.getLabel());
+		}
+		refreshTable();
+	}
+
+
+	/**
+	 * 
+	 */
+	protected void handleEdit() {
+		ISelection selection = mappingTableViewer.getSelection();
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection ss = (IStructuredSelection) selection;
+			Object element = ss.getFirstElement();
+			if (element instanceof BupMapTableViewer.BupMapEntry) {
+				BupMapTableViewer.BupMapEntry entry = (BupMapTableViewer.BupMapEntry)element;
+				BupMapEditDialog dialog = new BupMapEditDialog(getShell(), entry.keyCode, entry.enumString, entry.label);
+				if (dialog.open() == OK) {
+					cachedMap.removeMapping(entry.keyCode);
+					cachedMap.addMapping(entry.keyCode, dialog.getEnumString(), dialog.getLabel());
+				}
+			}
+		}
+		refreshTable();
+	}
+
+	private void initialize() {
+		// initialize
+		editButton.setEnabled(false);
+		removeButton.setEnabled(false);
+		refreshTable();
+	}
+	
+	public void okPressed() {
+		super.okPressed();
+		if (cachedMap.haveUncommitedChanges()) {
+			cachedMap.commitChanges();
+			BupEventMapManager.getInstance().commitEditToWorkspace(mapForThisEdit);
+		}
+		cleanUp();
+	}
+	
+	public void cancelPressed() {
+		if (cachedMap.haveUncommitedChanges()) {
+			MessageDialog dialog = new MessageDialog(getShell(), 
+					Messages.getString("BupProfileEditDialog.uncommittedChanges"),  //$NON-NLS-1$
+					null, 
+					Messages.getString("BupProfileEditDialog.saveChanges") + profileForThisEdit.getProfileId() + "?",  //$NON-NLS-1$ //$NON-NLS-2$
+					MessageDialog.QUESTION, 
+					new String[] { IDialogConstants.YES_LABEL,
+					IDialogConstants.NO_LABEL,
+					IDialogConstants.CANCEL_LABEL }, 0); // default yes
+			switch (dialog.open()) {
+			case 0: // yes
+				cachedMap.commitChanges();	// fall thru to no
+			case 1: // no
+				super.cancelPressed();
+				cleanUp();
+			case 2:	// cancel
+			default:
+				return;
+			}
+		}
+		super.cancelPressed();
+		cleanUp();
+	}
+	
+	// Override OK to look like save
+	protected Button createButton(Composite parent, int id, String label, boolean defaultButton) {
+		Button myButton = super.createButton(parent, id, label, defaultButton);
+		if (id == IDialogConstants.OK_ID) {
+			myButton.setText(Messages.getString("BupProfileEditDialog.save")); //$NON-NLS-1$
+		}
+		return myButton;
+	}
+	
+	private void refreshTable() {
+		mappingTableViewer.loadMap(cachedMap);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/BupProfileTreeViewer.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.ITreeSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Composite;
+
+import com.nokia.carbide.cpp.pi.button.BupEventMapManager;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapProfile;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+
+
+public class BupProfileTreeViewer extends TreeViewer {
+	private static final String WORKSPACE_PREF = Messages.getString("BupProfileTreeViewer.0"); //$NON-NLS-1$
+	private static final String CARBIDE_BUILTIN = Messages.getString("BupProfileTreeViewer.1"); //$NON-NLS-1$
+
+	private ISymbianSDK romKit;
+	private Set<ISymbianSDK> appKits;
+	private ISelection lastValidSelection;
+	
+	public class BupProfileTreeData {
+		private ISymbianSDK romSdk;
+		private Set<ISymbianSDK> appSdks;
+		
+		public BupProfileTreeData(ISymbianSDK rom, Set<ISymbianSDK> app) {
+			romSdk = rom;
+			appSdks = app;
+		}
+		
+		public ISymbianSDK getRomSdk() {
+			return romSdk;
+		}
+		
+		public Set<ISymbianSDK> getAppSdk() {
+			return appSdks;
+		}
+	}
+		
+	public class BupProfileTreeContentProvider implements ITreeContentProvider {
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
+		 */
+		public Object[] getChildren(Object arg0) {
+			if (arg0 instanceof String) {
+				if (((String)arg0).equals(WORKSPACE_PREF)) {
+					ArrayList<IBupEventMapProfile> workspaceProfiles = BupEventMapManager.getInstance().getProfilesFromWorkspacePref();
+					return workspaceProfiles.toArray();
+				}
+				if (((String)arg0).equals(CARBIDE_BUILTIN)) {
+					ArrayList<IBupEventMapProfile> builtinProfiles = BupEventMapManager.getInstance().getProfilesFromBuiltin();
+					return builtinProfiles.toArray();
+				}
+			}
+			if (arg0 instanceof ISymbianSDK) {
+				ArrayList<IBupEventMapProfile> sdkProfile = BupEventMapManager.getInstance().getProfilesFromSDK((ISymbianSDK)arg0);
+				return sdkProfile.toArray();
+			}
+			return null;
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
+		 */
+		public Object getParent(Object arg0) {
+			// not implemented
+			return null;
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
+		 */
+		public boolean hasChildren(Object arg0) {
+			if (arg0 instanceof String) {
+				if (((String)arg0).equals(WORKSPACE_PREF) || ((String)arg0).equals(CARBIDE_BUILTIN)) {
+					return true;
+				}
+			}
+			if (arg0 instanceof ISymbianSDK) {
+				return true;
+			}
+			return false;
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+		 */
+		public Object[] getElements(Object arg0) {
+			ArrayList<Object> elements = new ArrayList<Object>();
+			if (romKit != null) {
+				if (getChildren(romKit).length > 0) {
+					elements.add(romKit);
+				}
+			}
+			
+			ISymbianSDK [] appSdks = appKits.toArray(new ISymbianSDK[appKits.size()]);
+			for (ISymbianSDK sdk : appSdks) {
+				if (getChildren(sdk).length > 0) {
+					elements.add(sdk);
+				}
+			}
+			elements.add(WORKSPACE_PREF);
+			elements.add(CARBIDE_BUILTIN);
+			
+			return elements.toArray();
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+		 */
+		public void dispose() {
+		}
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+		 */
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+			if (newInput instanceof BupProfileTreeData) {
+				BupProfileTreeData data = (BupProfileTreeData)newInput;
+				romKit = data.romSdk;
+				appKits = data.appSdks;
+			}
+		}
+		
+	}
+	
+	private class BupProfileTreeLabelProvider extends LabelProvider implements IBaseLabelProvider{
+		public String getText(Object element) {
+			if (element instanceof IBupEventMapProfile) {
+				return ((IBupEventMapProfile)element).getProfileId();
+			}
+			if (element instanceof String) {
+				if (((String)element).equals(WORKSPACE_PREF)) {
+					return (String)element;
+				}
+				if (((String)element).equals(CARBIDE_BUILTIN)) {
+					return (String)element;
+				}
+			}
+			if (element instanceof ISymbianSDK) {
+				return Messages.getString("BupProfileTreeViewer.2") + ((ISymbianSDK)element).getUniqueId(); //$NON-NLS-1$
+			}
+			return ""; //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * @param parent
+	 * @param style
+	 */
+	public BupProfileTreeViewer(Composite parent) {
+		super(parent, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
+		setContentProvider(new BupProfileTreeContentProvider());
+		setLabelProvider(new BupProfileTreeLabelProvider());
+		final BupProfileTreeViewer viewerSelf = this;
+		this.getTree().addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				Object data = arg0.item.getData();
+				if (!(data instanceof IBupEventMapProfile)) {
+					// we are a SWT.SINGLE, so we select last good selection canceling this one,
+					// it behaves like last valid selection stick 
+					viewerSelf.setSelection(lastValidSelection);
+				} else {
+					// remember last valid selection
+					lastValidSelection = viewerSelf.getSelection();
+				}
+			}
+		});
+	}
+
+	/**
+	 * Handy routine for reading selection
+	 * 
+	 * @return
+	 */
+	public IBupEventMapProfile getSelectedProfile() {
+		if (getSelection().isEmpty()) {
+			return null;
+		} else {
+			ISelection selection = getSelection();
+			if (selection instanceof ITreeSelection) {
+				Object firstElement = ((ITreeSelection)selection).getFirstElement();
+				if (firstElement instanceof IBupEventMapProfile) {
+					return (IBupEventMapProfile)firstElement;
+				}
+			}
+		}
+		return null;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ButtonPreferencePage.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+public class ButtonPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+	private static int BUTTON_TAB_INDEX = 0;
+	
+	
+	private Composite content = null;
+	private TabFolder buttonTabFolder = null;
+	TabItem buttonTab = null;
+	ButtonTabPage buttonTabPage = null;
+	
+	@Override
+	protected Control createContents(Composite parent) {
+		GridLayoutFactory layoutExpandBoth = GridLayoutFactory.fillDefaults();
+		GridDataFactory gridDataExpandBoth = GridDataFactory.fillDefaults().grab(true, true);
+		
+		content = new Composite(parent, SWT.NONE);
+		layoutExpandBoth.applyTo(content);
+		gridDataExpandBoth.applyTo(content);
+		
+		buttonTabFolder = new TabFolder(content, SWT.TOP);
+		layoutExpandBoth.applyTo(buttonTabFolder);
+		gridDataExpandBoth.applyTo(buttonTabFolder);
+		
+		buttonTabPage = new ButtonTabPage(buttonTabFolder);
+		buttonTab = new TabItem(buttonTabFolder, SWT.NONE, BUTTON_TAB_INDEX);
+		buttonTab.setText(Messages.getString("ButtonPreferencePage.0")); //$NON-NLS-1$
+		buttonTab.setToolTipText(Messages.getString("ButtonPreferencePage.1")); //$NON-NLS-1$
+		buttonTab.setControl(buttonTabPage);
+		
+		getPageStoredValues();
+		return content;
+	}
+
+	/**
+	 * 
+	 */
+	private void getPageStoredValues() {
+		buttonTabPage.getStoredPreferenceValues();
+	}
+	
+	/**
+	 * 
+	 */
+	private boolean setPageStoredValues() {
+		if (buttonTabPage.setStoredPreferenceValues() == false) {
+			return false;
+		}
+		return true;
+	}
+	
+	/**
+	 * Things to do when user hit the "OK" button.
+	 */
+	public boolean performOk() {
+		setPageStoredValues();
+		cleanUp();
+		return super.performOk();
+	}
+
+	/**
+	 * 
+	 */
+	private void cleanUp() {
+		Runtime.getRuntime().gc();
+	}
+
+	/**
+	 * Things to do when user hit the "Apply" button.
+	 */
+	public void performApply() {
+		setPageStoredValues();
+		cleanUp();
+		super.performApply();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+	 */
+	public void init(IWorkbench arg0) {
+	}
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ButtonTabPage.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.pi.button.BupEventMapManager;
+import com.nokia.carbide.cpp.pi.button.ButtonPlugin;
+import com.nokia.carbide.cpp.pi.button.ComNokiaCarbidePiButtonHelpIDs;
+import com.nokia.carbide.cpp.pi.button.IBupEventMap;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapProfile;
+
+public class ButtonTabPage extends Composite {
+	
+	private ArrayList<IBupEventMapProfile> profiles = new ArrayList<IBupEventMapProfile>();
+	
+	// Controls
+	private Composite content = null;
+	private Group profileGroup = null;
+	private Combo profileCombo = null;
+	private Composite profileButtonComposite = null;
+	private Composite importExportButtonComposite= null;
+	private Button profileNewButton = null;
+	private Button profileRemoveButton = null;
+	private Button profileEditButton = null;
+	private Link profileImportLink = null;
+	private Link profileExportLink = null;
+	private Group mappingGroup = null;
+	private BupMapTableViewer mappingTableViewer = null;
+	
+	/**
+	 * import XML and merge into workspace pref
+	 */
+	private void importXML() {
+		ImportBupMapWizardDialog dialog = new ImportBupMapWizardDialog(getShell());
+		dialog.open();
+		refreshCombo();	// modified
+	}
+
+	/**
+	 * export
+	 */
+	private void exportXML() {
+		ExportBupMapWizardDialog dialog = new ExportBupMapWizardDialog(getShell());
+		dialog.open();
+	}
+	
+	public ButtonTabPage(Composite parent) {
+		super(parent, SWT.NONE);
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, ComNokiaCarbidePiButtonHelpIDs.PI_BUTTON_MAP_PREF_TAB);
+		
+		GridLayoutFactory layoutExpandBoth = GridLayoutFactory.fillDefaults();
+		GridDataFactory gridDataExpandBoth = GridDataFactory.fillDefaults().grab(true, true);
+		
+		GridLayoutFactory layoutExpandHorizontal = GridLayoutFactory.swtDefaults();
+		GridDataFactory gridDataExpandHorizontal = GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false);
+
+		GridDataFactory gridDataButton = GridDataFactory.swtDefaults();
+		
+		layoutExpandBoth.applyTo(this);
+		gridDataExpandBoth.applyTo(this);
+		
+		content = new Composite(this, SWT.NONE);
+		layoutExpandBoth.applyTo(content);
+		gridDataExpandBoth.applyTo(content);
+		
+		profileGroup = new Group (content, SWT.NONE);
+		layoutExpandHorizontal.applyTo(profileGroup);
+		gridDataExpandHorizontal.applyTo(profileGroup);
+		profileGroup.setText(Messages.getString("ButtonTabPage.manageProfiles")); //$NON-NLS-1$
+		
+		profileCombo = new Combo (profileGroup, SWT.READ_ONLY);
+		layoutExpandHorizontal.applyTo(profileCombo);
+		gridDataExpandHorizontal.applyTo(profileCombo);
+		profileCombo.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				refreshTableToCombo();
+			}
+		});
+		
+		profileButtonComposite = new Composite (profileGroup, SWT.NONE);
+		layoutExpandHorizontal.copy().numColumns(3).applyTo(profileButtonComposite);
+		gridDataExpandHorizontal.applyTo(profileButtonComposite);
+		
+		int maxWidth;
+		profileNewButton = new Button(profileButtonComposite, SWT.NONE);
+		profileNewButton.setText(Messages.getString("ButtonTabPage.duplicate")); //$NON-NLS-1$
+		profileNewButton.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				
+				BupProfileDuplicateDialog dialog = new BupProfileDuplicateDialog(getShell(), profiles.get(profileCombo.getSelectionIndex()));
+				if (dialog.open() == BupProfileDuplicateDialog.OK) { 
+					refreshCombo();
+					profileCombo.select(BupEventMapManager.getInstance().getProfilesFromWorkspacePref().size() - 1);	// we cheat a bit by knowing addToWorkspace always append to the end
+					refreshTableToCombo();	// current profile had been removed;
+				}
+			}
+		});
+		maxWidth = profileNewButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+		profileEditButton = new Button(profileButtonComposite, SWT.NONE);
+		profileEditButton.setText(Messages.getString("ButtonTabPage.Edit")); //$NON-NLS-1$
+		profileEditButton.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+			public void widgetSelected(SelectionEvent arg0) {
+				IBupEventMapProfile profile = profiles.get(profileCombo.getSelectionIndex());
+				if (profile != null) {
+					new BupProfileEditDialog(getShell(), profile).open();
+					refreshTableToCombo();	// current profile may had changed
+				}
+			}
+		});
+		maxWidth = Math.max(maxWidth, profileEditButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
+		profileRemoveButton = new Button(profileButtonComposite, SWT.NONE);
+		profileRemoveButton.setText(Messages.getString("ButtonTabPage.remove")); //$NON-NLS-1$
+		profileRemoveButton.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				IBupEventMapProfile profile = profiles.get(profileCombo.getSelectionIndex());
+				if (profile != null) {
+					if(MessageDialog.openQuestion(getShell(), Messages.getString("ButtonTabPage.confirmRemovalHeading"), //$NON-NLS-1$
+							Messages.getString("ButtonTabPage.profile") + profile.getProfileId() + Messages.getString("ButtonTabPage.confirmRemoval"))) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+						if (BupEventMapManager.getInstance().canRemoveProfile(profile)) { 
+							BupEventMapManager.getInstance().removeFromWorkspace(profile);
+							refreshCombo();
+							refreshTableToCombo();	// current profile had been removed;
+						} else {
+							MessageDialog.openInformation(getShell(), Messages.getString("ButtonTabPage.cannotRemoveProfile"), //$NON-NLS-1$
+									Messages.getString("ButtonTabPage.profile") + profile.getProfileId() + Messages.getString("ButtonTabPage.isStillOpen")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+						}
+					}
+				}
+			}
+		});
+		maxWidth = Math.max(maxWidth, profileRemoveButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
+
+		importExportButtonComposite = new Composite(content, SWT.NONE);
+		layoutExpandHorizontal.copy().numColumns(2).applyTo(importExportButtonComposite);
+		gridDataExpandHorizontal.applyTo(importExportButtonComposite);
+		
+		profileImportLink = new Link (importExportButtonComposite, SWT.NONE);
+		profileImportLink.setText(Messages.getString("ButtonTabPage.importHref")); //$NON-NLS-1$
+		profileImportLink.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				importXML();
+			}
+			
+		});
+		profileExportLink = new Link (importExportButtonComposite, SWT.NONE);
+		profileExportLink.setText(Messages.getString("ButtonTabPage.exportHref")); //$NON-NLS-1$
+		profileExportLink.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				exportXML();
+			}
+			
+		});
+		
+		gridDataButton.hint(maxWidth, profileNewButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).y).applyTo(profileNewButton);
+		gridDataButton.hint(maxWidth, profileRemoveButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).y).applyTo(profileRemoveButton);
+		gridDataButton.hint(maxWidth, profileEditButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).y).applyTo(profileEditButton);
+		
+		mappingGroup = new Group (content, SWT.NONE);
+		layoutExpandBoth.applyTo(mappingGroup);
+		gridDataExpandBoth.applyTo(mappingGroup);
+		mappingGroup.setText(Messages.getString("ButtonTabPage.keyPressMapping")); //$NON-NLS-1$
+
+		Composite compositeToLookBetter = new Composite(mappingGroup, SWT.NONE);
+		layoutExpandHorizontal.applyTo(compositeToLookBetter);
+		gridDataExpandHorizontal.applyTo(compositeToLookBetter);
+		
+		mappingTableViewer = new BupMapTableViewer(compositeToLookBetter, false);
+
+		refreshCombo();
+	}
+
+	private void refreshTableToCombo() {
+		IBupEventMapProfile profile = profiles.get(profileCombo.getSelectionIndex());
+		if (profile != null) {
+			profileRemoveButton.setEnabled(false);
+			profileEditButton.setEnabled(false);
+			ArrayList<IBupEventMapProfile> workspacePerfList = BupEventMapManager.getInstance().getProfilesFromWorkspacePref();
+			for (IBupEventMapProfile workspacePref : workspacePerfList) {
+				if (workspacePref.toString().equals(profile.toString())) {
+					// enable edit only when selection is workspace pref
+					profileRemoveButton.setEnabled(true);
+					profileEditButton.setEnabled(true);
+					break;
+				}
+			}
+			IBupEventMap map = BupEventMapManager.getInstance().captureMap(profile);
+			mappingTableViewer.loadMap(map);
+			BupEventMapManager.getInstance().releaseMap(map);
+		}
+	}
+	
+	private void refreshCombo() {		
+		profiles.clear();
+		ArrayList<IBupEventMapProfile> globalPrefProfile = BupEventMapManager.getInstance().getProfilesFromWorkspacePref();
+		profiles.addAll(globalPrefProfile);
+		profiles.addAll(BupEventMapManager.getInstance().getProfilesFromBuiltin());
+		
+		if (globalPrefProfile.size() > 0)
+			profileExportLink.setEnabled(true);
+		else
+			profileExportLink.setEnabled(false);
+		
+		String [] profileItems = new String [profiles.size()];
+		for (int i = 0; i < profiles.size(); i++) {
+			profileItems[i] = profiles.get(i).toString();
+		}
+		
+		// try to remember and select the same upon combo reload, select first if
+		// nothing was selected before or previous selection is removed
+		String savedId = null;
+		if (profileCombo.getSelectionIndex() > 0) {
+			savedId = profileCombo.getItem(profileCombo.getSelectionIndex());
+		} else {
+			savedId = BupEventMapManager.getInstance().getDefaultProfile().toString();
+		}
+		profileCombo.setItems(profileItems);
+		
+		int selectionIndex = 0;
+		if (savedId != null) {
+			for (int i = 0; i < profileCombo.getItemCount(); i++) {
+				if (profileCombo.getItem(i).equals(savedId)) {
+					selectionIndex = i;
+					break;
+				}
+			}
+		}
+		profileCombo.select(selectionIndex);
+		refreshTableToCombo();
+	}
+	
+	public void getStoredPreferenceValues() {
+		IPreferenceStore store = ButtonPlugin.getBupPrefsStore();
+
+		String profileID = store.getString(BupPreferenceConstants.KEY_MAP_PROFILE_STRING);
+		if (profileID == null || profileID.equals("")) { //$NON-NLS-1$
+			profileID = BupEventMapManager.getInstance().getDefaultProfile().toString();
+		}
+		int selectionIndex = 0;
+		if (profileID != null) {
+			for (int i = 0; i < profileCombo.getItemCount(); i++) {
+				if (profileCombo.getItem(i).equals(profileID)) {
+					selectionIndex = i;
+				}
+			}
+		}
+		profileCombo.select(selectionIndex);
+		refreshTableToCombo();
+	}
+	
+	/**
+	 * Set the stored preference settings values of this tab page.
+	 */
+	public boolean setStoredPreferenceValues(){
+		String profileString = profileCombo.getItem(profileCombo.getSelectionIndex());
+
+		IPreferenceStore store = ButtonPlugin.getBupPrefsStore();
+		store.setValue(BupPreferenceConstants.KEY_MAP_PROFILE_STRING, profileString);
+		
+		return true;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ExportBupMapGetXmlTask.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import java.io.File;
+
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+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.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.pi.button.ComNokiaCarbidePiButtonHelpIDs;
+
+
+public class ExportBupMapGetXmlTask extends WizardPage {
+	String exportXmlPathString = null;
+	
+	protected ExportBupMapGetXmlTask() {
+		super(Messages.getString("ExportBupMapGetXmlTask.selectProfile"));   //$NON-NLS-1$
+		setTitle(Messages.getString("ExportBupMapGetXmlTask.selectProfile"));   //$NON-NLS-1$
+		setDescription(Messages.getString("ExportBupMapGetXmlTask.exportProfileExplained"));   //$NON-NLS-1$
+	}
+
+	// controls
+	Composite container;
+	private Text exportXmlFileText;
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createControl(Composite parent) {
+		container = new Composite(parent, SWT.NULL);
+		GridLayout layout = new GridLayout();
+		container.setLayout(layout);
+		layout.numColumns = 1;
+		layout.verticalSpacing = 9;
+
+		Label labelSampleFile = new Label(container, SWT.NONE);
+		labelSampleFile.setText(Messages.getString("ExportBupMapGetXmlTask.exportThisProfile"));   //$NON-NLS-1$
+		
+		// subcomposite with textbox/button
+		Composite subContainer = new Composite(container, SWT.NULL);
+		GridLayout subLayout = new GridLayout();
+		subContainer.setLayout(subLayout);
+		subContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		subLayout.numColumns = 2;
+		subLayout.verticalSpacing = 9;
+
+		exportXmlFileText = new Text(subContainer, SWT.BORDER | SWT.SINGLE);
+		exportXmlFileText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		exportXmlFileText.addModifyListener(new ModifyListener(){
+			public void modifyText(ModifyEvent arg0) {
+				validatePage();
+			}
+		});
+
+		Button button = new Button(subContainer, SWT.PUSH);
+		button.setText(Messages.getString("ExportBupMapGetXmlTask.keyPressProfile"));   //$NON-NLS-1$
+		button.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				handleBrowse();
+			}
+		});
+			
+		// top tap get focus
+		exportXmlFileText.setFocus();
+
+		setControl(container);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), ComNokiaCarbidePiButtonHelpIDs.PI_KEY_MAP_EXPORT_WIZARD_XML);
+	}
+
+	public void validatePage() {
+		if (exportXmlFileText.getText() == null || exportXmlFileText.getText().length() < 1) {
+			updateStatus(null);
+			setPageComplete(false);
+			return;		// blank should be OK, consistent with Eclipse guideline
+		}
+		
+		setMessage(null, WARNING);
+		String xmlFileString = exportXmlFileText.getText();
+		File xmlFile = new File (xmlFileString);
+		if (xmlFile != null && !xmlFile.isDirectory()) {
+			String parentString = xmlFile.getParent();
+			if (parentString != null) {
+				File parentFile = new File(parentString);
+				if (parentFile.isDirectory() && parentFile.exists()) {
+					if (!xmlFileString.endsWith(".xml")) { //$NON-NLS-1$
+						updateStatus (Messages.getString("ExportBupMapGetXmlTask.extensionMustBeXML"));   //$NON-NLS-1$
+						return;
+					}
+				} else {
+					updateStatus(Messages.getString("ExportBupMapGetXmlTask.directory") + parentString + Messages.getString("ExportBupMapGetXmlTask.doesNotExist"));     //$NON-NLS-1$ //$NON-NLS-2$
+					return;
+				}
+			} else {
+				updateStatus(Messages.getString("ExportBupMapGetXmlTask.directory") + xmlFileString + Messages.getString("ExportBupMapGetXmlTask.doesNotExist"));     //$NON-NLS-1$ //$NON-NLS-2$
+				return;
+			}
+		} else {
+			updateStatus(Messages.getString("ExportBupMapGetXmlTask.enterFileName"));   //$NON-NLS-1$
+			return;
+		}
+
+		exportXmlPathString = xmlFileString;
+		if (new File(exportXmlPathString).exists()) {
+			setMessage(exportXmlPathString + Messages.getString("ExportBupMapGetXmlTask.willBeOverwritten"), WARNING); //$NON-NLS-1$
+		}
+		
+		setPageComplete(true);
+		updateStatus(null);
+	}
+
+	private void updateStatus(String message) {
+		// need to enable finish, setPageComplete eventually check global states
+		setErrorMessage(message);
+		setPageComplete(message == null);
+	}
+		
+	private void handleBrowse() {
+		FileDialog dialog = new FileDialog(getShell());
+		String[] datExtensions = {"*.xml", //$NON-NLS-1$
+									"*.*"}; //$NON-NLS-1$
+		String[] datNames = {Messages.getString("ExportBupMapGetXmlTask.profilerFiles"),   //$NON-NLS-1$
+								Messages.getString("ExportBupMapGetXmlTask.allFiles")};   //$NON-NLS-1$
+		dialog.setFilterExtensions(datExtensions);
+		dialog.setFilterNames(datNames);
+		// Try guiding user to path user is trying to fill
+		File clueFile = new File(exportXmlFileText.getText());
+		String cluePath = null;
+		if (clueFile.isDirectory()) {
+			cluePath = clueFile.getAbsolutePath();
+		} else {
+			cluePath = clueFile.getParent();
+		}
+		if (cluePath != null) {
+			dialog.setFilterPath(cluePath);
+		}
+		String filePath = dialog.open();
+
+		if (filePath != null) {
+			if (filePath.length() > 0) {
+				if (!filePath.endsWith(".xml")) {	//$NON-NLS-1$
+					filePath += ".xml";	//$NON-NLS-1$
+				}
+				exportXmlFileText.setText(filePath);
+			}
+		}		
+	}
+	
+	public String getExportXml() {
+		return exportXmlPathString;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ExportBupMapWizard.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.IExportWizard;
+import org.eclipse.ui.IWorkbench;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileType;
+import com.nokia.carbide.cpp.pi.button.BupEventMapManager;
+import com.nokia.carbide.cpp.pi.button.IBupEventMap;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapProfile;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+public class ExportBupMapWizard extends Wizard implements IExportWizard {
+
+	private ExportBupMapGetXmlTask exportPage;
+	
+	public ExportBupMapWizard() {
+		setWindowTitle(Messages.getString("ExportBupMapWizard.0"));   //$NON-NLS-1$
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.Wizard#addPages()
+	 */
+	public void addPages() {
+		addPage(exportPage = new ExportBupMapGetXmlTask());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.Wizard#performFinish()
+	 */
+	@Override
+	public boolean performFinish() {
+		ArrayList<IBupEventMapProfile> workspacePrefProfiles = BupEventMapManager.getInstance().getProfilesFromWorkspacePref();
+		if (workspacePrefProfiles.size() <= 0) {
+			GeneralMessages.showErrorMessage(Messages.getString("ExportBupMapWizard.1"));   //$NON-NLS-1$
+			return false;
+		}
+
+		java.io.File file = new java.io.File(exportPage.getExportXml());
+		ArrayList<ButtonEventProfileType> profileList = new ArrayList<ButtonEventProfileType>();
+		for (IBupEventMapProfile profile : workspacePrefProfiles) {
+			IBupEventMap map = BupEventMapManager.getInstance().captureMap(profile);
+			profileList.add(map.toEmfModel());
+			BupEventMapManager.getInstance().releaseMap(map);
+		}
+		BupEventMapManager.getInstance().saveMap(file.toURI(), profileList);	
+
+		return true;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection)
+	 */
+	public void init(IWorkbench arg0, IStructuredSelection arg1) {
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ExportBupMapWizardDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.widgets.Shell;
+
+
+public class ExportBupMapWizardDialog extends WizardDialog {
+
+	/**
+	 * @param parentShell
+	 */
+	public ExportBupMapWizardDialog(Shell parentShell) {
+		super(parentShell, new ExportBupMapWizard());
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ImportBupMapGetXmlTask.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+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.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.pi.button.BupEventMapManager;
+import com.nokia.carbide.cpp.pi.button.ComNokiaCarbidePiButtonHelpIDs;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapProfile;
+
+
+public class ImportBupMapGetXmlTask extends WizardPage {
+	private final static String XML_EXTENSION= "xml"; //$NON-NLS-1$
+	private boolean visableBefore = false;
+	String importXmlPathString = null;
+	
+	ArrayList<IBupEventMapProfile> overlapList = new ArrayList<IBupEventMapProfile>();
+	
+	protected ImportBupMapGetXmlTask() {
+		super(Messages.getString("ImportBupMapGetXmlTask.selectProfile"));  //$NON-NLS-1$
+		setTitle(Messages.getString("ImportBupMapGetXmlTask.selectProfile"));  //$NON-NLS-1$
+		setDescription(Messages.getString("ImportBupMapGetXmlTask.importProfileExplained"));  //$NON-NLS-1$
+	}
+
+	// controls
+	Composite container;
+	private Text inputXmlFileText;
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createControl(Composite parent) {
+		container = new Composite(parent, SWT.NULL);
+		GridLayout layout = new GridLayout();
+		container.setLayout(layout);
+		layout.numColumns = 1;
+		layout.verticalSpacing = 9;
+
+		Label labelSampleFile = new Label(container, SWT.NONE);
+		labelSampleFile.setText(Messages.getString("ImportBupMapGetXmlTask.importThisProfile"));  //$NON-NLS-1$
+		
+		// subcomposite with textbox/button
+		Composite subContainer = new Composite(container, SWT.NULL);
+		GridLayout subLayout = new GridLayout();
+		subContainer.setLayout(subLayout);
+		subContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		subLayout.numColumns = 2;
+		subLayout.verticalSpacing = 9;
+
+		inputXmlFileText = new Text(subContainer, SWT.BORDER | SWT.SINGLE);
+		inputXmlFileText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		inputXmlFileText.addModifyListener(new ModifyListener(){
+			public void modifyText(ModifyEvent arg0) {
+				validatePage();
+			}
+		});
+
+		Button button = new Button(subContainer, SWT.PUSH);
+		button.setText(Messages.getString("ImportBupMapGetXmlTask.keyPressProfile"));  //$NON-NLS-1$
+		button.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				handleBrowse();
+			}
+		});
+			
+		// top tap get focus
+		inputXmlFileText.setFocus();
+
+		setControl(container);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), ComNokiaCarbidePiButtonHelpIDs.PI_KEY_MAP_IMPORT_WIZARD_XML);
+	}
+
+	public void validatePage() {
+		if (inputXmlFileText.getText() == null || inputXmlFileText.getText().length() < 1) {
+			updateStatus(null);
+			setPageComplete(false);
+			return;		// blank should be OK, consistent with Eclipse guideline
+		}
+		
+		int dotLoc = inputXmlFileText.getText().lastIndexOf('.');
+		if (dotLoc != -1) {
+			String ext = inputXmlFileText.getText().substring(dotLoc + 1);
+			if (ext.equalsIgnoreCase(XML_EXTENSION) == false) {
+				updateStatus(Messages.getString("ImportBupMapGetXmlTask.mustEndWithXML"));  //$NON-NLS-1$
+				return;
+			}
+		}
+
+		if (!(new File(inputXmlFileText.getText()).exists())) {
+			updateStatus(Messages.getString("ImportBupMapGetXmlTask.fileDoesNotExist"));  //$NON-NLS-1$
+			return;
+		}
+		if (!(new File(inputXmlFileText.getText()).isFile())) {
+			updateStatus(Messages.getString("ImportBupMapGetXmlTask.enterProfileFileName"));  //$NON-NLS-1$
+			return;		
+		}
+		
+		// this file looks good, let's see if it got overlap
+		java.io.File file = new java.io.File(inputXmlFileText.getText());
+		overlapList = BupEventMapManager.getInstance().getOverLapWithWorkspace(file.toURI());
+		importXmlPathString = inputXmlFileText.getText();
+		((ImportBupMapWizard)getWizard()).setAllowFinish(overlapList.size() == 0);
+
+		setPageComplete(true);
+		updateStatus(null);
+	}
+
+	private void updateStatus(String message) {
+		// need to enable finish, setPageComplete eventually check global states
+		setErrorMessage(message);
+		setPageComplete(message == null);
+	}
+		
+	private void handleBrowse() {
+		FileDialog dialog = new FileDialog(getShell());
+		String[] datExtensions = {"*.xml", //$NON-NLS-1$
+									"*.*"}; //$NON-NLS-1$
+		String[] datNames = {Messages.getString("ImportBupMapGetXmlTask.profileFiles"),  //$NON-NLS-1$
+								Messages.getString("ImportBupMapGetXmlTask.allFiles")};  //$NON-NLS-1$
+		dialog.setFilterExtensions(datExtensions);
+		dialog.setFilterNames(datNames);
+		// Try guiding user to path user is trying to fill
+		File clueFile = new File(inputXmlFileText.getText());
+		String cluePath = null;
+		if (clueFile.isDirectory()) {
+			cluePath = clueFile.getAbsolutePath();
+		} else {
+			cluePath = clueFile.getParent();
+		}
+		if (cluePath != null) {
+			dialog.setFilterPath(cluePath);
+		}
+		String filePath = dialog.open();
+
+		if (filePath != null) {
+			if (filePath.length() > 0) {
+				inputXmlFileText.setText(filePath);
+			}
+		}		
+	}
+
+	public void setVisible(boolean visable) {
+		super.setVisible(visable);
+		
+		if (visable) {
+			// block the text if it's wrong on startup, so user know what's wrong
+			if (visableBefore == false && getErrorMessage() != null) {
+				inputXmlFileText.selectAll();
+			}
+			if (new java.io.File(inputXmlFileText.getText()).exists()) {
+				if (overlapList.size() > 0) {
+					((ImportBupMapWizard)getWizard()).setAllowFinish(false);
+				}
+				((ImportBupMapWizard)getWizard()).setAllowFinish(true);
+			} else {
+				((ImportBupMapWizard)getWizard()).setAllowFinish(false);
+			}
+		} else {
+			((ImportBupMapWizard)getWizard()).setAllowFinish(true);
+		}
+		visableBefore = visable;
+	}
+
+	/**
+	 * @return
+	 */
+	public String[] getOverLapList() {
+		ArrayList<String> resultList = new ArrayList<String>();
+
+		for (IBupEventMapProfile overlapProfile : overlapList) {
+			resultList.add(overlapProfile.getProfileId());
+		}
+		
+		return resultList.toArray(new String[resultList.size()]);
+	}
+
+	/**
+	 * @return
+	 */
+	public String getxImportXml() {
+		return importXmlPathString;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ImportBupMapShowOverLapTask.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.pi.button.ComNokiaCarbidePiButtonHelpIDs;
+
+
+public class ImportBupMapShowOverLapTask extends WizardPage {
+	
+	/**
+	 * @param pageName
+	 */
+	protected ImportBupMapShowOverLapTask() {
+		super(Messages.getString("ImportBupMapShowOverLapTask.0"));  //$NON-NLS-1$
+		setTitle(Messages.getString("ImportBupMapShowOverLapTask.1"));  //$NON-NLS-1$
+		setDescription(Messages.getString("ImportBupMapShowOverLapTask.2"));  //$NON-NLS-1$
+	}
+	
+	// controls
+	Composite container;
+	Table table;
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createControl(Composite parent) {
+		GridLayoutFactory layoutExpandBoth = GridLayoutFactory.fillDefaults();
+		GridDataFactory gridDataExpandBoth = GridDataFactory.fillDefaults().grab(true, true);
+		
+		container = new Composite(parent, SWT.NULL);
+		layoutExpandBoth.applyTo(container);
+		gridDataExpandBoth.applyTo(container);
+		
+		table = new Table(container, SWT.BORDER | SWT.V_SCROLL);
+		layoutExpandBoth.applyTo(table);
+		gridDataExpandBoth.applyTo(table);
+		
+		setControl(container);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), ComNokiaCarbidePiButtonHelpIDs.PI_KEY_MAP_IMPORT_WIZARD_OVERLAP);
+	}
+
+	/**
+	 * @param overLapList
+	 */
+	public void setOverLapList(String[] overLapList) {
+		table.removeAll();
+		for (String profile : overLapList) {
+			TableItem item = new TableItem(table, SWT.NONE);
+			item.setText(profile);
+		}
+	}
+	
+	public void setVisible(boolean visable) {
+		super.setVisible(visable);
+		if (visable) {
+			((ImportBupMapWizard)getWizard()).setAllowFinish(true);
+		} else {
+			((ImportBupMapWizard)getWizard()).setAllowFinish(false);
+		}
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ImportBupMapWizard.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.IWorkbench;
+
+import com.nokia.carbide.cpp.pi.button.BupEventMapManager;
+
+
+public class ImportBupMapWizard extends Wizard implements IImportWizard {
+
+	private ImportBupMapGetXmlTask importPage;
+	private ImportBupMapShowOverLapTask overlapPage;
+	private boolean allowFinish = false;
+	
+	public ImportBupMapWizard() {
+		setWindowTitle(Messages.getString("ImportBupMapWizard.0"));  //$NON-NLS-1$
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.Wizard#addPages()
+	 */
+	public void addPages() {
+		addPage(importPage = new ImportBupMapGetXmlTask());
+		addPage(overlapPage = new ImportBupMapShowOverLapTask());
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.wizard.Wizard#performFinish()
+	 */
+	@Override
+	public boolean performFinish() {
+		java.io.File file = new java.io.File(importPage.getxImportXml());
+		BupEventMapManager.getInstance().importMergeToWorkspace(file.toURI());
+		return true;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection)
+	 */
+	public void init(IWorkbench arg0, IStructuredSelection arg1) {
+	}
+	
+	public void setAllowFinish(boolean cond) {
+		allowFinish = cond;
+	}
+	
+	public boolean canFinish() {
+		return allowFinish;
+	}
+	
+	public IWizardPage getNextPage (IWizardPage page) {
+		String [] overlaps = importPage.getOverLapList();
+		if (page == importPage ) {
+			overlapPage.setOverLapList(overlaps);
+			if (overlaps.length > 0) {
+				return overlapPage;
+			}
+			else {
+				return overlapPage.getNextPage();
+			}
+		}
+		return super.getNextPage(page);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ImportBupMapWizardDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.widgets.Shell;
+
+
+public class ImportBupMapWizardDialog extends WizardDialog {
+
+	/**
+	 * @param parentShell
+	 */
+	public ImportBupMapWizardDialog(Shell parentShell) {
+		super(parentShell, new ImportBupMapWizard());
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.button.ui.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/ModifyCachedBupEventMap.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+import org.eclipse.emf.common.util.EList;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.MappingType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigFactory;
+import com.nokia.carbide.cpp.pi.button.IBupEventMap;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapEditable;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapProfile;
+
+/**
+ *
+ * A class that cache IBupEventMap, handles modifications and commits update
+ *
+ */
+public class ModifyCachedBupEventMap implements IBupEventMap,  IBupEventMapEditable {
+	
+	private IBupEventMap srcMap;
+	private boolean modified;
+	class TableEntry {
+		String enumString;
+		String label;
+		boolean modified = false;
+	};
+	private TreeMap<Integer, TableEntry> cachedMap = new TreeMap<Integer, TableEntry>();
+	
+	public ModifyCachedBupEventMap(IBupEventMap map) {
+		srcMap = map;
+		initializeFromMap(srcMap);
+	}
+	
+	public void initializeFromMap(IBupEventMap map) {
+		modified = !map.equals(srcMap);
+		cachedMap.clear();
+		Set<Integer> keyCodeSet = map.getKeyCodeSet();
+		for (Integer keyCode : keyCodeSet) {
+			TableEntry entry = new TableEntry();
+			entry.enumString = map.getEnum(keyCode);
+			entry.label = map.getLabel(keyCode);
+			cachedMap.put(keyCode, entry);
+		}
+	}
+
+	public void commitChanges() {
+		if (haveUncommitedChanges()) {
+			// reset the map to blank
+			Integer [] keyCodeSet = srcMap.getKeyCodeSet().toArray(new Integer[srcMap.getKeyCodeSet().size()]);
+			for (Integer keyCode : keyCodeSet) {
+				srcMap.removeMapping(keyCode);
+			}
+			// replace with all new mapping
+			Set<Entry<Integer, TableEntry>> entrySet = cachedMap.entrySet();
+			for (Entry<Integer, TableEntry> mapEntry : entrySet) {
+				srcMap.addMapping(mapEntry.getKey(), mapEntry.getValue().enumString, mapEntry.getValue().label);
+			}
+		}
+		initializeFromMap(srcMap);	// now we are done, reload as if freshly instantiated
+	}
+	
+	public Set<Integer> getKeyCodeSet() {
+		return cachedMap.keySet();
+	}
+	
+	public String getLabel(int keyCode) {
+		TableEntry entry = cachedMap.get(keyCode);
+	    
+	    if (entry == null) {
+	    	return "" + keyCode;	// default is just the decimal value string //$NON-NLS-1$
+	    }
+
+	    return entry.label;		
+	}
+	
+	public String getEnum(int keyCode) {
+		TableEntry entry = cachedMap.get(keyCode);
+	    
+	    if (entry == null) {
+	    	return ""; //$NON-NLS-1$
+	    }
+
+	    return entry.enumString;
+	}
+
+	public boolean isModified(int keyCode) {
+		TableEntry cachedEntry = cachedMap.get(keyCode);
+	    
+	    if (cachedEntry == null) {
+	    	if (srcMap.getKeyCodeSet().contains(keyCode)) {
+	    		return true;
+	    	}
+	    	return false;
+	    }
+	    return cachedEntry.modified;
+	}
+
+	
+	public boolean haveUncommitedChanges() {
+		return modified;
+	}
+
+	public boolean flagAsModified(int keyCode) {
+		boolean inCachedMap = cachedMap.keySet().contains(keyCode);
+		boolean inSrcMap = srcMap.getKeyCodeSet().contains(keyCode);
+		
+		if (inCachedMap != inSrcMap) {
+			return true;
+		}
+		
+		if (inCachedMap == false) {
+			return false;	// both doesn't exist
+		}
+		
+		TableEntry cachedEntry = cachedMap.get(keyCode);
+		return (!cachedEntry.enumString.equals(srcMap.getEnum(keyCode)) ||
+				!cachedEntry.label.equals(srcMap.getLabel(keyCode)));
+	}
+
+	public void addMapping(int keyCode, String enumString, String label) {
+		modified = true;
+		TableEntry entry = cachedMap.get(keyCode);
+		if (entry == null) {	
+			entry = new TableEntry();
+			cachedMap.put(new Integer(keyCode), entry);
+		}
+		entry.enumString = enumString;
+		entry.label = label;
+		entry.modified = true;
+	}
+
+	public void removeMapping(int keyCode) {
+		modified = true;
+		cachedMap.remove(keyCode);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.pi.button.IBupEventMap#getProfile()
+	 */
+	public IBupEventMapProfile getProfile() {
+		return srcMap.getProfile();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.pi.button.IBupEventMap#toEmfModel()
+	 */
+	public ButtonEventProfileType toEmfModel() {
+		ButtonEventProfileType profile = PIConfigFactory.eINSTANCE.createButtonEventProfileType();
+
+		profile.setProfileId(getProfile().getProfileId());
+		EList<MappingType> mappingList = profile.getMapping();
+		for (Entry<Integer, TableEntry> entry : cachedMap.entrySet()) {
+			MappingType mappingType = PIConfigFactory.eINSTANCE.createMappingType();
+			mappingType.setKeyCode(entry.getKey().longValue());
+			mappingType.setEnumString(entry.getValue().enumString);
+			mappingType.setLabel(entry.getValue().label);
+			mappingList.add(mappingType);
+		}
+		
+		return profile;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/SwitchBupMapDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.button.ui;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.pi.button.ComNokiaCarbidePiButtonHelpIDs;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapProfile;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
+import com.nokia.carbide.cpp.ui.CarbideUIPlugin;
+import com.nokia.carbide.cpp.ui.ICarbideSharedImages;
+
+
+public class SwitchBupMapDialog extends TitleAreaDialog {
+	private IBupEventMapProfile oldProfile;
+	private IBupEventMapProfile newProfile;
+	private boolean resetAll;
+	
+	// control
+	private Composite composite = null;
+	private BupProfileTreeViewer profileTreeViewer = null;
+	private Composite currentProfileComposite = null;
+	private Label currentProfileLabel = null;
+	private Text currenProfileText = null;
+	private Button resetAllKeysButton = null;
+	
+	public SwitchBupMapDialog (Shell parentShell, IBupEventMapProfile formerProfile) {
+		super(parentShell);
+		oldProfile = formerProfile;
+	}
+	
+	public Control createDialogArea(Composite parent) {
+		composite = new Composite(parent, SWT.NONE);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ComNokiaCarbidePiButtonHelpIDs.PI_KEY_MAP_SWITCH_DIALOG);
+		getShell().setText(Messages.getString("SwitchBupMapDialog.switchKeyPressProfile")); //$NON-NLS-1$
+		setTitleImage(CarbideUIPlugin.getSharedImages().getImageDescriptor(ICarbideSharedImages.IMG_PI_METER_20_20).createImage());
+		setTitle(Messages.getString("SwitchBupMapDialog.remapMessage")); //$NON-NLS-1$
+		
+		GridLayoutFactory layoutExpandBoth = GridLayoutFactory.fillDefaults();
+		GridDataFactory gridDataExpandBoth = GridDataFactory.fillDefaults().grab(true, true);
+		
+		layoutExpandBoth.applyTo(composite);
+		gridDataExpandBoth.applyTo(composite);
+		
+		profileTreeViewer = new BupProfileTreeViewer(composite);
+		gridDataExpandBoth.applyTo(profileTreeViewer.getTree());
+		profileTreeViewer.addPostSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent arg0) {
+				validatePage();
+			}
+		});
+		
+		currentProfileComposite = new Composite(composite, SWT.NONE);
+		layoutExpandBoth.copy().numColumns(2).applyTo(currentProfileComposite);
+		gridDataExpandBoth.applyTo(currentProfileComposite);
+		
+		currentProfileLabel = new Label(currentProfileComposite, SWT.NONE);
+		currentProfileLabel.setText(Messages.getString("SwitchBupMapDialog.currentProfile")); //$NON-NLS-1$
+		
+		currenProfileText = new Text(currentProfileComposite, SWT.READ_ONLY);
+		
+		resetAllKeysButton = new Button(composite, SWT.CHECK);
+		resetAllKeysButton.setText(Messages.getString("SwitchBupMapDialog.overwriteAllEventsWithDefault")); //$NON-NLS-1$
+		resetAllKeysButton.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				resetAll = resetAllKeysButton.getSelection();
+			}
+			
+		});
+		
+		buildBupMapProfileList();
+		resetAllKeysButton.setSelection(true);
+		resetAllKeysButton.setEnabled(false);
+		currenProfileText.setText(Messages.getString("SwitchBupMapDialog.none")); //$NON-NLS-1$
+		
+		if (oldProfile != null) {
+			resetAllKeysButton.setSelection(false);
+			resetAllKeysButton.setEnabled(true);
+			currenProfileText.setText(oldProfile.toString());
+		}
+		
+		return composite;
+	}
+
+	/**
+	 * 
+	 */
+	protected void validatePage() {
+		Button buttonSwitch = getButton(IDialogConstants.OK_ID);
+		if ((newProfile = profileTreeViewer.getSelectedProfile()) == null) {
+			buttonSwitch.setEnabled(false);
+		} else {
+			buttonSwitch.setEnabled(true);
+		}
+	}
+	
+	private void buildBupMapProfileList() {
+		Set<ISymbianSDK> sdks = new HashSet<ISymbianSDK>();
+		sdks.addAll(SDKCorePlugin.getSDKManager().getSDKList());
+		BupProfileTreeViewer.BupProfileTreeData data = profileTreeViewer.new BupProfileTreeData(null, sdks);
+		profileTreeViewer.setInput(data);
+		profileTreeViewer.expandAll();
+	}
+	
+	ArrayList<Integer> allId = new ArrayList<Integer>();
+	protected Button createButton(Composite parent, int id, String label, boolean defaultButton) {
+		Button result = super.createButton(parent, id, label, defaultButton);
+		if (id == IDialogConstants.OK_ID) {
+			result.setText(Messages.getString("SwitchBupMapDialog.switchToNewProfile")); //$NON-NLS-1$
+		}
+		allId.add(id);
+		return result;
+	}
+	
+	protected void createButtonsForButtonBar(Composite parent) {
+		super.createButtonsForButtonBar(parent);
+		GridDataFactory gridDataButton = GridDataFactory.swtDefaults();
+		int maxWidth = 0;
+		for (Integer id : allId) {
+			Button button = getButton(id);
+			maxWidth = Math.max(maxWidth, button.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
+		}
+		for (Integer id : allId) {
+			Button button = getButton(id);
+			gridDataButton.hint(maxWidth, button.computeSize(SWT.DEFAULT, SWT.DEFAULT).y).applyTo(button);
+		}
+		// now buttons are there, we can  disable key
+		getButton(IDialogConstants.OK_ID).setEnabled(false);
+	}
+
+	public boolean resetAll() {
+		return resetAll;
+	}
+	
+	public IBupEventMapProfile getNewProfile() {
+		return newProfile;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/internal/pi/button/ui/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,85 @@
+BupMapAddDialog.addMapping=Add Mapping
+BupMapAddDialog.value=Value:
+BupMapAddDialog.hexNeeds0x=Hex value should be given as 0x
+BupMapAddDialog.tKeyCode=TKeyCode:
+BupMapAddDialog.label=Label:
+BupMapAddDialog.invalidNumber=\ is an invalid number
+BupMapAddDialog.existsInMap1=\ (0x
+BupMapAddDialog.existsInMap2=) already exists in map
+BupMapAddDialog.startHexWith0x=Hex values must start with '0x'
+BupMapEditDialog.editMappingForKey=Edit Mapping for Key 
+BupMapEditDialog.hexValue=Hex Value:
+BupMapEditDialog.tKeyCode=TKeyCode:
+BupMapEditDialog.label=Label:
+BupMapTableViewer.keycode=keycode
+BupMapTableViewer.enum=enum
+BupMapTableViewer.label=label
+BupMapTableViewer.hex=Hex
+BupMapTableViewer.tKeyCode=TKeyCode
+BupMapTableViewer.Label=Label
+BupProfileDuplicateDialog.duplicateProfile=Duplicate Profile
+BupProfileDuplicateDialog.enterNewNameHeading=Please enter a new profile name:
+BupProfileDuplicateDialog.duplicateWith=Duplicate with:
+BupProfileDuplicateDialog.profileName=Profile 
+BupProfileDuplicateDialog.alreadyExists=\ exists in the workspace.
+BupProfileDuplicateDialog.duplicate=Duplicate
+BupProfileDuplicateDialog.selectProfileToDuplicate=Please select a profile to duplicate from.
+BupProfileEditDialog.editingProfile=Editing Profile 
+BupProfileEditDialog.save=Save
+BupProfileEditDialog.add=Add...
+BupProfileEditDialog.edit=Edit...
+BupProfileEditDialog.remove=Remove
+BupProfileEditDialog.profile=Profile: 
+BupProfileEditDialog.clearProfile=Clear Profile
+BupProfileEditDialog.uncommittedChanges=There are uncommitted changes
+BupProfileEditDialog.saveChanges=Save changes to profile 
+BupProfileEditDialog.clearAllConfirm=All key map entries in this profile will be cleared.\n\nDo you want to clear them?
+BupProfileTreeViewer.0=workspace preferences
+BupProfileTreeViewer.1=Carbide built-in
+BupProfileTreeViewer.2=SDK: 
+ButtonPreferencePage.0=Key Press Trace
+ButtonPreferencePage.1=Key Press Trace
+ButtonTabPage.Edit=Edit...
+ButtonTabPage.keyPressMapping=Key Press Mapping
+ButtonTabPage.confirmRemoval=\ will be removed from workspace preferences.\n\nDo you want to remove it?
+ButtonTabPage.importHref=<a href="com.nokia.carbide.cpp.internal.pi.button.ui.ImportBupMapWizardDialog">Import Profiles...</a>
+ButtonTabPage.exportHref=<a href="com.nokia.carbide.cpp.internal.pi.button.ui.ExportBupMapWizardDialog">Export Profiles...</a>
+ButtonTabPage.confirmRemovalHeading=Confirm Profile Removal
+ButtonTabPage.manageProfiles=Manage Profiles
+ButtonTabPage.duplicate=Duplicate...
+ButtonTabPage.remove=Remove
+ButtonTabPage.cannotRemoveProfile=Cannot Remove Profile
+ButtonTabPage.isStillOpen=\ is still being used by one of the opened files, it cannot be removed.
+ButtonTabPage.profile=Profile 
+ExportBupMapGetXmlTask.selectProfile=Select Key Press Profile
+ExportBupMapGetXmlTask.enterFileName=Please enter a file name.
+ExportBupMapGetXmlTask.profilerFiles=Profiler Key Press Profile (*.xml)
+ExportBupMapGetXmlTask.allFiles=All Files (*.*)
+ExportBupMapGetXmlTask.exportProfileExplained=Select the Carbide Profiler key press profile (.xml) for export from workspace preference.
+ExportBupMapGetXmlTask.exportThisProfile=&Export the following key press profile:
+ExportBupMapGetXmlTask.keyPressProfile=Key Press Profile...
+ExportBupMapGetXmlTask.extensionMustBeXML=Carbide.c++ Profiler key press profile extension must be "xml".
+ExportBupMapGetXmlTask.directory=Directory 
+ExportBupMapGetXmlTask.doesNotExist=\ does not exist.
+ExportBupMapGetXmlTask.willBeOverwritten=\ will be overwritten.
+ExportBupMapWizard.0=Performance Investigator Key Press Profile Export Wizard
+ExportBupMapWizard.1=Workspace preference does not contain key press profiles
+ImportBupMapGetXmlTask.selectProfile=Select Key Press Profile
+ImportBupMapGetXmlTask.importProfileExplained=Select the Carbide Profiler key press profile (.xml) for import to workspace preference.
+ImportBupMapGetXmlTask.importThisProfile=&Import the following key press profile:
+ImportBupMapGetXmlTask.keyPressProfile=Key Press Profile...
+ImportBupMapGetXmlTask.mustEndWithXML=Carbide.c++ Profiler key press profile extension must be "xml".
+ImportBupMapGetXmlTask.fileDoesNotExist=Carbide.c++ Profiler key press profile file specified does not exist.
+ImportBupMapGetXmlTask.enterProfileFileName=Please enter a Carbide.c++ Profiler key press profile file.
+ImportBupMapGetXmlTask.profileFiles=Profiler Key Press Profile (*.xml)
+ImportBupMapGetXmlTask.allFiles=All Files (*.*)
+ImportBupMapShowOverLapTask.0=Profile(s) Overwrite
+ImportBupMapShowOverLapTask.1=Profile(s) Overwrite
+ImportBupMapShowOverLapTask.2=Following profile(s) in workspace will be overwritten by import:
+ImportBupMapWizard.0=Performance Investigator Key Press Profile Import Wizard
+SwitchBupMapDialog.currentProfile=Current Profile: 
+SwitchBupMapDialog.none=None
+SwitchBupMapDialog.overwriteAllEventsWithDefault=Overwrite all modified key labels
+SwitchBupMapDialog.remapMessage=Remap button event using a new profile.
+SwitchBupMapDialog.switchKeyPressProfile=Switch Key Press Profile
+SwitchBupMapDialog.switchToNewProfile=Switch To New Profile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupEventDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+public class BupEventDialog extends TrayDialog {
+	
+	private int			eventKeyCode;
+	private String		eventEnumString;
+	private String		eventName;
+	private String		eventComment;
+	private long		eventTime;
+	private boolean		eventPropagate;
+
+	private String		newEventName;
+	private String		newEventComment;
+	private boolean		newEventPropagate;
+	
+	
+	// control
+	private Composite composite = null;
+	private Composite labelAndValueComposite = null;
+	private Composite checkBoxComposite = null;
+	
+	private Label keyCodeLabel = null;
+	private Label keyCodeValueLabel = null;
+	
+	private Label enumLabel = null;
+	private Label enumValueLabel = null;
+	
+	private Label nameLabel = null;
+	private Text nameText = null;
+	
+	private Label commentLabel = null;
+	private Text commentText = null;
+	
+	private Label timeLabel = null;
+	private Label timeValueLabel = null;
+	
+	private Button propagateButton = null;
+	private Label propagateLabel = null;
+	
+	public BupEventDialog(Shell shell, String title, int keyCode, String enumString, String label, String comment, boolean propagate,
+			long sampleSynchTime) {
+		super(shell);
+		
+		// store original values
+		eventKeyCode = keyCode;
+		eventEnumString = enumString;
+		newEventName = eventName = label;
+		newEventComment = eventComment = comment;
+		eventTime = sampleSynchTime;
+		newEventPropagate = eventPropagate = propagate;
+	}
+	
+	public Control createDialogArea(Composite parent) {
+		Point textBoxSize = new Point(150, (int) (PIPageEditor.helvetica_9.getFontData()[0].height + 6));
+		getShell().setText(com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.0") + eventName + com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.1") + eventTime/1000d + com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.2")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		
+		composite = new Composite(parent, SWT.NONE);
+		GridDataFactory.fillDefaults().applyTo(composite);
+		GridLayoutFactory.fillDefaults().margins(5, 5).applyTo(composite);
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ComNokiaCarbidePiButtonHelpIDs.PI_EDIT_BUTTON_EVENT);
+
+		labelAndValueComposite = new Composite(composite, SWT.NONE);
+		GridDataFactory.fillDefaults().applyTo(labelAndValueComposite);
+		GridLayoutFactory.fillDefaults().numColumns(2).applyTo(labelAndValueComposite);
+		
+		keyCodeLabel = new Label(labelAndValueComposite, SWT.RIGHT);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(keyCodeLabel);
+		keyCodeLabel.setFont(PIPageEditor.helvetica_9);
+		keyCodeLabel.setText(com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.3")); //$NON-NLS-1$
+		
+		keyCodeValueLabel = new Label(labelAndValueComposite, SWT.NONE);
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(keyCodeValueLabel);
+		keyCodeValueLabel.setFont(PIPageEditor.helvetica_9);
+		keyCodeValueLabel.setText("0x" + Integer.toHexString(eventKeyCode)); //$NON-NLS-1$
+		
+		enumLabel = new Label(labelAndValueComposite, SWT.RIGHT);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(enumLabel);
+		enumLabel.setFont(PIPageEditor.helvetica_9);
+		enumLabel.setText(com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.5")); //$NON-NLS-1$
+		
+		enumValueLabel = new Label(labelAndValueComposite, SWT.NONE);
+		enumValueLabel.setFont(PIPageEditor.helvetica_9);
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(enumValueLabel);
+		enumValueLabel.setText(eventEnumString);
+		
+		nameLabel = new Label(labelAndValueComposite, SWT.RIGHT);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(nameLabel);
+		nameLabel.setFont(PIPageEditor.helvetica_9);
+		nameLabel.setText(com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.6")); //$NON-NLS-1$
+		
+		nameText = new Text(labelAndValueComposite, SWT.BORDER);
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(nameText);
+		nameText.setFont(PIPageEditor.helvetica_9);
+		nameText.setData(com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.7")); //$NON-NLS-1$
+		
+		if (eventName != null) {
+			nameText.setText(eventName);
+		}
+		nameText.setEditable(true);
+		GridDataFactory.fillDefaults().hint(textBoxSize).applyTo(nameText);
+
+		// add the listener(s)
+		nameText.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				newEventName = nameText.getText();
+			}
+		});
+		nameText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				newEventName = nameText.getText();
+			}
+		});
+
+		commentLabel = new Label(labelAndValueComposite, SWT.RIGHT);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(commentLabel);
+		commentLabel.setText(com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.8")); //$NON-NLS-1$
+		commentLabel.setFont(PIPageEditor.helvetica_9);
+
+		commentText = new Text(labelAndValueComposite, SWT.BORDER);
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(commentText);
+		commentText.setFont(PIPageEditor.helvetica_9);
+		commentText.setData(com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.9")); //$NON-NLS-1$
+
+		if (eventComment != null) {
+			commentText.setText(eventComment);
+		}
+		commentText.setEditable(true);
+		GridDataFactory.fillDefaults().hint(textBoxSize).applyTo(commentText);
+
+		// add the listener(s)
+		commentText.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				newEventComment = commentText.getText();
+			}
+		});
+		commentText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				newEventComment = commentText.getText();
+			}
+		});
+		
+		timeLabel = new Label(labelAndValueComposite, SWT.RIGHT);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(timeLabel);
+		timeLabel.setFont(PIPageEditor.helvetica_9);
+		timeLabel.setText(com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.10")); //$NON-NLS-1$
+		
+		timeValueLabel = new Label(labelAndValueComposite, SWT.NONE);
+		timeValueLabel.setFont(PIPageEditor.helvetica_9);
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(timeValueLabel);
+		timeValueLabel.setText(eventTime/1000d + com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.11")); //$NON-NLS-1$
+
+
+		checkBoxComposite = new Composite(composite, SWT.NONE);
+		GridDataFactory.fillDefaults().applyTo(checkBoxComposite);
+		GridLayoutFactory.fillDefaults().numColumns(2).applyTo(checkBoxComposite);
+		
+		propagateButton = new Button(checkBoxComposite, SWT.CHECK);
+		propagateButton.setEnabled(true);
+		propagateButton.setSelection(eventPropagate);
+		propagateButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				newEventPropagate = propagateButton.getSelection();
+			}
+		});
+		
+		propagateLabel = new Label(checkBoxComposite, SWT.NONE);
+		propagateLabel.setFont(PIPageEditor.helvetica_9);
+		GridDataFactory.fillDefaults().grab(false, true).applyTo(propagateLabel);
+		propagateLabel.setText(com.nokia.carbide.cpp.pi.button.Messages.getString("BupEventDialog.12")); //$NON-NLS-1$
+		
+		return composite;
+	}
+
+	public String getNewName() {
+		return newEventName;
+	}
+
+	public String getNewComment() {
+		return newEventComment;
+	}
+
+	public boolean getNewSamePropagate() {
+		return newEventPropagate;
+	}
+
+	protected void okPressed() {
+		if (   ((eventName == null) && (newEventName != null))
+				|| ((eventName != null) && !eventName.equals(newEventName))
+				|| ((eventComment == null) && (newEventComment != null))
+				|| ((eventComment != null) && !eventComment.equals(newEventComment))
+				|| eventPropagate != newEventPropagate)
+			{
+				// the file has changed
+				PIPageEditor.currentPageEditor().setDirty();
+			}
+		super.okPressed();
+	}
+	
+	protected void cancelPressed() {
+		newEventName    = eventName;
+		newEventComment = eventComment;
+		newEventPropagate = eventPropagate;
+		super.cancelPressed();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupEventMapManager.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,638 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import java.io.File;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+import com.nokia.carbide.cpp.internal.pi.button.ui.BupPreferenceConstants;
+import com.nokia.carbide.cpp.internal.pi.util.config.PIConfigXMLLoader;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileListType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.MappingType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigFactory;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
+
+public class BupEventMapManager {
+	static private IBupEventMapProfile DEFAULT_PROFILE;		// this is initialized at constructor, static public is bad
+	static private IBupEventMapProfile TECHVIEW_PROFILE;	// this is initialized at constructor, static public is bad
+	static private IBupEventMapProfile S60_PROFILE;			// this is initialized at constructor, static public is bad
+	static private IBupEventMapProfile MOAP_PROFILE;		// this is initialized at constructor, static public is bad
+	static private IBupEventMapProfile UIQ_PROFILE;			// this is initialized at constructor, static public is bad
+	static private IBupEventMapProfile LEGACY_PROFILE;		// this is initialized at constructor, static public is bad
+	static private String WORKSPACE_PROFILE_FILENAME = "keymap.xml";	//$NON-NLS-1$
+	static public String TECHVIEW_PROFILE_ID = "Symbian_TechView";	//$NON-NLS-1$
+	static public String S60_PROFILE_ID = "S60";	//$NON-NLS-1$
+	static public String MOAP_PROFILE_ID = "MOAP";	//$NON-NLS-1$
+	static public String UIQ_PROFILE_ID = "UIQ";	//$NON-NLS-1$
+	static public String LEGACY_PROFILE_ID = "PI pre-2.0";	//$NON-NLS-1$
+	static public URI DEFAULT_PROFILE_URI;
+	static public URI WORKSPACE_PREF_KEY_MAP_URI;
+	static private BupEventMapManager instance = null;
+	static HashMap <IBupEventMapProfile, IBupEventMap> loadedKeyMap = new HashMap <IBupEventMapProfile, IBupEventMap>();
+	
+	private class BupEventMapProfile implements IBupEventMapProfile {
+
+		String profileId = null;
+		ISymbianSDK sdk = null;
+		URI uri = null;
+		
+		/**
+		 * @param profileId	ID string for the profile in XML
+		 * @param sdk SDK associated, could be null
+		 * @param xmlUri URI for the XML file(SDK, workspace pref, built in location)
+		 */
+		public BupEventMapProfile (String profileId, ISymbianSDK sdk, URI xmlURI) {
+			this.profileId = profileId;
+			this.sdk = sdk;
+			this.uri = xmlURI;
+		}
+		
+		/* (non-Javadoc)
+		 * @see java.lang.Object#equals(java.lang.Object)
+		 */
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null)
+				return false;
+			if (getClass() != obj.getClass())
+				return false;
+			BupEventMapProfile other = (BupEventMapProfile) obj;
+			if (!getOuterType().equals(other.getOuterType()))
+				return false;
+			if (profileId == null) {
+				if (other.profileId != null)
+					return false;
+			} else if (!profileId.equals(other.profileId))
+				return false;
+			if (sdk == null) {
+				if (other.sdk != null)
+					return false;
+			} else if (!sdk.equals(other.sdk))
+				return false;
+			if (uri == null) {
+				if (other.uri != null)
+					return false;
+			} else if (!uri.equals(other.uri))
+				return false;
+			return true;
+		}
+		
+		/* (non-Javadoc)
+		 * @see java.lang.Object#hashCode()
+		 */
+		@Override
+		public int hashCode() {
+			final int prime = 31;
+			int result = 1;
+			result = prime * result + getOuterType().hashCode();
+			result = prime * result
+					+ ((profileId == null) ? 0 : profileId.hashCode());
+			result = prime * result + ((sdk == null) ? 0 : sdk.hashCode());
+			result = prime * result + ((uri == null) ? 0 : uri.hashCode());
+			return result;
+		}
+
+		
+		public String toString() {
+			if (sdk == null) {
+				if (uri.equals(DEFAULT_PROFILE_URI))
+					return profileId + Messages.getString("BupEventMapManager.34"); //$NON-NLS-1$
+				return profileId + Messages.getString("BupEventMapManager.35"); //$NON-NLS-1$
+			} else
+				return profileId + Messages.getString("BupEventMapManager.37") + sdk.getUniqueId() + Messages.getString("BupEventMapManager.39"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		
+		public String getProfileId() {
+			return profileId;
+		}
+
+		public ISymbianSDK getSDK() {
+			return sdk;
+		}
+		
+		public URI getURI() {
+			return uri;
+		}
+
+		private BupEventMapManager getOuterType() {
+			return BupEventMapManager.this;
+		}
+		
+	}
+	
+	private class BupEventMap implements IBupEventMap{
+		private class MapEntry {
+			String enumString;
+			String label;
+		}
+		
+		private String profileName = null;
+		private IBupEventMapProfile profile = null;
+		
+		private int checkOutCount = 1;	// count myself too
+		private TreeMap<Integer, MapEntry> keyCodeMap = new TreeMap<Integer, MapEntry>();
+		
+		public BupEventMap(ButtonEventProfileType buttonProfileType, IBupEventMapProfile buttonProfile) {
+			profileName = buttonProfileType.getProfileId();
+			profile = buttonProfile;
+			EList<MappingType> mappingList = buttonProfileType.getMapping();
+			for (MappingType mapping : mappingList) {
+				addMapping(new Long(mapping.getKeyCode()).intValue(), mapping.getEnumString(), mapping.getLabel());
+			}
+		}
+		
+		public int getCheckOutCount() {
+			return checkOutCount;
+		}
+		
+		public void upCheckOutCount() {
+			++checkOutCount;
+		}
+		
+		public void downCheckOutCount() {
+			--checkOutCount;
+		}
+		
+		public IBupEventMapProfile getProfile() {
+			return profile;
+		}
+		
+		public String getProfileName () {
+			return profileName;
+		}
+				
+		public String getLabel(int keyCode)
+		{
+			MapEntry entry = keyCodeMap.get(keyCode);
+		    
+		    if (entry == null) {
+		    	return "" + keyCode;	// default is just the decimal value string //$NON-NLS-1$
+		    }
+
+		    return entry.label;
+		}
+		
+		public Set<Integer> getKeyCodeSet() {
+			return keyCodeMap.keySet();
+		}
+		
+		public String getEnum(int keyCode)
+		{
+			MapEntry entry = keyCodeMap.get(keyCode);
+		    
+		    if (entry == null) {
+		    	return ""; //$NON-NLS-1$
+		    }
+
+		    return entry.enumString;
+		}
+
+		public void addMapping(int keyCode, String enumString, String label) {
+			MapEntry entry = keyCodeMap.get(keyCode);	// support override of mapping
+			if (entry == null) {
+				entry = new MapEntry();
+				keyCodeMap.put(new Integer(keyCode), entry);
+			}
+			entry.enumString = enumString;
+			entry.label = label;
+		}
+		
+		public void removeMapping(int keyCode) {
+			MapEntry entry = keyCodeMap.get(keyCode);
+			if (entry != null) {
+				keyCodeMap.remove(new Integer(keyCode));
+			}
+		}
+		
+		public ButtonEventProfileType toEmfModel() {
+			ButtonEventProfileType profile = PIConfigFactory.eINSTANCE.createButtonEventProfileType();
+
+			profile.setProfileId(getProfileName());
+			EList<MappingType> mappingList = profile.getMapping();
+			for (Entry<Integer, MapEntry> entry : keyCodeMap.entrySet()) {
+				MappingType mappingType = PIConfigFactory.eINSTANCE.createMappingType();
+				mappingType.setKeyCode(entry.getKey().longValue());
+				mappingType.setEnumString(entry.getValue().enumString);
+				mappingType.setLabel(entry.getValue().label);
+				mappingList.add(mappingType);
+			}
+			
+			return profile;
+		}
+	}
+	
+	private BupEventMapManager () {
+		// singleton		
+		try {
+			DEFAULT_PROFILE_URI = FileLocator.find(ButtonPlugin.getDefault().getBundle(), new Path("/data/default.xml"), null).toURI(); //$NON-NLS-1$
+			WORKSPACE_PREF_KEY_MAP_URI = new File(ButtonPlugin.getDefault().getStateLocation().append(WORKSPACE_PROFILE_FILENAME).toOSString()).toURI();
+		} catch (URISyntaxException e) {
+			GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.41")); //$NON-NLS-1$
+		}	
+		ArrayList<IBupEventMapProfile> profiles = getProfilesFromBuiltin();
+		for (IBupEventMapProfile profile: profiles) {
+			if (profile.getProfileId().equals(TECHVIEW_PROFILE_ID)) {
+				TECHVIEW_PROFILE = profile;
+			}
+			if (profile.getProfileId().equals(S60_PROFILE_ID)) {
+				S60_PROFILE = profile;
+			}
+			if (profile.getProfileId().equals(MOAP_PROFILE_ID)) {
+				MOAP_PROFILE = profile;
+			}
+			if (profile.getProfileId().equals(UIQ_PROFILE_ID)) {
+				UIQ_PROFILE = profile;
+			}
+			if (profile.getProfileId().equals(LEGACY_PROFILE_ID)) {
+				LEGACY_PROFILE = profile;
+			}
+		}
+		DEFAULT_PROFILE = S60_PROFILE;
+	}
+	
+	public Object clone() throws CloneNotSupportedException {
+	    throw new CloneNotSupportedException(); // singleton
+	}
+	
+	public static BupEventMapManager getInstance() {
+		if (instance == null) {
+			instance = new BupEventMapManager();
+		}
+		return instance;
+	}
+	
+	private ArrayList<IBupEventMapProfile> getProfilesFromURI(URI uri, ISymbianSDK sdk) {
+		ArrayList<IBupEventMapProfile> allProfiles = new ArrayList<IBupEventMapProfile>();
+		ButtonEventProfileListType settings;
+		try {
+			settings = PIConfigXMLLoader.loadPiSettings(uri.toURL());
+			EList<ButtonEventProfileType> profileList = settings.getButtonEventProfile();
+			for (ButtonEventProfileType profile : profileList) {
+				allProfiles.add(new BupEventMapProfile(profile.getProfileId(), sdk, uri));
+			}
+		} catch (MalformedURLException e) {
+			// just skip this file if it failed, sdk relative and hardcoded path should never fail
+		} catch (IOException e) {
+			// just skip this file if it failed, sdk relative and hardcoded path should never fail
+		}
+		
+		return allProfiles;
+	}
+	
+	/**
+	 * @return Key press profiles available from built in.
+	 */
+	public ArrayList<IBupEventMapProfile> getProfilesFromBuiltin() {
+		return getProfilesFromURI(DEFAULT_PROFILE_URI, null);
+	}
+	
+	/**
+	 * @return Key press profiles available from workspace preference.
+	 */
+	public ArrayList<IBupEventMapProfile> getProfilesFromWorkspacePref() {
+		if (new File(WORKSPACE_PREF_KEY_MAP_URI).exists()) {
+			return getProfilesFromURI(WORKSPACE_PREF_KEY_MAP_URI, null);
+		} else {
+			try {
+				new File(WORKSPACE_PREF_KEY_MAP_URI).createNewFile();
+			} catch (IOException e) {
+				// just try our best creating new file
+			}
+			return new ArrayList<IBupEventMapProfile>();
+		}
+	}
+	
+	public String profileLocatationInSDK(ISymbianSDK sdk) {
+		String profileString = sdk.getEPOCROOT();
+		
+		if (profileString.endsWith(File.separator))
+			profileString += "epoc32" + File.separator + "data" + File.separator + "pikeymap.xml";	//$NON-NLS-1$" //$NON-NLS-2$" //$NON-NLS-3$"
+		else
+			profileString += File.separator + "epoc32" + File.separator + "data" + File.separator + "pikeymap.xml";	//$NON-NLS-1$" //$NON-NLS-2$" //$NON-NLS-3$"
+
+		return profileString;
+	}
+	
+	/**
+	 * @param sdk Any SDK from devices.xml, null workspace pref
+	 * @return Key press profiles available in a SDK.
+	 */
+	public ArrayList<IBupEventMapProfile> getProfilesFromSDK(ISymbianSDK sdk) {		
+		File profileFile = new File (profileLocatationInSDK(sdk));
+		
+		if (!profileFile.exists()) {	//$NON-NLS-1$"
+			return new ArrayList<IBupEventMapProfile>();	// just return blank if there is no XML file
+		}
+		
+		return getProfilesFromURI(profileFile.toURI(), sdk);
+	}	
+	
+	/**
+	 * @return A List of all known good key press profiles available to Carbide.
+	 */
+	public ArrayList<IBupEventMapProfile> getAllProfiles() {
+		ArrayList<IBupEventMapProfile> allProfiles = new ArrayList<IBupEventMapProfile>();
+		
+		allProfiles.addAll(getProfilesFromBuiltin());
+		allProfiles.addAll(getProfilesFromWorkspacePref());
+		
+		List<ISymbianSDK> sdkList = SDKCorePlugin.getSDKManager().getSDKList();
+		for (ISymbianSDK sdk: sdkList) {
+			allProfiles.addAll(getProfilesFromSDK(sdk));
+		}
+		
+		return allProfiles;
+	}
+	
+	/**
+	 * 
+	 * We hide mapping profile creation inside BupEventMapManager on purpose, user should
+	 * obtain list of profile from BupEventMapManager and use them immediately, this save
+	 * us from error handling user specified profile ID unavailable (e.g. removed from SDK)
+	 * 
+	 * @param uid The UID for the instance(e.g. current editor) to bind mapping to.
+	 * @param profile The mapping obtain from getProfilesFromSDK/getAllProfiles.
+	 * @return The key press map captured.
+	 */
+	public IBupEventMap captureMap(IBupEventMapProfile profile) {
+		synchronized(loadedKeyMap) {
+			IBupEventMap map = loadedKeyMap.get(profile);
+			if (map == null) {
+				try {
+					ButtonEventProfileListType settings = PIConfigXMLLoader.loadPiSettings(profile.getURI().toURL());
+					EList<ButtonEventProfileType> profileList = settings.getButtonEventProfile();
+					for (ButtonEventProfileType buttonProfileType : profileList) {
+						if (buttonProfileType.getProfileId().equals(profile.getProfileId())) {
+							map = new BupEventMap(buttonProfileType, profile);
+							loadedKeyMap.put(profile, map);
+						}
+					}
+				} catch (MalformedURLException e) {
+					GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.44") + profile.getURI()); //$NON-NLS-1$
+				} catch (IOException e) {
+					GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.45") + profile.getURI()); //$NON-NLS-1$
+				}
+				if (map == null) {
+					GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.42") + profile); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			} else {
+				((BupEventMap)map).upCheckOutCount();
+			}
+			return map;
+		}
+	}
+	
+	/**
+	 * Release the key mapping when the UID is going away
+	 * 
+	 * @param uid The UID for the instance you want to release key mapping binding
+	 */
+	public void releaseMap(IBupEventMap map) {
+		synchronized(loadedKeyMap) {
+			if (map != null) {
+				((BupEventMap)map).downCheckOutCount();
+				if (((BupEventMap)map).getCheckOutCount() <= 0) {
+					loadedKeyMap.remove(((BupEventMap)map).getProfile());
+				}
+			}
+		}
+	}
+	
+	public void addToWorkspace (String profileId) {
+		
+		try {
+			ButtonEventProfileListType workspace_settings = PIConfigXMLLoader.loadPiSettings(WORKSPACE_PREF_KEY_MAP_URI.toURL());
+			EList<ButtonEventProfileType> workspace_profileList = workspace_settings.getButtonEventProfile();
+			
+			ButtonEventProfileType buttonEventProfileType = PIConfigFactory.eINSTANCE.createButtonEventProfileType();
+			buttonEventProfileType.setProfileId(profileId);
+			buttonEventProfileType.getMapping().clear();
+			
+			workspace_profileList.add(buttonEventProfileType);
+			// write back the model
+			PIConfigXMLLoader.writePiSettings(workspace_settings, WORKSPACE_PREF_KEY_MAP_URI.toURL());
+		} catch (MalformedURLException e) {
+			GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.47") + profileId); //$NON-NLS-1$
+		} catch (IOException e) {
+			GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.48") + profileId); //$NON-NLS-1$
+		}
+
+	}
+	
+	public void removeFromWorkspace (IBupEventMapProfile removedProfile) {
+		synchronized(loadedKeyMap) {
+			try {
+				ButtonEventProfileListType workspace_settings = PIConfigXMLLoader.loadPiSettings(WORKSPACE_PREF_KEY_MAP_URI.toURL());
+				EList<ButtonEventProfileType> workspace_profileList = workspace_settings.getButtonEventProfile();
+				// profile with the same ID will replace workspace pref
+				ButtonEventProfileType remove = null;
+				for (ButtonEventProfileType profile : workspace_profileList) {
+					if (profile.getProfileId().equals(removedProfile.getProfileId())) {
+						remove = profile;
+					}
+				}
+				if (remove != null) {
+					int i = workspace_profileList.indexOf(remove);
+					workspace_profileList.remove(i);
+				}
+				// write back the model
+				PIConfigXMLLoader.writePiSettings(workspace_settings, WORKSPACE_PREF_KEY_MAP_URI.toURL());
+			} catch (MalformedURLException e) {
+				GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.49") + removedProfile.getProfileId()); //$NON-NLS-1$
+			} catch (IOException e) {
+				GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.50") + removedProfile.getProfileId()); //$NON-NLS-1$
+			}
+		}
+	}
+	
+	public void commitEditToWorkspace (IBupEventMap map) {
+		synchronized(loadedKeyMap) {
+			try {
+				ButtonEventProfileListType workspace_settings = PIConfigXMLLoader.loadPiSettings(WORKSPACE_PREF_KEY_MAP_URI.toURL());
+				EList<ButtonEventProfileType> workspace_profileList = workspace_settings.getButtonEventProfile();
+
+				// profile with the same ID will replace workspace pref
+				ButtonEventProfileType replace = null;
+				for (ButtonEventProfileType profile : workspace_profileList) {
+					if (profile.getProfileId().equals(map.getProfile().getProfileId())) {
+						replace = profile;
+					}
+				}
+				if (replace != null) {
+					int i = workspace_profileList.indexOf(replace);
+					workspace_profileList.remove(i);
+					workspace_profileList.add(i, map.toEmfModel());
+				} else {
+					workspace_profileList.add(map.toEmfModel());
+				}
+				// write back the model
+				PIConfigXMLLoader.writePiSettings(workspace_settings, WORKSPACE_PREF_KEY_MAP_URI.toURL());
+			} catch (MalformedURLException e) {
+				GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.51") + map.getProfile().getProfileId()); //$NON-NLS-1$
+			} catch (IOException e) {
+				GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.52") + map.getProfile().getProfileId()); //$NON-NLS-1$
+			}
+		}
+	}
+	
+	public void importMergeToWorkspace (URI uri) {
+		try {
+			ButtonEventProfileListType workspace_settings = PIConfigXMLLoader.loadPiSettings(WORKSPACE_PREF_KEY_MAP_URI.toURL());
+			EList<ButtonEventProfileType> workspace_profileList = workspace_settings.getButtonEventProfile();
+			
+			ButtonEventProfileListType settings = PIConfigXMLLoader.loadPiSettings(uri.toURL());
+			EList<ButtonEventProfileType> profileList = settings.getButtonEventProfile();
+			
+			// profile with the same ID will replace workspace pref
+			while(profileList.size() > 0) {
+				ButtonEventProfileType replace = null;
+				for (ButtonEventProfileType profile : workspace_profileList) {
+					if (profile.getProfileId().equals(profileList.get(0).getProfileId())) {
+						replace = profile;
+					}
+				}
+				// containment == true in XML, profileList will remove the element
+				if (replace != null) {
+					int i = workspace_profileList.indexOf(replace);
+					workspace_profileList.remove(i);
+					workspace_profileList.add(i, profileList.get(0));
+				} else {
+					workspace_profileList.add(profileList.get(0));
+				}
+			}
+			// write back the model
+			PIConfigXMLLoader.writePiSettings(workspace_settings, WORKSPACE_PREF_KEY_MAP_URI.toURL());
+		} catch (MalformedURLException e) {
+			GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.53") + uri); //$NON-NLS-1$
+		} catch (IOException e) {
+			GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.54") + uri); //$NON-NLS-1$
+		}
+	}
+	
+	public void saveMap (URI uri, ArrayList<ButtonEventProfileType> mapList) {
+		ButtonEventProfileListType profileList = PIConfigFactory.eINSTANCE.createButtonEventProfileListType();
+		profileList.setButtonEventProfileVersion(new BigDecimal("1.0")); //$NON-NLS-1$
+		profileList.getButtonEventProfile().addAll(mapList);
+		try {
+			PIConfigXMLLoader.writePiSettings(profileList, uri.toURL());
+		} catch (MalformedURLException e) {
+			GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.56") + uri); //$NON-NLS-1$
+		} catch (IOException e) {
+			GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.57") + uri); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * @param uri
+	 * @return
+	 */
+	public ArrayList<IBupEventMapProfile> getOverLapWithWorkspace(URI uri) {
+		ArrayList<IBupEventMapProfile> result = new ArrayList<IBupEventMapProfile>();
+			
+		ArrayList<IBupEventMapProfile> uriProfiles = getProfilesFromURI(uri, null);
+		ArrayList<IBupEventMapProfile> workspaceProfiles = getProfilesFromWorkspacePref();
+		
+		for (IBupEventMapProfile workspaceProfile : workspaceProfiles) {
+			for (IBupEventMapProfile uriProfile : uriProfiles) {
+				if (workspaceProfile.getProfileId().equals(uriProfile.getProfileId())) {
+					result.add(workspaceProfile);
+				}
+			}
+		}
+		
+		return result;
+	}
+
+	/**
+	 * Read from global preference for profile selection
+	 * 
+	 * @return
+	 */
+	public IBupEventMapProfile getPrefSelectedProfile() {
+		IPreferenceStore store = ButtonPlugin.getBupPrefsStore();
+
+		String profileID = store.getString(BupPreferenceConstants.KEY_MAP_PROFILE_STRING);
+		
+		if (profileID != null) {
+			ArrayList<IBupEventMapProfile> profiles = getAllProfiles();
+			for (IBupEventMapProfile profile : profiles) {
+				if (profile.toString().equals(profileID)) {
+					return profile;
+				}
+			}
+		}
+
+		return DEFAULT_PROFILE;
+	}
+
+	/**
+	 * @param profile
+	 * @return
+	 */
+	public boolean canRemoveProfile(IBupEventMapProfile profile) {
+		return loadedKeyMap.get(profile) == null;
+	}
+
+	/**
+	 * @return
+	 */
+	public IBupEventMapProfile getLegacyProfile() {
+		return LEGACY_PROFILE;
+	}
+
+	/**
+	 * @return
+	 */
+	public IBupEventMapProfile getDefaultProfile() {
+		return DEFAULT_PROFILE;
+	}
+	
+	/**
+	 * @return
+	 */
+	public IBupEventMapProfile getTechViewProfile() {
+		return TECHVIEW_PROFILE;
+	}
+
+	/**
+	 * @return
+	 */
+	public IBupEventMapProfile getBuiltinS60Profile() {
+		return S60_PROFILE;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupMapSwitchAction.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.ide.ResourceUtil;
+
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+public class BupMapSwitchAction implements IObjectActionDelegate {
+	
+	// IDs defined in plugin.xml
+	public static final String BUP_MAP_SWITCH_POP_UP_ID = ButtonPlugin.PLUGIN_ID + ".BupMapSwitchAction"; //$NON-NLS-1$
+	
+	// private members
+	private ISelection selection;
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, org.eclipse.ui.IWorkbenchPart)
+	 */
+	public void setActivePart(IAction arg0, IWorkbenchPart arg1) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+	 */
+	public void run(IAction arg0) {
+		if (arg0.getId().equals(BUP_MAP_SWITCH_POP_UP_ID)){
+			handleBupMapSwitch();
+		}
+	}
+		
+	private void handleBupMapSwitch() {
+		if (selection != null && selection instanceof IStructuredSelection) {
+			Iterator iter = ((IStructuredSelection)selection).iterator();
+			while (iter.hasNext()) {
+				Object selectedItem = iter.next();
+				IResource selectedResource = getResourceFromObject(selectedItem);
+				if (selectedResource != null && selectedResource instanceof IFile) {
+					IEditorPart selectedEditorPart = ResourceUtil.findEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), (IFile) selectedResource);
+					if (selectedEditorPart != null) {
+						if (selectedEditorPart instanceof PIPageEditor) {
+							// found an opened editor instance
+							PIPageEditor selectedPIPageEditor = (PIPageEditor) selectedEditorPart;
+							PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().activate(selectedPIPageEditor);
+							ButtonPlugin.getDefault().switchMap();
+						} else {
+							GeneralMessages.showErrorMessage(Messages.getString("BupMapSwitchAction.notPIPageeditor")); //$NON-NLS-1$
+						}
+					} else {
+						// NPI file is not opened
+						try {
+							IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), (IFile) selectedResource);
+							// found an opened editor instance
+							PIPageEditor selectedPIPageEditor = (PIPageEditor) selectedEditorPart;
+							PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().activate(selectedPIPageEditor);
+							ButtonPlugin.getDefault().switchMap();
+						} catch (PartInitException e) {
+						}
+					}
+				}
+			}
+		}
+
+	}
+	
+	/**
+	 * Return the resource associated with an object.
+	 * @param element - object in question
+	 * @return associated resource if there is one
+	 */
+	private IResource getResourceFromObject(Object element) {
+		if (element instanceof IResource) {
+			return (IResource)element;
+		} else if (element instanceof IAdaptable) {
+			return (IResource)((IAdaptable)element).getAdapter(IResource.class);
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
+	 */
+	public void selectionChanged(IAction arg0, ISelection arg1) {
+		this.selection = arg1;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupSample.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSample;
+
+public class BupSample extends GenericSample {
+
+	private static final long serialVersionUID = -498083219245040352L;
+	
+	private int keyCode = 0;
+	private String label = null;
+	private String comment = null;
+	// version 1.3
+	private boolean labelModified = false;	// any one need to reset this should use resetLabelToMapDefault or declare a new sample
+	
+	public BupSample (long sampleTime, int code, IBupEventMap map) {
+		this.sampleSynchTime = sampleTime;
+		this.keyCode = code;
+		
+		// if event is touch event add labels for it.
+		if ( code == 69999 ) {
+			this.label = Messages.getString("BupSample.0"); //$NON-NLS-1$
+		}
+		else if ( code == 70000 ){
+			this.label = Messages.getString("BupSample.1"); //$NON-NLS-1$
+		}
+		else{
+			this.label = map.getLabel(code);
+		}
+		this.comment = null;
+		this.labelModified = false;
+	}
+	
+	public int getKeyCode() {
+		return keyCode;
+	}
+	
+	public void setLabel(String label) {
+		this.label = label;
+		this.labelModified = true;
+	}
+	
+	public String getLabel() {
+		return label;
+	}
+	
+	// insist on not exposing labelModified, use this for map switching and take care of modified flag
+	public void resetLabelToMapDefault(IBupEventMap map) {
+		label = map.getLabel(keyCode);
+		labelModified = false;
+	}
+
+	public void setComment(String comment) {
+		this.comment = comment;
+	}
+	
+	public String getComment() {
+		return this.comment;
+	}
+	
+	public boolean isLabelModified() {
+		return labelModified;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+public class BupTrace extends GenericSampledTrace
+{
+	
+	private static final long serialVersionUID = -2398791759386296139L;
+	
+	private double scale = 0.0;
+	private double min = 0.0;
+	private double max = 0.0;
+	private double synchValue = 0.0;
+
+	private transient BupTraceGraph[] graphs;
+	private transient IBupEventMap map;
+		
+	public GenericTraceGraph getTraceGraph(int graphIndex)
+	{
+		if (graphs == null) {
+			graphs = new BupTraceGraph[3];
+			
+			BupUpdater.getInstance().convertToLatest(this.samples);
+			
+			AnalysisInfoHandler handler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+			BupEventMapManager.getInstance().releaseMap(getCurrentBupMapInUse());
+			IBupEventMapProfile profile;
+			profile = ButtonPlugin.getDefault().getBupMapProfileFromInfoHandler(handler);
+			map = BupEventMapManager.getInstance().captureMap(profile);
+		}
+
+		if (   (graphIndex == PIPageEditor.THREADS_PAGE)
+			|| (graphIndex == PIPageEditor.BINARIES_PAGE)
+			|| (graphIndex == PIPageEditor.FUNCTIONS_PAGE)) {
+			if (graphs[graphIndex] == null)
+				graphs[graphIndex] = new BupTraceGraph(graphIndex, this);
+			return graphs[graphIndex];
+		}
+	
+		return null;
+	}
+
+	public double getScale()
+	{
+		return scale;
+	}
+
+	public double getMin()
+	{
+		return min;
+	}
+
+	public double getMax()
+	{
+		return max;
+	}
+
+	public double getSynchValue()
+	{
+		return synchValue;
+	}
+
+	public void setSynchValue(double aSynchValue)
+	{
+		synchValue = aSynchValue;
+	}
+
+	public void addSample(BupSample sample)
+	{
+		this.samples.add(sample);
+	}
+
+	public BupSample getBupSample(int number)
+	{
+		return (BupSample)this.samples.elementAt(number);
+	}
+
+	/**
+	 * @return
+	 */
+	public IBupEventMap getCurrentBupMapInUse() {
+		return map;
+	}
+	
+	public void setCurrentBupMapInUse(IBupEventMap newMap) {
+		map = newMap;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupTraceGraph.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,590 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Panel;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+
+import com.nokia.carbide.cpp.internal.pi.actions.SaveSamples;
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IContextMenu;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+public class BupTraceGraph extends GenericTraceGraph implements MouseMoveListener,
+																MouseListener,
+																IContextMenu
+{
+	/*
+	 * Draw button text in existing Address plugin panel
+	 *
+	 * For each button press, draw a line from the top to below the thread/binary/function start and end
+	 * indicators, but above the x-axis label that tells seconds
+	 */
+	
+	// whether to display events
+	private boolean display_events = true;
+
+	// constants used in drawing event: line coming down with a rectangle at the end and a name underneath
+	private static final int EVENT_TOPOFLINE    = 50;
+	private static final int EVENT_BOTTOMOFLINE = 30;
+	private static final int EVENT_RECTWIDTH    = 5;
+	private static final int EVENT_RECTHEIGHT   = 5;
+
+	private ArrayList<BupSample> matchingSamples;
+	private Button eventButtons[];
+	private boolean selectedEventButtons;
+	
+	// class to pass sample data to the save wizard
+    public class SaveSampleString implements ISaveSamples {
+    	boolean done = false;
+    	
+    	public SaveSampleString() {
+		}
+
+    	public String getData() {
+    		if (done)
+    			return null;
+    		
+			String returnString = getSampleString();
+			done = true;
+			return returnString;
+		}
+
+		public String getData(int size) {
+ 			return getData();
+		}
+
+		public int getIndex() {
+			return done ? 1 : 0;
+		}
+
+		public void clear() {
+			done = false;
+		}
+   }
+
+	/*
+	 * return the button samples selected in the interval 
+	 */
+	protected String getSampleString()
+	{
+		int startTime = (int) this.getSelectionStart();
+		int endTime   = (int) this.getSelectionEnd();
+		
+		Vector sampleVector = ((GenericSampledTrace) this.getTrace()).samples;
+		
+		int i = 0;
+		while (i < sampleVector.size() && ((BupSample) sampleVector.get(i)).sampleSynchTime < startTime)
+			i++;
+	
+		String returnString = Messages.getString("BupTraceGraph.saveSamplesHeading"); //$NON-NLS-1$
+
+		while (i < sampleVector.size() && ((BupSample) sampleVector.get(i)).sampleSynchTime <= endTime) {
+			BupSample sample = (BupSample) sampleVector.get(i);
+			returnString += sample.sampleSynchTime + "," + sample.getLabel() + ",\""; //$NON-NLS-1$ //$NON-NLS-2$
+
+			String comment = sample.getComment();
+			if (comment != null) {
+				for (int j = 0; j < comment.length(); j++) {
+					if (comment.charAt(j) == '"')
+						returnString += '"';
+					returnString += comment.charAt(j);
+				}
+			}
+			returnString += "\"\n"; //$NON-NLS-1$
+			i++;
+		}
+
+		return returnString;
+	}
+
+	protected void actionSaveSamples(ISaveSamples saveSamples)
+	{
+		new SaveSamples(saveSamples);
+	}
+
+	protected MenuItem getSaveSamplesItem(Menu menu, boolean enabled) {
+	    MenuItem saveSamplesItem = new MenuItem(menu, SWT.PUSH);
+
+		saveSamplesItem.setText(Messages.getString("BupTraceGraph.saveSamplesForInterval")); //$NON-NLS-1$
+		saveSamplesItem.setEnabled(enabled);
+		
+		if (enabled) {
+			saveSamplesItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+					saveEventSamples();
+				}
+			});
+		}
+	
+		return saveSamplesItem;
+	}
+
+	public BupTraceGraph(int graphIndex, BupTrace trace)
+	{
+		super(trace);
+		this.graphIndex = graphIndex;
+	}
+
+	public void paint(Panel panel, Graphics graphics)
+	{
+		if (!display_events)
+			return;
+
+		Enumeration samples = ((GenericSampledTrace)this.getTrace()).samples.elements();
+		graphics.setForegroundColor(ColorConstants.red);
+		double scale = this.getScale();
+		int height = this.getVisualSize().height;
+		String eventName;
+
+		while (samples.hasMoreElements())
+		{
+			BupSample sa = (BupSample)samples.nextElement();
+			int x = (int)(sa.sampleSynchTime/scale);
+
+			graphics.setForegroundColor(ColorConstants.red);
+			graphics.drawLine(x, height - EVENT_TOPOFLINE, x, height - EVENT_BOTTOMOFLINE);
+
+			// center the text under vertical line
+			eventName = sa.getLabel();
+
+			graphics.setFont(PIPageEditor.helvetica_8);
+
+			GC gc = new GC(PIPageEditor.currentPageEditor().getSite().getShell());
+			Point point = gc.stringExtent(eventName);
+			gc.dispose();
+
+			if (sa.isLabelModified()) {
+				graphics.setForegroundColor(ColorConstants.blue);
+			} else {
+				graphics.setForegroundColor(ColorConstants.red);
+			}
+			graphics.drawString(eventName, x - (point.x / 2), height - EVENT_BOTTOMOFLINE + 3 + EVENT_RECTHEIGHT);
+
+			// events with comments will have blue rectangles; otherwise, red triangles
+			if ((sa.getComment() != null) && (!sa.getComment().equals(""))) //$NON-NLS-1$
+			{
+				graphics.setForegroundColor(ColorConstants.blue);
+				graphics.setBackgroundColor(ColorConstants.blue);
+			}
+			else
+			{
+				graphics.setBackgroundColor(ColorConstants.red);
+			}
+			graphics.drawLine(x , height - EVENT_BOTTOMOFLINE + 1, x, height - EVENT_BOTTOMOFLINE + 2);
+			graphics.fillRectangle(x - (EVENT_RECTWIDTH / 2), height - EVENT_BOTTOMOFLINE + 3,
+									EVENT_RECTWIDTH, EVENT_RECTHEIGHT);
+		}
+	}
+
+	public void repaint()
+	{
+	}
+
+	public void refreshDataFromTrace()
+	{
+	}
+
+	public void action(String action)
+	{
+		// do/don't show events in graph
+		if (   action.equals("button_events_on") //$NON-NLS-1$
+			|| action.equals("button_events_off")) //$NON-NLS-1$
+  		{
+  			this.display_events = action.equals(Messages.getString("BupTraceGraph.button.events.on")); //$NON-NLS-1$
+  			this.parentComponent.repaintComponent();
+  		} else if (action.equals("button_map_switch")){ //$NON-NLS-1$
+  			this.parentComponent.repaintComponent();
+  		}
+  	}
+
+	public void mouseMove(MouseEvent me)
+//	public void mouseHover(MouseEvent me)
+	{
+		if (!display_events)
+			return;
+
+		long x = me.x;
+		long y = me.y;
+
+		int height = this.getVisualSize().height;
+
+		// make sure we're in the right area of the graph window
+		if ((y < height - EVENT_BOTTOMOFLINE) || (y > height - EVENT_BOTTOMOFLINE + EVENT_RECTHEIGHT + 2))
+			return;
+
+		Enumeration samples = ((GenericSampledTrace) this.getTrace()).samples.elements();
+		double scale = this.getScale();
+		
+//		x += ((FigureCanvas)me.getSource()).getViewport().getViewLocation().x;
+
+		String tooltip = ""; //$NON-NLS-1$
+
+		while (samples.hasMoreElements())
+		{
+			BupSample sample = (BupSample)samples.nextElement();
+			long xSample = (long)(sample.sampleSynchTime/scale + 0.5);
+			
+			// samples are in timestamp order, so stop when xSample + EVENT_RECTWIDTH is too high
+			if (x < xSample - EVENT_RECTWIDTH)
+				break;
+
+			if ((x >= xSample - EVENT_RECTWIDTH) && (x <= xSample + EVENT_RECTWIDTH))
+			{
+				String parsedName = sample.getLabel();
+				if (!tooltip.equals("")) //$NON-NLS-1$
+					tooltip += Messages.getString("BupTraceGraph.newline"); //$NON-NLS-1$
+				tooltip += Messages.getString("BupTraceGraph.tooltip1") + parsedName + Messages.getString("BupTraceGraph.tooltip2") + sample.sampleSynchTime/1000.0 + Messages.getString("BupTraceGraph.tooltip3"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				if (sample.getComment() != null)
+					 tooltip += Messages.getString("BupTraceGraph.tooltip4") + sample.getComment(); //$NON-NLS-1$
+			}
+		}
+		
+		if (!tooltip.equals("")) //$NON-NLS-1$
+			((FigureCanvas)me.getSource()).setToolTipText(tooltip);
+	}
+
+	public void mouseDoubleClick(MouseEvent me)
+	{
+		if (!display_events)
+			return;
+
+		long x = me.x;
+		long y = me.y;
+
+		int height = this.getVisualSize().height;
+
+		// make sure we're in the right area of the graph window
+		if ((y < height - EVENT_BOTTOMOFLINE) || (y > height - EVENT_BOTTOMOFLINE + EVENT_RECTHEIGHT + 2))
+			return;
+
+		// repaint if the name or comment changes
+		boolean redraw = false;
+
+		Enumeration samples = ((GenericSampledTrace)this.getTrace()).samples.elements();
+		double scale = this.getScale();
+
+		// unlike mouseMove, the x coordinate is not relative to the FigureCanvas
+		x += ((FigureCanvas)me.getSource()).getViewport().getViewLocation().x;
+
+		matchingSamples = new ArrayList<BupSample>();
+		
+		while (samples.hasMoreElements())
+		{
+			BupSample sample = (BupSample)samples.nextElement();
+			long xSample = (long)(sample.sampleSynchTime/scale + 0.5);
+
+			// samples are in timestamp order, so stop when xSample + EVENT_RECTWIDTH is too high
+			if (x < xSample - EVENT_RECTWIDTH)
+				break;
+
+			if ((x >= xSample - EVENT_RECTWIDTH) && (x <= xSample + EVENT_RECTWIDTH))
+			{
+				matchingSamples.add(sample);
+			}
+		}
+
+		if (matchingSamples.size() == 0)
+			return;
+	
+		// let them change some information
+		Display display = PIPageEditor.currentPageEditor().getEditorSite().getShell().getDisplay();
+
+		GridData gridData;
+
+		if (matchingSamples.size() > 1) {
+			selectedEventButtons = false;
+
+			// query for which of several to display
+			Shell shell = new Shell(display, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+			shell.setText(Messages.getString("BupTraceGraph.chooseEvents")); //$NON-NLS-1$
+			shell.setLayout(new GridLayout(2, true));
+			final Shell shellFinal = shell;
+
+			Label label = new Label(shell, SWT.LEFT);
+			label.setText(Messages.getString("BupTraceGraph.selectEvents")); //$NON-NLS-1$
+			label.setFont(PIPageEditor.helvetica_10);
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			gridData.horizontalSpan = 2;
+			label.setLayoutData(gridData);
+
+			eventButtons = new Button[matchingSamples.size()];
+
+			for (int i = 0; i < matchingSamples.size(); i++) {
+				eventButtons[i] = new Button(shell, SWT.CHECK);
+				gridData = new GridData(GridData.FILL_HORIZONTAL);
+				gridData.horizontalSpan = 2;
+				eventButtons[i].setLayoutData(gridData);
+				
+				BupSample sample = matchingSamples.get(i);
+				
+				String parsedName = sample.getLabel();
+				eventButtons[i].setText(Messages.getString("BupTraceGraph.buttonString1") + parsedName + Messages.getString("BupTraceGraph.buttonString2") + sample.sampleSynchTime/1000d + Messages.getString("BupTraceGraph.buttonString3")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				eventButtons[i].setFont(PIPageEditor.helvetica_10);
+			}
+			
+			// create the OK button
+			Button okButton = new Button(shell, SWT.NONE);
+			okButton.setText(Messages.getString("BupTraceGraph.ok")); //$NON-NLS-1$
+			gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
+			okButton.setLayoutData(gridData);
+
+			// add the listener(s)
+			okButton.addSelectionListener(new SelectionListener(){
+				public void widgetSelected(SelectionEvent e) {
+					selectedEventButtons = true;
+					for (int i = matchingSamples.size() - 1; i >= 0; i--)
+						if (eventButtons[i].getSelection() == false)
+							matchingSamples.remove(i);
+
+					shellFinal.close();
+				}
+
+				public void widgetDefaultSelected(SelectionEvent e) {
+					widgetSelected(e);
+				}
+			});
+
+			// create the Cancel button
+			Button cancelButton = new Button(shell, SWT.NONE);
+			cancelButton.setText(Messages.getString("BupTraceGraph.cancel")); //$NON-NLS-1$
+			gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
+			cancelButton.setLayoutData(gridData);
+
+			// add the listener(s)
+			cancelButton.addSelectionListener(new SelectionListener(){
+				public void widgetSelected(SelectionEvent e) {
+					shellFinal.close();
+				}
+
+				public void widgetDefaultSelected(SelectionEvent e) {
+					widgetSelected(e);
+				}
+			});
+
+			shell.pack();
+			shell.open();
+
+			while (!shell.isDisposed()) {
+				if (!display.readAndDispatch()) {
+					display.sleep();
+				}
+			}
+
+			if (selectedEventButtons == false)
+				matchingSamples.clear();
+		}
+
+		IBupEventMap map = ((BupTrace)this.getTrace()).getCurrentBupMapInUse();
+		for (int i = 0; i < matchingSamples.size(); i++)
+		{
+			BupSample sample = matchingSamples.get(i);
+			
+			String enumString = map.getEnum(sample.getKeyCode());
+
+			BupEventDialog eventDialog = new BupEventDialog(PIPageEditor.currentPageEditor().getEditorSite().getShell(), Messages.getString("BupTraceGraph.buttonDialog"), //$NON-NLS-1$
+														sample.getKeyCode(), enumString, sample.getLabel(), sample.getComment(), false, sample.sampleSynchTime);
+			eventDialog.open();
+
+			if (   (eventDialog.getNewName() != null)
+				&& (!eventDialog.getNewName().equals(sample.getLabel()))) {
+				sample.setLabel(eventDialog.getNewName());
+				redraw = true;
+			}
+
+			if (   (eventDialog.getNewComment() != null)
+				&& (!eventDialog.getNewComment().equals(sample.getComment()))) {
+				sample.setComment(eventDialog.getNewComment());
+				redraw = true;
+			}
+			
+			if (eventDialog.getNewSamePropagate()) {
+				Vector<BupSample> allSamples = (Vector<BupSample>)((GenericSampledTrace)this.getTrace()).samples;
+				for (BupSample currentSample : allSamples) {
+					if (currentSample.getKeyCode() == sample.getKeyCode()) {
+						currentSample.setLabel(eventDialog.getNewName());
+					}
+				}
+				redraw = true;
+			}
+		}
+
+		if (redraw)
+			((FigureCanvas)me.getSource()).redraw();
+	}
+
+	public void mouseDragged(MouseEvent me) {}
+
+	public void mouseEntered(MouseEvent me) {}
+
+	public void mouseExited(MouseEvent me) {}
+
+	public void mouseDown(MouseEvent me) {}
+
+	public void mouseUp(MouseEvent me) {}
+
+	public static boolean openButtonDialog(int buttonIndex)
+	{
+		boolean redraw = false;
+
+		BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
+
+		if (buttonIndex > bupTrace.samples.size() || buttonIndex < 1)
+			return false;
+
+		BupSample sample = bupTrace.getBupSample(buttonIndex - 1);
+
+		// let them change some information
+		Display display = PIPageEditor.currentPageEditor().getEditorSite().getShell().getDisplay();
+
+		GridData gridData;
+
+		IBupEventMap map = bupTrace.getCurrentBupMapInUse();
+		String enumString = map.getEnum(sample.getKeyCode());
+
+		BupEventDialog eventDialog = new BupEventDialog(PIPageEditor.currentPageEditor().getEditorSite().getShell(), Messages.getString("BupTraceGraph.buttonDialog"), //$NON-NLS-1$
+													sample.getKeyCode(), enumString, sample.getLabel(), sample.getComment(), false, sample.sampleSynchTime);
+		eventDialog.open();
+
+		if (   (eventDialog.getNewName() != null)
+			&& (!eventDialog.getNewName().equals(sample.getLabel()))) {
+			sample.setLabel(eventDialog.getNewName());
+			redraw = true;
+		}
+
+		if (   (eventDialog.getNewComment() != null)
+			&& (!eventDialog.getNewComment().equals(sample.getComment()))) {
+			sample.setComment(eventDialog.getNewComment());
+			redraw = true;
+		}
+			
+		if (eventDialog.getNewSamePropagate()) {
+			Vector<BupSample> allSamples = (Vector<BupSample>)bupTrace.samples;
+			for (BupSample currentSample : allSamples) {
+				if (currentSample.getKeyCode() == sample.getKeyCode()) {
+					currentSample.setLabel(eventDialog.getNewName());
+				}
+			}
+			redraw = true;
+		}
+		
+		return true;
+	}
+
+	public void addContextMenuItems(Menu menu, MouseEvent me)
+	{
+		if (!display_events)
+			return;
+
+		long x = me.x;
+		long y = me.y;
+
+		int height = this.getVisualSize().height;
+
+		// make sure we're in the right area of the graph window
+		if ((y < height - EVENT_BOTTOMOFLINE) || (y > height - EVENT_BOTTOMOFLINE + EVENT_RECTHEIGHT + 2))
+			return;
+
+		Enumeration samples = ((GenericSampledTrace) this.getTrace()).samples.elements();
+		double scale = this.getScale();
+
+		boolean found = false;
+
+		// unlike mouseMove, the x coordinate is not relative to the FigureCanvas
+		x += ((FigureCanvas)me.getSource()).getViewport().getViewLocation().x;
+
+		while (samples.hasMoreElements())
+		{
+			BupSample sample = (BupSample)samples.nextElement();
+			long xSample = (long)(sample.sampleSynchTime/scale + 0.5);
+
+			// samples are in timestamp order, so stop when xSample + EVENT_RECTWIDTH is too high
+			if (x < xSample - EVENT_RECTWIDTH)
+				break;
+
+			if ((x >= xSample - EVENT_RECTWIDTH) && (x <= xSample + EVENT_RECTWIDTH))
+			{
+				found = true;
+				break;
+			}
+		}
+
+		if (!found)
+			return;
+
+		new MenuItem(menu, SWT.SEPARATOR);
+
+		final MouseEvent meFinal = me;
+
+		MenuItem changeEventItem = new MenuItem(menu, SWT.PUSH);
+		changeEventItem.setText(Messages.getString("BupTraceGraph.changeEvent")); //$NON-NLS-1$
+		changeEventItem.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				mouseDoubleClick(meFinal);
+			}
+		});
+
+		int startTime = (int) this.getSelectionStart();
+		int endTime   = (int) this.getSelectionEnd();
+
+		// save raw samples
+		Vector sampleVector = ((GenericSampledTrace) this.getTrace()).samples;
+		
+		int i = 0;
+		while (i < sampleVector.size() && ((BupSample) sampleVector.get(i)).sampleSynchTime < startTime)
+			i++;
+		
+		// enable if we have at least one event in the interval
+		getSaveSamplesItem(menu, (i < sampleVector.size() && ((BupSample) sampleVector.get(i)).sampleSynchTime <= endTime));
+	}
+	
+	public void saveEventSamples() {
+    	SaveSampleString saveSampleString = new SaveSampleString();
+    	actionSaveSamples(saveSampleString); //$NON-NLS-1$
+	}
+
+	public void paintLeftLegend(FigureCanvas figureCanvas, GC gc) {
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupTraceParser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.Parser;
+import com.nokia.carbide.cpp.pi.importer.SampleImporter;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
+
+
+public class BupTraceParser extends Parser
+{
+	private BupSample[] traceData;	
+	private boolean debug = false;
+
+	public BupTraceParser() throws Exception
+	{
+	}
+		
+	public ParsedTraceData parse(File file) throws Exception 
+	{
+		if (!file.exists() || file.isDirectory())
+		{
+			throw new Exception(Messages.getString("BupTraceParser.unableToOpenTrace")); //$NON-NLS-1$
+		}
+		
+		Vector<BupSample> intermediateTraceData = new Vector<BupSample>();
+		IBupEventMap map = null;
+		try 
+		{
+			FileInputStream fis = new FileInputStream(file);
+			byte[] data = new byte[(int)file.length()];
+			fis.read(data);
+			
+			this.traceVersion = this.getVersion(data);
+			System.out.println(Messages.getString("BupTraceParser.versionTitle") + this.traceVersion); //$NON-NLS-1$
+			if (traceVersion.indexOf("V1.20") == -1) //$NON-NLS-1$
+			{
+			    System.out.println(Messages.getString("BupTraceParser.unsupportedVersion") + this.traceVersion); //$NON-NLS-1$
+			    fis.close();
+			    return null;
+			}
+			
+			ByteArrayInputStream bais = new ByteArrayInputStream(data);
+			DataInputStream dis = new DataInputStream(bais);
+			
+			// read the length of the header
+			int length = dis.readByte();
+			// skip the header
+			for (int i = 0; i < length; i++)
+				dis.readByte();
+			
+			int keyCode = 0;
+			long sampleTime = 0;
+			long sampleCount = 0;
+			
+			SampleImporter sampleImporter = SampleImporter.getInstance();
+			IBupEventMapProfile profileForParsing = null;
+			String sdkId = sampleImporter.getBupMapSymbianSDKId();
+			if (sdkId != null && !sdkId.equals("")) { //$NON-NLS-1$
+				ISymbianSDK sdk = SDKCorePlugin.getSDKManager().getSDK(sdkId, true);
+				ArrayList<IBupEventMapProfile> profiles = BupEventMapManager.getInstance().getProfilesFromSDK(sdk);
+				for (IBupEventMapProfile profile : profiles) {
+					if (profile.getProfileId().equals(sampleImporter.getBupMapProfileId())) {
+						profileForParsing = profile;
+					}
+				}
+			} else if (sampleImporter.isBupMapIsWorkspace()) {
+				ArrayList<IBupEventMapProfile> profiles = BupEventMapManager.getInstance().getProfilesFromWorkspacePref();
+				for (IBupEventMapProfile profile : profiles) {
+					if (profile.getProfileId().equals(sampleImporter.getBupMapProfileId())) {
+						profileForParsing = profile;
+					}
+				}
+			} else {
+				ArrayList<IBupEventMapProfile> profiles = BupEventMapManager.getInstance().getProfilesFromBuiltin();
+				for (IBupEventMapProfile profile : profiles) {
+					if (profile.getProfileId().equals(sampleImporter.getBupMapProfileId())) {
+						profileForParsing = profile;
+					}
+				}
+			}
+			// fall back
+			if (profileForParsing == null) {
+				profileForParsing = BupEventMapManager.getInstance().getDefaultProfile();
+				GeneralMessages.showErrorMessage(Messages.getString("BupTraceParser.profile.cannot.load")); //$NON-NLS-1$
+			}
+			
+			map = BupEventMapManager.getInstance().captureMap(profileForParsing);
+			try
+			{
+				while(true)
+				{
+					keyCode = (int) readTUint(dis);
+					sampleTime = readTUint(dis);
+					sampleCount++;
+					BupSample sample = new BupSample(sampleTime, keyCode, map);
+
+					intermediateTraceData.add(sample);
+//					System.out.println("Keycode: " + keyCode + " sampletime: " + sampleTime);
+				}
+			}
+			catch (EOFException eof)
+			{
+				//return;
+			}
+			catch (Exception e)
+			{
+				GeneralMessages.showErrorMessage(Messages.getString("BupTraceParser.errorReadingTraceFile")); //$NON-NLS-1$
+				throw e;				
+			}
+			BupEventMapManager.getInstance().releaseMap(map);
+		} catch (Exception e)
+		{
+			BupEventMapManager.getInstance().releaseMap(map);
+			GeneralMessages.showErrorMessage(Messages.getString("BupTraceParser.errorReadingTraceFile")); //$NON-NLS-1$
+			throw e;				
+		} finally {
+			BupEventMapManager.getInstance().releaseMap(map);
+		}
+	
+		if (debug)
+			System.out.println(Messages.getString("BupTraceParser.traceFileParsed") + intermediateTraceData.size()); //$NON-NLS-1$
+		
+		// all samples have been parsed
+		this.traceData = new BupSample[intermediateTraceData.size()];
+		
+		// store the trace data into an array
+		intermediateTraceData.toArray(this.traceData);
+		
+		ParsedTraceData ptd = new ParsedTraceData();
+		ptd.traceData = this.getTrace();
+		return ptd;
+	}
+	
+	private String getVersion(byte[] data)
+	{
+		int length = data[0];
+
+		String ver = Messages.getString("BupTraceParser.unknown"); //$NON-NLS-1$
+		String verString = new String(data, 1, length);
+		if (debug) System.out.println(Messages.getString("BupTraceParser.version") + verString); //$NON-NLS-1$
+		
+		if (verString.indexOf("Bappea") != -1) //$NON-NLS-1$
+			if (verString.indexOf("BUP") != -1) //$NON-NLS-1$
+			{
+				int index = verString.indexOf("_"); //$NON-NLS-1$
+				ver = verString.substring(index+1,length);
+				
+			}
+		return ver;		  			
+	}		
+	
+	private long readTUint(DataInputStream dis) throws Exception
+	{
+		long result = dis.readUnsignedByte();
+		result += dis.readUnsignedByte() << 8;
+		result += dis.readUnsignedByte() << 16;
+		result += dis.readUnsignedByte() << 24;
+		return result;
+	}
+	
+	private GenericTrace getTrace()
+	{
+		BupTrace trace = new BupTrace();
+		for (int i = 0; i < traceData.length; i++)
+		{
+			trace.addSample(this.traceData[i]);
+		}
+		return trace;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/BupUpdater.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import java.util.TreeMap;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.CusSample;
+import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
+import com.nokia.carbide.cpp.internal.pi.test.PIAnalyser;
+
+
+public class BupUpdater {
+	
+	static private BupUpdater instance = null;
+	private static TreeMap<String, Integer> OneOneHexToStringMap = new TreeMap<String, Integer>();
+	
+	public static BupUpdater getInstance() {
+		if (instance == null) {
+			instance = new BupUpdater();
+		}
+		return instance;
+	}
+	
+	private BupUpdater() {
+		// singleton
+		
+		String nonPrintable[] = {
+				Messages.getString("BupUpdater.0"), Messages.getString("BupUpdater.1"), Messages.getString("BupUpdater.2"), Messages.getString("BupUpdater.3"), Messages.getString("BupUpdater.4"), Messages.getString("BupUpdater.5"), Messages.getString("BupUpdater.6"), Messages.getString("BupUpdater.7"), Messages.getString("BupUpdater.8"), Messages.getString("BupUpdater.9"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$
+				Messages.getString("BupUpdater.10"), Messages.getString("BupUpdater.11"), Messages.getString("BupUpdater.12"), Messages.getString("BupUpdater.13"), Messages.getString("BupUpdater.14"), Messages.getString("BupUpdater.15"), Messages.getString("BupUpdater.16"), Messages.getString("BupUpdater.17"), Messages.getString("BupUpdater.18"), Messages.getString("BupUpdater.19"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$
+				Messages.getString("BupUpdater.20"), Messages.getString("BupUpdater.21"), Messages.getString("BupUpdater.22"), Messages.getString("BupUpdater.23"), Messages.getString("BupUpdater.24"), Messages.getString("BupUpdater.25"), Messages.getString("BupUpdater.26"), Messages.getString("BupUpdater.27"), Messages.getString("BupUpdater.28"), Messages.getString("BupUpdater.29"), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$
+				Messages.getString("BupUpdater.30"), Messages.getString("BupUpdater.31"), Messages.getString("BupUpdater.32") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			};
+		for (int i = 0; i < 33; i++) {
+			OneOneHexToStringMap.put(nonPrintable[i], i);
+		}
+		for (int i = 33; i < 127; i++) {
+			OneOneHexToStringMap.put(Character.toString ((char) i), i);
+		}
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.33"), 127); //$NON-NLS-1$
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.34"), 63495);	 //$NON-NLS-1$
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.35"), 63496);	 //$NON-NLS-1$
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.36"), 63497);	 //$NON-NLS-1$
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.37"), 63498); //$NON-NLS-1$
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.38"), 63499);	 //$NON-NLS-1$
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.39"), 63554); //$NON-NLS-1$
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.40"), 63555); //$NON-NLS-1$
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.41"), 63557);	 //$NON-NLS-1$
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.42"), 63570); //$NON-NLS-1$
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.43"), 63586);		 //$NON-NLS-1$
+		OneOneHexToStringMap.put(Messages.getString("BupUpdater.44"), 63587); //$NON-NLS-1$
+
+	}
+	
+	public void convertToLatest(Vector samples) {
+		String fileVersion = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler().getFileVersion();
+		float version = 0;
+		try  {
+			version = Float.parseFloat(fileVersion);
+		} catch (NumberFormatException e) {
+			version = -1;
+		}
+
+		if (!fileVersion.equals(PIAnalyser.NPIFileFormat)) {		
+			
+			if (   fileVersion.startsWith(com.nokia.carbide.cpp.internal.pi.test.Messages.getString("AnalysisInfoHandler.unknownFileVersion")) //$NON-NLS-1$
+					|| fileVersion.startsWith(com.nokia.carbide.cpp.internal.pi.test.Messages.getString("AnalysisInfoHandler.unknown")) //$NON-NLS-1$
+					|| version <= Float.parseFloat("1.0")) //$NON-NLS-1$ // do not externalize this version number
+			{
+				NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler().setFileVersion(PIAnalyser.NPIFileFormat);
+				Vector <BupSample> bupSamples = new Vector <BupSample>();
+				// set additional info on file to proper profile
+				AnalysisInfoHandler handler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+				ButtonPlugin.getDefault().setBupMapProfileToInfoHandler(handler, BupEventMapManager.getInstance().getLegacyProfile());
+				IBupEventMap map = BupEventMapManager.getInstance().captureMap(BupEventMapManager.getInstance().getLegacyProfile());
+				for (int i = 0; i < samples.size(); i++)
+				{
+					CusSample sample = (CusSample)samples.elementAt(i);
+					BupSample bupSample = convertFromOneZeroOrBefore(sample, map);
+					bupSamples.add(bupSample);
+				}
+				BupEventMapManager.getInstance().releaseMap(map);
+				samples.clear();
+				samples.addAll(bupSamples);
+			} else if (version <= Float.parseFloat("1.1")) {	//$NON-NLS-1$	// do not externalize this version number
+				// 1.2 introduce BupSample instead of using CusSample, do conversion for any file lower than this
+				NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler().setFileVersion(PIAnalyser.NPIFileFormat);
+				Vector <BupSample> bupSamples = new Vector <BupSample>();
+				// set additional info on file to proper profile
+				AnalysisInfoHandler handler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+				ButtonPlugin.getDefault().setBupMapProfileToInfoHandler(handler, BupEventMapManager.getInstance().getLegacyProfile());
+				IBupEventMap map = BupEventMapManager.getInstance().captureMap(BupEventMapManager.getInstance().getLegacyProfile());
+				for (int i = 0; i < samples.size(); i++)
+				{
+					CusSample cusSample = (CusSample) samples.elementAt(i);
+					BupSample bupSample = convertFromOneOne(cusSample, map);
+					bupSamples.add(bupSample);
+				}
+				BupEventMapManager.getInstance().releaseMap(map);
+				samples.clear();
+				samples.addAll(bupSamples);
+			} else if (version <= Float.parseFloat("1.2")) {	//$NON-NLS-1$	// do not externalize this version number
+				// 1.3 introduce isLabelModified
+				Vector <BupSample> bupSamples = new Vector <BupSample>();
+				AnalysisInfoHandler handler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+				// 2.0 M1 does not have current profile saved yet, reset to default
+				IBupEventMapProfile profile = ButtonPlugin.getDefault().getBupMapProfileFromInfoHandler(handler);
+				ButtonPlugin.getDefault().setBupMapProfileToInfoHandler(handler, profile);
+				IBupEventMap map = BupEventMapManager.getInstance().captureMap(profile);
+				for (int i = 0; i < samples.size(); i++)
+				{
+					BupSample bupSample = (BupSample) samples.elementAt(i);
+					bupSamples.add(convertFromOneTwo(bupSample, map));
+				}
+				BupEventMapManager.getInstance().releaseMap(map);
+				samples.clear();
+				samples.addAll(bupSamples);
+			}
+		}		
+	}
+	
+	
+	// 1.0 or before
+	// base on CustSample
+	// CustSample.name:
+	// unmodified name = hex string of corresponding key code e.g. 1 button is "49"
+	// modified name = label string typed
+	// CustSample.comment
+	
+
+	public BupSample convertFromOneZeroOrBefore(CusSample oldSample, IBupEventMap map)
+	{
+		int hexCode = 0;
+		BupSample bupSample = null;
+	    try {
+	    	// 1.0 or before save the hex string of corresponding key code e.g. 1 button is "49"
+	    	if (oldSample.name == null) {
+		    	bupSample = new BupSample(oldSample.sampleSynchTime, 0, map);
+		    	bupSample.setLabel(""); //$NON-NLS-1$
+	    	} else  {
+		    	hexCode = Integer.parseInt(oldSample.name);
+		    	bupSample = new BupSample(oldSample.sampleSynchTime, hexCode, map);	    		
+	    	}
+	    } catch (NumberFormatException exc) {
+	    	// a modified label with hexcode zero as we cannot recover that with 1.0
+	    	bupSample = new BupSample(oldSample.sampleSynchTime, 0, map);
+	    	bupSample.setLabel(oldSample.name);
+		}
+	    bupSample.setComment(oldSample.comment);
+	    return bupSample;
+	}	
+	
+	// 1.1
+	// base on CustSample
+	// CustSample.name:
+	// 0-33		ASCII name shorthand
+	// 33-126	printable ASCII char
+	// 127		DEL
+	// 128-		hex string for corresponding key
+	// CustSample.comment
+	public BupSample convertFromOneOne(CusSample oldSample, IBupEventMap map) {
+		Integer keyCode = 0;
+		keyCode = OneOneHexToStringMap.get(oldSample.name);
+		if (keyCode == null) {
+			try {
+				keyCode = Integer.parseInt(oldSample.name);
+			} catch (NumberFormatException e) {
+				// it may be just a label
+			}
+		}
+		BupSample bupSample = new BupSample(oldSample.sampleSynchTime, keyCode != null ? keyCode : 0, map);
+		if (keyCode == null) {
+			// this is a modified key label
+			bupSample.setLabel(oldSample.name);
+		}
+		bupSample.setComment(oldSample.comment);
+		return bupSample;
+	}
+
+	// 1.2
+	// base on BupSample
+	// BupSample.keyCode: hex key code of event
+	// BupSample.label: label to display
+	// BupSample.comment: comment for label
+	public BupSample convertFromOneTwo(BupSample oldSample, IBupEventMap map) {
+		BupSample bupSample = new BupSample(oldSample.sampleSynchTime, oldSample.getKeyCode(), map);
+		bupSample.setComment(oldSample.getComment());
+		// retain modified label
+		if (!oldSample.getLabel().equals(map.getLabel(oldSample.getKeyCode()))) {
+			bupSample.setLabel(oldSample.getLabel());
+		}
+		return bupSample;
+	}
+
+	// 1.3
+	// base on BupSample(same serial UID, additional field)
+	// BupSample.keyCode: hex key code of event
+	// BupSample.label: label to display
+	// BupSample.comment: comment for label	
+	// BupSample.labelModified: label is modified, not from mapping
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/ButtonPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Vector;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.osgi.framework.BundleContext;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.button.ui.SwitchBupMapDialog;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IFinalizeTrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IViewMenu;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable;
+import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
+import com.nokia.carbide.cpp.internal.pi.test.IProvideTraceAdditionalInfo;
+import com.nokia.carbide.cpp.internal.pi.test.TraceAdditionalInfo;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.internal.pi.visual.GraphDrawRequest;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.importer.SampleImporter;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class ButtonPlugin extends AbstractPiPlugin
+			implements ITrace, IViewMenu, IEventListener, IClassReplacer, IVisualizable, IFinalizeTrace, IProvideTraceAdditionalInfo
+{
+	public static final String PLUGIN_ID = PIPageEditor.PI_ID + ".button";  //$NON-NLS-1$
+
+	// There will be three graphs - one each for editor pages 0, 1, 2
+	// This code may assume that page 0 has the threads graph, 1 the binaries, and 2 the functions
+	private final static int GRAPH_COUNT = 3;
+
+	//The shared instance.
+	private static ButtonPlugin plugin;
+	
+	private static IPreferenceStore prefsStore;
+	
+	private static void setPlugin(ButtonPlugin newPlugin)
+	{
+		plugin = newPlugin;
+	}
+
+	/**
+	 * The constructor.
+	 */
+	public ButtonPlugin() {
+		super();
+		setPlugin(this);
+	}
+
+	public Class getTraceClass() {
+		return BupTrace.class;
+	}
+
+	public Class getReplacedClass(String className)
+	{
+		if (   className.indexOf("com.nokia.carbide.cpp.pi.button.BupTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("com.nokia.carbide.pi.button.BupTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.model.BupTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.bupTracePlugin.BupTrace") != -1) //$NON-NLS-1$
+		{
+			return BupTrace.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.button.BupSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.button.BupSample") != -1 )//$NON-NLS-1$
+		{
+			return BupSample.class;
+		}
+		else
+			return null;
+	}
+	
+	public void initialiseTrace(GenericTrace trace) 
+	{
+		if (!(trace instanceof BupTrace))
+			return;
+
+		BupTrace bupTrace = (BupTrace)trace;
+		
+		NpiInstanceRepository.getInstance().activeUidAddTrace("com.nokia.carbide.cpp.pi.button", trace); //$NON-NLS-1$
+	}
+
+	public String getTraceName() {
+		return "Button"; //$NON-NLS-1$
+	}
+
+	public int getTraceId() {
+		return 7;
+	}
+
+	public ParsedTraceData parseTraceFile(File file) throws Exception 
+	{
+		try
+        {
+            BupTraceParser parser;
+            parser = new BupTraceParser();
+            return parser.parse(file);
+        } catch (Exception e)
+        {
+            e.printStackTrace();
+            throw e;
+        }
+	}
+
+	public MenuManager getViewOptionManager() {
+		// current tab
+		if (NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button") == null) //$NON-NLS-1$
+			return null;	// no trace, so no MenuManager
+
+		Action action;
+
+		Boolean showEvents = Boolean.TRUE;		// by default, show button press events
+
+		// if there is a value associated with the current Analyser tab, then use it
+		Object obj = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.button.show"); //$NON-NLS-1$
+		if ((obj != null) && (obj instanceof Boolean))
+			// retrieve the current value
+			showEvents = (Boolean)obj;
+		else
+			// set the initial value
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.button.show", showEvents); //$NON-NLS-1$
+
+		action = new Action(Messages.getString("ButtonPlugin.showEventsAction"), Action.AS_CHECK_BOX) { //$NON-NLS-1$
+			public void run() {
+				if (this.isChecked())
+					receiveSelectionEvent("button_events_on"); //$NON-NLS-1$
+				else
+					receiveSelectionEvent("button_events_off"); //$NON-NLS-1$
+			}
+		};
+		action.setChecked(showEvents);
+		action.setToolTipText(Messages.getString("ButtonPlugin.showEventsTooltip")); //$NON-NLS-1$
+		PIPageEditor.currentMenuManager().add(action);
+
+		action = new Action("Apply New Key Press Profile", Action.AS_PUSH_BUTTON) {	//$NON-NLS-1$
+			public void run() {
+				switchMap();
+			}
+		};
+		action.setChecked(showEvents);
+		action.setToolTipText(Messages.getString("ButtonPlugin.applyProfile")); //$NON-NLS-1$
+		PIPageEditor.currentMenuManager().add(action);
+
+		return PIPageEditor.currentMenuManager();
+	}
+	
+	public void receiveEvent(String actionString, Event event) 
+	{
+		if (   actionString.equals("button_events_on")  //$NON-NLS-1$
+			|| actionString.equals("button_events_off")	//$NON-NLS-1$
+			|| actionString.equals("button_map_switch")) //$NON-NLS-1$
+	  	{
+			BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
+			
+			if (bupTrace == null)
+				return;
+
+	  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.THREADS_PAGE)).action(actionString);	
+	  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.BINARIES_PAGE)).action(actionString);	
+	  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).action(actionString);	
+	  	}
+	}
+
+	public void receiveSelectionEvent(String actionString) 
+	{
+		if (actionString == null)
+			return;
+		
+		int currentPage = PIPageEditor.currentPageIndex();
+
+		if (   (currentPage != PIPageEditor.THREADS_PAGE)
+			&& (currentPage != PIPageEditor.BINARIES_PAGE)
+			&& (currentPage != PIPageEditor.FUNCTIONS_PAGE))
+			  return;
+
+		if (actionString.equals("button_events_on")) { //$NON-NLS-1$
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.button.show", true); //$NON-NLS-1$
+	  	} else if (actionString.equals("button_events_off")) { //$NON-NLS-1$
+	  		NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.button.show", false); //$NON-NLS-1$
+	  	} else {
+	  		return;
+	  	}
+
+		BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
+		
+		if (bupTrace == null)
+			return;
+
+  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.THREADS_PAGE)).action(actionString);	
+  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.BINARIES_PAGE)).action(actionString);	
+  		((BupTraceGraph)bupTrace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).action(actionString);	
+	}
+
+	public Integer getLastSample(int graphIndex) {
+		return null;
+	}
+
+	public GraphDrawRequest getDrawRequest(int graphIndex) {
+		GraphDrawRequest request = new GraphDrawRequest();
+		request.addParentGraph(
+				graphIndex,
+				"com.nokia.carbide.cpp.pi.address.AddressPlugin", //$NON-NLS-1$
+				GraphDrawRequest.DRAW_TO_MOST_IMPORTANT_AVAILABLE,
+				1);
+		return request;
+	}
+
+//	public GenericTraceGraph getTraceGraph() 
+//	{
+//		return this.trace.getTraceGraph();
+//	}
+
+	public GenericTraceGraph getTraceGraph(int graphIndex) 
+	{
+		BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
+		
+		if (bupTrace == null)
+			return null;
+
+		return bupTrace.getTraceGraph(graphIndex);
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		setPlugin(null);
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static ButtonPlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractPiPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi.button", path); //$NON-NLS-1$
+	}
+
+	public int getGraphCount() {
+		return GRAPH_COUNT;
+	}
+
+	public int getPageNumber(int graphIndex) {
+		// Assumes page 0 has the threads graph, 1 has the binaries, and 2 has the functions
+		return graphIndex;
+	}
+
+	// return whether this plugin's editor pages have been created
+	public boolean arePagesCreated() {
+		return false;
+	}
+	
+	public void setPagesCreated(boolean pagesCreated) {
+		return;
+	}
+
+	public int getCreatePageCount() {
+		return 0;
+	}
+
+	public int getCreatePageIndex(int index) {
+		return 0;
+	}
+
+	public ProfileVisualiser createPage(int index) {
+		return null;
+	}
+
+	public void setPageIndex(int index, int pageIndex) {
+		return;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable#getGraphTitle(int)
+	 */
+	public String getGraphTitle(int graphIndex) {
+		return null;
+	}
+	
+	/**
+	 * Returns the shared preference store of this plugin
+	 */
+	public static IPreferenceStore getBupPrefsStore(){
+		if (prefsStore == null){
+			prefsStore = getDefault().getPreferenceStore();
+		}
+		
+		return prefsStore;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.plugin.model.IPIPageEditorDispose#runOnDispose()
+	 */
+	public void runOnDispose() {
+		BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
+		if (bupTrace != null) {
+			BupEventMapManager.getInstance().releaseMap(bupTrace.getCurrentBupMapInUse());
+		}
+	}
+	
+	public void switchMap() {
+		BupTrace bupTrace = (BupTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.button"); //$NON-NLS-1$
+		IBupEventMapProfile oldProfile = bupTrace.getCurrentBupMapInUse().getProfile();
+		SwitchBupMapDialog dialog = new SwitchBupMapDialog(Display.getCurrent().getActiveShell(), oldProfile);
+		if (dialog.open() == Window.OK) {
+			IBupEventMap oldMap = bupTrace.getCurrentBupMapInUse();
+			IBupEventMap newMap = BupEventMapManager.getInstance().captureMap(dialog.getNewProfile());
+			if (bupTrace != null) {
+				boolean resetAll = dialog.resetAll();
+				Vector<BupSample> samples = bupTrace.samples;
+				for (BupSample sample : samples) {
+					if (resetAll || !sample.isLabelModified()) {
+						sample.resetLabelToMapDefault(newMap);
+					}
+				}
+				bupTrace.setCurrentBupMapInUse(newMap);
+				AnalysisInfoHandler handler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+				// apply profile change to AnalysisInfoHandler that handling additional info in NPI file lifetime
+				setBupMapProfileToInfoHandler(handler, dialog.getNewProfile());
+				PIPageEditor.currentPageEditor().setDirty();
+				// Use this for sending graph fresh
+				receiveEvent("button_map_switch", new Event());	//$NON-NLS-1$
+			}
+			BupEventMapManager.getInstance().releaseMap(oldMap);
+		}
+	}
+	
+	/*
+	 * (non-javadoc)
+	 * Only Bup Plugin should know about it's own additional info
+	 * This class keep around a profile, and handle transfer in and out fo additional info
+	 * in one place for consistence.
+	 */
+	private class BupInfoHandlerAdditionalInfo {
+		// index of additional info in NPI file
+		private static final transient int BUP_MAP_PROFILE_ID = 0;
+		private static final transient int BUP_MAP_SYMBIAN_SDK_ID = 1;
+		private static final transient int BUP_MAP_IS_BUILTIN = 2;
+		private static final transient int BUP_MAP_IS_WORSPACE = 3;
+		
+		IBupEventMapProfile profile;
+		
+		Vector<Object> toAdditionalInfo() {
+			
+			int maxSize = BUP_MAP_PROFILE_ID;
+			maxSize = Math.max(maxSize, BUP_MAP_SYMBIAN_SDK_ID);
+			maxSize = Math.max(maxSize, BUP_MAP_IS_WORSPACE);
+			maxSize = Math.max(maxSize, BUP_MAP_IS_BUILTIN);
+			Vector<Object> result = new Vector<Object>(maxSize + 1);
+			result.setSize(maxSize + 1);
+			result.setElementAt(profile.getProfileId(), BUP_MAP_PROFILE_ID);
+			result.setElementAt(profile.getSDK() != null ? profile.getSDK().getUniqueId() : "", BUP_MAP_SYMBIAN_SDK_ID); //$NON-NLS-1$
+			result.setElementAt(new Boolean(profile.getURI().equals(BupEventMapManager.WORKSPACE_PREF_KEY_MAP_URI)), BUP_MAP_IS_WORSPACE);
+			result.setElementAt(new Boolean(profile.getURI().equals(BupEventMapManager.DEFAULT_PROFILE_URI)), BUP_MAP_IS_BUILTIN);
+			
+			return result;
+		}
+		
+		void fromAddtionalInfo(Vector<Object> additional_info) {
+			if (!(additional_info.get(BUP_MAP_PROFILE_ID) instanceof String) ||
+					!(additional_info.get(BUP_MAP_SYMBIAN_SDK_ID) instanceof String) ||
+					!(additional_info.get(BUP_MAP_IS_BUILTIN) instanceof Boolean) ||
+					!(additional_info.get(BUP_MAP_IS_WORSPACE) instanceof Boolean))
+			{
+				// did you changed anything in analysisInfoHandlerToAdditonalInfo()?
+				// did you changed the data format of addition info?
+				GeneralMessages.showErrorMessage(Messages.getString("ButtonPlugin.InternalError")); //$NON-NLS-1$
+			}
+			ArrayList<IBupEventMapProfile> profiles = new ArrayList<IBupEventMapProfile>();
+			if (!additional_info.get(BUP_MAP_SYMBIAN_SDK_ID).equals("")) { //$NON-NLS-1$
+				String sdkId = (String) additional_info.get(BUP_MAP_SYMBIAN_SDK_ID);
+				ISymbianSDK sdk = SDKCorePlugin.getSDKManager().getSDK(sdkId, true);
+				profiles.addAll(BupEventMapManager.getInstance().getProfilesFromSDK(sdk));
+			} else if ((Boolean)additional_info.get(BUP_MAP_IS_WORSPACE)) {
+				profiles.addAll(BupEventMapManager.getInstance().getProfilesFromWorkspacePref());
+			} else if ((Boolean)additional_info.get(BUP_MAP_IS_BUILTIN)) {
+				profiles.addAll(BupEventMapManager.getInstance().getProfilesFromBuiltin());
+			}
+			
+			profile = null;
+			for (IBupEventMapProfile tempProfile : profiles) {
+				if (tempProfile.getProfileId().equals(additional_info.get(BUP_MAP_PROFILE_ID))) {
+					profile = tempProfile;
+					break;
+				}
+			}
+			if (profile == null) {
+				if (additional_info.get(BUP_MAP_PROFILE_ID).equals("")) {	//$NON-NLS-1$
+					profile = BupEventMapManager.getInstance().getLegacyProfile();
+				} else {
+					GeneralMessages.showWarningMessage(Messages.getString("ButtonPlugin.keyMapRemoved")); //$NON-NLS-1$
+					profile = BupEventMapManager.getInstance().getPrefSelectedProfile();					
+				}
+			}
+		}
+	}
+
+	public void setupInfoHandler(AnalysisInfoHandler handler) {
+		ArrayList<IBupEventMapProfile> profiles = new ArrayList<IBupEventMapProfile>();
+		if (SampleImporter.getInstance().getBupMapSymbianSDKId() != null &&
+			!SampleImporter.getInstance().getBupMapSymbianSDKId().equals("")) { //$NON-NLS-1$
+			ISymbianSDK sdk = SDKCorePlugin.getSDKManager().getSDK(SampleImporter.getInstance().getBupMapSymbianSDKId(), true);
+			profiles.addAll(BupEventMapManager.getInstance().getProfilesFromSDK(sdk));
+		} else if (SampleImporter.getInstance().isBupMapIsWorkspace()) {
+			profiles.addAll(BupEventMapManager.getInstance().getProfilesFromWorkspacePref());
+		} else if (SampleImporter.getInstance().isBupMapIsBuiltIn()) {
+			profiles.addAll(BupEventMapManager.getInstance().getProfilesFromBuiltin());
+		}
+
+		for (IBupEventMapProfile profile : profiles) {
+			if (profile.getProfileId().equals(SampleImporter.getInstance().getBupMapProfileId())) {
+				BupInfoHandlerAdditionalInfo info = (BupInfoHandlerAdditionalInfo) handler.getTraceDefinedInfo(getTraceId());
+				if (info == null) {
+					info = new BupInfoHandlerAdditionalInfo();
+				}
+				info.profile = profile;
+				handler.setTraceDefinedInfo(getTraceId(), info);
+				break;
+			}
+		}
+	}
+
+	public void additionalInfoToAnalysisInfoHandler(Vector<Object> additional_info, AnalysisInfoHandler handler) { 
+		BupInfoHandlerAdditionalInfo info = (BupInfoHandlerAdditionalInfo) handler.getTraceDefinedInfo(getTraceId());
+		if (info == null) {
+			info = new BupInfoHandlerAdditionalInfo();
+		}
+		info.fromAddtionalInfo(additional_info);
+		handler.setTraceDefinedInfo(getTraceId(), info);
+	}
+	
+	public void analysisInfoHandlerToAdditonalInfo(TraceAdditionalInfo info, AnalysisInfoHandler handler) {
+		Vector<Object> additional_info = new Vector<Object>();
+		Object handlerInfo = handler.getTraceDefinedInfo(getTraceId());
+		if (handlerInfo instanceof BupInfoHandlerAdditionalInfo) {
+			additional_info = ((BupInfoHandlerAdditionalInfo)handlerInfo).toAdditionalInfo();
+		}
+		info.addAdditionalInfo(getTraceId(), additional_info);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.test.IProvideTraceAdditionalInfo#InfoHandlerToDisplayString(java.util.Vector)
+	 */
+	public String InfoHandlerToDisplayString(AnalysisInfoHandler handler) {
+		Object info = handler.getTraceDefinedInfo(getTraceId());
+		if (info instanceof BupInfoHandlerAdditionalInfo) {
+			return Messages.getString("ButtonPlugin.keyPressProfile") +((BupInfoHandlerAdditionalInfo)info).profile.toString(); //$NON-NLS-1$
+		}
+		return ""; //$NON-NLS-1$
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * Manipulate additional info among AnalysisInfoHandler during lifetime of loaded NPI file
+	 */
+	public void setBupMapProfileToInfoHandler(AnalysisInfoHandler handler, IBupEventMapProfile profile) {
+		BupInfoHandlerAdditionalInfo info = (BupInfoHandlerAdditionalInfo) handler.getTraceDefinedInfo(getTraceId());
+		if (info == null) {
+			info = new BupInfoHandlerAdditionalInfo();
+		}
+		info.profile = profile;
+		handler.setTraceDefinedInfo(getTraceId(), info);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * Read additional info among AnalysisInfoHandler during lifetime of loaded NPI file
+	 */
+	public IBupEventMapProfile getBupMapProfileFromInfoHandler(AnalysisInfoHandler handler) {
+		Object info = handler.getTraceDefinedInfo(getTraceId());
+		if (info != null && info instanceof BupInfoHandlerAdditionalInfo) {
+			return ((BupInfoHandlerAdditionalInfo)info).profile;
+		}
+		GeneralMessages.showWarningMessage(Messages.getString("ButtonPlugin.keyMapRemoved")); //$NON-NLS-1$
+		return BupEventMapManager.getInstance().getPrefSelectedProfile();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/ButtonReturnPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IReturnPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+
+
+public class ButtonReturnPlugin implements IReturnPlugin {
+	public AbstractPiPlugin getPlugin() {
+		return ButtonPlugin.getDefault();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/ComNokiaCarbidePiButtonHelpIDs.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+public class ComNokiaCarbidePiButtonHelpIDs {
+	private static final String PI_PLUGIN_ID = "com.nokia.carbide.cpp.pi.button"; //$NON-NLS-1$
+	
+	// see com.nokia.carbide.cpp.pi.help/html/context_help/com_nokia_carbide_pi_button.xml
+	public static final String PI_EDIT_BUTTON_EVENT = PI_PLUGIN_ID + "." + "btnPressChangeContext"; //$NON-NLS-1$ //$NON-NLS-2$
+
+	public static final String PI_BUTTON_ADD_DIALOG = PI_PLUGIN_ID + "." + "btnPressMapAddDialog"; //$NON-NLS-1$ //$NON-NLS-2$;
+
+	public static final String PI_BUTTON_EDIT_DIALOG = PI_PLUGIN_ID + "." + "btnPressMapEditDialog"; //$NON-NLS-1$ //$NON-NLS-2$
+
+	public static final String PI_PROFILE_ADD_DIALOG = PI_PLUGIN_ID + "." + "btnPressAddProfileDialog"; //$NON-NLS-1$ //$NON-NLS-2$
+
+	public static final String PI_PROFILE_EDIT_DIALOG = PI_PLUGIN_ID + "." + "btnPressEditProfileDialog"; //$NON-NLS-1$ //$NON-NLS-2$
+
+	public static final String PI_BUTTON_MAP_PREF_TAB = PI_PLUGIN_ID + "." + "btnPressMapPrefTab"; //$NON-NLS-1$ //$NON-NLS-2$
+	
+	public static final String PI_BUTTON_LOAD_DIALOG = PI_PLUGIN_ID + "." + "btnPressMapLoadDialog"; //$NON-NLS-1$ //$NON-NLS-2$;
+	
+	public static final String PI_KEY_MAP_IMPORT_WIZARD_OVERLAP = PI_PLUGIN_ID + "." + "import_key_map_wizard_overlap_context"; //$NON-NLS-1$ //$NON-NLS-2$
+
+	public static final String PI_KEY_MAP_EXPORT_WIZARD_XML = PI_PLUGIN_ID + "." + "export_key_map_wizard_xml_context"; //$NON-NLS-1$ //$NON-NLS-2$
+
+	public static final String PI_KEY_MAP_IMPORT_WIZARD_XML = PI_PLUGIN_ID + "." + "import_key_map_wizard_xml_context"; //$NON-NLS-1$ //$NON-NLS-2$
+	
+	public static final String PI_KEY_MAP_SWITCH_DIALOG = PI_PLUGIN_ID + "." + "import_key_map_switch_dialog_context"; //$NON-NLS-1$ //$NON-NLS-2$
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/IBupEventMap.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import java.util.Set;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileType;
+
+public interface IBupEventMap {
+	public IBupEventMapProfile getProfile ();
+	public Set<Integer> getKeyCodeSet();
+	public String getLabel(int keyCode);
+	public String getEnum(int keyCode);
+	public void addMapping(int keyCode, String enumString, String label);
+	public void removeMapping(int keyCode);
+	public ButtonEventProfileType toEmfModel();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/IBupEventMapEditable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+public interface IBupEventMapEditable {
+	public boolean isModified(int keyCode);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/IBupEventMapProfile.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import java.net.URI;
+
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+
+public interface IBupEventMapProfile {
+	
+	public String getProfileId();
+	public ISymbianSDK getSDK();
+	public URI getURI();
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.button;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.button.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.button/src/com/nokia/carbide/cpp/pi/button/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,109 @@
+BupEventDialog.0=Button "
+BupEventDialog.1=" at 
+BupEventDialog.10=Time:
+BupEventDialog.11=s
+BupEventDialog.12=Propagate to all labels of the same button
+BupEventDialog.2=s
+BupEventDialog.3=Hex Value:
+BupEventDialog.5=TKeyCode:
+BupEventDialog.6=Label:
+BupEventDialog.7=Type a name
+BupEventDialog.8=Comment:
+BupEventDialog.9=Type a comment
+BupEventMapManager.34=\ (Carbide built-in)
+BupEventMapManager.35=\ (workspace preference)
+BupEventMapManager.37=(SDK ID:
+BupEventMapManager.39=)
+BupEventMapManager.41=URISyntaxException in BupEventMapManager()
+BupEventMapManager.42=captureMap failed for profile 
+BupEventMapManager.44=MalformedURLException in loadMap() on 
+BupEventMapManager.45=IOException in loadMap() on 
+BupEventMapManager.47=MalformedURLException in addToWorkspace()
+BupEventMapManager.48=IOException in addToWorkspace()
+BupEventMapManager.49=MalformedURLException in commitEditToWorkspace() on 
+BupEventMapManager.50=IOException in commitEditToWorkspace() on 
+BupEventMapManager.51=MalformedURLException in commitEditToWorkspace() on 
+BupEventMapManager.52=IOException in commitEditToWorkspace() on 
+BupEventMapManager.53=MalformedURLException in importMergeToWorkspace() on 
+BupEventMapManager.54=IOException in importMergeToWorkspace() on 
+BupEventMapManager.56=MalformedURLException in saveMap() on 
+BupEventMapManager.57=IOException in saveMap() on 
+BupMapSwitchAction.notPIPageeditor=Selected resource is not a PIPageEditor
+BupSample.0=Touch down
+BupSample.1=Touch up
+BupTraceParser.unableToOpenTrace=Unable to open button capture trace file
+BupTraceParser.versionTitle=BUP trace version 
+BupTraceGraph.buttonString1=Button "
+BupTraceGraph.buttonString2=" at 
+BupTraceGraph.buttonString3=s
+BupTraceGraph.button.events.on=button_events_on
+BupTraceGraph.chooseEvents=Events to Modify
+BupTraceGraph.selectEvents=Select events to modify:
+BupTraceGraph.buttonDialog=Button
+BupTraceGraph.changeEvent=Change Event Information...
+BupTraceParser.unsupportedVersion=Unsupported BUP trace version: 
+BupTraceGraph.ok=OK
+BupTraceGraph.cancel=Cancel
+BupTraceParser.errorReadingTraceFile=Error in reading button capture trace file
+BupTraceParser.profile.cannot.load=Key press profile from import wizard cannot be loaded
+BupTraceGraph.saveSamplesForInterval=Save All Event Samples for Interval...
+BupTraceGraph.saveSamplesHeading=Time (ms),Event Name,Event Comment\n
+BupTraceParser.traceFileParsed=Button capture trace file parsed, size: 
+ButtonPlugin.applyProfile=Apply New Key Press Profile
+ButtonPlugin.InternalError=Internal error in additional info
+ButtonPlugin.keyMapRemoved=Key map for this file was removed, workspace profile selection is used
+ButtonPlugin.keyPressProfile=Key press profile: 
+ButtonPlugin.showEventsTooltip=Show button press events
+BupTraceParser.unknown=Unknown
+BupTraceParser.version=Version string: 
+BupTraceGraph.newline=\n
+BupTraceGraph.tooltip1=Button "
+BupTraceGraph.tooltip2=" at 
+BupTraceGraph.tooltip3=s
+BupTraceGraph.tooltip4=\ - 
+ButtonPlugin.showEventsAction=Show Button Events
+BupUpdater.0=NUL
+BupUpdater.1=SOH
+BupUpdater.10=LF
+BupUpdater.11=VT
+BupUpdater.12=FF
+BupUpdater.13=Enter
+BupUpdater.14=SO
+BupUpdater.15=SI
+BupUpdater.16=DLE
+BupUpdater.17=DC1
+BupUpdater.18=DC2
+BupUpdater.19=DC3
+BupUpdater.2=STX
+BupUpdater.20=DC4
+BupUpdater.21=NAK
+BupUpdater.22=SYN
+BupUpdater.23=ETB
+BupUpdater.24=CAN
+BupUpdater.25=EM
+BupUpdater.26=SUB
+BupUpdater.27=ESC
+BupUpdater.28=FS
+BupUpdater.29=GS
+BupUpdater.3=ETX
+BupUpdater.30=RS
+BupUpdater.31=US
+BupUpdater.32=Space
+BupUpdater.33=DEL
+BupUpdater.34=Left
+BupUpdater.35=Right
+BupUpdater.36=Up
+BupUpdater.37=Down
+BupUpdater.38=Pencil
+BupUpdater.39=LSK
+BupUpdater.4=EOT
+BupUpdater.40=RSK
+BupUpdater.41=Rocker
+BupUpdater.42=Application
+BupUpdater.43=Call
+BupUpdater.44=Terminate
+BupUpdater.5=ENQ
+BupUpdater.6=ACK
+BupUpdater.7=BEL
+BupUpdater.8=Cancel
+BupUpdater.9=Tab
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/.settings/org.eclipse.core.resources.prefs	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,3 @@
+#Mon Feb 09 13:40:05 CST 2009
+eclipse.preferences.version=1
+encoding//src/com/nokia/carbide/cpp/pi/call/messages.properties=8859_1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Function Calls
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.call;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.call.CallPlugin
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ com.nokia.carbide.cpp.pi,
+ com.nokia.carbide.cpp.pi.address,
+ com.nokia.carbide.cpp.pi.util,
+ org.eclipse.draw2d
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.pi.call;x-friends:="com.nokia.carbide.cpp.pi.function,com.nokia.carbide.cpp.pi.call.tests"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,6 @@
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .
+jars.compile.order = .
+source.. = src/
+output.. = bin/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+   <extension
+         point="com.nokia.carbide.cpp.pi.piPluginData">
+      <plugin pluginClass="com.nokia.carbide.cpp.pi.call.CallReturnPlugin"/>
+   </extension>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/CallPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.call;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.ui.PlatformUI;
+import org.osgi.framework.BundleContext;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.interfaces.IToolBarActionListener;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable;
+import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.internal.pi.visual.GraphDrawRequest;
+import com.nokia.carbide.cpp.pi.call.GfcFunctionItem.GfcFunctionItemData;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class CallPlugin extends AbstractPiPlugin
+		implements ITrace, IClassReplacer, IVisualizable, IEventListener, IToolBarActionListener
+{
+	private static final String HELP_CONTEXT_ID = PIPageEditor.PI_ID + ".call";  //$NON-NLS-1$
+
+	// the shared instance
+	private static CallPlugin plugin;
+	
+	// page index assigned to the page displaying call info
+	private int pageIndex = PIPageEditor.NEXT_AVAILABLE_PAGE;
+	
+	// call trace
+	private GfcTrace trace;
+
+	// call page
+	private ProfileVisualiser profileVisualiser;
+
+	// call table handler
+	private CallVisualiser callVisualiser;
+
+	private static void setPlugin(CallPlugin newPlugin)
+	{
+		plugin = newPlugin;
+	}
+
+	/**
+	 * The constructor.
+	 */
+	public CallPlugin() {
+		super();
+		setPlugin(this);
+	}
+	
+	public Class getTraceClass() 
+	{
+		return GfcTrace.class;
+	}
+
+	public Class getReplacedClass(String className)
+	{
+		if (   className.indexOf("com.nokia.carbide.cpp.pi.call.GfcTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("com.nokia.carbide.pi.call.GfcTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.model.GfcTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.gfcTracePlugin.GfcTrace") != -1) //$NON-NLS-1$
+		{
+			return GfcTrace.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.call.GfcSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.call.GfcSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.model.GfcSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.gfcTracePlugin.GfcSample") != -1) //$NON-NLS-1$
+		{
+			return GfcSample.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.call.GfcFunctionItem$GfcFunctionItemData") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.call.GfcFunctionItem$GfcFunctionItemData") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.gfcTracePlugin.GfcFunctionItem$GfcFunctionItemData") != -1) //$NON-NLS-1$
+		{
+			return GfcFunctionItemData.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.call.GfcFunctionItem") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.call.GfcFunctionItem") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.analyser.GfcFunctionItem") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.gfcTracePlugin.GfcFunctionItem") != -1) //$NON-NLS-1$
+		{
+			return GfcFunctionItem.class;
+		}
+		else 
+		{
+			return null;
+		}
+	}
+
+	public void initialiseTrace(GenericTrace trace) 
+	{
+		if (!(trace instanceof GfcTrace))
+			return;
+		
+		this.trace = (GfcTrace) trace;
+		
+		this.trace.samples.trimToSize();
+		this.trace.getCompleteGfcTrace().trimToSize();
+		
+		NpiInstanceRepository.getInstance().activeUidAddTrace("com.nokia.carbide.cpp.pi.call", trace); //$NON-NLS-1$
+		
+	  	/*
+	  	 * Check if the trace is complete (first sample is at time 1,
+	  	 * sample N is at time N)
+	  	 */
+		this.trace.setComplete();
+		
+		ArrayList<CallVisualiser>    callVisualiserList    = new ArrayList<CallVisualiser>();
+
+		NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.call.CallPlugin.callVisualiserList", callVisualiserList);	//$NON-NLS-1$
+
+		ArrayList<ProfileVisualiser> profileVisualiserList = new ArrayList<ProfileVisualiser>();
+		NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.call.CallPlugin.profileVisualiserList", profileVisualiserList);	//$NON-NLS-1$
+
+	}
+
+	public String getTraceName() {
+		return "Function Call"; //$NON-NLS-1$
+	}
+
+	public int getTraceId() {
+		return 2;
+	}
+
+	public ParsedTraceData parseTraceFile(File file /*, ProgressBar progressBar*/) throws Exception 
+	{
+        GfcTraceParser gfcParser;
+        gfcParser = new GfcTraceParser();
+
+        return gfcParser.parse(file);
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		setPlugin(null);
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static CallPlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractPiPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi.call", path); //$NON-NLS-1$
+	}
+
+	boolean pagesCreated = false;
+
+	// return whether this plugin's editor pages have been created
+	public boolean arePagesCreated() {
+		return this.pagesCreated;
+	}
+	
+	// set whether this plugin's editor pages have been created
+	public void setPagesCreated(boolean pagesCreated) {
+		this.pagesCreated = pagesCreated;
+	}
+
+	// number of editor pages to create
+	public int getCreatePageCount() {
+		return 1;
+	}
+
+	// editor page index for each created editor page
+	public int getCreatePageIndex(int index) {
+		return PIPageEditor.NEXT_AVAILABLE_PAGE;
+	}
+
+	// page index actually assigned to a created page
+	public void setPageIndex(int index, int pageIndex) {
+		if (index == 0)
+			this.pageIndex = pageIndex;
+	}
+
+	// create the page(s)
+	public ProfileVisualiser createPage(int index) {
+		Composite parent = NpiInstanceRepository.getInstance().activeUidGetParentComposite();
+		if (parent == null) {
+			// no parent composite is only for temp instance used by non-GUI importer
+			GeneralMessages.showErrorMessage(Messages.getString("CallPlugin.0")); //$NON-NLS-1$
+			return null;
+		}
+		
+		// there is one page, with no graph
+		this.profileVisualiser = new ProfileVisualiser(ProfileVisualiser.TOP_ONLY, parent,
+														Messages.getString("CallPlugin.functionCalls")); //$NON-NLS-1$
+		AnalysisInfoHandler infoHandler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+		this.profileVisualiser.getParserRepository().setPIAnalysisInfoHandler(infoHandler);
+	    
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(profileVisualiser.getContentPane(),
+														HELP_CONTEXT_ID + ".functionCallsPageContext"); //$NON-NLS-1$
+
+		PIPageEditor pageEditor = PIPageEditor.currentPageEditor();
+		
+		this.callVisualiser = new CallVisualiser(pageEditor, pageIndex, profileVisualiser.getTopComposite().getSashForm(), this.trace);
+	    
+		this.profileVisualiser.getTitle().setText(Messages.getString("CallPlugin.functionCallAnalysis")); //$NON-NLS-1$
+		this.profileVisualiser.getTitle().setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
+		this.profileVisualiser.getTitle().setFont(PIPageEditor.helvetica_12);
+
+		this.profileVisualiser.getTitle2().setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
+
+		this.profileVisualiser.getTimeString().setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
+		this.profileVisualiser.getTimeString().setFont(PIPageEditor.helvetica_10);
+
+		Object objCallList = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.call.CallPlugin.callVisualiserList"); //$NON-NLS-1$
+		ArrayList<CallVisualiser> callVisualiserList = (ArrayList<CallVisualiser>) objCallList;
+
+		Object objProfileList = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.call.CallPlugin.profileVisualiserList"); //$NON-NLS-1$
+		ArrayList<ProfileVisualiser> profileVisualiserList = (ArrayList<ProfileVisualiser>) objProfileList;
+
+		if (callVisualiserList != null)
+			callVisualiserList.add(this.callVisualiser);
+
+		if (profileVisualiserList != null)
+			profileVisualiserList.add(this.profileVisualiser);
+
+		return this.profileVisualiser;
+	}
+
+	// number of graphs supplied by this plugin
+	public int getGraphCount() {
+		return 0;
+	}
+
+	// page number of each graph supplied by this plugin
+	public int getPageNumber(int graphIndex) {
+		Object objCallList = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.call.CallPlugin.callVisualiserList");	//$NON-NLS-1$
+		ArrayList<CallVisualiser> callVisualiserList = (ArrayList<CallVisualiser>) objCallList;
+		
+		if (callVisualiserList == null)
+			return this.pageIndex;
+
+		for (int i = 0; i < callVisualiserList.size(); i++) {
+			if (callVisualiserList.get(i).getPageEditor() == PIPageEditor.currentPageEditor())
+				return callVisualiserList.get(i).getPageIndex();
+		}
+		
+		return this.pageIndex;
+	}
+
+	public GenericTraceGraph getTraceGraph(int graphIndex) {
+		return null;
+	}
+
+	public Integer getLastSample(int graphIndex) {
+		return null;
+	}
+
+	public GraphDrawRequest getDrawRequest(int graphIndex) {
+		return null;
+	}
+
+	public void receiveEvent(String action, Event event) {
+		Object objCallList = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.call.CallPlugin.callVisualiserList");	//$NON-NLS-1$
+		ArrayList<CallVisualiser> callVisualiserList = (ArrayList<CallVisualiser>) objCallList;
+
+		if (callVisualiserList == null)
+			return;
+		
+		Object objProfileList = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.call.CallPlugin.profileVisualiserList");	//$NON-NLS-1$
+		ArrayList<ProfileVisualiser> profileVisualiserList = (ArrayList<ProfileVisualiser>) objProfileList;
+
+		if (profileVisualiserList == null)
+			return;
+		
+		if (action.equals("changeSelection")) { //$NON-NLS-1$
+			// find the right callVisualiser and ProfileVisualiser
+			for (int i = 0; i < callVisualiserList.size(); i++) {
+				if (callVisualiserList.get(i).getPageEditor() == PIPageEditor.currentPageEditor()) {
+					callVisualiserList.get(i).setStartAndEnd(event.start, event.end);
+					double startTime = PIPageEditor.currentPageEditor().getStartTime();
+					double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+					profileVisualiserList.get(i).getTimeString().setText(ProfileVisualiser.getTimeInterval(startTime, endTime));
+				}
+			}
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable#getGraphTitle(int)
+	 */
+	public String getGraphTitle(int graphIndex) {
+		return null;
+	}
+
+	public void setActions(boolean entering, int pageIndex) {
+		if (pageIndex != this.pageIndex)
+			return;
+		
+		if (entering) {
+			PIPageEditor.getZoomInAction().setEnabled(false);
+			PIPageEditor.getZoomOutAction().setEnabled(false);
+			PIPageEditor.getZoomToSelectionAction().setEnabled(false);
+			PIPageEditor.getZoomToTraceAction().setEnabled(false);
+		} else {
+			PIPageEditor.getZoomInAction().setEnabled(true);
+			PIPageEditor.getZoomOutAction().setEnabled(true);
+			PIPageEditor.getZoomToSelectionAction().setEnabled(true);
+			PIPageEditor.getZoomToTraceAction().setEnabled(true);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/CallReturnPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.call;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IReturnPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+
+
+public class CallReturnPlugin implements IReturnPlugin {
+	public AbstractPiPlugin getPlugin() {
+		return CallPlugin.getDefault();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/CallTraceGraph.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.call;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Panel;
+import org.eclipse.swt.graphics.GC;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEventListener;
+
+
+public class CallTraceGraph extends GenericTraceGraph implements ActionListener, 
+	PIEventListener {
+
+	public CallTraceGraph(GenericTrace data) {
+		super(data);
+	}
+
+	public void paint(Panel panel, Graphics graphics) {
+	}
+
+	public void repaint() {
+	}
+
+	public void refreshDataFromTrace() {
+	}
+
+	public void action(String action) {
+	}
+
+	public void actionPerformed(ActionEvent e) {
+	}
+
+	public void piEventReceived(PIEvent event) {
+	}
+
+	public void paintLeftLegend(FigureCanvas figureCanvas, GC gc) {
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/CallVisualiser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2020 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.call;
+
+//import java.awt.Color;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.MouseEvent;
+import java.text.DecimalFormat;
+import java.util.Vector;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.SubMenuManager;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.ide.IIDEActionConstants;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveTable;
+import com.nokia.carbide.cpp.internal.pi.save.SaveTableWizard;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTable;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.SourceLookup;
+
+
+public class CallVisualiser extends GenericTable
+{
+	private static final long serialVersionUID = 1L;
+
+	// table column IDs in hopes it's quicker than comparing characters
+	protected static final int COLUMN_ID_IS_CALLED       = 100;
+	protected static final int COLUMN_ID_IS_CALLER       = 101;
+	protected static final int COLUMN_ID_RECURSIVE_CALL  = 102;
+	protected static final int COLUMN_ID_CALLER_PERCENT  = 103;
+	protected static final int COLUMN_ID_CALLEE_PERCENT  = 104;
+	protected static final int COLUMN_ID_IS_CALLED_COUNT = 105;
+	protected static final int COLUMN_ID_IS_CALLER_COUNT = 106;
+	
+	// table column headings
+	protected static final String COLUMN_HEAD_IS_CALLED       = Messages.getString("CallVisualiser.isCalled"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_IS_CALLER       = Messages.getString("CallVisualiser.isCaller"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_RECURSIVE_CALL  = Messages.getString("CallVisualiser.recursiveCaller"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_CALLER_PERCENT  = Messages.getString("CallVisualiser.percentOfCalls"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_CALLEE_PERCENT  = Messages.getString("CallVisualiser.percentOfCalls"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_IS_CALLED_COUNT = Messages.getString("CallVisualiser.calledSamples"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_IS_CALLER_COUNT = Messages.getString("CallVisualiser.callerSamples"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_IS_CALLED_COUNT2 = Messages.getString("CallVisualiser.calls"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_IS_CALLER_COUNT2 = Messages.getString("CallVisualiser.calls"); //$NON-NLS-1$
+
+	// table column widths
+	protected static final int COLUMN_WIDTH_IS_CALLED       = 70;
+	protected static final int COLUMN_WIDTH_IS_CALLER       = 70;
+	protected static final int COLUMN_WIDTH_RECURSIVE_CALL  = 105;
+	protected static final int COLUMN_WIDTH_CALLER_PERCENT  = 98;
+	protected static final int COLUMN_WIDTH_CALLEE_PERCENT  = 98;
+	protected static final int COLUMN_WIDTH_IS_CALLED_COUNT = 113;
+	protected static final int COLUMN_WIDTH_IS_CALLER_COUNT = 85;
+	protected static final int COLUMN_WIDTH_IS_CALLED_COUNT2 = 65;
+	protected static final int COLUMN_WIDTH_IS_CALLER_COUNT2 = 65;
+	
+	// SashForm to hold the tables and their titles
+	private SashForm sashForm;
+	
+	// Table viewers and their tables
+	private TableViewer callerTableViewer;
+	private Table callerTable;
+	
+	private TableViewer currentFunctionTableViewer;
+	private Table       currentFunctionTable;
+	private TableColumn  currentFunctionDefaultColumn;
+
+	private TableViewer calleeTableViewer;
+	private Table calleeTable;
+
+	// context menus
+	private Menu callerMenu;
+	private Menu currentFunctionMenu;
+	private Menu calleeMenu;
+	
+	private Table currentMenuTable;
+
+	private SashForm parent;
+
+	// this display's editor and page
+	private PIPageEditor pageEditor;
+	private int pageIndex;
+	
+	// trace associated with this display
+	private GfcTrace myTrace;
+	
+	// lists of functions, function callers, and function callees
+	private GfcFunctionItem[]  functionArray;
+	private CallerCalleeItem[] callerList;
+	private CallerCalleeItem[] calleeList;
+	
+	// menu items
+	protected Action copyAction;
+	protected Action copyTableAction;
+	protected Action functionCopyFunctionAction;
+	protected Action saveTableAction;
+	protected Action functionSaveFunctionAction;
+	
+	protected static int SAMPLES_AT_ONE_TIME = 1000;
+	
+	// class to pass sample data to the save wizard
+    public class SaveSampleString implements ISaveSamples {
+    	int startIndex = 0;
+    	
+    	public SaveSampleString() {
+		}
+
+    	public String getData() {
+    		return getData(SAMPLES_AT_ONE_TIME);
+		}
+
+		public String getData(int size) {
+			String returnString = getSampleString(this.startIndex, this.startIndex + size);
+    		if (returnString == null)
+    			this.startIndex = 0;
+    		else
+    			this.startIndex += size;
+			return returnString;
+		}
+
+		public int getIndex() {
+			return this.startIndex;
+		}
+
+		public void clear() {
+			this.startIndex = 0;
+		}
+    }
+
+	/*
+	 * return the call samples selected in the interval 
+	 */
+	protected String getSampleString(int startIndex, int endIndex)
+	{
+		int startTime = (int) (PIPageEditor.currentPageEditor().getStartTime() * 1000.0 + 0.0005);
+		int endTime   = (int) (PIPageEditor.currentPageEditor().getEndTime()   * 1000.0 + 0.0005);
+		
+		// check if we have returned everything
+		if (startIndex > (endTime - startTime))
+			return null;
+		
+		GfcTrace trace = this.myTrace;
+		Vector samples = trace.samples;
+	
+		String returnString = ""; //$NON-NLS-1$
+		
+		if (startIndex == 0)
+			returnString = Messages.getString("CallVisualiser.callHeading"); //$NON-NLS-1$
+
+		for (int i = startTime + startIndex; i < endTime && i < startTime + endIndex; i++) {
+			GfcSample sample = (GfcSample) samples.get(i);
+
+			returnString +=   sample.sampleSynchTime + ",0x" //$NON-NLS-1$
+							+ Long.toHexString(sample.linkRegister)
+							+ ",\"" //$NON-NLS-1$
+							+ (sample.callerFunctionItt != null
+								? sample.callerFunctionItt.functionName
+								: sample.callerFunctionSym.functionName)
+							+ "\"," //$NON-NLS-1$
+							+ (sample.callerFunctionItt != null
+								? sample.callerFunctionItt.functionBinary.binaryName
+								: sample.callerFunctionSym.functionBinary.binaryName)
+							+ ",0x" //$NON-NLS-1$
+							+ Long.toHexString(sample.programCounter)
+							+ ",\"" //$NON-NLS-1$
+							+ (sample.currentFunctionItt != null
+								? sample.currentFunctionItt.functionName
+								: sample.currentFunctionSym.functionName)
+							+ "\"," //$NON-NLS-1$
+							+ (sample.currentFunctionItt != null
+								? sample.currentFunctionItt.functionBinary.binaryName
+								: sample.currentFunctionSym.functionBinary.binaryName)
+							+ "\n"; //$NON-NLS-1$
+		}
+
+		return returnString;
+	}
+
+	protected MenuItem getSaveSamplesItem(Menu menu, boolean enabled) {
+	    MenuItem saveSamplesItem = new MenuItem(menu, SWT.PUSH);
+
+		saveSamplesItem.setText(Messages.getString("CallVisualiser.saveAllSamplesForInterval")); //$NON-NLS-1$
+		saveSamplesItem.setEnabled(enabled);
+		
+		if (enabled) {
+			saveSamplesItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+					action("saveSamples"); //$NON-NLS-1$
+				}
+			});
+		}
+	
+		return saveSamplesItem;
+	}
+
+	public CallVisualiser(PIPageEditor pageEditor, int pageIndex, SashForm parent, GfcTrace trace)
+	{
+		this.pageEditor = pageEditor;
+		this.pageIndex  = pageIndex;
+		this.parent     = parent;
+		this.myTrace    = trace;
+		
+		// let the trace know about the CallVisualiser so that unit tests can find it
+		trace.setCallVisualiser(this);
+
+		// create the 3 table viewers: caller functions, selected function, callee functions
+		createTableViewers(parent);
+	}
+
+	public void createTableViewers(SashForm parent)
+	{
+		if (parent == null)
+			return;
+
+		/*
+		 * Create a SashForm with three labeled tables:
+		 * 
+		 * 1. Functions called by
+		 * 2. Functions (one checkbox selectable at a time)
+		 * 3. Functions called
+		 */
+
+		// the 3 tables will be in a sashForm
+		if (parent.getOrientation() != SWT.VERTICAL)
+		{
+			// put a SashForm in the SashForm
+			this.sashForm = new SashForm(parent, SWT.VERTICAL);
+			this.sashForm.SASH_WIDTH = 5; // 5 pixel wide sash
+		} else
+			this.sashForm = parent;
+		
+		createCallerTableViewer(sashForm);
+		createCurrentFunctionTableViewer(sashForm);
+		createCalleeTableViewer(sashForm);
+
+		createDefaultActions(true);
+	}
+	
+	private void createCurrentFunctionTableViewer(SashForm sashForm)
+	{
+		/*
+		 * Functions (one checkbox selectable at a time)
+		 *
+		 * 		selected checkbox
+		 *		percent load
+		 *  	function name
+		 *		function start address
+		 *		binary containing function
+		 *		sample count
+		 */
+		Label label;
+		Composite holder;
+		Table table;
+		TableColumn column;
+		
+		// middle functionTable and title
+		holder = new Composite(sashForm, SWT.NONE);
+		GridLayout gridLayout = new GridLayout(1, true);
+		gridLayout.marginWidth = 0;
+		gridLayout.marginHeight = 0;
+		holder.setLayout(gridLayout);
+
+		label = new Label(holder, SWT.CENTER | SWT.BORDER);
+		label.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_YELLOW));
+		label.setFont(PIPageEditor.helvetica_10);
+		label.setText(Messages.getString("CallVisualiser.selectFunction")); //$NON-NLS-1$
+		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		this.currentFunctionTableViewer = new TableViewer(holder,
+  				SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
+		this.currentFunctionTable = currentFunctionTableViewer.getTable();
+		
+		// add the label provider and content provider
+		this.currentFunctionTableViewer.setLabelProvider(new SharedLabelProvider(this.currentFunctionTable));
+		this.currentFunctionTableViewer.setContentProvider(new ArrayContentProvider());
+		this.currentFunctionTableViewer.setSorter(new SharedSorter());
+		
+		table = this.currentFunctionTable;
+		table.setRedraw(false);
+
+		// give the table a heading for use in copying and exported
+		table.setData(Messages.getString("CallVisualiser.selectedFunction")); //$NON-NLS-1$
+		
+		// create the other table entries when a row in this table is selected
+		table.addSelectionListener(new SelectionListener() {
+
+			public void widgetSelected(SelectionEvent event) {
+
+				if (!(event.item instanceof TableItem))
+					return;
+				
+	       		// set the other tables based on this selection
+	       		if (!(event.item.getData() instanceof GfcFunctionItem))
+	       			return;
+	       		
+	       		updateCallerCalleeTables((GfcFunctionItem)event.item.getData());
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}});
+		
+		// data associated with the TableViewer will note which columns contain hex values
+		// Keep this in the order in which columns have been created
+		boolean[] isHex = {false, false, false, true, false, false, false};
+		this.currentFunctionTable.setData("isHex", isHex); //$NON-NLS-1$
+
+		// is called percent column
+		column = new TableColumn(table, SWT.RIGHT);
+		column.setText(COLUMN_HEAD_IS_CALLED);
+		column.setWidth(COLUMN_WIDTH_IS_CALLED);
+		column.setData(new Integer(COLUMN_ID_IS_CALLED));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CheckboxColumnSelectionHandler());
+
+		// is caller percent column
+		column = new TableColumn(table, SWT.RIGHT);
+		column.setText(COLUMN_HEAD_IS_CALLER);
+		column.setWidth(COLUMN_WIDTH_IS_CALLER);
+		column.setData(new Integer(COLUMN_ID_IS_CALLER));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CheckboxColumnSelectionHandler());
+
+		// function name column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_FUNCTION);
+		column.setWidth(COLUMN_WIDTH_FUNCTION_NAME);
+		column.setData(new Integer(COLUMN_ID_FUNCTION));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CheckboxColumnSelectionHandler());
+
+		// function start address column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_START_ADDR);
+		column.setWidth(COLUMN_WIDTH_START_ADDRESS);
+		column.setData(new Integer(COLUMN_ID_START_ADDR));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CheckboxColumnSelectionHandler());
+
+		// binary containing function column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_IN_BINARY);
+		column.setWidth(COLUMN_WIDTH_IN_BINARY);
+		column.setData(new Integer(COLUMN_ID_IN_BINARY));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CheckboxColumnSelectionHandler());
+
+		// path to binary containing function column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_IN_BINARY_PATH);
+		column.setWidth(COLUMN_WIDTH_IN_BINARY_PATH);
+		column.setData(new Integer(COLUMN_ID_IN_BINARY_PATH));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CheckboxColumnSelectionHandler());
+
+		// sample count column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_IS_CALLED_COUNT);
+		column.setWidth(COLUMN_WIDTH_IS_CALLED_COUNT);
+		column.setData(new Integer(COLUMN_ID_IS_CALLED_COUNT));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CheckboxColumnSelectionHandler());
+
+		// set the default sort column to COLUMN_ID_IS_CALLED_COUNT
+		currentFunctionDefaultColumn = column;
+
+		// sample count column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_IS_CALLER_COUNT);
+		column.setWidth(COLUMN_WIDTH_IS_CALLER_COUNT);
+		column.setData(new Integer(COLUMN_ID_IS_CALLER_COUNT));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CheckboxColumnSelectionHandler());
+
+		table.setLayoutData(new GridData(GridData.FILL_BOTH));
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+		table.setRedraw(true);
+
+		// listen for mouse clicks: to select a row, pop up a menu, etc.
+		table.addMouseListener(new CurrentFunctionMouseListener());
+
+		table.addFocusListener(new FocusListener() {
+			IAction oldCopyAction = null;
+
+			public void focusGained(org.eclipse.swt.events.FocusEvent arg0) {
+				IActionBars bars = PIPageEditor.getActionBars();
+				
+				// modify what is executed when Copy is called from the Edit menu
+				oldCopyAction = bars.getGlobalActionHandler(ActionFactory.COPY.getId());
+
+				bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
+
+				copyAction.setEnabled(currentFunctionTable.getSelectionCount() > 0);
+				bars.updateActionBars();
+				
+				// add to the Edit menu
+		        IMenuManager editMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_EDIT);
+
+		        if (editMenuManager instanceof SubMenuManager)
+		        {
+		        	IContributionManager editManager = ((SubMenuManager)editMenuManager).getParent();
+		        	ActionContributionItem item;
+
+					editMenuManager.remove("PICopyFunction"); //$NON-NLS-1$
+					functionCopyFunctionAction.setEnabled(currentFunctionTable.getSelectionCount() > 0);
+		        	item = new ActionContributionItem(functionCopyFunctionAction);
+		        	item.setVisible(true);
+		        	editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+
+					editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
+					copyTableAction.setEnabled(currentFunctionTable.getItemCount() > 0);
+		        	item = new ActionContributionItem(copyTableAction);
+		        	item.setVisible(true);
+		        	editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+		        }
+				
+				// add to the File menu
+		        IMenuManager fileMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_FILE);
+
+		        if (fileMenuManager instanceof SubMenuManager)
+		        {
+		        	IContributionManager fileManager = ((SubMenuManager)fileMenuManager).getParent();
+		        	ActionContributionItem item;
+
+					fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
+					saveTableAction.setEnabled(currentFunctionTable.getItemCount() > 0);
+		        	item = new ActionContributionItem(saveTableAction);
+		        	item.setVisible(true);
+		        	fileManager.insertAfter("saveAll", item); //$NON-NLS-1$
+
+					fileMenuManager.remove("PISaveFunction"); //$NON-NLS-1$
+					functionSaveFunctionAction.setEnabled(currentFunctionTable.getSelectionCount() > 0);
+		        	item = new ActionContributionItem(functionSaveFunctionAction);
+		        	item.setVisible(true);
+		        	fileManager.insertAfter("PISaveTable", item); //$NON-NLS-1$
+		        }
+		}
+
+			public void focusLost(org.eclipse.swt.events.FocusEvent arg0) {
+				IActionBars bars = PIPageEditor.getActionBars();
+				bars.setGlobalActionHandler(ActionFactory.COPY.getId(), oldCopyAction);
+				bars.updateActionBars();
+
+				SubMenuManager editMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_EDIT);
+				editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
+				editMenuManager.remove("PICopyFunction"); //$NON-NLS-1$
+
+				SubMenuManager fileMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_FILE);
+				fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
+				fileMenuManager.remove("PISaveFunction"); //$NON-NLS-1$
+			}
+		});
+	}
+	
+	private void createCallerTableViewer(SashForm sashForm)
+	{
+		/*
+		 * Functions called by
+		 * 
+		 *		percent of calls
+		 *		total percent
+		 *		caller percent
+		 *  	function name
+		 *		function start address
+		 *		binary containing function
+		 *		sample count
+		 */
+		Label label;
+		Composite holder;
+		Table table;
+		TableColumn column;
+		
+		// top functionTable and title
+		holder = new Composite(sashForm, SWT.NONE);
+//		holder.setLayout(new FillLayout(SWT.VERTICAL));
+		GridLayout gridLayout = new GridLayout(1, true);
+		gridLayout.marginWidth = 0;
+		gridLayout.marginHeight = 0;
+		holder.setLayout(gridLayout);
+
+		label = new Label(holder, SWT.CENTER | SWT.BORDER);
+		label.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_CYAN));
+		label.setFont(PIPageEditor.helvetica_10);
+		label.setText(Messages.getString("CallVisualiser.callingSelectedFunction")); //$NON-NLS-1$
+		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		this.callerTableViewer = new TableViewer(holder,
+  				SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
+		this.callerTable = callerTableViewer.getTable();
+		
+		// add the label provider and content provider
+		this.callerTableViewer.setLabelProvider(new SharedLabelProvider(this.callerTable));
+		this.callerTableViewer.setContentProvider(new ArrayContentProvider());
+		this.callerTableViewer.setSorter(new SharedSorter());
+
+		table = this.callerTable;
+		table.setRedraw(false);
+
+		// give the table a heading for possible use in copying and exported
+		table.setData(Messages.getString("CallVisualiser.callerFunctions")); //$NON-NLS-1$
+		
+		// data associated with the TableViewer will note which columns contain hex values
+		// Keep this in the order in which columns have been created
+		boolean[] isHex = {false, false, false, true, false, false, false};
+		this.callerTable.setData("isHex", isHex); //$NON-NLS-1$
+
+		// percent of calls column
+		column = new TableColumn(table, SWT.RIGHT);
+		column.setText(COLUMN_HEAD_CALLER_PERCENT);
+		column.setWidth(COLUMN_WIDTH_CALLER_PERCENT);
+		column.setData(new Integer(COLUMN_ID_CALLER_PERCENT));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledByColumnSelectionHandler());
+
+		// sample count column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_IS_CALLER_COUNT2);
+		column.setWidth(COLUMN_WIDTH_IS_CALLER_COUNT2);
+		column.setData(new Integer(COLUMN_ID_IS_CALLER_COUNT));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledByColumnSelectionHandler());
+
+		// function name column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_FUNCTION);
+		column.setWidth(COLUMN_WIDTH_FUNCTION_NAME);
+		column.setData(new Integer(COLUMN_ID_FUNCTION));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledByColumnSelectionHandler());
+
+		// function start address column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_START_ADDR);
+		column.setWidth(COLUMN_WIDTH_START_ADDRESS);
+		column.setData(new Integer(COLUMN_ID_START_ADDR));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledByColumnSelectionHandler());
+
+		// binary containing function column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_IN_BINARY);
+		column.setWidth(COLUMN_WIDTH_IN_BINARY);
+		column.setData(new Integer(COLUMN_ID_IN_BINARY));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledByColumnSelectionHandler());
+
+		// path to binary containing function column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_IN_BINARY_PATH);
+		column.setWidth(COLUMN_WIDTH_IN_BINARY_PATH);
+		column.setData(new Integer(COLUMN_ID_IN_BINARY_PATH));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledByColumnSelectionHandler());
+
+		// is caller percent column
+		column = new TableColumn(table, SWT.RIGHT);
+		column.setText(COLUMN_HEAD_IS_CALLER);
+		column.setWidth(COLUMN_WIDTH_IS_CALLER);
+		column.setData(new Integer(COLUMN_ID_IS_CALLER));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledByColumnSelectionHandler());
+
+		table.setLayoutData(new GridData(GridData.FILL_BOTH));
+//		table.setLayout(new FillLayout());
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+		table.setRedraw(true);
+		
+		// when a row is selected, allow the user to double-click or right click and make that function the selected function
+		table.addSelectionListener(new SelectionAdapter() {
+
+			public void widgetDefaultSelected(SelectionEvent se) {
+				TableItem item = (TableItem)se.item;
+				Table table = (Table)se.widget;
+				CallerCalleeItem callerCalleeItem = (CallerCalleeItem)item.getData();
+				
+				// deselect this line
+				table.deselectAll();
+				
+				// choose this row's function
+				chooseNewFunction(callerCalleeItem);
+			}
+		});
+		
+		table.addMouseListener(new CallerMouseListener());
+		
+		table.addFocusListener(new FocusListener() {
+			IAction oldCopyAction = null;
+
+			public void focusGained(org.eclipse.swt.events.FocusEvent arg0) {
+				IActionBars bars = PIPageEditor.getActionBars();
+				
+				// modify what is executed when Copy is called from the Edit menu
+				oldCopyAction = bars.getGlobalActionHandler(ActionFactory.COPY.getId());
+
+				bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
+
+				copyAction.setEnabled(callerTable.getSelectionCount() > 0);
+				bars.updateActionBars();
+				
+				// add to the Edit menu
+		        IMenuManager editMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_EDIT);
+
+		        if (editMenuManager instanceof SubMenuManager)
+		        {
+		        	IContributionManager editManager = ((SubMenuManager)editMenuManager).getParent();
+		        	ActionContributionItem item;
+
+					editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
+					copyTableAction.setEnabled(callerTable.getItemCount() > 0);
+		        	item = new ActionContributionItem(copyTableAction);
+		        	item.setVisible(true);
+		        	editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+		        }
+				
+				// add to the File menu
+		        IMenuManager fileMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_FILE);
+
+		        if (fileMenuManager instanceof SubMenuManager)
+		        {
+		        	IContributionManager fileManager = ((SubMenuManager)fileMenuManager).getParent();
+		        	ActionContributionItem item;
+
+					fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
+					saveTableAction.setEnabled(callerTable.getItemCount() > 0);
+		        	item = new ActionContributionItem(saveTableAction);
+		        	item.setVisible(true);
+		        	fileManager.insertAfter("saveAll", item); //$NON-NLS-1$
+		        }
+			}
+
+			public void focusLost(org.eclipse.swt.events.FocusEvent arg0) {
+				IActionBars bars = PIPageEditor.getActionBars();
+				bars.setGlobalActionHandler(ActionFactory.COPY.getId(), oldCopyAction);
+				bars.updateActionBars();
+
+				SubMenuManager editMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_EDIT);
+				editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
+
+				SubMenuManager fileMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_FILE);
+				fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
+			}
+		});
+	}
+	
+	private void createCalleeTableViewer(SashForm sashForm)
+	{
+		/*
+		 * Functions called
+		 * 
+		 *		percent of calls
+		 *		total percent
+		 *		caller percent
+		 *  	function name
+		 *		function start address
+		 *		binary containing function
+		 *		sample count
+		 */
+		Label label;
+		Composite holder;
+		Table table;
+		TableColumn column;
+		
+		// bottom functionTable and title
+		holder = new Composite(sashForm, SWT.NONE);
+//		holder.setLayout(new FillLayout(SWT.VERTICAL));
+		GridLayout gridLayout = new GridLayout(1, true);
+		gridLayout.marginWidth = 0;
+		gridLayout.marginHeight = 0;
+		holder.setLayout(gridLayout);
+
+		label = new Label(holder, SWT.CENTER | SWT.BORDER);
+		label.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_CYAN));
+		label.setFont(PIPageEditor.helvetica_10);
+		label.setText(Messages.getString("CallVisualiser.calledBySelectedFunction")); //$NON-NLS-1$
+		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		this.calleeTableViewer = new TableViewer(holder,
+  				SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
+		this.calleeTable = calleeTableViewer.getTable();
+		
+		// add the label provider and content provider
+		this.calleeTableViewer.setLabelProvider(new SharedLabelProvider(this.calleeTable));
+		this.calleeTableViewer.setContentProvider(new ArrayContentProvider());
+		this.calleeTableViewer.setSorter(new SharedSorter());
+
+		table = this.calleeTable;
+		table.setRedraw(false);
+
+		// give the table a heading for possible use in copying and exported
+		table.setData(Messages.getString("CallVisualiser.calleeFunctions")); //$NON-NLS-1$
+		
+		// data associated with the TableViewer will note which columns contain hex values
+		// Keep this in the order in which columns have been created
+		boolean[] isHex = {false, false, false, true, false, false, false};
+		this.calleeTable.setData("isHex", isHex); //$NON-NLS-1$
+		
+		// percent of calls column
+		column = new TableColumn(table, SWT.RIGHT);
+		column.setText(COLUMN_HEAD_CALLEE_PERCENT);
+		column.setWidth(COLUMN_WIDTH_CALLEE_PERCENT);
+		column.setData(new Integer(COLUMN_ID_CALLEE_PERCENT));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledColumnSelectionHandler());
+
+		// sample count column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_IS_CALLED_COUNT2);
+		column.setWidth(COLUMN_WIDTH_IS_CALLED_COUNT2);
+		column.setData(new Integer(COLUMN_ID_IS_CALLED_COUNT));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledColumnSelectionHandler());
+
+		// function name column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_FUNCTION);
+		column.setWidth(COLUMN_WIDTH_FUNCTION_NAME);
+		column.setData(new Integer(COLUMN_ID_FUNCTION));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledColumnSelectionHandler());
+
+		// function start address column
+		column = new TableColumn(table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_START_ADDR);
+		column.setWidth(COLUMN_WIDTH_START_ADDRESS);
+//		column.setData(new Integer(COLUMN_ID_START_ADDR3));
+		column.setData(new Integer(COLUMN_ID_START_ADDR));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledColumnSelectionHandler());
+
+		// binary containing function column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_IN_BINARY);
+		column.setWidth(COLUMN_WIDTH_IN_BINARY);
+//		column.setData(new Integer(COLUMN_ID_IN_BINARY3));
+		column.setData(new Integer(COLUMN_ID_IN_BINARY));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledColumnSelectionHandler());
+
+		// path to binary containing function column
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText(COLUMN_HEAD_IN_BINARY_PATH);
+		column.setWidth(COLUMN_WIDTH_IN_BINARY_PATH);
+//		column.setData(new Integer(COLUMN_ID_IN_BINARY_PATH3));
+		column.setData(new Integer(COLUMN_ID_IN_BINARY_PATH));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledColumnSelectionHandler());
+
+		// percent of calls column
+		column = new TableColumn(table, SWT.RIGHT);
+		column.setText(COLUMN_HEAD_IS_CALLED);
+		column.setWidth(COLUMN_WIDTH_IS_CALLED);
+//		column.setData(new Integer(COLUMN_ID_IS_CALLED3));
+		column.setData(new Integer(COLUMN_ID_IS_CALLED));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new CalledColumnSelectionHandler());
+
+		table.setLayoutData(new GridData(GridData.FILL_BOTH));
+//		table.setLayout(new FillLayout());
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+		table.setRedraw(true);
+		
+		// when a row is selected, allow the user to double-click or right click and make that function the selected function
+		table.addSelectionListener(new SelectionAdapter() {
+
+			public void widgetDefaultSelected(SelectionEvent se) {
+				TableItem item = (TableItem)se.item;
+				Table table = (Table)se.widget;
+				CallerCalleeItem callerCallee = (CallerCalleeItem)item.getData();
+				
+				// deselect this row
+				table.deselectAll();
+				
+				// choose this row's function
+				chooseNewFunction(callerCallee);
+			}
+		});
+		
+		table.addMouseListener(new CalleeMouseListener());
+		
+		table.addFocusListener(new FocusListener() {
+			IAction oldCopyAction = null;
+
+			public void focusGained(org.eclipse.swt.events.FocusEvent arg0) {
+				IActionBars bars = PIPageEditor.getActionBars();
+				
+				// modify what is executed when Copy is called from the Edit menu
+				oldCopyAction = bars.getGlobalActionHandler(ActionFactory.COPY.getId());
+
+				bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
+
+				copyAction.setEnabled(calleeTable.getSelectionCount() > 0);
+				bars.updateActionBars();
+				
+				// add to the Edit menu
+		        IMenuManager editMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_EDIT);
+
+		        if (editMenuManager instanceof SubMenuManager)
+		        {
+		        	IContributionManager editManager = ((SubMenuManager)editMenuManager).getParent();
+		        	ActionContributionItem item;
+
+					editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
+					copyTableAction.setEnabled(calleeTable.getItemCount() > 0);
+		        	item = new ActionContributionItem(copyTableAction);
+		        	item.setVisible(true);
+		        	editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+		        }
+				
+				// add to the File menu
+		        IMenuManager fileMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_FILE);
+
+		        if (fileMenuManager instanceof SubMenuManager)
+		        {
+		        	IContributionManager fileManager = ((SubMenuManager)fileMenuManager).getParent();
+		        	ActionContributionItem item;
+
+					fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
+					saveTableAction.setEnabled(calleeTable.getItemCount() > 0);
+		        	item = new ActionContributionItem(saveTableAction);
+		        	item.setVisible(true);
+		        	fileManager.insertAfter("saveAll", item); //$NON-NLS-1$
+		        }
+			}
+
+			public void focusLost(org.eclipse.swt.events.FocusEvent arg0) {
+				IActionBars bars = PIPageEditor.getActionBars();
+				bars.setGlobalActionHandler(ActionFactory.COPY.getId(), oldCopyAction);
+				bars.updateActionBars();
+
+				SubMenuManager editMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_EDIT);
+				editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
+
+				SubMenuManager fileMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_FILE);
+				fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
+			}
+		});
+	}
+	
+	private void chooseNewFunction(CallerCalleeItem callerCalleeItem)
+	{
+		// find the correct line in the function table and select it
+		int count = currentFunctionTable.getItemCount();
+
+		for (int i = 0; i < count; i++) {
+			GfcFunctionItem functionItem = (GfcFunctionItem)(currentFunctionTable.getItem(i).getData());
+			if (   functionItem.name.equals(callerCalleeItem.item.name)
+				&& functionItem.dllName.equals(callerCalleeItem.item.dllName)) {
+				currentFunctionTable.select(i);
+				currentFunctionTable.showSelection();
+				updateCallerCalleeTables(functionItem);
+				return;
+			}
+		}
+	}
+
+	public void updateCallerCalleeTables(GfcFunctionItem item)
+	{
+		Table table;
+		TableColumn sortByColumn;
+
+   		setCallerListToFunctionsThatCallThisFunction(item);
+    	setCalleeListToFunctionsThisFunctionCalls(item);
+    	
+    	callerTableViewer.setInput(callerList);
+
+    	if ((callerList != null) && (callerList.length > 0)) {
+    		SharedSorter sorter = ((SharedSorter) callerTableViewer.getSorter());
+    		int columnID = sorter.getColumnID();
+    		
+    		if (columnID == -1) {
+    			columnID = COLUMN_ID_CALLER_PERCENT;
+    		} else {
+    			sorter.setSortAscending(!sorter.getSortAscending());
+    		}
+			sorter.doSort(columnID);
+ 	
+	    	sortByColumn = null;
+	    	table = callerTableViewer.getTable();
+			for (int i = 0; i < table.getColumnCount(); i++) {
+				if (table.getColumn(i).getData() instanceof Integer) {
+					if (((Integer)table.getColumn(i).getData()) == columnID) {
+						sortByColumn = table.getColumn(i);
+						break;
+					}
+				}
+			}
+	
+			if (sortByColumn != null) {
+				table.setSortColumn(sortByColumn);
+				table.setSortDirection(sorter.getSortAscending() ? SWT.UP : SWT.DOWN);
+			}
+	    	callerTableViewer.refresh();
+    	} else {
+    		callerTableViewer.getTable().setSortColumn(null);
+    	}
+
+    	calleeTableViewer.setInput(calleeList);
+
+    	if ((calleeList != null) && (calleeList.length > 0)) {
+    		SharedSorter sorter = ((SharedSorter) calleeTableViewer.getSorter());
+    		int columnID = sorter.getColumnID();
+    		
+    		if (columnID == -1) {
+    			columnID = COLUMN_ID_CALLEE_PERCENT;
+    		} else {
+    			sorter.setSortAscending(!sorter.getSortAscending());
+    		}
+			sorter.doSort(columnID);
+	
+	    	sortByColumn = null;
+	    	table = calleeTableViewer.getTable();
+			for (int i = 0; i < table.getColumnCount(); i++) {
+				if (table.getColumn(i).getData() instanceof Integer) {
+					if (((Integer)table.getColumn(i).getData()) == columnID) {
+						sortByColumn = table.getColumn(i);
+						break;
+					}
+				}
+			}
+	
+			if (sortByColumn != null) {
+				table.setSortColumn(sortByColumn);
+				table.setSortDirection(sorter.getSortAscending() ? SWT.UP : SWT.DOWN);
+			}
+			calleeTableViewer.refresh();
+    	} else {
+    		calleeTableViewer.getTable().setSortColumn(null);
+    	}
+	}
+	
+	private class CallerMouseListener implements MouseListener
+	{
+		public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent me) {}
+
+		public void mouseDown(org.eclipse.swt.events.MouseEvent me) {}
+
+		public void mouseUp(org.eclipse.swt.events.MouseEvent me) {
+			copyAction.setEnabled(callerTable.getSelectionCount() > 0);
+			copyTableAction.setEnabled(callerTable.getItemCount() > 0);
+
+			// only look for button 3 (right click)
+			if (me.button != MouseEvent.BUTTON3)
+				return;
+
+			// make the caller table the menu table
+			currentMenuTable = callerTable;
+
+			if (callerMenu != null) {
+				callerMenu.dispose();
+			}
+
+			callerMenu = new Menu(callerTable.getShell(), SWT.POP_UP); 
+			
+			MenuItem showCallInfoItem = new MenuItem(callerMenu, SWT.PUSH);
+			showCallInfoItem.setText(Messages.getString("CallVisualiser.showCallInfo")); //$NON-NLS-1$
+			showCallInfoItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent se) {
+				    // based on the table's selected item, update the tables
+					TableItem[] selections = callerTable.getSelection();
+					callerTable.deselectAll();
+					
+					if (selections.length != 0)
+						chooseNewFunction((CallerCalleeItem)selections[0].getData());
+				}
+			});
+			
+			new MenuItem(callerMenu, SWT.SEPARATOR);
+			
+			MenuItem sourceLookupItem = new MenuItem(callerMenu, SWT.PUSH);
+			sourceLookupItem.setText(Messages.getString("CallVisualiser.sourcelookup"));	//$NON-NLS-1$
+			sourceLookupItem.addSelectionListener(new SelectionListener() {
+
+				public void widgetDefaultSelected(SelectionEvent arg0) {
+				}
+
+				public void widgetSelected(SelectionEvent arg0) {
+					doSourceLookup(callerTable);
+				}
+				
+			});
+
+			if (callerTable.getSelectionCount() == 0) {
+				showCallInfoItem.setEnabled(false);
+				sourceLookupItem.setEnabled(false);
+			}
+
+			// add copy, copy all, and save all
+			new MenuItem(callerMenu, SWT.SEPARATOR);
+			getCopyItem(callerMenu, callerTable.getSelectionCount() > 0);
+			getCopyTableItem(callerMenu, callerTable.getItemCount() > 0);
+			copyAction.setEnabled(callerTable.getSelectionCount() > 0);
+			copyTableAction.setEnabled(callerTable.getItemCount() > 0);
+
+			new MenuItem(callerMenu, SWT.SEPARATOR);
+			getSaveTableItem(callerMenu, callerTable.getItemCount() > 0);
+			saveTableAction.setEnabled(callerTable.getItemCount() > 0);
+			
+			// save samples
+			int startTime = (int) (PIPageEditor.currentPageEditor().getStartTime() * 1000.0f);
+			int endTime   = (int) (PIPageEditor.currentPageEditor().getEndTime()   * 1000.0f);
+
+			if ((startTime == -1) || (endTime   == -1) || (startTime == endTime))
+				getSaveSamplesItem(callerMenu, false); //$NON-NLS-1$
+			else
+				getSaveSamplesItem(callerMenu, true); //$NON-NLS-1$
+			
+			callerMenu.setLocation(callerTable.getParent().toDisplay(me.x, me.y));
+			callerMenu.setVisible(true);
+			callerTable.setMenu(callerMenu);
+		}
+	}
+	
+	private class CurrentFunctionMouseListener implements MouseListener
+	{
+		public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent me) {}
+
+		public void mouseDown(org.eclipse.swt.events.MouseEvent me) {}
+
+		public void mouseUp(org.eclipse.swt.events.MouseEvent me) {
+			copyAction.setEnabled(currentFunctionTable.getSelectionCount() > 0);
+			copyTableAction.setEnabled(currentFunctionTable.getItemCount() > 0);
+			functionCopyFunctionAction.setEnabled(currentFunctionTable.getSelectionCount() > 0);
+
+			// only look for button 3 (right click)
+			if (me.button != MouseEvent.BUTTON3)
+				return;
+
+			// make the current function table the menu table
+			currentMenuTable = currentFunctionTable;
+
+			if (currentFunctionMenu != null) {
+				currentFunctionMenu.dispose();
+			}
+
+			currentFunctionMenu = new Menu(currentFunctionTable.getShell(), SWT.POP_UP); 
+			
+//			new MenuItem(callerMenu, SWT.SEPARATOR);
+			
+			MenuItem sourceLookupItem = new MenuItem(currentFunctionMenu, SWT.PUSH);
+			sourceLookupItem.setText(Messages.getString("CallVisualiser.sourcelookup"));	//$NON-NLS-1$
+			sourceLookupItem.addSelectionListener(new SelectionListener() {
+
+				public void widgetDefaultSelected(SelectionEvent arg0) {
+				}
+
+				public void widgetSelected(SelectionEvent arg0) {
+					doSourceLookup(currentFunctionTable);
+				}
+				
+			});
+			
+			if (currentFunctionTable.getSelectionCount() == 0) {
+				sourceLookupItem.setEnabled(false);
+			}
+
+			// add copy, copy all, copy caller/callee info, save all, save caller/callee info
+			new MenuItem(currentFunctionMenu, SWT.SEPARATOR);
+			getCopyItem(currentFunctionMenu, currentFunctionTable.getSelectionCount() > 0);
+			getCopyTableItem(currentFunctionMenu, currentFunctionTable.getItemCount() > 0);
+			getCopyFunctionItem(currentFunctionMenu, currentFunctionTable.getSelectionCount() > 0);
+			copyAction.setEnabled(currentFunctionTable.getSelectionCount() > 0);
+			copyTableAction.setEnabled(currentFunctionTable.getItemCount() > 0);
+			functionCopyFunctionAction.setEnabled(currentFunctionTable.getSelectionCount() > 0);
+
+			new MenuItem(currentFunctionMenu, SWT.SEPARATOR);
+			getSaveTableItem(currentFunctionMenu, currentFunctionTable.getItemCount() > 0);
+			getSaveFunctionItem(currentFunctionMenu, currentFunctionTable.getSelectionCount() > 0);
+			saveTableAction.setEnabled(currentFunctionTable.getItemCount() > 0);
+			functionSaveFunctionAction.setEnabled(currentFunctionTable.getSelectionCount() > 0);
+			
+			// save samples
+			int startTime = (int) (PIPageEditor.currentPageEditor().getStartTime() * 1000.0f);
+			int endTime   = (int) (PIPageEditor.currentPageEditor().getEndTime()   * 1000.0f);
+
+			if ((startTime == -1) || (endTime   == -1) || (startTime == endTime))
+				getSaveSamplesItem(currentFunctionMenu, false); //$NON-NLS-1$
+			else
+				getSaveSamplesItem(currentFunctionMenu, true); //$NON-NLS-1$
+
+			currentFunctionMenu.setLocation(currentFunctionTable.getParent().toDisplay(me.x, me.y));
+			currentFunctionMenu.setVisible(true);
+			currentFunctionTable.setMenu(currentFunctionMenu);
+		}
+	}
+
+	private class CalleeMouseListener implements MouseListener
+	{
+		public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent me) {}
+
+		public void mouseDown(org.eclipse.swt.events.MouseEvent me) {}
+
+		public void mouseUp(org.eclipse.swt.events.MouseEvent me) {
+			copyAction.setEnabled(calleeTable.getSelectionCount() > 0);
+			copyTableAction.setEnabled(calleeTable.getItemCount() > 0);
+
+			// only look for button 3 (right click)
+			if (me.button != MouseEvent.BUTTON3)
+				return;
+
+			// make the callee table the menu table
+			currentMenuTable = calleeTable;
+
+			if (calleeMenu != null) {
+				calleeMenu.dispose();
+			}
+			
+			calleeMenu = new Menu(calleeTable.getShell(), SWT.POP_UP); 
+			
+			MenuItem showCallInfoItem = new MenuItem(calleeMenu, SWT.PUSH);
+			showCallInfoItem.setText(Messages.getString("CallVisualiser.showCallInfo")); //$NON-NLS-1$
+			showCallInfoItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent se) {
+				    // based on the table's selected item, update the tables
+					TableItem[] selections = calleeTable.getSelection();
+					calleeTable.deselectAll();
+					
+					if (selections.length != 0)
+						chooseNewFunction((CallerCalleeItem)selections[0].getData());
+				}
+			});
+			
+			new MenuItem(calleeMenu, SWT.SEPARATOR);
+			
+			MenuItem sourceLookupItem = new MenuItem(calleeMenu, SWT.PUSH);
+			sourceLookupItem.setText(Messages.getString("CallVisualiser.sourcelookup"));	//$NON-NLS-1$
+			sourceLookupItem.addSelectionListener(new SelectionListener() {
+
+				public void widgetDefaultSelected(SelectionEvent arg0) {
+				}
+
+				public void widgetSelected(SelectionEvent arg0) {
+					doSourceLookup(calleeTable);
+				}
+				
+			});
+			
+			if (calleeTable.getSelectionCount() == 0) {
+				showCallInfoItem.setEnabled(false);
+				sourceLookupItem.setEnabled(false);
+			}
+
+			// add copy, copy all, and save all
+			new MenuItem(calleeMenu, SWT.SEPARATOR);
+			getCopyItem(calleeMenu, calleeTable.getSelectionCount() > 0);
+			getCopyTableItem(calleeMenu, calleeTable.getItemCount() > 0);
+			copyAction.setEnabled(calleeTable.getSelectionCount() > 0);
+			copyTableAction.setEnabled(calleeTable.getItemCount() > 0);
+
+			new MenuItem(calleeMenu, SWT.SEPARATOR);
+			getSaveTableItem(calleeMenu, calleeTable.getItemCount() > 0);
+			saveTableAction.setEnabled(calleeTable.getItemCount() > 0);
+			
+			// save samples
+			int startTime = (int) (PIPageEditor.currentPageEditor().getStartTime() * 1000.0f);
+			int endTime   = (int) (PIPageEditor.currentPageEditor().getEndTime()   * 1000.0f);
+
+			if ((startTime == -1) || (endTime   == -1) || (startTime == endTime))
+				getSaveSamplesItem(calleeMenu, false); //$NON-NLS-1$
+			else
+				getSaveSamplesItem(calleeMenu, true); //$NON-NLS-1$
+
+			calleeMenu.setLocation(calleeTable.getParent().toDisplay(me.x, me.y));
+			calleeMenu.setVisible(true);
+			calleeTable.setMenu(calleeMenu);
+		}
+	}
+	
+	protected void createDefaultActions(boolean copyFunction)
+	{
+		copyAction = new Action(Messages.getString("CallVisualiser.0")) { //$NON-NLS-1$
+			public void run() {
+				action("copy"); //$NON-NLS-1$
+			}
+		};
+		copyAction.setEnabled(false);
+
+		copyTableAction = new Action(Messages.getString("CallVisualiser.1")) { //$NON-NLS-1$
+			public void run() {
+				action("copyTable"); //$NON-NLS-1$
+			}
+		};
+		copyTableAction.setEnabled(true);
+		copyTableAction.setId("PICopyTable"); //$NON-NLS-1$
+		copyTableAction.setText(Messages.getString("CallVisualiser.CopyTable")); //$NON-NLS-1$
+
+		saveTableAction = new Action(Messages.getString("CallVisualiser.2")) { //$NON-NLS-1$
+			public void run() {
+				action("saveTable"); //$NON-NLS-1$
+			}
+		};
+		saveTableAction.setEnabled(true);
+		saveTableAction.setId("PISaveTable"); //$NON-NLS-1$
+		saveTableAction.setText(Messages.getString("CallVisualiser.SaveTable")); //$NON-NLS-1$
+
+		functionCopyFunctionAction = new Action(Messages.getString("CallVisualiser.3")) { //$NON-NLS-1$
+			public void run() {
+				action("copyFunction"); //$NON-NLS-1$
+			}
+		};
+		functionCopyFunctionAction.setEnabled(true);
+		functionCopyFunctionAction.setId("PICopyFunction"); //$NON-NLS-1$
+		functionCopyFunctionAction.setText(Messages.getString("CallVisualiser.CopyDataForFunction")); //$NON-NLS-1$
+
+		functionSaveFunctionAction = new Action(Messages.getString("CallVisualiser.4")) { //$NON-NLS-1$
+			public void run() {
+				action("saveFunction"); //$NON-NLS-1$
+			}
+		};
+		functionSaveFunctionAction.setEnabled(true);
+		functionSaveFunctionAction.setId("PISaveFunction"); //$NON-NLS-1$
+		functionSaveFunctionAction.setText(Messages.getString("CallVisualiser.SaveDataForFunction")); //$NON-NLS-1$
+	}
+
+	private class SharedLabelProvider extends LabelProvider implements ITableLabelProvider {
+		
+		Table table;
+
+		public SharedLabelProvider(Table table) {
+			super();
+			this.table = table;
+		}
+
+		public String getColumnText(Object element, int columnIndex) {
+			if (   !(element instanceof GfcFunctionItem)
+				&& !(element instanceof CallerCalleeItem))
+				return ""; //$NON-NLS-1$
+
+			int columnId = ((Integer) this.table.getColumn(columnIndex).getData()).intValue();
+			
+			GfcFunctionItem item = null;
+			
+			if (element instanceof GfcFunctionItem)
+				item = (GfcFunctionItem)element;
+			else
+				item = ((CallerCalleeItem)element).item;
+
+			switch (columnId)
+			{
+				case COLUMN_ID_CALLEE_PERCENT:
+				case COLUMN_ID_CALLER_PERCENT:
+				{
+					double percent;
+					if (element instanceof CallerCalleeItem)
+						percent = ((CallerCalleeItem)element).percent;
+					else
+						percent = 0.0;
+						
+					// Percent load string
+					return (new DecimalFormat(Messages.getString("CallVisualiser.shortDecimalFormat"))).format(percent); //$NON-NLS-1$
+				}
+				case COLUMN_ID_FUNCTION:
+				{
+					// Function
+					return item.name;
+				}
+				case COLUMN_ID_START_ADDR:
+				{
+					// Function start
+					return Long.toHexString(item.address);
+				}
+				case COLUMN_ID_IN_BINARY:
+				{
+					// Binary
+					String binary = item.dllName;
+					int index = binary.lastIndexOf('\\');
+					if (index == -1)
+						return binary;
+					else
+						return binary.substring(index + 1);
+				}
+				case COLUMN_ID_IN_BINARY_PATH:
+				{
+					// Path
+					String binary = item.dllName;
+					int index = binary.lastIndexOf('\\');
+					if (index == -1)
+						return ""; //$NON-NLS-1$
+					else
+						return binary.substring(0, index);
+				}
+				case COLUMN_ID_IS_CALLED:
+				{
+					// Percent load string
+					return (new DecimalFormat(Messages.getString("CallVisualiser.decimalFormat"))).format(myTrace.getAbsoluteTraditionalPercentageFor(item)); //$NON-NLS-1$
+				}
+				case COLUMN_ID_IS_CALLER:
+				{
+					// Percent load string
+					return (new DecimalFormat(Messages.getString("CallVisualiser.decimalFormat"))).format(myTrace.getAbsoluteCallerPercentageFor(item)); //$NON-NLS-1$
+				}
+				case COLUMN_ID_RECURSIVE_CALL:
+				{
+					// Percent load string
+					return (new DecimalFormat(Messages.getString("CallVisualiser.decimalFormat"))).format(myTrace.getRecursiveCallerPrecentageFor(item)); //$NON-NLS-1$
+				}
+				case COLUMN_ID_IS_CALLED_COUNT:
+				{
+					// Sample count
+					int samples;
+					if (element instanceof CallerCalleeItem)
+						samples = ((CallerCalleeItem)element).samples;
+					else
+						samples = item.isCalledCount();
+					return String.valueOf(samples);
+				}
+				case COLUMN_ID_IS_CALLER_COUNT:
+				{
+					// Sample count
+					int samples;
+					if (element instanceof CallerCalleeItem)
+						samples = ((CallerCalleeItem)element).samples;
+					else
+						samples = item.isCallerCount();
+					return String.valueOf(samples);
+				}
+				default:
+				{
+					break;
+				}
+			}
+			// should never get here
+			return ""; //$NON-NLS-1$
+		}
+
+		public Image getColumnImage(Object element, int columnIndex) {
+			return null;
+		}
+	}
+
+	public void selectFunction(String functionName)
+	{
+	}
+  
+	public void setStartAndEnd(int start, int end)
+	{
+		if (this.myTrace == null)
+			return;
+		
+	    this.myTrace.parseEntries(start, end);
+	    this.functionArray = myTrace.getEntriesSorted(GfcTrace.SORT_BY_TOTAL_LOAD);
+	    this.currentFunctionTableViewer.setInput(this.functionArray);
+		
+	    updateCallerCalleeTables(null);
+	    
+	    Table table = this.currentFunctionTableViewer.getTable();
+	    
+	    if (table.getItemCount() == 0)
+	    	return;
+	    
+	    if (table.getSortColumn() == null) {
+	    	table.setSortColumn(currentFunctionDefaultColumn);
+	    	table.setSortDirection(SWT.UP);
+	    } else {
+	    	// use the user's preferred sort column, if any
+	    	boolean sortAscending = !((SharedSorter) currentFunctionTableViewer.getSorter()).getSortAscending();
+			((SharedSorter) currentFunctionTableViewer.getSorter()).setSortAscending(sortAscending);
+	    }
+	    
+	    sortAndRefresh(this.currentFunctionTableViewer, table.getSortColumn());
+	}
+
+	private static class CallerCalleeItem {
+	    GfcFunctionItem item;
+	    double percent;
+	    int samples;
+	}
+	
+	public void setCallerListToFunctionsThatCallThisFunction(GfcFunctionItem function)
+	{
+		if (function == null) {
+			this.callerList = null;
+			return;
+		}
+
+		GfcFunctionItem[] list = function.getCallerList();
+	    Double[] perc = function.getCallerPercentages();
+	
+	    this.callerList = new CallerCalleeItem[list.length];
+	    
+	    for (int i = 0; i < list.length; i++)
+	    {
+	    	this.callerList[i] = new CallerCalleeItem();
+	    	this.callerList[i].item    = list[i];
+	    	this.callerList[i].percent = perc[i];
+	    	this.callerList[i].samples = (int) (perc[i] * function.isCalledCount() + 0.5) / 100;
+	    }
+	}
+
+	public void setCalleeListToFunctionsThisFunctionCalls(GfcFunctionItem function)
+	{
+		if (function == null) {
+			this.calleeList = null;
+			return;
+		}
+
+	    GfcFunctionItem[] list = function.getCalleeList();
+	    Double[] perc = function.getCalleePercentages();
+	
+	    this.calleeList = new CallerCalleeItem[list.length];
+	    
+	    for (int i = 0; i < list.length; i++)
+	    {
+	    	this.calleeList[i] = new CallerCalleeItem();
+	    	this.calleeList[i].item    = list[i];
+	    	this.calleeList[i].percent = perc[i];
+	    	this.calleeList[i].samples = (int) (perc[i] * function.isCallerCount() + 0.5) / 100;
+	    }
+	}
+
+	public void action(String actionString) {
+		if (actionString.equals("copy")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, currentMenuTable, CHECKBOX_NONE, false, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("copyTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, currentMenuTable, CHECKBOX_NONE, true, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("copyFunction")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSaveFunction(true, "\t"); //$NON-NLS-1$
+	        return;
+	    }
+	    else if (actionString.equals("saveTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(false, currentMenuTable, CHECKBOX_NONE, true, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return;
+	    }
+	    else if (actionString.equals("saveFunction")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSaveFunction(false, ","); //$NON-NLS-1$
+	        return;
+	    }
+	    else if (actionString.equals("saveSamples")) //$NON-NLS-1$
+	    {
+	    	SaveSampleString saveSampleString = new SaveSampleString();
+	    	actionSaveSamples(saveSampleString); //$NON-NLS-1$
+	        return;
+	    }
+	    else if (actionString.equals("saveTableTest")) //$NON-NLS-1$
+	    {
+			// copy save file contents to the clipboard for easy viewing
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+			SaveTableString getString = new SaveTableString(currentMenuTable, CHECKBOX_NONE, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        String copyString = getString.getData();
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+	        return;
+	    }
+	    else if (actionString.equals("saveFunctionTest")) //$NON-NLS-1$
+	    {
+			// copy save file contents to the clipboard for easy viewing
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+	        SaveFunctionString getString = new SaveFunctionString(","); //$NON-NLS-1$
+	        String copyString = getString.getData();
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+	        return;
+	    }
+	}
+	
+	/*
+	 * TableViewer sorter for the called-by and called function tableviewers
+	 */
+	private class SharedSorter extends ViewerSorter {
+		// sort direction
+		private boolean sortAscending;
+		
+		// last column sorted
+		private int column = -1;
+		
+		/* 
+		 * decide on which column to sort by, and the sort ordering
+		 */
+		public void doSort(int column) {
+			// ignore the column passed in and use the id set by the column selection handler
+			if (column == this.column) {
+				// sort in other order
+				sortAscending = !sortAscending;
+			} else {
+				switch (column) {
+					case COLUMN_ID_FUNCTION:
+					case COLUMN_ID_START_ADDR:
+					case COLUMN_ID_IN_BINARY:
+					case COLUMN_ID_IN_BINARY_PATH:
+					{
+		            	// sort in ascending order
+		            	sortAscending = true;
+		                break;
+					}
+					case COLUMN_ID_IS_CALLED:
+					case COLUMN_ID_IS_CALLER:
+					case COLUMN_ID_RECURSIVE_CALL:
+					case COLUMN_ID_CALLER_PERCENT:
+					case COLUMN_ID_CALLEE_PERCENT:
+					case COLUMN_ID_IS_CALLED_COUNT:
+					case COLUMN_ID_IS_CALLER_COUNT:
+					{
+		            	// sort in descending order
+		            	sortAscending = false;
+		                break;
+					}
+					default:
+					{
+						// ignore the column
+						return;
+					}
+				}
+				this.column = column;
+			}
+		}
+		
+		/*
+		 * compare two items from a table column
+		 */
+		public int compare(Viewer viewer, Object e1, Object e2) {
+			int comparison = 0;
+			
+			GfcFunctionItem item1 = null;
+			GfcFunctionItem item2 = null;
+			CallerCalleeItem ccItem1 = null;
+			CallerCalleeItem ccItem2 = null;
+			
+			if (e1 instanceof GfcFunctionItem) {
+				item1 = (GfcFunctionItem) e1;
+				item2 = (GfcFunctionItem) e2;
+			} else {
+				ccItem1 = (CallerCalleeItem)e1;
+				ccItem2 = (CallerCalleeItem)e2;
+				item1 =   ccItem1.item;
+				item2 =   ccItem2.item;
+			}
+
+			switch (column) {
+				case COLUMN_ID_CALLER_PERCENT:
+				case COLUMN_ID_CALLEE_PERCENT:
+				{
+					double percent1;
+					double percent2;
+					if (e1 instanceof GfcFunctionItem) {
+						percent1 = 0.0;
+						percent2 = 0.0;
+					} else {
+						percent1 = ccItem1.percent;
+						percent2 = ccItem2.percent;
+					}
+					comparison = percent1 > percent2 ? 1 : -1;
+					break;
+				}
+				case COLUMN_ID_FUNCTION:
+				{
+					comparison = this.getComparator().compare(item1.name, item2.name);
+					break;
+				}
+				case COLUMN_ID_START_ADDR:
+				{
+					comparison = (item1.address > item2.address) ? 1 : -1; 
+					break;
+				}
+				case COLUMN_ID_IN_BINARY:
+				{
+					int index;
+					String name1 = item1.dllName;
+					index = name1.lastIndexOf('\\');
+					if (index != -1)
+						name1 = name1.substring(index);
+
+					String name2 = item2.dllName;
+					index = name2.lastIndexOf('\\');
+					if (index != -1)
+						name2 = name2.substring(index);
+
+					comparison = this.getComparator().compare(name1, name2);
+					break;
+				}
+				case COLUMN_ID_IN_BINARY_PATH:
+				{
+					int index;
+					String name1 = item1.dllName;
+					index = name1.lastIndexOf('\\');
+					if (index == -1)
+						name1 = ""; //$NON-NLS-1$
+					else
+						name1 = name1.substring(0, index);
+
+					String name2 = item2.dllName;
+					index = name2.lastIndexOf('\\');
+					if (index == -1)
+						name2 = ""; //$NON-NLS-1$
+					else
+						name2 = name2.substring(0, index);
+
+					comparison = this.getComparator().compare(name1, name2);
+					break;
+				}
+				case COLUMN_ID_IS_CALLED:
+				{
+					// actual sample count used as a proxy for the percentage
+					comparison = item1.isCalledCount() - item2.isCalledCount();
+					break;
+				}
+				case COLUMN_ID_IS_CALLER:
+				{
+					// actual sample count used as a proxy for the percentage
+					comparison = item1.isCallerCount() - item2.isCallerCount();
+					break;
+				}
+				case COLUMN_ID_RECURSIVE_CALL:
+				{
+					comparison = myTrace.getRecursiveCallerPrecentageFor(item1) >
+								 myTrace.getRecursiveCallerPrecentageFor(item2) ? 1 : -1;
+					break;
+				}
+				case COLUMN_ID_IS_CALLED_COUNT:
+				{
+					if (e1 instanceof GfcFunctionItem) {
+						comparison = item1.isCalledCount() - item2.isCalledCount();
+					} else {
+						comparison = ccItem1.samples - ccItem2.samples;
+					}
+					break;
+				}
+				case COLUMN_ID_IS_CALLER_COUNT:
+				{
+					if (e1 instanceof GfcFunctionItem) {
+						comparison = item1.isCallerCount() - item2.isCallerCount();
+					} else {
+						comparison = ccItem1.samples - ccItem2.samples;
+					}
+					break;
+				}
+				default:
+				{
+					break;
+				}
+			}
+
+			// for descending order, reverse the sense of the compare
+			if (!sortAscending)
+				comparison = -comparison;
+			return comparison;
+		}
+		
+		public boolean getSortAscending() {
+			return sortAscending;
+		}
+		
+		public void setSortAscending(boolean sortAscending) {
+			this.sortAscending = sortAscending;
+		}
+		
+		public int getColumnID() {
+			return column;
+		}
+	}
+	
+	public void sortAndRefresh(TableViewer tableViewer, TableColumn tableColumn)
+	{
+		Table table = tableViewer.getTable();
+    	int columnID = ((Integer) tableColumn.getData()).intValue();
+    	
+    	if (table.getItemCount() == 0)
+    		return;
+		
+		// sort by selected columnID
+    	((SharedSorter) tableViewer.getSorter()).doSort(columnID);
+		table.setSortColumn(tableColumn);
+		table.setSortDirection(((SharedSorter) tableViewer.getSorter()).getSortAscending() ? SWT.UP : SWT.DOWN);
+		tableViewer.refresh();
+	}
+
+	private class CalledByColumnSelectionHandler extends SelectionAdapter
+	{
+		public void widgetSelected(SelectionEvent e)
+        {
+        	if (!(e.widget instanceof TableColumn))
+        		return;
+        	
+        	sortAndRefresh(callerTableViewer, (TableColumn) e.widget);
+       }
+	}
+
+	private class CalledColumnSelectionHandler extends SelectionAdapter
+	{
+		public void widgetSelected(SelectionEvent e)
+        {
+        	if (!(e.widget instanceof TableColumn))
+        		return;
+
+        	sortAndRefresh(calleeTableViewer, (TableColumn) e.widget);
+        }
+	}
+
+	private class CheckboxColumnSelectionHandler extends SelectionAdapter
+	{
+		public void widgetSelected(SelectionEvent e)
+        {
+        	if (!(e.widget instanceof TableColumn))
+        		return;
+
+        	sortAndRefresh(currentFunctionTableViewer, (TableColumn) e.widget);
+        }
+	}
+	
+	public PIPageEditor getPageEditor()
+	{
+		return this.pageEditor;
+	}
+	
+	public int getPageIndex()
+	{
+		return this.pageIndex;
+	}
+	
+	private MenuItem getCopyFunctionItem(Menu menu, boolean enabled) {
+	    MenuItem copyFunctionItem = new MenuItem(menu, SWT.PUSH);
+	    
+		copyFunctionItem.setText(Messages.getString("CallVisualiser.CopyDataForFunction")); //$NON-NLS-1$
+		copyFunctionItem.setEnabled(enabled);
+		
+		if (enabled) {
+			copyFunctionItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("copyFunction"); //$NON-NLS-1$
+				}
+			});
+		}
+		
+		return copyFunctionItem;
+	}
+	
+	private MenuItem getSaveFunctionItem(Menu menu, boolean enabled) {
+	    MenuItem saveFunctionItem = new MenuItem(menu, SWT.PUSH);
+	    
+		saveFunctionItem.setText(Messages.getString("CallVisualiser.SaveDataForFunction")); //$NON-NLS-1$
+		saveFunctionItem.setEnabled(enabled);
+		
+		if (enabled) {
+			saveFunctionItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("saveFunction"); //$NON-NLS-1$
+				}
+			});
+		}
+		
+		return saveFunctionItem;
+	}
+
+	private void doSourceLookup(Table mytable) {
+		// source look up for selected items
+		if ((mytable.getItemCount() == 0) || (mytable.getSelectionCount() == 0))
+			return;
+
+		TableItem selectedItem = mytable.getSelection()[0];
+		Object selectedData = selectedItem.getData();
+		String functionName = null;
+		String binaryName = null;
+		if (selectedData instanceof GfcFunctionItem) {
+			GfcFunctionItem functionItem = (GfcFunctionItem) selectedData;
+			functionName = functionItem.name;
+			binaryName = functionItem.dllName;
+		} else if (selectedData instanceof CallerCalleeItem) {
+			CallerCalleeItem callerCalleeItem = (CallerCalleeItem) selectedData;
+			functionName = callerCalleeItem.item.name;
+			binaryName = callerCalleeItem.item.dllName;
+		}
+		if (functionName != null && binaryName != null)
+		{
+			SourceLookup.getInstance().lookupAndopenEditorWithHighlight(functionName , binaryName);
+		}
+
+	}
+	
+	// class to pass the function caller/callee data to the save wizard
+	private class SaveFunctionString implements ISaveTable {
+		private String separator;
+		
+		public SaveFunctionString(String separator) {
+			this.separator = separator;
+		}
+
+		public String getData() {
+			return copyFunction(separator);
+		}
+	}
+	
+    private void actionCopyOrSaveFunction(boolean doCopy, String separator)
+    {
+    	// one function must be selected
+    	if (currentFunctionTable.getSelectionCount() != 1)
+    		return;
+ 
+		// copy one function's caller and callee data to the clipboard or save to a file
+		if (doCopy) {
+			// change the clipboard contents
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+			String copyString = copyFunction(separator);
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+	    } else {
+			SaveFunctionString getString = new SaveFunctionString(separator);
+			WizardDialog dialog;
+			Wizard w = new SaveTableWizard(getString);
+			dialog = new WizardDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), w);
+	    	dialog.open();
+	    }
+    }
+
+    private String copyFunction(String separator)
+	{	
+    	// one function must be selected
+    	if (currentFunctionTable.getSelectionCount() != 1)
+			return ""; //$NON-NLS-1$
+		
+		String copyString = ""; //$NON-NLS-1$
+
+		// create the multiple table heading line (e.g., "Selected Function     Callers")
+		// space them out based on how many columns are in their table
+		if (currentFunctionTable.getData() instanceof String) {
+			copyString += (String) (currentFunctionTable.getData());
+		}
+		for (int j = 0; j < currentFunctionTable.getColumnCount(); j++) {
+			copyString += separator;
+		}
+
+		if (callerTable.getData() instanceof String) {
+			copyString += (String) (callerTable.getData());
+		}
+		for (int j = 0; j < callerTable.getColumnCount(); j++) {
+			copyString += separator;
+		}
+
+		if (calleeTable.getData() instanceof String) {
+			copyString += (String) (calleeTable.getData());
+		}
+		for (int j = 0; j < calleeTable.getColumnCount(); j++) {
+			copyString += separator;
+		}
+
+		copyString += "\n"; //$NON-NLS-1$
+		
+		// create the multiple table column headings
+		copyString += copyHeading(currentFunctionTable, CHECKBOX_NONE, separator, separator); //$NON-NLS-1$
+		copyString += copyHeading(callerTable, CHECKBOX_NONE, separator, separator); //$NON-NLS-1$
+		copyString += copyHeading(calleeTable, CHECKBOX_NONE, separator, "\n"); //$NON-NLS-1$
+		
+		// determine the row, column count, and column ordering in each table
+		// NOTE: the first table in the copy will contain the function, and it only its
+		// one selected line will be shown
+		int rowCount0      = 1;
+		int columnCount0   = currentFunctionTable.getColumnCount();
+		int[] columnOrder0 = currentFunctionTable.getColumnOrder();
+		boolean[] isHex0   = (boolean[]) currentFunctionTable.getData("isHex"); //$NON-NLS-1$
+		String emptyRow0 = ""; //$NON-NLS-1$
+
+		int rowCount1      = callerTable.getItemCount();
+		int columnCount1   = callerTable.getColumnCount();
+		int[] columnOrder1 = callerTable.getColumnOrder();
+		boolean[] isHex1   = (boolean[]) callerTable.getData("isHex"); //$NON-NLS-1$
+		String emptyRow1 = ""; //$NON-NLS-1$
+
+		int rowCount2      = calleeTable.getItemCount();
+		int columnCount2   = calleeTable.getColumnCount();
+		int[] columnOrder2 = calleeTable.getColumnOrder();
+		boolean[] isHex2   = (boolean[]) calleeTable.getData("isHex"); //$NON-NLS-1$
+		String emptyRow2 = ""; //$NON-NLS-1$
+
+		// determine the number of multiple table rows (max of any table's rows) 
+		int rowCount = rowCount0 >= rowCount1 ? rowCount0 : rowCount1;
+		rowCount = rowCount2 > rowCount ? rowCount2 : rowCount;
+		
+		// generate empty row strings, to speed things up
+		if (rowCount0 < rowCount) {
+			for (int j = 0; j < columnCount0 - 1; j++) {
+				emptyRow0 += separator;
+			}
+		}
+
+		if (rowCount1 < rowCount) {
+			for (int j = 0; j < columnCount1; j++) {
+				emptyRow1 += separator;
+			}
+		}
+
+		if (rowCount2 < rowCount) {
+			for (int j = 0; j < columnCount2; j++) {
+				emptyRow2 += separator;
+			}
+		}
+
+		// generate the rows
+		for (int i = 0; i < rowCount; i++) {
+			if (i < 1) {
+				copyString += copyRow(isHex0, currentFunctionTable.getItem(currentFunctionTable.getSelectionIndex()),
+										CHECKBOX_NONE, columnCount0, columnOrder0, separator);
+			} else {
+				copyString += emptyRow0;
+			}
+			
+			if (i < rowCount1) {
+				copyString += separator + copyRow(isHex1, callerTable.getItem(i), CHECKBOX_NONE, columnCount1, columnOrder1, separator);
+			} else {
+				// NOTE: if this is the last table, or the 3rd table has nothing but empty
+				// rows left, we may not need to fill in these fields
+				copyString += emptyRow1;
+			}
+			
+			if (i < rowCount2) {
+				copyString += separator + copyRow(isHex2, calleeTable.getItem(i), CHECKBOX_NONE, columnCount2, columnOrder2, separator);
+			} else {
+				// NOTE: we may not need to fill in the empty fields of the last table
+				copyString += emptyRow2;
+			}
+			
+			copyString += "\n"; //$NON-NLS-1$
+		}
+		
+		return copyString;
+	}
+	
+    // added to give JUnit tests access
+	public TableViewer getCallerViewer() {
+		return this.callerTableViewer;
+	}
+	
+    // added to give JUnit tests access
+	public TableViewer getCurrentFunctionViewer() {
+		return this.currentFunctionTableViewer;
+	}
+	
+    // added to give JUnit tests access
+	public TableViewer getCalleeViewer() {
+		return this.calleeTableViewer;
+	}
+	
+    // added to give JUnit tests access
+	public void setCurrentMenuTable(Table currentMenuTable) {
+		this.currentMenuTable = currentMenuTable;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/GfcFunctionItem.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.call;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class GfcFunctionItem implements Serializable
+{
+	private static final long serialVersionUID = -8082342532211331507L;
+	
+	// this function has been called by these functions
+	private Hashtable callerData;
+
+	// this function has called these functions
+	private Hashtable calleeData;
+
+	public long address;
+	public String name;
+	public String dllName;
+	private int totalCallerAmount; // really number of times this function is called
+	private int totalCalleeAmount;	// really number of times this function is the caller
+	private boolean percentageUpdated;
+
+	private double recursiveLoad = 0;
+	private double accumulatedRecursiveLoad = 0;
+
+	private double absoluteTotalPercentage = 0;
+	private double absoluteCallerPercentage = 0;
+	private double recursiveTotalPercentage = 0;
+	private double recursiveSampleCount = 0;
+
+	private int storedPercentageStart = -1;
+	private int storedPercentageEnd = -1;
+
+	private boolean isSymbolParsed;
+
+	public GfcFunctionItem(String name, long address, String dllName, boolean isSymbolParsed)
+	{
+		this.isSymbolParsed  = isSymbolParsed;
+		this.address         = address;
+		this.name            = name;
+		this.dllName         = dllName;
+		this.totalCallerAmount   = 0;
+		this.percentageUpdated = false;
+		this.callerData = new Hashtable<Long,GfcFunctionItemData>();
+		this.calleeData = new Hashtable<Long,GfcFunctionItemData>();
+	}
+
+	public boolean isSymbolParsed()
+	{
+		return this.isSymbolParsed;
+	}
+
+	public int isCalledCount() {
+		return this.totalCallerAmount;
+	}
+	
+	public int isCallerCount() {
+		return this.totalCalleeAmount;
+	}
+	
+	public double getAbsoluteTotalPercentage(int start,int end)
+	{
+		if (this.storedPercentageStart == start && this.storedPercentageEnd == end)
+		{
+			return this.absoluteTotalPercentage;
+		}
+		else return -1;
+	}
+
+	public double getAbsoluteCallerPercentage(int start,int end)
+	{
+		if (this.storedPercentageStart == start && this.storedPercentageEnd == end)
+		{
+			return this.absoluteCallerPercentage;
+		}
+		else return -1;
+	}
+
+	public double getRecursiveCallerPercentage(int start,int end)
+	{
+		if (this.storedPercentageStart == start && this.storedPercentageEnd == end)
+		{
+			return this.recursiveTotalPercentage;
+		}
+		else return -1;
+	}
+
+	public void storePercents(double total, double caller, double recursive, int start, int end)
+	{
+		this.absoluteCallerPercentage = caller;
+		this.absoluteTotalPercentage  = total;
+		this.recursiveTotalPercentage = recursive;
+		this.storedPercentageStart    = start;
+		this.storedPercentageEnd      = end;
+	}
+
+	public double getRecursiveCallerSamples(int recursion, double cumulativeValue, GfcFunctionItem exclude)
+	{
+		if (recursion > 10)
+			return 0;
+		recursion++;
+
+		GfcFunctionItem[] callees = this.getCalleeList();
+		Double[] calleePerc = this.getCalleePercentages();
+
+		double callActivity =
+			this.countSamplesWhereThisFunctionIsTheCaller() /
+			(this.countSamplesThatCallThisFunction() +
+			 this.countSamplesWhereThisFunctionIsTheCaller());
+
+		if (this.recursiveSampleCount == 0)
+		{
+			for (int i = 0; i < callees.length; i++)
+			{
+				GfcFunctionItem item = callees[i];
+				Double itemPerc = calleePerc[i];
+
+				if (item != this)
+				{
+					// get the direct value this function causes
+					this.recursiveSampleCount += (itemPerc.doubleValue() / 100) * item.countSamplesThatCallThisFunction();
+
+					// recursively get the values this function calls:
+					// itemPerc = percentage of the function in this functions call share (that sums 100%)
+					// callActivity = factor of samples related to this function, that indicate that this
+					// function has called another function (has been the caller). Call activity is
+					// 100% if all the samples related to this function are such that they have
+					// the pointer to this function only in the link register
+
+					this.recursiveSampleCount += (itemPerc.doubleValue() * callActivity / 100) *
+													item.getRecursiveCallerSamples(recursion, cumulativeValue, this);
+				}
+			}
+		}
+
+		cumulativeValue += this.recursiveSampleCount;
+
+		//System.out.println("rec "+recursion+" cum"+cumulativeValue);
+		return cumulativeValue;
+	}
+
+	public void addRecursiveLoad(double samples)
+	{
+		this.recursiveLoad += samples;
+		this.accumulatedRecursiveLoad += samples;
+	}
+
+	public void setRecursiveLoad(double load)
+	{
+		this.recursiveLoad = load;
+	}
+
+	public double getRecursiveLoad()
+	{
+		return this.recursiveLoad;
+	}
+
+	public double getAccumulatedLoad()
+	{
+		return this.accumulatedRecursiveLoad;
+	}
+
+	public int countSamplesThatCallThisFunction()
+	{
+		int callCount = 0;
+		Enumeration<GfcFunctionItemData> callerEnum = this.callerData.elements();
+		while (callerEnum.hasMoreElements())
+		{
+			GfcFunctionItemData data = callerEnum.nextElement();
+			callCount += data.callTimes.size();
+		}
+		return callCount;
+	}
+
+	public ArrayList getSamplesThatCallThisFunction()
+	{
+		ArrayList callTimes = new ArrayList();
+		Enumeration<GfcFunctionItemData> callerEnum = this.callerData.elements();
+		while (callerEnum.hasMoreElements())
+		{
+			GfcFunctionItemData data = callerEnum.nextElement();
+			callTimes.addAll(data.callTimes);
+		}
+		return callTimes;
+	}
+
+	public int countSamplesWhereThisFunctionIsTheCaller()
+	{
+		int callCount = 0;
+		Enumeration<GfcFunctionItemData> calleeEnum = this.calleeData.elements();
+		while (calleeEnum.hasMoreElements())
+		{
+			GfcFunctionItemData data = calleeEnum.nextElement();
+			callCount += data.callTimes.size();
+		}
+		return callCount;
+	}
+
+	public ArrayList getSamplesWhereThisFunctionIsTheCaller()
+	{
+		ArrayList callTimes = new ArrayList();
+		Enumeration<GfcFunctionItemData> calleeEnum = this.calleeData.elements();
+		while (calleeEnum.hasMoreElements())
+		{
+			GfcFunctionItemData data = calleeEnum.nextElement();
+			callTimes.addAll(data.callTimes);
+		}
+		return callTimes;
+	}
+
+	public static class GfcFunctionItemData implements Serializable
+	{
+		private static final long serialVersionUID = -8082342532211331507L;
+		public GfcFunctionItem function;
+		public Double percentage;
+		// size of the vector indicates the amount
+		// of times this function has been called
+		public Vector callTimes = new Vector();
+	}
+
+	// this function has been called but the caller is unknown
+	public void addUnknownCaller(Integer callTime)
+	{
+		// store unknown callers with an address -1
+		if (!this.callerData.containsKey(new Long(-1)) )
+		{
+			GfcFunctionItemData newData = new GfcFunctionItemData();
+			newData.function = null;
+			newData.percentage = new Double(0);
+			newData.callTimes.add(callTime);
+
+			// add a new caller
+			this.callerData.put(new Long(-1),newData);
+		}
+		else
+		{
+			// just add the call count of an existing caller
+			GfcFunctionItemData oldData = (GfcFunctionItemData)this.callerData.get(new Long(-1));
+			this.totalCallerAmount++;
+			oldData.callTimes.add(callTime);
+		}
+
+		this.percentageUpdated = false;
+	}
+
+	// this function has been called
+	public void addCaller(GfcFunctionItem caller, Integer callTime)
+	{
+		Long address = new Long(caller.address);
+		if (!this.callerData.containsKey(address))
+		{
+			GfcFunctionItemData newData = new GfcFunctionItemData();
+			newData.function = caller;
+			newData.percentage = new Double(0);
+			newData.callTimes.add(callTime);
+
+			this.totalCallerAmount++;
+
+			// add a new caller
+			this.callerData.put(address,newData);
+		}
+		else
+		{
+			// just add the call count of an existing caller
+			GfcFunctionItemData oldData = (GfcFunctionItemData)this.callerData.get(address);
+			this.totalCallerAmount++;
+			oldData.callTimes.add(callTime);
+		}
+
+		this.percentageUpdated = false;
+	}
+
+	// this function has called another function
+	public void addCallee(GfcFunctionItem callee, Integer callTime)
+	{
+		Long address = new Long(callee.address);
+		if (!this.calleeData.containsKey(address))
+		{
+			GfcFunctionItemData newData = new GfcFunctionItemData();
+			newData.function = callee;
+			newData.percentage = new Double(0);
+			newData.callTimes.add(callTime);
+
+			this.totalCalleeAmount++;
+
+			// add the new callee
+			this.calleeData.put(address,newData);
+		}
+		else
+		{
+			// just add the call count of an existing callee
+			GfcFunctionItemData oldData = (GfcFunctionItemData)this.calleeData.get(address);
+			this.totalCalleeAmount++;
+			oldData.callTimes.add(callTime);
+		}
+
+		this.percentageUpdated = false;
+	}
+
+	public GfcFunctionItem[] getCallerList()
+	{
+		GfcFunctionItem[] functionList = new GfcFunctionItem[callerData.size()];
+		Enumeration callEnum = this.callerData.elements();
+		int i = 0;
+
+		while (callEnum.hasMoreElements())
+		{
+			GfcFunctionItemData di = (GfcFunctionItemData)callEnum.nextElement();
+			if (di.function != null)
+			{
+				functionList[i] = di.function;
+			}
+			i++;
+		}
+		return functionList;
+	}
+
+	public Double[] getCallerPercentages()
+	{
+		calculatePercentages();
+
+		Double[] pList = new Double[callerData.size()];
+		Enumeration callEnum = this.callerData.elements();
+		int i = 0;
+		
+		while (callEnum.hasMoreElements())
+		{
+			GfcFunctionItemData di = (GfcFunctionItemData)callEnum.nextElement();
+			if (di.function != null)
+			{
+				pList[i] = di.percentage;
+			}
+			i++;
+		}
+		return pList;
+	}
+
+	public GfcFunctionItem[] getCalleeList()
+	{
+		GfcFunctionItem[] functionList = new GfcFunctionItem[calleeData.size()];
+		Enumeration callEnum = this.calleeData.elements();
+		int i = 0;
+
+		while (callEnum.hasMoreElements())
+		{
+			GfcFunctionItemData di = (GfcFunctionItemData)callEnum.nextElement();
+			functionList[i] = di.function;
+			i++;
+		}
+		return functionList;
+	}
+
+	public Double[] getCalleePercentages()
+	{
+		calculatePercentages();
+
+		Double[] pList = new Double[calleeData.size()];
+		Enumeration callEnum = this.calleeData.elements();
+		int i = 0;
+
+		while (callEnum.hasMoreElements())
+		{
+			GfcFunctionItemData di = (GfcFunctionItemData)callEnum.nextElement();
+			pList[i] = di.percentage;
+			i++;
+		}
+		return pList;
+	}
+
+	public String toString()
+	{
+		this.calculatePercentages();
+
+		String result = Messages.getString("GfcFunctionItem.calledBy1") + this.name + Messages.getString("GfcFunctionItem.calledBy2"); //$NON-NLS-1$ //$NON-NLS-2$
+		Enumeration callers = this.callerData.elements();
+
+		while (callers.hasMoreElements())
+		{
+			GfcFunctionItemData item = (GfcFunctionItemData)callers.nextElement();
+			result += Messages.getString("GfcFunctionItem.calledBy3") + item.percentage + Messages.getString("GfcFunctionItem.calledBy4") + item.function.name + Messages.getString("GfcFunctionItem.calledBy5") + item.function.dllName + Messages.getString("GfcFunctionItem.calledBy6"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+		}
+
+		result += Messages.getString("GfcFunctionItem.calls1") + this.name + Messages.getString("GfcFunctionItem.calls2"); //$NON-NLS-1$ //$NON-NLS-2$
+
+		Enumeration callees = this.calleeData.elements();
+		while (callees.hasMoreElements())
+		{
+			GfcFunctionItemData item = (GfcFunctionItemData)callees.nextElement();
+			result += Messages.getString("GfcFunctionItem.calls3") + item.percentage + Messages.getString("GfcFunctionItem.calls4") + item.function.name + Messages.getString("GfcFunctionItem.calls5") + item.function.dllName + Messages.getString("GfcFunctionItem.calls6"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+		}
+
+		result += Messages.getString("GfcFunctionItem.calls7"); //$NON-NLS-1$
+
+		return result;
+	}
+
+	private void calculatePercentages()
+	{
+		if (this.percentageUpdated == false)
+		{
+			Enumeration callEnum = this.callerData.elements();
+			while (callEnum.hasMoreElements())
+			{
+				GfcFunctionItemData di = (GfcFunctionItemData)callEnum.nextElement();
+				if (di.function != null)
+				{
+					di.percentage = new Double((double)((double)di.callTimes.size()/(double)this.totalCallerAmount)*100);
+				}
+			}
+
+			callEnum = this.calleeData.elements();
+			while (callEnum.hasMoreElements())
+			{
+				GfcFunctionItemData di = (GfcFunctionItemData)callEnum.nextElement();
+				if (di.function != null)
+				{
+					di.percentage = new Double((double)((double)di.callTimes.size()/(double)this.totalCalleeAmount)*100);
+				}
+			}
+
+			this.percentageUpdated = true;
+		}
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/GfcSample.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.call;
+
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampleWithFunctions;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
+import com.nokia.carbide.cpp.pi.address.GppSample;
+import com.nokia.carbide.cpp.pi.address.GppTrace;
+
+
+public class GfcSample extends GenericSampleWithFunctions
+{
+  private static final long serialVersionUID =  4293607815033391377L;
+  
+  private static transient Vector gppSamples = null;
+ 
+  public long programCounter;
+  public long linkRegister;
+  public long sampleNumber;
+
+  public Function callerFunctionSym;
+  public Function currentFunctionSym;
+  
+  public Function callerFunctionItt;
+  public Function currentFunctionItt;
+  
+  public GfcSample(long programCounter, long linkRegister, long sampleNumber, long sampleSynchTime)
+  {
+    this.programCounter = programCounter;
+    this.linkRegister = linkRegister;
+    this.sampleNumber = sampleNumber;
+    this.sampleSynchTime = sampleSynchTime;
+  }
+
+  public void resolveFunction(FunctionResolver res)
+  {
+	  if (res.getResolverName().equals("Symbol")) //$NON-NLS-1$
+	  {
+		  this.callerFunctionSym  = res.findFunctionForAddress(linkRegister);
+		  int index = (int)this.sampleNumber;
+		  if (gppSamples != null && index < gppSamples.size()) {
+			  GppSample gppSample = (GppSample)gppSamples.get(index);
+			  if (gppSample.programCounter == programCounter)
+				  this.currentFunctionSym = gppSample.currentFunctionSym;
+			  else
+				  this.currentFunctionSym = res.findFunctionForAddress(programCounter);
+		  } else
+			  this.currentFunctionSym = res.findFunctionForAddress(programCounter);		  
+	  }
+	  else if (res.getResolverName().equals("ITT")) //$NON-NLS-1$
+	  {
+		  if (this.callerFunctionSym == null)
+			  this.callerFunctionItt  = res.findFunctionForAddress(linkRegister);
+		  if (this.currentFunctionSym == null) {
+			  GppSample gppSample = (GppSample)gppSamples.get((int)this.sampleNumber);
+			  if (gppSample.programCounter == programCounter)
+				  this.currentFunctionItt = gppSample.currentFunctionItt;
+			  else
+				  this.currentFunctionItt = res.findFunctionForAddress(programCounter);		  
+		  }
+	  }
+  }
+  
+  public String toString()
+  {
+  	return "Gfc:#" + this.sampleSynchTime //$NON-NLS-1$
+  			+ " @0x" + Long.toHexString(this.programCounter) //$NON-NLS-1$
+  			+ " fS:" //$NON-NLS-1$
+  			+ ((this.currentFunctionSym == null || (this.currentFunctionSym.functionName == null)) ? "" : this.currentFunctionSym.functionName) //$NON-NLS-1$
+  			+ " cS:" //$NON-NLS-1$
+  			+ ((this.callerFunctionSym  == null || (this.callerFunctionSym.functionName  == null)) ? "" : this.callerFunctionSym.functionName); //$NON-NLS-1$
+  }
+  
+  public static void setAddressTraceSamples() {
+	  ParsedTraceData traceData = TraceDataRepository.getInstance().getTrace(NpiInstanceRepository.getInstance().activeUid(), GppTrace.class);
+	  if (traceData != null && traceData.traceData != null && (traceData.traceData instanceof GppTrace))
+		  gppSamples = ((GppTrace)traceData.traceData).samples; //$NON-NLS-1$
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/GfcTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.call;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSample;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTraceWithFunctions;
+import com.nokia.carbide.cpp.internal.pi.utils.QuickSortImpl;
+import com.nokia.carbide.cpp.internal.pi.utils.Sortable;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+
+
+public class GfcTrace extends GenericSampledTraceWithFunctions
+{
+	private static final long serialVersionUID = -8144591614894549185L;
+
+	private long previousSample;
+	  
+	private Hashtable parsedGfcTrace;
+	private Vector    completeGfcTrace;
+	private int firstSample;
+	private int lastSample;
+	
+	private transient CallVisualiser callVisualiser;
+
+	private transient boolean completeTrace   = true;
+	private transient boolean completeSamples = true;
+	private transient int samplingInterval;
+	
+	public static final int SORT_BY_TOTAL_LOAD = 1;
+	public static final int SORT_BY_CALLED_LOAD = 2;
+	public static final int SORT_BY_RECURSIVE_LOAD = 3;
+
+	public GfcTrace(int size)
+	{	
+	    this.completeGfcTrace = new Vector(size);
+	    this.samples = new Vector(size);
+	    previousSample = 0;  	
+	}
+	
+	public void addSample(GfcSample sample, Long[] element)
+	{
+	    this.samples.add(sample);
+	  	  
+	    long sampleNumber   = sample.sampleSynchTime;
+	      
+	    if (previousSample != 0)
+	    {
+	    	if (sampleNumber != previousSample + samplingInterval)
+	    		System.out.println(Messages.getString("GfcTrace.missingSample1") + previousSample + Messages.getString("GfcTrace.missingSample2") + sample); //$NON-NLS-1$ //$NON-NLS-2$
+	    }
+	    previousSample = sampleNumber;
+	
+	    if (this.firstSample == -1)
+	    	this.firstSample = (int)sampleNumber;
+	    else
+	    	this.lastSample  = (int)sampleNumber;
+	    /*
+	    System.out.print("\n\nSample: "+sample+" pc: "+programCounter+" lr: "+linkRegister);
+	    System.out.print("\nSample: "+sample+
+	                       "\npc: "+symbolParser.getFunctionForAddress(programCounter).functionName+
+	                       "\nlr: "+symbolParser.getFunctionForAddress(linkRegister).functionName);
+	    */
+	    this.completeGfcTrace.add(element);
+	}
+  
+	public Hashtable parseEntries(int startSample, int endSample)
+	{
+	  	// code to avoid stack overflow in saving analysis,
+	  	// with parameters -20,-20 , the parsedGfcTrace field is cleared,
+	  	// and it is restored with values -10,-10
+	    if (startSample == -20 && endSample == -20)
+	    {
+	    	if (this.parsedGfcTrace == null)
+	    	{
+	    		return null;
+	    	}
+	    	else
+	    	{
+	    		this.parsedGfcTrace = null;
+	    		return new Hashtable();
+	    	}
+	    }
+	    else if (startSample == -10 && endSample == -10)
+	    {
+	    	this.parseEntries(this.firstSample, this.lastSample);
+	    	return null;
+	    }
+	
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+
+    	if (startSample < 1)
+    		startSample = 0;
+
+    	this.firstSample = startSample / samplingInterval;
+	    this.lastSample  = endSample / samplingInterval;
+	    
+	    this.parsedGfcTrace = new Hashtable();
+	    
+    	if (this.completeTrace) {
+	    	// adjust the sample search
+	    	if (startSample > this.completeGfcTrace.size())
+	    		startSample = this.completeGfcTrace.size();
+	    	if (endSample > this.completeGfcTrace.size())
+	    		endSample = this.completeGfcTrace.size();
+	    	
+	    	for (int i = startSample; i < endSample; i++) {
+	    		Long[] data = (Long[])this.completeGfcTrace.elementAt(i);
+	    		this.parseOneEntry(data[0], data[1], data[2]);
+	    	}
+	    } else if (endSample >= samplingInterval) {
+	    	// sample is incomplete, so find the sample nearest but after the start
+	    	int nearest = 0;
+	    	if (startSample >= samplingInterval) {
+	    		int last = 0;
+	    		int half = this.completeGfcTrace.size() / 2;
+	    		nearest = this.completeGfcTrace.size() - 1;
+	    		long time = ((Long[]) this.completeGfcTrace.get(nearest))[0];
+	    		
+	    		while (time != startSample && half > 0) {
+	    			if (time < startSample)
+	    				nearest = nearest + half;
+	    			else
+	    				nearest = nearest - half;
+	    			half /= 2;
+	    			time = ((Long[]) this.completeGfcTrace.get(nearest))[0];
+	    		}
+	    		
+	    		while (nearest > 0 && time > startSample) {
+	    			nearest--;
+	    			time = ((Long[]) this.completeGfcTrace.get(nearest))[0];
+	    		}
+	    		
+	    		while (nearest < this.completeGfcTrace.size() - 1 && time + samplingInterval < startSample) {
+	    			nearest++;
+	    			time = ((Long[]) this.completeGfcTrace.get(nearest))[0];
+	    		}
+	    	}
+	    	
+	    	// we're starting at the right spot, so collect data (don't worry that we get the first one twice - we only parse it once
+	    	Long[] data = (Long[])this.completeGfcTrace.get(nearest);
+		    for ( ; data[0].longValue() <= endSample && nearest < this.completeGfcTrace.size(); nearest++) {
+		        data = (Long[])this.completeGfcTrace.get(nearest);
+		        this.parseOneEntry(data[0], data[1], data[2]);
+		    }
+	    }
+
+	    countRecursiveLoad();
+    
+	    return this.parsedGfcTrace;
+	}
+	
+	private class CallerCallee {
+		String  functionName;
+		Long    startAdress;
+		String  binaryName;
+		boolean symbolParsed;
+	}
+  
+  	private void parseOneEntry(long sample, long programCounter, long linkRegister)
+  	{
+	  	GfcSample gSam = null;
+ 
+	  	if (this.completeSamples)
+  	    {
+	  		// find it directly
+	  		if (sample <= this.getLastSampleNumber())
+	  			gSam = (GfcSample)this.samples.elementAt((int) (sample - 1));
+  	    } else {
+  	    	// find it the slow way
+  		  	if (this.getLastSampleNumber() <= sample + 1 || this.getFirstSampleNumber() > sample)
+  		  		return;
+
+  		  	GenericSample[] samples = this.getSamplesForTime(sample);
+	  	    if ((samples != null) && (samples.length != 0))
+	  	    	gSam = (GfcSample)samples[0];
+  	    }
+  	    
+  	    if (gSam == null) {
+  	    	System.out.println(Messages.getString("GfcTrace.sampleNotFound") + sample);  	    	 //$NON-NLS-1$
+  	    	return;
+  	    }
+  	    
+  	    CallerCallee caller = new CallerCallee();
+  	    CallerCallee callee = new CallerCallee();
+
+		if (  (gSam.callerFunctionSym == null || gSam.callerFunctionSym.functionName.endsWith(Messages.getString("GfcTrace.functionNotFound"))) //$NON-NLS-1$
+			&& gSam.callerFunctionItt != null) //$NON-NLS-1$
+		{
+			caller.functionName = gSam.callerFunctionItt.functionName;
+    		caller.startAdress  = gSam.callerFunctionItt.startAddress;
+			caller.binaryName   = gSam.callerFunctionItt.functionBinary.binaryName;
+			caller.symbolParsed = false;
+		}
+		else
+		{
+			caller.functionName = gSam.callerFunctionSym.functionName;
+			caller.startAdress  = gSam.callerFunctionSym.startAddress;
+			caller.binaryName   = gSam.callerFunctionSym.functionBinary.binaryName;
+			caller.symbolParsed = Boolean.valueOf(true);
+		}
+		
+		if (   (gSam.currentFunctionSym == null || gSam.currentFunctionSym.functionName.endsWith(Messages.getString("GfcTrace.functionNotFound"))) //$NON-NLS-1$
+			&& gSam.currentFunctionItt != null) //$NON-NLS-1$
+		{
+			callee.functionName = gSam.currentFunctionItt.functionName;
+    		callee.startAdress  = gSam.currentFunctionItt.startAddress;
+			callee.binaryName   = gSam.currentFunctionItt.functionBinary.binaryName;
+			callee.symbolParsed = Boolean.valueOf(false);
+		}
+		else
+		{
+			callee.functionName = gSam.currentFunctionSym.functionName;
+    		callee.startAdress  = gSam.currentFunctionSym.startAddress;
+			callee.binaryName   = gSam.currentFunctionSym.functionBinary.binaryName;
+			callee.symbolParsed = Boolean.valueOf(true);
+		}
+
+		this.updateEntryLists(sample, programCounter, linkRegister, caller, callee);
+  	}
+
+  	private void updateEntryLists(long sample, long programCounter, long linkRegister, CallerCallee callerObj, CallerCallee calleeObj)
+	{
+	    String callerName          = callerObj.functionName;
+	    Long callerStart           = callerObj.startAdress;
+	    String callerDllName       = callerObj.binaryName;
+	    boolean callerSymbolParsed = callerObj.symbolParsed;
+	
+	    String calleeName           = calleeObj.functionName;
+	    Long calleeStart            = calleeObj.startAdress;
+	    String calleeDllName        = calleeObj.binaryName;
+	    boolean calleeSymbolParsed  = calleeObj.symbolParsed;
+	    
+	    GfcFunctionItem caller;
+	    GfcFunctionItem callee;
+	
+	    // is the callee in the list
+	    if (parsedGfcTrace.containsKey(calleeStart))
+	    {
+		    // the callee is in the list
+		    callee = (GfcFunctionItem)this.parsedGfcTrace.get(calleeStart);
+	    }
+	    else
+	    {
+		    // the callee is not in the list
+		    callee = new GfcFunctionItem(calleeName, calleeStart.longValue(), calleeDllName, calleeSymbolParsed);
+		    this.parsedGfcTrace.put(calleeStart, callee);
+	    }
+
+	    // is the caller in the list
+	    if (this.parsedGfcTrace.containsKey(callerStart))
+	    {
+	    	// the caller is in the list
+	    	caller = (GfcFunctionItem)this.parsedGfcTrace.get(callerStart);
+	    }
+	    else
+	    {
+	    	// no, we have to add the caller to the list as well
+	    	caller = new GfcFunctionItem(callerName, callerStart.longValue(), callerDllName, callerSymbolParsed);
+	    	this.parsedGfcTrace.put(callerStart, caller);
+	    }
+
+	    if (!caller.equals(callee))
+	    {
+	    	callee.addCaller(caller, new Integer((int)sample));
+	    	caller.addCallee(callee, new Integer((int)sample));
+	    }
+	}
+  
+	public void countRecursiveLoad()
+	{
+		//if (exclude == null)
+		ArrayList exclude = new ArrayList();
+
+		GfcFunctionItem[] sorted = this.getEntriesSorted(SORT_BY_CALLED_LOAD);
+		
+		if (sorted.length == 0)
+			return;
+		
+		int index = sorted.length - 1;
+		int lastExclude = 0;
+
+		// add the load of this function to the accumulated load
+		for (int i = 0; i < sorted.length; i++)
+		{
+			GfcFunctionItem gfi = sorted[i];
+			gfi.addRecursiveLoad(gfi.countSamplesThatCallThisFunction());
+			gfi.setRecursiveLoad(0);
+		}
+
+		while (true)
+		{
+		    GfcFunctionItem item = sorted[index];
+		    item.storePercents(-1, -1, -1, this.firstSample, this.lastSample);
+		
+		    index--;
+		    if (index == -1)
+		    {
+		        index = sorted.length - 1;
+		        if (lastExclude == exclude.size())
+		        {
+		        	break;
+		        }
+		        else
+		        {
+		        	lastExclude = exclude.size();
+		        }
+		    }
+		
+		    if (!exclude.contains(item))
+		    {
+		        double load = item.countSamplesThatCallThisFunction();
+		
+		        GfcFunctionItem[] callers = item.getCallerList();
+		        Double[] percentages = item.getCallerPercentages();
+		
+		        for (int i = 0; i < callers.length; i++)
+		        {
+			        //System.out.println(item.name+" load:"+load+" Adding "+load*(percentages[i].doubleValue()/100)+" to"+callers[i].name);
+			        callers[i].addRecursiveLoad(load*(percentages[i].doubleValue()/100));
+			
+			        // there is some accumulated recursive load to distribute
+			        // between the callers
+			        if (item.getRecursiveLoad() > 0)
+			        {
+			            double recursiveLoadToShare = item.getRecursiveLoad()*(percentages[i].doubleValue()/100);
+			
+			            // add recursive load only if the caller is not the function itself
+			            if (!callers[i].equals(item))
+			            {
+			            	callers[i].addRecursiveLoad(recursiveLoadToShare);
+			            }
+			        }
+		        }
+		        // clear the recursive load
+		        item.setRecursiveLoad(0);
+		    }
+	
+		    // this function does not call any other functions so it can be added
+		    // to the excluded functions list
+		    if (item.getCalleeList().length == 0)
+		    {
+		        if (!exclude.contains(item))
+		        	exclude.add(item);
+		        //sorted.remove(item);
+		    }
+		    else
+		    {
+		        GfcFunctionItem[] callees = item.getCalleeList();
+		        int i;
+		        for (i = 0; i < callees.length; i++)
+		        {
+			        // break if any item is found that is not excluded
+			        if (!exclude.contains(callees[i]))
+			        	break;
+		        }
+		
+		        // there are only excluded items in this function's call list,
+		        // thus it can also be excluded
+		        if (i == callees.length)
+		        {
+			        if (!exclude.contains(item))
+			        	exclude.add(item);
+			        //sorted.remove(item);
+		        }
+		    }
+		}
+	}
+  
+	public GfcFunctionItem[] getEntriesSorted(final int sortMethod)
+	{
+	  	class ItemSorter implements Sortable
+	  	{
+	  		GfcFunctionItem item;
+	  		
+	  		double itemTotal;
+	  		double itemCaller;
+	  		double itemRecursive;
+	        
+	        public ItemSorter(GfcFunctionItem item)
+	        {
+	        	this.item = item;
+	            // calculate and store the percentages for the items for the selected period
+	            itemTotal     = item.getAbsoluteTotalPercentage(firstSample, lastSample);
+	            itemCaller    = item.getAbsoluteCallerPercentage(firstSample, lastSample);
+	            itemRecursive = item.getRecursiveCallerPercentage(firstSample, lastSample);
+	            
+	            if (itemTotal == -1 || itemCaller == -1 || itemRecursive == -1)
+	            {
+	            	itemTotal     = getAbsoluteTraditionalPercentageFor(item);
+	            	itemCaller    = getAbsoluteCallerPercentageFor(item);
+	            	itemRecursive = getRecursiveCallerPrecentageFor(item);
+	            
+	            	item.storePercents(itemTotal, itemCaller, itemRecursive,
+	                               		firstSample, lastSample);
+	            }
+	        }
+        
+	  		public long valueOf()
+	  		{
+	  	        if (sortMethod == GfcTrace.SORT_BY_TOTAL_LOAD)
+	  	        {
+	  	        	return (long)(1000 * itemTotal);
+	  	        }
+	  	        else if (sortMethod == GfcTrace.SORT_BY_CALLED_LOAD)
+	  	        {
+	  	        	return (long)(1000 * itemCaller);
+	  	        }
+	  	        else if (sortMethod == GfcTrace.SORT_BY_RECURSIVE_LOAD)
+	  	        {
+	  	        	return (long)(1000 * itemRecursive);
+	  	        }
+	  	        else
+	  	        {
+	  	        	return 0;
+	  	        }
+	  		}
+	  	}
+  	
+		Enumeration elements = this.parsedGfcTrace.elements();
+	  	
+		Vector s = new Vector();
+		while (elements.hasMoreElements())
+		{
+	  		ItemSorter is = new ItemSorter((GfcFunctionItem)elements.nextElement());
+	  		s.add(is);
+	  	}
+	  	
+	  	QuickSortImpl.sortReversed(s);
+  	
+	  	elements = s.elements();
+	  	this.parsedGfcTrace.clear();
+	  	
+	  	GfcFunctionItem[] f = new GfcFunctionItem[s.size()];
+	  	int i = 0;
+	  	while (elements.hasMoreElements())
+	  	{
+	  		ItemSorter is = (ItemSorter)elements.nextElement();
+	  		f[i++] = is.item;
+	  		this.parsedGfcTrace.put(new Long(is.item.address), is.item);
+	  	}
+  	
+	  	return f;
+	}
+  
+  	public double getAbsoluteTraditionalPercentageFor(GfcFunctionItem gfi)
+	{
+	    double samples = gfi.countSamplesThatCallThisFunction();
+	    double total = this.lastSample - this.firstSample;
+	    return 100 * (samples / total);
+	}
+
+  	public double getAbsoluteCallerPercentageFor(GfcFunctionItem gfi)
+  	{
+  		double samples = gfi.countSamplesWhereThisFunctionIsTheCaller();
+  		double total = this.lastSample - this.firstSample;
+  		return 100 * (samples / total);
+  	}
+
+  	public double getRecursiveCallerPrecentageFor(GfcFunctionItem gfi)
+  	{
+  		double samples = gfi.getAccumulatedLoad();
+  		double total = this.lastSample - this.firstSample;
+  		return 100 * (samples / total);
+  	}
+
+  	/*
+  	 * Check if the function call sample set and trace are complete
+  	 * (first sample is at time 1, sample N is at time N)
+  	 */
+  	public void setComplete()
+  	{
+  		Object intervalObject = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+		int samplingInterval = intervalObject != null ? (Integer) intervalObject : -1; 
+  		int size;
+  		
+  		this.completeTrace = true;
+  		
+  		size = this.completeGfcTrace.size();
+  		for (int i = 0; i < size; i++) {
+  			Long[] element = (Long[])this.completeGfcTrace.elementAt(i);
+  			if (element[0].longValue() != (i + 1)*samplingInterval) {
+  				this.completeTrace = false;
+  				break;
+  			}
+  		}
+
+  		this.completeSamples = true;
+  		
+  		size = this.samples.size();
+  		for (int i = 0; i < size; i++) {
+  			GfcSample element = (GfcSample)this.samples.elementAt(i);
+  			if (element.sampleSynchTime != (i + 1)*samplingInterval) {
+  				this.completeSamples = false;
+  				break;
+  			}
+  		}
+  	}
+  	
+  	// this method is not used
+  	public GenericTraceGraph getTraceGraph()
+  	{
+  		return null;
+  	}
+
+  	// this method is not used
+  	public GenericTraceGraph getTraceGraph(int graphNumber)
+  	{
+		return null;
+	}
+	
+	public CallVisualiser getCallVisualiser()
+	{
+		return this.callVisualiser;
+	}
+	
+	public void setCallVisualiser(CallVisualiser callVisualiser)
+	{
+		this.callVisualiser = callVisualiser;
+	}
+	
+	public void setSamplingInterval(int samplingInterval) {
+		this.samplingInterval = samplingInterval;
+	}
+	
+	public void refineTrace(FunctionResolver resolver)
+	{
+		GfcSample.setAddressTraceSamples();
+		super.refineTrace(resolver);
+	}
+	
+	public Vector getCompleteGfcTrace()
+	{
+		return this.completeGfcTrace;
+	}
+
+	@Override
+	public void finalizeTrace()
+	{
+		for (int i = 0; i < samples.size(); i++) {
+			GfcSample sample = (GfcSample) samples.get(i);
+			
+			if (sample.currentFunctionItt == null && sample.currentFunctionSym == null) {
+				sample.currentFunctionItt = new Function(Messages.getString("GfcTrace.functionNotFound1") + Long.toHexString(sample.programCounter) + Messages.getString("GfcTrace.functionNotFound2"), //$NON-NLS-1$ //$NON-NLS-2$
+						new Long(sample.programCounter),
+						Messages.getString("GfcTrace.binaryNotFound1") +  Long.toHexString(sample.programCounter) + Messages.getString("GfcTrace.binaryNotFound2")); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			
+			if (sample.callerFunctionItt == null && sample.callerFunctionSym == null) {
+				sample.callerFunctionItt = new Function(Messages.getString("GfcTrace.functionNotFound1") + Long.toHexString(sample.linkRegister) + Messages.getString("GfcTrace.functionNotFound2"), //$NON-NLS-1$ //$NON-NLS-2$
+						new Long(sample.linkRegister),
+						Messages.getString("GfcTrace.binaryNotFound1") +  Long.toHexString(sample.linkRegister) + Messages.getString("GfcTrace.binaryNotFound2")); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/GfcTraceParser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.call;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.Parser;
+import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
+import com.nokia.carbide.cpp.pi.address.GppSample;
+import com.nokia.carbide.cpp.pi.address.GppTrace;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+public class GfcTraceParser extends Parser
+{
+//  private String profilerVersion;
+	private ArrayList<Long[]> completeGfcTrace;
+//  private int firstSample,lastSample;
+  
+	public GfcTraceParser() throws Exception
+	{
+		this.completeGfcTrace = new ArrayList<Long[]>();
+	}
+  
+	public ParsedTraceData parse(File f) throws Exception 
+	{
+		if (!f.exists()) //throw new IOException("GFC file does not exist");
+		{
+			setStateOk(false);
+		}
+		else
+		{
+			FileInputStream fis = new FileInputStream(f);
+			byte[] data = new byte[(int)f.length()];
+			fis.read(data);
+			String version = getVersion(data);
+			System.out.println(Messages.getString("GfcTraceParser.traceVersion")+version); //$NON-NLS-1$
+			//profilerVersion = version;
+//			traceVersion = "GFC_V" + version;
+			traceVersion = "V" + version; //$NON-NLS-1$
+			ByteArrayInputStream bais = new ByteArrayInputStream(data);
+			DataInputStream dis = new DataInputStream(bais);
+			
+			if (version.equals("0.91")||version.equals("1.00")||version.equals("1.10")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			{
+				// skip the intro
+				int intro = dis.readUnsignedByte();
+				for (int i=0;i<intro;i++) dis.readUnsignedByte();
+				
+				// start parsing
+				try
+				{
+					readEntriesV091(dis);
+				}
+				catch (Exception e)
+				{
+					GeneralMessages.showErrorMessage(Messages.getString("GfcTraceParser.invalidTraceFile")); //$NON-NLS-1$
+					throw e;				
+				}
+			}
+			else if (version.equals("0.40-0.85")) //$NON-NLS-1$
+			{
+				try
+				{
+					readEntries(dis);
+				}
+				catch (Exception e)
+				{
+					GeneralMessages.showErrorMessage(Messages.getString("GfcTraceParser.invalidtraceFile")); //$NON-NLS-1$
+					throw e;
+				}
+			}
+			else
+			{
+				GeneralMessages.showErrorMessage(Messages.getString("GfcTraceParser.traceVersionNotSupported1")+version+Messages.getString("GfcTraceParser.traceVersionNotSupported2")); //$NON-NLS-1$ //$NON-NLS-2$
+				throw new Exception(Messages.getString("GfcTraceParser.traceVersionNotSupportedException")); //$NON-NLS-1$
+			}
+	    }
+	  	ParsedTraceData ptd = new ParsedTraceData();
+	  	ptd.traceData = this.getTrace();
+	  	return ptd;
+	}
+  
+	//this returns profiler version for pre 1.0 traces
+	public String getProfilerVersion()
+	{
+    	return traceVersion;
+	}
+  
+	private String getVersion(byte[] data)
+	{
+	  	int length = data[0];
+	  	if (length > 8)
+	  	{
+	  		String verString = new String(data,1,length);
+	  		if (verString.indexOf("Bappea_V") != -1) //$NON-NLS-1$
+	  			if (verString.indexOf("GFC") != -1) //$NON-NLS-1$
+	  			{
+	  				int index = verString.indexOf("Bappea_V")+8; //$NON-NLS-1$
+	  				String ver = verString.substring(index,index+4);
+	  				return ver;
+	  			}
+	  	}
+	  	return "0.40-0.85"; //$NON-NLS-1$
+	}
+  
+	private void readEntriesV091(DataInputStream dis) throws Exception
+	{
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+
+		// if address/thread trace's 1st sample was sent before its thread name,
+		// then the first GPP sample was thrown out. In that case, the 1st GfcTrace sample needs to be thrown out also
+		ParsedTraceData traceData = TraceDataRepository.getInstance().getTrace(NpiInstanceRepository.getInstance().activeUid(), GppTrace.class);
+		
+		GppSample gppSample = null;
+		if (traceData != null && traceData.traceData != null && (traceData.traceData instanceof GppTrace)) {
+			Vector gppSamples = ((GppTrace)traceData.traceData).samples; 
+			gppSample = ((GppSample)gppSamples.get(0)); //$NON-NLS-1$
+		}
+
+		try
+		{
+			long[] data = new long[3];
+			long pc = 0;
+			long lr = 0;
+			long sampleTime = 0;
+	
+			for (int i=0;i<3;i++) data[i] = 0;
+			
+	  		while (true)
+	  		{
+	  			boolean pcNeg = true;
+	  			boolean lrNeg = true;
+	  		  	int[] entry = readEntry(dis);
+	  		  	
+	  		  	// information on whether this increment is positive
+	  		  	// or negative, has been encoded to the first bit
+	  		  	// of entry indices 0 and 1
+	  		  	
+	  		  	// they should not be considered in case entry 0
+	  		  	// is 0xff, because in that case the repeat length 
+	  		  	// is encoded to those values
+	  		  	if (entry[0] != 0xff)
+	  		  	{
+	  		  		if (entry[0] > 4)
+	  		  		{
+	  		  			pcNeg = false;
+	  		  			entry[0] = entry[0] & 0x0f;
+	  		  		}
+	  		  		if (entry[1] > 4)
+	  		  		{
+	  		  			lrNeg = false;
+	  		  			entry[1] = entry[1] & 0x0f;  		  		
+	  		  		}
+	  		  	}
+	  		  	//System.out.println("Entry "+entry[0]+" "+entry[1]+" "+entry[2]);
+	  		  	
+	  			long[] newData = getNewData(data,entry,dis);
+	  			{
+	  				if (newData[0] == 0 && newData[1] == 0)
+	  				{
+	  					// repeat
+	  					for (int i=0;i<newData[2];i++)
+	  					{
+	  						data[2]+=samplingInterval;
+	  						
+	  	  					pc = (data[0] << 32) >>> 32;
+	  	  					lr = (data[1] << 32) >>> 32;
+	  	  					sampleTime = (data[2] << 32) >>> 32;
+	  						
+	  	  					//System.out.println("REP: pc:"+Long.toHexString(pc)+" lr:"+Long.toHexString(lr)+" sa:"+sa);
+	  	  					// sometimes the first address/thread sample had to be discarded,
+	  	  					// so 2nd call sample matches first address/thread sample
+	  	  					if (   sampleTime == gppSample.sampleSynchTime && gppSample.sampleSynchTime == samplingInterval * 2
+	  	  						&& this.completeGfcTrace.size() == 1) {
+	  	  						// replace the first sample with this one
+	  	  						this.completeGfcTrace.remove(0);
+	  	  					}
+	  	  					this.completeGfcTrace.add(new Long[]{new Long(sampleTime),new Long(pc), new Long(lr)});
+	  					}
+	  				}
+	  				else
+	  				{
+	  					if (pcNeg) 
+	  					{
+	  						//System.out.println("Subtracting PC "+Long.toHexString(newData[0])+" from "+Long.toHexString(data[0]));
+	  						data[0]-=newData[0];
+	  					}
+	  					else 
+	  					{
+	  						//System.out.println("Adding PC "+Long.toHexString(newData[0])+" to "+Long.toHexString(data[0]));
+	  						data[0] += newData[0];
+	  					}
+	
+	  					if (lrNeg) 
+	  					{
+	  						//System.out.println("Subtracting LR "+Long.toHexString(newData[1])+" from "+Long.toHexString(data[1]));
+	  						data[1] -= newData[1];
+	  					}
+	  					else 
+	  					{
+	  						//System.out.println("Adding LR "+Long.toHexString(newData[1])+" to "+Long.toHexString(data[1]));
+	  						data[1] += newData[1];
+	  					}
+	  					
+	  					data[2] += newData[2];
+	  					
+	  					pc = (data[0] << 32) >>> 32;
+	  					lr = (data[1] << 32) >>> 32;
+	  					sampleTime = (data[2] << 32) >>> 32;
+	  					//System.out.println("pc:"+Long.toHexString(pc)+" lr:"+Long.toHexString(lr)+" sa:"+sa);
+  	  					// sometimes the first address/thread sample had to be discarded,
+  	  					// so 2nd call sample matches first address/thread sample
+  	  					if (   sampleTime == gppSample.sampleSynchTime && gppSample.sampleSynchTime == samplingInterval * 2
+  	  						&& this.completeGfcTrace.size() == 1) {
+  	  						// replace the first sample with this one
+  	  						this.completeGfcTrace.remove(0);
+  	  					}
+	  					this.completeGfcTrace.add(new Long[]{new Long(sampleTime),new Long(pc), new Long(lr)});
+	  					
+	  					data[0] = pc;
+	  					data[1] = lr;
+	  					data[2] = sampleTime;
+	  				}
+	  			}
+	  		}
+		}
+	  	catch (EOFException e)
+		{
+	  		return;
+		}
+	  	catch (Exception e)
+		{
+	  		throw e;
+		}
+	}
+	
+	private long[] getNewData(long[] prevData,int[] entry,DataInputStream dis) throws Exception
+	{
+		long[] data = new long[3];
+	
+	  	if (entry[0] == 0xff)
+	  	{
+	  		// repeat
+	  		long repeat = entry[1]<<8;
+	  		repeat += entry[2];
+	  		//System.out.println("Repeat "+repeat);
+	  		data[0] = 0;
+	  		data[1] = 0;
+	  		data[2] = repeat;
+	  		return data;
+	  	}
+	  	else
+	  	{
+	  		// read pc and lr values
+	  		for (int k=0;k<2;k++)
+	  		{
+	  			for (int i=0;i<entry[k];i++)
+	  			{
+	  				long value = (((long)dis.readUnsignedByte()) << (8*i));
+	  				data[k] |= value;
+	  			}
+	  			//System.out.println("Data ["+k+"] = "+Long.toHexString(data[k]));
+	  		}
+	  		
+	  		// read sample number, if present
+	  		if (entry[2] == 0xff)
+	  		{
+	  			for (int i=0;i<4;i++)
+	  			{
+	  				long value = (((long)dis.readUnsignedByte()) << (8*i));
+	  				data[2] |= value;
+	  			}
+	  			//System.out.println("SampleNr "+data[2]);
+	  		}
+	  		else
+	  		{
+	  			data[2] = entry[2];
+	  		}
+	  		return data;
+	  	}
+	}
+  
+	private int[] readEntry(DataInputStream dis) throws Exception
+	{
+	  	int[] e = new int[3];
+	  	e[0] = dis.readUnsignedByte();
+	  	e[1] = dis.readUnsignedByte();
+	  	e[2] = dis.readUnsignedByte();
+	 	return e;
+	}
+
+	private void readEntries(DataInputStream dis) throws Exception
+	{
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+	    int byteCount = 0;
+	    long previousSample = 0;
+	    
+	    while (dis.available() >= 4)
+	    {
+		    long programCounter = readUnsignedIntFromStream(dis);
+		    programCounter = ((programCounter << 32) >>> 32);
+		   	long linkRegister = readUnsignedIntFromStream(dis);
+		   	linkRegister = ((linkRegister << 32) >>> 32);
+		    long sample = readUnsignedIntFromStream(dis);
+		      
+		    if (previousSample != 0)
+		    {
+		      	if (sample != previousSample+samplingInterval)
+		      		System.out.println(Messages.getString("GfcTraceParser.missingSample1")+previousSample+Messages.getString("GfcTraceParser.missingSample2")+sample); //$NON-NLS-1$ //$NON-NLS-2$
+		    }
+		    previousSample = sample;
+	
+		    this.completeGfcTrace.add(new Long[]{new Long(sample),new Long(programCounter), new Long(linkRegister)});
+		    byteCount += 12;
+	    }
+//		setProgressBarString("Done");
+	    System.out.println(Messages.getString("GfcTraceParser.bytesRead1")+byteCount+Messages.getString("GfcTraceParser.bytesRead2")); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	private long readUnsignedIntFromStream(DataInputStream dis) throws IOException
+	{
+	    int b1 = dis.readUnsignedByte();
+	    int b2 = dis.readUnsignedByte();
+	    int b3 = dis.readUnsignedByte();
+	    int b4 = dis.readUnsignedByte();
+	
+	    return (b4 * 16777216 + b3 * 65536 + b2 * 256 + b1);
+	}
+  
+	private GenericTrace getTrace()
+	{
+	  	GfcTrace trace = new GfcTrace(this.completeGfcTrace.size());
+	  	
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+		trace.setSamplingInterval(samplingInterval);
+
+		int i = 0;
+	  	for (Long[] element : this.completeGfcTrace)
+	  	{
+	  		GfcSample sample = new GfcSample(	element[1].longValue(), // program counter
+	  											element[2].longValue(), // link register
+	  											i++,
+												element[0].longValue());// sample time  		
+	  		trace.addSample(sample, element);
+	  	}
+	  	return trace;
+	}
+
+  /*
+	public static void main(String a[]) throws Exception
+	{
+		new GfcTraceParser(new File("C:\\Bappea_1_GFC_Trace.dat"),null,null);
+	}
+   */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.call;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.call.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.call/src/com/nokia/carbide/cpp/pi/call/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,62 @@
+GfcFunctionItem.calledBy1=\nFunction:
+GfcFunctionItem.calledBy2=\nThis function is CALLED by:\n
+GfcFunctionItem.calledBy3=\ \ \ \ - 
+GfcFunctionItem.calledBy4=% 
+GfcFunctionItem.calledBy5=\ IN: 
+GfcFunctionItem.calledBy6=\ \n
+GfcTraceParser.bytesRead1=Read 
+GfcTraceParser.bytesRead2=\ bytes
+GfcTrace.binaryNotFound1=Binary at 0x
+GfcTrace.binaryNotFound2=\ not found
+GfcTrace.missingSample1=Missing GFC Sample(s): prev:
+GfcTrace.missingSample2=\ next:
+GfcTrace.sampleNotFound=Sample not found for time 
+GfcTrace.functionNotFound=not found
+GfcTrace.functionNotFound1=Function at 0x
+GfcTrace.functionNotFound2=\ not found
+GfcFunctionItem.calls1=\nFunction:
+GfcFunctionItem.calls2=\nThis function CALLS:\n
+GfcFunctionItem.calls3=\ \ \ \ - 
+GfcFunctionItem.calls4=% 
+GfcFunctionItem.calls5=\ IN: 
+GfcFunctionItem.calls6=\ \n
+GfcFunctionItem.calls7=\n---------------------------\n
+GfcTraceParser.traceVersion=GFC trace version 
+GfcTraceParser.invalidTraceFile=Not a valid GFC trace file, possible buffer overflow in profiler?
+GfcTraceParser.invalidtraceFile=Not a valid GFC trace file, possible buffer overflow in profiler?
+GfcTraceParser.traceVersionNotSupported1=GFC trace version 
+GfcTraceParser.traceVersionNotSupported2=\ not supported\!
+GfcTraceParser.traceVersionNotSupportedException=GFC trace version not supported
+GfcTraceParser.missingSample1=Missing GFC Sample(s): prev:
+GfcTraceParser.missingSample2=\ next:
+CallVisualiser.0=Copy
+CallVisualiser.1=CopyTable
+CallVisualiser.2=SaveTable
+CallVisualiser.3=CopyFunction
+CallVisualiser.4=SaveFunction
+CallVisualiser.isCalled=Is Called %
+CallVisualiser.isCaller=Is Caller %
+CallVisualiser.CopyTable=Copy Table
+CallVisualiser.SaveTable=Save Table...
+CallPlugin.functionCalls=Function Calls
+CallVisualiser.recursiveCaller=Recursive Caller %
+CallPlugin.functionCallAnalysis=Function Call Analysis
+CallVisualiser.percentOfCalls=% of Calls
+CallVisualiser.calledSamples=Called Samples
+CallVisualiser.callerSamples=Caller Samples
+CallVisualiser.callHeading=Time (ms),Caller Address,Caller Function,Caller Binary,Callee Address,Callee Function,Callee Binary\n
+CallVisualiser.callerFunctions=Calls Selected Function
+CallVisualiser.calleeFunctions=Called by Selected Function
+CallVisualiser.calls=Calls
+CallPlugin.0=Call trace failed to create UI
+CallVisualiser.selectFunction=Select One Function
+CallVisualiser.selectedFunction=Select One Function
+CallVisualiser.callingSelectedFunction=Functions calling the selected function
+CallVisualiser.calledBySelectedFunction=Functions called by the selected function
+CallVisualiser.saveAllSamplesForInterval=Save All Call Samples for Interval...
+CallVisualiser.showCallInfo=Show highlighted function's call info
+CallVisualiser.shortDecimalFormat=\#\#0.0
+CallVisualiser.CopyDataForFunction=Copy Data for Selected Function
+CallVisualiser.SaveDataForFunction=Save Data for Selected Function...
+CallVisualiser.decimalFormat=\#\#0.00
+CallVisualiser.sourcelookup=Open source for function
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/.settings/org.eclipse.core.resources.prefs	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding//src/com/nokia/carbide/pi/core/messages.properties=8859_1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Core
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.core;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.core.PICorePlugin
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ com.nokia.carbide.cpp.pi.util
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.pi.core
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,6 @@
+bin.includes = META-INF/,\
+               plugin.xml,\
+               .
+jars.compile.order = .
+source.. = src/
+output.. = bin/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+   <extension
+         id="pinature"
+         name="Carbide.c++ Performance Investigator Nature"
+         point="org.eclipse.core.resources.natures">
+      <runtime>
+         <run class="com.nokia.carbide.cpp.pi.core.PIProjectNature"/>
+      </runtime>
+      <builder id="com.nokia.carbide.cpp.pi.core.PIProjectNature"/>
+   </extension>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/src/com/nokia/carbide/cpp/pi/core/PICorePlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.core;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class PICorePlugin extends AbstractUIPlugin {
+
+	public static final String PLUGIN_ID = "com.nokia.carbide.cpp.pi.core"; //$NON-NLS-1$
+
+	//The shared instance.
+	private static PICorePlugin plugin;
+	
+	/**
+	 * The constructor.
+	 */
+	public PICorePlugin() {
+		plugin = this;
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		plugin = null;
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static PICorePlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractUIPlugin.imageDescriptorFromPlugin("test", path); //$NON-NLS-1$
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/src/com/nokia/carbide/cpp/pi/core/PIProjectNature.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.core;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IProjectNature;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+public class PIProjectNature implements IProjectNature {
+
+	public static final String PI_NATURE_ID = PICorePlugin.PLUGIN_ID + ".pinature";  //$NON-NLS-1$
+	
+	private IProject fProject;
+	
+	public void configure() throws CoreException {
+	}
+
+	public void deconfigure() throws CoreException {
+	}
+
+	public PIProjectNature() {
+	}
+	
+	public PIProjectNature(IProject project) {
+		setProject(project);
+	}
+
+	public IProject getProject() {
+		return fProject;
+	}
+
+	public void setProject(IProject project) {
+		fProject = project;
+	}
+
+	public static void addPINature(IProject project, IProgressMonitor mon) throws CoreException {
+		addNature(project, PI_NATURE_ID, mon);
+	}
+
+	public static void removePINature(IProject project, IProgressMonitor mon) throws CoreException {
+		removeNature(project, PI_NATURE_ID, mon);
+	}
+
+	private static void addNature(IProject project, String natureId, IProgressMonitor monitor) throws CoreException {
+		IProjectDescription description = project.getDescription();
+		String[] prevNatures = description.getNatureIds();
+		for (String prevNature : prevNatures) {
+			if (natureId.equals(prevNature)) {
+				return;
+			}
+		}
+		String[] newNatures = new String[prevNatures.length + 1];
+		System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
+		newNatures[prevNatures.length] = natureId;
+		description.setNatureIds(newNatures);
+		project.setDescription(description, monitor);
+	}
+
+	private static void removeNature(IProject project, String natureId, IProgressMonitor monitor) throws CoreException {
+		IProjectDescription description = project.getDescription();
+		String[] prevNatures = description.getNatureIds();
+		List<String> newNatures = new ArrayList<String>(Arrays.asList(prevNatures));
+		newNatures.remove(natureId);
+		description.setNatureIds((String[]) newNatures.toArray(new String[newNatures.size()]));
+		project.setDescription(description, monitor);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.core/src/com/nokia/carbide/cpp/pi/core/SessionPreferences.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.core;
+
+public class SessionPreferences {
+	private static SessionPreferences instance;
+
+	private static final int WINDOW_DEFAULT_HEIGHT = 778;
+	private static final int WINDOW_DEFAULT_WIDTH = 1024;
+
+	private boolean barMode;
+	private boolean toolTipsEnabled;
+	private boolean fillAllEnabled;
+	private int windowWidth;
+	private int windowHeight;
+
+	private SessionPreferences() {
+//		 singleton
+//		setup defaults here
+		setWindowWidth(WINDOW_DEFAULT_WIDTH);
+		setWindowHeight(WINDOW_DEFAULT_HEIGHT);
+		setBarMode(false);
+		setToolTipsEnabled(true);
+		setFillAllEnabled(true);
+	}
+	
+	static public SessionPreferences getInstance() {
+		if (instance == null) {
+			instance = new SessionPreferences();
+		}
+		
+		return instance;
+	}
+	
+	public Object clone() throws CloneNotSupportedException {
+		throw new CloneNotSupportedException();
+	}
+
+	public int getWindowWidth() {
+		return windowWidth;
+	}
+	
+	public void setWindowWidth(int width) {
+		windowWidth = width;
+	}
+
+	public int getWindowHeight() {
+		return windowHeight;
+	}
+
+	public void setWindowHeight(int height) {
+		windowHeight = height;
+	}
+	
+	public boolean getBarMode() {
+		return barMode;
+	}
+	
+	public void setBarMode(boolean enabled) {
+		barMode = enabled;
+	}
+
+	public boolean getToolTipsEnabled() {
+		return toolTipsEnabled;
+	}
+
+	public void setToolTipsEnabled(boolean enabled) {
+		toolTipsEnabled = enabled;
+	}
+
+	public boolean getFillAllEnabled() {
+		return fillAllEnabled;
+	}
+
+	public void setFillAllEnabled(boolean enabled) {
+		fillAllEnabled = enabled;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,9 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Help
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.doc.user;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.help,
+ org.eclipse.ui.cheatsheets
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/book.css	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,184 @@
+/*	
+	Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+	All rights reserved. 
+	License: http://www.eclipse.org/legal/epl-v10.html
+*/
+
+/*	Add whitespace around entire display to avoid crowding edges of view 	*/
+/* 	20070523-Removed top margin size to close gap between location breadcrumbs and page title	*/
+html {
+	margin: 2px 10px 10px 10px;
+	}
+
+/* 	Set default font to serif style, 12-pt and plain	*/
+body, p, table {
+	font-family: Verdana, Helvetica, Arial, sans-serif;
+	font-size: 13px;
+	font-weight: normal;
+}
+
+/*	Use sans-serif fonts for all title styles	*/
+h1, h2, h3, h4, h5, h6, strong, em {
+	font-family: Verdana, Helvetica, Arial, sans-serif;
+	color: #000000;	
+	}
+
+h1	{ font-size:20px }
+h2	{ font-size:18px }
+h3	{ font-size:16px }
+h4	{ font-size:14px }
+h5	{ font-size:13px }
+h6	{ font-size:12px }
+
+/*	For headlines at the top of a view, add space	*/
+/*	20090224-changed green fade to gold header image	*/
+h1, h2, h3 {
+	background-image: url(html/images/gold_header.png);
+	background-repeat: no-repeat;
+	padding:10px 0px 10px 12px;	
+	}
+
+li	{
+	margin-bottom:8px;	
+	margin-top:8px;
+	}
+
+/*	Footer includes space and a gray line above the company logo	*/
+#footer {
+	padding-top:10px;
+	margin-top:20px;
+	border-top:1px solid #999;
+	font-family: Helvetica, sans-serif;
+	font-size: 11px;
+	color:#333;
+	}
+
+.listing	{
+	font-family: "Courier New", Courier, mono;
+	color: #000000;
+	background-color: #FFFFCC;
+	margin: 5px 0px;
+	}
+		
+.code, pre	{
+	font-family: "Courier New", Courier, mono;
+	font-size: 13px;
+	color: #000000;
+	}
+
+.step	{
+	/* background-color: #EEE; */
+	/* margin: 10px 0px; */
+	/* color: #111; */
+	/* border-bottom:2px solid #EEE; */
+	}
+	
+.substep	{
+	background-color: #EEE;
+	}
+	
+	
+/*	Figure/Listing/Table titles are centered and gray	*/
+p.table {
+	color: #999;
+	font-weight: bold;
+	padding-top: 5px;
+	}
+
+table	{
+	border: solid #999 1px;
+	table-layout: auto;
+	font-size: 13px;
+	}
+
+td, th	{
+	border: solid #999 1px;
+	padding: 5px;
+	vertical-align:top;
+	}
+	
+/*	20070522-replaced gray with green background to match gradiant color for title	*/
+th	{
+	background-color:#FFC550;	/* background-color:#acd79b;
+	background-color:#999;
+	color:#FFF; */
+	}
+
+div.ol.p	{
+	margin-left: 3em;
+	}
+
+/* Make all ordered/unordered list items appear in bold gray */
+div ol > li, div ul > li {
+	font-weight:bold;
+	color: #333;
+	}
+
+div ol > p, div ul > p, div li > p {
+	font-weight:normal;
+	}
+	
+/* Make all H4 and H5 items appear in bold gray against a light green background */
+div h5, div h4	{
+	padding:5px 0px 5px 12px;
+	background-color:#FDCB2F;
+	/* background-color: #EEE; */
+	font-weight:bold;
+	color: #000000;
+	}
+	
+	
+/*	Notes stand out using a light top & bottom borders with dark gray text	*/
+p.note {
+	/* color: #03C; */
+	/* background-color: #FFFF99; */
+	color: #333;
+	padding: 5px;
+	margin-left: 1em;
+	margin-right: 1em;
+	border-top: solid #BBB thin;
+	border-bottom: solid #BBB thin;
+	}
+
+	
+/*	Figure/Listing/Table titles are centered and gray	*/
+p.figure {
+	color: #333;
+	text-align: center;
+	font-weight: bold;
+	}
+
+/*	highly visible red background and white text for things that need fixing before release	*/
+/*  SHOULD NOT BE PRESENT IN RELEASED PRODUCTS */
+.fix	{
+	background-color: red;
+	font-weight: bold;
+	color: white;
+	}
+
+.question	{
+	font-style:italic;
+	font-weight:bold;
+	color: #555;
+	}
+	
+.titleSmall {
+	font-family: Helvetica, sans-serif;
+	font-size: 11px;
+	}
+
+	
+.plain {
+	font-family: Helvetica, sans-serif;
+	font-size: 12px;
+	font-style: normal;
+	line-height: normal;
+	font-weight: normal;
+	font-variant: normal;
+	color: #000000;
+	text-decoration: none;
+	}
+
+a:link 		{ color: #0033CC }
+a:visited	{ color: #555555 }
+a:hover 	{ color: #0033CC }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+bin.includes = META-INF/,\
+               plugin.xml,\
+               html/,\
+               tocPI.xml,\
+               intro/,\
+               index.xml,\
+               tocProfiler.xml,\
+               tocAnalyzer.xml,\
+               tocConcepts.xml,\
+               tocRelease.xml,\
+               book.css,\
+               index/
+src.includes = plugin.xml,\
+               html/,\
+               META-INF/,\
+               tocPI.xml,\
+               intro/,\
+               index.xml,\
+               tocAnalyzer.xml,\
+               tocProfiler.xml,\
+               tocConcepts.xml,\
+               tocRelease.xml,\
+               book.css
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/build_index.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="com.nokia.carbide.cpp.pi.doc.user" default="build.index" basedir=".">
+
+	<target name="build.index" if="eclipse.running" >
+		<help.buildHelpIndex manifest="${basedir}/plugin.xml" destination="${basedir}" />
+	</target>
+	
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/Getting_Started/GS_index.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head>
+<meta name="keywords" content="Carbide.c++ Performance Investigator" />
+<title>Carbide.c++ Performance Investigator</title>
+<script language="JavaScript" src="PLUGINS_ROOT/org.eclipse.help/livehelp.js"></script>
+<link href="../../book.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<h2>Getting Started</h2>
+<p>The primary goal of the Carbide.c++ Performance Investigator (PI) is to gather performance data on a handheld device and save the data to a profiler data (.dat) file. On your PC workstation, PI lets you analyze that performance data. The Performance Investigator analyzer software is a plugin to Eclipse Carbide.c++.</p>
+<p>Importing the profiler data file in Carbide.c++ will launch the analyzer and present graphs and tables related to the data captured on the handheld target device. The following links provide information to  capture and analyze data.</p>
+<ul>
+  <li><a href="../tasks/profiler/prof_installation.htm">Installing the Profiler on the Target Device</a></li>
+  <li><a href="../reference/profiler/prof_using.htm">Using the Profiler</a></li>
+  <li><a href="../tasks/analyser/an_load_trace_files.htm">Importing Profiler Data File for Analysis</a></li>
+  <li><a href="../reference/analyzer/an_use_case_features.htm">Examining a Profiling Project</a></li>
+</ul>
+<p class="note"><b>NOTE</b> You can also use <img src="PLUGINS_ROOT/org.eclipse.help/command_link.png" align="middle" alt="" /> <a class="command-link" href='javascript:executeCommand("org.eclipse.ui.cheatsheets.openCheatSheet(cheatSheetId=com.nokia.carbide.cpp.pi.doc.user.getStarted)")'>Performance Investigator Setup</a> to walk you through this getting started process. </p>
+<p class="note"><b>NOTE</b> The recommended amount of memory is at least 1Gbytes. If you open or import several large profiler data files, the Java Virtual Machine executing Carbide.c++ may run out of memory.
+<br /> <br />
+To allocate more memory, edit the <span class="code">Carbide.c++.ini</span> file (typically in the Carbide.c++ folder that contains <span class="code">Carbide.c++.exe</span>). For example, for 1GBytes, edit <span class="code">Carbide.c++.ini</span> to contain <span class="code">-Xmx1024m</span> and then restart Carbide.c++.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+   </html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/Getting_Started/example_project.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,49 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head>
+<title>Examining a Profiling Project</title>
+<link href="../../book.css" rel="stylesheet" type="text/css" />
+</head><body>
+<h2><a name="example" id="example"></a>Examining a Profiling Project</h2>
+<p>The purpose of creating a profiling use case is to analyze the performance of Symbian OS applications. In general, the objective is to define the behavior of an application and its environment when they are interacting. When designing a profiling use case, it helps to document the process and save log files.</p>
+<p>Existing test cases created by application developers or test personnel can be used as a template. However, consider the following when designing and preparing a test of a profiling use case.</p>
+<p>High Profiler sampling rates can cause trace files to grow excessively large, especially if the test lasts for a long time. Therefore, it is recommended that the duration of the test be as short as possible. The maximum duration of a profiling test is typically two to three minutes. There should also be reasonable gaps between input events so that specific events can be easily detected and distinguished from the trace log.</p>
+<p>The following example describes in a high-level how to search for performance bottlenecks. Refer to Figure 1 to illustrate an example of determining time spent in a particular application and the related functions consuming most of the CPU time.</p>
+<p align="center"><img src="../images/GS_example_figure1.png" width="679" height="574" /></p>
+<p align="center" class="figure">Figure 1. Examining a Specific Application</p>
+<p align="left">As shown in Figure 1, examine the thread load graph and select the time interval of interest. In this example, the selected time interval is 21.010 to 21.970 seconds.</p>
+<p align="left">Figure 1 indicates the three most CPU time consuming threads in the time frame 21-22 seconds:</p>
+<ul>
+  <li>23.02% Null</li>
+  <li>16.56% Wserv_36 </li>
+  <li>15.31% Main_295</li>
+</ul>
+<p>Notice that only <span class="code">Null (ekern.exe[1]::Null_0)</span> and<span class="code"> Wserv_36</span> are checked and thus are shown in the graph. To add or remove threads from the graph, use the shift and control keys to check or uncheck multiple lines. Right-click to display a context menu for more options.</p>
+<p>You can determine which binaries are executed by the threads during the 21-22 second interval by right-clicking inside the table and selecting <strong>Thread &gt; Binary</strong>. This will change the graph displayed to the binary load graph in Figure 2.</p>
+<p align="center"><img src="../images/GS_example_figure2.png" width="679" height="574" /></p>
+<p align="center" class="figure">Figure 2. Binary Load Graph </p>
+<p>As shown in Figure 2, this application spends 21.25% of the time in the <span class="code">_reka2_ekern.exe</span> binary. At the lowest level, you can find out which functions are executed by the binaries that execute during the 21-22 second interval by right-clicking inside either table and selecting <strong>Thread &gt; Binary &gt; Function</strong>. This will change the graph displayed to the function load graph in Figure 3.</p>
+<p class="note"><strong>NOTE:</strong> For each selected binary in Figure 2, the Analyser graphs all of
+that binary's samples, just as if you had selected that binary in the Binaries tab. The graph does not only
+show binary samples that are also associated with threads
+<span class="code">ekern.exe[1]::Null_0</span> and<span class="code"> Wserv_36</span>.
+We expect to deliver that functionality in a future release. 
+Keep this in mind as you drill down into a specific thread, binary, or function.</p>
+<p align="center"><img src="../images/GS_example_figure3.png" width="679" height="574" /></p>
+<p align="center" class="figure">Figure 3. Function Load Graph</p>
+<p>Figure 3 shows that 9.90% of the execution time was spent in a single function called NKern::RestoreInterrupts(int), within the _reka2_ekern.exe binary. In the Function table scroll to see the <strong>In Binary</strong> column to determine the binary containing the function.</p>
+<p>Select the Function Calls tab to view the Function Call Analysis tables, as shown in Figure 4.</p>
+<p align="center"><img src="../images/GS_example_figure4.png" width="682" height="574" /></p>
+<p align="center" class="figure">Figure 4. Function Call Analysis</p>
+<p align="left">Individual functions can be selected to determine, within the time frame 21-22 seconds, which functions called the selected function and which functions were called by the selected function. You can sort functions by clicking the headings provided for each column.</p>
+<p align="left"><strong>Related references</strong></p>
+<ul>
+  <li><a href="../reference/analyzer/GUI_tour.htm">Analyzer GUI Controls </a></li>
+  <li><a href="../reference/analyzer/analyzing_table_data.htm">Analyzing Table Data</a> </li>
+  <li><a href="../reference/analyzer/thread_load.htm">Thread Load</a></li>
+  <li><a href="../reference/analyzer/binary_load.htm">Binary Load</a></li>
+  <li><a href="../reference/analyzer/function_load.htm">Function Load</a></li>
+  <li><a href="../reference/analyzer/function_calls.htm">Function Calls</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br />License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/Getting_Started/tour.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Tour of Sample Target UI and Profiler UI</title>
+<link href="../../book.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+  <h2><a name="tour"></a>Tour of User Interface</h2>
+  <p>The user interfaces for the target sotware (sampling application running on handheld device) and host software (profiler application running on PC) are described below.</p>
+  <h4>Handheld Device</h4>
+  <p>Handheld devices running the Symbian S60 Operating System can capture a data profile sequence from  a running application.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/bugs_fixed.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <title>PI Bugs Fixed</title>
+  <link href="../book.css" rel="stylesheet" type="text/css" />
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link href="../book.css" rel="stylesheet" type="text/css" />
+  <script language="JavaScript" src="PLUGINS_ROOT/org.eclipse.help/livehelp.js"></script>
+</head>
+<body bgcolor="#ffffff">
+<h2>Performance Investigator Bugs Fixed </h2>
+<p>This is a comprehensive list of  bugs fixed by release: </p>
+<ul>
+  <li><a href="#bugs210">Bugs Fixed in 2.1.0</a></li>
+  <li><a href="#bugs200">Bugs Fixed in 2.0.0</a></li>
+  <li><a href="\">Bugs Fixed in 1.3.1</a>, <a href="\">1.3.0</a>, <a href="\">1.2.2</a>, <a href="#bugs121">1.2.1</a></li>
+</ul>
+<h3><a name="bugs210" id="bugs2"></a>Bugs Fixed in v2.1.0</h3>
+<ul>
+  <li><a href="https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=8500">8500</a> - Fixed an issue that when importing symbols where certain symbols contained erroneous address data.</li>
+</ul>
+<h3><a name="bugs200" id="bugs"></a>Bugs Fixed in v2.0.0</h3>
+<ul>
+  <li><a href="https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=2332">2332</a> - Added ability to change the CPU address/thread sampling interval between 1ms and 10000ms (10 seconds). </li>
+  <li><a href="https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=4033">4033</a> - The Select Time Interval dialog has been improved to prevent choosing intervals that extend outside the range of profiled data. Choosing time intervals by using click-drag-release in graphs has been similarly improved. An interval partly outside the graph is converted to one that ends at the last CPU load sample time. </li>
+</ul>
+<h3><a name="bugs131" id="bugs131"></a>Bugs Fixed in v1.3.1</h3>
+<ul>
+  <li><a href="https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=2550">2550</a> - Made PI importing more robust to prevent attempts to load malformed or incorrectly labeled .DAT files.</li>
+</ul>
+<h3><a name="bugs130" id="bugs130"></a>Bugs Fixed in v1.3.0</h3>
+<ul>
+  <li><a href="https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=3664">3664</a> - Use the pointer to select time in any of the graph views (CPU load, power, memory) or enter the selection values in the Select Time Interval dialog</li>
+  <li><a href="https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=3933">3933</a> - Its now possible in PI to select all the rows in a table using Ctrl-A/Select All</li>
+  <li><a href="https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=4033">4033</a> - CPU Profiling Data selection has been improved to prevent assigning values that extend outside the range of profiled data</li>
+  <li><a href="https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=4458">4458</a> - Added support to Importer for ROFS symbols and multiple ROFS images</li>
+  <li><a href="https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=4488">4488</a> - PI will no longer issue a &quot;Function not found&quot; error message when the SYMBOL file function is the last function in the DLL</li>
+  <li><a href="https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=4785">4785</a> - The Average Power Mode graphics should be much more readable now</li>
+  <li><a href="https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=5759">5759</a> - Updated the Carbide Profiler to work with the N93 </li>
+</ul>
+<h3><a name="bugs122" id="bugs122"></a>Bugs Fixed in v1.2.2</h3>
+<ul>
+  <li><b>4197</b> - Fixed an issue that could cause the PI Function tab to hang when zooming to the entire selection</li>
+  <li><b>4206</b> - Corrected a syntax reading error in OBY files that incorrectly resolved the ROFS path and prevented analysis of binaries and functions</li>
+  <li><b>4333</b> - Contextual menus now correctly appear as inactive when tables in the Function Calls tab are blank</li>
+  <li><b>4335</b> - Selecting an empty time period now correctly clears all tables in the Function Calls tab</li>
+  <li><b>4336</b> - Closing an error dialog will no longer cause an exception after attempting to open a source file for the selected function</li>
+</ul>
+<h3><a name="bugs121" id="bugs121"></a>Bugs Fixed in v1.2.1</h3>
+<ul>
+  <li><b>3942</b>	- Changing a Button Event Mark value from numerical &quot;5&quot; to string &quot;Five&quot; in the Name box and adding a comment should no longer corrupt the NPI data file</li>
+  <li><b>3946</b>	- The Memory Statistics dialog now shows a value for the highest memory usage found in the given interval  (see 4018) </li>
+  <li><b>3951</b>	- The Memory Usage Data view revised to show more meaningful thread/process names and documentation revised to clarify column contents </li>
+  <li><b>3959</b>	- Power usage documentation revised to clarify constraint of device timing when doing power measurements </li>
+  <li><b>3979</b> - Analyzer updated to better handle  data files with incorrectly structured address/thread traces </li>
+  <li><b>4018</b>	- Added the Memory Statistics dialog with max RAM usage information to the documentation (see 3946)</li>
+</ul>
+<p><br />
+</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/cheatsheets/getStarted_pi_cs.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<cheatsheet title="Performance Investigator Setup">
+	<intro>
+		<description>
+		Follow these steps to create a Performance Investigator project and analyze it.
+		</description> 
+	</intro> 
+	
+	<item title="Install the Profiler" href="/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/prof_installation.htm" skip="true" >
+		<description>
+		Transfer and install S60_3_1_Prof_v1_62.sisx file to the target device.
+		</description>
+	</item>
+
+	<item title="Setup and Start Profiler" href="/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/prof_using.htm" skip="true" >
+		<description>
+		Setup Profiler on the target device and capture application data.
+		</description>
+	</item>
+
+	<item title="Transfer Profiler Data File to PC" href="/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/usb_connection.htm" skip="true" >
+		<description>
+		Transfer the profiler data file to the PC by USB, Bluetooth, or serial interface connection.
+		</description>
+	</item>
+
+	<item title="Import Profiler Data File" href="/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/an_load_trace_files.htm" skip="true" >
+		<description>
+		Import profiler data file in Carbide.c++ for analysis.
+		</description>
+	</item>
+
+	<item title="Analyze Application Profile" href="/com.nokia.carbide.cpp.pi.doc.user/html/Getting_Started/example_project.htm" skip="false" >
+		<description>
+		Analyze the profiled application data within Carbide.c++.
+		</description>
+	</item>
+
+</cheatsheet>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/abbrev.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Abbreviations</title>
+<link href="../../book.css" rel="stylesheet" type="text/css">
+<meta http-equiv="Content-Type">
+</head>
+<body>
+<h2>Acronyms</h2>
+<table width="69%"  border="0" cellpadding="2" cellspacing="0">
+  <tr>
+    <th width="23%" scope="col">Abbreviation</th>
+    <th width="77%" scope="col">Definition</th>
+  </tr>
+  <tr>
+    <td><b>ANSI</b></td>
+    <td>American National Standards Institute</td>
+  </tr>
+  <tr>
+    <td><b>CPSR</b></td>
+    <td>Current Program Status Register</td>
+  </tr>
+  <tr>
+    <td><b>CPU</b></td>
+    <td>Central Processing Unit</td>
+  </tr>
+  <tr>
+    <td><b>DFC</b></td>
+    <td>Delayed Function Call</td>
+  </tr>
+  <tr>
+    <td><b>DLL</b></td>
+    <td>Dynamic Link Library</td>
+  </tr>
+  <tr>
+    <td><b>DSP</b></td>
+    <td>Digital Signal Processor</td>
+  </tr>
+  <tr>
+    <td><b>FIQ</b></td>
+    <td>Fast Interrupt reQuest</td>
+  </tr>
+  <tr>
+    <td><b>IRQ</b></td>
+    <td>Interrupt ReQuest</td>
+  </tr>
+  <tr>
+    <td><b>ISR</b></td>
+    <td>Interrupt Service Routine</td>
+  </tr>
+  <tr>
+    <td><b>LDD</b></td>
+    <td>Logical Device Driver</td>
+  </tr>
+  <tr>
+    <td><b>LR</b></td>
+    <td>Link Register</td>
+  </tr>
+  <tr>
+    <td><b>MMC</b></td>
+    <td>MultiMedia Card</td>
+  </tr>
+  <tr>
+    <td><b>MMU</b></td>
+    <td>Memory Management Unit</td>
+  </tr>
+  <tr>
+    <td><b>OBY</b></td>
+    <td>OBeY file (file type)</td>
+  </tr>
+  <tr>
+    <td><b>OMAP</b></td>
+    <td>Open Multimedia Application Platform</td>
+  </tr>
+  <tr>
+    <td><b>PC</b></td>
+    <td>Program Counter (also Personal Computer)</td>
+  </tr>
+  <tr>
+    <td><b>RAM</b></td>
+    <td>Random Access Memory</td>
+  </tr>
+  <tr>
+    <td><b>ROFS</b></td>
+    <td>Read Only File System</td>
+  </tr>
+  <tr>
+    <td><b>ROM</b></td>
+    <td>Read Only Memory</td>
+  </tr>
+  <tr>
+    <td><b>SDRAM</b></td>
+    <td>Synchronous Dynamic Random Access Memory</td>
+  </tr>
+  <tr>
+    <td><b>SPSR</b></td>
+    <td>Saved Program Status Register</td>
+  </tr>
+  <tr>
+    <td><b>SRAM</b></td>
+    <td>Static Random Access Memory</td>
+  </tr>
+  <tr>
+    <td><b>SWI</b></td>
+    <td>Software Interrupt</td>
+  </tr>
+  <tr>
+    <td><b>UART</b></td>
+    <td>Universal Asynchronous Receiver/Transmitter</td>
+  </tr>
+</table>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/analyser.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Performance Investigator Analyzer</title>
+    <link href="../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Performance Investigator Analyzer</h2>
+<p> The Analyzer is graphical software for analyzing software performance measurement results collected from a device running the Profiler. The analyzer consists of a plugin-architecture. This means that the software consists of a static core-component (Analyzer Core), and several dynamic plug-in components. This is depicted in  Figure 1.</p>
+<p align="center"><img src="../reference/analyzer/images/analz_plugins.png" width="668" height="213"></p>
+<p class="figure">Figure 1. Analyzer plug-in architecture</p>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="../reference/analyzer/an_installation.htm">Analyzer Installation</a></li>
+  <li><a href="../tasks/analyser/an_load_trace_files.htm">Importing Profiler Data File for Analysis</a></li>
+  <li><a href="../reference/analyzer/an_use_case_features.htm">Analyzing Sampled Data</a></li>
+  <li><a href="../Getting_Started/example_project.htm">Examining a Profiler Project</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/basic_operation.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Basic Operation</title>
+    <link href="../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Basic Operation</h2>
+<p>The following Profiler information provides a view on how trace items have been put together to produce a functional combination of measurement software.</p>
+<p><a href="#figure1">Figure 1</a> gives an overview of the practical instrumentation in use within the Performance Investigator Tool. As shown, the low-level functionality has been encapsulated to a LDD (Logical Device Driver), which is able to perform under a supervisor mode with kernel privileges. In Figure 2, the data flow is represented by a dashed line, and the control flow with a solid line. Active elements that perform processing (processes and interrupts) are indicated in grey and passive elements (software components) in white.</p>
+<p align="center"><img src="../images/concpt_thread_analysis.png" width="1004" height="754"></p>
+<p class="figure"><a name="figure1"></a>Figure 1. Conceptual model of the thread level load analysis instrumentation</p>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="func_level_load.htm">Function Level Load Analysis</a></li>
+<li><a href="dll_support.htm">DLL Support Trace and Analysis</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/button_press_capture.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Button Press Capture</title>
+    <link href="../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Button Press Capture </h2>
+<p> It is possible with Performance Investigator to capture button press information in the Profiler and display it in the Analyser. When doing a Button Press Capture trace on the target device, a timestamp and string for each button pressed is stored. </p>
+<p align="center"><img src="images/view_button_markers.png" width="816" height="154"></p>
+<p class="figure">Figure 1. Button Press Capture information displayed in an analyser view. </p>
+<p>You  <a href="../tasks/profiler/btn_press_enable.htm">enable</a> the Button Press Capture option in the Profiler to gather button event information. The data is stored in the profiler data file and can later be viewed in the Analyzer. You can choose to <a href="../tasks/analyser/btn_press_show.htm">show or hide</a> the button event information in the analyzer view or <a href="../tasks/analyser/btn_press_change.htm">add</a> comments to every  button press event. By default, button events are shown. </p>
+<h5>Related references</h5>
+<h5>Related tasks</h5>
+<ul>
+  <li><a href="../tasks/analyser/btn_press_change.htm">Changing Button  Event Information</a></li>
+  <li><a href="../tasks/profiler/btn_press_enable.htm">Setting the Button Press Capture Option</a></li>
+  <li><a href="../tasks/analyser/btn_press_show.htm">Showing/Hiding Button Events</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/dll_support.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>DLL Support Trace and Analysis EKA1 version</title>
+    <link href="../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Dynamic Binary Support Trace and Analysis</h2>
+<p>Dynamic binary support  trace analysis is dedicated to performing function level performance analysis on binaries that have been uploaded to the device at run-time, at least in the operating system&rsquo;s point of view. In those cases, the address of the binary is not known at compile-time. If sampled with any of the previously mentioned methods, it is impossible to tell the binary from an address that is not found from the symbol file, which is produced at run-time. One solution to resolve the problem is to store small pieces of the executed binary code at run-time and store them along with the trace taken.</p>
+<p>Performance Investigator suppports  EKA2 dynamic support trace and analysis. Dynamic binary support trace in EKA2 works on a different principle than in EKA1. This is facilitated by certain changes in the kernel. In the EKA2 version, the collected information provides a semantically similar result as the EKA1 version, thus information about dynamically loaded binaries and their locations in memory is provided as the result of the analysis. However, the information collected from the system is much more straightforward in the EKA2 version.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/func_level_load.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Function Level Load Analysis</title>
+    <link href="../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Function Level Load Analysis</h2>
+<p>Function level load analysis is based on the same principles as the thread level load analysis. The main difference is that the information collected within the periodic interrupt is used in a different way and combined with external symbolic information collected at compile-time. In function level load analysis, the importance is on the recorded value of the retrieved program counter register (PC), indicating the location of the execution before the periodic interrupt. By comparing the value of the PC with the memory map within the symbolic information, the name of the function that was executed can be extracted. In addition, the location of the interrupted execution within the function can be calculated as an offset value.</p>
+<p><a href="#fig2">Figure 1</a> shows how information from the symbolic function list is used to resolve a function&rsquo;s name and an offset to its starting point. The procedure is simple. In the example, the address 0x5032014e is from a periodic interrupt, thus execution was in that location when the interrupt occurred. In the analysis phase, the name of the function is calculated by first searching for a function from the symbolic function name list that matches the address in question. A match means that the searched address must be larger than the function start address (0x5032011c) and smaller than the function address + function length (0x5032011c + 0x50 = 0x5032016c). The addresses in the symbolic function name list appear in order, arranged according to the function addresses. Since the functions never overlap each other, there can be only one function matching each address. The example address 0x5032014e fulfils both of these conditions. Therefore the function name can be resolved as shown in Figure 2. In addition, a more precise place of execution within the function can be calculated by subtracting the function&rsquo;s start address from the sampled value. A value smaller than the function length (in this case 0x50) should be the outcome of the subtraction. The calculation in this example indicates that the execution has been in a location that is 0x32 bytes from the start of the function.</p>
+<p>When analyzing large amounts of sampled PC values gathered during normal execution, the most heavily loaded functions can be figured out with analysis that maps the PC values with functions, since without the symbolic information it would be impossible to distinguish between different functions. With periodic sampling, a heavily loaded function has more samples in a time period than other functions. Interpretation of the results is always case-dependent and accordingly there is no generic value or percentage that would distinguish heavily loaded functions from others. It is also important to notice that the amount of execution time spent in a function does not reveal the actual cause of the load nor the actual amount of function calls made to the function. The time spent in a function is a combination of the initial status of the data accessed by the function, the input parameters of the function, and the state of other activities performed in parallel with the function. Therefore the understanding of the statistical nature of function-level load analysis is a strong prerequisite for further analysis aiming at resolving the actual cause of the load.</p>
+<p align="center"><img src="../images/fig3_rslv_func_offset.png" width="580" height="304"></p>
+<p class="figure"><a name="fig2"></a>Figure 1. Resolving the function name and a relative offset</p>
+<p>A high load percentage in one function is not always an indication of a performance problem. Certain functions have a well justified right to occupy processing time at certain occurrences. One way to have more understanding of the results of the function-level load analysis is to perform a linked function level load analysis, in which the call/callee relations of function call chains can be resolved to a certain extent. This however requires more complicated instrumentation and analysis methods as will be explained in the following.</p>
+<h3>Linked function level load tracing and analysis (Function Call trace)</h3>
+<p>When performing periodic sampling, processing of a normal scheduled load (application threads and processes) is interrupted externally with a timer interrupt. During the time the interrupt service routine executes, the register values within the processor and the data values within the kernel structures can be investigated. As explained in the previous examples of periodic sampling and function level load analysis, the stored value of the program counter register (PC) is used to resolve the location of the interrupted execution.</p>
+<p>In addition to the value of the PC, another important register within the ARM architecture is the link register (LR). With the GCC (and RVCT) compiler options set for current Symbian build, entering an arbitrary function (performing a function call) takes place with a machine instruction called branch and link (BL). In the internal operation of the ARM processor, the BL instruction stores the return address to the link register. The return address follows the BL instruction that causes the branch. Returning from a function takes place simply by storing the LR value back to the PC, thus forcing the processor to continue execution from the location in the function that preceded the branch.</p>
+<p>Accordingly, it is possible to resolve the function that made the call to the currently executing function by examining the value of the LR at any arbitrary point of execution. The value can be used to add important information to the one produced by the function analysis. From a large number of individual samples it is possible to create a statistical distribution of the callers of each function. When the distribution of each function&rsquo;s callers is known, the caller and callee functions can be connected together in the analysis. This way it is possible to construct more complex representations of the relevant functions and their call relationships within the sampled execution. In other words, the individual functions can be connected together into a grid that gives a more comprehensive view on the execution by giving indication about the functions that initiate complex function call chains.</p>
+<p align="center"><img src="../images/fig4_prin_lnkd_func.png" width="937" height="485"></p>
+<p class="figure"> Figure 2. Basic principle of linked function level load analysis</p>
+<p>Just to make things a bit more complicated, there is one important circumstance in which the value in the LR is invalid for use with the ARM processor and GCC (and RVCT) compiler with Symbian software. After entering a function, the value of the return address is stored in the LR by the BL instruction. According to common practices, the value of the LR register is most often pushed to the stack (depending on the compiler-initiated decisions within the function&rsquo;s register usage). The LR can then be retrieved from the stack just before leaving the function, or in some cases the value can be copied directly from the stack to the PC register in order to cause the processor to branch. Pushing the LR to the stack makes it possible to waste the original value within the LR within the function, without having to worry about its appropriate retrieval before leaving the function and thus retrieving the value from the stack. The compiler takes care of all of this automatically. In the presented use, however, it is essential to know whether the value in the LR is the correct value (pointing to the original return address).</p>
+<p>Fortunately, the mechanism in which the LR gets wasted is in most cases quite trivial. The original value is overwritten in a subsequent branch and link (BL) command within the function. After a subsequent branch, the LR value remains to point to the return value of the last BL command executed, and therefore the original value is lost. In all cases, this last value has to be inside the function in which the execution takes place. Therefore, a simple rule can be applied. If the value within the LR register points outside the currently executing function, it points to the original return value of the function. On the contrary, if the value within the LR points to a value within the currently executing function, its value is due to a subsequent branch that has taken place within the currently executing function. In such cases the original value remains unknown. In practice, the original value remains in the stack, but due to the dynamic nature of stack utilization within a function, its retrieval would be much more complicated. In practice the retrieval would require instruction-level back-trace of the function&rsquo;s execution.</p>
+<p align="center"><img src="../images/figure5.png" width="849" height="482"></p>
+<p class="figure">Figure 3. Resolving correct values in linked function level load analysis</p>
+<p>Thus, through periodic sampling it is possible to always retrieve the address of the interrupted execution from the PC, and in a certain proportion of cases it is also possible to retrieve the caller of the function in which the execution takes place from the LR. The proportion of those two cases is in practice dictated by the proportion of instructions executed on average before and after the first subsequent BL command within the function. When analyzing the results, this proportion can be calculated for each function as a proportion between the sampled LR values that point outside the function and the values that point inside the function. In the analysis within the Performance Investigator, this proportion is used in extrapolating the amount of callers to a certain function. It is assumed that the distribution of callers of a certain function is the same in the samples from which the caller function could not be resolved as it is within the samples in which the value could be retrieved. This is shown in Figure 3. In specific circumstances, this assumption can result in an error, mainly by multiplying &ldquo;noise&rdquo; to statistically important dimensions. This has to be taken into consideration when reading the results.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/images/con_memory_usage.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/images/view_button_markers.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/learn_prof.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Learning the Tool</title>
+    <link href="../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Learning the Tool</h2>
+<p>The following topics will familiarize you with the Performance Investigator. The topics provide a conceptual overview, basic operation, and software measurement methods used in analyzing the performance of your applications.</p>
+<ul>
+  <li><a href="overview/overview.htm">Overview</a></li>
+<li> <a href="overview/sw_performance.htm">Software Performance</a></li>
+<li> <a href="methods.htm">Performance Measurement Methods</a></li>
+<li><a href="../reference/profiler/profiler.htm">Profiler</a></li>
+<li> <a href="../reference/analyzer/analyser.htm">Performance Investigator Analyzer</a></li>
+<li><a href="../reference/profiler/Trace_Items.htm">Trace Items</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/memory_usage_capture.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Memory Usage Capture</title>
+    <link href="../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Memory Usage Capture</h2>
+<p> Use the Profiler application's <b>Memory usage capture</b> <a href="../reference/profiler/tracing_options.htm">option</a> to capture memory usage data on the target device. The data is stored in the profiler data file during a trace operation and can later be viewed in the Analyzer (Figure 1).</p>
+<p align="center"><img src="images/con_memory_usage.png" width="708" height="653"></p>
+<p class="figure">Figure 1. Memory Usage Capture information displayed in an analyser view. </p>
+<p>The Symbian OS API allocates memory in chunks. A chunk is a region of RAM mapped into contiguous linear addresses. At creation, a process has one to three chunks: </p>
+<ul>
+  <li>a stack/heap chunk contains the stack and heap used in the main thread of the process</li>
+  <li>a code chunk exists if the process is loaded into RAM</li>
+  <li>a data chunk exists if the process has static data</li>
+</ul>
+<p> A process can create more chunks, including global chunks accessible by other processes. When a chunk is created, is owned by the current process or the current thread.</p>
+<h5>Related references</h5>
+<ul>
+  <li><a href="../reference/analyzer/view_memory_usage.htm">Memory Usage View</a></li>
+  <li><a href="../reference/analyzer/menu_memory_graph.htm">Memory Graph Menu </a> </li>
+</ul>
+<h5>Related tasks</h5>
+<ul>
+  <li><a href="../reference/profiler/tracing_options.htm">Setting Tracing Options</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/methods.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Performance Measurement Methods</title>
+    <link href="../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Performance Measurement Methods</h2>
+<p> Characteristics of the software being analyzed will set rules and freedoms for performance measurements. Similarly, characteristics of the hardware architecture play a significant role in the mechanisms that can be used in performance measurement. If performing computations without a multitasking operating system, a thread-load distribution does not exist since there would be no threads. Computational load within a system that bases heavily on external interrupts is more unpredictable and complex from the software point of view than the load of a system in which most of the interrupts are caused by internal mechanisms known to the system. Therefore the measurement mechanisms have to suit the particular dynamics of the software being measured. Those mechanisms have to be feasible within the particular hardware. This makes things a bit more complicated for software based performance measurements since the same measurement software cannot necessarily be used for two systems with different run-time or input/output dynamics or hardware architecture. The methods and building blocks used in performance measurements include:</p>
+<ul>
+  <li><a href="../reference/methods/compile_time.htm">Compile-Time Symbolic Information</a></li>
+  <li><a href="../reference/methods/delayed_fn_call.htm">DFC, Delayed Function Call</a></li>
+  <li><a href="../reference/methods/dynamic_bin_res.htm">Dynamic Binary Resolution</a></li>
+  <li><a href="../reference/methods/file_sys_storing.htm">File System</a></li>
+  <li><a href="../reference/methods/int_stack.htm">Interrupt Stack</a></li>
+  <li><a href="../reference/methods/kernel_containers.htm">Kernel Containers</a></li>
+  <li><a href="../reference/methods/kernel_hook.htm">Kernel Hook</a></li>
+  <li><a href="../reference/methods/link_register.htm">Link Register value</a></li>
+  <li><a href="../reference/methods/os_thread.htm">OS Thread Name and ID</a></li>
+  <li><a href="../reference/methods/periodic_int.htm">Periodic Interrupt</a></li>
+  <li><a href="../reference/methods/pgm_counter.htm">Program Counter value</a></li>
+  <li><a href="../reference/methods/read_write_load.htm">Read/Write Load Characteristics (Memory and File system)</a></li>
+  <li><a href="../reference/methods/rofs.htm">ROFS</a></li>
+</ul>
+<p class="note"> <strong>NOTE:</strong> Many of these methods and building blocks are specific to the OMAP/ARM architecture and Symbian OS actually used.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/overview/overview.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Overview</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Overview</h2>
+<p>The Performance Investigator is a software performance measurement tool. The Performance Investigator collects run-time information from your application and other software running on a Symbian OS enabled device, such as a Nokia S60 phone, or a SEMC device running UIQ. The recorded information is then analyzed in the Performance Investigator analyzer software running on a PC.</p>
+<p>Performance Investigator currently supports the following:</p>
+<ul>
+  <li>Nokia devices running S60 3.0 and 3.1 </li>
+  <li>SEMC devices running UIQ 3.0</li>
+  <li>Symbian TechView for Symbian OS 9.2, 9.3, 9.4, and 9.5</li>
+</ul>
+<p>The Performance Investigator collects performance data. It interrupts software execution at regular intervals and copies to memory the contents of some processor registers and the results of some Symbian OS calls.</p>
+<p>The Performance Investigator contains two main parts:</p>
+<ul>
+  <li>First, on the target device is a user application called the Profiler. Installed with the Profiler is a device driver component that collects information from low-level (kernel and hardware-level) sources that are not generally accessed by application software. The Profiler acts as an interface to the device driver component and is required for its configuration, activation, and deactivation.</li>
+  <li>Second, on the PC there is Performance Investigator code integrated with Carbide.c++. This software consists of an importer for processing profiler data and the Analyzer, which provides a user-friendly way to examine and analyze the run-time performance information.</li>
+</ul>
+<p>The following figure illustrates the basic scenario to gather and analyze software performance data. The target device contains the actual performance measurement instrumentation referred to as the Profiler. The data file imported by Carbide.c++ is analyzed on a PC workstation independent of the target device.</p>
+<p align="center"><img src="../../images/overview.png" width="537" height="336"></p>
+<p class="figure">Figure 1. Performance Investigator Tool: profiler and analyzer</p>
+<p>Performance measurements follow a pattern in which separate performance related activities are recorded to a profiler data file within the target device as distinct traces. Each trace represents an independent performance characteristic of the target device. When the profiler data file is imported by Carbide.c++, more information can be derived from the traces. Each trace can be independently analyzed. Furthermore, information gathered from the software at compile-time can be used in the analysis in order to exploit the cross-relations between elements of information available exclusively at run-time or at compile-time.</p>
+<p><strong>Related references </strong></p>
+<ul>
+  <li><a href="sw_performance.htm">Software Performance</a></li>
+<li><a href="../../reference/profiler/profiler.htm">Profiler</a></li>
+<li><a href="../../reference/analyzer/analyser.htm">Analyzer</a></li>
+<li><a href="../../reference/abbrev.htm">Acronyms</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/overview/sw_performance.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Software Performance</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Software Performance </h2>
+<p>Two fundamental goals in understanding software performance can be seen as:</p>
+<ol>
+  <li>The ability to know which part of the software the CPU is executing at any particular instance of time</li>
+  <li>The ability to know why the CPU is executing that particular software at that particular instance of time</li>
+</ol>
+<p>Obstacles in determining software performance include:</p>
+<ol>
+  <li>Since large amounts of software can be executed with a state-of-the-art CPU, the recorded information has to be brought to some kind of an abstract level before it can be analyzed.</li>
+  <li>The complexity of action-reaction chains within state-of-the-art mobile terminal software is so huge, that it is impossible to directly derive the fundamental causes.</li>
+</ol>
+<p>When a software performance profile attributes 100% of CPU load to a set of threads, it is wise to remember that the Symbian OS performs tasks (such as switching tasks, scheduling, and exception handling) that are not really part of any thread. So the load attributed to any thread in a particular time period is only approximate.</p>
+<p>At any particular time, the software executing can be known quite precisely. This is not however, the point at which the problem can be considered solved. On the contrary, the information that performance measurements are trying to look for is &ldquo;the why&rdquo;. By understanding why excessive execution takes place within certain parts of the software, the source of the problem is a bit clearer. After understanding the &ldquo;why&rdquo;, modifications that would change the behavior can be considered.</p>
+<p>There are no comprehensive patterns to solve a performance problem. However, it is possible to resolve several performance problems at once through modifications made to one critical point in the software (referred to as a bottleneck).</p>
+<h3>Profiler Characteristics</h3>
+<p>The Profiler uses periodic interrupts to gather trace information. When a periodic interrupt occurs, the processor runs an interrupt service routine (ISR). The ISR can determine the address of the instruction executing at the time of the interrupt. Also, the ISR runs in a privileged mode that lets the ISR gather information from the Symbian OS in ways that are not allowed while in user mode.</p>
+<p>Activities within ISRs must be brief, or they will disturb other processing. So the ISR records information in a memory buffer and uses delayed function calls (DFCs) to write the information to a debug port or file system. A DFC is a Symbian OS feature that lets an ISR request that the OS run a routine later. The OS processes DFCs after all outstanding ISRs have been processed, but before control is given back to the currently executing thread.</p>
+<h5>Related references</h5>
+<ul>
+  <li><a href="../perfanalysis/perfanalysis.htm">Software Performance Analysis</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/perfanalysis/perf_basic_procedures.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Basic Analysis Procedure</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Basic Analysis Procedure</h2>
+<p>The following gives basic guidelines how to proceed and find possible problems in the system during the actual analyzing work using the analyzer&rsquo;s capabilities. </p>
+<h4>Overall CPU load graph
+</h4>
+<blockquote>
+  <p>Scale the time line (i.e. x-axis) in the CPU load graph such that you can see all essential activity from start to end of the measurement. Display all threads. This gives an overview of overall CPU load during your use case.</p>
+</blockquote>
+<h4>NULL thread overview
+</h4>
+<blockquote>
+  <p>Examine overall NULL thread execution. Time frames in which the NULL thread does not gain any CPU time are potential bottlenecks and need more detailed analysis. On the other hand, when the NULL thread has 100% of the CPU time, the system does not have anything to do. If this occurs, for example in the middle of intensive processing, available resources might be used non-optimally.</p>
+</blockquote>
+<h4>Overview of other threads
+</h4>
+<blockquote>
+  <p>Find out thread(s) causing most of the CPU load. There are typically 1-3 high-load threads within the selected time frame. Study time frames that contain potential bottlenecks one by one. </p>
+</blockquote>
+<h4>Application characteristics overview
+</h4>
+<blockquote>
+  <p>Take an overview of CPU load characteristics of the specific application(s) running in the use case. Focus on time frames in which the application(s) consume more CPU time than assumed. The binaries executing during those time frames tell you where time is being spent in user and system code.</p>
+  <p>Within the time frames requiring a more detailed analysis, try to determine at a high level what the application has been doing. When getting into a more detailed analysis, it is essential to know the origin causing the activity chain. For example, the end-user has completed a menu selection, which triggers playback of an audio file. The event has to be associated with a specific point in time in the CPU load profile.</p>
+</blockquote>
+<h4>Function-level analysis</h4>
+<blockquote>
+  <p>Examine the set of functions called within high-load threads during selected time frames. Keep in mind that your use case will determine which threads are relevant to analysis. As a rule of thumb, threads consuming more than 10% of available CPU time are rational candidates to be analysed.</p>
+  <p>When you analyze the binaries and functions in which the application spends most of its execution time, it is recommended that you analyze based on a single thread at a time.</p>
+  <p>For a high-load function, examine the code for an explanation (e.g., computation-intensive loop) as to why significant time was spent in the function. If you have captured function call data, examine the functions calling the high-load function to determine whether so many calls were necessary.</p>
+</blockquote>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/perfanalysis/perf_other_dynamic_mem.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Dynamic Memory Characteristics</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Dynamic Memory Characteristics</h3>
+<p>  Symbian programming guidelines instruct that memory should be handled as a scarce resource. Basically, memory should be allocated on demand and freed as soon as possible. Based on gathered empirical data, a typical characteristic of a dynamic memory implementation pattern in an Symbian application is the following:</p>
+<ol>
+  <li>Allocate memory</li>
+  <li>Reset contents of memory</li>
+  <li>Do something</li>
+  <li>Free the allocated memory</li>
+</ol>
+<p>If the sequential functional trace shows the above pattern and it occurs frequently in the application, try to determine why it happens. Determine whether allocation and free operations for objects of the same type and size could be replaced with a simple cache.</p>
+<p>If an application uses dynamic memory extensively, it is beneficial to know statistics of utilized block sizes. Very small block sizes used frequently are potential performance bottlenecks.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/perfanalysis/perf_other_server_threads.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Server Threads Analysis</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Server Threads Analysis</h3>
+<p>  A typical Symbian application implementation pattern is based on a client-server model. The client requests a service, and the server does the actual work. As a result, the server parts of the application cause most of the CPU load.</p>
+<p>The Symbian OS provides several system servers, such as file, font bitmap and database servers, which might be used by several applications concurrently. There might also be other application framework specific servers. In order to analyze the application characteristics properly, find out which servers the application uses. In addition, recognize how extensively the application under analysis really uses the servers, especially system ones.</p>
+<p>If the thread overview shows that server threads cause high CPU load, the problem is not necessarily in the server implementation. If a more detailed analysis of the server implementation does not reveal any major improvement items, more focus has to be put on overall application characteristics. Things to consider include the following:</p>
+<ul>
+  <li>Is client-server interaction rational? For example, frequently exchanged small messages cause overhead and decrease the application performance.</li>
+  <li>Are there nested client-server call chains? A long chain of servers utilizing services of other servers should be studied. For example, a top-level client makes a simple service request to a server that forwards the request to another server in multiple requests. As a result, a simple service request has been split up into several small requests resulting in a potential bottleneck in overall application performance.</li>
+</ul>
+<p>In general, the goal should be to minimize unnecessary calls to servers. Multiple application requests should be grouped in a single server request whenever possible.<br>
+</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/perfanalysis/perf_other_subjects.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Other Analysis Subjects</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Other Analysis Subjects</h3>
+<p>The following are additional analysis subjects: </p>
+<ul>
+  <li><a href="perf_other_server_threads.htm">Server Threads Analysis</a></li>
+  <li><a href="perf_other_dynamic_mem.htm">Dynamic Memory Characteristics</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/perfanalysis/perfanalysis.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Software Performance Analysis</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Software Performance Analysis </h3>
+<p>The Performance Investigator is based on software methods that analyze software performance. No external hardware is required. In analysis, trace data is combined with compile-time produced information (symbol files and binaries). All trace data and required symbolic information can be stored as a stand-alone file and imported into the analyzer software.</p>
+<ul>
+  <li><a href="perf_basic_procedures.htm">Basic Analysis Procedure</a></li>
+  <li><a href="perf_other_dynamic_mem.htm">Dynamic Memory Characteristics</a></li>
+  <li><a href="perf_other_server_threads.htm">Server Threads Analysis</a></li>
+</ul>
+<p><img src="../../images/nokia_copyright.png" alt="copyright" width="280" height="21"></img></p>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/concepts/power_usage_capture.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Power Usage Capture</title>
+    <link href="../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Power Usage  Capture </h2>
+<p> Use  <b>Power Usage Capture</b> to capture and examine a program&#8217;s power consumption in milliwatts. You <a href="../reference/profiler/tracing_options.htm">enable</a> Tracing Option Power Usage Capture in the Profiler and  start profiling. Then run the program you want to record power consumption on. Once recording has stopped, the data file is moved to the PC and examined within the  <a href="../reference/analyzer/view_power_usage.htm">Power Usage</a> view (Figure 1) of the Analyzer. </p>
+<p align="center"><img src="../reference/analyzer/images/view_power_usage.png" width="705" height="652"></p>
+<p class="figure">Figure 1. Power Usage Capture information displayed in an analyser view.</p>
+<h5>Related references</h5>
+<ul>
+  <li><a href="../reference/analyzer/view_power_usage.htm">Power Usage View</a> </li>
+  <li><a href="../reference/analyzer/menu_power_graph.htm">Power Graph Menu</a></li>
+</ul>
+<h5>Related tasks</h5>
+<ul><li><a href="../reference/profiler/tracing_options.htm">Setting Tracing Options</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/com_nokia_carbide_pi_address.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<!-- Define help for Debug Perspective default views -->
+<!-- plugin="com.nokia.carbide.cpp.pi.address" -->
+
+<contexts>
+
+	<!-- THREAD TAB -->
+	<context id="threadsPageContext"  >
+		<description>Use the Threads view to display the Threads Load.</description>
+		<topic label="Thread Load"    					href="html/reference/analyzer/thread_load.htm" />
+		<topic label="Analyzer view" 					href="html/reference/analyzer/main_view.htm" />
+		<topic label="Using the Analyzer"  				href="html/reference/analyzer/an_use_case_features.htm" />
+		<topic label="Examining a Profiling Project"  	href="html/Getting_Started/example_project.htm" />
+		<topic label="Setting Time Interval"  			href="html/tasks/analyser/time_interval.htm" />
+		<topic label="Setting Thresholds" 				href="html/tasks/analyser/set_thresholds.htm" />
+		<topic label="Changing Graph Colors" 			href="html/tasks/analyser/chng_graphcolor.htm" />
+	</context>
+
+	<!-- BINARIES TAB -->
+	<context id="binariesPageContext" >
+		<description>Use the Binaries view to display the Binary Load.</description>
+		<topic label="Binary Load"    					href="html/reference/analyzer/binary_load.htm" />
+		<topic label="Analyzer view" 					href="html/reference/analyzer/main_view.htm" />
+		<topic label="Using the Analyzer"  				href="html/reference/analyzer/an_use_case_features.htm" />
+		<topic label="Examining a Profiling Project"  	href="html/Getting_Started/example_project.htm" />
+		<topic label="Setting Time Interval"  			href="html/tasks/analyser/time_interval.htm" />
+		<topic label="Setting Thresholds" 				href="html/tasks/analyser/set_thresholds.htm" />
+		<topic label="Changing Graph Colors" 			href="html/tasks/analyser/chng_graphcolor.htm" />
+	</context>
+
+	<!-- FUNCTIONS TAB -->
+	<context id="functionsPageContext" >
+		<description>Use the Functions view to display the Function Load.</description>
+		<topic label="Function Load"  					href="html/reference/analyzer/function_load.htm" />
+		<topic label="Analyzer view" 					href="html/reference/analyzer/main_view.htm" />
+		<topic label="Using the Analyzer"  				href="html/reference/analyzer/an_use_case_features.htm" />
+		<topic label="Examining a Profiling Project"  	href="html/Getting_Started/example_project.htm" />
+		<topic label="Setting Time Interval"  			href="html/tasks/analyser/time_interval.htm" />
+		<topic label="Setting Thresholds" 				href="html/tasks/analyser/set_thresholds.htm" />
+		<topic label="Changing Graph Colors" 			href="html/tasks/analyser/chng_graphcolor.htm" />
+	</context>
+
+</contexts>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/com_nokia_carbide_pi_button.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<contexts>
+   <context id="btnPressChangeContext">
+      <description>Change button event information</description>
+      <topic label="Button event information" href="html/tasks/analyser/btn_press_change.htm" />
+   </context>
+   <context id="btnPressMapPrefTab">
+      <description>Select or create new Key Map Profile</description>
+      <topic label="Key Press Profile" href="html/tasks/analyser/key_profile_pref.htm" />
+   </context>
+   <context id="btnPressAddProfileDialog">
+      <description>Create Key Map Profile from copy of builtin profile</description>
+      <topic label="Define new key map profile" href="html/tasks/analyser/key_profile_pref.htm#newkeyprof" />
+   </context>
+   <context id="btnPressMapAddDialog">
+      <description>Add Key Map Entry for Profile</description>
+      <topic label="Define key map entry" href="html/tasks/analyser/key_profile_pref.htm#addkeymap" />
+   </context>
+   <context id="btnPressMapEditDialog">
+      <description>Edit Key Map Entry</description>
+      <topic label="Edit selected key map entry" href="html/tasks/analyser/key_profile_pref.htm#editkeyentry" />
+   </context>
+   <context id="btnPressEditProfileDialog">
+      <description>Define Key Map Profile</description>
+      <topic label="Add, Remove, Edit key map entries" href="html/tasks/analyser/key_profile_pref.htm#editkeymap" />
+   </context>
+   <context id="import_key_map_wizard_overlap_context">
+      <description>Import Key Map Profile</description>
+      <topic label="Existing profiles to be overwritten" href="html/tasks/analyser/key_profile_imp.htm#overlap" />
+   </context>
+   <context id="export_key_map_wizard_xml_context">
+      <description>Export Key Map Profile</description>
+      <topic label="Export to XML file" href="html/tasks/analyser/key_profile_exp.htm" />
+   </context>
+   <context id="import_key_map_wizard_xml_context">
+      <description>Import Key Map Profile</description>
+      <topic label="Import from XML file" href="html/tasks/analyser/key_profile_imp.htm" />
+   </context>
+   <context id="import_key_map_switch_dialog_context">
+      <description>Switch Key Press Profile</description>
+      <topic label="Change NPI File Key Map" href="html/tasks/analyser/key_profile_switch.htm" />
+   </context>
+
+</contexts>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/com_nokia_carbide_pi_call.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<!-- Define help for Debug Perspective default views -->
+<!-- plugin="com.nokia.carbide.cpp.pi.call" -->
+
+<contexts>
+
+	<!-- BINARIES TAB -->
+	<context id="functionCallsPageContext" >
+		<description>Show information about the function call relationships during the selected time period.</description>
+		<topic label="Function Calls"  					href="html/reference/analyzer/function_calls.htm" />
+		<topic label="Setting Time Interval"  			href="html/tasks/analyser/time_interval.htm" />
+	</context>
+
+</contexts>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/com_nokia_carbide_pi_wizards.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<!-- Define help for Debug Perspective default views -->
+<!-- plugin="com.nokia.carbide.cpp.pi.wizards" -->
+
+<contexts>
+
+	<context id="import_wizard_selection_wizard_page_context" >
+		<description>Profiler data files contain run-time performance information of your test runs.</description>
+		<topic label="Importing Profiler Data Files"		href="html/tasks/analyser/an_load_trace_files.htm" />
+	</context>
+
+	<context id="import_wizard_config_selector_page_context" >
+		<description>With varying amount of information available, Performance Investigator can resolve data to varying detail.</description>
+		<topic label="Select Known Available Information"		href="html/tasks/analyser/an_load_trace_files.htm#Select_Known_Available_Information" />
+	</context>
+
+	<context id="import_wizard_input_page_context" >
+		<description>Profiler data files contain run-time performance information of your test runs.</description>
+		<topic label="Select Profiler Data File"		href="html/tasks/analyser/an_load_trace_files.htm#Select_Profiler_Data_File" />
+	</context>
+
+	<context id="import_wizard_output_page_context" >
+		<description>Profiler output need to be named and placed into a project in the workspace.</description>
+		<topic label="Select Output File and Project"		href="html/tasks/analyser/an_load_trace_files.htm#Select_Output_File_and_Project" />
+	</context>
+
+	<context id="import_wizard_pkg_list_page_context" >
+		<description>Profiler data may be associated with projects.</description>
+		<topic label="Select Associated Project and Package"		href="html/tasks/analyser/an_load_trace_files.htm#Select_Associated_Project_and_Package" />
+	</context>
+	
+	<context id="import_wizard_rom_sdk_page_context" >
+		<description>Profiler data files contain run-time performance information of your test runs.</description>
+		<topic label="Importing Profiler Data Files"		href="html/tasks/analyser/an_load_trace_files.htm" />
+	</context>
+
+	<context id="import_wizard_rom_page_context" >
+		<description>Profiler data files contain run-time performance information of your test runs.</description>
+		<topic label="Importing Profiler Data Files"		href="html/tasks/analyser/an_load_trace_files.htm" />
+	</context>
+
+	<context id="import_wizard_custom_page_context" >
+		<description>Profiler data files contain run-time performance information of your test runs.</description>
+		<topic label="Importing Profiler Data Files"		href="html/tasks/analyser/an_load_trace_files.htm" />
+	</context>
+
+	<context id="import_wizard_bup_map_page_context" >
+        <description>Select key press mapping for target device</description>
+        <topic label="Select Key Map Profile" href="html/tasks/analyser/key_profile_select.htm" />
+	</context>
+
+	<context id="import_key_map_wizard_xml_context" >
+        <description>Import Key Map Profile</description>
+        <topic label="Import key press mapping" href="html/tasks/profiler/key_profile_imp.htm" />
+	</context>
+
+</contexts>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/org_eclipse_ui.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- Define help for Debug Perspective default views -->
+<!-- plugin="org.eclipse.ui" -->
+
+<contexts>
+	<!-- WIZARDs -->
+	
+	<!-- NEW WIZARD
+	<context id="new_wizard_selection_wizard_page_context" >
+		<description>Use the Console view to show the output of a process and provide keyboard input to a process.</description>
+		<topic label="Creating New Projects" 					href="html/tasks/CreatingNewProjects.html"/>
+	</context>
+	-->
+	
+	<!-- IMPORT WIZARD -->
+	<context id="import_wizard_selection_wizard_page_context" >
+		<topic label="Importing Profiler Data Files"		href="html/tasks/analyser/an_load_trace_files.htm" />
+	</context>
+
+    <context id="save_table_page_context" >
+	   <description>Save selected samples to a comma separated file that can be opened in a spreadsheet application.</description>
+		<topic label="Save table data to csv file"  			href="html/reference/analyzer/save_table.htm" />
+	</context>
+
+    <context id="PI_SAVE_SAMPLES_WIZARD_PAGE" >
+	   <description>Save selected samples to a comma separated file that can be opened in a spreadsheet application.</description>
+		<topic label="Save checked samples to csv file"  			href="html/reference/analyzer/save_table.htm" />
+	</context>
+
+	<!-- EXPORT WIZARD
+	<context id="export_wizard_selection_wizard_page_context" >
+		<description>Use the Console view to show the output of a process and provide keyboard input to a process.</description>
+		<topic label="Console view"  			href="html/reference/view_log.htm" />
+	</context>
+	-->
+
+	<!-- PREFERENCE PANELS -->
+
+	<!-- KEYS
+	<context id="keys_preference_page_context" >
+		<description>Use the Console view to show the output of a process and provide keyboard input to a process.</description>
+		<topic label="Console view"  			href="html/reference/view_log.htm" />
+	</context>
+	-->
+
+</contexts>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/context_help/pi.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<!-- Define help for PI default views -->
+<!-- plugin="org.eclipse.cdt.debug.ui" -->
+
+<contexts>
+
+	<!--  NOTE - PLACEHOLDERS ONLY -->
+
+	<!-- ANALYZER VIEW
+	<context id="modules_view_context" >
+		<topic label="Analyzer view" 					href="html/reference/analyzer/main_view.htm" />
+		<topic label="Using the Analyzer"  				href="html/reference/analyzer/an_use_case_features.htm" />
+		<topic label="Examining a Profiling Project"  	href="html/Getting_Started/example_project.htm" />
+		<topic label="Changing Graph Colors" 			href="html/tasks/analyser/chng_graphcolor.htm" />
+	</context>
+
+	<context id="modules_view_context" >
+		<topic label="Threshold Limits for Traced Data"  	href="html/reference/analyzer/threshold.htm" />
+   		<topic label="Setting Thresholds" 					href="html/tasks/analyser/set_thresholds.htm" />
+	</context>
+	-->
+
+</contexts>
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_fig1.jpg has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_fig1.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_fig2.jpg has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_fig2.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_figure1.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_figure2.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_figure3.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/GS_example_figure4.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/N73device.jpg has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/about_cpp.jpg has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/about_cpp.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/background_carbide.jpg has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/brandmark_cpp.gif has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/command_link.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/concpt_thread_analysis.jpg has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/concpt_thread_analysis.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/copy_drilldown_table.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/fig3_rslv_func_offset.jpg has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/fig3_rslv_func_offset.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/fig4_prin_lnkd_func.jpg has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/fig4_prin_lnkd_func.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/figure5.jpg has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/figure5.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/figure6.jpg has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/figure6.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/gold_header.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/icons/pi.gif has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/icons/pi_hov.gif has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/overview.jpg has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/overview.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/images/wnd_import_rom_build_files.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/index.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.index"?>
+
+<index>
+
+	<!-- AAAAAA  -->
+
+	<entry keyword="Advanced options" >
+		<topic href="html/reference/profiler/advanced_options.htm" />
+	</entry>
+
+	<entry keyword="Analyzer" >
+		<topic href="html/Getting_Started/example_project.htm" />
+		<topic title="Analyzer view" href="html/reference/analyzer/main_view.htm" />
+		<topic title="Binary Load" href="html/reference/analyzer/binary_load.htm" />
+		<topic title="Function Calls"	href="html/reference/analyzer/function_calls.htm" />
+		<topic title="Function Load" href="html/reference/analyzer/function_load.htm" />
+		<topic title="Thread Load" href="html/reference/analyzer/thread_load.htm" />
+		<topic href="html/reference/analyzer/analyzing_table_data.htm" />
+	</entry>
+	
+	<entry keyword="Analyzer GUI Controls" >
+	 	<topic href="html/reference/analyzer/GUI_tour.htm" />
+	</entry>
+	
+	<entry keyword="Analyzer View" >
+		<topic href="html/reference/analyzer/main_view.htm" />
+	</entry>
+	
+
+	<!-- BBBBBB  -->
+	
+	<entry keyword="Binary Load" >
+		<topic href="html/reference/analyzer/binary_load.htm" />
+	</entry>
+
+	<entry keyword="Bluetooth connection" >
+		<topic href="html/tasks/profiler/bluetooth_connection.htm" />
+	</entry>
+	
+	<entry keyword="Button Press Capture" >
+		<topic href="html/concepts/button_press_capture.htm" />
+	</entry>
+	
+	
+	<!-- CCCCCC  -->
+	
+	<entry keyword="colors, changing graph" >
+		<topic href="html/tasks/analyser/chng_graphcolor.htm" />
+	</entry>
+
+	<entry keyword="connecting" >
+		<topic href="html/tasks/profiler/bluetooth_connection.htm" />
+		<topic href="html/tasks/profiler/usb_connection.htm" />
+	</entry>
+
+	<entry keyword="Context menu options" >
+		<topic href="html/reference/analyzer/context_menu.htm" />
+	</entry>
+
+	<entry keyword="command-line tool" >
+		<topic href="html/reference/profiler/cmd_line_overview.htm" />
+	</entry>
+	
+	<entry keyword="copy" >
+		<topic href="html/reference/analyzer/analyzing_table_data.htm" />
+	</entry>
+
+	<!-- DDDDDD  -->
+	
+	<entry keyword="data file, importing profiler" >
+		<topic href="html/tasks/analyser/an_load_trace_files.htm" />
+	</entry>
+
+	<entry keyword="dialogs" >
+		<topic href="html/reference/analyzer/wnd_power_graph_settings.htm" />
+		<topic href="html/reference/analyzer/wnd_power_usage_statistics.htm" />
+		<topic href="html/reference/analyzer/threshold.htm" />
+	</entry>
+
+
+	<!-- EEEEEE  -->
+	<!-- FFFFFF  -->
+	
+	<entry keyword="Function Calls"	>
+		<topic href="html/reference/analyzer/function_calls.htm" />
+	</entry>
+	
+	<entry keyword="Function Load" >
+		<topic href="html/reference/analyzer/function_load.htm" />
+	</entry>
+
+	<!-- GGGGGG  -->
+	<!-- HHHHHH  -->
+	<!-- IIIIII  -->
+	
+	<entry keyword="importing profiler data file" >
+		<topic href="html/tasks/analyser/an_load_trace_files.htm" />
+	</entry>
+
+	<entry keyword="installation" >
+		<topic label="Installing the Analyzer" href="html/reference/analyzer/an_installation.htm" />
+		<topic title="Installing the Profiler" href="html/tasks/profiler/prof_installation.htm" />
+	</entry>
+
+	<entry keyword="Investigator menu" >
+		<topic href="html/reference/analyzer/investigator_menu.htm" />
+	</entry>
+
+	<!-- JJJJJJ  -->
+	<!-- KKKKKK  -->
+	<entry keyword="Key Map Profile" >
+		<topic href="html/tasks/analyser/key_profile_pref.htm" label="Key Map Profile Settings"/>
+		<topic href="html/tasks/analyser/key_profile_exp.htm" label="Export Key Map Profile"/>
+        <topic href="html/tasks/analyser/key_profile_imp.htm" label="Import Key Map Profile"/>
+        <topic href="html/tasks/analyser/key_profile_switch.htm" label="Switch Key Map Profile"/>
+	</entry>
+
+	<!-- LLLLLL  -->
+	<!-- MMMMMM  -->
+
+	<entry keyword="requirements, memory" >
+		<topic href="html/reference/analyzer/an_installation.htm" />
+	</entry>
+
+	<entry keyword="menus" >
+		<topic href="html/reference/profiler/advanced_options.htm" />
+		<topic href="html/reference/analyzer/context_menu.htm" />
+		<topic href="html/reference/analyzer/investigator_menu.htm" />
+		<topic href="html/reference/analyzer/menu_memory_graph.htm" />
+		<topic href="html/reference/profiler/output_settings.htm" />
+		<topic href="html/reference/analyzer/menu_power_graph.htm" />
+		<topic href="html/reference/profiler/tracing_options.htm" />
+	</entry>
+	
+	<!-- NNNNNN  -->
+	<!-- OOOOOO  -->
+	
+	<entry keyword="Output Settings" >
+		<topic href="html/reference/profiler/output_settings.htm" />
+	</entry>
+
+	<entry keyword="Open Source for Function" >
+		<topic href="html/tasks/analyser/source_lookup.htm" />
+	</entry>
+
+	<!-- PPPPPP  -->
+
+	<entry keyword="installing, profiler to target device" >
+		<topic href="html/tasks/profiler/prof_installation.htm" />
+	</entry>		
+
+	<entry keyword="Profile" >
+		<topic href="html/tasks/analyser/key_profile_pref.htm" label="Key Map Profile Settings" />
+		<topic href="html/tasks/analyser/key_profile_exp.htm" label="Export Key Map Profile"/>
+        <topic href="html/tasks/analyser/key_profile_imp.htm" label="Import Key Map Profile"/>		
+	</entry>
+
+	<entry keyword="Profiler" >
+		<topic href="html/reference/profiler/advanced_options.htm" />
+		<topic href="html/reference/profiler/output_settings.htm" />
+		<topic href="html/reference/profiler/profiler.htm" />
+		<topic href="html/reference/settings.htm" />
+		<topic href="html/reference/profiler/tracing_options.htm" />
+		<topic href="html/reference/profiler/prof_using.htm" />
+		<topic href="html/reference/profiler/cmd_line_overview.htm" />
+	</entry>
+
+
+	<entry keyword="projects" >
+		<topic title="examining" href="html/Getting_Started/example_project.htm" />
+		<topic title="profiling" href="html/reference/profiler/prof_using.htm" />
+	</entry>
+
+	<entry keyword="Power Graph menu" >
+		<topic href="html/reference/analyzer/menu_power_graph.htm" />
+	</entry>
+
+	<entry keyword="Power Usage Interval" >
+		<topic href="html/reference/profiler/advanced_options.htm" />
+	</entry>
+
+	<entry keyword="Power Usage Graph Settings" >
+		<topic title="Power Usage Settings" href="html/reference/analyzer/wnd_power_graph_settings.htm" />
+		<topic title="Power Graph menu" href="html/reference/analyzer/menu_power_graph.htm" />
+	</entry>
+
+	<entry keyword="Power Usage Statistics" >
+		<topic title="Power Usage Statistics" href="html/reference/analyzer/wnd_power_usage_statistics.htm" />
+		<topic title="Power Graph menu" href="html/reference/analyzer/menu_power_graph.htm" />
+	</entry>
+
+	<!-- QQQQQQ  -->
+	<!-- RRRRRR  -->
+	<!-- SSSSSS  -->
+	
+	<entry keyword="save" >
+		<topic href="html/reference/analyzer/analyzing_table_data.htm" />
+	</entry>
+
+	<entry keyword="save table" >
+		<topic href="html/reference/analyzer/save_table.htm" />
+	</entry>
+		
+	<entry keyword="Set Thread, Binary, or Function Thresholds" >
+		<topic href="html/reference/analyzer/threshold.htm" />
+	</entry>
+
+	<entry keyword="Selected Interval Average Power Line" >
+		<topic href="html/reference/analyzer/menu_power_graph.htm" />
+	</entry>
+
+	<entry keyword="Scale to Graph" >
+		<topic href="html/reference/analyzer/menu_power_graph.htm" />
+	</entry>
+
+	<entry keyword="Scale to Current Selected Interval" >
+		<topic href="html/reference/analyzer/menu_power_graph.htm" />
+	</entry>
+
+	<entry keyword="Source Lookup" >
+		<topic href="html/tasks/analyzer/source_lookup.htm" />
+	</entry>
+	
+	<!-- TTTTTT  -->
+
+	<entry keyword="tables" >
+		<topic href="html/reference/analyzer/analyzing_table_data.htm" />
+	</entry>
+	
+	<entry keyword="Thread Load" >
+		<topic href="html/reference/analyzer/thread_load.htm" />
+	</entry>
+
+	<entry keyword="Threshold Limits" >
+		<topic href="html/reference/analyzer/threshold.htm" />
+	</entry>
+
+	<entry keyword="time interval, setting" >
+		<topic href="html/tasks/analyser/time_interval.htm" />
+	</entry>
+
+	<entry keyword="Tracing options" >
+		<topic href="html/reference/profiler/tracing_options.htm" />
+	</entry>
+
+
+	<!-- UUUUUU  -->
+	
+	<entry keyword="USB connection" >
+		<topic href="html/tasks/profiler/usb_connection.htm" />
+	</entry>
+
+	<entry keyword="UIQ" >
+		<topic href="html/concepts/overview/overview.htm" />
+		<topic href="html/reference/profiler/prof_using.htm" />
+		<topic href="html/reference/profiler/tracing_options.htm" />
+		<topic href="html/reference/profiler/output_settings.htm" />
+		<topic href="html/reference/profiler/advanced_options.htm" />
+	</entry>
+	
+	<!-- VVVVVV  -->
+	
+	<entry keyword="views" >
+		<topic title="Analyzer" href="html/reference/analyzer/main_view.htm" />
+		<topic title="Power Usage Graph"  href="html/reference/analyzer/view_power_usage.htm" />
+		<topic title="Memory Usage Graph" href="html/reference/analyzer/view_memory_usage.htm" />
+	</entry>
+
+	
+	<!-- XXXXXX  -->
+	<!-- YYYYYY  -->
+	<!-- ZZZZZZ  -->
+	
+</index>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/legal.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>License Information</title>
+    <link href="../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>License Information</h2>
+<h5>COPYRIGHTS</h5>
+
+<p>Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. This component and the accompanying materials are made available under the terms of the License "Eclipse Public License v1.0" which accompanies this distribution, and is available at the URL <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.</p>
+ 
+<h5>Initial Contributors:</h5>
+<p> Nokia Corporation - initial contribution</p>
+<h5>NOTICES</h5>
+<p>Portions of this product are covered by the following licenses:</p>
+<ul>
+  <li>Eclipse 3.4 (available at <a href="http://www.eclipse.org/legal/epl/notice.php">http://www.eclipse.org/legal/epl/notice.php</a>)</li>
+  <li>Eclipse CDT 5.0 (available at <a href="http://www.eclipse.org/legal/epl/notice.php">http://www.eclipse.org/legal/epl/notice.php</a>)</li>
+  <li>Eclipse EMF 2.3 (available at <a href="http://www.eclipse.org/legal/epl/notice.php">http://www.eclipse.org/legal/epl/notice.php</a>) </li>
+  <li>Eclipse GEF 3.3 (available at <a href="http://www.eclipse.org/legal/epl/notice.php">http://www.eclipse.org/legal/epl/notice.php</a>) </li>
+  <li>Eclipse Remote System Explorer-1.0 (available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>)</li>
+  <li>Eclipse System Search (available at <a href="http://www.eclipse.org/legal/epl/notice.php">http://www.eclipse.org/legal/epl/notice.php</a>)</li>
+  <li>Apache Xerces-2.2.0  (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>) </li>
+  <li>Apache Batick-1.6  (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+  <li>Apache HttpClient (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+  <li>Mozilla Rhino 1.5r2 (available at <a href="http://www.mozilla.org/NPL/">http://www.mozilla.org/NPL/</a>) </li>
+  <li>OmniORB-4.0.4 (available at <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>) </li>
+  <li>GNU Binutils (available at <a href="http://sources.redhat.com/binutils/">http://sources.redhat.com/binutils/</a>)</li>
+  <li>Python 2.5.1 (available from <a href="http://www.python.org/download/releases/2.5/license/">http://www.python.org/download/releases/2.5/license/</a>) </li>
+  <li>Psyco 1.5.2 (available from <a href="http://www.opensource.org/licenses/mit-license.php">http://www.opensource.org/licenses/mit-license.php</a>) </li>
+</ul>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/profiler.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Carbide.c++ User Guide</title>
+    <link href="../book.css" rel="stylesheet" type="text/css">
+	<style>
+		table, td, th { border: 0px none #FFF; }
+    </style>
+</head>
+
+<body background="images/background_carbide.jpg" >
+<p>&nbsp;</p>
+<table width="530" border="0" align="center" cellpadding="0" cellspacing="5" bgcolor="#FFFFFF" >
+  <tr>
+    <td width="215"><img src="images/about_cpp.png" width="225" height="200"></td>
+    <td width="294" valign="bottom"><p align="right"><b><img src="images/brandmark_cpp.gif" width="106" height="52"></b></p>
+        <p>&nbsp;</p>
+        <p>&nbsp;</p>
+        <p>&nbsp;</p>
+        <p class="titleSmall">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>
+        License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></p>
+    </td>
+  </tr>
+  <tr>
+    <td colspan="2"><h1 align="center">Performance Investigator User Guide </h1>
+      <p align="center" class="titleSmall">Version 2.1.0; June, 2009</p></td>
+  </tr>
+</table>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/abbrev.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Acronyms</title>
+<link href="../../book.css" rel="stylesheet" type="text/css">
+<meta http-equiv="Content-Type">
+<style type="text/css">
+<!--
+body,td,th {
+	color: #000000;
+}
+.style1 {font-family: Arial, Helvetica, sans-serif}
+-->
+</style></head>
+<body>
+<h2>Acronyms</h2>
+<table class="MsoNormalTable"
+ style="border: 1pt solid rgb(153, 153, 153); margin-left: 10pt; width: 69%;"
+ cellspacing="0" cellpadding="0" width="100%" border="1">
+  <tr>
+    <th scope="col"><p>Abbreviation</p></th>
+    <th width="78%" scope="col">Definition</th>
+  </tr>
+  <tr>
+    <td><p class="style1">CPU</p></td>
+    <td ><p>Central Processing Unit</p></td>
+  </tr>
+  <tr>
+    <td><p class="style1">DFC</p></td>
+    <td><p>Delayed Function Call</p></td>
+  </tr>
+  <tr>
+    <td><p class="style1">DLL</p></td>
+    <td ><p>Dynamic Link Library</p></td>
+  </tr>
+  <tr>
+    <td><p class="style1">IBY</p></td>
+    <td><p>File included by an OBY file</p></td>
+  </tr>
+  <tr>
+    <td><p class="style1">IRQ</p></td>
+    <td><p>Interrupt ReQuest</p></td>
+  </tr>
+  <tr>
+    <td><p class="style1">ISR</p></td>
+    <td><p>Interrupt Service Routine</p></td>
+  </tr>
+  <tr>
+    <td><p class="style1">LR</p></td>
+    <td><p>Link Register</p></td>
+  </tr>
+  <tr>
+    <td><p class="style1">MMC</p></td>
+    <td><p>MultiMedia Card</p></td>
+  </tr>
+  <tr>
+    <td><p class="style1">OBY</p></td>
+    <td><p>OBeY file (file type)</p></td>
+  </tr>
+  <tr>
+    <td>OS</td>
+    <td>Operating System </td>
+  </tr>
+  <tr>
+    <td><p class="style1">PC</p></td>
+    <td><p>Program Counter (also Personal Computer)</p></td>
+  </tr>
+  <tr>
+    <td><p class="style1">ROFS</p></td>
+    <td><p>Read Only File System</p></td>
+  </tr>
+  <tr>
+    <td><p class="style1">ROM</p></td>
+    <td><p>Read Only Memory</p></td>
+  </tr>
+</table>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/GUI_tour.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Analyzer GUI Controls</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Analyzer GUI Controls </h2>
+<p>The Analyzer provides several user interface items to control the analyzing process as shown in Figure 1.</p>
+<p align="center"><img src="images/analz_startend.png" width="138" height="30"></p>
+<p align="center" class="figure">Figure 1. Analyzer toolbar icons</p>
+<h5>Table 1. Toolbar icons</h5>
+<table width="90%" border="0" cellpadding="2" cellspacing="0" >
+  <tr>
+    <th width="244" scope="col">Option </th>
+    <th width="72" scope="col">Icon</th>
+    <th width="473" scope="col">Description</th>
+  </tr>
+  <tr>
+    <td><b>Select Time Interval </b></td>
+    <td><div align="center"><img src="images/icon_select_time_interval.png" width="17" height="18"></div></td>
+    <td>Select the Start-End icon to <a href="../../tasks/analyser/time_interval.htm">select</a> the time interval (in seconds) to be displayed in the current load graph being viewed.</td>
+  </tr>
+  <tr>
+    <td><b>Zoom In </b></td>
+    <td><div align="center"><img src="images/icon_zoom_in.png" width="19" height="19"></div></td>
+    <td>Zooms in on the graph view to display more detail. </td>
+  </tr>
+  <tr>
+    <td><b>Zoom Out </b></td>
+    <td><div align="center"><img src="images/icon_zoom_out.png" width="18" height="18"></div></td>
+    <td>In the graph view, zooms out to display less detail of the selected time interval. </td>
+  </tr>
+  <tr>
+    <td><b>Zoom to Selected Time Interval </b></td>
+    <td><div align="center"><img src="images/icon_zoom_to_selected_int.png" width="18" height="16"></div></td>
+    <td>Locates the graph's selected time interval and displays it in center of graph. </td>
+  </tr>
+  <tr>
+    <td><b>Show Entire Graph </b></td>
+    <td><div align="center"><img src="images/icon_show_entire_graph.png" width="18" height="16"></div></td>
+    <td>Displays all profiled data in graph.</td>
+  </tr>
+</table>
+<p>You can also hover the pointer over the graph to view information as shown in Figure 2. </p>
+<p align="center"><img src="images/analz_graphitem.png" width="295" height="200"></p>
+<p align="center" class="figure">Figure 2. Specific items in graph</p>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="main_view.htm">Analyzer View</a></li>
+  <li><a href="thread_load.htm">Thread Load</a></li>
+  <li><a href="binary_load.htm">Binary Load</a></li>
+  <li><a href="function_load.htm">Function Load</a></li>
+<li><a href="function_calls.htm">Function Calls</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/an_installation.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Analyzer Installation</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Installing the Analyzer</h2>
+<p> The Performance Investigator Analyzer comes installed with Carbide.c++.</p>
+<p>Recommended amount of memory is at least 1Gbytes. If you open or import several large profiler data files, the Java Virtual Machine executing Carbide.c++ may run out of memory.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/an_use_case_features.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Analyzing Sampled Data</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Using the Analyzer</h2>
+<p>The following topics provide information about the Analyzer.</p>
+<ul>
+  <li> <a href="main_view.htm">Analyzer View</a></li>
+  <li><a href="GUI_tour.htm">Analyzer GUI Controls </a></li>
+  <li><a href="../../Getting_Started/example_project.htm">Examining a Profiling Project</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/analyser.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Profiler</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Analyzer</h2>
+<p> The Performance Investigator Analyser is used to graph, measure
+and analyze the collected traces from a device running the <a href="../profiler/profiler.htm">Profiler</a>. It appears as a standard <a href="main_view.htm">Analyzer</a> view in a Carbide perspective. </p>
+<p>The following topics provide information about the Analyzer.</p>
+<ul>
+  <li> <a href="main_view.htm">Analyzer View</a></li>
+  <li><a href="GUI_tour.htm">Analyzer GUI Controls </a></li>
+  <li><a href="../../Getting_Started/example_project.htm">Examining a Profiling Project</a></li>
+</ul>
+<h5>Related tasks </h5>
+<ul>
+  <li><a href="../../tasks/analyser/an_load_trace_files.htm">Importing Profiler Data File for Analysis</a></li>
+  <li><a href="an_use_case_features.htm">Analyzing Profiler Data</a></li>
+  <li><a href="../profiler/Trace_Items.htm">Trace Items</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/analyzing_table_data.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Analyzing Table Data</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Analyzing Table Data </h2>
+<p>Performance Investigator (PI) files collect and store a wealth of data which is then displayed in several panes for  analysis. However, it is sometimes more convenient to transfer the data to a  spreadsheet where better numerical functions and additional charting options are available. To accomplish that you must transfer the data in the PI file to the spreadsheet program. You can do this using the clipboard.</p>
+<p>Once a profiler data file is open and visible in an  active  view, the Edit menu and context menus include the following  commands:</p>
+<p>Note that additional Menu options are available for saving more precise data; depending on the table in which the context menu is activated. </p>
+<table width="90%" border="0" cellpadding="2" cellspacing="0" >
+  <tr>
+    <th width="210" scope="col">Menu Option </th>
+    <th width="461" scope="col">Description</th>
+  </tr>
+  <tr>
+    <td><strong>Copy</strong></td>
+    <td>Copies the contents of the current selection to the clipboard. The current selection is made by highlighting specific cells in a table or by <a href="../../tasks/analyser/time_interval.htm">selecting</a> a time interval on a graph. </td>
+  </tr>
+  <tr>
+    <td><strong>Copy Data for Selected Function </strong></td>
+    <td>Copies the function data, as well as the calling and called associated with the selected function, to the clipboard. </td>
+  </tr>
+  <tr>
+    <td><strong>Copy Drilldown Table</strong></td>
+    <td>Copies the  contents of the entire <a href="../../Getting_Started/example_project.htm">drilldown</a>, including column titles, to the clipboard. </td>
+  </tr>
+  <tr>
+    <td><strong>Copy Table</strong></td>
+    <td>Copies the  contents of the active table, including column titles, to the clipboard. The table contents do not have to be selected for a table copy to occur. </td>
+  </tr>
+  <tr>
+    <td><strong>Save Data for Selected Function...</strong></td>
+    <td>Saves the function data, as well as the calling and called associated with the selected function, to a file (.csv). </td>
+  </tr>
+  <tr>
+    <td><strong>Save Drilldown Table...</strong></td>
+    <td>Saves the  contents of the entire drilldown table (e.g. Threads &gt; Binaries &gt; Functions), including column titles, to a file (.csv). </td>
+  </tr>
+  <tr>
+    <td><strong>Save Table...</strong></td>
+    <td>Saves the  contents of the active table, including column titles, to a file (.csv).  </td>
+  </tr>
+  <tr>
+    <td><strong>Select All</strong></td>
+    <td>Selects the entire table in the current pane. When followed by  Copy, the entire contents of the table minus the column titles are copied to the clipboard. </td>
+  </tr>
+</table>
+<p>When copied to the clipboard, the clipboard data is stored in tab delimited format, which can be pasted into other programs for analysis. For example, if Copy Drilldown Table is used, the pasted output may look something like  Figure 1. You can then utilize the spreadsheet functions on the data to better understand it. </p>
+<p align="center"><img src="../../images/copy_drilldown_table.png" alt=" " width="725" height="342"></p>
+<p class="figure">Figure 1. Copy Drilldown Table data pasted into a spreadsheet for analysis</p>
+<h5>Related references</h5>
+<ul>
+  <li><a href="context_menu.htm">Context Menu</a></li>
+  <li><a href="../../Getting_Started/example_project.htm">Examining a Profiling Project</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/binary_load.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Binary Load</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Binary Load</h2>
+<p>Select the Binaries tab to display the Binary Load. The Binary Load graph and related table show information about binaries that were active during the selected time period. The load is visually separated according to the executed binary, independent of the thread or function that was executing. Figure 1 shows an example graph with the Binaries tab selected.</p>
+<p align="center"><img src="images/binary_mode_graph.png" width="705" height="659"></p>
+<p class="figure">Figure 1. Example Binary Load Graph</p>
+<p>You can check or uncheck items to be displayed in the graph or right-click to display a context menu of various options. The color next to a checkbox corresponds to that item’s color in the graph.</p>
+<p>Description of table columns:</p>
+<ul>
+  <li>The % Load column indicates what percentage of the CPU load was spent in each binary during the selected time interval.</li>
+<li>The Binary column identifies the binary files by name. </li>
+  <li>The Path column shows the PC folder containing the binary.</li>
+<li>The Samples column indicates how many samples were taken during the selected time interval (in this case between XXX and YYY seconds).</li>
+</ul>
+<p>Columns may be reordered, resized, and sorted by clicking or dragging column headers.</p>
+<p>The final row of the information section contains summary information about all binaries below a threshold, if a threshold limit has been specified. The threshold row is not affected by sorting, it is always the last row.</p>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="main_view.htm">Analyzer View</a></li>
+  <li><a href="../profiler/GPP_trace.htm">Address/Thread Trace</a></li>
+  <li><a href="thread_load.htm">Thread Load</a></li>
+  <li><a href="function_load.htm">Function Load</a></li>
+  <li><a href="function_calls.htm">Function Calls</a></li>
+<li><a href="threshold.htm">Threshold Limits for Traced Data</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/context_menu.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,227 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title></title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+    <style type="text/css">
+<!--
+.style1 {
+	font-family: Georgia, "Times New Roman", Times, serif;
+	font-weight: bold;
+}
+-->
+    </style>
+</head>
+
+<body>
+<h2>Context Menu Options </h2>
+<p>Right-clicking within the Analyzer graph and tables will display context popup menus that will vary slightly depending on where you initiated the popup menu. The following table lists and defines Analyzer context menu options.</p>
+<p class="note"><strong>Note </strong>Several menu options allow you to save information to a .csv file that can be opened in a text editor or system editor (such as Excel). Beware that the default filename to save information is <span class="style1">new_file.csv</span>. Specify a unique filename if you do not want the default file to be overwritten each time you save information. </p>
+<h5>Table 1. Analyzer context menu options</h5>
+<table width="90%" border="0" cellpadding="2" cellspacing="0" >
+  <tr>
+    <th width="25%" scope="col">Menu Option </th>
+    <th width="581" scope="col">Description</th>
+  </tr>
+  <tr>
+    <td><b>Binary -&gt; Function -&gt; Thread </b></td>
+    <td>Displays the Binary, Function, and Thread tables. The graph will display the Threads from which the selected binaries were executed. The functions within the binaries that were called are listed in the functions table. </td>
+  </tr>
+  <tr>
+    <td><b>Binary -&gt; Thread </b></td>
+    <td>Displays the Binary and Thread tables. The graph will display the threads where the selected binaries were executed.</td>
+  </tr>
+  <tr>
+    <td><b>Binary -&gt; Thread -&gt; Function </b></td>
+    <td>Displays the Binary, Thread, and Function tables. The graph will display the functions that were called in the selected binaries. The threads table lists the threads where the selected binaries were executed.</td>
+  </tr>
+  <tr>
+    <td><b>Binary -&gt;Function </b></td>
+    <td>Displays the Binary and Function tables. The graph will display the functions that were called from within the selected binaries. </td>
+  </tr>
+  <tr>
+    <td><b>Binary Only </b></td>
+    <td>Displays the Binary table and all selected binaries in the graph view. </td>
+  </tr>
+  <tr>
+    <td><span class="style1">Change Event Information...</span> </td>
+    <td>Right-click on a button event marker in the Thread Load, Binary Load, or Function Load graph and select this menu option to display a dialog to <a href="../../tasks/analyser/btn_press_change.htm">change related event information</a>.</td>
+  </tr>
+  <tr>
+    <td><b>Change Threshold Limits... </b></td>
+    <td>Displays the <a href="threshold.htm">Set Thread, Binary, or Function Thresholds</a> dialog box.</td>
+  </tr>
+  <tr>
+    <td><b>Check All Rows </b></td>
+    <td>All rows will be checked and represented on the graph.</td>
+  </tr>
+  <tr>
+    <td><b>Check Highlighted Rows </b></td>
+    <td>This option will place a check mark in all highlighted rows. You can use the shift key and mouse button to select and highlight a continuous sequence  of rows. Use the control key to select and highlight random rows. Checked rows will be visible on the graph.</td>
+  </tr>
+  <tr>
+    <td><b>Copy</b></td>
+    <td>Copies the contents of the selected data from the table to the clipboard.  </td>
+  </tr>
+  <tr>
+    <td><b>Copy Drilldown Tables</b></td>
+    <td>Copies the contents of the entire drilldown table to the clipboard including column titles for easy identification when pasted into a spreadsheet for analysis. </td>
+  </tr>
+  <tr>
+    <td><b>Copy Table</b></td>
+    <td>Copies the contents of the entire table in the current pane to the clipboard including column titles for easy identification when pasted into a spreadsheet for analysis. The table contents do not have to be selected for the table copy to occur.</td>
+  </tr>
+  <tr>
+    <td><span class="style1">Dynamically Rescale Based on Selected Threads </span></td>
+    <td>Right-click in Memory Usage graph and select this option to rescale the graph based on selected threads. </td>
+  </tr>
+  <tr>
+    <td><span class="style1">Function Only </span></td>
+    <td>Displays Functions only. </td>
+  </tr>
+  <tr>
+    <td class="style1">Function -&gt; Thread </td>
+    <td>Displays Functions and related Threads. The graph will display threads containing the function calls. </td>
+  </tr>
+  <tr>
+    <td class="style1">Function -&gt; Thread -&gt; Binary </td>
+    <td>Displays Functions and related Threads and Binaries containing the functions called.</td>
+  </tr>
+  <tr>
+    <td><span class="style1">Memory Usage Statistics </span></td>
+    <td>Right-click in Memory Usage graph and select this menu option to open a Memory Usage Statistics dialog box that reports memory use for the selected time interval.</td>
+  </tr>
+  <tr>
+    <td class="style1">Open Source for Function </td>
+    <td>Opens the source code file containing the selected function in the editor window.</td>
+  </tr>
+  <tr>
+    <td><span class="style1">Power Usage Settings...</span></td>
+    <td>Right-click in the Power Usage graph and select this menu option to display a dialog box that reports the voltage and battery capacity. The values can be modifed as mentioned in <a href="wnd_power_graph_settings.htm">Power Usage Settings</a>.</td>
+  </tr>
+  <tr>
+    <td><span class="style1">Power Usage Statistics </span></td>
+    <td>Right-click in the Power Usage graph and select this option to display a dialog that reports detailed power information for the selected time interval.</td>
+  </tr>
+  <tr>
+    <td><b>Recolor Highlighted Binaries...</b></td>
+    <td>Displays a color swatch for you to choose a different color for a highlighted row. If multiple rows are selected, then multiple color swatch windows will appear. Change or accept current color for each row selected. Selected rows appear grey.</td>
+  </tr>
+  <tr>
+    <td><b>Recolor Highlighted Functions...</b></td>
+    <td>Displays a color swatch for you to choose a different color for a highlighted row. If multiple rows are selected, then multiple color swatch windows will appear. Change or accept current color for each row selected. Selected rows appear grey.</td>
+  </tr>
+  <tr>
+    <td><b>Recolor Highlighted Threads...</b></td>
+    <td>Displays a color swatch for you to choose a different color for a highlighted row. If multiple rows are selected, then multiple color swatch windows will appear. Change or accept current color for each row selected. Selected rows appear grey.</td>
+  </tr>
+  <tr>
+    <td class="style1">Save All Call Samples for Interval... </td>
+    <td>Right-click in one of the Function Call Analysis tables (when Function Calls tab is selected) and choose this option to save all function calls to a .csv file for the selected time interval. Information provided includes the time, caller address, caller function, caller binary, callee address, callee function, and callee binary.</td>
+  </tr>
+  <tr>
+    <td class="style1">Save All Event Samples for Interval... </td>
+    <td>Right-click on a button event marker in the Thread Load, Binary Load, or Function Load graph and choose this option to save all button events for the selected time interval. </td>
+  </tr>
+  <tr>
+    <td><span class="style1">Save All Power Samples for Interval... </span></td>
+    <td>Right-click in the Power Usage graph and select this option to save all collected power samples for the selected time interval.</td>
+  </tr>
+  <tr>
+    <td class="style1">Save Data for Selected Function... </td>
+    <td>Select a function in the Select One Function table (when Function Calls tab is selected) and right-click to choose this option. Detailed information is saved to a .csv file for the selected function. </td>
+  </tr>
+  <tr>
+    <td><b>Save Drilldown Tables...</b></td>
+    <td>Saves the contents of the entire drilldown table (e.g. Thread -&gt; Binary -&gt; Function) to a specified file including column titles for easy identification when opened in a spreadsheet for analysis.</td>
+  </tr>
+  <tr>
+    <td><span class="style1">Save Priority Samples for Checked Threads...</span></td>
+    <td>Saves the priority setting for Threads that are checked in the Thread table. The first entry in the file shows the last value recorded before entering the selected time interval. Subsequent entries show a change in the priority during the interval. Priority settings are detected when a change is made; thus they are not sampled every millisecond.</td>
+  </tr>
+  <tr>
+    <td><span class="style1">Save Samples for Checked Binaries... </span></td>
+    <td>Right-click in the Binary table (when Binaries tab is selected) and choose this option to save samples for binaries that are checked.</td>
+  </tr>
+  <tr>
+    <td><span class="style1">Save Samples for Checked Threads... </span></td>
+    <td>When Threads tab is selected, save samples for Threads that are checked in the Thread table to a .csv file.</td>
+  </tr>
+  <tr>
+    <td><span class="style1">Save Memory Samples for Checked Table Entries...</span> </td>
+    <td>This option is enabled when a time interval is selected. Save memory samples that are checked in the Memory Usage table to a .csv file. The first entry in the file shows the last value recorded before entering the selected time interval. Subsequent entries show changes made during the interval. Memory samples are detected when a change is made; thus they are not sampled every millisecond.</td>
+  </tr>
+  <tr>
+    <td><b>Save Table...</b></td>
+    <td>Saves the contents of the entire table in the current pane to a specified file including column titles for easy identification when opened in a spreadsheet for analysis. The table contents do not have to be selected for the table to be saved.</td>
+  </tr>
+  <tr>
+    <td><b>Select All</b></td>
+    <td>Selects the entire table in the current pane.</td>
+  </tr>
+  <tr>
+    <td><b>Show Entire Graph </b></td>
+    <td>Displays all profiled data in graph.</td>
+  </tr>
+  <tr>
+    <td><b>Show highlighted function's call info </b></td>
+    <td>This context menu option appears in the top and bottom tables of the Function Calls table - <strong>Functions calling the selected function</strong> and <strong>Functions called by the selected function</strong>. Select a function in one of these two tables, right-click and select this option to move the selected function into middle table labeled <strong>Select One Function</strong>. Functions calling and called by the selected function will be displayed in top and bottom tables.</td>
+  </tr>
+  <tr>
+    <td class="style1">Show Selected Interval Average Power Line </td>
+    <td>This option appears when you right-click in the Power Usage graph. Check this option to display the average power for the selected time interval.</td>
+  </tr>
+  <tr>
+    <td><b>Sort by Binary Path, then Binary Name </b></td>
+    <td>In the Binaries and Functions table views, this option will alphabetically sort the path of binaries, then alphabetically sort the binary files by name. Binary path and binary file names are listed in the Binary and Path columns (Binaries table), and In Binary and Path of Binary columns (Functions table). </td>
+  </tr>
+  <tr>
+    <td><strong>Switch Key Press Profile</strong> </td>
+    <td>Opens a dialog that allows you to change the<a href="../../tasks/analyser/key_profile_switch.htm"> key map profile</a> associated with the current NPI file.</td>
+  </tr>
+  <tr>
+    <td><b>Thread -&gt; Binary</b></td>
+    <td>Displays the Thread and Binary tables. The graph will display the binaries that have executed in the selected Thread(s); in relation to the selected time interval. </td>
+  </tr>
+  <tr>
+    <td><b>Thread -&gt; Binary -&gt; Function </b></td>
+    <td>Displays the Thread, Binary, and Function tables. The graph will display the functions that have been called in the selected binaries that exist in the selected threads. </td>
+  </tr>
+  <tr>
+    <td><b>Thread -&gt; Function</b></td>
+    <td>Displays the Thread and Function tables. The graph will display the functions that have been called in the selected threads; in relation to the selected time interval. </td>
+  </tr>
+  <tr>
+    <td><b>Thread -&gt; Function -&gt; Binary </b></td>
+    <td>Displays the Thread, Function, and Binary tables. The graph will display the binaries executed in the selected threads. The functions within the binaries that were called are listed in the functions table.</td>
+  </tr>
+  <tr>
+    <td><b>Thread Only </b></td>
+    <td>Displays the Thread table and all selected threads in the graph view.</td>
+  </tr>
+  <tr>
+    <td><b>Uncheck All Rows </b></td>
+    <td>All rows will be unchecked and all related items will be removed from the graph. </td>
+  </tr>
+  <tr>
+    <td><b>Uncheck Highlighted Rows </b></td>
+    <td>Unchecks highlighted rows and removes the  represented item(s) from the graph. </td>
+  </tr>
+  <tr>
+    <td><b>Zoom In </b></td>
+    <td>Zooms in on the graph view to display more detail. </td>
+  </tr>
+  <tr>
+    <td><b>Zoom Out </b></td>
+    <td>In the graph view, zooms out to display less detail of the selected time interval. </td>
+  </tr>
+  <tr>
+    <td><b>Zoom to Selected Time Interval </b></td>
+    <td>Locates the graph's selected time interval and displays it in center of graph. </td>
+  </tr>
+</table>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/function_calls.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Function Calls</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Function Calls</h2>
+<p>If the profiler data file contained function call information, select the Function Calls tab to show information about the function call relationships during the selected time period.  Figure 1 shows an example set of tables that provide information about function calls.</p>
+<p align="center"><img src="images/function_call_info.png" width="764" height="609"></p>
+<p class="figure">Figure 1. Function Call Information</p>
+<p>Only one function can be selected at a time. For the selected function, you can see the functions that have been found calling it and the functions that it has called. Additional columns provide more information, such as the percentage of each functions activity based on 100 percent of all calls to and from the selected function, Function's starting address (in hex), binary where function exists, and the path of the binary.</p>
+<p>Description of table columns:<br>
+  (for all tables)</p>
+<ul>
+  <li>The <strong>Function Start</strong> column displays the hexadecimal start address of each function.</li>
+<li>The <strong>In Binary</strong> column tells(s) the binary containing each function.</li>
+<li>The <strong>Path of Binary</strong> column shows the PC folder containing each function’s binary.</li>
+<li>The<strong> Is Caller %</strong> column shows the percentage of time that this function was the caller of the function that was executing.</li>
+<li>The <strong>Is Called %</strong> column shows the percentage of time in the selected time period that this function was executing.</li>
+</ul>
+<p>(in the <strong>Select One Function</strong> table)</p>
+<ul>
+  <li>The <strong>Called Samples</strong> column shows the number of samples in which this function was executing.</li>
+<li>The <strong>Caller Samples</strong> column displays the number of samples in which this function was the caller of the function that was executing.</li>
+</ul>
+<p>The selected function may have been called from one or more functions. In the <strong>Functions calling the selected function</strong> table, the <strong>% of Calls</strong> column shows what percentage of the time the selected function was called by each function in the table. For each function in this table, the <strong>Is Caller %</strong> column indicates the percentage of samples that the function was the caller of the executing function.</p>
+<p>The selected function may have called one or more functions. In the <strong>Functions called by the selected function</strong> table, the <strong>% of Calls</strong> column shows what percent of the time the selected function called each function in the table. For each function in this table, the <strong>Is Called %</strong> column indicates in what percentage of samples the function was executing.</p>
+<p class="note"><strong>NOTE</strong>
+On the target device, the link register usually contains the return address of the caller function.
+However, a called function may temporarily use the link register to hold a constant or variable.
+Performance Investigator uses link register values in the profiler data file to determine the names
+of caller functions.
+When PI cannot determine the name of a caller function, it may be because the link register held a constant
+or variable. For example, if the link register held a constant 0x0, PI would display the caller's name as &quot;Function at 0x0 not found&quot;. </p>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="binary_load.htm">Binary Load</a></li>
+  <li><a href="function_load.htm">Function Load</a></li>
+  <li><a href="thread_load.htm">Thread Load</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/function_load.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Function Load</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Function Load</h2>
+<p>Select the Functions tab to display the Function Load. The function load graph and related table show information about functions that were active during the selected time period. In Function mode, the graph and information views show the CPU load separated at a function level, independent of the thread that has been executing it. Figure 1 shows an example of the Function tab selected and Function load displayed.</p>
+<p align="center"><img src="images/function_mode_graph.png" width="708" height="605"> </p>
+<p class="figure">Figure 1. Function Load Graph</p>
+You can check or uncheck items to be displayed in the graph or right-click to display a context menu of various options. The color next to a checkbox corresponds to that item’s color in the graph.
+<p>Description of table columns:</p>
+<ul>
+  <li>The <b>% Load</b> column indicates what percentage of the CPU load was spent in each function during the selected time interval.</li>
+<li>The <b>Function Start</b> column displays the hexadecimal start address of each function.</li>
+<li>The <b>In Binary</b> column indicates the binary containing each function.</li>
+<li>The <b>Path of Binary</b> column lists the PC folder containing each function’s binary.</li>
+<li>The <b>Samples</b> column indicates how many samples were taken during the selected time interval (in this case between 10 and 12.8 seconds).</li>
+</ul>
+<p>Columns may be reordered, resized, and sorted by clicking or dragging column headers.</p>
+<p>The final row of the information section contains summary information about all functions below a threshold, if a threshold limit is specified. The threshold row is not affected by sorting, it is always the last row.</p>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="main_view.htm">Analyzer View</a></li>
+  <li><a href="../profiler/GPP_trace.htm">Address/Thread Trace</a></li>
+  <li><a href="binary_load.htm">Binary Load</a></li>
+  <li><a href="thread_load.htm">Thread Load</a></li>
+  <li><a href="function_calls.htm">Function Calls</a></li>
+<li><a href="threshold.htm">Threshold Limits for Traced Data</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/analyzer_mainview.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/analz_graphitem.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/analz_loads_tabs.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/analz_plugins.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/analz_startend.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/binary_mode_graph.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/chng_threshold.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/chng_threshold1.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/function_call_info.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/function_mode_graph.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/icon_select_time_interval.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/icon_show_entire_graph.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/icon_zoom_in.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/icon_zoom_out.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/icon_zoom_to_selected_int.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/investigator_menu.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/memory_usage_stats.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/menu_memory_usage.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/menu_power_usage.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/savetable1.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/savetable2.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/savetable3.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/thread_mode_graph.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/view_memory_usage.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/view_power_usage.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/wnd_memory_usage_stats.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/wnd_power_usage_settings.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/wnd_power_usage_stats.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/images/wnd_select_time_interval.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/import_rom_build_files.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+  <meta http-equiv="Content-Type"
+ content="text/html; charset=iso-8859-1">
+  <title>Select Build Files for ROM</title>
+  <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<h2>Select Build Files for ROM </h2>
+<p>Use the <strong>Select build files from ROM</strong> dialog to select the build files that correspond to the ROM on the device. Start by selecting the SDK, then the ROM OBY file as well as the ROM symbol file.  </p>
+<p align="center"><img src="../../images/wnd_import_rom_build_files.png" width="629" height="705"></p>
+<p class="figure">Figure 1. Select build files from ROM dialog </p>
+<h5>Table 1. <strong>Select build files from ROM</strong> &mdash; options </h5>
+<table width="778"
+border="0" cellpadding="2" cellspacing="0">
+  <tr valign="top">
+    <th width="266" class="Cell">Menu Item </th>
+    <th width="502" class="Cell">Description</th>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><strong>Installed SDK </strong></td>
+    <td class="Cell">Shows a list of the currently installed SDKs. Use <strong>Add SDK..</strong>. to open the <strong>Add New SDK</strong> dialog where you can define the SDK to use. Use <strong>Remove SDK</strong> to  remove the selected SDK from the <span class="code">devices.xml</span> file and the <strong>Installed SDK</strong> list. The SDK is not removed from from the drive. </td>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><p><strong>ROM OBY File </strong></p></td>
+    <td class="Cell"><p>Type a ROM OBY file name or click ROM OBY File...  to locate a ROM OBY file.</p></td>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><strong>ROM Symbol File </strong></td>
+    <td class="Cell">Type a ROM symbol file name or click ROM Symbol File... to locate a ROM symbol file. </td>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><strong>ROFS OBY/Symbol File Pairs </strong></td>
+    <td class="Cell"><p>Click <strong>Add...</strong> to add a ROFS OBY/Symbol File pair. Click <strong>Remove...</strong> to remove the selected ROFS OBY/Symbol File pair from the list. </p>    </td>
+  </tr>
+</table>
+<p align="left"><strong>Related references</strong></p>
+<ul>
+  <li><a href="main_view.htm" align="left">Analyzer
+View</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/investigator_menu.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Investigator Menu</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Investigator Menu </h2>
+<p>In the main menu, select <b>Investigator</b> to display menu options available for the Analyzer; as shown in Figure 1.</p>
+<p align="center"><img src="images/investigator_menu.png" width="297" height="86"></p>
+<p class="figure">Figure 1 - Investigator menu options</p>
+<h5 align="left">Table 1. Investigator menu items </h5>
+<table width="90%" border="0" cellpadding="2" cellspacing="0" >
+  <tr>
+    <th width="224" scope="col">Menu Options</th>
+    <th width="584" scope="col">Description</th>
+  </tr>
+  <tr>
+    <td><b>Show Individual Samples </b></td>
+    <td>Displays selected items as a vertical line on the graph. Items are displayed at the time interval at which they occurred. </td>
+  </tr>
+  <tr>
+    <td><b>Fill in Graph Loads </b></td>
+    <td>Items in graph will be filled in with solid color representing each item. If Show Individual Samples is selected, this option has no effect. </td>
+  </tr>
+  <tr>
+    <td><b>Change Threshold Limits...</b></td>
+    <td>Opens the <a href="threshold.htm">Set Thread, Binary, or Function Thresholds</a> dialog box. </td>
+  </tr>
+</table>
+<h5>Related references</h5>
+<ul>
+  <li><a href="menu_memory_graph.htm">Memory Graph menu </a></li>
+<li><a href="menu_power_graph.htm">Power Graph menu</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/main_view.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Analyzer View</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Analyzer View</h2>
+<p>The main analysis view is visible after trace data taken by the profiler has been imported into Carbide.c++ and opened with the Analyzer. The thread load data in the main analysis view is built from the address/thread trace. Other trace data is also shown in the main analysis view, such as dynamic binary support trace and function call trace. Figure 1 is an example view of imported profiler data that has been opened with the analyzer, including memory and power usage information, with a time interval of 9.1 to 13 seconds selected.</p>
+<p align="center"><img src="images/analyzer_mainview.png" width="705" height="659"> </p>
+<p align="center" class="figure">Figure 1. Analyzer main view showing Thread, Memory, and Power graphs</p>
+<p>The address/thread trace graph is the most generic and perhaps most informative visual of the sampled data.
+  The different colors represent different items. You can select Thread load, Binary load, or Function load as shown in Figure 2. Time is represented on the horizontal axis of the graph and share of CPU use is represented on the vertical axis.</p>
+<p align="center"><img src="images/analz_loads_tabs.png" width="423" height="84"></p>
+<p align="center" class="figure">Figure 2. Selecting Threads, Binaries, Functions, or Function Calls</p>
+<p>Each of the lines in the thread list represents a single thread. The color codes in the thread list correspond to the colors in the thread load graphs. Therefore, each color in the thread load graph represents the load of its corresponding thread.</p>
+<p>You can select a portion of the graph by clicking on the trace graph. The Information view beneath the graph displays information about the currently selected part of the graph. For example, thread load statistics are shown in the information view if the thread load graph is selected.</p>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="GUI_tour.htm">Analyzer GUI Controls </a></li>
+<li><a href="thread_load.htm">Thread Load</a></li>
+<li><a href="binary_load.htm">Binary Load</a></li>
+<li><a href="function_load.htm">Function Load</a></li>
+<li><a href="function_calls.htm">Function Calls</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/menu_memory_graph.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Memory Graph Menu</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Memory Graph Menu </h2>
+<p>The <strong>Memory Graph</strong> menu is available whenever a <span class="code">.npi</span> or <span class="code">.bap</span> data file is opened that contains memory usage trace data. Use it to modify how the graph is calculated, view memory statistics, and control how the memory information is displayed. </p>
+<p align="center"><img src="images/menu_memory_usage.png" width="412" height="151"></p>
+<p class="figure">Figure 1. Memory Graph menu items </p>
+<h5>Table 1. Memory Graph &mdash;menu items
+</h5>
+<table width="778"
+border="0" cellpadding="2" cellspacing="0">
+  <tr valign="top">
+    <th width="236" class="Cell">Menu Item </th>
+    <th width="532" class="Cell">Description</th>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><b>Memory Usage Statistics </b></td>
+    <td class="Cell">Open the <a href="wnd_memory_usage_statistics.htm">Memory Usage Statistics</a> dialog. </td>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><p><b>Show Chunk Usage </b></p></td>
+    <td class="Cell"><p>Select<b> Show Chunk Usage</b> to show  chunks allocated to threads. Heap threads are not included. The graph refreshes and scales the vertical axis to cover the maximum non-heap chunk usage of the entire graph or the current selected threads. </p></td>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><b>Show Stack/Heap Usage </b></td>
+    <td class="Cell">Select<b> Show Stack/Heap Usage</b> to show thread heap chunks.</td>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><b>Show Current and Stack/Heap Usage </b></td>
+    <td class="Cell">This is the default setting showing both the current and stack/heap usage portions of the graph.</td>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><b>Dynamically Rescale to Selected Threads </b></td>
+    <td class="Cell">Enable to rescale the vertical axis of the graph to
+
+
+the maximum memory usage in the entire graph by the threads currently checked in the CPU load table. When disabled, rescale the vertical axis to the maximum memory usage of all threads in the entire graph. The default settings is disabled. </td>
+  </tr>
+</table>
+<p><strong>Related references </strong></p>
+<ul>
+  <li><a href="main_view.htm">Analyzer View</a></li>
+<li><a href="view_memory_usage.htm">Memory Usage View</a></li>
+<li><a href="wnd_memory_usage_statistics.htm">Memory Usage Statistics</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/menu_power_graph.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Power Graph Menu</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Power Graph Menu </h2>
+<p>The <strong>Power Graph</strong> menu is available whenever a <span class="code">.npi</span> or <span class="code">.bap</span> data file is opened that contains power usage trace data. Use it to modify how the graph is calculated, view power statistics, and control how the power information is displayed. </p>
+<p align="center"><img src="images/menu_power_usage.png" width="378" height="124"></p>
+<p class="figure">Figure 1. Power Graph menu items </p>
+<h5>Table 1. Power Graph &mdash;menu items
+</h5>
+<table width="778"
+border="0" cellpadding="2" cellspacing="0">
+  <tr valign="top">
+    <th width="266" class="Cell">Menu Item </th>
+    <th width="502" class="Cell">Description</th>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><p><strong>Power Usage Graph Settings  </strong></p></td>
+    <td class="Cell"><p>Select to open the <a href="wnd_power_graph_settings.htm">Power Usage Graph Settings</a> dialog and modify the voltage and battery capacity used by the target device.</p></td>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><strong>Power Usage Statistics </strong></td>
+    <td class="Cell">Select to display the <a href="wnd_power_usage_statistics.htm">Power Usage Statistics</a> dialog. </td>
+  </tr>
+  <tr valign="top">
+    <td class="Cell"><strong>Show Selected Interval Average Power Line </strong></td>
+    <td class="Cell">Select the <strong>Selected Interval Average Power Line</strong> option to show a horizontal line on the graph corresponding to the average power usage during the selected time interval.</td>
+  </tr>
+</table>
+<p><strong>Related references </strong></p>
+<ul>
+  <li><a href="main_view.htm">Analyzer View</a></li>
+<li><a href="view_power_usage.htm">Power Usage View</a> </li>
+<li><a href="wnd_power_graph_settings.htm">Power Usage Graph Settings</a></li>
+<li><span class="Cell"><a href="wnd_power_usage_statistics.htm">Power Usage Statistics</a></span></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/save_table.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<meta name="keywords" content="Saving Selected Samples">
+	<title>Save table</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Save Table</h2>
+<p>The Save Table dialog allows you to save the contents of the entire table in the current pane to a specified (.csv) file. Column titles will be included for easy identification when opened in an spreadsheet for analysis. The table contents do not have to be selected for the table to be saved. Figure 1 shows the Save Table dialog. You can select an existing project and folder in which to add the .csv file or select the <strong>Create Empty Project...</strong> button to create a new empty project to contain the new .csv file.</p>
+<p align="center"><img src="images/savetable1.png" alt="Save Table dialog" width="438" height="415"></p>
+<p align="center" class="figure">Figure 1 - Saving Table Data Dialog</p>
+<p>If you select the <strong>Create Empty Project...</strong> button, the New Project dialog will appear as shown in Figure 2. Enter a project name and specify a workspace location to store the project. Click Next to specify project dependencies or click Finish to create the new project. If you select Finish at this point, then you can select the new project (in the list of projects) as the project to contain the .csv file.</p>
+<p align="center"><img src="images/savetable2.png" alt="Create empty project" width="438" height="415"></p>
+<p align="center" class="figure">Figure 2 - New Project Dialog</p>
+<p>If you select Next the Project References page will appear. In Project <SPAN name="resultofMatch"><SPAN name="resultofMatch">Referenc</SPAN>es</SPAN>, you can set <SPAN name="resultofMatch">project</SPAN> dependencies for   the new <SPAN name="resultofMatch">project</SPAN>. In the   list of other <SPAN name="resultofMatch">project</SPAN>s in   the Workspace, you can select one or more <SPAN name="resultofMatch">project</SPAN>s on which you want the new <SPAN name="resultofMatch">project</SPAN> to depend upon. Click Finish to return to the main Save Table dialog and select the new project as the project to contain the .csv file. Click Finish in the main dialog to create and open the new file in your default spreadsheet program.</p>
+<p align="center"><img src="images/savetable3.png" alt="Reference project" width="438" height="415"></p>
+<p align="center" class="figure">Figure 3 - Select Referenced Projects (if applicable)</p>
+<h4>Related Information</h4>
+<h5>Save Drilldown Tables</h5>
+<p>The Save Drilldown Tables command is similar to the Save Table command and related dialogs. The difference being that the .csv file will include Thread, Binary, and/or Function information; as displayed in the analyzer. For example, if Thread -&gt; Binary -&gt; Function is selected by the user and displayed in the analyzer, then Thread, Binary, and Function related information will be saved in the .csv file.</p>
+<h5>Save Samples for Checked Threads</h5>
+<p>When the Threads tab is selected, this command saves samples of checked threads. A dialog similar to the Save Table dialog will appear for you to save threads checked  in the Thread table to a comma separated .csv file. This file can be opened in a spreadsheet application.</p>
+<h5>Save Samples for Checked Binaries</h5>
+<p>When the Binaries tab is selected, this command saves samples of checked binaries. A dialog similar to the Save Table dialog will appear for you to save binaries checked in the Binaries table to a comma separated .csv file. This file can be opened in a spreadsheet application.</p>
+<h5>Save Samples for Checked Functions</h5>
+<p>When the Functions tab is selected, this command saves samples of checked functions. A dialog similar to the Save Table dialog will appear for you to save functions checked in the Functions table to a comma separated .csv file. This file can be opened in a spreadsheet application.</p>
+<h5>Save All Call Samples for Interval</h5>
+<p>When the Function Calls tab is selected, this command saves all function calls for the selected time interval. A dialog similar to the Save Table dialog will appear for you to save all function calls made during the selected time interval to a comma separated .csv file. This file can be opened in a spreadsheet application.</p>
+<p></p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/thread_load.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Thread Load</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Thread Load</h2>
+<p>Select the Threads tab to display the Thread Load. The Thread Load graph and related table show information about threads that were active during the selected time period. The graph and table show the CPU load separated according to the executed thread, independent of the binary or function in which execution took place. Figure 1 shows an example graph with the Threads tab selected.</p>
+<p align="center"><img src="images/thread_mode_graph.png" width="705" height="659"> </p>
+<p align="center" class="figure">Figure 1. Thread Load Graph</p>
+<p>You can check or uncheck items to be displayed in the graph or right-click to display a context menu of various options. The color next to a checkbox corresponds to that item’s color in the graph.</p>
+<p>Description of table columns:</p>
+<ul>
+  <li>The <b>% Load</b> column indicates what percentage of the CPU load was spent in each thread during the selected time interval.</li>
+<li>The <b>Thread</b> column identifies the thread by name and executable which is composed of:
+    <ul>
+      <li>Executable or process  name &#8212; name of the binary as identified by the OS</li>
+      <li>Process ID (PID) &#8212;  the process ID that uniquely identifies the process to the OS </li>
+      <li>Thread name  &#8212;the name of the thread</li>
+      <li>Thread ID (TID) &#8212;  the thread ID that uniquely identifies the thread </li>
+    </ul>
+</li>
+  <li>The <b>Samples</b> column indicates how many samples were taken during the selected time interval (in this case between 8.16 and 8.5 seconds).</li>
+<li>If the profiler data file contained thread priority information, then a <b>Priority List</b> column will be shown.  The column lists the time at which a thread was assigned that priority. Sometimes you will see more than one priority listed for each thread.</li>
+</ul>
+<p>Columns may be reordered, resized, and sorted by clicking or dragging column headers.</p>
+<p> The final row of the information section contains summary information about all threads below a threshold, if a threshold limit has been specified. The threshold row is not affected by sorting, it is always the last row.</p>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="main_view.htm">Analyzer View</a></li>
+<li><a href="../profiler/GPP_trace.htm">Address/Thread Trace</a></li>
+  <li><a href="binary_load.htm">Binary Load</a></li>
+  <li><a href="function_load.htm">Function Load</a></li>
+<li><a href="function_calls.htm">Function Calls</a></li>
+<li><a href="threshold.htm">Threshold Limits for Traced Data</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/threshold.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Thresholds</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Threshold Limits for Traced Data</h2>
+<p>The Set Thread, Binary, or Function Thresholds dialog box allows you to group items that meet the specified threshold into one item that is listed as the last item in the Threads, Binaries, or Functions table, as shown in Figure 1. Basically, you are specifying items that are consuming a percentage of the CPU load and grouping them into a &quot;I don't care to view&quot; category. The threshold represents items you want to set aside;  meaning everything below the percent specified is grouped into one item.</p>
+<p>The titles included in the Thread column contain a wealth of data and are composed of:</p>
+<ul>
+  <li>Process name &#8212; name of the binary as identified by the OS</li>
+  <li>Process ID (PID) &#8212;  the process ID that uniquely identifies the process to the OS </li>
+  <li>Thread name  &#8212;the name of the thread</li>
+  <li>Thread ID (TID) &#8212;  the thread ID that uniquely identifies the thread </li>
+</ul>
+<p>You specify a percent of the total CPU load, which equates to a fraction of the total samples for each item specified; either threads, binaries, or functions. Total samples refers to all samples covering the entire time of the profile; not a selected time interval.</p>
+<p class="note"><strong>Note:</strong> Notice that the % Load and Samples columns indicate zero. This is because no time interval is selected on the graph for this particular example.</p>
+<p align="center"><img src="images/chng_threshold1.png" width="707" height="419"></p>
+<p align="center" class="figure">Figure 1. Grouped Items Matching Specified Threshold</p>
+<p>If you enter zero in the &quot;Average load &lt;&quot; fields, then all items are displayed on the graph. If you select a threshold of 100 percent, then all  items will be compacted as one item, which will most likely not be very useful for performance evaluation; but mentioned as reference to the action that is performed. If you enter a threshold of .10 percent (1/10th of a percent) in each Average load field, then all trace items that consume a tenth of the CPU load or less will be grouped into one item. The remaining items listed in the table represent items that consumed more than a tenth of the CPU load.</p>
+<p>For example, if you have a total of 15,000 samples for all threads and you want to set aside all threads that used a tenth of the CPU load or less (which equals to 15 samples in this case), then you would enter 0.10. Refer to Figure 2. As shown in Figure 1, this example found 30 threads that consumed less than a tenth of the CPU load and were sampled less than 269 times.</p>
+<p>If you now select a time interval on the graph, you will notice the Threads, Binaries, and Functions tables has updated to reflect the items that were sampled within that time interval and their percentage of CPU usage. You can also check or uncheck items you wish to display on the graph.</p>
+<p align="center"><img src="images/chng_threshold.png" width="578" height="221"></p>
+<p align="center" class="figure">Figure 2. Set Thresholds Dialog Box</p>
+<p><strong>Related Task</strong></p>
+<p><a href="../../tasks/analyser/set_thresholds.htm">Setting Thresholds For Threads, Binaries, and Functions</a></p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/view_memory_usage.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Memory Usage View</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Memory Usage View</h2>
+<p>Use  the <strong>Memory  Usage</strong> view to display thread&#8217;s chunk usage, stack/heap usage, or both, of the profiled software running on a device. The graph portion of the Memory Usage view shows the amount of memory used along the same time interval as the thread load. A list of each thread or process appears at the bottom of the view showing the chunks, stack/heap, and total memory for each thread.</p>
+<p>Data in the Memory Usage view is layered with the stack/heap data overlaying the chunk data. Stack/heap data is represented by the color blue, while chunk data is represented by gold. The display is different depending upon the view option selected in the context menu (section A in Figure 1):</p>
+<ul>
+  <li>Show Chunk Usage &#8212; gold box only</li>
+  <li>Show Stack/Heap Usage &#8212; blue box only </li>
+  <li>Show Chunk and Stack/Heap Usage (Figure 1) &#8212; show gold box (chunk data) and a blue line (stack/heap data) </li>
+</ul>
+<p>When both are selected for display and the amounts are also equal, only a blue box will appear in the view. If the amounts are not equal, the chunk data is shown as a gold box and the stack/heap data is shown as a blue line. </p>
+<p class="note"><b>NOTE</b> The Memory Usage view is synchronized with the Thread Load view along the horizontal axis. </p>
+<p align="center"><img src="images/view_memory_usage.png" width="705" height="652"></p>
+<p class="figure">Figure 1. Memory Usage graph and thread list </p>
+<p>Description of table columns (section B in Figure 1):</p>
+<ul>
+  <li>The <b>Thread/Process</b> column name contains a wealth of data and is composed of:<ul>
+    <li>Chunks appear as: <span class="code">&lt;process&gt;::&lt;chunk name&gt; [&lt;hex start address&gt;]</span> </li>
+      <li>Threads appear as: <span class="code">&lt;process&gt;::&lt;thread name&gt;_&lt;thread ID&gt; </span></li>
+      <li> If no name is returned by the OS, the entry may appear as undetermined, e.g. &quot;<span class="code">::_</span>&quot;. </li>
+      </ul>
+  </li>
+  <li>The <b>Chunks</b> column displays the  amount of memory used by each chunk.</li>
+  <li>The <b>Stack/Heap</b> column displays the  amount  of memory used by the thread in its stack/heap.</li>
+  <li>The <b>Memory Total</b> column displays the  sum of the Chunks and Stack/Heap columns. </li>
+</ul>
+<p>Columns may be reordered, resized, and sorted by clicking or dragging column headers.</p>
+<p><strong>Related references </strong></p>
+<ul>
+  <li><a href="main_view.htm">Analyzer View</a></li>
+<li><a href="menu_memory_graph.htm">Memory Usage Menu </a></li>
+<li><a href="wnd_memory_usage_statistics.htm">Memory Usage Statistics</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/view_power_usage.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Power Usage View</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Power Usage View</h2>
+<p>Use  the <strong>Power Usage</strong> view to display  the power consumption of the profiled software running on a device. </p>
+<p align="center"><img src="images/view_power_usage.png" width="705" height="652"></p>
+<p class="figure">Figure 1. Power Usage graph</p>
+<p>The Power Usage view (Figure 1) provides:</p>
+<ul>
+  <li>graph power usage over time.</li>
+<li>graph or hide a horizontal line of average power usage during the selected time interval</li>
+<li>display and change the voltage (v)</li>
+<li>display and change the battery capacity (mAh)</li>
+<li>display average power usage (mV) over the selected interval</li>
+<li>display average energy consumption (mWs) over the selected interval</li>
+</ul>
+<p>Left-click and drag the pointer across the graph to select a portion of the power consumption graph. As the pointer is dragged, the start and end lines appear on the graph. Once the mouse click is released, the time interval is updated to indicate the changes made. </p>
+<p><strong>Related references </strong></p>
+<ul>
+  <li><a href="main_view.htm">Analyzer View</a></li>
+<li><a href="menu_power_graph.htm">Power Graph Menu </a></li>
+	<li><a href="wnd_power_usage_statistics.htm">Power Usage Statistics</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/wnd_memory_usage_statistics.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Memory Usage Statistics</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Memory Usage Statistics</h2>
+<p>Use  the <strong>Memory Usage Statistics</strong> dialog to view the on-device and  memory usage. These values are displayed  for the selected time  interval as follows:</p>
+<ul><li>Interval  selected in the memory usage view</li>
+  <li>The Used, Free, and Total memory on the device</li>
+  <li>The total memory allocated to all chunks, stacks, heaps, and other code in RAM in the selected time interval </li>
+</ul>
+<p align="center"><img src="images/wnd_memory_usage_stats.png" width="270" height="269"></p>
+<p class="figure">Figure 1. Memory Usage Statistics dialog</p>
+<p>&nbsp;</p>
+<p><strong>Related references </strong></p>
+<ul>
+  <li><a href="main_view.htm">Analyzer View</a></li>
+<li><a href="menu_memory_graph.htm">Memory Graph Menu </a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/wnd_power_graph_settings.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Power Usage Settings</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Power Usage Settings</h2>
+<p>Use the <b>Power Usage Settings</b> dialog to to change the voltage and battery capacity. The Power Usage Settings dialog enables:</p>
+<ul>
+  <li>Setting the Voltage value using  an integer or floating point number that represents <a href="http://en.wikipedia.org/wiki/Volt">volts</a> (V) and rounded to the neareth 100th of a volt </li>
+<li>Setting the Battery capacity to an integer that represents battery capacity in <a href="http://en.wikipedia.org/wiki/Ampere">milliamperes</a> (mAh)</li>
+</ul>
+<p>The power usage graph is redrawn and any statistics displayed are updated as needed.</p>
+<p align="center"><img src="images/wnd_power_usage_settings.png" width="198" height="132"></p>
+<p class="figure">Figure 1. Power Usage Settings dialog</p>
+<p><strong>Related references </strong></p>
+<ul>
+  <li><a href="main_view.htm">Analyzer View</a></li>
+<li><a href="menu_power_graph.htm">Power Graph Menu </a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/analyzer/wnd_power_usage_statistics.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Power Usage Statistics</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Power Usage Statistics</h2>
+<p>Use the <strong>Power Usage Statistics</strong> dialog to view the average power, estimated power, estimated battery life, as well as maximum and minimum power requirements, and variance for the selected interval. These values are displayed as follows: </p>
+<ul>
+  <li>Interval  selected in the power usage view</li>
+  <li>Total battery current  in <a href="http://en.wikipedia.org/wiki/Milliamp">milliamp</a> (mAh) and <a href="http://en.wikipedia.org/wiki/Voltage">voltage</a> (V) </li>
+  <li>Estimated energy is displayed in <a href="http://en.wikipedia.org/wiki/Joule">millijoules</a> (mJ)</li>
+  <li>Estimated battery life in hours (h) and minutes (m) </li>
+  <li>Average power is displayed in <a href="http://en.wikipedia.org/wiki/Watt">milliwatts</a> (mW), to the nearest tenth</li>
+  <li>Minimum to maximum power are displayed in <a href="http://en.wikipedia.org/wiki/Watt">milliwatts</a> (mW), to the nearest tenth</li>
+  <li><a href="http://en.wikipedia.org/wiki/Variance">Variance</a> is displayed in milliwatts squared (mW*mW), to the nearest tenth</li>
+</ul>
+<p align="center"><img src="images/wnd_power_usage_stats.png" width="233" height="429"></p>
+<p class="figure">Figure 1. Power Usage Statistics dialog</p>
+<p><strong>Related references </strong></p>
+<ul>
+  <li><a href="main_view.htm">Analyzer View</a></li>
+<li><a href="menu_power_graph.htm">Power Graph Menu </a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/banked_registers.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Banked Registers</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Banked Registers </h3>
+<P LANG="en-GB" ALIGN=JUSTIFY>Current ARM processor architecture has a total of 37 registers. The registers are arranged into overlapping banks. Each of the banks represents a set of 16 general-purpose registers, a current program status register and an optional stored program status register (which is present only in the exception mode banks). There is one bank of registers for each of the processor modes. Some of the registers between the register banks refer to the same physical register, and some of the registers are private for each of the banks respectively. </P>
+<P LANG="en-GB" ALIGN=JUSTIFY>Purpose of the banks is to reduce the amount of data to be stored to the stack when the processor mode is changed. User mode registers can be accessed from the privileged modes through a specific form of the STM (store multiple) and LDM (load multiple) instructions. Information within the user mode registers are valuable in performance measurements when analyzing the operation of the user mode software from a privileged mode, such as during a periodic interrupt</P>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/compile_time.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Compile-Time Symbolic Information</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Compile-Time Symbolic Information</h3>
+<p>The deployment of programmed and compiled functionality within a final software image can be resolved from symbolic information that is produced at compile-time. In practice, symbolic information contains an address map of each of the data and code segments that have been produced within the compilation and combined when building a complete image in so-called rombuild stage (in Symbian toolchain). The address map connects the final addresses within a software image with names of functions, methods, dynamic link libraries, executables, device drivers, or other names that have been assigned by the programmer.</p>
+<P LANG="en-GB" ALIGN=JUSTIFY>In performance evaluation, it is essential to be able to discriminate points of execution according to their presence in different functions. With the ability to perform such discrimination, it is possible to identify the functions and methods in which the execution has been recorded to take place. Accordingly, it is possible to calculate statistical utilization percentages for individual functions or methods. On the other hand, symbolic information has other applications. In general, without sources of symbolic information, performance measurement information cannot be grounded to the actual software design known by the developer, making it difficult to interpret the results. Through understanding of the memory layout of the analyzed software image, it becomes possible to perform more complicated analysis such as resolution of function call chains.</P>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/cpu_timer.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>CPU Timer</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>CPU Timer</h3>
+<p> If available, free CPU timers can be
+			used to calculate time spent within activities whose performance
+			Related references is required. For example, in OMAP1510/ARM925T
+			architecture, there are three freely usable CPU timers that can
+			count with frequencies up to the CPU main clock frequency, therefore
+			accurately recording temporal activities.
+			The disadvantage in using CPU timers in performance measurements
+			is that in most cases the timers have already been employed
+			by other activities. Through investigation of those activities it
+is still possible to use the CPU timers in harmony with them, but with certain limitations.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/curr_pgm_status_reg.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Current Program Status Register Value</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Current Program Status Register Value</h3>
+<p> In ARM architecture, the current
+			program status register (CPSR) is an unbanked register, thus it
+			refers to the same physical register in all processor
+			modes. It contains condition code flags, interrupt disable bits,
+			the current processor mode, and other status and control
+			information. The state of the processor reflects changes in the
+			flags and values within the CPSR. CPSR cannot be changed while
+			in user mode, thus preventing the software from accessing privileged resources. However, CPSR values
+			can be investigated within user mode, making it possible to
+			distinguish the current processor mode at all times. Performance
+			measurements may require such investigation of the CPSR in order
+			to distinguish the modes and to select appropriate actions
+			according to the mode. Without such precautions, exceptions or
+fault situations might take place.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/delayed_fn_call.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Delayed Function Call</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Delayed Function Call</h3>
+<P LANG="en-GB" ALIGN=JUSTIFY>A delayed function call (DFC) is a feature within the Symbian interrupt architecture. DFCs are used to perform interrupt-related activities that are too time-consuming to be processed in the interrupt service routine (ISR). Symbian kernel keeps a list of all DFCs queued to be processed. An ISR can add a DFC to the queue at any time, but the actual processing of the DFCs takes place only after all the ISRs have been processed first, but before the control is taken back to the scheduled threads. In addition to the exit from the interrupt handling, the DFC queue is also processed in the context of exit from a kernel executive call or a kernel server call.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>Performance measurements can utilize DFCs in activities that require processing that cannot be performed within the interrupts. Such processing could be, for example, exporting buffered data from privileged buffers to user-mode software. In addition, performance measurements should take into account the time spent within the DFCs, since the activities that take place in them do not belong to the normal processing of the scheduled threads.</P>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/dynamic_bin_res.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Dynamic Binary Resolution</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Dynamic Binary Resolution</h3>
+<p>In some products, location of binaries can change at run-time. This is especially true if the product allows software modules to be uploaded through any medium of information transfer, which is in practice a common use case nowadays. Problem with dynamic binaries in performance tracking is that the actual binary that has been under execution at any particular time cannot be resolved by examining only the PC value. There are at least two alternatives to fight the problem.</p>
+<OL>
+  <LI>
+    <P LANG="en-GB" ALIGN=JUSTIFY>Location of binaries have to be stored at run-time so that each code address can then be bound to its respective binary at each particular time, or</P>
+  <LI>
+    <P LANG="en-GB" ALIGN=JUSTIFY>The actual binary code is sampled during execution so that small pieces of executable binaries can be known to have resided at a certain address at a certain time. After sampling the execution, it is then possible to solve the puzzle of many small pieces of code/address/time elements during the analysis phase. This approach requires quite complicated processing.</P>
+</OL>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/file_sys_storing.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>File System Storing</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>File System Storing</h3>
+<p>Storing performance related data has to suit the performance measurement activity. If there is not much data, it can be exported from the device right away by suitable means, such as through the serial port. When the amount of data is larger, it can also be exported to a file within the file system. In that case it is practical to store the data at first to a small memory buffer. Then the buffer can be written to the file in a separate activity that does not disturb the measured mechanisms. For example if the data is being collected within an interrupt or in a kernel hook, the file system related activities should take place within the user code.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/int_stack.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Interrupt Stack</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Interrupt Stack</h3>
+<p>When the ARM processor state is switched to the IRQ (or FIQ) mode, the processor registers that are in use are also changed to banked registers dedicated to that mode. Each of the processor modes has specific banked registers in the ARM architecture, facilitating rapid switching between the modes. The stack pointer register (usually register R13) has a banked register in each of the modes. The pointer within the R13 points to the Interrupt Stack, which becomes the active stack immediately after execution is resumed within the interrupt processing. The interrupt stack holds the return value to the point of execution immediately before the interrupt. Therefore it is possible to resolve the exact point of execution for statistical analysis within an interrupt, such as for example within a periodic interrupt.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/kernel_containers.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Kernel Containers </title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Kernel Containers </h3>
+<P LANG="en-GB" ALIGN=JUSTIFY>Kernel containers are internal parts of the Symbian OS kernel. The Kernel stores its most fundamental data structures in kernel containers. Those fundamental data structures include threads, processes, chunks, mutex objects, semaphores, and many other similar kinds of elements that belong to the internal operation of the OS. In an interrupt, it is possible to investigate the contents of the kernel container, thus resolving information that is available in a readily processed form and that may be very difficult to be extracted by any other means.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>One use of investigating kernel containers is in the implementation of memory tracing. Information about the memory allocated by each thread (stack and heap size) can be easily acquired during an interrupt. Experiences show that resolving the same information from the user side requires much more processing.</P>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/kernel_hook.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Kernel Hook</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Kernel Hook</h3>
+<P LANG="en-GB" ALIGN=JUSTIFY>The information and execution flow within the Symbian kernel contains lots of useful information that can be used to trace sources of performance problems. The only problem with that information is that it is difficult to be stored at real time with any external user-mode software, since it has no access to the data that is private to the kernel executable. One way to gain access to the private data of the kernel is to add small modifications to selected locations of the kernel. Those modifications are referred to as the kernel hooks.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>When execution reaches a kernel hook, a small part of kernel hook code is executed. The kernel hook code stores selected important information that may be available only at a small fraction of time in the processing that takes place at the immediate vicinity of the hook. The collected few bytes of data are then stored sequentially into a large memory array. The process takes place quickly and should not disturb the kernel activities very much.</P>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/link_register.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Link Register Value</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Link Register Value</h3>
+<p>Link register as presented here is specific to the instruction set of the ARM architecture, even though similar solutions can be found from other processor families. Purpose of the link register is to store the value of the address following an executed Branch and Link instruction. Purpose of storing the value is to be able to continue the execution from the next instruction following the branch and link instruction, after returning from a subroutine. In practice this takes place by storing the value from the link register back to the program counter. Link register is a banked register, thus each of the processor modes refer to a dedicated physical register. In performance measurements, link register values can be inspected in order to resolve addresses from which the execution has branched to the currently executing function. A problem in this resolution is that the link register value is usually stored to the stack after entering a custom subroutine, and therefore the values in it do not have to be preserved. The correct link register value is always retrieved from the stack just before returning from the subroutine. This permits the subroutine to trash the value present in the link register during its execution. The trashing usually takes place when a sequential branch and link command is executed within a subroutine. It leaves the link register with a value of the address next to the most recent branch and link command instead of the original value (stored to the stack) that would point to the return address outside the subroutine.</p>
+<P LANG="en-GB" ALIGN=JUSTIFY>In performance measurements, link register values can be used to resolve the caller / callee relations between the functions or methods at run-time. In a practical arrangement, this can be done for example during a periodic interrupt. The explained limitations within the correctness of the link register value have to be taken into account in the analysis, but by following a certain logic the correct values can be distinguished from the values in which the link register has already trashed. In simple terms, the values that point outside the function that are currently under execution can be considered as correct return values for the function, thus revealing the caller of that function. The values that point inside the same function result from subsequent branches that have taken place within the function before the investigation, and cannot be considered correct return values.</P>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/os_thread.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>OS Thread Name and ID</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>OS Thread Name and ID </h3>
+<p>In interrupt processing or kernel executable in a privileged mode and within the kernel process, it is possible to efficiently resolve the name and the thread ID of the currently executing thread. Accordingly, it is possible to resolve the average execution time distribution between different threads in a periodic interrupt. This takes place simply by sequentially storing the identification of the thread that was under execution when the interrupt occurred.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/periodic_int.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Periodic Interrupt</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Periodic Interrupt</h3>
+<p>Symbian OS provides periodic interrupts that occur each millisecond or its multiples. The benefit of employing a periodic interrupt in performance measurements is that when the interrupt occurs, the processor is switched to a privileged mode before the measurement software interrupt gets executed. In a privileged mode it is possible to gather information from the operating system in ways that would not be possible while in user mode. Disadvantage of periodic interrupts is that activities within them cannot last for too long in order not to disturb other processing. Therefore the recorded information has to be gathered in a memory buffer and written to an external output or file system at a later time, for example in a DFC.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/pgm_counter.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Program Counter Value</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Program Counter Value</h3>
+<p>Program counter is a special register in sequential processors following the principles of Von Neumann architecture. Its purpose is to store the address of the currently executing instruction. In performance measurements, the value of the program counter can be inspected in order to resolve the location of the current execution. On the other hand, program counter-relative values stored to the stack can be used to retrieve return values of branch instructions and interrupts. In ARM architecture, program counter is the register R15 but it is usually referred to as the PC. It is an unbanked register thus its value refers to the same physical register in each of the processor modes.<br>
+</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/proc_mode.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Processor Mode</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Processor Mode</h3>
+<P LANG="en-GB" ALIGN=JUSTIFY>ARM processor architecture supports seven processor modes. Names of the modes are User, FIQ, IRQ, Supervisor, Abort, Undefined, and System. Purpose of the modes is to enable a suitably written operating system to control the use of certain system resources. On the other hand, the modes enable fast switching of context, for example, from user code to interrupt handling (see Banked Registers). All modes except the User mode are known as privileged modes. Of the privileged modes, all five modes except the System mode are known as exception modes. Exception modes are entered when an exception or an interrupt occurs. System mode can be used to control system resources from within the same register context as the user mode.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>User mode can be changed to another mode only through an exception or an interrupt, making it possible to efficiently control the change between modes. In performance measurements, processor modes have a large importance since the processor mode indicates the status of processing within the system. When storing performance Related references in a part of the system that may be accessed with any of the processor modes active, it may be necessary to deduce from the processor mode whether certain operations are legal or not, and to proceed accordingly.</P>
+<p>&nbsp;</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/read_write_load.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Read/Write Load Characteristics</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Read/Write Load Characteristics</h3>
+<p>Memory and file system share the same conceptual function &ndash; they are used for storing and retrieving information. However, from a software point of view they operate on a completely different level of abstraction.</p>
+<P LANG="en-GB" ALIGN=JUSTIFY>Memory is a compulsory and fundamental property of information processing systems such as computers. In practice it can be said that the capability to process information is based on the ability to store and retrieve information from memory.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>A file system on the other hand, is a software construction that controls certain hardware peripheral or peripherals that have the ability to store information. This peripheral can also be the same memory as used by the processor. The software construct that implements the file system introduces a well-known abstraction, according to which collections of data can be considered as files.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY> Both memory and file system (if present) have an important role within the performance of almost any software system. For that reason, their performance characteristics are important to be considered when analysing software performance.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>Similar kinds of tests suit testing both memory and file system performance. To put it simple &ndash; in a basic test for performance, data blocks of specific sizes are rapidly either written or read to/from the file system or memory. By varying the sizes of the blocks, different characteristics of the memory and the file system can be found out. By making the amount of blocks large, the statistical values produced by the measurements can be made more reliable.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>Even though performing these kinds of characteristic measurements is quite easy, their interpretation should consider several issues that can make things a bit more complicated. First of all, memory performance is dependent on several factors that cannot be seen directly from the software. Such factors are the operation of MMU (Memory Management Unit), the operation of data cache(s) between the processor and memory, and the operation and load within the data bus between the memory and the processor.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>Secondly, operation of the file system is similarly complicated by disturbing factors such as the activity of other processing within the system, and interrupt load caused by other peripherals or other similar activity. For example, the load within the bus through which the data is transferred to the peripheral storing the information and disturbance caused by concurrent write or read requests.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>Therefore the performance measurements related to either memory or file system should be made under as undisturbed conditions as possible. Sometimes the measurements should be made repeatable so that the performance changes caused by possible modifications in certain properties of the system could be easily resolved.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>On the other hand, it may be handy to have measurement results of practical performance of memory/file system as it is seen by the applications. For that purpose it can be possible to use a technique similar to the sampling, as described earlier. In that approach very short tests are performed periodically and changes in their respective results are investigated with the other activities performed within the system. Through such kind of investigation it can be possible to identify which activities within the system are those that cause actual performance loss in say, the file system.</P>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/rofs.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Read Only File System (ROFS)</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Read Only File System (ROFS) </h3>
+<p>Read Only File System, which is actually the greatest source of need for dynamic binary resolution. ROFS is a file system that dynamically loads system binaries at run-time in an on-demand basis, thus reducing the amount of binary code required in the system start-up phase.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/saved_pgm_status_reg.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Saved Program Status Register</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Saved Program Status Register</h3>
+<p> In ARM architecture, the saved
+			program status register (SPSR) is a banked register in all of the
+			exception modes (thus not in user mode or system mode). When
+			switching the processor mode from any other mode to any of the
+			exception modes, the value within the CPSR is stored to the SPSR
+			so that it can be recovered after the exception (such as an
+			interrupt) has been processed. When having performance measurement
+			instrumentation within an interrupt, it can be useful to
+			investigate the value within the SPSR in order to find out the
+mode of the processor before the interrupt.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/serial_output.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Serial Output</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Serial Output</h2>
+<p>Serial Output through an UART can be used to generate an immediate trace of certain performance-critical activities. If formatted debug printing is supported by the software system (as it is in Symbian OS), it is possible to output information in human readable form. This includes numeric values or strings that are in connection to the immediate situation within the system at the point the printing occurs. Serial Output is a slow way to output information, and its excessive use affects the system performance significantly. Therefore it cannot be used in order to gather large amounts of data.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/sw_interrupt.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>SWI, Software Interrupt</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>SWI, Software Interrupt</h3>
+<p>In the ARM instruction set, software interrupts are software-generated exceptions that cause the processor mode to change to the supervisor mode, normal interrupts to disable, and the execution to branch into the location corresponding to the software interrupt exception (0xFFFF0008 or 0x00000008, depending on the configuration). The type of the interrupt can be defined with a 24-bit value.</p>
+<P LANG="en-GB" ALIGN=JUSTIFY>A software interrupt is issued with the SWI instruction. Software interrupts are used generally to implement operating system calls, since they enable a quick and controlled context switch to a privileged mode. When performing software performance measurements, the use of software interrupts can become very useful, as they provide a way to record run-time information about the current state of the software by using the resources available within the kernel while being in a privileged mode.</P>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/swi_interrupt.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Software Interrupts (SWI)</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>Software Interrupts (SWI)</h3>
+<p>Software Interrupts (SWIs) are commonly used for implementing operating system calls. In ARM architecture, SWIs can be performed with a specific SWI instruction. As the name already suggests, a software interrupt is a software-generated interrupt. When a SWI takes place, resulting actions are somewhat similar to those caused by hardware-generated interrupts. Execution of user-level software is halted and an interrupt service routine (ISR) is entered. SWIs cannot however halt interrupt requests (IRQs) or fast interrupt requests (FIQs), which are commonly hardware-generated and require uninterrupted processing.</p>
+<P LANG="en-GB" ALIGN=JUSTIFY>When processing a SWI, the operating mode of the ARM is switched rapidly to the supervisor mode, thus allowing a controlled means for accessing system and kernel resources with privileged rights. This makes SWIs a valuable tool for performance measurements. Custom SWIs can be used to collect important system-level information during the execution of normal user-level software.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>A drawback is that the instruction that causes the SWI to take place has to be added to the specific part of interest within the software. Recompilation of that part of source code is consequently needed. In practice this restricts the use of SWIs in performance measurements to those specific parts of software that have already been identified as interesting through other means of performance analysis.</P>
+<P LANG="en-GB" ALIGN=JUSTIFY>It may also be necessary to follow certain precautions before inserting a SWI into a custom part of software code &ndash; some generic functions can be entered in both user and privileged modes. Since SWIs are allowed in general only in user mode software, it may be necessary to take a look at the CPSR (current program status register) in order to resolve the current processor mode before invoking the SWI.</P>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/methods/tcpip.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>TCP/IP Stack Efficiency</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h3>TCP/IP Stack Efficiency and Its Tracing</h3>
+<p>The networking efficiency here is perceived as effective network packet handling on receiver side of a connection over a wireless network. In this context, the performance tools intend to benchmark that efficiency in two ways:</p>
+<ul>
+  <li>by tracking the usage of TCP/IP stack driver (GPP+ITT+GFC traces) and</li>
+  <li>by measuring the network traffic itself (TIP trace) that is passed through the stack when the connection opened.</li>
+</ul>
+<P LANG="en-GB" ALIGN=JUSTIFY>TCP/IP trace (or TIP trace) gathers information about packet sizes, source and destination addresses/ports and visualize the data in a cumulative graph. The main intention is to gather information about the causes of network traffic blocks whether they are caused by false implementation of an application or protocol stack or a result of highly loaded network.</P>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/BUP_trace.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>BUP Trace</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Button Press Trace</h2>
+<p>This provides an exact trace that records data about buttons pressed during the trace.</p>
+<p> It is often useful to see the positions where different buttons were pressed during the trace. The mechanism for collecting BUP traces is simple. The data is collected from the user side. The trace mechanism creates a new <span class="code">RwindowGroup</span> object and a <span class="code">RwsSession</span> object to interact with the Window Server. The window group is hidden from the display, and it is made to receive all of the needed key presses. When received, a key press event is then stored to the trace, along with the time the event took place.</p>
+<p><strong>Related Reference </strong></p>
+<ul>
+  <li><a href="../../tasks/analyser/key_profile_pref.htm">Key Press Profile</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/DSP_trace.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>DSP Trace</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>DSP Trace</h2>
+<p>This provides an exact trace for DSP load visualization.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/GFC_trace.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Function Call Trace</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Function Call Trace</h2>
+<p>This is a statistical trace that records function caller/callee relationships during execution. The trace is based on periodically sampling link register values. With the link register value, it is possible to resolve the caller function for the currently executing function.</p>
+<p>Because the link register value is recorded periodically rather than each time a function call occurs, the Function Call trace will not have information about all function calls. In general, the longer the profiling session, the more complete the function call information will be.</p>
+<p>A second problem with periodically recording link register values is that a function may preserve the link register value on the stack and then use the link register for computations or for sequential branch and link intructions within a function. In the former case, the caller of the function appears to be a function at a small address such as 0x1; in the latter case, the caller of the function appears to be the function itself.</p>
+<p>Analysis of Function Call trace data depends on the importer to determine the names, and start and end addresses of functions from information such as that in a .symbol file.</p>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="GPP_trace.htm">Address/Thread Trace</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/GPP_trace.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Address/Thread Trace</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Address/Thread Trace</h2>
+<p> This is a statistical trace for analyzing thread, binary, and function CPU load. All other traces are in synch with this trace, therefore, there has to be a address/thread trace in each measurement.</p>
+<p> The address/thread trace sampler records information about the current location of program execution and the currently executing thread with a sampling rate between 1ms and 10000ms (10 seconds).</p>
+<p>When the sampling interval is greater than 1ms, tables, graphs, and graph tooltips will display differently. When you select a time interval on a graph, the samples included will be from 1ms after the start time up to and including the end time. So if the interval=1ms, the time period is 3ms to 10ms, the samples will be 4, 5, 6, 7, 8, 9, and 10. If interval=2ms, the samples included will be 4, 6, 8, and 10. If interval=3, the samples will be 6 and 9.</p>
+<p>The Samples columns in Analyzer tables will reflect the amount of samples based on the profiler sampling rate. The thread, binary, and function graphs bundle together 100 samples and then draw their lines. Assume that  EKern.exe[1]::Null_0 has:<br>
+&nbsp;&nbsp;50 samples out of 100, followed by<br>
+ &nbsp;&nbsp;75 samples out of 100, followed by<br>
+ &nbsp;&nbsp;10 samples out of 100</p>
+<p>You will see EKern Null's graph has:<br>
+&nbsp;&nbsp; line segment starting at 50% and ending at 75% followed by<br>
+&nbsp;&nbsp; line segnmet starting at 75% and ending at 10%</p>
+<p>If interval=1ms, line segments start and end at multiples of 100ms (1/10 of a second). If interval=2ms, line segment endpoints are at multiples of 200ms. If interval=3ms line segment endpoints are at multiples of 300ms, etc.</p>
+<p>When you show individual samples, they will be spaced out by interval. When you move your cursor across a graph with individual samples, the tooltip will change half as frequently if the interval=2ms, etc.</p>
+<p>When a trace, such as priority trace, samples on an extended interval, it will be sampled at the time of the next address/thread interval. For example, if the priority period is 900 and the address/thread period is 25, priorities are sampled at 900 (actually 895). If the address/thread time interval is 40, however, priorities are sampled at 920 (really 915), because 900 is not a multiple of 40.</p>
+<p>Key presses will be given the last address/thread time. So if sampling interval=1000ms (1 second), and you press two keys quickly, they will be recorded as either 1 second apart or as being pressed at the same time.</p>
+<h3>Trace Data Modes </h3>
+<p>Address/Thread trace data can be visualized in different modes, depending on whether the items of interest are threads, binaries, or functions. For the elements associated with each mode, you can calculate the average CPU load within a selected time period, and display that information in tables and graphs.</p>
+<p>In all modes, address/thread trace graphs share the same semantics:</p>
+<ul>
+  <li>Colors represent different trace items, such as threads, binaries, and functions</li>
+<li>Time is represented on the horizontal axis</li>
+<li>CPU load is represented on the vertical axis</li>
+</ul>
+<p>The address/thread trace data can be visualized in different ways. In graphs, 100 samples are averaged in order to create a visual representation with temporal precision of 1/10 second. In contrast to the averaged graph, address/thread trace bar graph mode visualizes the samples individually without averaging (Figure 1). Bar graph mode shows address/thread trace information with each sample shown as a colored bar. With this visualization it is much easier to see different patterns that take place in the device, and to estimate more precisely the time of events. Select <strong>Investigator &gt; CPU Load Graphs &gt; Show Individual Samples</strong> to display bar graph mode.</p>
+<p align="center"><img src="images/gpp_bargraph.png" width="577" height="448"></p>
+<p align="center" class="figure">Figure 1. Address/Thread Trace - Bar graph mode</p>
+<p align="left"><strong>Related references</strong></p>
+<ul>
+  <li><a href="GFC_trace.htm">Function Call Trace</a>  </li>
+</ul>
+<p></p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/IRQ_trace.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>IRQ Trace</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Interrupt Request Trace</h2>
+<p>This trace records IRQ interrupts and their respective identification.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/ITT_trace.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>DLL Support Trace</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Dynamic Binary Support Trace</h2>
+<p>During sampling, the dynamic binary support trace records the full path names, starting locations, and lengths of binaries loaded on the target device. That data is used to determine which binaries and functions are associated with address/thread trace samples taken in dynamic binaries.</p>
+<p>Dynamic binary support trace is needed only if you had dynamic binaries present in the device during the use case. In practice, this is if you were using applications that were installed after you flashed the device, or if the device uses ROFS. For the importer to perform dynamic binary support trace analysis, you MUST have the binaries that were actually executed on the device. In addition, you MUST have correct .map files produced during their compilation. Each binary file and its corresponding .map file has to be found by the importer in the same directory.</p>
+<p>When you import a Profiler data file (*.dat) that contains dynamic binary support trace information, the importer needs to locate the compiled dynamic binary files. The importer relies on .pkg, .oby, and .iby files for mapping the fullpath binary names on the target device to the compiled dynamic binaries.</p>
+<p>If you specified a Carbide.c++ project for importing, the associated .pkg file will be automatically added. On the other hand, you may have a .oby or .iby file, such as the ROFS .oby file, that contains a list of binaries to be included. If an oby/iby file is added to the list, the importer automatically leaves out files that are known not to be binary executable data.   If you specified a Carbide.c++ project or EPOCROOT, the importer will try to help you find oby/iby files to add.</p>
+<p>If you have custom files in your oby/iby file that are not binary executables and should not take part in the analysis, you might consider removing them from the oby/iby before continuing with the analysis. If those files are very large, processing might take longer.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/MEM_trace.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>MEM Trace</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Memory Trace</h2>
+<p>This trace takes samples of memory consumption of processes and threads. It records the free and total amount of memory on the device, the amount of memory allocated to kernel chunks, and the amount of memory allocated to stack/heap of each individual thread.</p>
+<p>The memory trace measurement is performed periodically in a DFC function with interrupts disabled during the critical time of gathering data. Due to the large number of calculations involved in the memory sampling procedure, the minimum sampling frequency a user may request is 50 milliseconds. If several other traces are on, even a 50 millisecond memory sampling frequency may cause system instability because of the time spent in the interrupts disabled mode. </p>
+<p>The memory sampling procedure performs a loop in which each index in the kernel Chunk container is read. All normal system-level memory allocation takes place through Chunks, so it is a natural place to investigate system-level memory utilization. The chunks that contain thread heaps are explicitly sought (in EKA-2, the Chunks containing a thread’s heap have a name <span class="code">$HEAP</span>, which is used as the indicator). After being found, names of the threads owning the newly found chunks are added to the data stream. After that, the heap allocation status of both old and new heaps is pushed to the data stream, along with the information about the current stack size of the thread owning the heap.</p>
+<p class="note"><strong>NOTE</strong> A chunk whose name contains the   string “$HEAP†has a chunk   size and does not have a heap/stack size.</p>
+<p>In EKA-2 kernel, the memory allocated internally by the kernel is divided into three main regions, represented by:</p>
+<ul>
+  <li> <span class="code">SvData</span> (containing the kernel binary image)</li>
+  <li><span class="code">SvHeap</span> (containing the bulk of kernel memory)</li>
+  <li><span class="code">SvStack</span>, containing the supervisor stacks (used only in EKA-2) </li>
+</ul>
+<p>for all threads in the system. In its current form, tracing the allocation status of those chunks (mainly the <span class="code">SvHeap</span> and <span class="code">SvStack</span>, since <span class="code">SvData</span> is static) has not been implemented.</p>
+<p>The memory trace cannot determine the amount of memory being used within an allocated chunk or stack/heap.
+<h5>Related references</h5>
+<ul>
+  <li><a href="../analyzer/view_memory_usage.htm"> Memory Usage View</a></li>
+<li><a href="../analyzer/wnd_memory_usage_statistics.htm">Memory Usage Statistics </a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/PRI_trace.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Thread Priority Trace</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Thread Priority Trace</h2>
+<p>This trace takes samples of thread priorities. When the operating system is called, the time and priority ranking for the currently executing thread is recorded. Because a thread's priority may change over time, sometimes more than one priority ranking will be recorded for a thread.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/PWR_trace.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Power Usage Trace</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Power Usage Trace</h2>
+<p> The Power Usage trace sampler uses a specific ISC channel to gather information about energy consumption from the Energy Management (EM) server running on the domestic OS. The sampler collects battery voltage, current, and capacity values, but it does not change any EM settings. The default sampling frequency is 4Hz (250ms), and the minimum allowed is 20Hz (50ms). Requesting an interval faster than the hardware supports will result in return values being identical to the previously sampled values.</p>
+<p> Battery capacity and voltage values are assumed to be constant over a short measurement period. If longer periods are measured the slower 0.25 to 1 Hz sampling rate is recommended. </p>
+<h5>Related references</h5>
+<ul>
+  <li><a href="../analyzer/view_power_usage.htm"> Power Usage View</a></li>
+<li><a href="../analyzer/wnd_power_graph_settings.htm">Power Usage Settings</a> </li>
+<li><a href="../analyzer/wnd_power_usage_statistics.htm">Power Usage Statistics </a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/SWI_trace.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>SWI Trace</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Software Interrupt Trace</h2>
+<p>This trace records information on software interrupts and the threads that caused them.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/TIP_trace.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>TIP Trace</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>TCP/IP Trace</h2>
+<p>This is an exact trace that records TCP/IP activity such as packet and data amounts.</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/Trace_Items.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+    <title>Trace Items</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Trace Items</h2>
+<p>Recorded data is logically separated into different traces that can be selected or deselected by the Profiler. In analysis, trace data is combined with compile-time produced information (symbol files and  binaries). All trace data and required symbolic information is stored in a stand-alone file that can be imported into the analyzer.</p>
+<ul>
+  <li><a href="GPP_trace.htm">Address/Thread Trace </a></li>
+  <li><a href="BUP_trace.htm">Button Press Trace</a> </li>
+  <li><a href="ITT_trace.htm">Dynamic Binary Support Trace</a></li>
+  <li><a href="GFC_trace.htm">Function Call Trace</a></li>
+  <li><a href="MEM_trace.htm">Memory Trace </a></li>
+  <li><a href="PWR_trace.htm">Power Usage Trace </a></li>
+  <li><a href="PRI_trace.htm">Thread Priority Trace</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/advanced_options.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Setting Advanced Options</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+    <style type="text/css">
+<!--
+.style1 {	color: #FF0000;
+	font-weight: bold;
+}
+.style2 {font-family: Georgia, "Times New Roman", Times, serif}
+-->
+    </style>
+</head>
+
+<body>
+<h2>Setting Advanced Options </h2>
+<p>Use the <b>Advanced</b> options menu in the Profiler to specify the thread priority sample interval. The advanced options include:</p>
+<ul>
+  <li>Memory/Priority Sample interval</li>
+  <li>Power Usage interval</li>
+  <li>Address/Thread interval</li>
+</ul>
+<p class="note"><span class="style1">WARNING</span> When you enable all the traces, the 50ms minimum Memory/Priority  interval may not be sufficient for all of the traces to complete successfully between each cycle. This can cause strange errors, such as loss of icons in lists. If you suspect this problem, simply increase the sampling interval to 100ms or more or disable some traces.</p>
+<table width="600" border="1" align="center">
+  <tr align="center">
+    <td><b>S60</b></td>
+    <td><b>UIQ</b></td>
+  </tr>
+  <tr align="center">
+    <td width="50%"><div align="center"><img src="images/TracingOptionsList3.png" width="240" height="320"></div></td>
+    <td><div align="center"><img src="images/uiq_setting_advanced_settings.png" width="240" height="320"></div></td>
+  </tr>
+</table>
+<p class="figure">Figure 1. Advanced options settings in Profiler (S60 and UIQ) </p>
+<h5>Table 1. Advanced Options</h5>
+<table width="90%" border="0" cellpadding="2" cellspacing="0">
+  <tr>
+    <th width="213" scope="col">Menu Option </th>
+    <th width="646" scope="col">Description</th>
+  </tr>
+  <tr>
+    <td><b>Memory/Priority Sample interval </b></td>
+    <td><p>Specify the memory and thread priority sample interval.</p>
+      <p>The operating system is called automatically every millisecond to determine what thread is currently executing. This interval setting indicates how often an additional query to the operating system is made to determine the priority of the currently executing thread. </p>
+      <p>The interval is specified in milliseconds. The minimum interval for sampling is 50ms, with the default setting 1000ms. </p>
+      <p class="note"><b>NOTE</b> See<a href="output_settings.htm"> Setting Output Settings</a> for UIQ File prefix information. </p></td>
+  </tr>
+  <tr>
+    <td><b>Power Usage Interval </b></td>
+    <td><p>Specify the power usage priority sample interval.</p>
+    <p>The interval is specified in milliseconds. The minimum interval for sampling is 50ms (20Hz), with the default setting 250ms (4Hz). The minimum interval at which sampled power values change is device dependent. </p>
+    <p class="note"><b>NOTE</b> Power usage measurements are not available in UIQ version. </p>
+    <p class="note style2"><span class="note"><b>NOTE</b></span> If you install a 3.1 0r 3.2 SIZE SISX file, the power usage sampling time interval will always be 250 ms, regardless of what value you specify.</p></td>
+  </tr>
+  <tr>
+    <td><strong>Address/Thread interval</strong> </td>
+    <td>Specify the Address/Thread interval.  Enter an address/thread sampling interval between 1ms and 10000ms (10 seconds).</td>
+  </tr>
+</table>
+<div>
+  <h4>Setting an Advanced Option</h4>
+  <ol>
+    <li>Launch the Profiler application on the target device </li>
+    <li>Open the Output Settings options screen: </li>
+    <ul>
+      <li>S60 - Select the Output Settings menu</li>
+      <li>UIQ - Select the Misc Settings... menu</li>
+    </ul>
+    <li>Set the desired option on or off</li>
+    <li>Exit the screen </li>
+  </ol>
+</div>
+  <h5>Related references</h5>
+<ul>
+  <li><a href="prof_using.htm">Using the Profiler</a>
+</li>
+</ul>
+<h5>Related tasks</h5>
+<ul>
+  <li><a href="tracing_options.htm">Setting Tracing Options</a></li>
+<li><a href="output_settings.htm">Setting Output Settings </a>    </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/cmd_line_overview.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Using the Command-line</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Using the Command-line</h2>
+<p>Performance Investigator can be launched from the command line using <span class="code">eShell</span> or  other device resident command-line tool to facilitate program testing. Using <span class="code">eShell</span>, you can start, stop, or perform timed actions on any application you want to profile. </p>
+<p align="center"><img src="images/cmd_line_eshell_example.png" width="267" height="109"></p>
+<p class="figure">Figure 1. eShell ready to start a 30-second timed Profiler session. </p>
+<p>Calls of the command line version of the Carbide.c++ Profiler have the following forms:</p>
+<p class="listing">
+  CProfApp_SISX start [<i>settings_file</i>]<br>
+  CProfApp_SISX end [<i>settings_file</i>]<br>
+  CProfApp_SISX timed <i>seconds</i> [<i>settings_file</i>]<br>
+  CProfApp_SISX timed <i>settings_file</i> <i>seconds</i></p>
+<p>where:</p>
+<ul>
+  <li><span class="code">start </span>&#8212; starts a Profiler session based on the settings file</li>
+  <li><span class="code">end </span>&#8212; ends a Profiler session based on the settings file</li>
+  <li><span class="code">timed </span>&#8212; starts a timed Profiler session based on the settings file</li>
+  <li><i>settings_file</i> </span>&#8212; a file containing the session <a href="../settings.htm">settings</a>. The file name may be enclosed in double quote (") characters. If no settings file is specified, the default is <span class="code">C:\Data\CProfSettings.txt</span>.</li>
+  <li><i>seconds</i> </span>&#8212; the decimal time in seconds for a timed Profiler session. It must be present for a timed session, and it must be greater than 0.</li>
+</ul>
+<p class="note"><b>NOTE</b> You can generate a valid configuration file by starting the Carbide.c++ Profiler GUI, selecting suitable settings, and then exiting the GUI. The settings file created is called <span class="code">C:\Data\CProfSettings.txt</span>.</p>
+<h5>Command examples</h5>
+<p>Starting and stopping a session:</p>
+<blockquote>
+  <p class="listing"> cprofapp_sisx start c:\Data\cprofsettings.txt<br>
+    cprofapp_sisx end c:\Data\cprofsettings.txt</p>
+</blockquote>
+<p>Executing a 30 second session:</p>
+<blockquote>
+  <p class="listing"> cprofapp_sisx timed 30 c:\Data\cprofsettings.txt</p>
+</blockquote>
+<p><strong>Related references </strong></p>
+<ul>
+  <li><a href="../settings.htm">Profiler Settings File </a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/AdvancedOptionsEditBox.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/AdvancedOptionsEditBox_uiq.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/AdvancedOptionsWindow.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/OutputOptionsWindow_DebugPort.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/OutputOptionsWindow_FileSystem.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/S60GUI.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/S80GUI.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/S90GUI.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/SamplingProfilerMainWindow.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/SamplingProfilerMainWindow_uiq.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptions.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptionsList.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptionsList2.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptionsList3.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptionsList3_uiq.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptionsList_uiq.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/TracingOptions_uiq.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/cmd_line_eshell_example.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/gpp_bargraph.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/profiler_button_press_option.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/profiler_configuration.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/profiler_install.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/profiler_start_profiler.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/profiler_start_profiler_uiq.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/screen_output_settings.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/screen_output_settings_02.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/sw_root_directory.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/uiq_setting_advanced_settings.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/uiq_setting_output_settings.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/uiq_setting_tracing_options.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/images/uiq_using_the_profiler.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/output_settings.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Setting Output Settings</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+    <style type="text/css">
+<!--
+.style1 {font-family: "Courier New", Courier, mono}
+-->
+    </style>
+</head>
+
+<body>
+<h2>Setting Output Settings</h2>
+<p>Use the <b>Output settings </b>  menu in the Profiler to specify the characteristics of the  sampled data file. The output settings include:</p>
+<table width="650" border="1" align="center">
+  <tr>
+    <td width="33"><b>S60</b></td>
+    <td width="593"><div align="center">&nbsp;<img src="images/screen_output_settings.png" width="264" height="312">&nbsp;<img src="images/screen_output_settings_02.png" width="264" height="312"></div></td>
+  </tr>
+  <tr>
+    <td><b>UIQ</b></td>
+    <td><div align="center"><img src="images/uiq_setting_output_settings.png" width="240" height="320"></div></td>
+  </tr>
+</table>
+<p class="figure">Figure 1. Output Settings options for file system and debug mode (S60 and UIQ) </p>
+<h5>Table 1. Output Settings Options</h5>
+<table width="90%" border="0" cellpadding="2" cellspacing="0">
+  <tr>
+    <th width="147" scope="col">Menu Option </th>
+    <th width="640" scope="col">Description</th>
+  </tr>
+  <tr>
+    <td><b>Output to </b></td>
+    <td><p>Specify either the target device's <span class="style1">File system</span> or <span class="style1">Debug port</span> to store the sampled data.</p>
+    <p class="note"><b>NOTE </b>Not available in UIQ version. </span></p></td>
+  </tr>
+  <tr>
+    <td><b>Save file in </b></td>
+    <td>If you selected <span class="style1">File system</span> in the <span class="style1">Output to</span> menu option, then you can save the data file to a memory card or the target device's C:\ drive.
+    <p class="note"><b>NOTE</b> Not available in UIQ version. </span></p></td>
+  </tr>
+  <tr>
+    <td><b>File prefix </b></td>
+    <td><p>Specify the file prefix for data files. The name of the profiler data file is formed from the prefix and ends with a .dat extension. If you perform multiple traces and use the file output option, include a hash mark (#) in your file prefix. Subsequent traces will then be saved with different file names. The hash mark will be replaced with an incremented number starting from one.</p>
+    <p><span class="note">Files names must be 19 characters or less.</span></p>
+    <p class="note"><b>NOTE</b> See<a href="advanced_options.htm"> Setting Advanced Options</a> for UIQ Mem, Pri sample interval information. </p></td>
+  </tr>
+</table>
+<div>
+  <h4>Setting the Output Settings </h4>
+  <ol>
+    <li>Launch the Profiler application on the target device </li>
+    <li>Open the Output Settings options screen: </li>
+    <ul>
+      <li>S60 - Select the Output Settings menu</li>
+        <li>UIQ - Select the Misc Settings... menu</li>
+    </ul>
+    <li>Set the sampled data file informaton</li>
+  <li>Exit the screen </li>
+  </ol>
+</div>
+<h5>Related references</h5>
+<ul>
+  <li><a href="prof_using.htm">Using the Profiler</a></li>
+</ul>
+<h5>Related tasks</h5>
+<ul>
+  <li><a href="advanced_options.htm">Setting Advanced Options</a></li>
+  <li><a href="tracing_options.htm">Setting Tracing Options</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/prof_using.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Using the Profiler</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+    <style type="text/css">
+<!--
+.style1 {font-family: "Courier New", Courier, mono}
+-->
+    </style>
+</head>
+
+<body>
+<h2>Using the Profiler</h2>
+<h4>Overview</h4>
+<p>After successfully <a href="../../tasks/profiler/prof_installation.htm">installing</a> the Profiler .SISX file on your target device, you will be able to access the user interface. Run the <b>CarbidePI</b> application located in the &#8220;Installed&#8221; applications (Figure 1).</p>
+<table width="600" border="1" align="center">
+  <tr align="center">
+    <td><b>S60</b></td>
+    <td><b>UIQ</b></td>
+  </tr>
+  <tr align="center">
+    <td width="50%"><div align="center"><img src="../profiler/images/SamplingProfilerMainWindow.png" width="264" height="312"></div></td>
+    <td><div align="center"><img src="images/uiq_using_the_profiler.png" width="240" height="320"></div></td>
+  </tr>
+</table>
+<p align="center" class="figure">Figure 1 - Profiler Main Window (S60 and UIQ) </p>
+<p>In Options, configure the necessary run-time options. Specify which traces you want enabled, where to place the generated .dat profiler data file, the profiler file prefix, and the trace priority sampling interval.</p>
+<p>In the Profiler, the Address/Thread trace is <strong>always</strong> active when profiling is performed. Other traces are synchronized with the Address/Thread trace.</p>
+<p>In addition to Address/Thread trace, you can enable additional trace options such as dynamic binary support, memory and power usage, and function calls.</p>
+<div class="step">
+  <h4>Profiling an Application</h4>
+  <ol>
+    <li>Open the Profiler options screen
+      <p>Select the Tracing options menu  from the Profiler menu (Figure 2)</p>
+    </li>
+    <blockquote>
+    <table width="600" border="1" align="center">
+          <tr align="center">
+            <td><b>S60</b></td>
+            <td><b>UIQ</b></td>
+          </tr>
+          <tr align="center">
+            <td width="50%"><div align="center"><img src="../profiler/images/TracingOptions.png" width="264" height="312"></div></td>
+            <td><div align="center"><img src="images/TracingOptions_uiq.png" width="240" height="320"></div></td>
+          </tr>
+      </table>
+    </blockquote>
+    <blockquote>
+      <p align="center" class="figure">Figure 2 - Tracing Options</p>
+    </blockquote>
+    <li>Enable or disable trace options</li>
+
+    <p>Specify On or Off for the available trace items - Dynamic binary support, Function call capture, and Thread priority capture.  (Figure 3).</p>
+    <blockquote>
+      <p align="left" class="note"><b>NOTE</b> If the executables you wish to analyze are not in a ROM image (.symbol file) of your target device, then you will need to turn on Dynamic binary support.</p>
+    </blockquote>
+    <table width="600" border="1" align="center">
+      <tr align="center">
+        <td><b>S60</b></td>
+        <td><b>UIQ</b></td>
+      </tr>
+      <tr align="center">
+        <td width="50%"><div align="center"><img src="../profiler/images/TracingOptionsList.png" width="264" height="312"><img src="images/TracingOptionsList2.png" width="264" height="312"></div></td>
+        <td><div align="center"><img src="images/uiq_setting_tracing_options.png" width="240" height="320"></div></td>
+      </tr>
+    </table>
+    <p align="center" class="figure">Figure 3 - List of Trace Items</p>
+    <li>Specify Output</li>
+    <p>Specify the output for the sampled data (Figure 4). The output method can be either the <span class="style1">File system</span> or <span class="style1">Debug port</span>. If you select File system, you can save the data file to a memory card or the target device C:\ drive. With the debug port output method, you will need hardware (such as the Nokia Musti box)  connected to the XTI/STI debug port to capture the profiler data. There is less profiler overhead if the debug port is used.</p>
+    <table width="600" border="1" align="center">
+      <tr align="center">
+        <td><b>S60</b></td>
+        <td><b>UIQ</b></td>
+      </tr>
+      <tr align="center">
+        <td width="50%"><div align="center"><img src="../profiler/images/OutputOptionsWindow_FileSystem.png" width="264" height="312"></div></td>
+        <td><div align="center"><img src="images/uiq_setting_output_settings.png" width="240" height="320"></div></td>
+      </tr>
+    </table>
+    <p align="center" class="figure">Figure 4 - Output Options</p>
+    <p>You can specify the file prefix for data files. The name of the profiler data file is formed from the prefix plus stream.dat. If you perform multiple traces and use the file output option, include a hash mark (#) in your file prefix. Subsequent traces will then be saved with different file names. The hash mark is automatically replaced with a number. For example, if you define the file prefix as <span class="style1">PI_#_</span>, multiple trace files will be named  <span class="style1">PI_1_STREAM.dat, PI_2_STREAM.dat, &hellip; PI_100_STREAM.dat</span>. Only one hash mark is needed to provide sequential numbering. 
+    If no hash mark is present,  the same file will be overwritten with the same name.</p>
+    <p class="note"><strong>NOTE</strong> Currently, files names should be 19 characters or less.</p>
+    <li>Specify Advanced Options</li>
+    <p>In Advanced options, specify the thread priority sample interval (Figure 5). The operating system is called automatically every millisecond to determine what   thread is currently executing. This interval setting indicates how often an   additional query to the operating system is made to determine the priority of   the currently executing thread. The interval is specified in milliseconds. The   default is 3000 milliseconds (3 seconds). You can get a thread priority as often   as you like but be aware that frequent sampling of the OS may skew the   performance measurement while making the call. There is a significant overhead   to obtaining the priorities of all threads.</p>
+    <p>You can choose an address/thread sampling interval between 1ms and 10000ms (10 seconds). For intervals greater than 1 ms, memory, power, priority and button events are sampled periodically; not every millisecond. Memory and button events are individual events. For memory and priority the current memory size and priority are recorded before entering the time interval, then changes during the interval are recorded and the final memory size and priority  when it exits the interval is recorded.</p>
+    <table width="600" border="1" align="center">
+      <tr align="center">
+        <td><b>S60</b></td>
+        <td><b>UIQ</b></td>
+      </tr>
+      <tr align="center">
+        <td width="50%"><div align="center"><img src="../profiler/images/AdvancedOptionsEditBox.png" width="240" height="320"></div></td>
+        <td><div align="center"><img src="images/uiq_setting_advanced_settings.png" width="240" height="320"></div></td>
+      </tr>
+    </table>
+    <p align="center" class="figure">Figure 5 - Priority sample interval</p>
+    <li>Profile your application</li>
+    <p>After establishing your desired options, select <strong>Options &gt; Profiler &gt; Start</strong> from the main window (Figure 6) to begin sampling. On UIQ devices you will see the state of the profiler change from &ldquo;Ready&rdquo; to &ldquo;Initializing&rdquo;, and then to &ldquo;Profiling&rdquo;. On S60 3.x devices the state will change from  &quot;Initializing&quot; to &quot;Sampling&quot; and then &quot;Finished&quot;. When the state has changed to &ldquo;Profiling&rdquo; or &quot;Sampling&quot;, the trace activity has begun. Note that none of the configurations can be changed when the tracing is active.</p>
+    <p class="note">  <b>IMPORTANT!</b> After the trace activity has started, leave the Profiler running in the background. Now you can proceed with the use case you wish to analyze. For example, run your application on the device.</p>
+    <table width="600" border="1" align="center">
+      <tr align="center">
+        <td><b>S60</b></td>
+        <td><b>UIQ</b></td>
+      </tr>
+      <tr align="center">
+        <td width="50%"><div align="center"><img src="images/profiler_start_profiler.png" width="264" height="312"></div></td>
+        <td><div align="center"><img src="images/profiler_start_profiler_uiq.png" width="240" height="320"></div></td>
+      </tr>
+    </table>
+    <p align="center" class="figure">Figure 6 - Starting a trace session </p>
+    <p>Stop the trace activity by switching back to the profiler and selecting <strong>Options &gt; Profiler &gt; Stop</strong>. Do not use the profiler while the trace data is being written to the data file. When the profiler is stopped, the profiler state shown in the main window will change from &ldquo;profiling&rdquo; to &ldquo;stopping profiler&rdquo;, and finally back to &ldquo;ready&rdquo;. The profiler data file is automatically written to the output previously selected. The actual amount of produced data depends on the length of time tracing was active and which trace options were selected. The Address/Thread trace alone produces approximately 1-4 Kbytes / second. Transfer the data file to your workstation to be analyzed with the analyzer.</p>
+  </ol>
+</div>
+<p><strong>Related references </strong></p>
+<ul>
+  <li><a href="../../tasks/profiler/prof_installation.htm">Installing the Profiler on the Target Device</a></li>
+  <li><a href="../../tasks/analyser/an_load_trace_files.htm">Importing Profiler Data File for Analysis </a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/profiler.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Profiler</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Profiler</h2>
+<p>The profiler is the part of the Performance Investigator that resides on the target device. Its purpose is to gather performance measurement information from the device at run-time and to output the information to be analyzed within the Analyzer part of the tool. Each type of performance information recorded is called a trace. The most important Profiler traces include:</p>
+<ol>
+  <li> Address / thread trace periodically records the current program counter address and the currently executing thread.</li>
+  <li>Dynamic binary support trace periodically records information sufficient to determine which dynamically loaded user application or DLL is executing.</li>
+  <li>Function call trace periodically records the link register value, so that the caller of the currently executing routine can be determined.</li>
+</ol>
+<p><strong>Related references </strong></p>
+<ul>
+  <li><a href="../../tasks/profiler/prof_installation.htm">Installing the Profiler on the Target Device</a></li>
+  <li><a href="prof_using.htm">Using the Profiler</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/profiler/tracing_options.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Setting Tracing Options</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Setting Tracing Options </h2>
+<p>Use the <b>Tracing</b> options menu in the Profiler to specify the types of tracing data to collect when profiling an application executing on a device.</p>
+<table width="650" border="1" align="center">
+  <tr>
+    <td width="33"><b>S60</b></td>
+    <td width="593"><div align="center"><img src="images/TracingOptionsList.png" width="264" height="312">&nbsp;<img src="images/TracingOptionsList2.png" width="264" height="312"></div></td>
+  </tr>
+  <tr>
+    <td><b>UIQ</b></td>
+    <td><div align="center"><img src="images/uiq_setting_tracing_options.png" width="240" height="320"></div></td>
+  </tr>
+</table>
+<p class="figure">Figure 1. Tracing options screen in Profiler (S60 and UIQ)</p>
+<p> The tracing options include:</p>
+<h5>Table 1. <span class="figure">Profiler Tracing Options</span></h5>
+<table width="94%"  border="0" cellpadding="2" cellspacing="0">
+  <tr>
+    <th width="226" scope="col">Menu Option </th>
+    <th width="616" scope="col">Description</th>
+  </tr>
+  <tr>
+    <td><b>Dynamic binary support</b></td>
+    <td><p>Enable (On) or disable (Off) dynamic binary tracing in your profiling task. </p>
+    <p>If the executables you wish to analyze are not in a ROM image (.symbol file) of your target device, then you will need to turn on Dynamic binary support.</p></td>
+  </tr>
+  <tr>
+    <td><b>Function call capture </b></td>
+    <td>Enable (On) or disable (Off) function call information in your profiling task. If disabled, then <a href="../analyzer/function_calls.htm">Function call</a> information will not appear in the Analyzer.</td>
+  </tr>
+  <tr>
+    <td><b>Button press capture </b></td>
+    <td>Enable (On) or disable (Off) the gathering of button press information in your profiling task. If disabled, then Button Press information will not appear in the Analyzer.</td>
+  </tr>
+  <tr>
+    <td><b>Memory usage capture </b></td>
+    <td>Enable (On) or disable (Off) memory usage information in your profiling task. If disabled, then Memory usage information will not appear in the Analyzer.</td>
+  </tr>
+  <tr>
+    <td><b>Thread priority capture </b></td>
+    <td><p>Enable (On) or disable (Off) Thread priority information. If enabled, captured data will include the time and priority ranking of the currently executing thread when the operating system is called.</p>
+        <p>If disabled, then thread priority information is not included and a Priority List column will not be shown in the <a href="../analyzer/thread_load.htm">Thread Load</a> table in the Analyzer.</p></td>
+  </tr>
+  <tr>
+    <td><b>Power usage capture </b></td>
+    <td><p>Enable (On) or disable (Off) power usage information in your profiling task. If disabled, then Power usage information will not appear in the Analyzer.</p>
+    <p class="note"><b>NOTE</b> Power usage capture is not available in UIQ version. </span></p></td>
+  </tr>
+</table>
+<div class="step">
+  <h4>Setting a Tracing Option</h4>
+  <ol>
+    <li>Launch the Profiler application on the target device </li>
+<li>Open the Profiler options screen: </li>
+    <ul>
+  <li>S60 - Select the Tracing menu</li>
+  <li>UIQ - Select the Tracing Options menu</li>
+</ul>
+  <li>Set the desired option on or off</li>
+  <li>Exit the screen</li>
+  </ol>
+</div>
+<h5>Related references
+</h5>
+<ul>
+  <li><a href="prof_using.htm">Using the Profiler</a></li>
+</ul>
+<h5>Related tasks</h5>
+<ul>
+  <li><a href="advanced_options.htm">Setting Advanced Options</a></li>
+  <li><a href="output_settings.htm">Setting Output Settings </a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/reference/settings.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,188 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Profiler Settings File</title>
+<link href="../../book.css" rel="stylesheet" type="text/css">
+<meta http-equiv="Content-Type">
+<style type="text/css">
+<!--
+body,td,th {
+	color: #000000;
+}
+.style2 {color: #FFFFFF}
+-->
+</style>
+</head>
+<body>
+<h2>Profiler Settings File </h2>
+<p>The Profiler command-line  tool that executes on a target device reads its settings from a Profiler settings file. The GUI version creates a settings file from user imput, and then calls the command-line executable. The commands that a settings file can contain are shown in Table 1.</p>
+<h5>Syntax</h5>
+<ul>
+  <li>whitespaces at the start and end of lines are ignored</li>
+  <li>comments start with a semicolon (;) and the rest of the line is ignored</li>
+</ul>
+<h5>Limitations</h5>
+<ul>
+  <li>settings file contents are case sensitive </li>
+  <li>the settings file is limited to a maximum of 4096 characters</li>
+</ul>
+<p>The settings file contents must conform to the syntax described above. You can generate a valid configuration file by starting the Carbide.c++ Profiler GUI, selecting suitable settings, and then exiting the GUI. By default, the settings file created is called <span class="code">C:\Data\CProfSettings.txt</span>.</p>
+<h5>Table 1. Settings file options</h5>
+<table class="MsoNormalTable"
+ style="border: 1pt solid rgb(153, 153, 153); margin-left: 10pt; width: 69%;"
+ cellspacing="0" cellpadding="0" width="99%" border="1">
+  <tr>
+    <th width="13%" scope="col"><p class="style2">Option</p></th>
+    <th width="38%" scope="col">Syntax</th>
+    <th width="49%" scope="col"><span class="style2">Description</span></th>
+  </tr>
+  <tr>
+    <td><b>Profiler</b></td>
+    <td class="code" >version <i>version</i> </td>
+    <td >Restrict your settings file to a particular Profiler version. For example: <span class="code">version 1.60</span> </td>
+  </tr>
+  <tr>
+    <td rowspan="6"><b>Traces</b></td>
+    <td class="code" >button trace on|off </td>
+    <td >Enables or disables button capture trace. </td>
+  </tr>
+  <tr>
+    <td class="code" >call trace on|off </td>
+    <td >Enables or disables function call capture trace. </td>
+  </tr>
+  <tr>
+    <td class="code" >dynamic trace on|off </td>
+    <td >Enables or disables dynamic binary support trace. </td>
+  </tr>
+  <tr>
+    <td class="code">memory trace on|off </td>
+    <td >Enables or disables memory usage trace. </td>
+  </tr>
+  <tr>
+    <td class="code">power trace on|off </td>
+    <td >Enables or disables power usage trace. </td>
+  </tr>
+  <tr>
+    <td class="code">priority trace on|off </td>
+    <td >Enables or disables priority capture trace. </td>
+  </tr>
+  <tr>
+    <td rowspan="3"><b>Intervals</b></td>
+    <td class="code"><p>memorypriority interval <i>interval<br>
+    </i>prioritymemory interval <i>interval</i></p>
+      </td>
+    <td ><p>Set the interval between each check of memory usage and thread priorities.</p>
+    <p><i class="code"> interval</i> is the number of msecs, in decimal, between successive checks. 
+The minimum interval is 50 msec. </p>
+    </td>
+  </tr>
+  <tr>
+    <td class="code">addressthread interval <i>interval</i></td>
+    <td ><p>Set the interval between each check of the 					program counter address and current thread.</p>
+    <p><em> interval</em> is between 1 and 10000, and specifies 					the number of msecs between successive 					address and thread checks.</p></td>
+  </tr>
+  <tr>
+    <td class="code">power  interval <i>interval</i></td>
+    <td ><p>Set the interval between checks of power usage.</p>
+    <p><i class="code">interval</i> is the number of msecs, in decimal, between successive checks. The minimum interval is 250 msec. </p></td>
+  </tr>
+  <tr>
+    <td rowspan="3"><b>Files</b></td>
+    <td class="code"><p>output file phone|external<br>
+                        output debug</p>    </td>
+    <td >Set where output is written, either to a file on the phone, to a file on an external memory card, or to the debug port.
+    <p class="note"> <b>NOTE</b> On the phone, the file directory is <span class="code">C:\Data\PI</span>; on an external memory card, the file directory is <span class="code">E:\PI</span>.</p>    </td>
+  </tr>
+  <tr>  </tr>
+  <tr>
+    <td class="code">prefix <i>prefix</i> </td>
+    <td ><p>Set the output file prefix.</p>
+    <p><i class="code"> prefix </i> is a base file name of up to a 31 characters. It may contain at most one <span class="code">#</span> character. In the actual output file name, the Profiler will substitute an integer for the <span class="code">#</span>. </p></td>
+  </tr>
+  <tr>
+    <td rowspan="3"><b>SISA</b></td>
+    <td class="code">&nbsp;</td>
+    <td >If your code executes on a SISA single chip, then the Profiler needs to know whether a task is a Symbian OS task or an ISA OS task. The Profiler needs the addresses of the start and end of ISA code space, as well as where in ISA code space to find the start of ISA tasks.</td>
+  </tr>
+  <tr>
+    <td class="code">isa codespace <i>start end </i></td>
+    <td > <p>Change the ISA code space address range.</p>
+      <ul>
+        <li><span class="code"><i>start</i></span>- 
+
+
+a 32-bit hexadecimal number, optionally prefixed with &ldquo;0x &rdquo; or &ldquo;0X &rdquo;, for the start address of ISA code space.</li>
+        <li><span class="code"><i>end</i></span>-
+
+
+a 32-bit hexadecimal number, optionally prefixed with &ldquo;0x &rdquo; or &ldquo;0X &rdquo;, for the end address of ISA code space.</li>
+    </ul></td>
+  </tr>
+  <tr>
+    <td class="code">isa taskstart <i>start</i> <br>
+      isa taskoffset <i>offset</i> </td>
+    <td > <p>Change the address of the lowest addressed ISA task.</p>
+      <ul>
+        <li><span class="code"><i>start</i></span>- a 32-bit hexadecimal number, optionally prefixed with &ldquo;0x &rdquo; or &ldquo;0X &rdquo;, for the start of the lowest addressed ISA task.</li>
+        <li><span class="code"><i>offset</i></span>- a 32-bit hexadecimal number, optionally prefixed with &ldquo;0x &rdquo; or &ldquo;0X &rdquo;, for the offset to the lowest addressed ISA task from the start of ISA code space.</li>
+      </ul>      
+      <p class="note"> <b>NOTE</b> The ISA task address must be within the current ISA code space range. The sum of the ISA task offset plus the current ISA code space start must be less than or equal to the current ISA code space end. </p></td>
+  </tr>
+</table>
+<div class="step">
+  <h4>Default Settings File</h4>
+  <p class="listing">; Carbide.c++ Profiler Settings File<br>
+    <br>
+  ; Profiler version (use this command to restrict settings file to a particular version)<br>
+  version 1.60<br>
+  <br>
+  ; dynamic binary support on or off<br>
+  dynamic trace on<br>
+  <br>
+  ; function call capture on or off<br>
+  call trace off<br>
+  <br>
+  ; button press capture on or off<br>
+  button trace off<br>
+  <br>
+  ; memory usage capture on or off<br>
+  memory trace off<br>
+  <br>
+  ; thread priority capture on or off<br>
+  priority trace off<br>
+  <br>
+  ; power usage capture on or off<br>
+  power trace off<br>
+  <br>
+  ; &quot;output file phone&quot; writes *.dat file to phone<br>
+  ; &quot;output file external&quot; writes *.dat file to external memory<br>
+  ; &quot;output debug&quot; outputs to debug port<br>
+  output file external<br>
+  <br>
+  ; if writing to file, prefix of the *.dat file<br>
+  ; first '#' in the prefix is replaced with an integer<br>
+  prefix PI_#<br>
+  <br>
+  ; interval, in ms, at which memory usage and thread priorities are checked <br>
+  memorypriority interval 1000<br>
+  <br>
+  ; interval, in ms, at which power usage is checked <br>
+  power interval 250<br>
+  <br>
+  ; for ISA OS, the code space start and end addresses, separated by spaces or tabs <br>
+  ; addresses are in hex (optional prefix is 0x)<br>
+  isa codespace 0 0<br>
+  <br>
+  ; for ISA OS, the offset from the start of code space to the first ISA task <br>
+  ; address is in hex (optional prefix is 0x)<br>
+    isa taskoffset 0<br>
+  </p>
+</div>
+<p>addressthread interval &lt;number&gt;&quot;, where &lt;number&gt; is between 1 and 10000 inclusive</p>
+<h5>Other references</h5>
+<ul>
+  <li>   <a href="profiler/cmd_line_overview.htm"> Using the Command-line</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/release_notes.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,103 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="content-type"
+ content="text/html; charset=ISO-8859-1">
+<title>Release Notes</title>
+<link href="../book.css" rel="stylesheet" type="text/css">
+<style type="text/css">
+<!--
+.style2 {font-size: 13px}
+-->
+</style>
+</head>
+<body bgcolor="#FFFFFF">
+<h2>Performance Investigator Release Notes</h2>
+<ul>
+  <li><a href="#whatsNew">What's new </a></li>
+  <li><a href="#agent" >Target Performance Investigator Agent</a></li>
+  <li><a href="#pi_bugs">Fixed bugs and workarounds</a></li>
+  <li><a href="#support">Technical support</a></li>
+</ul>
+<h3><a name="whatsNew" id="whatsNew"></a>What's New </h3>
+<p>The Performance Investigator (PI) provides the means to measure program performance on a device running the Symbian OS. The new PI features provided with this release include:</p>
+<ul>
+  <li><b>Key Press profiles support</b> &#8212; PI now supports changing the key press map profile associated with a NPI file. Once changed using any of the pre-built profiles for TechView, S60, MOAP, UIQ, and PI pre-2.0, you can customize the key presses as desired to match new device functionality requirements.</li>
+  <li><b>Performance  improvements</b> &#8212; Several graphic routines have been rewritten to decrease the time it takes to draw and manipulate large data sets, making the process of changing graph sizes and scrolling them much more responsive. Also, the time to import a DAT file has been decreased. </li>
+  <li><b>Memory usage improvements</b> &#8212; Memory usage has has been significantly lowered. </li>
+</ul>
+<p><b>1.3.1</b></p>
+<ul>
+  <li><b>Copy tables and paste into spreadsheets</b> &#8212; copy displayed information in Threads, Binaries, Functions, and Function Calls tables to the clipboard and paste into a spreadsheet application, such as Microsoft Excel</li>
+  <li><b>Save tables</b> &#8212; save information displayed in tables into a comma delimited .csv file format that can be opened in a spreadsheet application</li>
+  <li><strong>Save more precise data in tables</strong> &#8212; save specific information about selected data within a table. For example, save samples for Threads that are checked in the Thread table or save the priority setting for Threads that are checked. You can also save data for one or more selected binaries, checked functions in Functions table, a single selected function in Function Calls table, checked memory samples, all button events for specified time interval, and all Power samples for time interval.</li>
+</ul>
+<p><b>1.5.0</b></p>
+<ul>
+  <li><b>PI Profiler 2.02 support added.</b> &#8212; Support for more detailed event based memory model added.</li>
+  <li><b>Touch Event support</b> &#8212; Button plug-in is now able to recognize touch events.</li>
+  <li><b>Some minor usability improvements and bug fixes</b></li>
+</ul>
+<h3><a name="agent"></a>Target Performance Investigator Profiler </h3>
+<ul>
+  <li>To produce a Profiler data file, you need to install one of these profiler agents: 
+    <ul>
+      <li><span class="code">Carbide Profiler 2.0 Installer</span> - for S60 3.0 (3rd Edition, initial release) devices</li>
+      <li><span class="code">Carbide Profiler 2.0 (Dual CPU) Installer </span>- for S60 3.1 (3rd Edition, Feature Pack 1) devices with dual CPUs, such as the N95 and N96</li>
+      <li><span class="code">Carbide Profiler 2.0 (Single CPU)Installer</span> - for S60 3.1 (3rd Edition, Feature Pack 1) devices with a single CPU, such as the E71, N76,  6290, N78 and 5320
+    </ul>
+    <p>Those files and others can be can be downloaded and installed using the <b>On-Device Connections &gt; New Connection Wizard &gt;</b><a href="PLUGINS_ROOT/com.nokia.carbide.cpp.doc.user/html/reference/trk/wnd_new_connection_wizard.htm"> Install remote agents</a> pane.</p>
+  </li>
+</ul>
+<h3><a name="pi_bugs"></a>Fixed bugs and workarounds</h3>
+<ul>
+  <li>Complete list of Carbide.c++ <a href="bugs_fixed.htm">bugs fixed</a></li>
+  <li>Workarounds for known issues:</li>
+</ul>
+<table width="100%"  border="0" cellpadding="2" cellspacing="0" >
+  <tr>
+    <th width="27%" scope="col">Item</th>
+    <th width="62%" scope="col">Explanation</th>
+  </tr>
+  <tr>
+    <td style="vertical-align: top;"><span class="style2">The Investigator menu item does not appear on the menu toolbar after an invalid format error occurs while opening an NPI file.</span></td>
+    <td style="vertical-align: top;"><p>Workaround:  To show the Investigator menu item, give focus to any non-NPI file or to any view other than the editor view (e.g., to the Symbian Project Navigator view).</p>
+    </td>
+  </tr>
+  <tr>
+    <td style="vertical-align: top;"><p>[3005] Profiling an application with all traces enabled and using the maximum sample rates (50ms and 250ms) may cause Profiler to exhibit strange behaviors</p></td>
+    <td style="vertical-align: top;"><p>Symptoms:</p>
+        <ul>
+          <li>S60 - You may get unusual errors such loss of icons in lists.</li>
+          <li>UIQ 3.0 - The generated .dat file is corrupted and when imported into the Analyzer can cause a crash.</li>
+        </ul>
+      <p>Workaround: Do not use maximum sampling rates, if all traces must be enabled, to avoid a high CPU overload condition. You can do this by either upping the time interval to 100ms/500ms or by disabling some traces.</p></td>
+  </tr>
+  <tr >
+    <td valign="top">[3049] Profiler sampling application closes when power usage sampling is requested on a device without power management</td>
+    <td valign="top"><p >On devices, such the N93, that do not have power management hardware, attempting to sample power usage will fail, and the application that samples, CProfApp, will close. </p>
+        <p >There is no workaround.</p></td>
+  </tr>
+  <tr>
+    <td style="vertical-align: top;">Carbide.c++ may run out of memory If you open or import several large profiler data files, the Java Virtual Machine may run out of memory.</td>
+    <td style="vertical-align: top;"><p>The workaround is to allocate more memory in the Carbide.c++.ini file (typically in the Carbide.c++ folder that contains Carbide.c++.exe). For example, to allocate 1GB, edit the Carbide.c++.ini to contain &ldquo;-Xmx1024m&rdquo; and then restart Carbide.c++.</p>
+        <p class="note"><b>NOTE</b> The eclipse.ini file was renamed Carbide.c++.ini for purposes of this product.</p></td>
+  </tr>
+  <tr>
+    <td style="vertical-align: top;">Host cannot import debug output from the target device You can send sampling data to the debug port of your device. However, this release cannot import the .base64 file that contains this data.</td>
+    <td style="vertical-align: top;">No workaround. </td>
+  </tr>
+</table>
+<h3><a name="support" id="support"></a>Technical support </h3>
+<p>The following support services are available:</p>
+<ul>
+  <li>Licensed technical support - submit service requests at <a href="https://pro.forum.nokia.com/loadServiceRequest.do">Forum Nokia Developer Programs</a> (<i>not available for Express users</i>) </li>
+  <li>License issues - send questions to <a href="mailto:license.carbide@nokia.com">license.carbide@nokia.com</a> to resolve any licensing issues </li>
+  <li>Visit the <a href="http://discussion.forum.nokia.com/forum/forumdisplay.php?s=&amp;forumid=95">Forum Nokia Developer Discussion Board</a> for lively Carbide.c++ discussions </li>
+  <li>Forum Nokia Wiki - visit <a href="http://wiki.forum.nokia.com/index.php/Carbide.c++">wiki.forum.nokia.com/index.php/Carbide.c++</a> for updated information, downloads and tips </li>
+  <li>Customer feedback - send your comments and suggestions to <a href="mailto:feedback.carbide@nokia.com">feedback.carbide@nokia.com</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/an_load_trace_files.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+  <meta http-equiv="Content-Type"
+ content="text/html; charset=iso-8859-1">
+  <title>Loading Sample Trace File for Analysis</title>
+  <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<h2>Importing Profiler Data Files</h2>
+<p>After capturing run-time information from your application on the
+target device, saving the profiler data file, and transfering the file
+to your PC, you must then import the profiler data (.dat) file.
+Importing the data file converts the file into a format that can be
+displayed by the analyzer (a .NPI file).</p>
+<p class="note"><strong>NOTE</strong> If a large .dat file is imported, the graph and table response time will slow down   until the  large NPI file is saved. Saving the NPI file will be performed in the background and  cannot be canceled.</p>
+<p>Importing a profiler data file will vary depending on if your
+application was built by Carbide.c++ or is a standalone application. To
+find the binaries in your application, the importer will need the *.pkg
+file created when your application was built, or you will need to list
+all application binaries. If you wish to analyze applications that
+execute at a static address, you will need the ROM image .symbol file
+that represents your phone. For dynamically loaded binaries stored in a
+phone&#8217;s ROFS or ROM, a .oby file can be used to describe and list
+binaries.</p>
+<p>Unless your application executes from a fixed address in phone
+memory (e.g., is part of the flashed phone image), enable dynamic
+binary support in the Profiler application when capturing your
+application data in a profiler data file.</p>
+<p>To import your profiler data file, perform the following steps.</p>
+<div class="step">
+<h4>Importing a Profiler Data File</h4>
+<ol>
+  <li><a name="Select_Performance_Investigator_Data"></a>Select
+Performance Investigator Data</li>
+  <p>Select <strong>File &gt; Import...</strong> from Carbide.c++ to
+display Import dialog box (Figure 1), and select Performance
+Investigator Data and click <strong>Next</strong>.</p>
+  <p align="center"><img src="images/importdatfile_step1.png"
+ width="470" height="550"></p>
+  <p align="center" class="figure">Figure 1. Carbide.c++ Import window </p>
+  <li><a name="Select_Profiler_Data_File"></a>Select Profiler Data File</li>
+  <p>Click <strong>Profiler Sample File...</strong>   and select the .dat file you transferred to your PC. The
+.dat file will be converted to a format displayable by the Carbide.c++
+analyzer and assigned the .npi extension (Figure 2). Click <strong>Next</strong>
+to continue.</p>
+  <p align="center"><img src="images/CB_import_step2.PNG" width="541"
+ height="385"></p>
+  <p align="center" class="figure">Figure 2. Select Profiler Data File</p>
+  <li><a name="Select_Known_Available_Information"></a>Select Known Available information </li>
+  <p align="left">Use the <strong>Available Information</strong> page to choose how the
+    profiler session is imported. The options include:</p>
+  <ul>
+    <li>Project importer &#8212; select this option if you have a Carbide project that has a PKG file or if you have a standalone PKG file (a PKG file that has absolute paths)</li>
+    <li>Project and ROM importer &#8212; select this option if you have both a Carbide project / package file for the profiled application as well as the ROM image symbol file and OBY file for the profiled device </li>
+    <li>ROM importer &#8212; select this option if you have  the ROM image symbol file and the OBY file for the profiled device</li>
+    <li>Unknown importer &#8212; select this option when you have neither a project or a ROM image </li>
+  </ul>
+  <p align="left">Click <strong>Next</strong> to continue.</p>
+  <p align="left" class="note"><strong>NOTE</strong> You can also click the Finish button (if enabled) to fill in the remaining wizard pages  with persisted values from the last .dat file import. In a new workspace or first time a workspace is used, you will need to define related information in remaining pages, since there is no previous import related to the new workspace. For a new imported .dat file, a new output file name will be generated base on this input file name (+ _digit + .npi).</p>
+  <p align="center"><img src="images/import_dat_file_step3.png"
+ width="629" height="705"></p>
+  <p align="center" class="figure">Figure 3. Enter known Available
+    Information</p>
+  <li><a name="ROM_files"></a>If  <strong>Both</strong> or <strong>the ROM image symbol file</strong> option is selected, the <strong>Select build files from ROM</strong> dialog appears. (optional) </li>
+  <p>Use the <strong><a href="../../reference/analyzer/import_rom_build_files.htm">Select build files from ROM</a></strong> dialog to select the build files that correspond to the ROM on the device. Start by selecting the SDK, then the ROM OBY file as well as the ROM symbol file. When done, clickc Next. </p>
+  <p align="center"><img src="../../images/wnd_import_rom_build_files.png" width="629" height="705"></p>
+  <p class="figure">Figure 4. Select build files from ROM dialog</p>
+  <li><a name="Select_Associated_Project_and_Package"></a>Select
+    Associated Project and Package (.pkg) File</li>
+  <p align="left">Use the Associated Project and Package (.pkg) File
+    page to select one or more projects to associate with the imported .dat
+    file as well as choosing its project configuration. Use the Add PKG
+    File control to add a .pkg file during the import operation or the
+    Remove PKG Files control to remove a PKG file from the imported
+    profiler session. Click <strong>Next</strong> to continue.</p>
+  <p align="center"><img src="images/import_dat_file_step4.png"
+ width="517" height="496"></p>
+  <p align="center" class="figure">Figure 5. Enter Associated Project
+    and Pakage (.pkg) File Information</p>
+  <li>Select Key Press Mapping Profile (requires button trace information)</li>
+  <p>If the DAT file has button trace enable, the <b>Select Key Press Mapping Profile</b> page appears. Select either a Carbide builtin Key Map Profile or user defined profile (if available) for the target device  key map. The  key map profile selected in the  <strong>Window &gt; Preferences &gt; Carbide.c++ &gt; Performance Investigator</strong> preference panel is highlighted as the suggested default. </p>
+  <p>A suggested key profile will also be selected if only one ROM kit/SDK is selected previously in this import wizard or the profile XML file in the ROM kit/SDK contains only   one key map profile.</p>
+  <p align="center"><img src="images/importdatfile_keyprofile.png" alt="keymap profile" width="541" height="516"></p>
+  <p align="center" class="figure">Figure 6. Select Key Press Mapping Profile </p>
+  <li><a name="Select_Output_File_and_Project"></a>Select Output File
+    and Project </li>
+
+  <p>Use the Output File and Project page to import the .dat file into
+an existing project or create a new empty project. In addition, use the
+Output file name field to specify the name output file name for the
+imported .dat file.</p>
+
+  <p align="center"><img src="images/import_dat_file_step5.png"
+ width="517" height="496"></p>
+  <p align="center" class="figure">Figure 7. Enter Output File and
+Project Information</p>
+  <li>Click Finish to create the *.npi file and open it with the
+Analyzer (Figure 8).</li>
+  <p align="center"><img src="images/importdatfile_step7.png"
+ width="708" height="653"></p>
+  <p align="center" class="figure">Figure 8. Performance Investigator
+Analyzer</p>
+</ol>
+</div>
+<p align="left"><strong>Related references</strong></p>
+<ul>
+  <li><a href="../../reference/analyzer/main_view.htm" align="left">Analyzer
+View</a></li>
+  <li><a href="key_profile_pref.htm">Key Press Profile</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/btn_press_change.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Changing Button Event Information</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Changing  Button Event Information</h2>
+<p>The default button event information includes the time when the event was recorded and a name for the button. The default display is shown in Figure 1. </p>
+<p align="center"><img src="images/pi_thread_load_01.png" width="550" height="125"></p>
+<p class="figure"><span class="figure">Figure 1.  Button event information shown in an Analyzer view</span></p>
+<p>To view additional information about the event, click a button event to see a tooltip with additional information about the event. </p>
+<p align="center"><img src="images/pi_thread_load_02.png" width="615" height="126"></p>
+<p class="figure"><span class="figure">Figure 2.  Click to show additional button event information in the tooltip</span></p>
+<p>To edit the button event information, double-click the button event marker to open the Button dialog to modifiy the information as shown in Figure 3. Edit the information in the dialog and press <b>OK</b> to save the changes to the NPI file. For example you can change the key label &quot;Down&quot; to a custom name for the button.</p>
+<p>Check &quot;Propagate to all labels of the same button&quot; to change all labels related to  the same key in the active NPI file.</p>
+<p align="center"><img src="images/pi_thread_load_03.png" width="252" height="215"></p>
+<p class="figure">Figure 3. Double-click a button event marker to edit the button   information</p>
+<p><strong>Related concepts </strong></p>
+<ul>
+  <li><a href="../../reference/profiler/prof_using.htm">Button Press Capture</a> </li>
+</ul>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="key_profile_pref.htm">Key Press Profile</a> </li>
+  <li><a href="../profiler/btn_press_enable.htm">Setting the Button Press Capture Option</a></li>
+  <li><a href="btn_press_show.htm">Showing/Hiding Button Events</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/btn_press_show.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Showing/Hiding Button Events</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Showing/Hiding  Button Events</h2>
+<p>Use the <b>Show Button Events</b> menu item to show or hide button event information in the Analyzer view. Button event information is displayed when a checkmark is present, or hidden if no checkmark appears on the menu item. </p>
+<p align="center"><img src="../../concepts/images/view_button_markers.png" width="816" height="154"></p>
+<p class="figure">Figure 1.  Button event information shown in an Analyzer view</p>
+<div class="step">
+  <h4>Changing the Button Event Visibility</h4>
+  <ul>
+    <li>Choose Investigator &gt; Show Button Events</li>
+	<p>The Analyzer updates its data display to include button event information and a checkmark appears next to the menu item. If a checkmark is already present, then the Analyzer view updates to hide button event information and the checkmark is removed.</p>
+  </ul>
+</div>
+<p><strong>Related concepts </strong></p>
+<ul>
+  <li><a href="../../reference/profiler/prof_using.htm">Button Press Capture</a> </li>
+</ul>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="../../reference/profiler/prof_using.htm">Using the Profiler</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/chng_graphcolor.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Changing the Color Representing a Thread, Binary, or Function</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Changing Graph Colors</h2>
+<p>Threads, binaries, and functions are assigned default colors when displayed on the graph. You can change the color representing an item. In either the Threads, Binaries, or Functions table, select one or more items and right-click to display context sensitive menu, as shown in Figure 1.</p>
+<p align="center"><img src="images/recolor_graphitem.png" width="788" height="271"></p>
+<p align="center" class="figure">Figure 1. Recoloring Graph Items</p>
+<p align="left">Select Recolor Highlighted Functions... to display a color swatch. Select a new color for selected item and click OK. The new color is visible in the table when the item is deselected, since the complete line appears grey when highlighted.</p>
+<p align="left" class="note"><strong>Note:</strong> The menu option will indicate Recolor Highlighted Functions, Recolor Highlighted Binaries, or Recolor Highlighted Threads depending on which table is currently active.</p>
+<p align="left">You can use the shift and control keys and the left mouse button to select multiple items. If multiple items are selected, then the swatch is displayed for each item selected. To select the same color for multiple selections, you will need to select the color and click OK for each swatch.</p>
+<p align="left" class="note"><strong>Note:</strong> Currently, any recoloring changes you make to binary and thread items will dirty the file, and will be saved to the .npi file when you save the file. Any recoloring changes you make to function items will not be saved. For function items, default colors are restored when the .npi file is reopened.<br>
+</p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step1.PNG has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step2.PNG has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step3.PNG has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step4.PNG has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step5.PNG has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/CB_import_step6.PNG has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/exportkeyprofile.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/import_dat_file_step3.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/import_dat_file_step4.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/import_dat_file_step5.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_keyprofile.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_selectkeymap.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step1.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step2.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step3.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step4.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step5.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step6.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importdatfile_step7.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importkeyprofile.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/importkeyprofileoverlap.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/menu_open_src_for_function.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/npi_prop.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_pref.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_pref_add.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_pref_edit.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_pref_edit_entry.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_pref_new.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_thread_load_01.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_thread_load_02.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/pi_thread_load_03.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/recolor_graphitem.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/set_threshold.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/start_end.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/switch_key_profile.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/images/time_interval.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/key_profile_exp.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<meta name="keywords" content="Performance Investigator">
+	<title>Performance Investigator Export Key Map Profile</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Export Key Map  Profile</h2>
+<p>Select <strong>Export Profile...</strong> to open a wizard dialog to export all user defined workspace profiles to a single XML File. <span style="vertical-align: top;">The Export function does not export builtin key profiles. By exporting all your profiles to one XML file you can provide a single XML file for a family of devices.</span></p>
+<p>Enter the full path and XML filename to store your key map profile(s) or select the <strong>Key Press Profile...</strong> button to browse to a folder and select or define a XML file. Click Finish to create the XML file. </p>
+<p align="center"><img src="images/exportkeyprofile.png" alt="Export profile" width="528" height="415"></p>
+<p align="center" class="figure">Figure 1. Key Press Profile Export Wizard</p>
+<p>&nbsp;</p>
+<p><strong>Related concepts </strong></p>
+<ul>
+  <li><a href="../../reference/profiler/prof_using.htm">Button Press Capture</a> </li>
+</ul>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="key_profile_pref.htm">Key Press Profile</a></li>
+  <li><a href="../profiler/btn_press_enable.htm">Setting the Button Press Capture Option</a></li>
+  <li><a href="btn_press_show.htm">Showing/Hiding Button Events</a></li>
+</ul>
+<p><strong>Related task</strong></p>
+<ul>
+  <li><a href="key_profile_switch.htm">Switch Key Map Profile</a></li>
+  <li><a href="btn_press_change.htm">Changing Button Event Information</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/key_profile_imp.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<meta name="keywords" content="Performance Investigator">
+	<title>Import Key Map Profile</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Import Key Map  Profile</h2>
+<p>Select <strong>Import Profile...</strong> to open a wizard dialog to enter or select a XML file containg key map entries. Enter the full path and filename or select the <strong>Key Press Profile...</strong> button to browse to a folder and select a XML key map file. </p>
+<p align="center"><img src="images/importkeyprofile.png" alt="Import key profile" width="514" height="415"></p>
+<p align="center" class="figure">Figure 1. Key Press Profile Import Wizard </p>
+<p><a name="overlap"></a>If the selected XML file contains  profiles for  existing workspace profiles, click Next to display a list of existing profiles that will be overwritten. Click Finish to import the profile(s). </p>
+<p align="center"><img src="images/importkeyprofileoverlap.png" alt="overwrite profiles" width="514" height="415"></p>
+<p align="center" class="figure">Figure 2. Profile Import - Profiles to be Overwritten</p>
+<p>&nbsp;</p>
+<p><strong>Related concepts </strong></p>
+<ul>
+  <li><a href="../../reference/profiler/prof_using.htm">Button Press Capture</a> </li>
+</ul>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="key_profile_pref.htm">Key Press Profile</a></li>
+  <li><a href="../profiler/btn_press_enable.htm">Setting the Button Press Capture Option</a></li>
+  <li><a href="btn_press_show.htm">Showing/Hiding Button Events</a></li>
+</ul>
+<p><strong>Related task</strong></p>
+<ul>
+  <li><a href="key_profile_switch.htm">Switch Key Map Profile</a></li>
+  <li><a href="btn_press_change.htm">Changing Button Event Information</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/key_profile_pref.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<meta name="keywords" content="Performance Investigator">
+	<title>Key Press Mapping</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Key Press Profile</h2>
+<p>If the Button Push Capture profile option was on during a profiling session, then Key presses are traced and saved in the profiler's .dat file as hex numbers. When a .dat file is imported, key press events are converted to key label strings and saved in the NPI file; and loses the original hex number.</p>
+<p>Key profiles vary depending on the SDK used and device targeted. Therefore, you can select the desired key profile for development.</p>
+<p class="note"><strong>NOTE</strong> The key profile selected in the Manage Profiles list serves as the suggested global default for profiler .dat files that are imported. When importing a .dat file (File &gt; Import &gt; Performance Investigator &gt; Performance Investigator Data) this default profile will be highlighted in the <strong>Select Key Press Mapping Profile</strong> wizard page.</p>
+<p>The key layout mapping  is maintained in a XML file. You can select from predefined built-in profiles or create your own key profile and save it to a XML file.</p>
+<p>A preference dialog is provided to create, delete, edit, import, or export a user defined workspace profile. Select <strong>Window &gt; Preferences &gt; Carbide.c++ &gt; Performance Investigator</strong> to open the Key Press Trace preference window.</p>
+<p align="center"><img src="images/pi_pref.png" alt="PI Preference" width="663" height="563"></p>
+<p align="center" class="figure">Figure 1. Key Profile Mapping </p>
+<p>In the Manage Profiles group you can select a user-defined or built-in key map profile for the device targeted by your current development. Developing for  different devices may require different key layouts. Built-in key profiles are displayed as Read only. New profiles you create can be edited.</p>
+<table width="100%"  border="0" cellpadding="2" cellspacing="0" >
+  <tr>
+    <th width="27%" scope="col">Item</th>
+    <th width="62%" scope="col">Explanation</th>
+  </tr>
+  <tr>
+    <td style="vertical-align: top;"><p><strong>Duplicate</strong></p></td>
+    <td style="vertical-align: top;"><p>Opens a Duplicate Profile dialog for you to define a name for a new key map profile and select a built-in profile to base it on.</p>    </td>
+  </tr>
+  <tr >
+    <td valign="top"><strong>Remove</strong></td>
+    <td valign="top"><p >This button is enabled when a user defined workspace profile is selected and will delete the currently selected user profile. A confirmation dialog will appear before removing the profile. </p>    </td>
+  </tr>
+  <tr>
+    <td style="vertical-align: top;"><strong>Edit...</strong></td>
+    <td style="vertical-align: top;"><p>This button is enabled when a user defined workspace profile is selected and will open an Editing Profile dialog. You can Add, Remove, and Edit key map entries for your profile. </p>    </td>
+  </tr>
+  <tr>
+    <td style="vertical-align: top;"><strong><a href="key_profile_imp.htm">Import Profiles...</a></strong></td>
+    <td style="vertical-align: top;">Opens a Key Press Profile Import Wizard to allow you to enter or select path and filename of a key profile XML file. If a profile exists in the workspace with the same name of a profile defined in imported XML file (identified by <strong>profileID</strong> argument) then a warning screen appears and lists the profile(s) that will be overwritten in the workspace.</td>
+  </tr>
+  <tr>
+    <td style="vertical-align: top;"><strong><a href="key_profile_exp.htm">Export Profiles...</a></strong></td>
+    <td style="vertical-align: top;">Opens a Key Press Profile Export Wizard to allow you to define or select a key profile XML file that will store user defined profiles. All user defined workspace profiles will be exported to one XML file. The Export function does not export built-in key profiles. By exporting all your profiles to one XML file you can provide a single XML file for a family of devices.</td>
+  </tr>
+  <tr>
+    <td style="vertical-align: top;"><strong>Restore Defaults</strong> </td>
+    <td style="vertical-align: top;">This button sets the profile to the Symbian TechView (carbide built-in) profile.</td>
+  </tr>
+</table>
+<p>&nbsp;</p>
+<p><a name="newkeyprof"></a>Click <strong>Duplicate</strong> to create a new profile. Enter a name for the profile and select a built-in profile to base your new profile on. After creating a new profile, it will appear in the Key Press Trace window. You can then click <strong>Edit...</strong> to make changes to the new profile.</p>
+<p align="center"><img src="images/pi_pref_new.png" alt="new key profile" width="366" height="198"></p>
+<p align="center" class="figure">Figure 2. Create New Profile</p>
+<p>&nbsp;</p>
+<p><a name="editkeymap"></a>Click <strong>Edit...</strong> to open a dialog for modifying key map entries for the profile. An Add, Remove, and Edit... button are provided to create a key mapping, delete a single selected entry, or modify a single key map entry. New or edited entries appear as Bold text in the table until you click the <strong>Save</strong> button. Click <strong>Save</strong> to accept all entries in the table and close the dialog box.</p>
+<p class="note"><strong>NOTE</strong> Once hex values have been entered, they cannot be edited. However, you can remove an entry and recreate it.</p>
+<p>Click <strong>Clear Profile</strong> if you want to clear all entries. A confirmation dialog will appear before erasing all profile entrys.</p>
+<p>Click the <strong>Remove</strong> button to delete a selected kep map entry from the profile.</p>
+<p align="center"><img src="images/pi_pref_edit.png" alt="Edit key profile" width="515" height="340"></p>
+<p align="center" class="figure">Figure 3. Key Map Editor</p>
+<p align="left"><a name="addkeymap"></a>Click the <strong>Add</strong> button in the <strong>Editing Profile <em>name</em></strong> dialog to open a dialog to define a key map entry. </p>
+<p align="center"><img src="images/pi_pref_add.png" alt="Add key map" width="293" height="186"></p>
+<p align="center" class="figure">Figure 4. Add Key Map Entry </p>
+<p align="left"><a name="editkeyentry"></a>Click the <strong>Edit...</strong> button in the <strong>Editing Profile <em>name</em></strong> dialog to open a dialog to edit a selected key map entry.</p>
+<p align="center"><img src="images/pi_pref_edit_entry.png" alt="Edit map entry" width="293" height="158"> </p>
+<p align="center" class="figure">Figure 5. Edit Key Map Entry </p>
+<p align="left">&nbsp;</p>
+<p><strong>Related concepts </strong></p>
+<ul>
+  <li><a href="../../reference/profiler/prof_using.htm">Button Press Capture</a> </li>
+</ul>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="../profiler/btn_press_enable.htm">Setting the Button Press Capture Option</a></li>
+  <li><a href="btn_press_show.htm">Showing/Hiding Button Events</a></li>
+</ul>
+<p><strong>Related task</strong></p>
+<ul>
+  <li><a href="key_profile_switch.htm">Switch Key Map Profile</a></li>
+  <li><a href="btn_press_change.htm">Changing Button Event Information</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/key_profile_select.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<meta name="keywords" content="Performance Investigator">
+	<title>Select Key Map Profile</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Select Key Map  Profile</h2>
+<p>When a profiler .dat file is imported and converted to a NPI file you may need to assign a key map profile. Select a key map profile that reflects your device either from:</p>
+<ul>
+  <li>A user defined key map profile (listed under workspace preferences if previously defined)</li>
+<li>A Carbide built-in that is related to an operating system SDK.</li>
+<li>A Recommended Profile, if listed.</li>
+</ul>
+<p>&nbsp;</p>
+<p align="center"><img src="images/importdatfile_selectkeymap.png" alt="switch key profile" width="541" height="485"></p>
+<p align="center" class="figure">Figure 1. Select Key Press Profile</p>
+<p>Select the desired key profile and click Next.</p>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="key_profile_pref.htm">Key Press Profile</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/key_profile_switch.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<meta name="keywords" content="Performance Investigator">
+	<title>Switch Key Map Profile</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Switch Key Map  Profile</h2>
+<p>When a profiler .dat file is imported and converted to a NPI file you can assign a key map profile. After importing a profiler .dat file,  the key map profile associated with a NPI file can be changed.</p>
+<p>To switch the key map profile, do either of the following:</p>
+<ul>
+  <li>Select an open NPI file to bring it into focus and select <strong>Investigator &gt; Apply New Key Press Profile</strong>.</li>
+  <li>Right-click on a NPI file in the Project Explorer view and select <strong>Switch Key Press Profile</strong>. (If NPI file is not open it will be opened.)</li>
+</ul>
+<p>The following dialog will appear.</p>
+<p align="center"><img src="images/switch_key_profile.png" alt="switch key profile" width="438" height="309"></p>
+<p align="center" class="figure">Figure 1. Switch Key Press Profile for Selected NPI File </p>
+<p>Select the desired key profile and click the <strong>Switch To New Profile</strong> button. The <strong>PI pre-2.0</strong> key map profile is used when a NPI file based on the older Carbide.c++ 1.3 format is opened.</p>
+<p>Check the option: <strong>Overwrite all modified key labels</strong> if you want all button events to be assigned the  labels defined in the selected profile, and which correspond with the same hex and TKeyCode values. For example, if the labels in the current profile and profile you are switching to have the same keycode, the labels are assumed to be unmodified. Any unmodified label will be changed to the label in the new  profile. Any modified label will remain unchanged if the check box is not  selected. So you must check this option to change all modified labels along with unmodified labels. </p>
+<p>Save the NPI file to accept the changes. You must close and reopen the file for the change to appear in the Current Profile field of the Switch Key Press Profile dialog.</p>
+<p>Right-click on a NPI file in the Project Explorer and select Properties to display key profile and other related profiler information.</p>
+<p align="center"><img src="images/npi_prop.png" alt="NPI properties" width="569" height="391"></p>
+<p align="center" class="figure">Figure 2. PI Property Information</p>
+<p><strong>Related concepts </strong></p>
+<ul>
+  <li><a href="../../reference/profiler/prof_using.htm">Button Press Capture</a> </li>
+</ul>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="key_profile_pref.htm">Key Press Profile</a></li>
+  <li><a href="../profiler/btn_press_enable.htm">Setting the Button Press Capture Option</a></li>
+  <li><a href="btn_press_show.htm">Showing/Hiding Button Events</a></li>
+</ul>
+<p><strong>Related task</strong></p>
+<ul>
+  <li><a href="btn_press_change.htm">Changing Button Event Information</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/set_thresholds.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Change Threshold Limits</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Setting Thresholds For Threads, Binaries, and Functions</h2>
+<p>Thresholds can be set to group threads, binaries, and/or functions according to their amount of CPU usage into a pile you do not care about. For example, you can specify all functions using less than 5 percent of the CPU load to be ignored. Then you can focus on other functions in the graph that occupy more than 5 percent of the CPU.</p>
+<p class="note"><strong>Note:</strong> You must select a time interval on the graph to view statistics for an item; such as the percent of CPU usage and number of times sampled.</p>
+<p align="center" class="figure"><img src="images/set_threshold.png" width="578" height="221"></p>
+<p align="center" class="figure">Figure 1. Set Thresholds Dialog Box</p>
+<h5>Table 1. <span class="figure">Set Thresholds</span> options</h5>
+<table width="90%" border="0" cellpadding="2" cellspacing="0" >
+  <tr>
+    <th width="273" scope="col">Options</th>
+    <th width="520" scope="col">Description</th>
+  </tr>
+  <tr>
+    <td><b>Average load &lt;</b></td>
+    <td>Enter a percentage between .10 and 100 percent of the CPU load </td>
+  </tr>
+  <tr>
+    <td><b>Total samples </b></td>
+    <td>Enter number of samples to use as threshold. All items sampled less than the number specified will be grouped into one item. The Average load will be calculated based on the Total samples threshold and number of total samples for the item: threads, binaries, or functions.</td>
+  </tr>
+  <tr>
+    <td><b>Use thread threshold for binaries and functions also </b></td>
+    <td>Check this box to apply the thread threshold value to binaries and functions.</td>
+  </tr>
+</table>
+<p><strong>Related references</strong></p>
+<p><a href="../../reference/analyzer/threshold.htm"> Threshold Limits for Traced Data</a></p>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/source_lookup.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Using Source Lookup</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Using Source Lookup </h2>
+<p>Use<b> Open Source for Function</b> to examine the source of the selected function. </p>
+<p class="note"><b>NOTE</b> The project must be indexed for Source Lookup to operate. See the project&#8217;s Properties &gt; C/C++ Indexer panel. </p>
+<p align="center"><img src="images/menu_open_src_for_function.png" width="475" height="249"></p>
+<p class="figure">Figure 1. Select Source Lookup from the context menu </p>
+<div class="step">
+  <h4>Viewing the Source of a Function </h4>
+  <ul>
+    <li>Right-click the function, select Open Source for Function </li>
+	<p>A source lookup is performed on the project. If a single source is found it is displayed in an editor view. If more than one source is found, a list of sources is presented to choose from. </p>
+  </ul>
+</div>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/analyser/time_interval.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Setting the Time Interval</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Setting the Time Interval</h2>
+<div class="step">
+  <ol>
+    <li>Click and drag your mouse across the graph to select a time period</li>
+  <p class="note"><strong>NOTE</strong> You may have to slightly move your mouse back and forth at the end of the graph to continue scrolling.</p>
+  <li>Click the Zoom to Selected Time Interval icon <img src="../../reference/analyzer/images/icon_zoom_to_selected_int.png" width="18" height="16" align="absmiddle"></li>
+  </ol>
+  <blockquote>
+    <p>OR</p>
+</blockquote>
+  <ol>
+    <li>Select the Start - End icon <img src="images/start_end.png" width="16" height="17" align="absmiddle">to open the Select Time Interval dialog</li>
+    <li>Enter a start and end time in seconds and click OK</li>
+  <p>The display graph updates to show the selected start and end times.</p>
+</ol>
+</div>
+<p>You can select time in any of the graphs (CPU load, power, memory) or enter values in the  Select Time Interval dialog. When clicking and dragging inside the graph, if you start inside the graph and then drag outside the graph, the end time will be set to the maximum sample time. If you start dragging outside the graph and end the drag operation inside the graph, then the end time is set to the maximum sample time. If you start and end dragging from outside the graph, then the start time and end time are set to zero (0); no samples are chosen.</p>
+<p>In the Select Time Interval dialog, a message in black stating &quot;Start time and end time maximum is XX.XXX seconds&quot; is displayed when legitimate start and end times are entered, and     the OK button is enabled.</p>
+<p>If the End time is less than or equal to the Start time, the dialog box will contain a message in red stating that &quot;End time must be greater than start time&quot;. The OK button will be disabled. If start time or end time is greater than the maximum sample time, the dialog box contains a message in red that states the maximum time. The OK button is disabled.</p>
+<p align="center"><img src="images/time_interval.png" alt="time interval" width="309" height="155"></p>
+<p>If start time or end time is less than zero or contains a bad float number format, the dialog box will contain a message in red stating that &quot;Start time and end time must be positive values&quot;.</p>
+<h5>Related references</h5>
+<ul>
+  <li><a href="../../reference/analyzer/GUI_tour.htm">Analyzer GUI Controls</a></li>
+<li><a href="../../reference/analyzer/context_menu.htm">Context Menu Options</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/images/wizard_new_connection.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/images/wnd_bluetooth_config.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/images/wnd_bluetooth_config_services.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/bluetooth_connection.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Bluetooth Connection</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+    <style type="text/css">
+<!--
+.style1 {font-family: "Courier New", Courier, mono}
+-->
+    </style>
+</head>
+
+<body>
+<h2>Connecting by Bluetooth</h2>
+<p>The Profiler agent can be wirelessly transferred to and from Bluetooth enabled Nokia S60 devices. Our overall goal is to:</p>
+<ol>
+  <li>Enable Bluetooth devices on the target device and PC.</li>
+  <li>Allow the target’s Bluetooth device to find and connect to the PC’s Bluetooth device, and vice versa.</li>
+  <li>Transfer the Performance Investigator Profiler .sisx files to the target device, and install them.</li>
+  <li>After profiling your application, transfer, import and analyze the profiler (.dat) data file.</li>
+</ol>
+<p>To enable communication with a Bluetooth device, a connection must be established between the PC and the device. Follow the steps below for a typical Bluetooth connection with a Bluetooth enabled device.</p>
+<p class="note">This example shows how to setup a Bluetooth connection on a PC running Windows XP SP2. The actions to setup Bluetooth connections may be different on your version of Windows. Refer to the OS documentation and your Bluetooth installation for information on configuring Bluetooth connections.</p>
+<div class="step">
+  <h4>Steps to Setup a Bluetooth Connection</h4>
+    <ol>
+      <li>
+      Enable Bluetooth on the Symbian OS target device</li>
+      <p> For example, select the Communications application on the device, then select Bluetooth. </p>
+      <li>On your PC, start the Bluetooth device</li>
+      <p>For example,  right-click the Bluetooth icon in your task bar and select <span class="style1">Start the Bluetooth device</span>. </p>
+      <li>Open your Bluetooth Configuration window</li>
+      <p> For example, select Bluetooth configuration from the control panel or double-click My Bluetooth Places icon on your Desktop.</p>
+      <li>Click the Accessibility tab and verify the following settings (Figure 1)</li>
+      <p>Check the option <span class="style1">Let other Bluetooth devices discover this computer</span>. Set the option <span class="style1">Allow</span> to <span class="style1">All Devices</span>.<br>
+        Click OK. 
+      <p align="center"><img src="../images/wnd_bluetooth_config.png" width="462" height="438"></p>
+      <p class="figure">Figure 1. Bluetooth Configuration window's Accessibility panel</p>
+      <li>
+        <p>Search for Devices in Range </p>
+      </li>
+     <p>Under Bluetooth Tasks select <span class="style1">Search for devices in range</span> (Figure 2).<br>
+          After devices are found, select your target device, right-click and select <span class="style1">Pair Device</span>.</p>
+      <p align="center"><img src="images/srch_devices.png" width="387" height="250"> </p>
+      <p align="center" class="figure">Figure 2. Bluetooth Devices in Range </p>
+      <li>Enter Unique Code</li>
+    
+        <p>Enter a unique Bluetooth PIN code. It can be any number you choose, such as 123456.</p>
+   
+      <li>Enter code on Target Device</li>
+        <p>The target device will prompt you to enter the same code. Enter code to connect devices.</p>
+      <li>
+        List Functions      </li>
+      <p>On your PC, double-click your device to list available functions.</p>
+      <li>
+      Run File Transfer Program      </li>
+       <p>Double-click <span class="style1">OBEX File Transfer</span> to display <span class="code">C:</span> drive folder on target device.</p>
+      <li>Browse to Transfer Location on Target Device</li>
+        <p> Browse to the location on the device to transfer Profiler agent SISX file. For example, create a folder on the device called <span class="code">C:\Data\CarbidePI Installer</span>.</p>
+      <li>
+       Transfer Performance Investigator .sisx files to Target Device</li>
+      <p>Locate the Profiler agent SISX file on your PC that you saved from  the <b><a href="prof_installation.htm">Install remote agents</a></b> pane in the <b>On-device Connections</b> wizard and drag it to the Window representing the <span class="code">C:\Data\CarbidePI Installer</span> folder on the device. Leave this window open for transferring your profiler data file.</p>
+    </ol>
+</div>
+<div class="step">
+      <h4>Transfering a DAT File</h4>
+      <p>Once you've collected some data from a profiler run, you'll need to transfer the DAT file back to your PC for analysis.</p>
+      <ol>
+      <li>Connect to the Device using Bluetooth (as described above)</li>
+      <li>Locate Profiler Data File</li>
+      <p>On your PC, in your Bluetooth connection window (used previously) navigate to <span class="code">C:\root</span> folder on phone and select <strong>View &gt; Refresh</strong> to update the list of files.</p>
+      <li>Transfer Profiler Data File to PC</li>
+    <p>Your new profiler data file should be listed. Drag this file to your PC.</p>
+    </ol>
+</div>
+<p>After you have the profiler data file on your PC you can import it into Carbide.c++ to analyze the captured data.</p>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="prof_installation.htm">Installing the Profiler on the Target Device</a></li>
+  <li><a href="../../reference/profiler/prof_using.htm">Using the Profiler</a></li>
+  <li><a href="../analyser/an_load_trace_files.htm">Importing Profiler Data File for Analysis</a></li>
+  <li><a href="serial_connection.htm">Connecting by Serial Interface </a></li>
+  <li><a href="usb_connection.htm">Connecting by USB</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/btn_press_enable.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Setting the Button Press Capture Option</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Setting the Button Press Capture Option</h2>
+<p>Use the <b>Button press capture</b> option in the Tracing menu of the Profiler application to set whether button press information is collected during a trace run of an application. When enabled (On), button press events are stored in the profiling data file. If disabled (Off), then no button press events are recorded. </p>
+<p align="center"><img src="../../reference/profiler/images/profiler_button_press_option.png" width="264" height="312"></p>
+<p class="figure">Figure 1. The Button press capture option in the Profiler Tracing menu </p>
+<div class="step">
+  <h4>Changing the Button Press Capture Option</h4>
+  <ol>
+    <li>Open the Profiler application on the target device </li>
+  <li>In  Tracing  menu, set the Button Press Capture option on or off as desired</li>
+</ol>
+</div>
+<p><strong>Related concepts </strong></p>
+<ul>
+  <li><a href="../../reference/profiler/prof_using.htm">Button Press Capture</a> </li>
+</ul>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="../../reference/profiler/prof_using.htm">Using the Profiler</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/exp_keyprofile.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/exp_keyprofile2.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/imp_keyprofile.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/imp_keyprofile2.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/imp_keyprofile3.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/images/srch_devices.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/key_profile_exp.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+  <meta http-equiv="Content-Type"
+ content="text/html; charset=iso-8859-1">
+  <title>Exporting Key Map Profile</title>
+  <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<h2>Exporting Key Map Profile</h2>
+<p>Key map profiles corresponding to specific target devices can be imported or exported. The profiles can also be selected, created, modified, and imported/exported in the Performance Investigator preference panel located in  <strong>Window &gt; Preferences &gt; Carbide.c++ &gt; Performance Investigator</strong>. </p>
+<p>To export your key map profile, perform the following steps.</p>
+<div class="step">
+<h4>Exporting a Key Map Profile</h4>
+<ol>
+  <li>Select
+Performance Investigator Key Press Profile</li>
+  <p>Select <strong>File &gt; Export...</strong> from Carbide.c++ to
+display Export dialog box (Figure 1), and select Performance
+Investigator Key Press Profile and click <strong>Next</strong>.</p>
+  <p align="center"><img src="images/exp_keyprofile.png" alt="Export key profile" width="470" height="465"></p>
+  <p align="center" class="figure">Figure 1. Carbide.c++ Export window </p>
+  <li>Select or Define Key Profile XML File</li>
+  <p>Enter a path and xml filename to store all workspace key map profiles or click <strong>Key Press Profile...</strong>  and select a key map profile (.xml) file for the device(s) being targeted.   Click <strong>Finish</strong>
+to export all workspace profiles to the xml file.</p>
+  <p align="center"><img src="images/exp_keyprofile2.png" alt="Define profile export file" width="470" height="465"></p>
+  <p align="center" class="figure">Figure 2. Select or Define Profile XML File</p>
+  </ol>
+</div>
+<p align="left"><strong>Related references</strong></p>
+<ul>
+  <li><a href="key_profile_imp.htm" align="left">Importing a Key Map Profile </a></li>
+  <li><a href="../analyser/key_profile_pref.htm">Key Press Profile</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/key_profile_imp.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+  <meta http-equiv="Content-Type"
+ content="text/html; charset=iso-8859-1">
+  <title>Importing Key Map Profile</title>
+  <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<h2>Importing Key Map Profile</h2>
+<p>Key map profiles corresponding to specific target devices can be imported or exported. The profiles can also be selected, created, modified, and imported/exported in the Performance Investigator preference panel located in  <strong>Window &gt; Preferences &gt; Carbide.c++ &gt; Performance Investigator</strong>. </p>
+<p>To import your key map profile, perform the following steps.</p>
+<div class="step">
+<h4>Importing a Key Map Profile</h4>
+<ol>
+  <li>Select
+Performance Investigator Key Press Profile</li>
+  <p>Select <strong>File &gt; Import...</strong> from Carbide.c++ to
+display Import dialog box (Figure 1), and select Performance
+Investigator Key Press Profile and click <strong>Next</strong>.</p>
+  <p align="center"><img src="images/imp_keyprofile.png" alt="import key profile" width="470" height="550"></p>
+  <p align="center" class="figure">Figure 1. Carbide.c++ Import window </p>
+  <li>Select Key Profile XML File</li>
+  <p>Click <strong>Key Press Profile...</strong>  and browse to and select a key map profile (.xml) file for the device(s) being targeted.   Click <strong>Next</strong>
+to continue.</p>
+  <p align="center"><img src="images/imp_keyprofile2.png" alt="key profile xml" width="470" height="422"></p>
+  <p align="center" class="figure">Figure 2. Select Profile XML File</p>
+  <li>View List of Profiles</li>
+  <p align="left">If the
+XML file contains mappings for one or more workspace profiles a <strong>Profile(s) Overwrite</strong> page will appear (Figure 3). Click <strong>Finish</strong> to import the workspace key map profile(s). </p>
+  <p align="center" class="figure"><img src="images/imp_keyprofile3.png" alt="Existing key profiles" width="462" height="358"></p>
+  <p align="center" class="figure">Figure 3. Existing Key Profiles in Selected XML File</p>
+  </ol>
+</div>
+<p align="left"><strong>Related references</strong></p>
+<ul>
+  <li><a href="key_profile_exp.htm" align="left">Exporting Key Map Profile</a></li>
+  <li><a href="../analyser/key_profile_pref.htm">Key Press Profile</a> </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/prof_installation.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Performance Investigator Profiler Installation</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Installing the Profiler on the Target Device</h2>
+<p> The Performance Investigator Profiler consists of  self installing Symbian executable files (.sisx) to be installed on the handheld device.The Profiler agent  can be downloaded and installed using the <b><a href="PLUGINS_ROOT/com.nokia.carbide.cpp.doc.user/html/reference/trk/wnd_new_conn_wiz_edit.htm">Install remote agents</a></b> pane in the <b>On-device Connections</b> wizard.</p>
+<p class="note"><b>NOTE</b> Nokia PC Suite is used by the Install remote agents pane to transfer the selected agent to the  device. Nokia <a href="http://www.nokia.com/pcsuite" title="PC Suite" target="_blank">PC Suite</a> is a free download from the Nokia website and can also be used to transfer, store, synchronize, and edit Nokia phone files with a compatible PC.</p>
+<p align="center"><img src="../images/wizard_new_connection.png" width="456" height="554"></p>
+<p class="figure">Figure 1 - New Connection window</p>
+<div class="step">  
+  <h4>Installing the Carbide Profiler
+  </h4>
+  <ol>
+    <li>Click <b>Help &gt; On-Device Connections...</b> to open the <b>New Connection</b> wizard</li>
+    <li>Enter a <b>Connection name</b>, and choose a<b> Connection type</b> from the connection types listed</li>
+    <li>Click <b>Next</b></li>
+    <li>Click the <b>Install remote agent</b> tab (Figure 1)</li>
+    <li>Select the type and version of <b>Carbide Profiler</b> to install</li>
+    <li>Click <b>Install</b></li>
+    <li>Click <b>Finish</b> once installation is complete</li>
+    </ol>
+</div>
+<p>Alternately, save the Profiler agent  to your PC by selecting a version of the Carbide Profiler and clicking <b>Save</b>. Once stored on your PC, you can connect and transfer the agent to the target device using one of the following transfer methods:</p>
+<ul>
+  <li><a href="bluetooth_connection.htm">Connecting by Bluetooth</a></li>
+  <li><a href="usb_connection.htm">Connecting by USB </a></li>
+  <li><a href="serial_connection.htm">Connecting by Serial Interface</a></li>
+</ul>
+<h5>Related Task</h5>
+<ul>
+  <li><a href="../../reference/profiler/prof_using.htm">Using the Profiler</a>  </li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/serial_connection.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Serial Connection</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Connecting by Serial Interface</h2>
+<p>If your  Nokia S60 handheld device supports a serial cable connection, you can use this method to transfer the Performance Investigator Profiler self installing Symbian executable files (.sisx) to the target device and transfer the profiler data file (.dat) to your PC. The Profiler agent can be downloaded and installed using the <b><a href="prof_installation.htm">Install remote agents</a></b> pane in the <b>On-device Connections</b> wizard.</p>
+<p><strong>Related Information</strong></p>
+<ul>
+  <li><a href="../../reference/profiler/prof_using.htm">Using the Profiler</a> </li>
+  <li><a href="../analyser/an_load_trace_files.htm">Importing Profiler Data File for Analysis </a></li>
+  <li><a href="bluetooth_connection.htm">Connecting by Bluetooth</a></li>
+  <li><a href="usb_connection.htm">Connecting by USB</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/html/tasks/profiler/usb_connection.htm	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>USB Connection</title>
+    <link href="../../../book.css" rel="stylesheet" type="text/css">
+</head>
+
+<body>
+<h2>Connecting by USB</h2>
+<p>Some Symbian OS devices support a USB cable connection between the device and your PC for transferring files. You can use this method to transfer the Profiler self installing Symbian executable files (.sisx) to the target device and transfer the profiler data file (.dat) to your PC.  The Profiler agent can be downloaded and installed using the <b><a href="prof_installation.htm">Install remote agents</a></b> pane in the <b>On-device Connections</b> wizard.</p>
+<p>To enable communication with a USB device, a connection must be established between the PC and the device. One of the following USB connectivity cables is required to physically connect the PC to the device:</p>
+<ul>
+  <li>DKU-2</li>
+<li>CA-53 </li>
+</ul>
+<h4 class="substep">Steps to Setup a USB Connection for On-target Profiling</h4>
+  <ol>
+    <li>
+      <p><strong>Connect the USB cable to your PC and then the target device
+      </strong></p>
+      <p>The USB Mode list appears on the target device.</p>
+    </li>
+  <li>  <strong>Select File Transfer mode from the USB Mode list and press the OK soft key  
+    </strong>
+    <p>The &quot;While USB file transfer mode is in use, the device will be offline&quot; message appears.</p>
+  </li>
+    <li><strong>Press the OK soft key  
+      </strong>
+      <p>The &quot;USB file transfer connection active&quot; message appears, and the PC displays the folder containing the device's MMC card files and folders.</p>
+    </li>
+  <li><strong>Copy the SISX files to the MMC card</strong>
+    <p>Copy and paste the .sisx files to the MMC card.</p>
+  </li>
+  <li><strong>Disconnect the USB device from the PC
+    </strong>
+    <p>Use Window's &quot;Safely Remove Hardware&quot; feature to disconnect the USB device from the PC.</p>
+  </li>
+  <li><strong>  Remove the USB cable from the PC and the phone</strong></li>
+    </ol>
+  <blockquote>
+    <p>The &quot;You can now safely remove the USB cable&quot; message appears on the device. Press the OK soft key and detach the cable.</p>
+    </blockquote>
+<p><strong>Related references</strong></p>
+<ul>
+  <li><a href="prof_installation.htm">Installing the Profiler on the Target Device</a></li>
+  <li><a href="../../reference/profiler/prof_using.htm">Using the Profiler</a> </li>
+  <li><a href="../analyser/an_load_trace_files.htm">Importing Profiler Data File for Analysis </a></li>
+  <li><a href="bluetooth_connection.htm">Connecting by Bluetooth</a></li>
+  <li><a href="serial_connection.htm">Connecting by Serial Interface</a></li>
+</ul>
+<div id="footer">Copyright &copy; 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/intro/overviewProfilerExtContent.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<introContent>
+
+	 	<extensionContent 
+		  id="com.nokia.carbide.cpp.pi.doc.user-overview" 
+		  style="pi.css" 
+		  alt-style="pi.properties" 
+		  name="Performance Investigator" 
+		  path="overview/@">
+		  
+		<group style-id="content-group" id="pi">
+       		<link 
+				   label="Performance Investigator" 
+				   url="http://org.eclipse.ui.intro/showHelpTopic?id=/com.nokia.carbide.cpp.pi.doc.user/html/Getting_Started/GS_index.htm" 
+				   id="pi-app" 
+				   style-id="content-link">
+				   <text>Get started using the Performance Investigator feature</text>
+       		</link>
+       	</group>
+  	</extensionContent>
+
+</introContent>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/intro/pi.css	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2 @@
+a#pi-app img { background-image : url(../html/images/icons/pi.gif); }
+a#pi-app:hover img { background-image : url(../html/images/icons/pi_hov.gif); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/intro/pi.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,6 @@
+
+whatsnew.pi-app = html/images/icons/pi.gif
+whatsnew.pi-app:hover = html/images/icons/pi_hov.gif
+
+overview.pi-app = html/images/icons/pi.gif
+overview.pi-app:hover = html/images/icons/pi_hov.gif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/intro/tutorialsProfilerExtContent.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<introContent>
+  <!-- Extension to the SDK Tutorial Page. -->
+	<extensionContent alt-style="css/swt.properties" style="css/tutorials.css" path="tutorials/page-content/carbideAnchor">
+		  
+        <group id="tutorials-group" label="Performance Investigator tutorials" style-id="tutorials-group" >
+			
+		<link label="PI tutorial#1" url="http://org.eclipse.ui.intro/showHelpTopic?id=/com.nokia.carbide.cpp.pi.doc.user/tutorials/piTutorial.html" id="carbideapp" style-id="tutorials-link" >
+			<text>Create a birthday tracking program that demonstrates S60 UI, proper UI and data separation, and simple persistent storage.</text>
+		</link>
+
+		</group>
+		
+	</extensionContent>
+
+</introContent>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/intro/whatsnewProfilerExtContent.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<introContent>
+	
+  	<extensionContent 
+		  id="com.nokia.carbide.cpp.pi.doc.user-whatsnew" 
+		  style="pi.css" 
+		  alt-style="pi.properties" 
+		  name="Performance Investigator Release Notes" 
+		  path="whatsnew/@">
+		<group style-id="content-group" id="pi">
+       		<link 
+				   label="Performance Investigator Release Notes" 
+ 				   url="http://org.eclipse.ui.intro/showHelpTopic?id=/com.nokia.carbide.cpp.pi.doc.user/html/release_notes.htm" 
+				   id="pi-app" 
+				   style-id="content-link">
+          		<text>Read these important engineering notes for the Performance Investigator feature</text>
+       		</link>
+       	</group>
+  	</extensionContent>
+
+</introContent>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+   <extension
+         point="org.eclipse.help.toc">
+      <toc
+            file="tocPI.xml"
+            primary="true"/>
+      <toc
+            file="tocConcepts.xml"
+            primary="false"/>
+      <toc
+            file="tocProfiler.xml"
+            primary="false"/>
+      <toc
+            file="tocAnalyzer.xml"
+            primary="false"/>
+	   
+	  <!-- Moved release notice to manual (20080517)
+      <toc
+            file="tocRelease.xml"
+            primary="false"/>
+	  -->
+	   
+ 		<index path="index" />
+
+   </extension>
+
+
+	<!-- Performance Investigator cheatsheets extension -->
+	
+   <extension
+         point="org.eclipse.ui.cheatsheets.cheatSheetContent">
+      <category
+            id="com.nokia.carbide.cpp.pi.cheatsheets"
+            name="Carbide.c++ Performance Investigator" />
+      <cheatsheet
+            category="com.nokia.carbide.cpp.pi.cheatsheets"
+            contentFile="html/cheatsheets/getStarted_pi_cs.xml"
+            id="com.nokia.carbide.cpp.pi.doc.user.getStarted"
+            name="Performance Investigator Setup"/>
+      <cheatsheet
+            category="com.nokia.carbide.cpp.pi.cheatsheets"
+            composite="false"
+            contentFile="$nl$/html/cheatsheets/getStarted_pi_cs.xml"
+            id="com.nokia.carbide.cpp.pi.help.cheatsheet919016247"
+            name="Performance Investigator Setup">
+      </cheatsheet>
+   </extension>
+
+	
+	<!-- Add PI info to Welcome pages to extend content -->
+	
+	<extension
+		point="org.eclipse.ui.intro.configExtension">
+		
+		<configExtension
+			configId="org.eclipse.ui.intro.universalConfig" 
+			content="intro/overviewProfilerExtContent.xml" /> 
+		 
+		<configExtension
+			configId="org.eclipse.ui.intro.universalConfig"
+			content="intro/whatsnewProfilerExtContent.xml" /> 
+		 
+<!--		<configExtension
+			configId="com.nokia.carbide.cpp.introConfig"
+			content="intro/tutorialsProfilerExtContent.xml" /> 
+-->
+	</extension>
+
+	
+	<!-- CONTEXT IDs for CONTEXTUAL HELP in windows, dialogs, and views -->
+	
+	<extension point="org.eclipse.help.contexts" >
+
+       <!-- PI THREADS/BINARY/FN TABS -->
+       <contexts file="html/context_help/com_nokia_carbide_pi_address.xml"
+       		plugin="com.nokia.carbide.cpp.pi.address" />
+
+       <!-- PI BUTTON TABS -->
+       <contexts file="html/context_help/com_nokia_carbide_pi_button.xml"
+       		plugin="com.nokia.carbide.cpp.pi.button" />
+
+       <!-- PI FN CALLS TAB -->
+       <contexts file="html/context_help/com_nokia_carbide_pi_call.xml" 
+       		plugin="com.nokia.carbide.cpp.pi.call" />
+
+       <!-- PI IMPORT WIZARD -->
+       <contexts file="html/context_help/com_nokia_carbide_pi_wizards.xml" 
+       		plugin="com.nokia.carbide.cpp.pi.wizards" />
+
+       <!-- ECLIPSE NEW/IMPORT/EXPORT WIZARDS and PREF PANELS HELP  -->
+       <contexts file="html/context_help/org_eclipse_ui.xml"
+       		plugin="org.eclipse.ui" />
+
+	</extension>
+
+	
+	<!-- KEYWORD INDEX ADDITION -->
+	
+	 <extension
+	       point="org.eclipse.help.index">
+	    <index file="html/index.xml"/>
+	 </extension>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/tocAnalyzer.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<toc label="Analyzer" href="html/reference/analyzer/an_use_case_features.htm" >
+	
+	<topic label="Analyzer Overview" 						href="html/reference/analyzer/analyser.htm" >
+		<topic label="Performance Investigator Analyzer" 	href="html/concepts/analyser.htm" />
+		<topic label="Basic Operation"  					href="html/concepts/basic_operation.htm" />
+		<topic label="Controls" 							href="html/reference/analyzer/GUI_tour.htm" />
+		<topic label="Graph views" 							href="html/reference/analyzer/main_view.htm" >
+			<topic label="Thread Load"    					href="html/reference/analyzer/thread_load.htm" />
+			<topic label="Binary Load"    					href="html/reference/analyzer/binary_load.htm" />
+			<topic label="Function Load"  					href="html/reference/analyzer/function_load.htm" />
+			<topic label="Function Calls"  					href="html/reference/analyzer/function_calls.htm" />
+		</topic>
+		<topic label="Threshold Limits for Traced Data"  	href="html/reference/analyzer/threshold.htm" />
+	</topic>
+	
+	<topic label="Importing Profiler Data Files"		href="html/tasks/analyser/an_load_trace_files.htm" >
+		<topic label="Select Build Files for ROM" 		href="html/reference/analyzer/import_rom_build_files.htm" />
+	</topic>
+	<topic label="Examining a Profiling Project"  		href="html/Getting_Started/example_project.htm" />
+
+	<topic label="Memory Usage" href="html/concepts/memory_usage_capture.htm" >
+		<topic label="Memory Usage view" 	href="html/reference/analyzer/view_memory_usage.htm" />
+		<topic label="Memory Usage Statistics" 	href="html/reference/analyzer/wnd_memory_usage_statistics.htm" />
+		<topic label="Memory Usage menu" 	href="html/reference/analyzer/menu_memory_graph.htm" />
+	</topic>
+
+	<topic label="Menus">
+		<topic label="Context Menu Options" 	href="html/reference/analyzer/context_menu.htm" />
+		<topic label="Save Table" 				href="html/reference/analyzer/save_table.htm" />
+		<topic label="Investigator menu" 		href="html/reference/analyzer/investigator_menu.htm" />
+		<topic label="Memory Graph" 			href="html/reference/analyzer/menu_memory_graph.htm" />
+		<topic label="Power Graph" 				href="html/reference/analyzer/menu_power_graph.htm" />
+		<topic label="Show Button Events" 		href="html/tasks/analyser/btn_press_show.htm" />
+	</topic>
+
+	<topic label="Options"  >
+		<topic label="Changing Button Event Information" 	href="html/tasks/analyser/btn_press_change.htm" />
+		<topic label="Changing Graph Colors" 				href="html/tasks/analyser/chng_graphcolor.htm" />
+		<topic label="Setting Thresholds" 					href="html/tasks/analyser/set_thresholds.htm" />
+		<topic label="Setting Time Interval" 				href="html/tasks/analyser/time_interval.htm" />
+		<topic label="Setting Key Press Profile" 			href="html/tasks/analyser/key_profile_pref.htm" />
+
+	</topic>
+
+	<topic label="Power Usage" 					href="html/reference/analyzer/view_power_usage.htm" >
+		<topic label="Power Usage Settings" 	href="html/reference/analyzer/wnd_power_graph_settings.htm" />
+		<topic label="Power Usage Statistics" 	href="html/reference/analyzer/wnd_power_usage_statistics.htm" />
+		<topic label="Power Graph menu" 		href="html/reference/analyzer/menu_power_graph.htm" />
+	</topic>
+
+	<topic label="Using Source Lookup" 					href="html/tasks/analyser/source_lookup.htm" />
+	<topic label="Analyzing Table Data" 				href="html/reference/analyzer/analyzing_table_data.htm" />
+
+</toc>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/tocConcepts.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<toc label="Software Performance" >
+
+	<topic label="Overview" href="html/concepts/overview/overview.htm" />
+	<topic label="Software Performance" 			href="html/concepts/overview/sw_performance.htm" />
+	<topic label="Basic Analysis Procedure" 		href="html/concepts/perfanalysis/perf_basic_procedures.htm" />
+	<topic label="Server Threads Analysis"  		href="html/concepts/perfanalysis/perf_other_server_threads.htm" />
+	<topic label="Dynamic Binary Support Trace"  	href="html/concepts/dll_support.htm" />
+	<topic label="Dynamic Memory Characteristics"	href="html/concepts/perfanalysis/perf_other_dynamic_mem.htm" />
+	<topic label="Function Level Load Analysis"		href="html/concepts/func_level_load.htm" />
+	
+	<topic label="Performance Measurement Methods"				href="html/concepts/methods.htm" >
+		<topic label="Compile-Time Symbolic Information"		href="html/reference/methods/compile_time.htm" />
+		<topic label="DFC, Delayed Function Call"				href="html/reference/methods/delayed_fn_call.htm" />
+		<topic label="Dynamic Binary Resolution"				href="html/reference/methods/dynamic_bin_res.htm" />
+		<topic label="File System"								href="html/reference/methods/file_sys_storing.htm" />
+		<topic label="Interrupt Stack"							href="html/reference/methods/int_stack.htm" />
+		<topic label="Kernel Containers"						href="html/reference/methods/kernel_containers.htm" />
+		<topic label="Kernel Hook"								href="html/reference/methods/kernel_hook.htm" />
+		<topic label="Link Register"							href="html/reference/methods/link_register.htm" />
+		<topic label="OS Thread Name and ID"					href="html/reference/methods/os_thread.htm" />
+		<topic label="Periodic Interrupt"						href="html/reference/methods/periodic_int.htm" />
+		<topic label="Program Counter value"					href="html/reference/methods/pgm_counter.htm" />
+		<topic label="Read/Write Load Characteristics"			href="html/reference/methods/read_write_load.htm" />
+		<topic label="ROFS"										href="html/reference/methods/rofs.htm" />
+	</topic>
+
+<!--
+		<topic label="Features" >
+			<topic label="Trace Items" 					href="html/reference/profiler/Trace_Items.htm" />
+			<topic label="Button Press Capture"  		href="html/concepts/button_press_capture.htm" />
+			<topic label="Memory Usage Capture"			href="html/concepts/memory_usage_capture.htm" />
+			<topic label="Power Usage Capture"			href="html/concepts/power_usage_capture.htm" />
+			<topic label="Profiler Setting File"  		href="html/reference/settings.htm" />
+		</topic>
+	-->
+	
+</toc>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/tocPI.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<toc label="Performance Investigator User Guide" href="html/profiler.htm" >
+				
+	<topic label="Release notes" href="html/release_notes.htm" />
+	<topic label="Getting Started with Performance Investigator"      href="html/Getting_Started/GS_index.htm" />
+	
+	<topic label="Software Performance" >
+		<link toc="tocConcepts.xml" />
+	</topic>
+	
+	
+	<topic label="Profiler" >
+		<link toc="tocProfiler.xml" />
+	</topic>
+	
+	<topic label="Analyzer" >
+		<link toc="tocAnalyzer.xml" />
+	</topic>
+		
+	<topic label="Acronyms" href="html/reference/abbrev.htm" />
+	
+	<topic label="Bugs fixed" href="html/bugs_fixed.htm" />
+	<topic label="Legal" href="html/legal.htm" />
+		      
+</toc>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/tocProfiler.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<toc label="Profiler" >
+
+	<topic label="Profiler" 					href="html/reference/profiler/profiler.htm" />
+	
+	<topic label="Installing the Profiler"  			href="html/tasks/profiler/prof_installation.htm" >
+		<topic label="Connecting by Bluetooth" 			href="html/tasks/profiler/bluetooth_connection.htm" />
+		<topic label="Connecting by Serial Interface" 	href="html/tasks/profiler/serial_connection.htm" />
+		<topic label="Connecting by USB" 				href="html/tasks/profiler/usb_connection.htm" />
+	</topic>
+
+	<topic label="Using the Profiler" 					href="html/reference/profiler/prof_using.htm" />
+	
+	<topic label="Profiler options"  >
+		<topic label="Setting Tracing options" 		href="html/reference/profiler/tracing_options.htm" />
+		<topic label="Setting Output Settings" 		href="html/reference/profiler/output_settings.htm" />
+		<topic label="Setting Advanced options" 	href="html/reference/profiler/advanced_options.htm" />
+	</topic>
+
+	<topic label="Trace items"  						href="html/reference/profiler/Trace_Items.htm" >
+		<topic label="Address/Thread Trace"				href="html/reference/profiler/GPP_trace.htm" />
+		<topic label="Button Press Trace" 				href="html/reference/profiler/BUP_trace.htm" />
+		<topic label="Dynamic Binary Support Trace" 	href="html/reference/profiler/ITT_trace.htm" />
+		<topic label="Function Call Trace" 				href="html/reference/profiler/GFC_trace.htm" />
+		<topic label="Memory Trace" 					href="html/reference/profiler/MEM_trace.htm" />
+		<topic label="Power Usage Trace" 				href="html/reference/profiler/PWR_trace.htm" />
+		<topic label="Thread Priority Trace" 			href="html/reference/profiler/PRI_trace.htm" />
+	</topic>
+	
+	<topic label="Using the Command-line" 			href="html/reference/profiler/cmd_line_overview.htm" >
+		<topic label="Profiler Settings File" 		href="html/reference/settings.htm" />
+	</topic>
+	
+</toc>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.doc.user/tocRelease.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<toc label="Release notes" 
+	link_to="../com.nokia.carbide.help.common/carbideHelpTOC.xml#anchorCarbideInfo" >
+  
+	<topic label="Performance Investigator Release Notes" 	href="html/release_notes.htm" />
+	
+</toc>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/.settings/org.eclipse.core.resources.prefs	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,3 @@
+#Mon Feb 09 13:31:17 CST 2009
+eclipse.preferences.version=1
+encoding//src/com/nokia/carbide/cpp/pi/function/messages.properties=8859_1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,17 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Functions
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.function;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.function.FunctionPlugin
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ com.nokia.carbide.cpp.pi,
+ com.nokia.carbide.cpp.pi.util,
+ com.nokia.carbide.cpp.pi.address,
+ com.nokia.carbide.cpp.pi.call
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.pi.function
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,6 @@
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .
+jars.compile.order = .
+source.. = src/
+output.. = bin/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+   <extension
+         point="com.nokia.carbide.cpp.pi.piPluginData">
+      <plugin pluginClass="com.nokia.carbide.cpp.pi.function.FunctionReturnPlugin"/>
+   </extension>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/FunctionPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.function;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Event;
+import org.osgi.framework.BundleContext;
+
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IAnalysisItem;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class FunctionPlugin extends AbstractPiPlugin
+		implements IAnalysisItem, IEventListener
+{
+	//The shared instance.
+	private static FunctionPlugin plugin;
+	
+	/**
+	 * The constructor.
+	 */
+	public FunctionPlugin() {
+		plugin = this;
+	}
+
+	public Action getAnalysisAction() {
+		return null;
+	}
+	
+	public void action()
+	{
+		
+	}
+	
+//	private boolean checkGfcRequirements(PICompositePanel compositePanel, GfcTrace gfcTrace)
+//	{
+//		boolean startOk = true;
+//		boolean endOk = true;
+//		
+//		if ( compositePanel.getSelectionEnd() < gfcTrace.getFirstSampleNumber() ||
+//				compositePanel.getSelectionStart() > gfcTrace.getLastSampleNumber())
+//		{
+//			GeneralMessages.showErrorMessage("There is no Gfc Trace Data for time "+
+//					(double)compositePanel.getSelectionStart()/1000+"s-"+
+//					((double)compositePanel.getSelectionEnd())/1000+
+//					"s Current GFC trace is "+
+//					(double)gfcTrace.getFirstSampleNumber()/1000+"s-"+
+//					(double)gfcTrace.getLastSampleNumber()/1000+"s");
+//			return false;				
+//		}
+//		
+//		if (compositePanel.getSelectionStart() < gfcTrace.getFirstSampleNumber())
+//		{
+//			boolean result = GeneralMessages.showProblemMessage("There is no Gfc Trace Data for time "+
+//					(double)compositePanel.getSelectionStart()/1000+"s-"+
+//					((double)gfcTrace.getFirstSampleNumber()-1)/1000+
+//					"s Current GFC trace is "+
+//					(double)gfcTrace.getFirstSampleNumber()/1000+"s-"+
+//					(double)gfcTrace.getLastSampleNumber()/1000+"s"+
+//					" Do you want to move selection start to "+(double)gfcTrace.getFirstSampleNumber()/1000+"s ?");
+//			
+//			if (result == true)
+//			{
+//				compositePanel.setSelectionFields(
+//						gfcTrace.getFirstSampleNumber(),(int) compositePanel.getSelectionEnd());
+//			}
+//			else startOk =false;
+//		}
+//		if (compositePanel.getSelectionEnd() > gfcTrace.getLastSampleNumber())
+//		{
+//			boolean result = GeneralMessages.showProblemMessage("There is no Gfc Trace Data for time "+
+//					((double)gfcTrace.getLastSampleNumber()+1)/1000+"s-"+
+//					(double)compositePanel.getSelectionEnd()/1000+
+//					"s Current GFC trace is "+
+//					(double)gfcTrace.getFirstSampleNumber()/1000+"s-"+
+//					(double)gfcTrace.getLastSampleNumber()/1000+"s"+
+//					" Do you want to move selection end to "+(double)gfcTrace.getLastSampleNumber()/1000+"s ?");	
+//			
+//			if (result == true)
+//			{
+//				compositePanel.setSelectionFields(
+//						(int) compositePanel.getSelectionStart(),gfcTrace.getLastSampleNumber());
+//			}
+//			else endOk =false;
+//		}
+//		if (startOk == false || endOk == false) return false;
+//		else return true;
+//	}
+
+	public void receiveEvent(String action, Event event) 
+	{
+		if (action.equals("functionAnalysis")) //$NON-NLS-1$
+		{
+    		try {
+/*
+			AnalyseTab tab = PIPageEditor.currentTab();
+			PICompositePanel compositePanel =  tab.getProfilePage(3).getTopSwingPanel(); 
+			
+			if (compositePanel.getSelectionStart() == -1 || compositePanel.getSelectionEnd() == -1 ||
+	    			(compositePanel.getSelectionStart() == compositePanel.getSelectionEnd()))
+	    	{
+				GeneralMessages.showErrorMessage("Make a selection from the graph");
+	    		return;
+	    	}
+	    	else
+	    	{
+	    		ParsedTraceData ptd = TraceDataRepository.getTrace(tab.getTabId(), "com.nokia.carbide.cpp.pi.address.GppTrace");
+	    		
+	    		int mode = ((GppTraceGraph)((GppTrace)ptd.traceData).getTraceGraph()).getDrawMode();
+	    	    String[] selectedItems = null;
+	    	    if (mode == Defines.THREADS || mode == Defines.THREADS_FUNCTIONS)
+	    	        selectedItems = compositePanel.getSharedData().GPP_SelectedThreadNames;
+	    	    else
+	    	        selectedItems = compositePanel.getSharedData().GPP_SelectedBinaryNames;
+
+	    	    ptd = TraceDataRepository.getTrace(tab.getTabId(), "com.nokia.carbide.cpp.pi.call.GfcTrace");
+	    	    //GfcTrace gfcTrace = (GfcTrace)ptd.traceData;
+	        	if (ptd == null ||
+	        			this.checkGfcRequirements(compositePanel, (GfcTrace)ptd.traceData) == false)
+	        	{
+	        		GeneralMessages.showNotificationMessage("Linked function analysis is disabled");
+	        		new NewFunctionAnalyse(compositePanel, selectedItems, false, mode);
+	        	}
+	        	else
+	        	{
+	        		new NewFunctionAnalyse(compositePanel, selectedItems, true, mode);
+	        	}
+	    	}
+*/
+	    			// this menu is not used in eclipse, replaced by function call
+	    			throw new Exception (Messages.getString("FunctionPlugin.fixException")); //$NON-NLS-1$
+	    		} catch (Exception e) {
+	    			e.printStackTrace();
+	    	}
+		}
+	}
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		plugin = null;
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static FunctionPlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractPiPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi.function", path); //$NON-NLS-1$
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/FunctionReturnPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.function;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IReturnPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+
+
+public class FunctionReturnPlugin implements IReturnPlugin {
+	public AbstractPiPlugin getPlugin() {
+		return FunctionPlugin.getDefault();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/GfcTraceVisualiser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.function;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.ListCellRenderer;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.nokia.carbide.cpp.internal.pi.model.GUITooltips;
+import com.nokia.carbide.cpp.pi.call.GfcFunctionItem;
+import com.nokia.carbide.cpp.pi.call.GfcTrace;
+import com.nokia.carbide.cpp.pi.util.AWTColorPalette;
+
+
+public class GfcTraceVisualiser extends JPanel
+{
+  private static final long serialVersionUID = 1L;
+  private GfcTrace myTrace;
+  private GfcFunctionItem[] sortedData;
+  private JList leftList;
+  private JList rightList;
+  private JList centerList;
+  private JPanel selectionPanel;
+  private JButton sortByTotalButton;
+  private JButton sortByCallerButton;
+  private JButton sortByRecursiveButton;
+  private JButton goBackButton;
+  private int lastIndex = -1;
+  private JPanel callerPanel;
+  private JPanel calleePanel;
+  private JPanel centerPanel;
+
+  public GfcTraceVisualiser(GfcTrace trace)
+  {
+    this.myTrace = trace;
+
+    this.selectionPanel = new JPanel(new GridLayout(6,1));
+    sortByTotalButton = new JButton(Messages.getString("GfcTraceVisualiser.totalLoad")); //$NON-NLS-1$
+    sortByCallerButton = new JButton(Messages.getString("GfcTraceVisualiser.callerLoad")); //$NON-NLS-1$
+    sortByRecursiveButton = new JButton(Messages.getString("GfcTraceVisualiser.recursiveLoad")); //$NON-NLS-1$
+    goBackButton = new JButton(Messages.getString("GfcTraceVisualiser.previousSelection")); //$NON-NLS-1$
+    
+    sortByTotalButton.setToolTipText(GUITooltips.getTotalLoadButton());
+    sortByCallerButton.setToolTipText(GUITooltips.getCallerLoadButton());
+    sortByRecursiveButton.setToolTipText(GUITooltips.getRecursiveLoadButton());
+    goBackButton.setToolTipText(GUITooltips.getPreviousSelectionButton());
+
+    ActionListener al = new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ae)
+      {
+        if (ae.getSource() == sortByCallerButton)
+        {
+          GfcFunctionItem[] sortedData = myTrace.getEntriesSorted(GfcTrace.SORT_BY_CALLED_LOAD);
+          centerList.setListData(sortedData);
+        }
+        else if (ae.getSource() == sortByTotalButton)
+        {
+          GfcFunctionItem[] sortedData = myTrace.getEntriesSorted(GfcTrace.SORT_BY_TOTAL_LOAD);
+          centerList.setListData(sortedData);
+        }
+        else if (ae.getSource() == sortByRecursiveButton)
+        {
+          GfcFunctionItem[] sortedData = myTrace.getEntriesSorted(GfcTrace.SORT_BY_RECURSIVE_LOAD);
+          centerList.setListData(sortedData);
+        }
+        else if (ae.getSource() == goBackButton)
+        {
+          if (lastIndex != -1)
+          {
+            int temp = centerList.getSelectedIndex();
+            centerList.setSelectedIndex(lastIndex);
+
+            if (lastIndex>5 && lastIndex < centerList.getModel().getSize()-5)
+            {
+              centerList.ensureIndexIsVisible(lastIndex-4);
+              centerList.ensureIndexIsVisible(lastIndex+4);
+              centerList.ensureIndexIsVisible(lastIndex);
+            }
+            else
+            {
+              centerList.ensureIndexIsVisible(lastIndex);
+            }
+
+            lastIndex = temp;
+          }
+        }
+      }
+    };
+
+    sortByTotalButton.addActionListener(al);
+    sortByCallerButton.addActionListener(al);
+    sortByRecursiveButton.addActionListener(al);
+    goBackButton.addActionListener(al);
+
+    this.selectionPanel.add(new JLabel(Messages.getString("GfcTraceVisualiser.sortBy"))); //$NON-NLS-1$
+    this.selectionPanel.add(sortByTotalButton);
+    this.selectionPanel.add(sortByCallerButton);
+    this.selectionPanel.add(sortByRecursiveButton);
+    this.selectionPanel.add(new JLabel(Messages.getString("GfcTraceVisualiser.goBackTo"))); //$NON-NLS-1$
+    this.selectionPanel.add(goBackButton);
+
+    this.leftList = new JList();
+    this.leftList.setCellRenderer(new GfcListCellRenderer(myTrace));
+    this.leftList.addListSelectionListener(new ListSelectionListener()
+    {
+      public void valueChanged(ListSelectionEvent lse)
+      {
+        Object[] element = (Object[]) leftList.getSelectedValue();
+        if (element != null)
+        {
+          setLeftListDataToFunctionsThisFunctionCalls((GfcFunctionItem)element[0]);
+          setRightListDataToFunctionsThisFunctionCalls((GfcFunctionItem)element[0]);
+
+          lastIndex = centerList.getSelectedIndex();
+          for (int i=0;i<centerList.getModel().getSize();i++)
+          {
+            if (centerList.getModel().getElementAt(i).equals(element[0]))
+            {
+              centerList.setSelectedIndex(i);
+              if (i>5 && i < centerList.getModel().getSize()-5)
+              {
+                centerList.ensureIndexIsVisible(i-4);
+                centerList.ensureIndexIsVisible(i+4);
+                centerList.ensureIndexIsVisible(i);
+              }
+              else
+              {
+                centerList.ensureIndexIsVisible(i);
+              }
+              break;
+            }
+          }
+        }
+      }
+    });
+
+    this.centerList = new JList();
+    this.centerList.setCellRenderer(new GfcListCellRenderer(myTrace));
+    this.centerList.addListSelectionListener(new ListSelectionListener()
+    {
+      public void valueChanged(ListSelectionEvent lse)
+      {
+        GfcFunctionItem element = (GfcFunctionItem)centerList.getSelectedValue();
+        if (element != null)
+        {
+          setLeftListDataToFunctionsThisFunctionCalls((GfcFunctionItem)element);
+          setRightListDataToFunctionsThisFunctionCalls((GfcFunctionItem)element);
+        }
+        else
+        {
+          leftList.setListData(new Object[]{});
+          rightList.setListData(new Object[]{});
+        }
+      }
+    });
+
+    this.rightList = new JList();
+    this.rightList.setCellRenderer(new GfcListCellRenderer(myTrace));
+    this.rightList.addListSelectionListener(new ListSelectionListener()
+    {
+      public void valueChanged(ListSelectionEvent lse)
+      {
+        Object[] element = (Object[]) rightList.getSelectedValue();
+        if (element != null)
+        {
+          setLeftListDataToFunctionsThisFunctionCalls((GfcFunctionItem)element[0]);
+          setRightListDataToFunctionsThisFunctionCalls((GfcFunctionItem)element[0]);
+
+          lastIndex = centerList.getSelectedIndex();
+          for (int i=0;i<centerList.getModel().getSize();i++)
+          {
+            if (centerList.getModel().getElementAt(i).equals(element[0]))
+            {
+              centerList.setSelectedIndex(i);
+              if (i>5 && i < centerList.getModel().getSize()-5)
+              {
+                centerList.ensureIndexIsVisible(i-4);
+                centerList.ensureIndexIsVisible(i+4);
+                centerList.ensureIndexIsVisible(i);
+              }
+              else
+              {
+                centerList.ensureIndexIsVisible(i);
+              }
+
+              break;
+            }
+          }
+
+        }
+
+      }
+    });
+
+    this.setLayout(new GridLayout(3,1));
+
+    // create and add the top panel
+    callerPanel = new JPanel();
+    JPanel labeledPanel = new JPanel();
+    labeledPanel.setLayout(new BorderLayout());
+    callerPanel.setLayout(new BorderLayout());
+    //Component c = new BasicArrowButton(BasicArrowButton.NORTH);
+    //c.set
+
+    labeledPanel.add(new JLabel(Messages.getString("GfcTraceVisualiser.calledSelectedFunction")),BorderLayout.CENTER); //$NON-NLS-1$
+    labeledPanel.setBackground(
+    	AWTColorPalette.getColor(new RGB(220, 220, 220)));
+    //labeledPanel.add(c,BorderLayout.EAST);
+    //c = new BasicArrowButton(BasicArrowButton.NORTH);
+    //labeledPanel.add(c,BorderLayout.WEST);
+    //labeledPanel.setBorder(BorderFactory.createEtchedBorder());
+    //callerPanel.add(labeledPanel,BorderLayout.SOUTH);
+    callerPanel.add(labeledPanel,BorderLayout.NORTH);
+    callerPanel.add(new JScrollPane(this.leftList));
+    this.add(callerPanel);
+
+    // create and add the center panel
+    centerPanel = new JPanel();
+    centerPanel.setLayout(new BorderLayout());
+    centerPanel.add(new JScrollPane(this.centerList),BorderLayout.CENTER);
+    centerPanel.add(this.selectionPanel,BorderLayout.WEST);
+
+    this.add(centerPanel);
+
+    // create and add the lower panel
+    calleePanel = new JPanel();
+    
+    
+    labeledPanel = new JPanel();
+    labeledPanel.setLayout(new BorderLayout());
+    calleePanel.setLayout(new BorderLayout());
+    //c = new BasicArrowButton(BasicArrowButton.SOUTH);
+
+    labeledPanel.add(new JLabel(Messages.getString("GfcTraceVisualiser.calledBySelectedFunction")),BorderLayout.CENTER); //$NON-NLS-1$
+    labeledPanel.setBackground(
+  			AWTColorPalette.getColor(new RGB(220, 220, 220)));
+    //labeledPanel.add(c,BorderLayout.EAST);
+    //c = new BasicArrowButton(BasicArrowButton.SOUTH);
+    //labeledPanel.add(c,BorderLayout.WEST);
+    //labeledPanel.setBorder(BorderFactory.createEtchedBorder());
+    calleePanel.add(labeledPanel,BorderLayout.NORTH);
+    calleePanel.add(new JScrollPane(this.rightList));
+    this.add(calleePanel);
+  }
+  
+  public JPanel getCalleeList()
+  {
+  	return this.calleePanel;
+  }
+  
+  public JPanel getCallerList()
+  {
+  	return this.callerPanel;
+  }
+  
+  public JPanel getCenterPanel()
+  {
+  	return this.centerPanel;
+  }
+  
+  public void selectFunction(String functionName)
+  {
+  	if (this.sortedData == null) return;
+  	
+  	for (int i = 0; i < this.sortedData.length; i++)
+  	{
+  		GfcFunctionItem gfi = this.sortedData[i];
+  		if (gfi.name.equals(functionName))
+  		{
+  			this.centerList.setSelectedValue(gfi,true);
+  			return;
+  		}  		 		
+  	}
+  }
+  
+  public JPanel getSelectionPanel()
+  {
+  	return this.selectionPanel;
+  }
+
+  public void setStartAndEnd(int start,int end,boolean symPrimary)
+  {
+    myTrace.parseEntries(start,end);
+    sortedData = myTrace.getEntriesSorted(GfcTrace.SORT_BY_TOTAL_LOAD);
+    
+    this.centerList.setListData(sortedData);
+  }
+
+
+  public void setLeftListDataToFunctionsThisFunctionCalls(GfcFunctionItem function)
+  {
+    GfcFunctionItem[] list = function.getCallerList();
+    Double[] perc = function.getCallerPercentages();
+
+    Object[] listData = new Object[list.length];
+
+    for (int i = 0;i<list.length;i++)
+    {
+      Object[] element = new Object[2];
+      element[0] = list[i];
+      element[1] = perc[i];
+      listData[i] = element;
+    }
+
+    this.leftList.setListData(listData);
+  }
+
+  public void setRightListDataToFunctionsThisFunctionCalls(GfcFunctionItem function)
+  {
+    GfcFunctionItem[] list = function.getCalleeList();
+    Double[] perc = function.getCalleePercentages();
+
+    Object[] listData = new Object[list.length];
+
+    for (int i = 0;i<list.length;i++)
+    {
+      Object[] element = new Object[2];
+      element[0] = list[i];
+      element[1] = perc[i];
+      listData[i] = element;
+    }
+    this.rightList.setListData(listData);
+  }
+
+  private static class GfcListCellRenderer extends JLabel implements ListCellRenderer
+  {
+    private GfcTrace myTrace;
+	public Color ittColor = Color.ORANGE.darker();
+	public Color gppColor = Color.BLUE.darker();
+
+    public GfcListCellRenderer(GfcTrace trace)
+    {
+      this.setOpaque(true);
+      myTrace = trace;
+    }
+
+    public Component getListCellRendererComponent(
+            JList list,
+            Object value,            // value to display
+            int index,               // cell index
+            boolean isSelected,      // is the cell selected
+            boolean cellHasFocus)    // the list and the cell have the focus
+    {
+
+      if (value instanceof GfcFunctionItem)
+      {
+        GfcFunctionItem item = (GfcFunctionItem)value;
+
+        double percent = myTrace.getAbsoluteCallerPercentageFor(item);
+        String perc2 = (((double)Math.round(100*percent)) / 100)+Messages.getString("GfcTraceVisualiser.percent"); //$NON-NLS-1$
+
+        percent = myTrace.getAbsoluteTraditionalPercentageFor(item);
+        String perc3 = (((double)Math.round(100*percent)) / 100)+Messages.getString("GfcTraceVisualiser.percent"); //$NON-NLS-1$
+
+        percent = myTrace.getRecursiveCallerPrecentageFor(item);
+        String perc4 = (((double)Math.round(100*percent)) / 100)+Messages.getString("GfcTraceVisualiser.percent"); //$NON-NLS-1$
+
+        if (isSelected)
+        {
+          String s = Messages.getString("GfcTraceVisualiser.functionString1")+perc3+Messages.getString("GfcTraceVisualiser.functionString2")+perc2+Messages.getString("GfcTraceVisualiser.functionString3")+perc4+Messages.getString("GfcTraceVisualiser.functionString4")+ //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+                     Messages.getString("GfcTraceVisualiser.functionString5")+Integer.toHexString((int)item.address)+Messages.getString("GfcTraceVisualiser.functionString6")+item.name; //$NON-NLS-1$ //$NON-NLS-2$
+          //s = item.getAccumulatedLoad() + s;
+
+          setText(s);
+        }
+        else
+        {
+          String s = Messages.getString("GfcTraceVisualiser.functionString1")+perc3+Messages.getString("GfcTraceVisualiser.functionString2")+perc2+Messages.getString("GfcTraceVisualiser.functionString3")+perc4+Messages.getString("GfcTraceVisualiser.functionString4")+ //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+                     Messages.getString("GfcTraceVisualiser.functionString5")+Integer.toHexString((int)item.address)+Messages.getString("GfcTraceVisualiser.functionString6")+item.name; //$NON-NLS-1$ //$NON-NLS-2$
+          //s = item.getAccumulatedLoad() + s;
+
+          setText(s);
+        }
+
+        if (isSelected)
+        {
+          setBackground(list.getSelectionBackground());
+        }
+        else
+        {
+          setBackground(list.getBackground());
+        }
+        
+        if (item.isSymbolParsed())
+        	setForeground(this.gppColor);
+        else
+        	setForeground(this.ittColor);	
+      }
+
+      else if (value instanceof Object[])
+      {
+
+        Object[] element = (Object[])value;
+        GfcFunctionItem item = (GfcFunctionItem)element[0];
+
+        double percent = ((Double)element[1]).doubleValue();
+        String perc1 = (((double)Math.round(100*percent)) / 100)+Messages.getString("GfcTraceVisualiser.percent"); //$NON-NLS-1$
+
+        // set color according to the relative load
+        setBackground(new Color((int)(155+(percent)),155,(int)(255-(percent))));
+        
+        if (item.isSymbolParsed())
+        	setForeground(this.gppColor);
+        else
+        	setForeground(this.ittColor);
+
+        percent = myTrace.getAbsoluteCallerPercentageFor(item);
+        String perc2 = (((double)Math.round(100*percent)) / 100)+Messages.getString("GfcTraceVisualiser.percent"); //$NON-NLS-1$
+
+        percent = myTrace.getAbsoluteTraditionalPercentageFor(item);
+        String perc3 = (((double)Math.round(100*percent)) / 100)+Messages.getString("GfcTraceVisualiser.percent"); //$NON-NLS-1$
+
+        if (isSelected)
+        {
+          String s = Messages.getString("GfcTraceVisualiser.addressString1")+Integer.toHexString((int)item.address)+ //$NON-NLS-1$
+                     Messages.getString("GfcTraceVisualiser.addressString2")+perc3+Messages.getString("GfcTraceVisualiser.addressString3")+perc2+Messages.getString("GfcTraceVisualiser.addressString4")+perc1+Messages.getString("GfcTraceVisualiser.addressString5")+item.name; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+          setText(s);
+        }
+        else
+        {
+          String s = Messages.getString("GfcTraceVisualiser.addressString2a")+perc3+Messages.getString("GfcTraceVisualiser.addressString3")+perc2+Messages.getString("GfcTraceVisualiser.addressString4")+perc1+Messages.getString("GfcTraceVisualiser.addressString5")+item.name; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+          setText(s);
+
+        }
+      }
+      else
+      {
+        setText(Messages.getString("GfcTraceVisualiser.listIsNotWorking")+value.getClass()); //$NON-NLS-1$
+      }
+
+      setEnabled(list.isEnabled());
+      setFont(list.getFont());
+
+      return this;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.function;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.function.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/NewFunctionAnalyse.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2108 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: 
+ *
+ */
+
+/*
+ * NewFunctionAnalyse.java
+ */
+package com.nokia.carbide.cpp.pi.function;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.text.DecimalFormat;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.KeyStroke;
+import javax.swing.ListCellRenderer;
+import javax.swing.border.LineBorder;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import org.eclipse.swt.graphics.RGB;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.internal.pi.model.GUITooltips;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
+import com.nokia.carbide.cpp.internal.pi.test.PIAnalyser;
+import com.nokia.carbide.cpp.internal.pi.utils.QuickSortImpl;
+import com.nokia.carbide.cpp.internal.pi.utils.Sortable;
+import com.nokia.carbide.cpp.internal.pi.visual.Defines;
+import com.nokia.carbide.cpp.internal.pi.visual.PICompositePanel;
+import com.nokia.carbide.cpp.pi.address.GppSample;
+import com.nokia.carbide.cpp.pi.address.GppTrace;
+import com.nokia.carbide.cpp.pi.call.GfcSample;
+import com.nokia.carbide.cpp.pi.call.GfcTrace;
+import com.nokia.carbide.cpp.pi.util.AWTColorPalette;
+
+
+public class NewFunctionAnalyse extends JPanel implements ListSelectionListener, ChangeListener
+{
+	private static final long serialVersionUID = 3803217794859007866L;
+
+	private PICompositePanel compositePanel;
+	//private TraceDataRepository traceData;
+	
+	private JList threadList;
+	private JList binaryList;
+	private JList percentList;	
+	
+	private JDialog frame;
+	
+	private GppTrace gppTrace;
+	private GfcTrace gfcTrace;
+	private GenericTrace ittTrace;
+	
+	private Vector gppSamples;
+	private Vector gfcSamples;
+	//private Vector ittSamples;
+	
+	private Hashtable threads;
+	private Vector binaryVector;
+	
+	private Hashtable binaries;
+	private Vector threadVector;
+	
+	private JSplitPane split;
+	private JSplitPane functionSplit;
+	
+	private JButton ittPrimary;
+	private JButton symPrimary;
+	
+	private JCheckBox totalPercents;
+	private JCheckBox functionPercents;
+	
+	private String[] originallySelectedThreads;
+	private String[] originallySelectedBinaries;
+	private int[] originallySelectedIndices;
+	private Vector selectedButNotVisibleBinaries;
+	private Vector selectedButNotVisibleThreads;
+	
+	private GfcTraceVisualiser gfcTraceVisualiser;
+	private Thread updateThread = null;
+	
+	private boolean symbolPrimary = true;
+	
+	private boolean gfcEnabled;
+	
+	//private int stateChangedCounter = 0;
+	//private Object[] oldSelectedBinaries;
+	private Object[] selectedBinaries;
+	//private boolean stateChanged = false;
+	
+	private Hashtable functionNameCacheSym;
+	private Hashtable functionNameCacheItt;
+	private final int mode; //thread mode(0) or binary mode(1)
+	
+public NewFunctionAnalyse(PICompositePanel compositePanel,
+								/*TraceDataRepository traceData,*/
+								String[] selectedItems,
+								boolean gfcEnabled, int mode)
+	{		
+		this.selectedButNotVisibleBinaries = new Vector();
+		this.selectedButNotVisibleThreads = new Vector();
+		this.gfcEnabled = gfcEnabled;
+		this.functionNameCacheSym = new Hashtable();
+		this.functionNameCacheItt = new Hashtable();
+		
+		//this.originallySelectedThreads = selectedThreads;
+		this.mode = mode;
+		if (selectedItems != null)
+		{
+			if (mode == Defines.BINARIES || mode == Defines.BINARIES_FUNCTIONS)
+			    this.originallySelectedBinaries = (String[])selectedItems.clone();
+			else
+			    this.originallySelectedThreads = (String[])selectedItems.clone();
+		}
+		
+		this.compositePanel = compositePanel;
+		//this.traceData = traceData;
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+		
+		ParsedTraceData ptd = TraceDataRepository.getInstance().getTrace(uid, "com.nokia.carbide.cpp.pi.address.GppTrace"); //$NON-NLS-1$
+		if (ptd != null)
+			this.gppTrace = (GppTrace)ptd.traceData;
+		ptd = TraceDataRepository.getInstance().getTrace(uid, "com.nokia.carbide.cpp.pi.call.GfcTrace"); //$NON-NLS-1$
+		if (ptd != null)
+			this.gfcTrace = (GfcTrace)ptd.traceData;
+		
+		//if (traceData.getIttTrace() instanceof IttTrace)
+		ptd = TraceDataRepository.getInstance().getTrace(uid, "com.nokia.carbide.cpp.pi.instr.IttTrace"); //$NON-NLS-1$
+		if (ptd != null)
+			this.ittTrace = ptd.traceData;
+		
+		this.refreshFrame();
+		if (mode == Defines.THREADS || mode == Defines.THREADS_FUNCTIONS)
+		    this.refreshThreadListComponent(true);
+		else
+		{
+		    this.refreshBinaryListComponent(true);
+		    this.refreshThreadListComponentSec();
+		}
+		//this.binaryList.grabFocus();
+		this.updateGfc();
+	}
+	
+	private void clearReferences()
+	{
+		// clear all possible references to other
+		// parts of the trace, to avoid memory leak
+		// execute this before disposing the frame
+		compositePanel = null;
+		//traceData = null;
+		
+		threadList = null;
+		binaryList = null;
+		percentList = null;	
+		
+		frame = null;
+		
+		gppTrace = null;
+		gfcTrace = null;
+		ittTrace = null;
+		
+		gppSamples = null;
+		gfcSamples = null;
+		//ittSamples = null;
+		
+		threads = null;
+		binaryVector = null;
+		
+		binaries = null;
+		threadVector = null;
+		
+		split = null;
+		functionSplit = null;
+		
+		ittPrimary = null;
+		symPrimary = null;
+		
+		totalPercents = null;
+		functionPercents = null;
+		
+		originallySelectedThreads = null;
+		originallySelectedBinaries = null;
+		originallySelectedIndices = null;
+		selectedButNotVisibleBinaries = null;
+		selectedButNotVisibleThreads = null;
+		
+		gfcTraceVisualiser = null;
+		updateThread = null;
+		selectedBinaries = null;
+		functionNameCacheSym = null;
+		functionNameCacheItt = null;
+	}
+	
+	private void refreshFrame()
+	{
+		this.extractSamples();
+		if (mode == Defines.THREADS || mode == Defines.THREADS_FUNCTIONS)
+		{
+			this.refreshThreadListComponent(false);
+			this.refreshBinaryListComponentSec();
+		}
+		else
+		{
+		    this.refreshBinaryListComponent(false);
+		    this.refreshThreadListComponentSec();
+		}
+		this.refreshPercentListComponent();
+
+		if (frame == null)
+		{
+			frame = new JDialog(PIAnalyser.getFrame());
+			frame.setSize(1000,900);
+			frame.getContentPane().setLayout(new BorderLayout());
+			frame.addComponentListener(new ComponentAdapter()
+			{
+				public void componentResized(ComponentEvent e) 
+				{
+					split.setDividerLocation((double)0.4);
+					if (gfcEnabled)
+						functionSplit.setDividerLocation((double)0.4);
+					else
+						functionSplit.setDividerLocation((double)1);					
+				}
+			});
+			
+			frame.addWindowListener(new WindowAdapter()
+			{
+				public void windowClosing(WindowEvent e)
+				{
+					// clear all possible references to the trace
+					//System.err.println("Closing");
+					frame.dispose();
+					clearReferences();
+				}
+				public void windowClosed(WindowEvent e)
+				{
+					// clear all possible references to the trace
+					//System.err.println("Closed");
+					clearReferences();
+				}
+			});
+			
+			JPanel leftPanel = new JPanel();
+			JPanel rightPanel = new JPanel();
+			this.functionSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+			this.functionSplit.setOneTouchExpandable(true);
+			
+			leftPanel.setLayout(new GridLayout(3,1));
+			rightPanel.setLayout(new BorderLayout());
+
+			JButton clearSelectionButton = null;
+			if (mode == Defines.THREADS || mode == Defines.THREADS_FUNCTIONS)
+			    clearSelectionButton = new JButton(Messages.getString("NewFunctionAnalyse.clearSelectedBinaries")); //$NON-NLS-1$
+			else 
+			    clearSelectionButton = new JButton(Messages.getString("NewFunctionAnalyse.clearSelectedThreads")); //$NON-NLS-1$
+			clearSelectionButton.setToolTipText(GUITooltips.getClearSelectedBinariesButton());
+			clearSelectionButton.addActionListener(new ActionListener()
+			{
+				public void actionPerformed(ActionEvent ae)
+				{
+					selectedButNotVisibleBinaries.clear();
+					binaryList.clearSelection();
+					selectedButNotVisibleThreads.clear();
+					threadList.clearSelection();
+				}
+			});
+			JButton setOriginallySelectedButton = null;
+			if (mode == Defines.THREADS || mode == Defines.THREADS_FUNCTIONS)
+			    setOriginallySelectedButton = new JButton(Messages.getString("NewFunctionAnalyse.selectOriginalThreads")); //$NON-NLS-1$
+			else
+			    setOriginallySelectedButton = new JButton(Messages.getString("NewFunctionAnalyse.selectOriginalBinaries")); //$NON-NLS-1$
+			setOriginallySelectedButton.setToolTipText(GUITooltips.getSetOriginalThreads());
+			setOriginallySelectedButton.addActionListener(new ActionListener()
+			{
+				public void actionPerformed(ActionEvent ae)
+				{
+					if (originallySelectedIndices != null && threadList != null && 
+					        (mode == Defines.THREADS || mode == Defines.THREADS_FUNCTIONS))
+						threadList.setSelectedIndices(originallySelectedIndices);
+					else if (originallySelectedIndices != null && binaryList != null && 
+					        (mode == Defines.BINARIES || mode == Defines.BINARIES_FUNCTIONS))
+					    binaryList.setSelectedIndices(originallySelectedIndices);
+				}
+			});
+			
+			this.ittPrimary = new JButton(Messages.getString("NewFunctionAnalyse.primarilyUseITT")); //$NON-NLS-1$
+			this.ittPrimary.setToolTipText(GUITooltips.getUsePrimarilyItt());
+			this.ittPrimary.addActionListener(new ActionListener()
+			{
+				public void actionPerformed(ActionEvent ae)
+				{
+					symbolPrimary = false;
+					
+					if (gfcEnabled) updateGfc();
+
+					if (mode == Defines.BINARIES || mode == Defines.BINARIES_FUNCTIONS)
+					{
+						refreshBinaryListComponent(false);
+						//refreshBinaryListComponentSec();
+					    refreshThreadListComponentSec();
+					}
+					else
+					{
+						//refreshBinaryListComponent(false);
+					    refreshBinaryListComponentSec();
+					}
+					refreshPercentListComponent();
+				}
+			});
+			
+			this.symPrimary = new JButton(Messages.getString("NewFunctionAnalyse.primarilyUseSymbolFile")); //$NON-NLS-1$
+			this.symPrimary.setToolTipText(GUITooltips.getUsePrimarilySymbol());
+			this.symPrimary.addActionListener(new ActionListener()
+			{
+				public void actionPerformed(ActionEvent ae)
+				{
+					symbolPrimary = true;
+					
+					if (gfcEnabled) updateGfc();
+					
+				    if (mode == Defines.BINARIES || mode == Defines.BINARIES_FUNCTIONS)
+					{
+						refreshBinaryListComponent(false);
+						//refreshBinaryListComponentSec();				    	
+				    	refreshThreadListComponentSec();
+					}
+					else
+					{
+						//refreshBinaryListComponent(false);
+					    refreshBinaryListComponentSec();
+					}
+					refreshPercentListComponent();
+					
+				}
+			});
+			
+			this.totalPercents = new JCheckBox(Messages.getString("NewFunctionAnalyse.showPercentsOfTotalLoad")); //$NON-NLS-1$
+			this.totalPercents.addChangeListener(this);
+			this.totalPercents.setToolTipText(GUITooltips.getAbsolutePercentage());
+			this.totalPercents.setSelected(true);
+			
+			this.functionPercents = new JCheckBox(Messages.getString("NewFunctionAnalyse.showPositionSpecificPercents")); //$NON-NLS-1$
+			this.functionPercents.addChangeListener(this);
+			this.functionPercents.setSelected(false);
+			
+			if (this.ittTrace == null)
+			{
+				this.ittPrimary.setEnabled(false);
+				this.symPrimary.setEnabled(false);
+			}
+			
+			JPanel checkBoxPanel = new JPanel();
+			checkBoxPanel.setLayout(new GridLayout(6,1));
+			checkBoxPanel.add(clearSelectionButton);
+			checkBoxPanel.add(setOriginallySelectedButton);
+			checkBoxPanel.add(this.symPrimary);
+			checkBoxPanel.add(this.ittPrimary);
+			checkBoxPanel.add(this.totalPercents);
+			checkBoxPanel.add(this.functionPercents);
+			
+			JScrollPane temp = new JScrollPane(this.threadList);
+			temp.setBorder(javax.swing.BorderFactory.createTitledBorder(null, Messages.getString("NewFunctionAnalyse.threadList"), //$NON-NLS-1$
+			        javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+			        javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
+			//temp.setColumnHeaderView(new JLabel("Thread list")); //tulee exceptioneja tästä
+			leftPanel.add(temp);
+			temp = new JScrollPane(this.binaryList);
+			temp.setBorder(javax.swing.BorderFactory.createTitledBorder(null, Messages.getString("NewFunctionAnalyse.binaryList"), //$NON-NLS-1$
+			        javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+			        javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
+			//temp.setColumnHeaderView(new JLabel("Binary list")); //tulee exceptioneja tästä
+			leftPanel.add(temp);
+			
+			leftPanel.add(checkBoxPanel);
+			
+			rightPanel.add(new JScrollPane(this.percentList));
+			this.functionSplit.setTopComponent(rightPanel);
+			this.functionSplit.setBottomComponent(new JPanel());
+						
+			split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+			split.setTopComponent(leftPanel);
+			split.setBottomComponent(this.functionSplit);
+			
+			frame.getContentPane().add(split);
+			
+
+            // frame.setVisible(true); //poikkeuksia
+
+
+			this.split.setDividerLocation((double)0.4);
+			if (this.gfcEnabled)
+				this.functionSplit.setDividerLocation((double)0.4);
+			else
+				this.functionSplit.setDividerLocation((double)1);					
+
+		}
+
+		String analysisName = ""; //$NON-NLS-1$
+		String modeString = ""; //$NON-NLS-1$
+		if (mode == Defines.THREADS || mode == Defines.THREADS_FUNCTIONS)
+		    modeString = Messages.getString("NewFunctionAnalyse.threadMode"); //$NON-NLS-1$
+		else if (mode == Defines.BINARIES || mode == Defines.BINARIES_FUNCTIONS)
+		    modeString = Messages.getString("NewFunctionAnalyse.binaryMode"); //$NON-NLS-1$
+		frame.setTitle(Messages.getString("NewFunctionAnalyse.functionAnalysis1") + analysisName + Messages.getString("NewFunctionAnalyse.functionAnalysis2")+ //$NON-NLS-1$ //$NON-NLS-2$
+							this.compositePanel.getSelectionStart()/1000.0+Messages.getString("NewFunctionAnalyse.functionAnalysis3")+ //$NON-NLS-1$
+							this.compositePanel.getSelectionEnd()/1000.0+Messages.getString("NewFunctionAnalyse.functionAnalysis4") + modeString); //$NON-NLS-1$
+		frame.validate();
+		frame.setVisible(true);
+	}
+	
+	private void extractSamples()
+	{		
+		getSelectedSamples(gppTrace);
+		getSelectedSamples(gfcTrace);
+		//getSelectedSamples(ittTrace);				
+	}
+	
+	private void getSelectedSamples(GenericSampledTrace gst)
+	{
+		if (gst != null)
+		{
+			int selectionStart = (int) this.compositePanel.getSelectionStart()+1;
+			int selectionEnd = (int) this.compositePanel.getSelectionEnd();
+		
+			System.out.println(Messages.getString("NewFunctionAnalyse.start")+selectionStart+Messages.getString("NewFunctionAnalyse.end")+selectionEnd); //$NON-NLS-1$ //$NON-NLS-2$
+			Vector s = gst.getSamplesInsideTimePeriod(selectionStart,selectionEnd);
+			System.out.println(Messages.getString("NewFunctionAnalyse.gotSamples")+s.size()); //$NON-NLS-1$
+			
+			if (gst instanceof GppTrace)
+			{
+				this.gppSamples = s;
+			}		
+			else if (gst instanceof GfcTrace)
+			{
+				this.gfcSamples = s;
+			}	
+			//else if (gst instanceof IttTrace)
+			//{
+			//	this.ittSamples = s;
+			//}
+		}	
+	}
+	
+	private void refreshThreadListComponent(boolean setValuesFromGraph)
+	{
+		threads = new Hashtable();
+		Vector listData = new Vector();
+		Enumeration enumer = this.gppSamples.elements();
+		Hashtable threadSampleAmount = new Hashtable();
+		
+		while(enumer.hasMoreElements())
+		{
+			//System.out.println("Class:"+enumer.nextElement().getClass().getName());
+			GppSample sample = (GppSample)enumer.nextElement();
+			String s = sample.thread.process.name+"::"+sample.thread.threadName+"_"+sample.thread.threadId; //$NON-NLS-1$ //$NON-NLS-2$
+			
+			if (!threads.containsKey(sample.thread.process.name+"::"+sample.thread.threadName+"_"+sample.thread.threadId)) //$NON-NLS-1$ //$NON-NLS-2$
+			{
+				threads.put(s,sample.thread);
+				//listData.add(sample.thread.process.name+"::"+sample.thread.threadName);
+				threadSampleAmount.put(s,new Integer(1));
+			}
+			else
+			{
+				int value = ((Integer)threadSampleAmount.get(s)).intValue();
+				threadSampleAmount.remove(s);
+				threadSampleAmount.put(s,new Integer(value+1));
+			}
+		}
+		
+		while(threadSampleAmount.size() > 0)
+		{
+			Enumeration sampEnum = threadSampleAmount.keys();
+			String threadName = ""; //$NON-NLS-1$
+			int maxValue = 0;
+			String maxString = ""; //$NON-NLS-1$
+
+			while(sampEnum.hasMoreElements())
+			{
+				threadName = (String)sampEnum.nextElement();
+				int value = ((Integer)threadSampleAmount.get(threadName)).intValue();
+				if (maxValue < value)
+				{
+					maxString = threadName;
+					maxValue = value;
+				}
+			}
+			threadSampleAmount.remove(maxString);
+			listData.add( maxValue+Messages.getString("NewFunctionAnalyse.samplesEqual")+((float)maxValue*100f)/this.gppSamples.size()+"% "+maxString); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		
+		if (this.threadList == null)
+		{
+			this.threadList = new JList(listData);
+			customKeys(threadList);
+			customKeys(threadList);
+			this.threadList.addListSelectionListener(this);
+		}
+		else
+		{
+			this.threadList.removeListSelectionListener(this);
+			
+			this.threadList.setListData(listData);
+
+			if (setValuesFromGraph && this.originallySelectedThreads != null)
+			{
+				Vector<Integer> selectedIndx = new Vector<Integer>();
+				for (int i=0;i<this.originallySelectedThreads.length;i++)
+				{
+					for (int k=0;k<listData.size();k++)
+					{
+						String test = ((String)listData.get(k));
+						test = test.substring(test.indexOf('%')+2,test.length());
+						if (test != null && this.originallySelectedThreads[i] != null)
+						{				
+							if (this.originallySelectedThreads[i].equals(test))
+							{
+								//System.out.println("Match:"+this.originallySelectedThreads[i]+" index "+k);
+								selectedIndx.add(new Integer(k));
+							}
+						}
+					}
+				}
+				
+				if (selectedIndx.size() > 0)
+				{
+					this.originallySelectedIndices = new int[selectedIndx.size()];
+					for (int i=0;i<this.originallySelectedIndices.length;i++)
+					{
+						this.originallySelectedIndices[i] = selectedIndx.elementAt(i);
+					}
+					this.threadList.setSelectedIndices(this.originallySelectedIndices);
+				}
+			}
+			this.threadList.addListSelectionListener(this);
+		}
+	}
+	
+	private void refreshBinaryListComponent(boolean setValuesFromGraph)
+	{
+	    binaries = new Hashtable();
+		Vector<BinaryNameItem> listData = new Vector<BinaryNameItem>();
+		Enumeration enumer = this.gppSamples.elements();
+		Hashtable<BinaryNameItem,Integer> binarySampleAmount = new Hashtable<BinaryNameItem,Integer>();
+		
+		while(enumer.hasMoreElements())
+		{
+			//System.out.println("Class:"+enumer.nextElement().getClass().getName());
+			GppSample sample = (GppSample)enumer.nextElement();
+			//String s = this.getBinaryNameForGppSample(sample).toString();
+			BinaryNameItem bi = this.getBinaryNameForGppSample(sample);
+			boolean containsKey = false;
+			for (Enumeration e = binaries.keys(); e.hasMoreElements();)
+			{
+			    String tmp = ((BinaryNameItem)e.nextElement()).toString();
+			    if (tmp.equalsIgnoreCase(bi.toString()))
+			    {
+			        containsKey = true;
+			        break;
+			    }
+			}
+			if (!containsKey)
+		    {
+		        binaries.put(bi, sample);
+		        binarySampleAmount.put(bi, new Integer(1));
+		    }
+		    else
+		    {
+		        for (Enumeration<BinaryNameItem> e = binarySampleAmount.keys(); e.hasMoreElements();)
+		        {
+		            BinaryNameItem biTemp = e.nextElement();
+		            if (biTemp.toString().equalsIgnoreCase(bi.toString()))
+		            {
+		                int value = ((Integer)binarySampleAmount.get(biTemp)).intValue();
+		                binarySampleAmount.remove(biTemp);
+						binarySampleAmount.put(biTemp, new Integer(value+1));
+		            }
+		        }
+		    }
+		}
+
+		int totalSamples = 0;
+		while(binarySampleAmount.size() > 0)
+		{
+		    Enumeration<BinaryNameItem> sampEnum = binarySampleAmount.keys();
+
+			BinaryNameItem binaryName;
+			int maxValue = 0;
+			BinaryNameItem maxItem = null;
+
+			while(sampEnum.hasMoreElements())
+			{
+			    binaryName = sampEnum.nextElement();
+				int value = binarySampleAmount.get(binaryName);
+				if (maxValue < value)
+				{
+					maxItem = binaryName;
+					maxValue = value;
+				}
+			}
+			binarySampleAmount.remove(maxItem);
+			totalSamples += maxValue;
+
+			maxItem.setSampleAmount(maxValue);
+			listData.add(maxItem);
+		}
+		
+		for (Enumeration<BinaryNameItem> e = listData.elements();e.hasMoreElements();)
+		{
+			BinaryNameItem item = e.nextElement();
+			item.setTotalSampleAmount(totalSamples);
+		}
+		
+		if (this.binaryList == null)
+		{
+			this.binaryList = new JList(listData);
+			customKeys(binaryList);
+			this.binaryList.setCellRenderer(new FunctionItemRenderer());
+			this.binaryList.addListSelectionListener(this);
+		}
+		else
+		{
+			this.binaryList.removeListSelectionListener(this);
+			this.binaryList.setListData(listData);
+
+			if (setValuesFromGraph && this.originallySelectedBinaries != null)
+			{
+				Vector<Integer> selectedIndx = new Vector<Integer>();
+				for (int i=0;i<this.originallySelectedBinaries.length;i++)
+				{
+					for (int k=0;k<listData.size();k++)
+					{
+						//String test = ((String)listData.get(k));
+						String test = listData.get(k).toString();
+						//test = test.substring(test.indexOf('%')+2,test.length());
+						if (test != null && this.originallySelectedBinaries[i] != null)
+						{				
+							if (this.originallySelectedBinaries[i].equalsIgnoreCase(test))
+							{
+								//System.out.println("Match:"+this.originallySelectedThreads[i]+" index "+k);
+								selectedIndx.add(new Integer(k));
+							}
+						}
+					}
+				}
+				
+				if (selectedIndx.size() > 0)
+				{
+					this.originallySelectedIndices = new int[selectedIndx.size()];
+					for (int i=0;i<this.originallySelectedIndices.length;i++)
+					{
+						this.originallySelectedIndices[i] = selectedIndx.elementAt(i);
+					}
+					this.binaryList.setSelectedIndices(this.originallySelectedIndices);
+				}
+			}
+			this.binaryList.addListSelectionListener(this);
+		}
+	}
+	
+	private void refreshThreadListComponentSec()
+	{
+	    threadVector = new Vector();
+		Vector listData = new Vector();
+		Vector threadSampleAmount = new Vector();
+//		Object[] selectedBinaries = this.removePercents(this.binaryList.getSelectedValues());
+		Object[] selectedBinaries = this.binaryList.getSelectedValues();
+		
+		Enumeration enumer = this.gppSamples.elements();
+		
+		while(enumer.hasMoreElements())
+		{
+			boolean match = false;
+			GppSample sample = (GppSample)enumer.nextElement();
+			for (int i=0;i<selectedBinaries.length;i++)
+			{
+				if ((this.getBinaryNameForGppSample(sample).toString()).
+				        equalsIgnoreCase(selectedBinaries[i].toString()))
+				{
+					match = true;
+					break;
+				}
+			}
+			
+			if (match == true)
+			{
+				String threadName = sample.thread.process.name+"::"+sample.thread.threadName+"_"+sample.thread.threadId; //$NON-NLS-1$ //$NON-NLS-2$
+	
+				if (!threadVector.contains(threadName))
+				{
+					threadVector.add(threadName);
+					threadSampleAmount.add(new Integer(1));
+				}
+				else
+				{	
+					//int value = ((Integer)binarySampleAmount.get(binaryName)).intValue();
+					int index = threadVector.indexOf(threadName);
+					int value = ((Integer)threadSampleAmount.get(index)).intValue();
+					
+					threadSampleAmount.remove(index);
+					threadSampleAmount.add(index,new Integer(value+1));
+				}
+			}
+		}
+		
+		int totalSamples = 0;
+		while(threadSampleAmount.size() > 0)
+		{
+			String sampItem = null;
+			int maxValue = 0;
+			String maxString = null;
+			int maxIndex = 0; 
+			
+			for (int i=0;i<this.threadVector.size();i++)
+			{
+				sampItem = (String)threadVector.get(i);
+				int value = ((Integer)threadSampleAmount.get(i)).intValue();
+				if (maxValue < value)
+				{
+					maxString = sampItem;
+					maxValue = value;
+					maxIndex = i;
+				}
+			}
+			threadSampleAmount.remove(maxIndex);
+			threadVector.remove(maxIndex);
+			totalSamples += maxValue;
+			
+			listData.add( maxValue+Messages.getString("NewFunctionAnalyse.samplesEqual")+((float)maxValue*100f)/this.gppSamples.size()+"% "+maxString); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		
+		if (this.threadList == null)
+		{
+			this.threadList = new JList(listData);
+			customKeys(threadList);
+			//this.threadList.setCellRenderer(new FunctionItemRenderer());
+			this.threadList.addListSelectionListener(this);
+		}
+		else
+		{			
+			Object[] valueStore = this.threadList.getSelectedValues();
+			Vector indexStore = new Vector();
+			Vector notVisibleStore = new Vector();
+			
+			for (int i=0;i<valueStore.length;i++)
+			{
+				int counter = 0;
+				boolean found = false;
+			    for (Enumeration e = listData.elements(); e.hasMoreElements(); counter++)
+			    {
+			        String listElement = (String)e.nextElement();
+			        listElement =  listElement.substring(listElement.indexOf("% ")+2,listElement.length()); //$NON-NLS-1$
+			        String valueString = (String)valueStore[i];
+			        valueString =  valueString.substring(valueString.indexOf("% ")+2,valueString.length()); //$NON-NLS-1$
+			        if (listElement.equals(valueString))
+			        {
+			            found = true;
+			            break;
+			        }
+			    }
+//			    int index = listData.indexOf(valueStore[i]);
+			    int index = (found) ? counter : -1;
+				if (index != -1)
+				{
+					indexStore.add(new Integer(index));
+				}
+				else
+				{
+					notVisibleStore.add(valueStore[i]);
+				}
+			}
+			
+			for (Enumeration e=this.selectedButNotVisibleThreads.elements();e.hasMoreElements();)
+			{
+				Object value = e.nextElement();
+				int counter = 0;
+				boolean found = false;
+				for (Enumeration enume = listData.elements(); enume.hasMoreElements(); counter++)
+			    {
+			        String listElement = (String)enume.nextElement();
+			        listElement =  listElement.substring(listElement.indexOf("% ")+2,listElement.length()); //$NON-NLS-1$
+			        String valueString = (String)value;
+			        valueString =  valueString.substring(valueString.indexOf("% ")+2,valueString.length()); //$NON-NLS-1$
+			        if (listElement.equals(valueString))
+			        {
+			            found = true;
+			            break;
+			        }
+			    }
+			    int index = (found) ? counter : -1;
+//				int index = listData.indexOf(value);
+				if (index != -1)
+				{
+					indexStore.add(new Integer(index));
+				}
+				else
+				{
+					notVisibleStore.add(value);
+				}
+			}
+			this.threadList.removeListSelectionListener(this);
+			this.threadList.setListData(listData);
+
+			if (indexStore.size() != 0)
+			{
+				int[] indexList = new int[indexStore.size()];
+				for (int i=0;i<indexStore.size();i++)
+				{
+					indexList[i] = ((Integer)indexStore.elementAt(i)).intValue();
+				}
+				this.threadList.setSelectedIndices(indexList);
+			}			
+			
+			this.selectedButNotVisibleThreads.clear();
+			this.selectedButNotVisibleThreads.addAll(notVisibleStore);
+			this.threadList.addListSelectionListener(this);
+
+		}
+	}
+	private void refreshBinaryListComponentSec()
+	{
+		binaryVector = new Vector();
+		Vector listData = new Vector();
+		Vector binarySampleAmount = new Vector();
+		Object[] selectedThreads = this.removePercents(this.threadList.getSelectedValues());
+		
+		Enumeration enumer = this.gppSamples.elements();
+		
+		while(enumer.hasMoreElements())
+		{
+			boolean match = false;
+			GppSample sample = (GppSample)enumer.nextElement();
+			for (int i=0;i<selectedThreads.length;i++)
+			{
+				if ((sample.thread.process.name+"::"+sample.thread.threadName+"_"+sample.thread.threadId).equals(selectedThreads[i])) //$NON-NLS-1$ //$NON-NLS-2$
+				{
+					match = true;
+					break;
+				}
+			}
+			
+			if (match == true)
+			{
+				BinaryNameItem binaryName = getBinaryNameForGppSample(sample);
+	
+				if (!binaryVector.contains(binaryName))
+				{
+					binaryVector.add(binaryName);
+					binarySampleAmount.add(new Integer(1));
+				}
+				else
+				{	
+					//int value = ((Integer)binarySampleAmount.get(binaryName)).intValue();
+					int index = binaryVector.indexOf(binaryName);
+					int value = ((Integer)binarySampleAmount.get(index)).intValue();
+					
+					binarySampleAmount.remove(index);
+					binarySampleAmount.add(index,new Integer(value+1));
+				}
+			}
+		}
+		
+		int totalSamples = 0;
+		while(binarySampleAmount.size() > 0)
+		{
+			BinaryNameItem sampItem = null;
+			int maxValue = 0;
+			BinaryNameItem maxItem = null;
+			int maxIndex = 0; 
+			
+			for (int i=0;i<this.binaryVector.size();i++)
+			{
+				sampItem = (BinaryNameItem)binaryVector.get(i);
+				int value = ((Integer)binarySampleAmount.get(i)).intValue();
+				if (maxValue < value)
+				{
+					maxItem = sampItem;
+					maxValue = value;
+					maxIndex = i;
+				}
+			}
+			binarySampleAmount.remove(maxIndex);
+			binaryVector.remove(maxIndex);
+			totalSamples += maxValue;
+
+			maxItem.setSampleAmount(maxValue);
+			listData.add(maxItem);
+		}
+		
+		for (Enumeration e = listData.elements();e.hasMoreElements();)
+		{
+			BinaryNameItem item = (BinaryNameItem)e.nextElement();
+			item.setTotalSampleAmount(totalSamples);
+		}
+		
+		if (this.binaryList == null)
+		{
+			this.binaryList = new JList(listData);
+			customKeys(binaryList);
+			this.binaryList.setCellRenderer(new FunctionItemRenderer());
+			this.binaryList.addListSelectionListener(this);
+		}
+		else
+		{			
+			Object[] valueStore = this.binaryList.getSelectedValues();
+			Vector indexStore = new Vector();
+			Vector notVisibleStore = new Vector();
+			
+			for (int i=0;i<valueStore.length;i++)
+			{
+				int index = listData.indexOf(valueStore[i]);
+				if (index != -1)
+				{
+					indexStore.add(new Integer(index));
+				}
+				else
+				{
+					notVisibleStore.add(valueStore[i]);
+				}
+			}
+			
+			for (Enumeration e=this.selectedButNotVisibleBinaries.elements();e.hasMoreElements();)
+			{
+				Object value = e.nextElement();
+				int index = listData.indexOf(value);
+				if (index != -1)
+				{
+					indexStore.add(new Integer(index));
+				}
+				else
+				{
+					notVisibleStore.add(value);
+				}
+			}
+
+			this.binaryList.removeListSelectionListener(this);
+			this.binaryList.setListData(listData);
+
+			if (indexStore.size() != 0)
+			{
+				int[] indexList = new int[indexStore.size()];
+				for (int i=0;i<indexStore.size();i++)
+				{
+					indexList[i] = ((Integer)indexStore.elementAt(i)).intValue();
+				}
+				this.binaryList.setSelectedIndices(indexList);
+			}			
+			
+			this.selectedButNotVisibleBinaries.clear();
+			this.selectedButNotVisibleBinaries.addAll(notVisibleStore);
+			this.binaryList.addListSelectionListener(this);
+		}
+	}
+	
+	private Object[] removePercents(Object[] data)
+	{
+		String[] fin = new String[data.length];
+		for (int i=0;i<data.length;i++)
+		{
+			String s = (String)data[i];
+			fin[i] = s.substring(s.indexOf("% ")+2,s.length()); //$NON-NLS-1$
+		}
+		return fin;
+	}
+	
+	private void refreshPercentListComponent()
+	{
+	    if (threadList == null)
+	        return;
+	    Vector percentData = new Vector();
+		Object[] selectedThreads = this.removePercents(this.threadList.getSelectedValues());
+		selectedBinaries = this.binaryList.getSelectedValues();
+//		if ((selectedBinaries != null) && (oldSelectedBinaries != null) && !stateChanged)
+//			if (selectedBinaries.length == oldSelectedBinaries.length)
+//			{
+//				boolean similar = true;
+//				for (int i=0;i<selectedBinaries.length;i++)
+//				{
+//					if (selectedBinaries[i].hashCode() != oldSelectedBinaries[i].hashCode())
+//					{
+//						similar = false;
+//						break;
+//					}
+//				}
+//				if (similar)
+//					return;
+//			}
+//		stateChanged = false;
+				
+		this.percentList = new JList();
+		customKeys(percentList);
+		Vector percentValueList = new Vector();
+		Vector functionIndexList = new Vector();
+		
+		int totalSamples = 0;
+		
+		Enumeration enumer = this.gppSamples.elements();
+		while(enumer.hasMoreElements())
+		{
+			GppSample s = (GppSample)enumer.nextElement();
+			boolean match = false;
+			// check if the thread has been selected from the thread list
+			for (int i=0;i<selectedThreads.length;i++)
+			{
+				String st = (String)selectedThreads[i];
+				int threadId = Integer.parseInt(st.substring (st.lastIndexOf("_")+1,st.length()) ); //$NON-NLS-1$
+				if (s.thread.threadId.intValue() == threadId)
+				{
+					match = true;
+					// yes, go ahead
+					break;
+				}
+			}
+			
+			if (match == true)
+			{
+				match = false;
+				for (int i=0;i<selectedBinaries.length;i++)
+				{
+					BinaryNameItem binaryName = getBinaryNameForGppSample(s);
+					
+					if (binaryName.equals(selectedBinaries[i]))
+					{
+						match = true;
+						break;
+					}
+				}
+			}
+			
+			// from now on, the match variable tells whether the function has already been
+			// found from the previous samples
+			if (match == true)
+			{
+				match = false;
+				for (int i=0;i<percentData.size();i++)
+				{
+					FunctionNameItem test = (FunctionNameItem)percentData.elementAt(i);
+					if (test.equals(getFunctionNameForGppSample(s)))
+					{
+						match = true;
+						break;
+					}
+				}
+					
+				if (!match)
+				{
+					// add the function name to percentData
+					percentData.add(getFunctionNameForGppSample(s));
+					// this is the first sample for this function, thus add number 1
+					// to the percent value list
+					percentValueList.add(new Integer(1));
+					// add a vector for the function offset values
+					
+					if (this.functionPercents.isSelected() == true)
+					{
+						Vector functionIndexVector = new Vector();
+						Long offset = getFunctionOffsetForGppSample(s);
+						functionIndexVector.add(offset);
+						functionIndexList.add(functionIndexVector);
+					}
+
+					//System.out.println("Added name "+s.currentFunctionSym.functionName);
+					totalSamples++;
+				}
+				else
+				{
+					int index = percentData.indexOf(getFunctionNameForGppSample(s));
+					
+					/*
+					System.out.println("old "+((String)percentData.elementAt(index))+
+							" = "+
+							((Integer)percentValueList.elementAt(index)).intValue());
+					*/
+					
+					Integer value = (Integer)percentValueList.elementAt(index);
+					percentValueList.remove(index);
+					percentValueList.add(index,new Integer(value.intValue()+1));
+					
+					if (this.functionPercents.isSelected() == true)
+					{					
+						Vector functionIndexVector = (Vector)functionIndexList.elementAt(index);
+						Long offset = getFunctionOffsetForGppSample(s);
+						functionIndexVector.add(offset);
+					}
+					
+					totalSamples++;
+				}
+			}
+		}
+		
+		if (totalSamples != 0)
+		{
+			sortFunctionIndexList(functionIndexList);
+			Vector finalList = this.sortPercentData(percentValueList,percentData,functionIndexList,totalSamples);
+			
+			if (this.percentList == null)
+			{
+				this.percentList = new JList(finalList);
+				customKeys(percentList);
+				this.percentList.setCellRenderer(new FunctionItemRenderer());
+				JScrollPane temp = new JScrollPane(this.percentList);
+				if (this.gfcEnabled)
+				{
+				    temp.setBorder(javax.swing.BorderFactory.createTitledBorder(null, Messages.getString("NewFunctionAnalyse.functionPercentListDoubleClick"), //$NON-NLS-1$
+					        javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+					        javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
+//					temp.setColumnHeaderView(
+//							new JLabel("Function percent list - double click to see the function in the linked function view"));
+				}
+				else
+				{
+				    temp.setBorder(javax.swing.BorderFactory.createTitledBorder(null, Messages.getString("NewFunctionAnalyse.functionPercentList"), //$NON-NLS-1$
+					        javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+					        javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
+//				    temp.setColumnHeaderView(
+//							new JLabel("Function percent list"));
+				}
+				this.functionSplit.setTopComponent(temp);
+//				this.split.setDividerLocation((double)0.4);
+				if (this.gfcEnabled)
+					this.functionSplit.setDividerLocation((double)0.4);
+				else
+					this.functionSplit.setDividerLocation((double)1);					
+			}
+			else
+			{
+				this.percentList = new JList(finalList);
+				customKeys(percentList);
+				this.percentList.setCellRenderer(new FunctionItemRenderer());
+				this.percentList.addMouseListener(new MouseAdapter()
+				{
+				 public void mouseClicked(MouseEvent e) 
+					{
+				 	if (e.getClickCount() > 1)
+				 		{
+				 			showLinkedData();
+				 		}
+					}
+				});
+
+				JScrollPane temp = new JScrollPane(this.percentList);
+				if (this.gfcEnabled)
+				{
+				    temp.setBorder(javax.swing.BorderFactory.createTitledBorder(null, Messages.getString("NewFunctionAnalyse.functionPercentListDoubleClick"), //$NON-NLS-1$
+					        javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+					        javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
+//					temp.setColumnHeaderView(
+//							new JLabel("Function percent list - double click to see the function in the linked function view"));
+				}
+				else
+				{
+				    temp.setBorder(javax.swing.BorderFactory.createTitledBorder(null, Messages.getString("NewFunctionAnalyse.functionPercentList"), //$NON-NLS-1$
+					        javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION,
+					        javax.swing.border.TitledBorder.DEFAULT_POSITION, null, null));
+//				    temp.setColumnHeaderView(
+//							new JLabel("Function percent list"));
+				}	
+				this.functionSplit.setTopComponent(temp);
+				
+//				this.split.setDividerLocation((double)0.4);
+				if (this.gfcEnabled)
+					this.functionSplit.setDividerLocation((double)0.4);
+				else
+					this.functionSplit.setDividerLocation((double)1);					
+			}
+		}	
+		else if (this.split != null)
+		{
+			Vector finalList = new Vector();
+			this.percentList = new JList(finalList);
+			customKeys(percentList);
+			this.percentList.setCellRenderer(new FunctionItemRenderer());
+			this.functionSplit.setTopComponent(new JScrollPane(this.percentList));
+//			this.split.setDividerLocation((double)0.4);
+			if (this.gfcEnabled)
+				this.functionSplit.setDividerLocation((double)0.4);
+			else
+				this.functionSplit.setDividerLocation((double)1);					
+		}
+//		oldSelectedBinaries = selectedBinaries;
+	}
+	
+	private BinaryNameItem getBinaryNameForGppSample(GppSample s)
+	{
+		String binaryName;
+		if (this.symbolPrimary || this.ittTrace == null)
+		{
+			binaryName = s.currentFunctionSym.functionBinary.binaryName;
+			if (!binaryName.endsWith(Messages.getString("NewFunctionAnalyse.notFound"))) //$NON-NLS-1$
+				return new BinaryNameItem(binaryName,false);
+		}
+
+		if (s.currentFunctionItt != null)
+		{
+			binaryName = s.currentFunctionItt.functionBinary.binaryName;
+			if (!binaryName.endsWith(Messages.getString("NewFunctionAnalyse.notFound"))) //$NON-NLS-1$
+			{
+				return new BinaryNameItem(binaryName,true);
+			}
+			else
+			{
+				binaryName = s.currentFunctionSym.functionBinary.binaryName;
+				if (binaryName.endsWith(Messages.getString("NewFunctionAnalyse.notFound"))) //$NON-NLS-1$
+					return new BinaryNameItem(Messages.getString("NewFunctionAnalyse.binaryNotFound"),true); //$NON-NLS-1$
+				else
+					return new BinaryNameItem(binaryName,false);
+			}			
+		}
+		else if (!s.currentFunctionSym.functionBinary.binaryName.endsWith(Messages.getString("NewFunctionAnalyse.notFound"))) //$NON-NLS-1$
+		{
+			binaryName = s.currentFunctionSym.functionBinary.binaryName;
+			return new BinaryNameItem(binaryName,false);
+		}
+		else
+		{
+			return new BinaryNameItem(Messages.getString("NewFunctionAnalyse.binaryNotFound"),false); //$NON-NLS-1$
+		}
+	}
+/*	
+	private IttSample getIttSampleForGppSample(GppSample s)
+	{
+		IttSample first = (IttSample)this.ittSamples.firstElement();
+		IttSample ittSample = null;
+		int diff = (int)(s.sampleSynchTime-first.sampleSynchTime);
+		
+		// the sample was found from the first index
+		if (diff == 0) return first;
+		
+		// normal case, the first itt sample number is smaller than the
+		// required sample number
+		if (diff > 0)
+		{
+			if (diff < this.ittSamples.size())
+			{
+				// try from the itt sample array, from the location
+				// marked by the diff value between the sample synch times
+				ittSample = (IttSample)this.ittSamples.elementAt(diff);
+				
+				if (ittSample.sampleSynchTime == s.sampleSynchTime)
+				{
+					// the right sample was found with the diff offset 
+					return ittSample; 
+				}
+			}
+			else
+			{
+				// the index points outside the itt sample array
+				// take the last itt sample
+				ittSample = (IttSample)this.ittSamples.lastElement();
+				diff = this.ittSamples.size()-1;
+			}
+		}
+		else
+		{
+			// the requested sample is outside the itt sample range
+			// (smaller than the first element)
+			return null;
+		}
+		
+		if ( ((IttSample)this.ittSamples.lastElement()).sampleSynchTime < s.sampleSynchTime)
+		{
+			// the requested sample is outside the itt sample range
+			// (larger than the last element)
+			return null;
+		}
+		
+		// the requested sample is in the itt sample range
+		// start with the current element and go backwards until it
+		// is found, or the correct one is not found
+		while(ittSample.sampleSynchTime > s.sampleSynchTime)
+		{
+			diff--;
+			ittSample = (IttSample)this.ittSamples.elementAt(diff);
+		}
+		
+		if (ittSample.sampleSynchTime == s.sampleSynchTime)
+		{
+			// the sample was finally found
+			return ittSample;
+		}
+		else
+		{
+			// this sample number is missing from the ITT trace
+			return null;
+		}
+		
+	}
+	*/
+	
+	private Long getFunctionOffsetForGppSample(GppSample s)
+	{
+		//String functionName;
+		if ((this.symbolPrimary || this.ittTrace == null) && 
+				!s.currentFunctionSym.functionBinary.binaryName.endsWith(Messages.getString("NewFunctionAnalyse.notFound")) ) //$NON-NLS-1$
+		{
+			return new Long(s.programCounter-s.currentFunctionSym.startAddress.longValue());
+		}
+		if (s.currentFunctionItt != null && !s.currentFunctionItt.functionName.endsWith(Messages.getString("NewFunctionAnalyse.notFound"))) //$NON-NLS-1$
+		{
+			//System.out.println("OFF:"+(s.programCounter-s.currentFunctionItt.startAddress.longValue())+" PC: "+Long.toHexString(s.programCounter)+" start"+Long.toHexString(s.currentFunctionItt.startAddress.longValue()));
+			return new Long(s.programCounter-s.currentFunctionItt.startAddress.longValue());
+		}
+		else if (s.currentFunctionSym != null)
+		{
+			return new Long(s.programCounter-s.currentFunctionSym.startAddress.longValue());
+		}
+		else
+		{
+			return new Long(666666);
+		}		
+	}
+	
+	private FunctionNameItem getFunctionNameForGppSample(GppSample s)
+	{
+		String functionName;
+		if (this.symbolPrimary || this.ittTrace == null)
+		{
+//			functionName = s.currentFunctionSym.functionName;
+//			if (!functionName.endsWith("not found"))
+//				return new FunctionNameItem(functionName,s.currentFunctionSym,false);
+			FunctionNameItem item = (FunctionNameItem)this.functionNameCacheSym.get(s);
+			if (item != null) 
+			{	
+				return item;
+			}
+			else
+			{
+				functionName = s.currentFunctionSym.functionName;
+				if (!functionName.endsWith(Messages.getString("NewFunctionAnalyse.notFound"))) //$NON-NLS-1$
+				{					
+					item = new FunctionNameItem(functionName,s.currentFunctionSym,false);
+					this.functionNameCacheSym.put(s,item);
+					return item;
+				}
+			}
+		}
+		
+		if (s.currentFunctionItt != null)
+		{
+			FunctionNameItem item = (FunctionNameItem)this.functionNameCacheItt.get(s);
+			if (item != null) return item;
+			
+			functionName = s.currentFunctionItt.functionName;
+
+			if (!functionName.endsWith(Messages.getString("NewFunctionAnalyse.notFound"))) //$NON-NLS-1$
+			{
+				item = new FunctionNameItem(functionName,s.currentFunctionItt,true);
+				this.functionNameCacheItt.put(s,item);
+				return item;
+//				return new FunctionNameItem(functionName,s.currentFunctionItt,true);
+			}
+			else
+			{
+				item = (FunctionNameItem)this.functionNameCacheSym.get(s);
+				if (item != null) return item;
+				
+				functionName = s.currentFunctionSym.functionName;
+				item = new FunctionNameItem(functionName,s.currentFunctionSym,false);
+				this.functionNameCacheSym.put(s,item);
+				return item;
+//				return new FunctionNameItem(functionName,s.currentFunctionSym,false);
+			}
+		}
+		else if (s.currentFunctionSym != null)
+		{
+			FunctionNameItem item = (FunctionNameItem)this.functionNameCacheSym.get(s);
+			if (item != null) return item;
+			
+			functionName = s.currentFunctionSym.functionName;
+			item = new FunctionNameItem(functionName,s.currentFunctionSym,false);
+			this.functionNameCacheSym.put(s,item);
+			return item;
+//			return new FunctionNameItem(functionName,s.currentFunctionSym,false);
+		}
+		else
+		{
+			FunctionNameItem item = new FunctionNameItem(Messages.getString("NewFunctionAnalyse.functionNotFound"),null,false); //$NON-NLS-1$
+			this.functionNameCacheItt.put(s,item);
+			this.functionNameCacheSym.put(s,item);
+			return item;
+//			return new FunctionNameItem("Function not found",null,false);
+		}
+	}
+	
+	private void sortFunctionIndexList(Vector offsets)
+	{
+		class IndexElement implements Sortable
+		{
+			long offset;
+			int count;
+			
+			public long valueOf()
+			{
+				return count;
+			}
+		}
+		
+		for (Enumeration e=offsets.elements();e.hasMoreElements();)
+		{
+			Vector functionOffsets = (Vector)e.nextElement();
+
+			Hashtable temp = new Hashtable();
+			
+			// count together the amounts of each offset
+			for (Enumeration b=functionOffsets.elements();b.hasMoreElements();)
+			{
+				Long offset = (Long)b.nextElement();
+				IndexElement ie = (IndexElement)temp.get(offset);
+				if (ie != null)
+				{
+					ie.count++;
+					//temp.remove(offset);
+					//count = new Long(count.longValue()+1);
+					//temp.put(offset,count);
+				}
+				else
+				{
+					ie = new IndexElement();
+					ie.count = 1;
+					ie.offset = offset.longValue();
+					temp.put(offset,ie);
+					//count = new Long(1);
+					//temp.put(offset,count);
+				}
+			}
+
+			//int tempCount = 0;
+			//for (Enumeration b=temp.elements();b.hasMoreElements();)
+			//{
+			//	Long l = (Long)b.nextElement();
+			//	tempCount+=l.longValue();
+			//}
+			
+			// all offsets counted together, now sort and put back to original vector
+			// the vector will then contain amount/offset pairs of data each element pair
+			// one after another
+			functionOffsets.clear();
+			Vector tempVec = new Vector();
+			tempVec.addAll(temp.values());
+			QuickSortImpl.sort(tempVec);
+			Enumeration finalEnum = tempVec.elements();
+			
+			while(finalEnum.hasMoreElements())
+			{
+				IndexElement ie = (IndexElement)finalEnum.nextElement();
+				functionOffsets.add(new Long(ie.offset));
+				functionOffsets.add(new Long(ie.count));
+			}
+			//System.out.print(" new count: "+functionOffsets.size()+"\n");
+			/*
+			long totalAmount=0;
+
+			while(temp.size()>0)
+			{
+				long largestAmount=0;
+				long largestOffset=0;
+
+				for (Enumeration keys = temp.keys();keys.hasMoreElements();)
+				{
+					Long offset = (Long)keys.nextElement();
+					Long amount = (Long)temp.get(offset);
+					if (amount.longValue()>largestAmount) 
+					{
+						largestAmount = amount.longValue();
+						largestOffset = offset.longValue();
+					}
+				}
+
+				temp.remove(new Long(largestOffset));
+				functionOffsets.add(new Long(largestOffset));
+				functionOffsets.add(new Long(largestAmount));
+				totalAmount+=largestAmount;
+			}	*/	
+		}
+	}
+	
+	private Vector sortPercentData(Vector percents, Vector names,Vector offsets,int totalSamples)
+	{
+		for (int i=0;i<names.size();i++)
+		{
+			FunctionNameItem item = (FunctionNameItem)names.get(i);
+			item.setTotalSampleAmount(totalSamples);
+			item.setSampleAmount(((Integer)percents.elementAt(i)).intValue());
+			
+			Vector offsetVector = null;
+			if (functionPercents.isSelected() == true)
+			{
+				offsetVector = (Vector)offsets.elementAt(i);
+			}
+			item.setOffsetVector(offsetVector);
+		}
+		QuickSortImpl.sortReversed(names);
+		return names;
+	}
+
+	private boolean updating = false;
+	
+	public void valueChanged(ListSelectionEvent lse)
+	{
+		if (lse.getValueIsAdjusting())
+			return;
+		
+		if (updating == true) 
+		{
+			return;
+		}
+		
+		updating = true;
+		
+		if (lse.getSource() == this.threadList && (mode == Defines.THREADS || mode == Defines.THREADS_FUNCTIONS))
+			this.refreshBinaryListComponentSec();
+		else if (lse.getSource() == this.binaryList && (mode == Defines.BINARIES || mode == Defines.BINARIES_FUNCTIONS))
+		    this.refreshThreadListComponentSec();
+		
+		this.refreshPercentListComponent();
+		
+		updating = false;
+	}
+	
+	public void updateGfc()
+	{
+		if (this.gfcEnabled == false)
+			return;
+		
+		if (this.updateThread != null)
+			return;
+
+		updateThread = new Thread()
+		{
+			public void run()
+			{
+			if (gfcTrace != null)
+				{
+				gfcTraceVisualiser = new GfcTraceVisualiser(gfcTrace);
+		
+				gfcTraceVisualiser.setStartAndEnd((int)((GfcSample)gfcSamples.firstElement()).sampleNumber
+						,(int)((GfcSample)gfcSamples.lastElement()).sampleNumber,
+						symbolPrimary);
+		
+				JPanel linkedPanel = new JPanel();
+				linkedPanel.setLayout(new BorderLayout());
+				linkedPanel.add(gfcTraceVisualiser.getCalleeList(),BorderLayout.NORTH);
+				linkedPanel.add(gfcTraceVisualiser.getCenterPanel(),BorderLayout.CENTER);
+				linkedPanel.add(gfcTraceVisualiser.getCallerList(),BorderLayout.SOUTH);
+				linkedPanel.add(gfcTraceVisualiser.getSelectionPanel(),BorderLayout.WEST);
+      
+				functionSplit.setBottomComponent(linkedPanel);
+				functionSplit.setDividerLocation((double)0.4);
+				functionSplit.revalidate();
+				functionSplit.updateUI();
+				updateUI();
+	
+				if (mode == Defines.BINARIES || mode == Defines.BINARIES_FUNCTIONS)
+				{
+				    refreshThreadListComponentSec();
+				}
+				else
+				{
+				    refreshBinaryListComponentSec();
+				};
+				refreshPercentListComponent();
+				updateThread = null;
+				}
+			}
+		};
+		updateThread.start();
+	}
+	
+	public void stateChanged(ChangeEvent ce)
+	{
+		if (this.updating == true) return;
+		
+		this.updating = true;
+		
+		if (ce.getSource() == this.totalPercents)
+		{
+			this.refreshPercentListComponent();
+			if (mode == Defines.BINARIES || mode == Defines.BINARIES_FUNCTIONS)
+			{
+			    refreshThreadListComponentSec();
+			}
+			else
+			{
+			    refreshBinaryListComponentSec();
+			}
+		}
+		else if (ce.getSource() == this.functionPercents)
+		{
+			this.refreshPercentListComponent();
+		}
+		
+		this.updating = false;
+	}
+	
+	public void customKeys(JList list)
+	{
+	    final JList tmpList = list;
+	    list.getInputMap().put(KeyStroke.getKeyStroke("control C"), "ctrl c"); //$NON-NLS-1$ //$NON-NLS-2$
+		
+		list.getActionMap().put("ctrl c", //$NON-NLS-1$
+	            new AbstractAction("ctrl c")  //$NON-NLS-1$
+	            {
+					private static final long serialVersionUID = 4692089714529176119L;
+
+					public void actionPerformed(ActionEvent evt) 
+	                {      
+	                    String toClipboard = ""; //$NON-NLS-1$
+	                    Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+	        			StringSelection contents;
+	                    Object[] listValues = tmpList.getSelectedValues();
+	                    for (int i = 0; i < listValues.length; i++)
+	                    {
+	                        Object listValue = listValues[i];
+	                        if (listValue instanceof String)
+	                        {
+	                            toClipboard += (String)listValue + "\n"; //$NON-NLS-1$
+	                        }
+	                        else if (listValue instanceof BinaryNameItem)
+	                        {
+	                            BinaryNameItem item = (BinaryNameItem)listValue;
+	                            if (totalPercents.isSelected())
+	            					toClipboard += item.sampleAmount+Messages.getString("NewFunctionAnalyse.samplesEqual")+((float)item.sampleAmount*100f)/gppSamples.size()+"% "+item + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	            				else 
+	            					toClipboard += item.sampleAmount+Messages.getString("NewFunctionAnalyse.samplesEqual")+((float)item.sampleAmount*100f)/item.totalSamples+"% "+item + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	                        }
+	                        else if (listValue instanceof FunctionNameItem)
+	                        {
+	                            FunctionNameItem item = (FunctionNameItem)listValue;
+	                            String offsetString = ""; //$NON-NLS-1$
+	            				
+	            				if (functionPercents.isSelected() == true)
+	            				{
+	            					DecimalFormat df = new DecimalFormat(Messages.getString("NewFunctionAnalyse.decimalFormat")); //$NON-NLS-1$
+	            					float total = 0;
+	            					for (Enumeration e = item.offsetVector.elements();e.hasMoreElements();)
+	            					{
+	            						Long offset = (Long)e.nextElement();
+	            						Long amount = (Long)e.nextElement();
+	            						offsetString += "(+"+offset.longValue()+"b "; //$NON-NLS-1$ //$NON-NLS-2$
+	            						offsetString += amount.longValue()+"s "; //$NON-NLS-1$
+	            						offsetString += "="+df.format(100f*(float)amount.longValue()/item.sampleAmount)+"% ) "; //$NON-NLS-1$ //$NON-NLS-2$
+	            						total+=(float)amount.longValue()/item.sampleAmount;
+	            					}
+	            				}
+
+	            				if (totalPercents != null)
+	            				{
+	            					if (!totalPercents.isSelected())
+	            					    toClipboard += item.sampleAmount+Messages.getString("NewFunctionAnalyse.samplesEqual")+((float)item.sampleAmount*100f)/item.totalSamples+"% "+item; //$NON-NLS-1$ //$NON-NLS-2$
+	            					else
+	            					    toClipboard += item.sampleAmount+Messages.getString("NewFunctionAnalyse.samplesEqual")+((float)item.sampleAmount*100f)/gppSamples.size()+"% "+item; //$NON-NLS-1$ //$NON-NLS-2$
+
+	            					toClipboard += offsetString;
+	            				}
+	            				toClipboard += "\n"; //$NON-NLS-1$
+	                        }
+	                    }
+	                    contents = new StringSelection(toClipboard);
+	        	        cb.setContents(contents, contents);
+				    }
+	            });
+	}
+	
+	public void showLinkedData()
+	{
+		if (this.gfcTraceVisualiser != null)
+		{
+			FunctionNameItem item = (FunctionNameItem)this.percentList.getSelectedValue();
+			this.gfcTraceVisualiser.selectFunction(item.name);
+		} 
+	}
+	
+	private class BinaryNameItem
+	{
+		public String name;
+		public boolean itt;
+		public int sampleAmount;
+		public int totalSamples;
+		
+		public BinaryNameItem(String name, boolean itt)
+		{
+			this.name = name.toLowerCase();
+			this.itt = itt;
+			this.sampleAmount = 0;
+		}
+		
+		public String toString()
+		{
+			return this.name;
+		}
+		
+		public void setSampleAmount(int amount)
+		{
+			this.sampleAmount = amount;
+		}
+		
+		public void setTotalSampleAmount(int total)
+		{
+			this.totalSamples = total;
+		}
+
+		public boolean equals(Object o)
+		{
+			if (o == null) return false;
+
+			if (o instanceof String)
+			{
+				if ( ((String)o).equals(this.name) ) return true;
+			}
+			else if (o instanceof BinaryNameItem)
+			{
+				if ( ((BinaryNameItem)o).name.equals(this.name) ) return true;
+			}
+			else if (this.name.equals(o.toString())) 
+			{
+				return true;
+			}
+						
+			return false;
+		}
+		
+		public int hashCode()
+		{
+			return this.name.hashCode();
+		}
+
+	}
+	
+	private static class FunctionNameItem implements Sortable
+	{
+		public String name;
+		public boolean itt;
+		public int sampleAmount;
+		public int totalSamples;
+		public Function function;
+		public Vector offsetVector;
+		public double currentPercent;
+		
+		public FunctionNameItem(String name, Function function, boolean itt)
+		{
+			this.offsetVector = new Vector();
+			this.sampleAmount = 0;
+			this.totalSamples = 0;
+			this.function = function;
+			this.name = name;
+			this.itt = itt;
+		}
+		
+		public long valueOf()
+		{
+			return this.sampleAmount;
+		}
+		
+		public String toString()
+		{
+			return this.name;
+		}
+		
+		public void setSampleAmount(int amount)
+		{
+			this.sampleAmount = amount;
+		}
+		
+		public void setTotalSampleAmount(int total)
+		{
+			this.totalSamples = total;
+		}
+		public void setOffsetVector(Vector offsetVector)
+		{
+			this.offsetVector = offsetVector;
+		}
+		
+		public boolean equals(Object o)
+		{
+			if (o == null) return false;
+
+			if (o instanceof String)
+			{
+				if ( ((String)o).equals(this.name) ) return true;
+			}
+			else if (o instanceof FunctionNameItem)
+			{
+				if ( ((FunctionNameItem)o).name.equals(this.name) ) return true;
+			}
+			else if (this.name.equals(o.toString())) 
+			{
+				return true;
+			}
+
+			return false;
+		}
+		
+		public int hashCode()
+		{
+			return this.name.hashCode();
+		}
+	}
+	
+	private class FunctionItemRenderer extends JLabel implements ListCellRenderer
+	{
+		private static final long serialVersionUID = 2036360032509070443L;
+
+		public Color ittColor = Color.ORANGE.darker();
+		public Color gppColor = Color.BLUE.darker();
+		public Color selectionColor = Color.YELLOW.brighter();
+		public FunctionNameItem functionNameItem = null;
+		
+		public void paint(Graphics g)
+		{
+			super.paint(g);
+
+			if (this.functionNameItem != null && this.functionNameItem.offsetVector != null)
+			{
+				
+				long length = this.functionNameItem.function.length;
+				g.setColor(
+						// AWT
+					    AWTColorPalette.getColor(new RGB(255, 255, 255))
+					    // SWT
+					    //ColorPalette.getColor(new RGB(255, 255, 255))
+				);
+				g.fillRect(0,0,100,14);
+				
+				int[] array = new int[100];
+				int maxAmount = 0;
+				
+				for (Enumeration e=functionNameItem.offsetVector.elements();e.hasMoreElements();)
+				{
+					long offset = ((Long)e.nextElement()).longValue();
+					long amount = ((Long)e.nextElement()).longValue();
+					//int color = (int)(amount*255/this.functionNameItem.sampleAmount);
+					
+					if (length > 0 /*&& !this.functionNameItem.itt*/)
+					{
+						//float width = (100f/(float)length);
+
+						if (offset > length)
+						{
+							// there is a problem with the offsets
+							// bail out and display a blue box
+							g.setColor(
+									// AWT
+								    AWTColorPalette.getColor(new RGB(100, 100, 200))
+								    // SWT
+								    //ColorPalette.getColor(new RGB(100, 100, 200))
+							);
+							g.fillRect(0,0,100,14);
+							break;
+						}
+						else
+						{	
+							if (offset == length) offset = length-1;
+							
+							float x1 = (float)(offset*100f)/((float)length);
+							float x2 = (float)((offset+1)*100f)/((float)length);
+							for (int j=(int)x1;j<(int)x2;j++)
+							{
+								array[j]+=amount;
+								if (maxAmount<array[j]) maxAmount = array[j];
+							}
+						}
+					}
+					else
+					{
+						// there is a problem with the offsets
+						// bail out and display a blue box
+						g.setColor(
+								// AWT
+							    AWTColorPalette.getColor(new RGB(100, 100, 200))
+							    // SWT
+							    //ColorPalette.getColor(new RGB(100, 100, 200))
+						);
+						g.fillRect(0,0,100,14);
+					}
+				}
+				
+				if (maxAmount != 0)
+				{
+					for (int j=0;j<100;j++)
+					{
+						if (array[j] > 0)
+						{
+							array[j] = (array[j]*255)/maxAmount;
+							Color c = 
+								// AWT
+							    AWTColorPalette.getColor(new RGB(array[j], 255-array[j], array[j]/2));
+							    // SWT
+							    //ColorPalette.getColor(new RGB(array[j], 255-array[j], array[j]/2));
+							g.setColor(c);
+							g.drawLine(j,0,j,14);
+						}
+					}
+				}
+				
+				g.setColor(					// AWT
+					    AWTColorPalette.getColor(new RGB(0, 0, 0))
+					    // SWT
+					    //ColorPalette.getColor(new RGB(0, 0, 0))
+				);
+				g.drawRect(0,0,100,14);
+				g.setColor(Color.BLACK);
+				g.drawString(""+length,10,12); //$NON-NLS-1$
+			}
+		}
+		
+		public Component getListCellRendererComponent(
+				JList list,
+				Object value,            // value to display
+				int index,               // cell index
+				boolean isSelected,      // is the cell selected
+				boolean cellHasFocus)    // the list and the cell have the focus
+		{	
+			if (value instanceof BinaryNameItem)
+			{
+				BinaryNameItem item = (BinaryNameItem)value;
+				String s;
+				
+				if (totalPercents.isSelected())
+					s = item.sampleAmount+Messages.getString("NewFunctionAnalyse.samplesEqual")+((float)item.sampleAmount*100f)/gppSamples.size()+"% "+item; //$NON-NLS-1$ //$NON-NLS-2$
+				else 
+					s = item.sampleAmount+Messages.getString("NewFunctionAnalyse.samplesEqual")+((float)item.sampleAmount*100f)/item.totalSamples+"% "+item; //$NON-NLS-1$ //$NON-NLS-2$
+				
+				setText(s);
+				
+				Color color;
+				if (item.itt)
+				{
+					color = this.ittColor;
+				}
+				else
+				{
+					color = this.gppColor;
+				}
+					
+				setOpaque(true);
+				
+				if (isSelected)
+				{
+					setForeground(color);					
+					if (cellHasFocus)
+						setBorder(new LineBorder(
+							// AWT
+						    AWTColorPalette.getColor(new RGB(0, 0, 0))
+						    // SWT
+						    //ColorPalette.getColor(new RGB(0, 0, 0))
+						));
+						else setBorder(null);
+					setBackground(this.selectionColor);	
+				}
+				else
+				{
+					setForeground(color);
+					setBackground(
+							// AWT
+						    AWTColorPalette.getColor(new RGB(255, 255, 255))
+						    // SWT
+						    //ColorPalette.getColor(new RGB(255, 255, 255))
+					);
+					setBorder(null);
+				}
+
+				setEnabled(list.isEnabled());
+				setFont(list.getFont());
+			}
+			else if (value instanceof FunctionNameItem)
+			{	
+				FunctionNameItem item = (FunctionNameItem)value;
+				this.functionNameItem = item;
+				String s = ""; //$NON-NLS-1$
+					
+				String offsetString = ""; //$NON-NLS-1$
+				
+				if (functionPercents.isSelected() == true)
+				{
+					DecimalFormat df = new DecimalFormat(Messages.getString("NewFunctionAnalyse.decimalFormal")); //$NON-NLS-1$
+					float total = 0;
+					for (Enumeration e = item.offsetVector.elements();e.hasMoreElements();)
+					{
+						Long offset = (Long)e.nextElement();
+						Long amount = (Long)e.nextElement();
+						offsetString += "(+"+offset.longValue()+"b "; //$NON-NLS-1$ //$NON-NLS-2$
+						offsetString += amount.longValue()+"s "; //$NON-NLS-1$
+						offsetString += "="+df.format(100f*(float)amount.longValue()/item.sampleAmount)+"% ) "; //$NON-NLS-1$ //$NON-NLS-2$
+						total+=(float)amount.longValue()/item.sampleAmount;
+						s = "                                         "; //$NON-NLS-1$
+					}
+				}
+
+				if (totalPercents != null)
+				{
+					if (!totalPercents.isSelected())
+						s += item.sampleAmount+Messages.getString("NewFunctionAnalyse.samplesEqual")+((float)item.sampleAmount*100f)/item.totalSamples+"% "+item; //$NON-NLS-1$ //$NON-NLS-2$
+					else
+						s += item.sampleAmount+Messages.getString("NewFunctionAnalyse.samplesEqual")+((float)item.sampleAmount*100f)/gppSamples.size()+"% "+item; //$NON-NLS-1$ //$NON-NLS-2$
+
+					setText(s +"  "+ offsetString); //$NON-NLS-1$
+				}
+				
+				
+				Color color;
+				if (item.itt)
+				{
+					color = this.ittColor;
+				}
+				else
+				{
+					color = this.gppColor;
+				}
+					
+				setOpaque(true);
+				
+				if (isSelected)
+				{
+					setForeground(color);
+					setBackground(this.selectionColor);
+					
+					if (cellHasFocus)
+						setBorder(new LineBorder(
+							// AWT
+						    AWTColorPalette.getColor(new RGB(0, 0, 0))
+						    // SWT
+						    //ColorPalette.getColor(new RGB(0, 0, 0))
+						));
+						else setBorder(null);
+				}
+				else
+				{
+					setForeground(color);
+					setBackground(
+							// AWT
+						    AWTColorPalette.getColor(new RGB(255, 255, 255))
+						    // SWT
+						    //ColorPalette.getColor(new RGB(255, 255, 255))
+					);					
+					setBorder(null);
+				}
+				
+				if (item.function != null)
+				{
+					if (item.function.functionBinary != null && item.function.functionBinary.binaryName != null)
+					{
+						this.setToolTipText(Messages.getString("NewFunctionAnalyse.function1")+item.function.functionName+Messages.getString("NewFunctionAnalyse.function2")+ //$NON-NLS-1$ //$NON-NLS-2$
+								Long.toHexString(item.function.startAddress.longValue())+
+								Messages.getString("NewFunctionAnalyse.function3")+item.function.functionBinary.binaryName); //$NON-NLS-1$
+					}
+					else
+					{
+						this.setToolTipText(Messages.getString("NewFunctionAnalyse.function1")+item.function.functionName+Messages.getString("NewFunctionAnalyse.function2")+ //$NON-NLS-1$ //$NON-NLS-2$
+								Long.toHexString(item.function.startAddress.longValue())+
+								Messages.getString("NewFunctionAnalyse.function3") + Messages.getString("NewFunctionAnalyse.binaryNotFound")); //$NON-NLS-1$ //$NON-NLS-2$
+					}
+				}
+				else
+				{
+					this.setToolTipText(Messages.getString("NewFunctionAnalyse.functionNotFound")); //$NON-NLS-1$
+				}
+			}
+		
+			return this;
+		}
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.function/src/com/nokia/carbide/cpp/pi/function/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,53 @@
+FunctionPlugin.fixException=SL: fix here
+GfcTraceVisualiser.totalLoad=Total Load
+GfcTraceVisualiser.callerLoad=Caller Load
+GfcTraceVisualiser.recursiveLoad=Recursive Load
+GfcTraceVisualiser.previousSelection=Previous Selection
+GfcTraceVisualiser.sortBy=Sort By:
+GfcTraceVisualiser.goBackTo=Go Back To:
+GfcTraceVisualiser.calledSelectedFunction=Functions that have called the selected function
+GfcTraceVisualiser.calledBySelectedFunction=Functions that have been called by the selected function
+GfcTraceVisualiser.percent=%
+GfcTraceVisualiser.functionString1=Total-[
+GfcTraceVisualiser.functionString2=] Caller-[
+GfcTraceVisualiser.functionString3=] Recursive-[
+GfcTraceVisualiser.functionString4=]
+GfcTraceVisualiser.functionString5=\ 0x
+GfcTraceVisualiser.functionString6=\ 
+GfcTraceVisualiser.addressString1=0x
+GfcTraceVisualiser.addressString2=\ Total-[
+GfcTraceVisualiser.addressString3=] Caller-[
+GfcTraceVisualiser.addressString4=] F-Relative-[
+GfcTraceVisualiser.addressString5=] 
+GfcTraceVisualiser.addressString2a=Total-[
+GfcTraceVisualiser.listIsNotWorking=List is not working properly 
+NewFunctionAnalyse.clearSelectedBinaries=Clear all selected binaries
+NewFunctionAnalyse.clearSelectedThreads=Clear all selected threads
+NewFunctionAnalyse.selectOriginalThreads=Select originally selected threads
+NewFunctionAnalyse.selectOriginalBinaries=Select originally selected binaries
+NewFunctionAnalyse.primarilyUseITT=Primarily use ITT analysis to resolve functions
+NewFunctionAnalyse.primarilyUseSymbolFile=Primarily use .symbol file to resolve functions
+NewFunctionAnalyse.showPercentsOfTotalLoad=Show all percents as total of complete load
+NewFunctionAnalyse.showPositionSpecificPercents=Show position specific percents in function
+NewFunctionAnalyse.threadList=Thread List
+NewFunctionAnalyse.binaryList=Binary List
+NewFunctionAnalyse.threadMode=\ Thread mode
+NewFunctionAnalyse.binaryMode=\ Binary mode
+NewFunctionAnalyse.functionAnalysis1=Function Analysis 
+NewFunctionAnalyse.functionAnalysis2=\ - samples 
+NewFunctionAnalyse.functionAnalysis3=s - 
+NewFunctionAnalyse.functionAnalysis4=s
+NewFunctionAnalyse.start=start:
+NewFunctionAnalyse.end=\ end:
+NewFunctionAnalyse.gotSamples=got samples 
+NewFunctionAnalyse.samplesEqual=\ samples = 
+NewFunctionAnalyse.functionPercentListDoubleClick=Function percent list - double click to see the function in the linked function view
+NewFunctionAnalyse.functionPercentList=Function percent list
+NewFunctionAnalyse.notFound=not found
+NewFunctionAnalyse.binaryNotFound=Binary not found
+NewFunctionAnalyse.functionNotFound=Function not found
+NewFunctionAnalyse.decimalFormat=0.\#\#
+NewFunctionAnalyse.decimalFormal=0.\#\#
+NewFunctionAnalyse.function1=Function: 
+NewFunctionAnalyse.function2=\ at: 0x
+NewFunctionAnalyse.function3=\ in: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/.settings/org.eclipse.core.resources.prefs	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,3 @@
+#Mon Feb 09 13:31:31 CST 2009
+eclipse.preferences.version=1
+encoding//src/com/nokia/carbide/cpp/pi/instr/messages.properties=8859_1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Dynamic Binaries
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.instr;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.instr.InstrPlugin
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ com.nokia.carbide.cpp.pi,
+ com.nokia.carbide.cpp.pi.core,
+ com.nokia.carbide.cpp.pi.util
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.pi.instr;x-friends:="com.nokia.carbide.cpp.pi.instr.tests"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,6 @@
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .
+jars.compile.order = .
+source.. = src/
+output.. = bin/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+   <extension
+         point="com.nokia.carbide.cpp.pi.piPluginData">
+      <plugin pluginClass="com.nokia.carbide.cpp.pi.instr.InstrReturnPlugin"/>
+   </extension>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/AdvancedMemoryMap.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+
+
+public class AdvancedMemoryMap implements FunctionResolver
+{
+    private boolean debug = false;
+	private UndecidedPool unDecided;
+	private DecidedPool decided;
+	private BinaryReader binReader;
+	
+	private IttTrace122 ittTrace122;
+	private BinaryReader122 binaryReader122;
+	
+	// whether the resolver has enough information to resolve anything
+	protected boolean ableToResolve = true;
+	
+	public AdvancedMemoryMap(BinaryReader122 binaryReader122,IttTrace122 ittTrace122)
+	{
+		this.binaryReader122 = binaryReader122;
+		this.ittTrace122 = ittTrace122;
+	}
+	
+	public AdvancedMemoryMap(BinaryReader myBinaryReader)
+	{
+		this.binReader = myBinaryReader;
+		this.decided = new DecidedPool(this);
+		this.unDecided = new UndecidedPool(this);
+	}
+	
+	public UndecidedPool getUndecidedPool()
+	{
+		return this.unDecided;
+	}
+
+	public DecidedPool getDecidedPool()
+	{
+		return this.decided;
+	}
+
+	public BinaryReader getBinaryReader()
+	{
+		return this.binReader;
+	}
+	
+	public void InsertSample(IttSample sample)
+	{
+		if (this.ittTrace122 == null)
+		{
+			// first check whether there is any binary in the location
+			// the sample is
+			boolean memStat = this.decided.isThereAnyBinaryInMemoryIn(sample.programCounter);
+			
+			if (memStat == true)
+			{
+				// there is a binary / binaries
+				// in the memory at the location
+				// where the sample is located
+				
+				this.decided.insertSample(sample);
+				// result tells whether the sample was binary compatible
+				// with any of the binaries. It is not important here though, as
+				// the sample should have a match also with its correct binary if
+				// it is present - consequent samples will then strenghten the 
+				// position of the binary
+			}
+			
+			else if (memStat == false)
+			{
+				// no, this sample has to be inserted to the
+				// undecided pool
+				
+				this.unDecided.insertSample(sample,10);
+			}
+			
+			if (this.unDecided.getUnprocessed().size() > 0)
+			{
+				//System.out.println("Unprocessed "+this.unDecided.getUnprocessed().size());
+				Vector unProcVec = this.unDecided.getUnprocessed();
+				Enumeration enumer = unProcVec.elements();
+				while(enumer.hasMoreElements())
+				{
+					IttSample s = (IttSample)enumer.nextElement();
+					// try the undecided samples again
+					this.decided.insertSample(s);
+				}
+			}
+		}
+		else
+		{
+			throw new ArrayIndexOutOfBoundsException(Messages.getString("AdvancedMemoryMap.notSupportedInV.1.22"));			 //$NON-NLS-1$
+		}
+	}
+	
+	public void postProcess()
+	{
+		if (this.ittTrace122 == null)
+		{
+			
+			for (int i=9;i>0;i--)
+			{		
+				Vector undecided = unDecided.getUndecided();
+				if (debug) System.out.println(Messages.getString("AdvancedMemoryMap.unmatchedSize")+undecided.size()); //$NON-NLS-1$
+				
+				Enumeration enumer = undecided.elements();
+				while(enumer.hasMoreElements())
+				{
+					IttSample is = (IttSample)enumer.nextElement();
+					
+					if (this.decided.insertSample(is) == false)
+						this.unDecided.insertSample(is,i);
+					
+				}
+			}
+		}
+		else
+		{
+			throw new ArrayIndexOutOfBoundsException(Messages.getString("AdvancedMemoryMap.notSupportedInV.1.22"));			 //$NON-NLS-1$
+		}
+	}
+	
+	public Binary findBinaryForSample(IttSample sample)
+	{
+		if (this.ittTrace122 == null)
+		{
+			Binary b = this.decided.findBinaryForSample(sample);
+			if (b != null)
+			{
+				return b;
+			}
+			else
+			{
+				b = new Binary(Messages.getString("AdvancedMemoryMap.binaryForAddressNotFound1")+Long.toHexString(sample.programCounter)+Messages.getString("AdvancedMemoryMap.binaryForAddressNotFound2")); //$NON-NLS-1$ //$NON-NLS-2$
+				b.length = 0;
+				b.offsetToCodeStart = 0;
+				b.startAddress = sample.programCounter+4;
+				b.type = null;
+				return b;
+			}
+		}
+		else
+		{
+			throw new ArrayIndexOutOfBoundsException(Messages.getString("AdvancedMemoryMap.notSupportedInV.1.22"));			 //$NON-NLS-1$
+		}
+	}
+	
+	public Function findFunctionForSample(IttSample sample)
+	{
+		if (this.ittTrace122 == null)
+		{
+			Function f;
+			ProcessedBinary pb = null;
+			
+			Binary b = this.decided.findBinaryForSample(sample);
+			if (b != null)
+			{
+				int offset = (int)(sample.programCounter+4-(b.startAddress+b.offsetToCodeStart));
+				pb = this.binReader.getProcessedBinaryForName(b.binaryName);
+				if (pb != null)
+				{
+					f = pb.getFunctionForOffset(offset);
+					if (f != null) 
+					{
+						f.startAddress = new Long(b.startAddress+f.offsetFromBinaryStart+pb.offsetToCodeStart);
+						// function found ok
+						// System.out.println(f.toString());
+						return f;
+					}
+					
+					// function not found in processed binary
+					f = new Function(Messages.getString("AdvancedMemoryMap.functionForAddressNotFound1")+Long.toHexString(sample.programCounter)+Messages.getString("AdvancedMemoryMap.functionForAddressNotFound2"), //$NON-NLS-1$ //$NON-NLS-2$
+							new Long(pb.startAddress),
+							pb.binaryName);
+					return f;
+				}
+			}
+			
+			// in all other cases
+			f = new Function(Messages.getString("AdvancedMemoryMap.functionForAddressNotFound1")+Long.toHexString(sample.programCounter)+Messages.getString("AdvancedMemoryMap.functionForAddressNotFound2"), //$NON-NLS-1$ //$NON-NLS-2$
+					new Long(sample.programCounter),
+					Messages.getString("AdvancedMemoryMap.binaryForAddressNotFound1")+Long.toHexString(sample.programCounter)+Messages.getString("AdvancedMemoryMap.binaryForAddressNotFound2")); //$NON-NLS-1$ //$NON-NLS-2$
+			return f;
+		}
+		else
+		{
+			throw new ArrayIndexOutOfBoundsException(Messages.getString("AdvancedMemoryMap.notSupportedInV.1.22"));			 //$NON-NLS-1$
+		}
+	}
+	
+	public Function findFunctionForAddress(long address)
+	{
+		if (this.ittTrace122 == null)
+		{
+			return this.decided.getFunctionForAddress(address);
+		}
+		else
+		{
+			return this.ittTrace122.getFunctionForAddress(address,this.binaryReader122);
+		}
+	}
+	
+	public String findFunctionNameForAddress(long address)
+	{
+		Function f = this.findFunctionForAddress(address);
+		if (f != null)
+		{
+			return f.functionName;
+		}
+		else
+		{
+			return Messages.getString("AdvancedMemoryMap.functionNotFound"); //$NON-NLS-1$
+		}
+	}
+	
+	public String findBinaryNameForAddress(long address)
+	{
+		Function f = this.findFunctionForAddress(address);
+		if (f != null)
+		{
+			return f.functionBinary.binaryName;
+		}
+		else
+		{
+			return Messages.getString("AdvancedMemoryMap.binaryNotFound"); //$NON-NLS-1$
+		}
+	}
+	
+	public String getResolverName()
+	{
+		return "ITT"; //$NON-NLS-1$
+	}
+
+	public String getResolverString()
+	{
+		return Messages.getString("AdvancedMemoryMap.resolverITT"); //$NON-NLS-1$
+	}
+	
+	public Binary findBinaryForAddress(long address)
+	{
+		if (this.ittTrace122 == null)
+		{
+			Function f = this.findFunctionForAddress(address);
+			
+			if (f != null)
+				return f.functionBinary;
+			else 
+				return null;
+		}
+		else
+		{
+			Function f = this.ittTrace122.getFunctionForAddress(address,this.binaryReader122);
+			
+			if (f != null)
+				return f.functionBinary;
+			else 
+				return null;
+		}
+	}
+
+	public String findFunctionNameForSample(IttSample sample)
+	{
+		if (this.ittTrace122 == null)
+		{
+			Binary b = this.decided.findBinaryForSample(sample);
+			if (b != null)
+			{
+				int offset = (int)(sample.programCounter+4-(b.startAddress+b.offsetToCodeStart));
+				return this.binReader.getFunctionName(b.binaryName,offset);
+			}
+			else 
+			{
+				return Messages.getString("AdvancedMemoryMap.functionForAddressNotFound1")+Long.toHexString(sample.programCounter)+Messages.getString("AdvancedMemoryMap.functionForAddressNotFound2"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+		else
+		{
+			throw new ArrayIndexOutOfBoundsException(Messages.getString("AdvancedMemoryMap.notSupportedInV.1.22")); //$NON-NLS-1$
+		}
+	}
+	
+	public Enumeration getSupportingSamples(Binary b)
+	{
+		if (this.ittTrace122 == null)
+		{
+			
+			return this.decided.getSupportingSamplesForBinary(b);
+		}
+		else
+		{
+			throw new ArrayIndexOutOfBoundsException(Messages.getString("AdvancedMemoryMap.notSupportedInV.1.22"));			 //$NON-NLS-1$
+		}
+		
+	}
+	
+	public Enumeration getNonSupportingSamples(Binary b)
+	{
+		if (this.ittTrace122 == null)
+		{
+			
+			return this.decided.getNonSupportingSamplesForBinary(b);
+		}
+		else
+		{
+			throw new ArrayIndexOutOfBoundsException(Messages.getString("AdvancedMemoryMap.notSupportedInV.1.22"));			 //$NON-NLS-1$
+		}
+		
+	}
+	
+	public Binary getBinary(String binaryName)
+	{		
+		if (this.ittTrace122 == null)
+		{
+			return this.decided.getBinaryWithName(binaryName);
+		}
+		else
+		{
+			throw new ArrayIndexOutOfBoundsException(Messages.getString("AdvancedMemoryMap.notSupportedInV.1.22"));			 //$NON-NLS-1$
+		}
+	}
+
+	public boolean canResolve() {
+		return this.ableToResolve;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/BinaryReader.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,676 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.pi.importer.SampleImporter;
+import com.nokia.carbide.cpp.pi.importer.SampleImporter.PkgObyFile;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+import com.nokia.carbide.cpp.pi.util.GuessAndFixPath;
+
+
+public class BinaryReader
+{
+  private boolean debug = false;
+  private Vector<File> files;
+  private Hashtable<String, ProcessedBinary> processedFiles;
+
+  public BinaryReader() throws Exception
+  {
+    files = new Vector<File>();
+    processedFiles = new Hashtable<String, ProcessedBinary>();
+
+    for (PkgObyFile currentFile : SampleImporter.getInstance().getPkgObyFilesList())
+    {    	
+    	{
+    		String epocRoot = null;
+    	    File epoc32;
+    		
+    	    if (currentFile.epocRoot.endsWith("\\")) //$NON-NLS-1$
+    	    {
+    	    	epocRoot = currentFile.epocRoot.substring(0, currentFile.epocRoot.length() - 1);
+    	    }
+    	    else
+    	    {
+    	    	epocRoot = currentFile.epocRoot;
+    	    }
+    	    epoc32 = new File(epocRoot + "\\epoc32"); //$NON-NLS-1$
+
+    	    if (!epoc32.exists() || !epoc32.isDirectory()) {
+    	    	GeneralMessages.showErrorMessage(Messages.getString("BinaryReader.cannotFindEpoc32FromRoot")+epoc32.toString()); //$NON-NLS-1$
+    	    	throw new Exception (Messages.getString("BinaryReader.cannotFindEpoc32FromRoot")+epoc32.toString()); //$NON-NLS-1$
+    	    }
+    	}
+    	
+    	if (currentFile.fileAbsolutePath.toLowerCase().endsWith(".oby") || currentFile.fileAbsolutePath.toLowerCase().endsWith(".iby")) //$NON-NLS-1$ //$NON-NLS-2$
+    		addFilesInOby(currentFile.fileAbsolutePath, currentFile.epocRoot);
+    	else if (currentFile.fileAbsolutePath.toLowerCase().endsWith(".pkg")) //$NON-NLS-1$
+    		addFilesInPkg(currentFile.fileAbsolutePath, currentFile.epocRoot);
+    	else
+    		this.addSingleFile(currentFile.fileAbsolutePath);
+    }
+    refreshFileTable();
+  }
+  public BinaryReaderResult findSequence(IttSample sample)
+  {
+    return findSequence(sample,(ProcessedBinary)null);
+  }
+
+  public BinaryReaderResult findSequence(IttSample sample, Binary b)
+  {
+    if (this.processedFiles.containsKey(b.binaryName))
+    {
+      ProcessedBinary pf = (ProcessedBinary)this.processedFiles.get(b.binaryName);
+      return this.findSequence(sample,pf);
+    }
+    return null;
+  }
+  
+  public ProcessedBinary getProcessedBinaryForName(String name)
+  {
+  	ProcessedBinary pb = (ProcessedBinary)this.processedFiles.get(name);
+  	
+  	if (pb != null)
+  	{
+  		return pb;
+  	}
+  	return null;
+  }
+  
+  public boolean checkSampleInBinary(IttSample sample,Binary binary,int differencesAllowed)
+  {
+  	ProcessedBinary pb = this.getProcessedBinaryForName(binary.binaryName);
+  	if (pb == null)
+  	{
+  		System.out.println(Messages.getString("BinaryReader.cannotFindBinary")+binary.binaryName); //$NON-NLS-1$
+		return false;
+  	}
+  	
+  	if (binary.startAddress <= sample.programCounter &&
+  	   binary.startAddress+binary.length >= sample.programCounter)
+  	{
+  		// the program counter value indicates that the sample
+  		// is within the binary
+  		long[] reversedInstructions = sample.reversedInstructions();
+  		int matches = 0;
+  		for (int i=0;i<reversedInstructions.length;i++)
+  		{
+  			
+  			long instruction = reversedInstructions[i];
+  			long offset = (long)(sample.programCounter-binary.startAddress);
+
+  			if (offset < binary.length)
+  			{
+  				// add the amount of bytes that match in the next 4 bytes
+  				matches += this.testNextFourBytes((int)offset+(i*4),instruction,pb);
+  			}
+  		}	
+  		
+  		if (matches >= (reversedInstructions.length*4 - differencesAllowed))
+  		{
+  			// binary matches with the sample
+  			// within the binary
+  			return true;
+  		}
+  	}
+  	
+  	// the sample is not within the binary memory area
+  	return false;
+  }
+
+  public BinaryReaderResult findSequence(IttSample sample,ProcessedBinary processedFile)
+  {
+    long[] sequence = sample.reversedInstructions();
+
+    Vector possibleBinaries  = new Vector();
+    Vector checksumValues = new Vector();
+
+    if (sequence.length != 0)
+    {
+      int first = (int) ((sequence[0] & (long)0xff000000) >> 24);
+      int second = (int) ((sequence[0] & (long)0x00ff0000) >> 16);
+      int third = (int) ((sequence[0] & (long)0x0000ff00) >> 8);
+      int fourth = (int) ((sequence[0] & (long)0x000000ff));
+
+      // this is for searching only one binary
+      Vector tempVec = null;
+      Enumeration enumer = null;
+
+      if (processedFile != null)
+      {
+        tempVec = new Vector();
+        tempVec.add(processedFile);
+        enumer = tempVec.elements();
+      }
+      else
+      {
+        enumer = this.processedFiles.elements();
+      }
+
+      while (enumer.hasMoreElements())
+      {
+        ProcessedBinary pf = (ProcessedBinary) enumer.nextElement();
+
+        int[] indicesToCheck = pf.getIndicesForSequence(first);
+
+        if (indicesToCheck != null)
+        {
+          for ( int k = 0;k<indicesToCheck.length;k++)
+          {
+            int i = indicesToCheck[k];
+
+            int match = 0;
+            
+            if (i < pf.length - 5)
+            {
+              if (pf.data[i] == (byte) first) match++;
+              
+              if (pf.data[i + 1] == (byte) second) match++;
+              
+              if (pf.data[i + 2] == (byte) third) match++;
+              
+              if (pf.data[i + 3] == (byte) fourth) match++;
+                    
+              // if at least three of the previous four bytes did match
+              if (match >= 3)
+                    {
+                      for (int s = 1; s < sequence.length; s++)
+                      {
+
+                      	// add the match value with one if three of the four bytes
+                      	// in the next 4 bytes match
+                      	match += testNextFourBytes(i + s * 4, sequence[s], pf);
+                      }
+                      
+                      if (match >= (sequence.length*4)-2)
+                      {
+                        // check the checksum
+                        // go back from the current position another 16 bytes
+                        // and calculate the xor checksum for 11 instructions
+                        long checksum = pf.calculateXorChecksum(i+12,8);
+
+                        // this value should match with the last value in the
+                        // search pattern
+                        if ( (checksum & 0xffffffff) == (sample.checksum & 0xffffffff) )
+                        {
+
+                          // add this location to possible binaries
+                          Binary b = new Binary(pf.binaryName);
+                          b.length = pf.length;
+                          b.offsetToCodeStart = pf.offsetToCodeStart;
+                          b.type = pf.type;
+
+                          // binary start address is the this address - this offset
+                          b.startAddress = sample.programCounter-i;
+                          possibleBinaries.add(b);
+
+                          //System.out.println (	"CHECKSUM MATCH at "+pf.binaryName+"@0x"+Long.toHexString(b.startAddress-b.offsetToCodeStart)+
+                          //						" pos:"+i+"!! Checksum:"+checksum+" "+pf.file.getAbsolutePath());
+
+                          
+                          // this is a checksum match
+                          checksumValues.add(Boolean.valueOf(true));
+                        }
+                        else
+                        {
+
+                          // add this location to possible binaries
+
+                          Binary b = new Binary(pf.binaryName);
+                          b.length = pf.length;
+                          b.offsetToCodeStart = pf.offsetToCodeStart;
+                          b.type = pf.type;
+
+                          // binary start address is this address - this offset
+                          b.startAddress = sample.programCounter-i;
+                          possibleBinaries.add(b);
+
+                          //System.out.println(	"MATCH at "+pf.binaryName+"@0x"+Long.toHexString(b.startAddress-b.offsetToCodeStart)+
+                          //						" pos:"+i+"!! "+pf.file.getAbsolutePath());
+                          
+                          // this one is not a checksum match
+                          checksumValues.add(Boolean.valueOf(false));
+                        }
+                      }
+                    }
+            }
+          }
+        }
+      }
+    }
+    BinaryReaderResult brr = new BinaryReaderResult();
+
+    brr.checksumValues = (Boolean[])checksumValues.toArray(new Boolean[checksumValues.size()]);
+    brr.possibleBinaries = (Binary[])possibleBinaries.toArray(new Binary[possibleBinaries.size()]);
+
+    return brr;
+    //System.out.println("Finished!");
+  }
+
+
+  public void printBinaryFromOffset(ProcessedBinary pf, int offset, int length)
+  {
+    if (pf.length < offset+length) return;
+    int c = 0;
+
+    for (int i=offset;i<offset+length;i++)
+    {
+      String hex = Integer.toHexString((int)pf.data[i] & 0xff);
+      if (hex.length() == 1) hex = "0"+hex; //$NON-NLS-1$
+
+      if (c%4 == 0) System.out.print(" "); //$NON-NLS-1$
+      if (c%40 == 0) System.out.print("\n"); //$NON-NLS-1$
+
+      System.out.print(hex);
+      c++;
+    }
+  }
+  
+  private int testNextFourBytes(int offset,long data, ProcessedBinary pf)
+  {
+      if (data == -1) return 4;
+
+      int first = (int) ((data & (long)0xff000000) >> 24);
+      int second = (int) ((data & (long)0x00ff0000) >> 16);
+      int third = (int) ((data & (long)0x0000ff00) >> 8);
+      int fourth = (int) ((data & (long)0x000000ff));
+
+      int matches = 0;
+      
+      if (pf.length > offset+4)
+      {
+        if (pf.data[offset] == (byte)first) matches++; 
+        
+        if (pf.data[offset+1] == (byte)second) matches++;
+        
+        if (pf.data[offset+2] == (byte)third) matches++;
+        
+        if (pf.data[offset+3] == (byte)fourth) matches++;
+      }
+      
+      return matches;
+  }
+
+  public void printBinary(String fileName)
+  {
+    this.printBinary(fileName,0,-1);
+  }
+
+  public void printBinary(String fileName,int startOffset,int length)
+  {
+  	System.out.println(binaryToString(fileName,startOffset,length));
+  }
+
+  public String binaryToString(String fileName,int startOffset,int length)
+  {
+  	String resultString = ""; //$NON-NLS-1$
+  	
+    int counter = 1;
+    if (this.processedFiles.containsKey(fileName))
+    {
+      ProcessedBinary pf = (ProcessedBinary)this.processedFiles.get(fileName);
+      if (length == -1)
+        {
+          startOffset = 0;
+          length = pf.length;
+        }
+
+      for (int i=startOffset;i<startOffset+length;i++)
+      {
+        String hex = Integer.toHexString((int)pf.data[i] & 0xff);
+        if (hex.length() == 1) hex = "0"+hex; //$NON-NLS-1$
+
+        resultString+=hex;
+
+        if (counter%4 == 0) resultString+=" "; //$NON-NLS-1$
+        if (counter%40 == 0) resultString+="\n"; //$NON-NLS-1$
+
+        counter++;
+      }
+    }
+    
+    return resultString;
+  }
+
+  
+  public String getFunctionName(String binaryName, long offset)
+  {
+  	ProcessedBinary pb = (ProcessedBinary)this.processedFiles.get(binaryName);
+  	if (pb != null)
+  	{
+  		return pb.getFunctionNameForOffset(offset);
+  	}
+  	else
+  	{
+  		return Messages.getString("BinaryReader.binaryNotFound1")+binaryName+Messages.getString("BinaryReader.binaryNotFound2"); //$NON-NLS-1$ //$NON-NLS-2$
+  	}
+  }
+  
+  public Function getFunction(String binaryName,long offset)
+  {
+  	ProcessedBinary pb = (ProcessedBinary)this.processedFiles.get(binaryName);
+  	if (pb != null)
+  	{
+  		return pb.getFunctionForOffset(offset);
+   	}
+  	else
+  	{
+  		return null;
+  	}
+  }
+  
+  public long getFunctionStartOffsetFromBinaryStart(String binaryName,String functionName)
+  {
+  	ProcessedBinary pb = (ProcessedBinary)this.processedFiles.get(binaryName);
+  	if (pb != null)
+  	{
+  		return pb.getOffsetFromBinaryStartForFunction(functionName);
+  	}
+  	else
+  	{
+  		return -1;
+  	}
+  }
+
+  public void refreshFileTable()
+  {
+    long length = 0;
+    int addedFiles = 0;
+
+    if (debug) System.out.println(this.files.size()+Messages.getString("BinaryReader.filesFound")); //$NON-NLS-1$
+    if (this.files.size() > 0)
+    {
+      Enumeration enumer = files.elements();
+      while (enumer.hasMoreElements())
+      {
+        File f = (File) enumer.nextElement();
+        String name = f.getAbsolutePath();
+        name = name.substring(name.indexOf(File.separator),name.length());
+
+        if (!(this.processedFiles.containsKey(name) &&
+              (((ProcessedBinary)this.processedFiles.get(name)).length == f.length())))
+        {
+          try
+          {
+            ProcessedBinary pf = processFile(f);
+            //System.out.println(f.getName());
+            this.processedFiles.put(pf.binaryName, pf);
+            length += pf.length;
+            addedFiles++;
+          }
+          catch (Exception e)
+          {
+            e.printStackTrace();
+          }
+        }
+        else
+        {
+          System.out.println(Messages.getString("BinaryReader.fileAlreadyPresent1")+f.getName()+Messages.getString("BinaryReader.fileAlreadyPresent2")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+      }
+    }
+
+    this.files.clear();
+
+    if (debug) System.out.println(Messages.getString("BinaryReader.bytesProcessed1")+length+Messages.getString("BinaryReader.bytesProcessed2")+addedFiles+Messages.getString("BinaryReader.bytesProcessed3")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+  }
+
+  private ProcessedBinary processFile(File f) throws Exception
+  {
+    return new ProcessedBinary(f);
+  }
+
+  public void addFilesInOby(String obyFile, String epocroot) throws Exception
+  {
+    File file = new File(obyFile);
+    if (!file.exists())
+    {
+      throw new Exception(Messages.getString("BinaryReader.cannotFindObyFile")); //$NON-NLS-1$
+    }
+
+    BufferedReader br = new BufferedReader(new FileReader(file));
+
+    String line = br.readLine();
+    
+    while(line != null)
+    {
+        line = line.trim(); 
+        
+        if (line.endsWith("\""))  //$NON-NLS-1$
+        {        
+        	line = line.replaceAll("\"",""); //$NON-NLS-1$ //$NON-NLS-2$
+        	line.trim();
+        }
+    	
+        int start = line.indexOf("="); //$NON-NLS-1$
+//        start = line.indexOf("\\", start);
+        start = line.indexOf(System.getProperty(Messages.getString("BinaryReader.fileSeparatorProperty")), start); //$NON-NLS-1$
+//        System.getProperty("file.separator")
+
+        int space = line.indexOf(" ",start+2); //$NON-NLS-1$
+        int tab = line.indexOf("\t",start+2); //$NON-NLS-1$
+        int end = 0;
+
+        if (space < 0 && tab < 0)
+          end = line.length();
+        else if (space > 0 && tab > 0 && space > tab)
+          end = tab;
+        else if (space > 0 && tab > 0 && tab > space)
+          end = space;
+        else if (space < 0 && tab > 0)
+          end = tab;
+        else if (space > 0)
+          end = space;
+        else
+          start = -1;
+
+        if (start >= 0)
+        {
+          String lowCase = line.toLowerCase();
+		  
+          if (checkFileExtension(lowCase) == false) start = -1;
+		                    	
+          if (line.indexOf("rem") >= 0) //$NON-NLS-1$
+          {
+            if (line.indexOf("rem") <= start) //$NON-NLS-1$
+              start = -1;
+          }
+          else if (line.indexOf("romname") >= 0) //$NON-NLS-1$
+          {
+            if (line.indexOf("romname") <= start) //$NON-NLS-1$
+              start = -1;
+          }
+        }
+
+        if (start >= 0 && end > start)
+        {
+          String fileNameLine = line.substring(start, end);
+          if (fileNameLine.endsWith("\"")) //$NON-NLS-1$
+            fileNameLine = fileNameLine.substring(0, fileNameLine.length() - 1);
+
+          addFile(fileNameLine, epocroot);
+          //System.out.println("ADDED "+fileNameLine);
+        }
+        else
+        {
+        	//if (line.indexOf(".rsc") == -1 && !line.startsWith("rem") && line.length() > 3)
+        	//System.out.println("SKIPPED "+line);
+        }
+
+        line = br.readLine();
+        //System.out.println("READ "+line);
+      }
+    br.close();
+
+  }
+  
+  public static boolean checkFileExtension(String lowCase)
+  {
+      if (lowCase.endsWith(".rsc")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".aif")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".dll55l")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".dof")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".mid")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".rng")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".ini")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".awb")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".dat")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".txt")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".mbm_rom")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".xml")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".dtd")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".snm")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".smil")) return false; //$NON-NLS-1$
+      else if (lowCase.endsWith(".sis")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".skn")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".lnk")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".gdr")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".esk")) return false;	   //$NON-NLS-1$
+      else if (lowCase.endsWith(".ota")) return false;	  //$NON-NLS-1$
+	  else if (lowCase.endsWith(".cfg")) return false;	  //$NON-NLS-1$
+	  else if (lowCase.endsWith(".wav")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".mp3")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".amr")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".pcm")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".mbm")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".bmp")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".aac")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".png")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".hlp")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".jpg")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".dic")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".mask")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".db")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".mxmf")) return false; //$NON-NLS-1$
+	  else if (lowCase.endsWith(".gif")) return false;          //$NON-NLS-1$
+
+	  else return true;
+  }
+  
+  public void addFilesInPkg(String pkgName, String epocroot) throws IOException
+  {
+	  File pkgFile = new File(pkgName);
+	  if (pkgFile.exists() && !pkgFile.isDirectory())
+	  {
+		  try
+		  	{
+			  BufferedReader br = new BufferedReader(new FileReader(pkgFile));
+			  
+			  while(true)
+			  {
+				  String line = br.readLine();
+				  //System.out.println(line);
+				  int first = line.indexOf("\""); //$NON-NLS-1$
+				  int second = -1;
+				  int third = -1;
+				  int fourth = -1;
+				  
+				  if (first != -1)
+					  second = line.indexOf("\"",first+1); //$NON-NLS-1$
+				  
+				  if (second != -1)
+					  third = line.indexOf("\"!:",second+1); //$NON-NLS-1$
+				  
+				  if (third != -1)
+					  fourth = line.indexOf("\"",third+1); //$NON-NLS-1$
+				  
+				  //System.out.println(first+" "+second+" "+third+" "+fourth);
+				  if (fourth != -1)
+				  {
+					  String localFile = line.substring(first+1,second);
+//					  String remoteFile = line.substring(third+3,fourth);
+					  
+					  // .PKG is referring everything as root relative,
+					  // sometime there is reference to $(EPOCROOT) too
+					  // let's try to guess what it was. I hate windows drive letter
+					  if (localFile.charAt(0) == '\\') {
+						  localFile = GuessAndFixPath.fixPath(localFile, epocroot, pkgName);
+					  }
+					  
+					  String lowerLocal = localFile.toLowerCase();
+					  if (checkFileExtension(lowerLocal))
+					  {
+						  System.out.println(Messages.getString("BinaryReader.addedPkgFile")+lowerLocal); //$NON-NLS-1$
+						  this.addFile(lowerLocal, epocroot);
+					  }
+				  }
+			  }
+		  	}
+		  catch (Exception e)
+		  {
+			  
+		  }
+	  }
+  }
+  
+  public void addSingleFile(String fileName)
+  {
+  	File file = new File(fileName);
+  	this.addFile(file); 
+  	this.refreshFileTable();
+  }
+  
+  private void addFile(String fileName, String epocroot)
+  {
+	  File f = new File(epocroot + fileName);
+    if (!f.exists()) System.out.println(Messages.getString("BinaryReader.epocRootFileNonexistent1")+fileName+Messages.getString("BinaryReader.epocRootFileNonexistent2")); //$NON-NLS-1$ //$NON-NLS-2$
+    else
+      {
+        addFile(f);
+        //System.out.println("Added file "+fileName+" length "+f.length());
+      }
+
+  }
+
+  private void addFile(File file)
+  {
+    if (file.exists() && !file.isDirectory())
+    {
+      //System.out.println("ADDED"+file.getName());
+      this.files.add(file);
+    }
+    else
+    {
+      System.out.println(Messages.getString("BinaryReader.fileNonexistent1")+file.getAbsolutePath()+Messages.getString("BinaryReader.fileNonexistent2")); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+  }
+
+  public static void main(String a[]) throws Exception
+  {
+	  System.out.println("Starting"); //$NON-NLS-1$
+	  try
+	  {
+	    	GeneralMessages.showErrorMessage("BinaryReader Internal Error"); //$NON-NLS-1$
+	    	throw new Exception ("BinaryReader Internal Error"); //$NON-NLS-1$
+	  }
+	  catch (Exception e)
+	  {
+		  e.printStackTrace();
+	  }
+  }
+  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/BinaryReader122.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.io.BufferedReader;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Hashtable;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.pi.importer.SampleImporter;
+import com.nokia.carbide.cpp.pi.importer.SampleImporter.PkgObyFile;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+import com.nokia.carbide.cpp.pi.util.GuessAndFixPath;
+
+
+/*
+ * This class is a reader of OBY/PKG file for building two hashes
+ * with the support of IttTrace22(the real trace reader)
+ * 1. binary(host side) => map files hash for using map file
+ * 2. string(host side) => binary hash for using ROFS symbol file
+ * 
+ * it reads OBY/PKG line by line and for host/target reference and 
+ * update records of "Binary" from dynamic binary trace.
+ * 
+ */
+
+public class BinaryReader122
+{
+	private boolean debug = false;
+	private IttTrace122 ittTrace122;
+	
+	private Hashtable<Binary, MapFile> binaryToMapFile;
+	private Hashtable<String, Binary> hostNameToBinary;	// so we can adjust ROFS symbol
+	
+	private Pattern stopPattern     = Pattern.compile("(?:\\p{Blank}*)(?:[S|s][T|t][O|o][P|p])(?:\\p{Blank}+(?!\\p{Blank}).*|\\p{Blank}*)"); //$NON-NLS-1$
+	private Pattern commentPattern  = Pattern.compile("(?:\\p{Blank}*)(?:[R|r][E|e][M|m])(?:\\p{Blank}+(?!\\p{Blank}).*|\\p{Blank}*)"); //$NON-NLS-1$
+	private Pattern fileSpecPattern = Pattern.compile("(?:\\p{Blank}*)(?:data|file|primary|secondary|variant|device|extension|dll|filecompress|fileuncompress)(?:(?:\\[.*?\\])?)(?:\\p{Blank}*=\\p{Blank}*)((?:\\S|[ ])+(?:\\S))(?:\\p{Blank}+)(?:\")((?:\\S|[ ])+(?:\\S))(?:\")(?:.*)"); //$NON-NLS-1$
+	
+	public BinaryReader122(IttTrace122 ittTrace122)
+	{
+		binaryToMapFile = new Hashtable<Binary, MapFile>();
+		setHostNameToBinary(new Hashtable<String,Binary>());
+		
+		this.ittTrace122 = ittTrace122;
+		
+		
+		for(PkgObyFile currentFile : SampleImporter.getInstance().getPkgObyFilesList()) {
+			String fileName = currentFile.fileAbsolutePath;
+			
+			if (fileName.toLowerCase().endsWith(".oby") || fileName.toLowerCase().endsWith(".iby")) //$NON-NLS-1$ //$NON-NLS-2$
+				parseAndProcessObyFile(fileName);
+			else if (fileName.toLowerCase().endsWith(".pkg")) //$NON-NLS-1$
+			{
+				addFilesInPkg(fileName);
+			}
+			else
+			{
+		    	GeneralMessages.showErrorMessage(Messages.getString("BinaryReader122.wrongEKA2FileType1")+fileName+Messages.getString("BinaryReader122.wrongEKA2FileType2")); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}		
+	}
+	
+	public MapFile getMapFileForBinary(Binary b)
+	{
+		return this.binaryToMapFile.get(b);
+	}
+	
+	public Binary getBinaryForHostName(String s)
+	{
+		return this.getHostNameToBinary().get(s);
+	}
+	
+	  public void addFilesInPkg(String pkgName)
+	  {
+		  long lineNumber = 0;
+		  File pkgFile = new File(pkgName);
+		  if (pkgFile.exists() && !pkgFile.isDirectory())
+		  {
+			  String localFile = ""; //$NON-NLS-1$
+			  String mapName = ""; //$NON-NLS-1$
+			  try
+			  {
+				  BufferedReader br = new BufferedReader(new FileReader(pkgFile));
+				  String line;
+				  
+				  while((line = br.readLine()) != null)
+				  {
+					  ++lineNumber;
+					  
+					  // find comment lines, which are started with a ';'
+					  int first = line.indexOf(";"); //$NON-NLS-1$
+					  
+					  if (first != -1) {
+						  int i = 0;
+						  for (; i < first; i++)
+						  {
+							  if (line.charAt(i) != ' ' && line.charAt(i) != '\t')
+								  break;
+						  }
+						  if (i == first)
+							  continue;
+					  }
+					  
+					  //System.out.println(line);
+					  first = line.indexOf("\""); //$NON-NLS-1$
+					  int second = -1;
+					  int third = -1;
+					  int fourth = -1;
+					  
+					  if (first != -1)
+						  second = line.indexOf("\"",first+1); //$NON-NLS-1$
+					  
+					  if (second != -1)
+						  third = line.indexOf("\"!:",second+1); //$NON-NLS-1$
+					  
+					  if (third != -1)
+						  fourth = line.indexOf("\"",third+1); //$NON-NLS-1$
+						  
+					  //System.out.println(first+" "+second+" "+third+" "+fourth);
+					  if (fourth != -1)
+					  {
+						  Binary binary = null;
+						  
+						  localFile = line.substring(first+1,second);
+						  String remoteFile = line.substring(third+3,fourth);
+						  
+						  // .PKG is referring everything as root relative,
+						  // sometime there is reference to $(EPOCROOT) too
+						  // let's try to guess what it was. I hate windows drive letter
+						  if (localFile.charAt(0) == '\\') {
+							  localFile = GuessAndFixPath.fixPath(localFile, "", pkgName);	//$NON-NLS-1$
+						  } else if (localFile.charAt(1) != ':') {
+							  // not absolute drive, resolve relative to PKG file
+							  File relativeMapFile = new File(pkgFile.getParent(), localFile);
+							  if (relativeMapFile.exists()) {
+								  localFile = relativeMapFile.getCanonicalPath();
+							  }
+						  }
+						  
+						  String lowerLocal = localFile.toLowerCase();
+						  if (BinaryReader.checkFileExtension(lowerLocal))
+						  {
+							  if (debug)System.out.println(Messages.getString("BinaryReader122.addingPkgFile")+lowerLocal); //$NON-NLS-1$
+			        		  
+				        	  binary = this.ittTrace122.getBinaryForFileName(remoteFile);
+				        	  if (debug)System.out.println(Messages.getString("BinaryReader122.gotBinaryPkgFile")+lowerLocal); //$NON-NLS-1$
+				        	  
+					          if (binary != null)
+					          {
+					        	  if (debug)System.out.println(Messages.getString("BinaryReader122.foundPkgBinary1")+binary.binaryName+Messages.getString("BinaryReader122.foundPkgBinary2")+localFile); //$NON-NLS-1$ //$NON-NLS-2$
+				        		  binary.binaryName = localFile;
+				        		  getHostNameToBinary().put(binary.binaryName, binary);
+					          }
+							  
+					          mapName = localFile+".map"; //$NON-NLS-1$
+					          File mapFile = new File(mapName);
+					          MapFile mf = new MapFile(mapFile, pkgFile.toString(), lineNumber);
+							  if (mapFile.exists() && binary != null)
+			        		  {
+			        			  try
+			        			  {
+			        				  if (binary != null)
+			        				  {
+							        	  if (debug)System.out.println(Messages.getString("BinaryReader122.canGetBinaryFrom1")+binary.binaryName+Messages.getString("BinaryReader122.canGetBinaryFrom2")+localFile); //$NON-NLS-1$ //$NON-NLS-2$
+			        					  binaryToMapFile.put(binary,mf);
+			        				  }
+			        				  else
+			        				  {
+			        					  if (debug)System.out.println(Messages.getString("BinaryReader122.cannotCreatePkgFileFrom") + mapName); //$NON-NLS-1$
+			        				  }
+			        			  }
+			        			  catch (Exception e)
+			        			  {
+			        				  if (debug)System.out.println(Messages.getString("BinaryReader122.pkgNotOK")+remoteFile); //$NON-NLS-1$
+			        			  }
+			        		  }
+						  }
+					  }
+				  } // while((line = br.readLine()) != null)
+			  } catch (Exception e) {
+				  // either malformed PKG or we are not robust enough
+				  GeneralMessages.showErrorMessage (Messages.getString("BinaryReader122.pkgMalform")); //$NON-NLS-1$
+			  }
+		  }
+	  }
+	
+	public void parseAndProcessObyFile(String obyFile) {
+		File f = new File (obyFile);
+		
+		try {
+			BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
+			String line = br.readLine();
+			long lineNumber = 1;
+			
+			while (line != null) {
+				Matcher stopMatcher = stopPattern.matcher(line);
+				if (stopMatcher.matches()) {
+					break;
+				}
+				Matcher commentMatcher = commentPattern.matcher(line); //$NON-NLS-1$
+				if (!commentMatcher.matches()) {
+					// case is sensitive in OBY keywords
+					// only read file spec from OBY
+					Matcher fileSpecMatcher = fileSpecPattern.matcher(line); //").matcher(line); //$NON-NLS-1$
+					if (fileSpecMatcher.matches()) {
+						Binary binary = ittTrace122.getBinaryForFileName(fileSpecMatcher.group(2).trim());
+						if (binary != null) {
+							binary.binaryName = fileSpecMatcher.group(1).trim();
+							getHostNameToBinary().put(binary.binaryName, binary);
+							
+							String pcFileName = fileSpecMatcher.group(1).trim();
+							// .OBY is referring everything as root relative,
+							// sometime there is reference to $(EPOCROOT) too
+							// let's try to guess what it was. I hate windows drive letter
+							if (pcFileName.charAt(0) == '\\') {
+								pcFileName = GuessAndFixPath.fixPath(pcFileName, SampleImporter.getInstance().getRomEpocroot(), ""); //$NON-NLS-1$ //$NON-NLS-2$
+							}
+							if (pcFileName.endsWith("\"")) //$NON-NLS-1$
+								pcFileName = pcFileName.substring(0, pcFileName.length() - 1);
+							
+							pcFileName += ".map"; //$NON-NLS-1$
+							File pcFile = new File(pcFileName);
+							if (pcFile.exists())
+							{
+								MapFile mf = new MapFile(pcFile, obyFile, lineNumber);
+								binaryToMapFile.put(binary,mf);
+							} else {
+								  // .map not found
+								  if(pcFileName.endsWith(".exe.map") || //$NON-NLS-1$
+										  pcFileName.endsWith(".dll.map") || //$NON-NLS-1$
+										  pcFileName.endsWith(".ldd.map") || //$NON-NLS-1$
+										  pcFileName.endsWith(".pdd.map") || //$NON-NLS-1$
+										  pcFileName.endsWith(".app.map"))  //$NON-NLS-1$
+								  {
+									  String myMessage = Messages.getString("BinaryReader122.map.file") +  pcFileName + Messages.getString("BinaryReader122.not.found"); //$NON-NLS-1$ //$NON-NLS-2$
+									  if (obyFile != null && obyFile.length() > 0) {
+										  myMessage += Messages.getString("BinaryReader122.referenced.by") + obyFile; //$NON-NLS-1$
+									  }
+									  if (lineNumber > 0) {
+										  myMessage += Messages.getString("BinaryReader122.line.number") + lineNumber; //$NON-NLS-1$
+									  }
+
+									  // if it is code binary...
+								      GeneralMessages.PiLog(myMessage, GeneralMessages.WARNING);
+								  }
+							}
+						}
+						else if (debug) {
+							System.out.print(fileSpecMatcher.group(1));
+							System.out.print("|"); //$NON-NLS-1$
+							System.out.print(fileSpecMatcher.group(2));
+							System.out.println(""); //$NON-NLS-1$
+						}
+					}
+				}
+				
+				line = br.readLine();
+				++lineNumber;
+			}
+		} catch (EOFException e) {
+			// good, that's the end of file, bail out peacefully
+		} catch (IOException e) {
+			GeneralMessages.PiLog(Messages.getString("BinaryReader122.IOException.on") + obyFile, GeneralMessages.ERROR, e); //$NON-NLS-1$
+		}
+	}
+	
+	public void setHostNameToBinary(Hashtable<String, Binary> hostNameToBinary) {
+		this.hostNameToBinary = hostNameToBinary;
+	}
+
+	public Hashtable<String, Binary> getHostNameToBinary() {
+		return hostNameToBinary;
+	}
+	
+	public int parsedMapFileCount() {
+		return this.binaryToMapFile.size();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/BinaryReaderResult.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+
+
+public class BinaryReaderResult
+{
+  public Binary[] possibleBinaries;
+  public Boolean[] checksumValues;
+
+  public String toString()
+  {
+    String s = ""; //$NON-NLS-1$
+    for (int i=0;i<possibleBinaries.length;i++)
+    {
+      s = s+"\n"+possibleBinaries[i].binaryName+" @ "+possibleBinaries[i].startAddress+" "+checksumValues[i].booleanValue(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+    return s;
+  }
+
+  public boolean hasAnyChecksumCorrectValues()
+  {
+    for (int i=0;i<this.checksumValues.length;i++)
+    {
+      if (this.checksumValues[i].booleanValue() == true) return true;
+    }
+    return false;
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/DecidedPool.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+
+
+public class DecidedPool 
+{
+    private boolean debug = false;
+	private MemoryLayout memLayout;
+	private AdvancedMemoryMap amm;
+	
+	public DecidedPool(AdvancedMemoryMap amm)
+	{
+		this.memLayout = new MemoryLayout();
+		this.amm = amm;
+	}
+	
+	public boolean insertSample(IttSample sample)
+	{
+		Vector binaries = this.memLayout.findBinariesForAddress(sample.programCounter);
+		Enumeration binEnum = binaries.elements();
+		
+		Vector okBins = new Vector();
+		while (binEnum.hasMoreElements())
+		{
+			Binary b = (Binary)binEnum.nextElement();
+			if (this.trySampleWithBinary(sample,b,4) == true)
+			{
+				okBins.add(b);
+			}
+		}
+
+		if (okBins.size() == 0)
+		{
+			// no matching binaries
+			return false;
+		}
+		else if (okBins.size() == 1)
+		{
+			// homma bueno
+			return true;
+		}
+		else if (okBins.size() > 1)
+		{
+			Vector okOkBins = new Vector();
+			Enumeration okBinEnum = binaries.elements();
+			while (okBinEnum.hasMoreElements())
+			{
+				Binary b = (Binary)okBinEnum.nextElement();
+				if (this.trySampleWithBinary(sample,b,0) == true)
+				{
+					okOkBins.add(b);
+				}
+			}
+			
+			if (okOkBins.size() > 1)
+			{
+				Enumeration okOkBinEnum = okOkBins.elements();
+				int winnerSupSamples = 0;
+				while (okOkBinEnum.hasMoreElements())
+				{
+					Binary b = (Binary)okOkBinEnum.nextElement();
+					DecidedLocation dl = this.memLayout.getDecidedLocationForBinary(b);
+					if (dl.getSupportingSamples().size() > winnerSupSamples) 
+					{
+						winnerSupSamples = dl.getSupportingSamples().size();
+					}
+				}
+			}
+						
+			return true;
+		}
+		else
+		{
+			if (debug)System.out.println(Messages.getString("DecidedPool.debugDecidedPool")); //$NON-NLS-1$
+			return false;
+		}
+	}
+	
+	public boolean isThereAnyBinaryInMemoryIn(long address)
+	{
+		if (this.memLayout.findBinariesForAddress(address).size() == 0)
+		{
+			return false;
+		}
+		else 
+		{
+			return true;
+		}
+	}
+	
+	public Function getFunctionForAddress(long address)
+	{
+		Vector binaries = this.memLayout.findBinariesForAddress(address);
+		Enumeration binEnum = binaries.elements();
+		
+		Binary winner = null;
+		int winnerSupport = -100000;
+		
+		while (binEnum.hasMoreElements())
+		{
+			Binary b = (Binary)binEnum.nextElement();
+			DecidedLocation dl = this.memLayout.getDecidedLocationForBinary(b);
+			int support = dl.supportingSamples.size()-dl.nonSupportingSamples.size();
+			if (support > winnerSupport)
+			{
+				winner = b;
+				winnerSupport = support;
+			}
+		}
+		if (winner != null)
+		{
+			ProcessedBinary pb = this.amm.getBinaryReader().
+									getProcessedBinaryForName(winner.binaryName);
+			
+			
+			String fName = pb.getFunctionNameForOffset(
+							address-(winner.startAddress+winner.offsetToCodeStart));
+			
+			String bName = winner.binaryName;
+			long fOffset = pb.getOffsetFromBinaryStartForFunction(fName);
+			Long fStart = new Long(winner.startAddress+winner.offsetToCodeStart+fOffset);
+			
+			Function f = new Function(fName,fStart,bName);
+			f.length = pb.getFunctionLengthForOffset(fOffset);
+			
+			return f;
+
+		}
+		
+		return null;
+	}
+	
+	public boolean trySampleWithBinary(IttSample sample, Binary b,int allowErrors)
+	{
+		if (b != null)
+		{
+			if (amm.getBinaryReader().checkSampleInBinary(sample,b,allowErrors) == true)
+			{
+				//System.out.println("Located 0x"+Long.toHexString(sample.programCounter)+" to "+b.binaryName);
+				DecidedLocation dl = this.memLayout.getDecidedLocationForBinary(b);
+				dl.insertSupportingSample(sample);
+
+				return true;
+			}
+			else
+			{
+				// binary is not a match with the sample, register the sample as
+				// a non-supporting sample. These will be processed at a later time
+
+				DecidedLocation dl = this.memLayout.getDecidedLocationForBinary(b);
+				dl.insertNonSupportingSample(sample);
+				
+				//System.out.println("Binary "+b.binaryName+" might be in a wrong place - n:"+
+				//					dl.getNonSupportingSamples().size()+" s:"+dl.getSupportingSamples().size());
+
+				return false;
+			}
+		}
+		else
+		{
+			return false;
+		}
+	}
+	
+	public void insertDecidedBinary(Binary binary,Vector samples)
+	{		
+		Vector currentBins = this.memLayout.isOccupiedBy(binary.startAddress,binary.length);
+		
+		if (currentBins.size() == 0)
+		{
+			if (debug) System.out.println(Messages.getString("DecidedPool.analysisResolved1")+binary.binaryName+Messages.getString("DecidedPool.analysisResolved2")+Long.toHexString(binary.startAddress+binary.offsetToCodeStart)+ //$NON-NLS-1$ //$NON-NLS-2$
+					Messages.getString("DecidedPool.analysisResolved3")+Long.toHexString(binary.startAddress+binary.offsetToCodeStart+binary.length)); //$NON-NLS-1$
+			
+			DecidedLocation dl = new DecidedLocation(binary);
+			dl.insertSupportingSamples(samples);
+			
+			this.memLayout.insertArea(dl);
+		}
+		else
+		{
+			Enumeration curEnum = currentBins.elements();
+			while (curEnum.hasMoreElements())
+			{
+				Binary b = (Binary)curEnum.nextElement();
+
+				boolean okForThis = true;
+				int okCount = 0;
+				Enumeration sampEnum = samples.elements();
+				
+				while (sampEnum.hasMoreElements())
+				{
+					IttSample is = (IttSample)sampEnum.nextElement();
+
+					if (is.programCounter >= b.startAddress && is.programCounter <= b.startAddress+b.length)
+					{
+						if (this.trySampleWithBinary(is,b,4) == false) 
+							okForThis=false;
+						else
+							okCount++;
+					}
+				}
+				
+				if (okForThis == true)
+				{
+					//System.out.println(okCount+" samples in "+binary.binaryName+" match to "+b.binaryName);
+				}
+			}
+						
+			DecidedLocation dl = new DecidedLocation(binary);
+			dl.insertSupportingSamples(samples);
+			
+			this.memLayout.insertArea(dl);			
+			
+			/*
+			System.out.println(overLap+" Area at "+Long.toHexString(currentBin.startAddress)+"-"
+								+Long.toHexString(currentBin.startAddress+currentBin.length)
+								+" is occupied by "
+								+currentBin.binaryName+" - unable to locate "+binary.binaryName+" to "
+								+Long.toHexString(binary.startAddress)+"-"
+								+Long.toHexString(binary.startAddress+binary.length));
+			*/
+		}
+	}
+	
+	public Enumeration getSupportingSamplesForBinary(Binary b)
+	{
+		DecidedLocation dl = this.memLayout.getDecidedLocationForBinary(b);
+		if (dl != null)
+		{
+			return dl.supportingSamples.elements();			
+		}
+		else
+		{
+			return new Vector().elements();
+		}
+	}
+
+	public Enumeration getNonSupportingSamplesForBinary(Binary b)
+	{
+		DecidedLocation dl = this.memLayout.getDecidedLocationForBinary(b);
+		if (dl != null)
+		{
+			return dl.nonSupportingSamples.elements();			
+		}
+		else
+		{
+			return new Vector().elements();
+		}
+	}
+	
+	public Binary getBinaryWithName(String binaryName)
+	{
+		return this.memLayout.getBinaryWithName(binaryName);
+	}
+	
+	public Binary findBinaryForSample(IttSample sample)
+	{
+		Vector binaries = this.memLayout.findBinariesForAddress(sample.programCounter+4);
+		if (binaries == null) return null;
+		if (binaries.size() == 0) return null;
+		
+		Vector okBins = new Vector();
+		Enumeration enumer = binaries.elements();
+		
+		while (enumer.hasMoreElements())
+		{
+			Binary b = (Binary)enumer.nextElement();
+			if (this.trySampleWithBinary(sample,b,6))
+			{
+				okBins.add(b);
+			}
+		}	
+		
+		if (okBins.size() <= 0)
+		{
+			if (binaries.size() == 1)
+			{
+				// there is only one binary at this location in memory,
+				// guess that it is the one we are looking for even though
+				// the samples don't match
+				Binary binary = (Binary)binaries.firstElement();
+				//System.out.println("Guessing that "+binary.binaryName+" is at 0x"+Long.toHexString(sample.programCounter));
+				return binary;
+			}
+			else if (binaries.size() > 1)
+			{
+				Enumeration binEnum = binaries.elements();
+				DecidedLocation bestGuess = this.memLayout.getDecidedLocationForBinary(
+												(Binary)binEnum.nextElement());
+				while (binEnum.hasMoreElements())
+				{
+					DecidedLocation dl = this.memLayout.getDecidedLocationForBinary(
+											(Binary)binEnum.nextElement());
+					
+					if ( (dl.supportingSamples.size()-dl.nonSupportingSamples.size()) >
+							(bestGuess.supportingSamples.size()-bestGuess.nonSupportingSamples.size()) )
+					{
+						bestGuess = dl;
+					}
+				}
+				// return the binary that has most support for its location
+				return bestGuess.binary;
+			}
+		}
+		else if (okBins.size() == 1)
+		{
+			return (Binary)okBins.firstElement();
+		}
+		else if (okBins.size() > 1)
+		{
+			Enumeration okEnum = okBins.elements();
+			
+			Vector okOkVec = new Vector();
+			
+			while (okEnum.hasMoreElements())
+			{
+				Binary okBin = (Binary)okEnum.nextElement();
+				if (this.trySampleWithBinary(sample,okBin,0) == true)
+				{
+					okOkVec.add(okBin);
+				}
+			}
+			
+			if (okOkVec.size() == 1) return (Binary)okOkVec.firstElement();
+			
+			else if (okOkVec.size() <= 0) return null;
+			
+			else if (okOkVec.size() > 1)
+			{
+					Enumeration okOkEnum = okOkVec.elements();
+					
+					Binary winner = null;
+					int winnerSupSamples = 0;
+					//System.out.println("Conflict: "+okOkVec.size()+" binaries");
+
+					while (okOkEnum.hasMoreElements())
+					{
+						Binary b = (Binary)okOkEnum.nextElement();
+						DecidedLocation dl = this.memLayout.getDecidedLocationForBinary(b);
+						if (dl.getSupportingSamples().size() > winnerSupSamples) 
+						{
+							winnerSupSamples = dl.getSupportingSamples().size();
+							winner = b;
+							//System.out.println("bin: "+b.binaryName+""+dl.getSupportingSamples().size());
+						}
+					}
+					/*
+					if (winner != null)
+						System.out.println("Winner: "+winner.binaryName+"\n");
+					else
+						System.out.println("NO WINNER???");
+					*/
+					return winner;
+			}
+		}
+		
+		return null;
+	}
+	
+	private static class DecidedLocation
+	{
+		private Binary binary;
+		private Vector supportingSamples;
+		private Vector nonSupportingSamples;
+		
+		public DecidedLocation(Binary binary)
+		{
+			this.binary = binary;
+			this.supportingSamples = new Vector();
+			this.nonSupportingSamples = new Vector();
+		}
+		
+		public void insertSupportingSample(IttSample sample)
+		{
+			this.supportingSamples.add(sample);
+		}
+		
+		public void insertSupportingSamples(Vector samples)
+		{
+			Enumeration enumer = samples.elements();
+			while (enumer.hasMoreElements())
+			{
+				IttSample s = (IttSample)enumer.nextElement();
+				if (!this.supportingSamples.contains(s))
+				{
+					this.insertSupportingSample(s);
+				}
+			}
+		}
+		
+		public void insertNonSupportingSample(IttSample sample)
+		{
+			if (!this.nonSupportingSamples.contains(sample))
+			{
+				this.nonSupportingSamples.add(sample);
+			}
+		}
+		
+		public Vector getSupportingSamples()
+		{
+			return this.supportingSamples;
+		}
+
+		public Vector getNonSupportingSamples()
+		{
+			return this.nonSupportingSamples;
+		}
+		
+	}
+	
+	private static class MemoryLayout
+	{
+		public Hashtable decidedLocations;
+		
+		public MemoryLayout()
+		{
+			// keys are the binaries
+			// decided locations are the elements
+			this.decidedLocations = new Hashtable();
+		}
+		
+		public void insertArea(DecidedLocation dl)
+		{
+			this.decidedLocations.put(dl.binary,dl);
+		}
+		
+		public Vector isOccupiedBy(long start, long length)
+		{
+			Vector binaries = new Vector();
+			
+			Enumeration enumer = this.decidedLocations.keys();
+			while (enumer.hasMoreElements())
+			{
+				Binary b = (Binary)enumer.nextElement();
+				long bStart = b.startAddress;
+				long bEnd = b.startAddress+b.length;
+				long end = start+length;
+				
+				// starts within the area
+				if (start <= bEnd && start >= bStart)
+				{
+					binaries.add(b);
+				}
+					
+				// ends within the area
+				else if (end <= bEnd && end >= bStart)
+				{
+					binaries.add(b);
+				}
+				
+				// is over the area
+				else if (start <= bStart && end >= bEnd)
+				{
+					binaries.add(b);
+				}
+
+			}
+			return binaries;
+		}
+		
+		public DecidedLocation getDecidedLocationForBinary(Binary b)
+		{
+			if (this.decidedLocations.containsKey(b))
+			{
+				return (DecidedLocation)this.decidedLocations.get(b);
+			}
+			else
+			{
+				return null;
+			}
+		}
+		
+		public Vector findBinariesForAddress(long address)
+		{
+			Enumeration enumer = this.decidedLocations.keys();
+			Vector binaries = new Vector();
+			
+			while (enumer.hasMoreElements())
+			{
+				Binary b = (Binary)enumer.nextElement();
+				long bStart = b.startAddress;
+				long bEnd = b.startAddress+b.length;
+				
+				if (address >= bStart && address <= bEnd)
+				{
+					binaries.add(b);
+				}
+				
+			}
+			return binaries;
+		}
+		
+		public Binary getBinaryWithName(String binaryName)
+		{
+			Enumeration dls = this.decidedLocations.keys();
+			while (dls.hasMoreElements())
+			{
+				Binary b = (Binary)dls.nextElement();
+				if (b.binaryName.toLowerCase().equals(binaryName.toLowerCase())) return b;
+			}
+			return null;
+		}
+		
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/InstrPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.io.File;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.osgi.framework.BundleContext;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class InstrPlugin extends AbstractPiPlugin
+			implements ITrace, IClassReplacer {
+
+	//The shared instance.
+	private static InstrPlugin plugin;
+	
+	/**
+	 * The constructor.
+	 */
+	public InstrPlugin() {
+		plugin = this;
+	}
+
+	public Class getReplacedClass(String className)
+	{
+		if (   className.indexOf("com.nokia.carbide.cpp.pi.instr.IttTrace122") != -1 //$NON-NLS-1$
+			|| className.indexOf("com.nokia.carbide.pi.instr.IttTrace122") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.model.IttTrace122") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.ittTracePlugin.IttTrace122") != -1) //$NON-NLS-1$
+		{
+			return IttTrace122.class;
+		}
+		if (   className.indexOf("com.nokia.carbide.cpp.pi.instr.IttEvent122") != -1 //$NON-NLS-1$
+			|| className.indexOf("com.nokia.carbide.pi.instr.IttEvent122") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.model.IttEvent122") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.ittTracePlugin.IttEvent122") != -1) //$NON-NLS-1$
+		{
+			return IttEvent122.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.instr.IttTrace") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.instr.IttTrace") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.model.IttTrace") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.ittTracePlugin.IttTrace") != -1) //$NON-NLS-1$
+		{
+			return IttTrace.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.instr.IttSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.instr.IttSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.model.IttSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.ittTracePlugin.IttSample") != -1) //$NON-NLS-1$
+		{
+			return IttSample.class;
+		}
+		else
+		{
+			return null;
+		}
+	}
+	
+	public Class getTraceClass() 
+	{
+		//return IttTrace.class;
+		// may be bad, but we should only support the new ITT
+		return IttTrace122.class;
+	}
+
+	public void initialiseTrace(GenericTrace trace) 
+	{
+		//no action required at the moment - maybe some event casting in future
+	}
+
+	public String getTraceName() {
+		return "Dynamic Binary Support"; //$NON-NLS-1$
+	}
+
+	public int getTraceId() {
+		return 3;
+	}
+
+	public ParsedTraceData parseTraceFile(File file /*, ProgressBar progressBar*/) throws Exception 
+	{
+		try
+        {
+            IttTraceParser ittParser;
+            
+            ittParser = new IttTraceParser();
+            
+            ParsedTraceData ptd = ittParser.parse(file/*,progressBar*/);
+     		return ptd;
+           
+        } catch (Exception e)
+        {
+            e.printStackTrace();
+            throw e;
+        }
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		plugin = null;
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static InstrPlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractPiPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi.instr", path); //$NON-NLS-1$
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/InstrReturnPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IReturnPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+
+
+public class InstrReturnPlugin implements IReturnPlugin {
+	public AbstractPiPlugin getPlugin() {
+		return InstrPlugin.getDefault();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/IttEvent122.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.internal.pi.model.GenericEvent;
+
+public class IttEvent122 extends GenericEvent 
+  {
+	private static final long serialVersionUID = -5460562756042454539L;
+
+	public String binaryName;
+	public long binaryLength;
+	public long binaryLocation;
+	public Binary binary;
+
+	public IttEvent122()
+	{
+		super(0);
+	}
+	
+	public void createBinary()
+	{
+		binary = new Binary(this.binaryName);
+		binary.length = (int)this.binaryLength;
+		binary.offsetToCodeStart = 0;
+		binary.startAddress = this.binaryLocation;
+		binary.type = Messages.getString("IttEvent122.unknownBinaryType"); //$NON-NLS-1$
+	}
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/IttSample.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampleWithFunctions;
+
+
+public class IttSample extends GenericSampleWithFunctions
+{
+  private static final long serialVersionUID = 31446918621985951L;
+	
+  public long[] instructions;
+  public long checksum;
+  public long programCounter;
+
+  public Function currentFunctionItt;
+  public Binary currentBinaryItt;
+  public Function currentFunctionSym;
+  public Binary currentBinarySym;
+  
+  public IttSample(int size)
+  {
+    instructions = new long[size];
+    sampleSynchTime = 0;
+  }
+
+  public long[] reversedInstructions()
+  {
+    long[] revs = new long[instructions.length];
+    for (int i=0;i<instructions.length;i++)
+    {
+      revs[i] |= (((instructions[i] & 0x000000ff) << 24) & 0xff000000);
+      revs[i] |= (((instructions[i] & 0x0000ff00) << 8) & 0x00ff0000);
+      revs[i] |= (((instructions[i] & 0x00ff0000) >> 8) & 0x0000ff00);
+      revs[i] |= (((instructions[i] & 0xff000000) >> 24) & 0x000000ff);
+
+      //System.out.print("\nOriginal "+Integer.toHexString((int)instructions[i]));
+
+      String temp = Long.toHexString(revs[i]);
+      String nulls = ""; //$NON-NLS-1$
+      for (int n=0;n<8-temp.length();n++) nulls=nulls+"0"; //$NON-NLS-1$
+      temp = nulls+temp;
+      //System.out.println(" reversed "+temp);
+    }
+    return revs;
+  }
+
+  public void resolveFunction(FunctionResolver res)
+  {
+  	if (res.getResolverName().equals("Symbol"))  //$NON-NLS-1$
+  	{
+  		this.currentFunctionSym = res.findFunctionForAddress(programCounter);
+  		
+  		if (this.currentFunctionSym != null)
+  			this.currentBinarySym = this.currentFunctionSym.functionBinary;
+  	}
+  	else if (res.getResolverName().equals("ITT"))  //$NON-NLS-1$
+  	{
+  		if (currentFunctionSym == null) {
+	  		this.currentFunctionItt = res.findFunctionForAddress(programCounter);
+	  		
+	  		if (this.currentFunctionItt != null)
+	  			this.currentBinaryItt = this.currentFunctionItt.functionBinary;
+  		}
+  	}
+  }
+   
+  public String toReversedString()
+  {
+    String s = ""; //$NON-NLS-1$
+    long[] revs = this.reversedInstructions();
+    
+    for (int i=0;i<instructions.length;i++)
+    {
+      String nulls = ""; //$NON-NLS-1$
+      String temp = ""; //$NON-NLS-1$
+      temp = Integer.toHexString((int)revs[i]);
+      for (int t = 0;t<(8-temp.length());t++) nulls = nulls+"0"; //$NON-NLS-1$
+      s = s+(nulls+temp+Messages.getString("IttSample.space")); //$NON-NLS-1$
+    }
+    return s;
+  }
+  
+  public String toString()
+  {
+  	long diff = 0;
+  	
+  	if (this.currentBinaryItt != null && this.currentBinarySym != null)
+  		diff = this.currentBinaryItt.startAddress+this.currentBinaryItt.offsetToCodeStart-
+			   this.currentBinarySym.startAddress;
+  	else
+  	{
+  		System.out.println("NULL"); //$NON-NLS-1$
+  	}
+  	
+  	String result = "Itt:#"+this.sampleSynchTime+ //$NON-NLS-1$
+			" @0x"+Long.toHexString(this.programCounter)+ //$NON-NLS-1$
+			" fS:"+this.currentFunctionSym.functionName+ //$NON-NLS-1$
+			" oS:"+Long.toHexString(this.currentFunctionSym.startAddress.longValue())+" +"+(this.programCounter-this.currentFunctionSym.startAddress.longValue())+ //$NON-NLS-1$ //$NON-NLS-2$
+			" fI:"+this.currentFunctionItt.functionName+ //$NON-NLS-1$
+			" oI:"+Long.toHexString(this.currentFunctionItt.startAddress.longValue())+" +"+(this.programCounter-this.currentFunctionItt.startAddress.longValue()); //$NON-NLS-1$ //$NON-NLS-2$
+  	
+  	if (diff != 0) result=" DIFF: "+diff+" "+result; //$NON-NLS-1$ //$NON-NLS-2$
+  	
+  	return result;
+  }
+
+  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/IttTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTraceWithFunctions;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+
+
+public class IttTrace extends GenericSampledTraceWithFunctions
+{	
+	private static final long serialVersionUID = 8450351679961604426L;
+	
+	public void addSample(IttSample sample)
+	{
+		this.samples.add(sample);
+	}
+
+	public IttSample getIttSample(int number)
+	{
+		return (IttSample)this.samples.elementAt(number);
+	}
+
+	public GenericTraceGraph getTraceGraph() {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace#getTraceGraph(int, com.nokia.carbide.cpp.internal.pi.analyser.AnalyseTab)
+	 */
+	public GenericTraceGraph getTraceGraph(int graphNumber) {
+		return null;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/IttTrace122.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.internal.pi.model.GenericEvent;
+import com.nokia.carbide.cpp.internal.pi.model.GenericEventTrace;
+
+
+public class IttTrace122 extends GenericEventTrace
+  {
+	private static final long serialVersionUID = -3670942351731061113L;
+	private boolean debug = false;
+	private transient boolean sortedEvents = false;
+	private transient Object[] sorted;
+	private transient Hashtable<String,Function> knownFunctions = new Hashtable<String,Function>();
+	private transient Hashtable<String,Binary> knownBinaries = new Hashtable<String,Binary>();
+	
+	public IttTrace122()
+	{
+	}
+	
+	public Binary getBinaryForAddress(long address)
+	{
+		Enumeration<GenericEvent> enr = this.getEvents().elements();
+		while(enr.hasMoreElements())
+		{
+			IttEvent122 ev = (IttEvent122)enr.nextElement();
+			if (   (address >= ev.binaryLocation)
+				&& (address < (ev.binaryLocation + ev.binaryLength)) )
+			{
+				//System.out.println("Found "+Long.toHexString(address));
+				return ev.binary;			
+			}
+		}
+		
+		return null;
+	}
+
+	public Binary getBinaryForAddressNew(long address)
+	{
+		if (!sortedEvents) {
+			sorted = this.getEvents().toArray();
+			Arrays.sort(sorted, new Comparator<Object>() {
+				
+				public int compare(Object arg0, Object arg1)
+				{
+					if (arg0 instanceof IttEvent122 && arg1 instanceof IttEvent122)
+						return (int) (((IttEvent122)arg0).binaryLocation - ((IttEvent122)arg1).binaryLocation);
+					else
+						return 0;
+				}
+			});
+			sortedEvents = true;
+		}
+
+		int high = sorted.length;
+		int low = -1;
+		int next;
+		
+		// find a match using binary search
+		while (high - low > 1) {
+			next = (low + high) >>> 1;
+			IttEvent122 event = (IttEvent122)sorted[next];
+
+			if (   (address >= event.binaryLocation)
+				&& (address < (event.binaryLocation + event.binaryLength)) ) {
+				return event.binary;
+			}
+
+			if (event.binaryLocation >= address) {
+				high = next;
+			} else {
+				low = next;
+			}
+		}
+
+		return null;
+	}
+
+	public Function getFunctionForAddress(long address,BinaryReader122 br)
+	{
+		Binary b = this.getBinaryForAddressNew(address);
+		if (b != null)
+		{	
+			MapFile mf = br.getMapFileForBinary(b);
+			Function f = null;
+			
+			if (mf != null)
+			{
+				f = mf.getFunctionForOffset(address-b.startAddress);
+				if (f != null)
+				{
+					f.startAddress = new Long(b.startAddress+mf.getOffsetFromBinaryStartForFunction(f.functionName));
+					if (f.startAddress != null)
+					{
+						if (f.functionBinary != null) 
+						{
+							f.functionBinary = b;
+						}
+						//System.out.println("Resolved function to "+f.functionName+" "+Long.toHexString(f.startAddress.longValue()));
+						return f;
+					}
+				}
+				
+				if (debug)System.out.println(Messages.getString("IttTrace122.couldNotResolveFunction")); //$NON-NLS-1$
+			}
+			else
+			{
+				if (debug)System.out.println(Messages.getString("IttTrace122.mapfileNotFound1")+b.binaryName+Messages.getString("IttTrace122.mapfileNotFound2")); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			
+			if (f != null)
+			{
+				return f;
+			}
+			else
+			{
+				String fName = Messages.getString("IttTrace122.functionForAddressNotFound1")+Long.toHexString(address)+Messages.getString("IttTrace122.functionForAddressNotFound2"); //$NON-NLS-1$ //$NON-NLS-2$
+
+				f = this.knownFunctions.get(fName);
+				
+				if (f == null) {
+					f = new Function(fName, new Long(address), b.binaryName);
+					f.functionBinary = b;
+					f.length = 1;
+					f.offsetFromBinaryStart = 0;
+					
+					this.knownFunctions.put(fName, f);
+				}
+
+				return f;
+			}
+		}
+		else
+			return null;
+//		{
+//			String bName = Messages.getString("IttTrace122.binaryForAddressNotFound1")+Long.toHexString(address)+Messages.getString("IttTrace122.binaryForAddressNotFound2"); //$NON-NLS-1$ //$NON-NLS-2$
+//
+//			b = this.knownBinaries.get(bName);
+//			
+//			if (b == null) {
+//				b = new Binary(bName);
+//				b.length = 1;
+//				b.offsetToCodeStart = 0;
+//				b.startAddress = address;
+//				b.type = Messages.getString("IttTrace122.unknownBinaryType"); //$NON-NLS-1$
+//				this.knownBinaries.put(bName, b);
+//			}
+//			
+//			Function f = new Function(	Messages.getString("IttTrace122.functionForAddressNotFound1")+Long.toHexString(address)+Messages.getString("IttTrace122.functionForAddressNotFound2"), //$NON-NLS-1$ //$NON-NLS-2$
+//										new Long(address),
+//										bName);
+//			
+//			f.functionBinary = b;
+//			f.length = 1;
+//			f.offsetFromBinaryStart = 0;
+//			
+//			return f;			
+//		}
+	}
+	
+	  public Binary getBinaryForFileName(String fileName)
+	  {
+		  Enumeration<GenericEvent> en = this.getEvents().elements();
+		  while (en.hasMoreElements())
+		  {
+			  IttEvent122 e = (IttEvent122)en.nextElement();
+			  if (e.binaryName.toLowerCase().indexOf(fileName.toLowerCase()) != -1)
+				  return e.binary;
+		  }
+		  return null;
+	  }
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/IttTraceParser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.Parser;
+import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
+import com.nokia.carbide.cpp.internal.pi.utils.QuickSortImpl;
+import com.nokia.carbide.cpp.internal.pi.utils.Sortable;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+public class IttTraceParser extends Parser
+{
+  private boolean debug = false;
+  private Vector<IttSample> samples;
+  private IttTrace122 trace122;
+
+  public IttTraceParser()
+  {
+  }
+  
+  public ParsedTraceData parseNoProgress(File f) throws Exception
+  {
+	  return this.parse(f/*,null*/);
+  }
+  
+  public ParsedTraceData parse(File f /*, ProgressBar progressBar*/) throws Exception 
+  {
+  		if (!f.exists() || f.isDirectory())
+  	    {
+  	      throw new Exception(Messages.getString("IttTraceParser.cannotOpenTraceFile")); //$NON-NLS-1$
+  	    }
+
+  		parseIttTrace(f);
+  		ParsedTraceData ptd = new ParsedTraceData();
+		ptd.traceData = this.getTrace();
+		
+		if (ptd.traceData instanceof IttTrace) 
+		{
+			BinaryReader br = new BinaryReader();
+			AdvancedMemoryMap amm = new AdvancedMemoryMap(br);
+			
+	  		int analysisId = NpiInstanceRepository.getInstance().activeUid();
+        	Enumeration resEnum = TraceDataRepository.getInstance().getResolvers(analysisId);
+        	
+        	FunctionResolver symbolFileParser = null;
+        	
+        	while(resEnum.hasMoreElements())
+        	{
+        		FunctionResolver fr = (FunctionResolver)resEnum.nextElement();
+        		if (fr.getResolverName().equals("Symbol"))  //$NON-NLS-1$
+        		{
+        			symbolFileParser = fr;
+        			break;
+        		}
+        	}
+			
+      		if (symbolFileParser == null)
+      	    {
+      			// unfortunately, GPP need to be read first in order to make Symbol function resolver available
+      	      throw new Exception(Messages.getString("IttTraceParser.symbolResolverNotFound")); //$NON-NLS-1$
+      	    }
+			
+            Enumeration sEnum = ((IttTrace)this.getTrace()).getSamples();
+            int i = 0;
+            int len = ((IttTrace)this.getTrace()).samples.size();
+            String progString = Messages.getString("IttTraceParser.traceProgress0Percent"); //$NON-NLS-1$
+            
+            while (sEnum.hasMoreElements())
+            {
+        		IttSample itts = (IttSample) sEnum.nextElement();
+
+            	if (symbolFileParser != null)
+            	{
+            		if (symbolFileParser.findBinaryNameForAddress(
+                				itts.programCounter).endsWith(Messages.getString("IttTraceParser.binaryNotFound"))) //$NON-NLS-1$
+            		{
+            			amm.InsertSample(itts);
+            		}
+            	}
+            	else
+            	{
+            		amm.InsertSample(itts);
+            	}
+                i++;
+                
+                String newProgString = Messages.getString("IttTraceParser.traceProgress1")+(i*100)/len+Messages.getString("IttTraceParser.traceProgress2"); //$NON-NLS-1$ //$NON-NLS-2$
+                if (!progString.equals(newProgString))
+                {
+                	progString = newProgString;
+                	
+                	if (symbolFileParser == null)
+                		progString +=Messages.getString("IttTraceParser.traceProgress3"); //$NON-NLS-1$
+                		
+                 }
+            }
+
+             amm.postProcess();
+			
+			ptd.functionResolvers = new FunctionResolver[]{amm};
+		}
+		else if (ptd.traceData instanceof IttTrace122)
+		{
+			BinaryReader122 br122 = new BinaryReader122((IttTrace122)ptd.traceData);
+			PiInstrFunctionResolver pifr = new PiInstrFunctionResolver(br122,(IttTrace122)ptd.traceData,br122.parsedMapFileCount());
+			ptd.functionResolvers = new FunctionResolver[]{pifr};
+		}
+		
+		return ptd;
+	}
+
+  private void parseIttTrace(File f) throws Exception
+  {
+    int instrPerSample = 4;
+
+    DataInputStream dis = new DataInputStream(new FileInputStream(f));
+    //checks if the itt trace is valid
+    
+    byte[] traceArray = new byte[(int)f.length()];
+    
+    dis.readFully(traceArray);
+    
+    String traceStart = new String(traceArray,0,30);
+    int offset = 0;
+    if (traceStart.indexOf("Bappea_ITT") != -1 ) //trace version 1.10 or later //$NON-NLS-1$
+    {
+        offset = traceArray[0];
+        traceVersion = new String(traceArray,1,offset);
+        traceVersion = traceVersion.substring(traceVersion.indexOf("_")+1); //$NON-NLS-1$
+        if (debug) System.out.println(Messages.getString("IttTraceParser.debugTraceVersion")+traceVersion);  //$NON-NLS-1$
+        offset++;
+    }
+    else
+    {
+        traceVersion = "ITT pre 1.0"; //$NON-NLS-1$
+        if (debug) System.out.println(Messages.getString("IttTraceParser.debugTraceVersion1.0")); //$NON-NLS-1$
+    }
+
+    //opens up to 1.10 version ITT traces.
+    if (traceVersion.indexOf("ITT_V1.10") != -1 || traceVersion.equals("ITT pre 1.0")) //$NON-NLS-1$ //$NON-NLS-2$
+    {
+	   	try
+		{
+	   		for (int i=offset;i<traceArray.length-16;)
+	   		{
+	   			long magic = this.getInt32From(traceArray,i);
+	   			long repeat = this.getInt32From(traceArray,i+4);
+	   			
+	   			if (magic == 0xbabbeaaa)
+	   			{
+	   				int valueHi = (int)(((repeat & 0xffff0000) >>> 16) & 0xffff);
+	   				int valueLo = (int)(repeat & 0xffff);
+	   				if (valueHi + valueLo == 0xffff)
+	   				{
+	   					//System.out.println("Performing a repeat of "+valueLo);
+	   					for (int m=0;m<valueLo;m++)
+	   					{
+	   						IttSample s = (IttSample)samples.lastElement();
+	   						IttSample newS = new IttSample(instrPerSample);
+	   						
+	   						// copy the fields, increase the synch time for each sample
+	   						newS.checksum = s.checksum;
+	   						newS.programCounter = s.programCounter;
+	   						newS.sampleSynchTime = s.sampleSynchTime+1;
+	   						//System.out.println("Sample: "+newS.sampleSynchTime);
+	   						for (int k=0;k<s.instructions.length;k++)
+	   							newS.instructions[k] = s.instructions[k];
+	   						
+	   						this.printError(traceArray,i,newS);
+	   						
+	   						samples.add(newS);
+	   					}
+	   					i+=8;
+	   				}
+	   				else
+	   				{
+	   					parseNormalSample(magic,repeat,instrPerSample,traceArray,i+8);
+	   					i+=(instrPerSample+3)*4;
+	   				}
+	   			}
+	   			else
+	   			{
+	   				parseNormalSample(magic,repeat,instrPerSample,traceArray,i+8);
+	   				i+=(instrPerSample+3)*4;
+	   			}
+	   		}
+		}
+	   	catch (Exception e)
+		{
+	   		// end of trace
+	   	}
+    }
+    else if (traceVersion.indexOf("ITT_V1.22") != -1 || traceVersion.indexOf("ITT_V2.01") != -1) //$NON-NLS-1$ //$NON-NLS-2$
+    {
+    	boolean isVersion201 = traceVersion.indexOf("ITT_V2.01") != -1; //$NON-NLS-1$
+    	this.trace122 = parse122IttTrace(traceArray, isVersion201);
+    }
+    else
+    {
+        GeneralMessages.showErrorMessage(Messages.getString("IttTraceParser.unsupportedTrace")+traceVersion); //$NON-NLS-1$
+    }
+  }
+   
+  private IttTrace122 parse122IttTrace(byte[] traceArray, boolean isVersion201)
+  {
+	  IttTrace122 trace = new IttTrace122();
+	  
+	  int ptr = 0;
+
+	  // read the first header
+	  byte length = traceArray[ptr++];
+	  String txt = new String(traceArray,ptr,length);ptr+=length;
+	  
+	  Vector sortables = new Vector();
+	  
+	  class SortableString implements Sortable
+	  {
+		  String string;
+		  long value;
+		  long startAddress;
+		  long endAddress;
+		  double samplingTime;
+		  
+		  public long valueOf()
+		  {
+			  return this.value;
+		  }
+	  }
+	  
+	  int adjust = isVersion201 ? 12 : 8;
+	  
+	  while(ptr < traceArray.length)
+	  {
+		  IttEvent122 event = new IttEvent122();
+		  try
+		  {
+		  length = traceArray[ptr++];
+		  txt = new String(traceArray,ptr,(length-adjust));
+		  ptr+=(length-adjust);
+		  event.binaryName = txt;
+		  }
+		  catch(Exception e)
+		  {
+			  e.printStackTrace();
+			  break;
+		  }
+		  
+		  long adr = getUnsignedByte(traceArray[ptr++]);
+		  adr |= (getUnsignedByte(traceArray[ptr++])<<8);
+		  adr |= (getUnsignedByte(traceArray[ptr++])<<16);
+		  adr |= (getUnsignedByte(traceArray[ptr++])<<24);
+		  adr = (adr<<32)>>>32;
+		  event.binaryLocation = adr;
+		  
+		  long len = getUnsignedByte(traceArray[ptr++]);
+		  len |= (getUnsignedByte(traceArray[ptr++])<<8);
+		  len |= (getUnsignedByte(traceArray[ptr++])<<16);
+		  len |= (getUnsignedByte(traceArray[ptr++])<<24);
+		  len = (len<<32)>>>32;
+		  event.binaryLength = len;
+		  
+		  if (isVersion201) {
+			  long time = getUnsignedByte(traceArray[ptr++]);
+			  time |= (getUnsignedByte(traceArray[ptr++])<<8);
+			  time |= (getUnsignedByte(traceArray[ptr++])<<16);
+			  time |= (getUnsignedByte(traceArray[ptr++])<<24);
+			  time = (time<<32)>>>32;
+			  event.eventTime = time / 1000.0;
+		  } else {
+			  event.eventTime = 0.0;
+		  }
+
+		  event.createBinary();
+		  
+		  trace.addEvent(event);
+		  if (debug)
+		  {
+			  SortableString s = new SortableString();
+			  s.string = Long.toHexString(adr)+" - "+Long.toHexString(adr+len)+" \t "+event.binary.binaryName+" length:"+len; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			  s.value = adr;
+			  s.startAddress = adr;
+			  s.endAddress = adr+len;
+			  s.samplingTime = event.eventTime;
+			  sortables.add(s);
+		  }
+	  }
+	  
+	  if (debug)
+	  {
+		  QuickSortImpl.sort(sortables);
+		  Enumeration e = sortables.elements();
+		  SortableString prev = null;
+		  while (e.hasMoreElements())
+		  {
+			  SortableString s = (SortableString)e.nextElement();
+			  if (prev != null)
+			  {
+				 // System.out.println("Empty:"+(s.startAddress - prev.endAddress)+" bytes");
+				  if (s.startAddress < prev.endAddress) {
+					  System.out.println(Messages.getString("IttTraceParser.debugOverlapping")); //$NON-NLS-1$
+					  System.out.println(Messages.getString("IttTraceParser.previous") + prev.string); //$NON-NLS-1$
+					  System.out.println(Messages.getString("IttTraceParser.this") + s.string); //$NON-NLS-1$
+				  }
+			  }
+			  System.out.println(s.string);
+			  prev = s;
+		  }
+	  }
+	  
+	  return trace;
+  }
+  
+  private int getUnsignedByte(byte b)
+  {
+	  return ((b<<24)>>>24);
+  }
+  
+  private long getInt32From(byte[] traceArray,int i)
+  {
+  	long value = (traceArray[i]& 0xff) | ((traceArray[i+1] & 0xff) << 8) |
+			((traceArray[i+2]& 0xff) << 16) | ((traceArray[i+3]&0xff) << 24);
+  	return value;
+  }
+  
+  private long getReversedInt32From(byte[] traceArray,int i)
+  {
+  	long value = ((traceArray[i]& 0xff) << 24) | ((traceArray[i+1] & 0xff) << 16) |
+					((traceArray[i+2]& 0xff) << 8) | (traceArray[i+3]&0xff);
+  	return value;
+  }
+  
+  private void parseNormalSample(	long first,long second,
+  										int instrPerSample,
+										byte[] traceArray,int i) throws Exception
+  {
+    IttSample sample = new IttSample(instrPerSample);
+    // change the byte order of the instructions
+    sample.instructions[0] = ((first & 0xff) << 24) | 
+							 ((first >> 8) & 0xff) << 16 |
+							 ((first >> 16) & 0xff) << 8 |
+							 ((first >> 24) & 0xff);
+
+    sample.instructions[1]  = ((second & 0xff) << 24) | 
+							  ((second >> 8) & 0xff) << 16 |
+							  ((second >> 16) & 0xff) << 8 |
+							  ((second >> 24) & 0xff);
+    
+    for (int k=2;k<instrPerSample;k++)
+    {
+    	// read in reverse byte order
+    	sample.instructions[k] = this.getReversedInt32From(traceArray,i);
+    	i+=4;
+    }
+
+    sample.sampleSynchTime = this.getInt32From(traceArray,i);
+    i+=4;
+
+    
+    sample.checksum = this.getInt32From(traceArray,i);
+    i+=4;
+
+
+    sample.programCounter = (((this.getInt32From(traceArray,i)) << 32) >>> 32);
+    i+= 4;
+
+    this.printError(traceArray,i,sample);
+    
+    this.samples.add(sample);
+  }
+
+  private void printError(byte[] traceArray,int i,IttSample newSample)
+  {
+    if (this.samples.size() > 0)
+    {
+    	IttSample sample = (IttSample)this.samples.lastElement();
+        if ( sample.sampleSynchTime != newSample.sampleSynchTime-1)
+        {
+        	System.out.println(Messages.getString("IttTraceParser.missingSample1")); //$NON-NLS-1$
+            
+            System.out.println(Messages.getString("IttTraceParser.missingSample2")+sample.sampleSynchTime); //$NON-NLS-1$
+            System.out.println(Messages.getString("IttTraceParser.missingSample3")+Integer.toHexString((int)sample.programCounter)); //$NON-NLS-1$
+            System.out.println(Messages.getString("IttTraceParser.missingSample4")+Integer.toHexString((int)sample.checksum)+Messages.getString("IttTraceParser.missingSample5")); //$NON-NLS-1$ //$NON-NLS-2$
+            
+            System.out.println(Messages.getString("IttTraceParser.missingSample6")+newSample.sampleSynchTime); //$NON-NLS-1$
+            System.out.println(Messages.getString("IttTraceParser.missingSample7")+Integer.toHexString((int)newSample.programCounter)); //$NON-NLS-1$
+            System.out.println(Messages.getString("IttTraceParser.missingSample8")+Integer.toHexString((int)newSample.checksum)+Messages.getString("IttTraceParser.missingSample9")); //$NON-NLS-1$ //$NON-NLS-2$
+
+            int v = 0;
+        	for (int k=i-48;k<i+48;k+=4)
+        	{
+        		v++;
+        		String s = Long.toHexString(this.getInt32From(traceArray,k));
+        		if (s.length() > 8) s = s.substring(s.length()-8,s.length());
+        		else if (s.length()<8) {for (int g=0;g<8-s.length();g++){s="0"+s;}} //$NON-NLS-1$
+        		
+        		System.out.print("0x"+s+" "); //$NON-NLS-1$ //$NON-NLS-2$
+        		if (v%4 == 0) System.out.print("\n"); //$NON-NLS-1$
+        	}
+        	
+        }
+    }
+  }
+
+  public Enumeration getSamples()
+  {
+    return this.samples.elements();
+  }
+
+  private GenericTrace getTrace()
+  {
+	  if (this.trace122 == null)
+	  {
+		  IttTrace trace = new IttTrace();
+		  Enumeration sEnum = this.samples.elements();
+		  while(sEnum.hasMoreElements())
+		  {
+			  IttSample s = (IttSample)sEnum.nextElement();
+			  trace.addSample(s);
+		  }	
+		  return trace;
+	  }
+	  else
+	  {
+		  return this.trace122;
+	  }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/MapFile.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,521 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+public class MapFile 
+{
+	private boolean parsedMapFile = false;
+	
+	private String name;
+	private File mapFile;
+	private String referencePath;
+	private long referenceLineNumber;
+	private LinkedList<Function> functionData;
+	private ArrayList<Function> sortedFunctionData;
+	private Long currentGccLibEndingOffset = new Long(0);
+	private Function lastGccFunction = null;
+	
+	// RVCT/RVDS map file line
+	private static final Pattern rvctLinePattern = Pattern.compile("\\p{Blank}*((?!\\d)\\S.+)\\p{Blank}+(0[x|X]\\p{XDigit}+|\\d+)\\p{Blank}+(?:ARM Code|Thumb Code)\\p{Blank}+(0x\\p{XDigit}+|\\d+)\\p{Blank}*.*");	//$NON-NLS-1$
+
+	// a GCC map file line looks like this:
+	// <%x|%d> <symbol name> for function symbols
+	// symbol name cannot be number (e.g. first non space is not a digit)
+	private static final Pattern gccFuncLinePattern  = Pattern.compile("\\p{Blank}*(0[x|X]\\p{XDigit}+|\\d+)\\p{Blank}+((?!\\d)\\S.+)");	//$NON-NLS-1$
+
+	// <section> <%x|%d> <%x|%d> <symbol name>	for whole library
+	// *fill* <%x|%d> <%x|%d> 00000000 for filler
+	private static final Pattern gccLibOrFillerLinePattern = Pattern.compile("\\p{Blank}*(?:\\S*)\\p{Blank}*(0[x|X]\\p{XDigit}+|\\d+)\\p{Blank}+(0[x|X]\\p{XDigit}+|\\d+)\\p{Blank}+(\\S.+)"); //$NON-NLS-1$
+
+
+	public MapFile(File file, String referencePath, long referenceLineNumber)
+	{
+		if (!file.exists())
+		{
+			  // .map not found
+			  if(file.getName().endsWith(".exe.map") || //$NON-NLS-1$
+					  file.getName().endsWith(".dll.map") || //$NON-NLS-1$
+					  file.getName().endsWith(".ldd.map") || //$NON-NLS-1$
+					  file.getName().endsWith(".pdd.map") || //$NON-NLS-1$
+					  file.getName().endsWith(".app.map"))  //$NON-NLS-1$
+			  {
+				  flagFileNotFound(file, referencePath, referenceLineNumber);
+			  }
+		}
+		//System.out.println("Creating MAP file "+file.getAbsolutePath());
+		
+		this.name = file.getName();
+		this.functionData = new LinkedList<Function>();
+		this.sortedFunctionData = new ArrayList<Function>();
+		
+		this.mapFile = file;
+		this.referencePath = referencePath;
+		this.referenceLineNumber = referenceLineNumber;
+		
+		/*
+		if (file.getName().indexOf("wserv.exe") != -1)
+		{
+			this.printSortedFunctions();
+			System.out.println("Map file "+file.getName()+" processed");
+		}*/
+	}
+	
+	public String getName()
+	{
+		return this.name;
+	}
+	
+	public String getFunctionNameForOffset(long offset)
+	{
+		if (!this.parsedMapFile) {
+			this.parseMapFile();
+			this.copyToSortedFunctionData();
+		}
+		
+		for (Function f : sortedFunctionData)
+		{
+			// is the asked offset within the area of this function
+			// test first is the offset equal or past the first
+			// instruction of the function
+			if (offset >= f.offsetFromBinaryStart)
+			{
+				// if so, make sure that the offset is less
+				// or equal to the last instruction within 
+				// this function
+				if (offset < (f.offsetFromBinaryStart+f.length))
+				{
+					return f.functionName;
+				}
+			}
+		}
+		
+		return Messages.getString("MapFile.functionWithOffsetNotFound1")+offset+Messages.getString("MapFile.functionWithOffsetNotFound2")+this.name+ //$NON-NLS-1$ //$NON-NLS-2$
+				Messages.getString("MapFile.functionWithOffsetNotFound3")+ //$NON-NLS-1$
+				(this.sortedFunctionData.get(this.sortedFunctionData.size() - 1)).offsetFromBinaryStart; 		 //$NON-NLS-1$
+	}
+	
+	public Function getFunctionForOffset(long offset)
+	{
+		if (!this.parsedMapFile) {
+			this.parseMapFile();
+			this.copyToSortedFunctionData();
+		}
+
+		for (Function f : sortedFunctionData)
+		{
+			// is the asked offset within the area of this function
+			// test first is the offset equal or past the first
+			// instruction of the function
+			if (offset >= f.offsetFromBinaryStart)
+			{
+				// if so, make sure that the offset is less
+				// or equal to the last instruction within 
+				// this function
+				if (offset < (f.offsetFromBinaryStart+f.length))
+				{
+					return f;
+				}
+			}
+		}
+		
+		return null; 		
+	}
+	
+	public long getFunctionLengthForOffset(long offset)
+	{
+		if (!this.parsedMapFile) {
+			this.parseMapFile();
+			this.copyToSortedFunctionData();
+		}
+
+		for (Function f : sortedFunctionData)
+		{
+			// is the asked offset within the area of this function
+			// test first is the offset equal or past the first
+			// instruction of the function
+			if (offset >= f.offsetFromBinaryStart)
+			{
+				// if so, make sure that the offset is less
+				// or equal to the last instruction within 
+				// this function
+				if (offset < (f.offsetFromBinaryStart+f.length))
+				{
+					return f.length;
+				}
+			}
+		}
+		return 0; 		
+	}
+	
+	public long getOffsetFromBinaryStartForFunction(String functionName)
+	{
+		if (!this.parsedMapFile) {
+			this.parseMapFile();
+			this.copyToSortedFunctionData();
+		}
+
+		for (Function f : sortedFunctionData)
+		{
+			if (f.functionName.equals(functionName))
+			{
+				return f.offsetFromBinaryStart;
+			}
+		}
+		return -1;
+	}
+	
+	private Function FunctionFromTokens(String funcNameToken, String funcOffsetToken, String funcLengthToken)
+	{	
+		Function f = new Function(funcNameToken,new Long(0),null);
+		// look for length, set it tentatively
+		// we may adjust it later
+		f.length = Long.decode(funcLengthToken);
+		f.offsetFromBinaryStart = Long.decode(funcOffsetToken);
+
+		return f;
+	}
+	
+	private void parseMapFile()
+	{
+		boolean isRVCT = false;
+		
+		System.out.println(Messages.getString("MapFile.parsingMapFile") + this.name); //$NON-NLS-1$
+		this.parsedMapFile = true;
+		
+		// read into the map and see if it's RVCT built
+		FileInputStream fis;
+		try {
+			fis = new FileInputStream(mapFile);
+			BufferedReader bufReader = new BufferedReader(new InputStreamReader(fis));
+			
+			String line = bufReader.readLine();
+			
+			if (line != null && line.length() > 0) {
+				if (line.toLowerCase().indexOf("arm linker,") != -1) //$NON-NLS-1$
+					isRVCT = true;
+				else
+					isRVCT = false;
+			} else {
+				// empty file, do nothing
+				return;
+			}
+			
+			bufReader.close();
+			fis.close();	
+			
+			fis = new FileInputStream(mapFile);		
+			bufReader = new BufferedReader(new InputStreamReader(fis));
+
+			if (isRVCT || mapFile.getAbsolutePath().toLowerCase().indexOf("armv5") != -1) //$NON-NLS-1$
+			{
+				parseRVCT(bufReader);
+			}
+			else
+			{
+				parseGCC(bufReader);
+			}
+
+			bufReader.close();
+			fis.close();	
+		} catch (FileNotFoundException e) {
+			flagFileNotFound(mapFile, referencePath, referenceLineNumber);
+		} catch (IOException e) {
+			flagIOException(mapFile, referencePath, referenceLineNumber);
+		}		
+	}
+	
+	private void parseGCC(BufferedReader bufReader) throws IOException
+	{
+		String line = bufReader.readLine();
+
+		while(line != null)
+		{
+			this.processLineGCC(line);
+			line = bufReader.readLine();
+		}
+	}
+	
+	private void parseRVCT(BufferedReader bufReader) throws IOException
+	{
+		String line = bufReader.readLine();
+
+		// find the global symbols section
+		//while(line.indexOf("Global Symbols") == -1)
+		// line = bufReader.readLine();		
+		
+		line = bufReader.readLine();
+		
+		while(line != null)
+		{
+			this.processLineRVCT(line);
+			line = bufReader.readLine();
+		}
+		bufReader.close();
+	}
+	
+	private void processLineRVCT(String line)
+	{
+		// a RVCT symbol line looks like this:
+		// <symbol name> <%x|%d> <ARM Code|Thumb Code> <%x|%d> <object>
+		// symbol name cannot be number (e.g. first non space is not a digit)
+		Matcher rvctLineMatcher = rvctLinePattern.matcher(line);
+		
+		if (rvctLineMatcher.matches())
+		{
+			String funcNameToken = rvctLineMatcher.group(1).trim();
+			// internal symbol, not a function
+			if (funcNameToken.indexOf(Messages.getString("MapFile.dollarSign")) != -1) //$NON-NLS-1$
+				return;
+			
+			String funcOffsetToken = rvctLineMatcher.group(2).trim();
+			
+			if (funcOffsetToken.equalsIgnoreCase("0x00000001") && line.contains("Thumb Code"))
+				return;
+			
+			String funcLengthToken = rvctLineMatcher.group(3).trim();
+			
+			Function f = FunctionFromTokens(funcNameToken, funcOffsetToken, funcLengthToken);
+			
+			this.insertToFunctionData(f);
+		}
+	}
+		
+	// our current parser picked up too many trash, let's try our best here
+	private boolean qualifyGCCSymbol(long address, String symbol) {
+		if (symbol == null || symbol.length() <= 0)
+			return false;
+		
+		// zero address on ARM, you must be kidding. This isn't a real program address
+		if (address <= 0) {
+			return false;
+		}
+		if (symbol.contains("(size before relaxing")) { //$NON-NLS-1$
+			return false;
+		}
+		if (symbol.contains("PROVIDE (")) { //$NON-NLS-1$
+			return false;
+		}
+		// you better be kidding if this is a C symbol, it's linker symbol
+		if (symbol.charAt(0) == '.') {
+			return false;
+		}
+		if (symbol.equals("_DYNAMIC")) { //$NON-NLS-1$
+			return false;
+		}
+		if (symbol.contains("vtable ") || symbol.contains("typeinfo ")) { //$NON-NLS-1$ //$NON-NLS-2$
+			return false;
+		}
+		if (symbol.contains("= .")) { //$NON-NLS-1$
+			return false;
+		}
+		return true;
+	}
+	
+	private void processLineGCC(String line)
+	{	
+		// a GCC symbol line looks like this:
+		// <%x|%d> <symbol name> for function symbols
+		// symbol name cannot be number (e.g. first non space is not a digit)
+		Matcher gccFuncLineMatcher  = gccFuncLinePattern.matcher(line);	//$NON-NLS-1$
+		// <section> <%x|%d> <%x|%d> <symbol name>	for whole library
+		// *fill* <%x|%d> <%x|%d> 00000000 for filler
+		Matcher gccLibOrFillerLineMatcher = gccLibOrFillerLinePattern.matcher(line); //$NON-NLS-1$
+		
+		Function f = null;
+		Long currentLineOffset = currentGccLibEndingOffset;
+		
+
+		if (gccFuncLineMatcher.matches())
+		{
+			String funcNameToken = gccFuncLineMatcher.group(2).trim();
+			String funcOffsetToken = gccFuncLineMatcher.group(1).trim();
+			String funcLengthToken = Messages.getString("MapFile.zero"); //$NON-NLS-1$
+			
+			f = FunctionFromTokens(funcNameToken, funcOffsetToken, funcLengthToken);
+			
+			// Some GCC symbol may be bogus
+			if (qualifyGCCSymbol(f.offsetFromBinaryStart, funcNameToken)) {
+				this.insertToFunctionData(f);
+			} 
+			
+			if (lastGccFunction != null){
+				// calculate size of last function with offset from current line
+				if (f.offsetFromBinaryStart > lastGccFunction.offsetFromBinaryStart &&
+						f.offsetFromBinaryStart < currentGccLibEndingOffset) {
+					currentLineOffset = f.offsetFromBinaryStart;
+				}
+			}
+			
+		} else if (gccLibOrFillerLineMatcher.matches()) {
+			String libOffsetToken = gccLibOrFillerLineMatcher.group(1).trim();
+			String libLengthToken = gccLibOrFillerLineMatcher.group(2).trim();
+			// next time around we will use the new library offset
+			currentGccLibEndingOffset = Long.decode(libLengthToken) + Long.decode(libOffsetToken);				
+		} else {
+			// next time around we will use the new library offset
+			currentGccLibEndingOffset = new Long(0);
+		}
+		
+		// update last function's size if needed
+		if (lastGccFunction != null)
+		{
+			if (currentLineOffset > lastGccFunction.offsetFromBinaryStart) {
+				lastGccFunction.length = currentLineOffset - lastGccFunction.offsetFromBinaryStart;
+			}
+		}
+		
+		// track function on this line as last function, or null if this line is not a function
+		lastGccFunction = f;
+
+	}
+	
+	private void insertToFunctionData(Function function)
+	{
+		if (functionData.size() == 0) 
+		{
+			functionData.addFirst(function);
+		}
+		else if ((functionData.getFirst()).offsetFromBinaryStart 
+					< function.offsetFromBinaryStart)
+		{
+			functionData.addFirst(function);
+		}
+		else if ((functionData.getLast()).offsetFromBinaryStart 
+					> function.offsetFromBinaryStart)
+		{
+			functionData.addLast(function);
+		}
+		else
+		{
+			for (int i=0;i<functionData.size();i++)
+			{
+				if ((functionData.get(i)).offsetFromBinaryStart 
+						< function.offsetFromBinaryStart)
+				{
+					functionData.add(i,function);
+					break;
+				}
+			}
+		}
+	}
+	
+	private void copyToSortedFunctionData()
+	{
+		if (this.functionData.size() <= 0) {
+			return;
+		}
+		this.sortedFunctionData.clear();
+		long start = (this.functionData.getLast()).offsetFromBinaryStart;
+		Function previous = null;
+		boolean reallyAdded = false;
+		
+		for (int i=this.functionData.size()-1;i>=0;i--)
+		{
+			//System.out.println(i);
+			Function f = this.functionData.get(i);
+			f.offsetFromBinaryStart = f.offsetFromBinaryStart - start;
+			
+			if (this.sortedFunctionData.size() == 0)
+			{
+				// add the function if the vector is empty
+				this.sortedFunctionData.add(f);
+				reallyAdded = true;
+			}
+			else if ( (this.sortedFunctionData.get(this.sortedFunctionData.size()-1)).offsetFromBinaryStart != f.offsetFromBinaryStart)
+			{
+				// add the function if the offset is not the same as with the previous line
+				this.sortedFunctionData.add(f);
+				reallyAdded = true;
+			}	
+			else if ( (this.sortedFunctionData.get(this.sortedFunctionData.size()-1)).functionName.startsWith("_")) //$NON-NLS-1$
+			{	
+				// if there is a key with this offset, discard the previous with prefix "_"
+				this.sortedFunctionData.remove(this.sortedFunctionData.get(this.sortedFunctionData.size()-1));
+				// add the new function with the same key
+				this.sortedFunctionData.add(f);
+				reallyAdded = true;
+			}
+			
+			// do this only if we really added the function to the sorted list
+			if (reallyAdded == true)
+			{
+				// store the length of the previous function
+				if (previous != null)
+					previous.length = f.offsetFromBinaryStart - previous.offsetFromBinaryStart;
+				previous = f;	
+				reallyAdded = false;
+			}
+			
+		}
+		this.functionData.clear();
+		this.functionData = null;
+	}
+	
+	/* internal test function: comment out so code coverage looks
+	 * good quantitatively
+	private void printSortedFunctions()
+	{ 
+		long totalLength = 0;
+		for (Function f : sortedFunctionData)
+		{	
+			System.out.println( f.offsetFromBinaryStart+Messages.getString("MapFile.openParenthesis")+totalLength+Messages.getString("MapFile.closeParenthesis")+Long.toHexString(f.length)+Messages.getString("MapFile.dashDash")+f.functionName); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			totalLength += f.length;
+		}
+	}
+	*/
+	
+	private void flagFileNotFound(File file, String referencePath, long referenceLineNumber) {
+		  String myMessage = Messages.getString("MapFile.map.file") +  file.getAbsoluteFile().getName() + Messages.getString("MapFile.not.found"); //$NON-NLS-1$ //$NON-NLS-2$
+		  if (referencePath != null && referencePath.length() > 0) {
+			  myMessage += Messages.getString("MapFile.referenced.by") + referencePath; //$NON-NLS-1$
+		  }
+		  if (referenceLineNumber > 0) {
+			  myMessage += Messages.getString("MapFile.line.number") + referenceLineNumber; //$NON-NLS-1$
+		  }
+
+    	  GeneralMessages.PiLog(myMessage, GeneralMessages.ERROR);
+	}
+
+	private void flagIOException(File file, String referencePath, long referenceLineNumber) {
+		  String myMessage = Messages.getString("MapFile.map.file") + file.getAbsoluteFile().getName() + Messages.getString("MapFile.ioexception"); //$NON-NLS-1$ //$NON-NLS-2$
+		  if (referencePath != null && referencePath.length() > 0) {
+			  myMessage += Messages.getString("MapFile.referenced.by") + referencePath; //$NON-NLS-1$
+		  }
+		  if (referenceLineNumber > 0) {
+			  myMessage += Messages.getString("MapFile.line.number") + referenceLineNumber; //$NON-NLS-1$
+		  }
+
+		  GeneralMessages.showErrorMessage(myMessage);
+		  GeneralMessages.PiLog(myMessage, GeneralMessages.ERROR);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.instr.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/PiInstrFunctionResolver.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.io.File;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+import com.nokia.carbide.cpp.internal.pi.resolvers.RofsSymbolFileFunctionResolver;
+import com.nokia.carbide.cpp.pi.importer.SampleImporter;
+
+
+public class PiInstrFunctionResolver implements FunctionResolver {
+	private IttTrace122 ittTrace122;
+	private BinaryReader122 binaryReader122;
+	private RofsSymbolFileFunctionResolver rofsResolver;
+	
+	boolean ableToResolve = false;
+	
+	String notFound = com.nokia.carbide.cpp.internal.pi.resolvers.Messages.getString("CachedFunctionResolver.notFound"); //$NON-NLS-1$
+	
+	public PiInstrFunctionResolver(BinaryReader122 binaryReader122,IttTrace122 ittTrace122,int parsedMapFileCount)
+	{
+		this.binaryReader122 = binaryReader122;
+		this.ittTrace122 = ittTrace122;
+		this.rofsResolver = new RofsSymbolFileFunctionResolver();
+
+		if (ittTrace122.getEvents().size() > 0 || parsedMapFileCount > 0)
+			this.ableToResolve = true;
+		
+		//reads the symbol name path from configuration data
+		String[] list = SampleImporter.getInstance().getRofsSymbolFileList();
+		for (String filename : list) {
+            File rofsSymbolFile = new File(filename);
+            if (rofsSymbolFile.exists()) {
+            	rofsResolver.parseAndProcessSymbolFile(rofsSymbolFile);
+            	this.ableToResolve = true;
+            }
+		}
+		rofsResolver.adjustRuntimeBinary(binaryReader122.getHostNameToBinary());		
+	}
+	
+	public Binary findBinaryForAddress(long address) {
+		Function f = this.findFunctionForAddress(address);
+		
+		if (f != null)
+			return f.functionBinary;
+		else 
+			return null;
+	}
+
+	public String findBinaryNameForAddress(long address) {
+		Function f = this.findFunctionForAddress(address);
+		if (f != null)
+		{
+			return f.functionBinary.binaryName;
+		}
+		else
+		{
+			return Messages.getString("PiInstrFunctionResolver.binaryNotFound"); //$NON-NLS-1$
+		}
+	}
+
+	public Function findFunctionForAddress(long address) {
+		Function f;
+		f = this.rofsResolver.findFunctionForAddress(address);
+		if (f == null) {	//$NON-NLS-1$
+			f = this.ittTrace122.getFunctionForAddress(address,this.binaryReader122);
+		}
+		return f;
+	}
+
+	public String findFunctionNameForAddress(long address) {
+		Function f = this.findFunctionForAddress(address);
+		if (f != null)
+		{
+			return f.functionName;
+		}
+		else
+		{
+			return Messages.getString("PiInstrFunctionResolver.functionNotFound"); //$NON-NLS-1$
+		}
+	}
+
+	public String getResolverName() {
+		return "ITT"; //$NON-NLS-1$
+	}
+
+	public String getResolverString() {
+		return Messages.getString("PiInstrFunctionResolver.resolverITT"); //$NON-NLS-1$
+	}
+	
+	public boolean canResolve() {
+		return this.ableToResolve;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/ProcessedBinary.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+
+
+public class ProcessedBinary extends Binary
+{
+  private static final long serialVersionUID = 8267855662123433263L;
+  	
+  public File file;
+  public byte[] data;
+  private MapFile mapFile;
+  private int[][] finalLookupTable;
+  private boolean debug;
+  private Hashtable<String,Function> knownFunctions = new Hashtable<String,Function>();
+  
+  public ProcessedBinary(File file) throws Exception
+  {
+  	//super(file.getName());
+  	super(file.getAbsolutePath().substring(
+  			file.getAbsolutePath().indexOf(File.separator),
+			file.getAbsolutePath().length()));
+  	
+  	//System.out.println("File name: "+file.getAbsolutePath().substring(
+  	//		file.getAbsolutePath().indexOf("\\"),
+	//		file.getAbsolutePath().length()));
+  	
+  	this.file = file;
+    this.length = (int)file.length();
+    this.resolveType(file.getAbsolutePath());
+    
+    FileInputStream fis = new FileInputStream(file);
+    data = new byte[(int)file.length()];
+    fis.read(data,0,(int)file.length());
+    fis.close();
+    //System.out.println("Read "+length+" bytes from "+name);
+    createLookupTable();
+    
+	mapFile = new MapFile(new File(file.getAbsolutePath()+".map"), "", 0); //$NON-NLS-1$ //$NON-NLS-2$
+    
+    if (this.data.length > 0x7C)
+    {
+    	this.offsetToCodeStart = 	( (long)this.data[0x67] << 24)+
+									( (long)this.data[0x66] << 16)+
+									( (long)this.data[0x65] << 8)+
+									( (long)this.data[0x64] );
+	
+    	this.offsetToCodeStart += 	( (long)this.data[0x4B] << 24)+
+									( (long)this.data[0x4A] << 16)+
+									( (long)this.data[0x49] << 8)+
+									( (long)this.data[0x48] );
+    	
+    	if (this.type == "thumb") this.offsetToCodeStart -=1; //$NON-NLS-1$
+    	
+    	if (this.offsetToCodeStart >= 4) this.offsetToCodeStart -=4;
+    }
+    
+    //System.out.println("Bin "+this.binaryName+" offset "+this.offsetToCodeStart);
+  }
+  
+  public long getOffsetFromBinaryStartForFunction(String functionName)
+  {
+  	if (this.mapFile != null)
+  		return this.mapFile.getOffsetFromBinaryStartForFunction(functionName);
+  	else 
+  		return -1;
+  }
+  
+  private void resolveType(String filePath)
+  {
+  	filePath = filePath.toLowerCase();
+  	filePath = filePath.replace('\\','/');
+  	
+    if ( filePath.indexOf("/thumb/") != -1 ) //$NON-NLS-1$
+    {
+    	this.type = "thumb"; //$NON-NLS-1$
+    }
+    else if ( filePath.indexOf("/armi/") != -1 ) //$NON-NLS-1$
+			  
+    {
+    	this.type = "armi"; //$NON-NLS-1$
+    }
+    
+    else if ( filePath.indexOf("/momap15xx/") != -1 ) //$NON-NLS-1$
+    {
+    	this.type = "momap15xx"; //$NON-NLS-1$
+    }
+
+    else if ( filePath.indexOf("/momap16xx/") != -1 ) //$NON-NLS-1$
+    {
+    	this.type = "momap16xx"; //$NON-NLS-1$
+    }
+
+    else if ( filePath.indexOf("/arm4/") != -1 ) //$NON-NLS-1$
+    {
+    	this.type = "arm4"; //$NON-NLS-1$
+    }
+    else this.type = Messages.getString("ProcessedBinary.unknownType"); //$NON-NLS-1$
+
+  }
+  
+  public String getFunctionNameForOffset(long offset)
+  {
+  	if (this.mapFile == null) return Messages.getString("ProcessedBinary.mapFileForBinaryNotFound1")+this.binaryName+Messages.getString("ProcessedBinary.mapFileForBinaryNotFound2"); //$NON-NLS-1$ //$NON-NLS-2$
+  	return this.mapFile.getFunctionNameForOffset(offset);
+  }
+  
+  public Function getFunctionForOffset(long offset)
+  {
+  	if (this.mapFile == null) 
+  	{
+  		return null;
+  	}
+  	else
+  	{
+  		String name = this.mapFile.getFunctionNameForOffset(offset);
+  		String dllName = this.binaryName;
+  		
+  		long offsetFromBinaryStart = this.mapFile.getOffsetFromBinaryStartForFunction(name); 
+  		// this cannot be resolved here, since the address is not known
+  		Long addr = new Long(0);
+  		
+  		String search = name + dllName;
+  		Function f = this.knownFunctions.get(search);
+  		
+  		if (f == null) {
+	  		f = new Function(name,addr,dllName);
+	  		f.offsetFromBinaryStart = offsetFromBinaryStart;
+	  		f.length = this.mapFile.getFunctionLengthForOffset(offset);
+	  		this.knownFunctions.put(search, f);
+  		}
+  		
+  		return f;
+  	}
+  	
+  }
+  
+  public long getFunctionLengthForOffset(long offset)
+  {
+  	if (this.mapFile != null)
+  		return this.mapFile.getFunctionLengthForOffset(offset);
+  	else return 0;
+  }
+
+  private static class Value
+  {
+    int value;
+
+    public Value(int value)
+    {this.value = value;}
+  }
+
+  private void createLookupTable()
+  {
+    Vector[] lookupTable = new Vector[256];
+
+    //System.out.println("Creating Lookup Table for "+this.name);
+    for (int i=0;i<data.length-1;i++)
+    {
+      //System.out.println("Processing sequence "+Integer.toHexString(value.intValue())+"\n");
+      int unsigned = ((int)data[i] & 0xff);
+
+      if (lookupTable[unsigned] == null)
+      {
+        Vector v = new Vector();
+        v.add(new Value(i));
+        lookupTable[unsigned] = v;
+        //System.out.println("New Value "+Integer.toHexString(unsigned));
+      }
+      else
+      {
+        Vector v = lookupTable[unsigned];
+        v.add(new Value(i));
+        //System.out.println("Old Value "+Integer.toHexString(unsigned));
+        //System.out.print("e");
+      }
+      //if (i%40 == 0) System.out.print("\n");
+    }
+
+    this.finalLookupTable = new int[256][];
+    for (int i=0;i<256;i++)
+    {
+      if (lookupTable[i] != null)
+      {
+        this.finalLookupTable[i] = new int[lookupTable[i].size()];
+
+        Enumeration enumer = lookupTable[i].elements();
+
+        int element = 0;
+
+        while (enumer.hasMoreElements())
+        {
+          Value v = (Value) enumer.nextElement();
+          this.finalLookupTable[i][element] = v.value;
+          element++;
+        }
+      }
+    }
+  }
+
+  public long getInstructionFromOffset(int offset)
+  {
+    long instruction = 0;
+
+    instruction = ((long)(( (long)this.data[offset+3])   & 0xff));
+    instruction += ((long)((((long)(this.data[offset+2])) & 0xff) << 8));
+    instruction += ((long)((((long)(this.data[offset+1])) & 0xff) << 16));
+    instruction += ((long)((((long)(this.data[offset])) & 0xff) << 24));
+
+    //System.out.println("INSTRUCTION: "+Integer.toHexString((int)instruction));
+
+    return instruction;
+  }
+
+  public long calculateXorChecksum(int startIndex, int lengthInInstructions)
+  {
+    long value = 0;
+    for (int i=0;i<lengthInInstructions;i++)
+    {
+      long instruction = this.getInstructionFromOffset(startIndex+(i*4));
+
+      // xor the value with the provious value
+      value ^= instruction;
+    }
+    return value;
+  }
+
+  public int[] getIndicesForSequence(int sequence)
+  {
+    if (sequence < this.finalLookupTable.length)
+    {
+      return this.finalLookupTable[sequence];
+    }
+    else return null;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/UndecidedPool.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.instr;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+
+
+public class UndecidedPool 
+{	
+	private Hashtable undecidedLocations;
+	private Vector unprocessed;
+	private AdvancedMemoryMap amm;
+	private Vector unDecided;
+	
+	public UndecidedPool(AdvancedMemoryMap amm)
+	{
+		this.amm = amm;
+		// keys will be the binary names, and values wile be
+		// their corresponding UndecidedLocation objects
+		this.undecidedLocations = new Hashtable();
+		
+		this.unprocessed = new Vector();
+		this.unDecided = new Vector();
+	}
+	
+	public Vector getUnprocessed()
+	{
+		return this.unprocessed;
+	}
+	
+	public void clearUnprocessed()
+	{
+		this.unprocessed = new Vector();
+	}
+	
+	public Vector getUndecided()
+	{
+		return this.unDecided;
+	}
+
+	public void insertSample(IttSample sample,int decisionBoundary)
+	{
+		if (!this.unDecided.contains(sample))
+			this.unDecided.add(sample);
+		
+		BinaryReaderResult brr = this.amm.getBinaryReader().findSequence(sample);
+		for (int i=0;i<brr.possibleBinaries.length;i++)
+		{
+			Binary possibleBinary = brr.possibleBinaries[i];
+			UndecidedLocation ul = 
+				(UndecidedLocation)undecidedLocations.get(possibleBinary.binaryName);
+			
+			if (ul != null)
+			{
+				ul.addSample(sample,possibleBinary.startAddress);
+			}
+			else
+			{
+				ul = new UndecidedLocation(possibleBinary); 
+				ul.addSample(sample,possibleBinary.startAddress);
+				this.undecidedLocations.put(possibleBinary.binaryName,ul);
+			}
+			
+			// the value of decisionBoundary has to be reduced in the future
+			// when no binaries can be resolved with the current value
+			if (ul.getDecidedAddress(decisionBoundary) != -1)
+			{
+			 	// location of the binary has been resolved
+				
+				// refresh the samples that belong to the decision
+				ul.refreshDecidedAndUndecidedSamples();
+				
+				// add all the samples that didn't fit to this binary, to
+				// the pool of unprocessed samples				
+				Vector undecided = ul.getUndecidedSamples();
+				// add only those samples that are not present in the undecided
+				// vector already
+				Enumeration unEnum = undecided.elements();
+				while(unEnum.hasMoreElements())
+				{
+					IttSample us = (IttSample)unEnum.nextElement();
+					if (!this.unprocessed.contains(us)) this.unprocessed.add(us);
+				}
+				
+				// then, pass the decision to the decidedPool
+				Vector decided = ul.getDecidedSamples();
+				this.amm.getDecidedPool().insertDecidedBinary(possibleBinary,decided);
+				
+				// then, remove the decided samples from all other possible binaries
+				Enumeration renum = decided.elements();
+				while(renum.hasMoreElements())
+				{
+					IttSample sampleToRemove = (IttSample)renum.nextElement();
+					this.removeSampleFromAllPossibleLocations(sampleToRemove);
+				}
+			}
+		}
+	}
+	
+	private void removeSampleFromAllPossibleLocations(IttSample sample)
+	{	
+		Enumeration renum = this.undecidedLocations.keys();
+		Vector removeList = new Vector();
+		
+		this.unDecided.remove(sample);
+		
+		while(renum.hasMoreElements())
+		{
+			String name = (String)renum.nextElement();
+			
+			UndecidedLocation ul = (UndecidedLocation)this.undecidedLocations.get(name);
+			ul.removeSample(sample);
+			
+			if (ul.samplesForLocations.size() == 0) removeList.add(name);
+		}
+		
+		if (removeList.size() > 0)
+		{
+			Enumeration enumer = removeList.elements();
+			while(enumer.hasMoreElements())
+			{
+				this.undecidedLocations.remove(enumer.nextElement());
+			}
+		}
+		
+		if (this.unprocessed.contains(sample))
+		{
+			this.unprocessed.remove(sample);
+		}
+	} 
+	
+	private static class UndecidedLocation
+	{
+		private Hashtable samplesForLocations;
+
+		private Binary binary;
+		
+		private int processedMostHits = 0;
+		private Long addressWithMostHits = null;
+		private Vector samplesWithMostHits = null;
+		
+		private boolean processedUndecided = false;
+		private Vector undecidedSamples = null;
+		private Vector decidedSamples = null; 
+		
+		public UndecidedLocation(Binary binary)
+		{
+			// key will be the address, and the value will be a
+			// vector with all samples that support that location 
+			this.samplesForLocations = new Hashtable();
+			this.binary = binary;
+		}
+		
+		public Binary getBinary()
+		{
+			return this.binary;
+		}
+		
+		public void addSample(IttSample sample,long startAddress)
+		{
+			// clear the flags so that the values will be recalculated if needed
+			this.processedMostHits = 0;
+			this.processedUndecided = false;
+			
+			Object o = this.samplesForLocations.get(new Long(startAddress));
+			
+			if (o != null)
+			{
+				// this location has already a vector associated with it
+				Vector sampleVec = (Vector)o;
+				
+				Enumeration sampleEnum = sampleVec.elements();
+				boolean isAlready = false;
+				
+				while(sampleEnum.hasMoreElements())
+				{
+					IttSample testSample = (IttSample)sampleEnum.nextElement();
+					if (testSample.programCounter == sample.programCounter && 
+							testSample.checksum == sample.checksum)
+						{
+							isAlready = true;
+							break;
+						}
+				}
+				// add the sample only if it is 
+				// different from the other samples
+				if (isAlready == false) 
+				{
+					//System.out.println("Added unique sample "+sample.programCounter+" to "+this.binary.binaryName);
+					sampleVec.add(sample);
+				}
+				else
+				{
+					//System.out.println("Discarded "+sample.programCounter+" to "+this.binary.binaryName);
+				}
+				
+			}
+			else
+			{
+				//System.out.println("Added unique sample "+sample.programCounter+" to "+this.binary.binaryName);
+				Vector sampleVec = new Vector();
+				sampleVec.add(sample);
+				samplesForLocations.put(new Long(startAddress),sampleVec);
+			}
+		}
+		
+		public void removeSample(IttSample sample)
+		{
+			// clear the flags so that the values will be recalculated if needed
+			this.processedMostHits = 0;
+			this.processedUndecided = false;
+
+			// remove this sample from all vectors, remove the vectors if they
+			// become empty
+			Enumeration enumer = this.samplesForLocations.keys();
+			Vector removeList = new Vector();
+			
+			while(enumer.hasMoreElements())
+			{
+				Long address = (Long)enumer.nextElement();
+				Vector v = (Vector)this.samplesForLocations.get(address);
+				
+				if (v.contains(sample)) 
+				{
+					v.remove(sample);
+					// do not remove the vector yet because
+					// it would mess the hashtable iteration
+					if (v.size() == 0) removeList.add(address);
+				}
+			}
+			
+			// finally, remove the vectors that 
+			// were emptied after removing the last sample
+			if (removeList.size() > 0) 
+			{
+				Enumeration renum = removeList.elements();
+				while(renum.hasMoreElements())
+				{
+					this.samplesForLocations.remove(renum.nextElement());
+				}
+			}
+		
+		}
+		
+		public long getDecidedAddress(int minSampleAmount)
+		{
+			if (minSampleAmount <= 0) return -1;
+			
+			if (this.processedMostHits == minSampleAmount)
+			{
+				// the function has been run with this value
+				return this.addressWithMostHits.longValue();
+			}
+			
+			Enumeration addresses = samplesForLocations.keys();
+			
+			int amountOfMaxValues = 0;
+			
+			while(addresses.hasMoreElements())
+			{
+				Long address = (Long)addresses.nextElement();
+				Vector samples = (Vector)samplesForLocations.get(address);
+				if (samples.size() >= minSampleAmount)
+				{
+					// there are at least minSampleAmount different samples
+					// that support this binary being in this place
+					if (samplesWithMostHits != null)
+					{
+						// there is already a value, check do we exceed it
+						if (samples.size() > samplesWithMostHits.size())
+						{
+							samplesWithMostHits = samples;
+							addressWithMostHits = address;
+							amountOfMaxValues = 1;
+						}
+						else if (samples.size() == samplesWithMostHits.size())
+						{
+							amountOfMaxValues++;
+						}
+					}
+					else
+					{
+						// there is no max value yet
+						samplesWithMostHits = samples;
+						addressWithMostHits = address;
+						amountOfMaxValues = 1;
+					}
+				}
+			}
+			
+			// this function does not need to be run again
+			// if the values do not change
+			this.processedMostHits = minSampleAmount;
+
+			// there are two or more max values
+			// or no max values at all
+			if (amountOfMaxValues != 1) return -1;
+				else return addressWithMostHits.longValue();
+		}
+		
+		public void refreshDecidedAndUndecidedSamples()
+		{
+			if (this.processedUndecided == true) return;
+			
+			this.undecidedSamples = new Vector();
+			this.decidedSamples = new Vector();
+			
+			Enumeration enumer = this.samplesForLocations.elements();
+			while(enumer.hasMoreElements())
+			{
+				Vector v = (Vector)enumer.nextElement();
+				
+				if (!v.equals(this.samplesWithMostHits))
+				{
+					// count all samples but the one with 
+					undecidedSamples.addAll(v);
+				}
+				else
+				{
+					// add the decided samples
+					this.decidedSamples.addAll(v);
+				}
+			}
+	
+			this.processedUndecided = true;
+		}
+		
+		public Vector getDecidedSamples()
+		{
+			// there is no value according to which the decision
+			// could base on
+			if (this.processedMostHits == 0) return new Vector();
+
+			this.refreshDecidedAndUndecidedSamples();
+			
+			return this.decidedSamples;
+		}
+		
+		public Vector getUndecidedSamples()
+		{
+			// there is no value according to which the decision
+			// could base on
+			if (this.processedMostHits == 0) return new Vector();
+
+			this.refreshDecidedAndUndecidedSamples();			
+			
+			return this.undecidedSamples;
+		}
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.instr/src/com/nokia/carbide/cpp/pi/instr/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,92 @@
+AdvancedMemoryMap.notSupportedInV.1.22=Not supported in ITT trace v.1.22
+AdvancedMemoryMap.unmatchedSize=Postprocessing memory map... unmatched size = 
+AdvancedMemoryMap.binaryForAddressNotFound1=Binary at 0x
+AdvancedMemoryMap.binaryForAddressNotFound2=\ not found
+AdvancedMemoryMap.functionForAddressNotFound1=Function at 0x
+AdvancedMemoryMap.functionForAddressNotFound2=\ not found
+AdvancedMemoryMap.functionNotFound=Function not found
+AdvancedMemoryMap.binaryNotFound=Binary not found
+AdvancedMemoryMap.resolverITT=OBY/IBY files
+ProcessedBinary.unknownType=unknown
+ProcessedBinary.mapFileForBinaryNotFound1=Mapfile for 
+ProcessedBinary.mapFileForBinaryNotFound2=\ not found - unable to resolve functions
+IttSample.space=\ 
+DecidedPool.debugDecidedPool=Something wrong in ITT trace / insertSample\!
+DecidedPool.analysisResolved1=Dynamic binary support Analysis - resolved: 
+DecidedPool.analysisResolved2=\ to 0x
+DecidedPool.analysisResolved3=\ - 
+IttTrace122.couldNotResolveFunction=Could not resolve function
+IttTraceParser.cannotOpenTraceFile=Unable to open dynamic binary support trace file
+IttTraceParser.debugTraceVersion1.0=ITT trace version 1.0
+IttTrace122.mapfileNotFound1=Mapfile for 
+IttTrace122.mapfileNotFound2=\ not found
+IttTrace122.functionForAddressNotFound1=Function at 0x
+IttTrace122.functionForAddressNotFound2=\ not found
+IttTraceParser.symbolResolverNotFound=PI Internal Error: function resolver "Symbol" not found
+IttTraceParser.this=this: 
+IttTraceParser.traceProgress0Percent=dynamic binary support progress 0%
+IttTraceParser.binaryNotFound=not found
+IttTraceParser.traceProgress1=dynamic binary support progress 
+IttTraceParser.traceProgress2=%
+IttTraceParser.traceProgress3=\ (slow)
+IttTraceParser.debugTraceVersion=ITT trace version: 
+IttTraceParser.unsupportedTrace=Unsupported ITT trace: 
+IttTraceParser.debugOverlapping=OVERLAPPING\!\!\!
+IttTraceParser.missingSample1=************** Missing Sample ******************
+IttTraceParser.missingSample2=Previous Sample: 
+IttTraceParser.missingSample3=ProgramCounter: 
+IttTraceParser.missingSample4=Checksum: 
+IttTraceParser.missingSample5=\n
+IttTraceParser.missingSample6=Next Sample: 
+IttTraceParser.missingSample7=ProgramCounter: 
+IttTraceParser.missingSample8=Checksum: 
+IttTraceParser.missingSample9=\n
+IttTraceParser.previous=prev: 
+IttEvent122.unknownBinaryType=Not known
+MapFile.functionWithOffsetNotFound1=Function with offset 
+MapFile.functionWithOffsetNotFound2=\ not found according to 
+MapFile.functionWithOffsetNotFound3=\ last function offset is
+BinaryReader122.wrongEKA2FileType1=Problem with item 
+BinaryReader122.wrongEKA2FileType2=\ - In EKA2 dynamic binary support traces, you can add only .pkg, .oby and .iby files to the analysis
+BinaryReader.fileSeparatorProperty=file.separator
+BinaryReader122.addingPkgFile=Adding PKG File 
+BinaryReader122.gotBinaryPkgFile=Got Binary PKG File 
+BinaryReader122.foundPkgBinary1=Found PKG binary for 
+BinaryReader122.foundPkgBinary2=\ from 
+BinaryReader122.IOException.on=IOException on 
+BinaryReader.cannotFindBinary=Could not find the binary\!\! 
+BinaryReader.cannotFindObyFile=Could not find the oby file
+BinaryReader.fileNonexistent1=File 
+BinaryReader.fileNonexistent2=\ does not exist or is a directory
+BinaryReader122.canGetBinaryFrom1=YESSSS\!\! 
+BinaryReader122.canGetBinaryFrom2=\ from 
+BinaryReader122.cannotCreatePkgFileFrom=Problem PKG creating map file from 
+BinaryReader122.pkgNotOK=Not PKG ok 
+BinaryReader122.map.file=Map file 
+BinaryReader122.pkgMalform=PKG file parser internal error
+BinaryReader122.not.found=\ not found.
+BinaryReader122.referenced.by=\ Referenced by 
+BinaryReader122.line.number=\ line 
+BinaryReader.filesFound=\ Files found
+BinaryReader.addedPkgFile=Added PKG File 
+BinaryReader.cannotFindEpoc32FromRoot=Can't find epoc32 directory from 
+BinaryReader.epocRootFileNonexistent1=File 
+BinaryReader.epocRootFileNonexistent2=\ does not exist
+BinaryReader.binaryNotFound1=Binary 
+BinaryReader.binaryNotFound2=\ not found
+BinaryReader.bytesProcessed1=Processed total of 
+BinaryReader.bytesProcessed2=\ bytes in 
+BinaryReader.bytesProcessed3=\ files
+BinaryReader.fileAlreadyPresent1=File 
+BinaryReader.fileAlreadyPresent2=\ is already present
+PiInstrFunctionResolver.binaryNotFound=Binary not found
+PiInstrFunctionResolver.functionNotFound=Function not found
+PiInstrFunctionResolver.resolverITT=OBY/IBY files
+MapFile.dollarSign=$
+MapFile.referenced.by=\ Referenced by 
+MapFile.line.number=\ line 
+MapFile.ioexception=\ encountered IOException upon access.
+MapFile.zero=0
+MapFile.map.file=Map file 
+MapFile.not.found=\ not found.
+MapFile.parsingMapFile=Parsing map file 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,17 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Memory Usage
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.memory;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.memory.MemoryPlugin
+Bundle-Vendor: Nokia
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ com.nokia.carbide.cpp.pi,
+ com.nokia.carbide.cpp.pi.util,
+ com.nokia.carbide.cpp.pi.priority,
+ org.eclipse.draw2d
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.pi.memory;x-friends:="com.nokia.carbide.cpp.pi.memory.tests"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,6 @@
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .
+jars.compile.order = .
+source.. = src/
+output.. = bin/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+   <extension
+         point="com.nokia.carbide.cpp.pi.piPluginData">
+      <plugin pluginClass="com.nokia.carbide.cpp.pi.memory.MemoryReturnPlugin"/>
+   </extension>
+   <extension
+         point="org.eclipse.ui.actionSets">
+      <actionSet
+            label="Memory Graph"
+            visible="false"
+            id="com.nokia.carbide.cpp.pi.memory.graphActionSet">
+         <menu
+               label="Memory Graph"
+               path="window/additions"
+               id="com.nokia.carbide.cpp.pi.memory.viewMenu">
+            <separator name="show"/>
+            <separator name="scale"></separator>
+            <separator name="additions"></separator>
+         </menu>
+         <action
+               class="com.nokia.carbide.cpp.internal.pi.memory.actions.ShowTotalDelegate"
+               id="com.nokia.carbide.cpp.pi.memory.showTotalAction"
+               label="Show Total Memory Usage"
+               menubarPath="window/com.nokia.carbide.cpp.pi.memory.viewMenu/show"
+               state="true"
+               style="radio"/>
+         <action
+               class="com.nokia.carbide.cpp.internal.pi.memory.actions.ShowStackDelegate"
+               id="com.nokia.carbide.cpp.pi.memory.showStackAction"
+               label="Show Stack Usage"
+               menubarPath="window/com.nokia.carbide.cpp.pi.memory.viewMenu/show"
+               state="false"
+               style="radio"/>
+         <action
+               class="com.nokia.carbide.cpp.internal.pi.memory.actions.ShowHeapDelegate"
+               id="com.nokia.carbide.cpp.pi.memory.showHeapAction"
+               label="Show Heap Usage"
+               menubarPath="window/com.nokia.carbide.cpp.pi.memory.viewMenu/show"
+               state="false"
+               style="radio"/>
+         <action
+               class="com.nokia.carbide.cpp.internal.pi.memory.actions.DynamicScaleDelegate"
+               id="com.nokia.carbide.cpp.pi.memory.dynamicScaleAction"
+               label="Dynamic visualization scale"
+               menubarPath="window/com.nokia.carbide.cpp.pi.memory.viewMenu/scale"
+               state="false"
+               style="toggle"/>
+      </actionSet>
+   </extension>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/internal/pi/memory/actions/DynamicScaleDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.memory.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.memory.MemoryPlugin;
+
+public class DynamicScaleDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+
+		if (action.isChecked())
+		{
+			MemoryPlugin.getDefault().receiveSelectionEvent("dynamicMemoryVisualisation"); //$NON-NLS-1$
+		}
+		else
+		{
+			MemoryPlugin.getDefault().receiveSelectionEvent("absoluteMemoryVisualisation"); //$NON-NLS-1$
+		}
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/internal/pi/memory/actions/MemoryStatisticsDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.memory.actions;
+
+import java.text.DecimalFormat;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.memory.MaxMemoryItem;
+import com.nokia.carbide.cpp.pi.memory.MemThread;
+import com.nokia.carbide.cpp.pi.memory.MemThreadTable;
+import com.nokia.carbide.cpp.pi.memory.MemTrace;
+import com.nokia.carbide.cpp.pi.memory.MemTraceGraph;
+import com.nokia.carbide.cpp.pi.memory.Messages;
+
+
+public class MemoryStatisticsDialog {
+
+	private Shell shell;
+	private GridData gridData;
+	private DecimalFormat formatKBytes = new DecimalFormat(Messages.getString("MemoryStatisticsDialog.KBformat")); //$NON-NLS-1$
+	private DecimalFormat formatBytes  = new DecimalFormat(Messages.getString("MemoryStatisticsDialog.BytesFormat")); //$NON-NLS-1$
+	private MemTrace trace;
+	private double startTime;
+	private double endTime;
+	
+	public MemoryStatisticsDialog(Display display)
+	{
+		Group group;
+		
+		shell = new Shell(display, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+		shell.setText(Messages.getString("MemoryStatisticsDialog.statistics")); //$NON-NLS-1$
+		shell.setLayout(new GridLayout(3, false));
+
+    	startTime = PIPageEditor.currentPageEditor().getStartTime();
+    	endTime   = PIPageEditor.currentPageEditor().getEndTime();
+
+		trace = (MemTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.memory"); //$NON-NLS-1$
+		
+//		group = new Group(shell, SWT.SHADOW_NONE);
+//		group.setText(Messages.getString("MemoryStatisticsDialog.memoryModel")); //$NON-NLS-1$
+//		group.setFont(PIPageEditor.helvetica_9);
+//		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+//		gridData.horizontalSpan = 3;
+//		group.setLayoutData(gridData);
+//		group.setLayout(new GridLayout(3, false));//new FillLayout());
+//		
+//		String model = ""; //$NON-NLS-1$
+//		if (trace.getMemoryModel() == MemTrace.MEMORY_MULTIPLE)
+//			model = Messages.getString("MemoryStatisticsDialog.multiple"); //$NON-NLS-1$
+//		else if (trace.getMemoryModel() == MemTrace.MEMORY_MOVING)
+//			model = Messages.getString("MemoryStatisticsDialog.moving"); //$NON-NLS-1$
+//		else if (trace.getMemoryModel() == MemTrace.MEMORY_DIRECT)
+//			model = Messages.getString("MemoryStatisticsDialog.direct"); //$NON-NLS-1$
+//		else
+//			model = Messages.getString("MemoryStatisticsDialog.notRecorded"); //$NON-NLS-1$
+//
+//		textGrid(group, model, SWT.CENTER, SWT.CENTER, 3); //$NON-NLS-1$
+
+		group = new Group(shell, SWT.SHADOW_NONE);
+		group.setText(Messages.getString("MemoryStatisticsDialog.interval")); //$NON-NLS-1$
+		group.setFont(PIPageEditor.helvetica_9);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 3;
+		group.setLayoutData(gridData);
+		group.setLayout(new GridLayout(3, false));//new FillLayout());
+		textGrid(group, showTimeInterval(startTime, endTime), SWT.CENTER, SWT.CENTER, 3);
+		
+		int pageIndex = PIPageEditor.currentPageIndex();
+		
+		MemTraceGraph graph = (MemTraceGraph) trace.getTraceGraph(pageIndex); // since graph intervals are in lockstep, any pageIndex will do
+		MemThreadTable table = graph.getMemThreadTable();
+		
+		MaxMemoryItem systemUseByInterval = trace.getSystemUseByInterval((long) (startTime * 1000.0), (long) (endTime * 1000.0));
+		
+		group = new Group(shell, SWT.NONE);
+		group.setText(Messages.getString("MemoryStatisticsDialog.onDevice")); //$NON-NLS-1$
+		group.setFont(PIPageEditor.helvetica_9);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 3;
+		group.setLayoutData(gridData);
+		group.setLayout(new GridLayout(3, false));//new FillLayout());
+		
+		String usedKB     = Messages.getString("MemoryStatisticsDialog.notRecorded"); //$NON-NLS-1$
+		String usedBytes  = ""; //$NON-NLS-1$
+		String freeKB     = usedKB;
+		String freeBytes  = usedBytes;
+		String totalKB    = usedKB;
+		String totalBytes = usedBytes;
+
+		if ((long) (endTime * 1000.0 + 0.5) >= trace.getFirstSampleNumber()) {
+			long deviceTotalMemory = systemUseByInterval.maxTotal;
+			long deviceUsedMemory  = systemUseByInterval.maxChunks;
+
+			usedKB     = formatKBytes.format(deviceUsedMemory / 1024.0);
+			usedBytes  = formatBytes.format(deviceUsedMemory);
+			freeKB     = formatKBytes.format((deviceTotalMemory - deviceUsedMemory) / 1024.0);
+			freeBytes  = formatBytes.format(deviceTotalMemory - deviceUsedMemory);
+			totalKB    = formatKBytes.format(deviceTotalMemory / 1024.0);
+			totalBytes = formatBytes.format(deviceTotalMemory);
+		}
+		textGrid(group, Messages.getString("MemoryStatisticsDialog.used"), SWT.LEFT, SWT.CENTER, 1); //$NON-NLS-1$
+		textGrid(group, usedKB, SWT.RIGHT, SWT.CENTER, 1);
+		textGrid(group, usedBytes, SWT.RIGHT, SWT.CENTER, 1);
+		textGrid(group, Messages.getString("MemoryStatisticsDialog.free"), SWT.LEFT, SWT.CENTER, 1); //$NON-NLS-1$
+		textGrid(group, freeKB, SWT.RIGHT, SWT.CENTER, 1);
+		textGrid(group, freeBytes, SWT.RIGHT, SWT.CENTER, 1);
+		textGrid(group, Messages.getString("MemoryStatisticsDialog.total"),  SWT.LEFT, SWT.CENTER, 1); //$NON-NLS-1$
+		textGrid(group, totalKB, SWT.RIGHT, SWT.CENTER, 1);
+		textGrid(group, totalBytes, SWT.RIGHT, SWT.CENTER, 1);
+
+		group = new Group(shell, SWT.NONE);
+		group.setText(Messages.getString("MemoryStatisticsDialog.currentSelection")); //$NON-NLS-1$
+		group.setFont(PIPageEditor.helvetica_9);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 3;
+		group.setLayoutData(gridData);
+		group.setLayout(new GridLayout(3, false));//new FillLayout());
+		
+		String chunkKB    = Messages.getString("MemoryStatisticsDialog.notRecorded"); //$NON-NLS-1$
+		String chunkBytes = ""; //$NON-NLS-1$
+		String stackKB    = chunkKB;
+		String stackBytes = chunkBytes;
+
+		if ((long) (endTime * 1000.0 + 0.5) >= trace.getFirstSampleNumber()) {
+			float selectedMaxChunks    = 0;
+			float selectedMaxStackHeap = 0;
+
+			Object[] selected = table.getTableViewer().getCheckedElements();
+			
+			for (int i = 0; i < selected.length; i++) {
+				if (selected[i] instanceof MemThread) {
+					MemThread checked = (MemThread) selected[i];
+					selectedMaxChunks    += checked.maxMemoryItem.maxChunks;
+					selectedMaxStackHeap += checked.maxMemoryItem.maxStackHeap;
+				}
+			}
+
+			chunkKB    = formatKBytes.format(selectedMaxChunks / 1024.0);
+			chunkBytes = formatBytes.format((long) selectedMaxChunks);
+			stackKB    = formatKBytes.format(selectedMaxStackHeap / 1024.0);
+			stackBytes = formatBytes.format((long) selectedMaxStackHeap);
+		}
+
+		textGrid(group, Messages.getString("MemoryStatisticsDialog.chunks"),  SWT.LEFT, SWT.CENTER, 1); //$NON-NLS-1$
+		textGrid(group, chunkKB, SWT.RIGHT, SWT.CENTER, 1);
+		textGrid(group, chunkBytes, SWT.RIGHT, SWT.CENTER, 1);
+		textGrid(group, Messages.getString("MemoryStatisticsDialog.stackHeap"), SWT.LEFT, SWT.CENTER, 1); //$NON-NLS-1$
+		textGrid(group, stackKB, SWT.RIGHT, SWT.CENTER, 1);
+		textGrid(group, stackBytes, SWT.RIGHT, SWT.CENTER, 1);
+		
+		// create the Close button
+		Button close = new Button(shell, SWT.NONE);
+		close.setText(Messages.getString("MemoryStatisticsDialog.close")); //$NON-NLS-1$
+		gridData = new GridData(SWT.CENTER, SWT.CENTER, true, true);
+		gridData.minimumWidth = 60;
+		gridData.horizontalSpan = 3;
+		close.setLayoutData(gridData);
+		close.addSelectionListener(new SelectionListener(){
+
+			public void widgetSelected(SelectionEvent e) {
+				shell.close();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+		});
+
+		shell.pack();
+		shell.open();
+
+		while (!shell.isDisposed()) {
+			if (!shell.getDisplay().readAndDispatch()) {
+				shell.getDisplay().sleep();
+			}
+		}
+	}
+	
+	private void textGrid(Composite parent, String text, int labelStyle, int gridStyle, int gridSpan)
+	{
+		Label label = new Label(parent, labelStyle);
+		label.setFont(PIPageEditor.helvetica_9);
+		label.setText(text);
+		gridData = new GridData(SWT.FILL, gridStyle, true, true);
+		gridData.horizontalSpan = gridSpan;
+		label.setLayoutData(gridData);		
+	}
+
+	public void dispose()
+	{
+		if (this.shell != null) {
+			if (!this.shell.isDisposed()) {
+				this.shell.close();				
+			}
+			this.shell.dispose();
+		}
+
+		this.shell = null;
+	}
+
+	private static String showTimeInterval(double startTime, double endTime)
+	{
+		return ProfileVisualiser.timeFormat.format(startTime)
+		     + Messages.getString("MemoryStatisticsDialog.interval1") + ProfileVisualiser.timeFormat.format(endTime) //$NON-NLS-1$
+		     + Messages.getString("MemoryStatisticsDialog.interval2") + ProfileVisualiser.timeFormat.format(endTime - startTime) //$NON-NLS-1$
+		     + Messages.getString("MemoryStatisticsDialog.interval3"); //$NON-NLS-1$
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/internal/pi/memory/actions/ShowHeapDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.memory.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.memory.MemoryPlugin;
+
+public class ShowHeapDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+		MemoryPlugin.getDefault().receiveSelectionEvent("showHeap"); //$NON-NLS-1$
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/internal/pi/memory/actions/ShowStackDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.memory.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.memory.MemoryPlugin;
+
+public class ShowStackDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+		MemoryPlugin.getDefault().receiveSelectionEvent("showStack"); //$NON-NLS-1$
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/internal/pi/memory/actions/ShowTotalDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.memory.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.memory.MemoryPlugin;
+
+public class ShowTotalDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+		MemoryPlugin.getDefault().receiveSelectionEvent("showTotal"); //$NON-NLS-1$
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MaxMemoryItem.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.memory;
+
+public class MaxMemoryItem {
+	public long maxChunks;
+	public long maxStackHeap;
+	public long maxTotal;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemSample.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.memory;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSample;
+
+
+public class MemSample extends GenericSample
+{
+	private static final long serialVersionUID = 5829017896307372969L;
+	
+	public MemThread thread;
+	public int heapSize;
+	public int stackSize;
+	public int sampleNum;
+	public int type;
+	
+	
+	public MemSample(MemThread thread, int heapSize, int stackSize, int sampleTime)
+	{
+		this.thread = thread;
+		this.heapSize = heapSize;
+		this.stackSize = stackSize;
+		this.sampleNum = sampleTime;
+		this.sampleSynchTime = sampleTime;
+	}
+	
+	
+	public MemSample(MemThread thread, int heapSize, int stackSize, int sampleNum, int type)
+	{
+		this.thread = thread;
+		this.heapSize = heapSize;
+		this.stackSize = stackSize;
+		this.sampleNum = sampleNum;
+		this.type = type;
+		this.sampleSynchTime = sampleNum;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemSampleByTime.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.memory;
+
+import java.util.ArrayList;
+
+
+public class MemSampleByTime {
+	private long time;
+	private ArrayList<MemSample> samples;
+	private long totalMemory;
+	private long usedMemory;
+	
+	public MemSampleByTime(long time, long totalMemory, long usedMemory)
+	{
+		this.time = time;
+		this.totalMemory = totalMemory;
+		this.usedMemory  = usedMemory;
+		this.samples = new ArrayList<MemSample>();
+	}
+
+	public ArrayList<MemSample> getSamples()
+	{
+		return this.samples;
+	}
+
+	public long getTime()
+	{
+		return this.time;
+	}
+
+	public long getTotalMemory()
+	{
+		return this.totalMemory;
+	}
+
+	public long getUsedMemory()
+	{
+		return this.usedMemory;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemThread.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.memory;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericThread;
+
+public class MemThread extends GenericThread
+{
+	private static final long serialVersionUID = 2633643437981913631L;
+	
+	// name to be shown for the thread
+	transient public String fullName;
+	
+	// maximum memory usage of thread/process within the current time interval
+	transient public MaxMemoryItem maxMemoryItem;
+	
+	// remember whether the thread/process is enabled for the given graph
+	transient public boolean[] enabled;
+
+	public MemThread(Integer threadId, String threadName, String processName)
+	{
+		this.threadId = threadId;
+		this.threadName = threadName;
+		this.processName = processName;
+	}
+	
+	// get whether the thread/process is enabled for the given graph
+    public boolean isEnabled(int graphIndex)
+    {
+    	return this.enabled[graphIndex];
+    }
+	
+    // set whether the thread/process is enabled for the given graph
+    public void setEnabled(int graphIndex, boolean enabled)
+    {
+    	this.enabled[graphIndex] = enabled;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemThreadTable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,852 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.memory;
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.ActionEvent;
+import java.awt.event.FocusEvent;
+import java.awt.event.MouseEvent;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.SubMenuManager;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.ide.IIDEActionConstants;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
+import com.nokia.carbide.cpp.internal.pi.memory.actions.MemoryStatisticsDialog;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTable;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+public class MemThreadTable extends GenericTable
+{
+	private static final int COLUMN_ID_MEMORY_CHUNKS  = 14;
+	private static final int COLUMN_ID_MEMORY_STACK   = 15;
+	private static final int COLUMN_ID_MEMORY_TOTAL   = 16;
+	private static final int COLUMN_ID_MEMORY_NAME    = 17;
+
+	// sort direction
+	private boolean sortAscending = true;
+	
+	// trace associated with this display
+//	private MemTrace myTrace;
+	private MemTraceGraph myGraph;
+	private Composite parent;
+
+	// override
+    protected Vector<MemThread> tableItemData;
+
+    // menu items
+	private Action selectAllAction;
+	private Action copyTableAction;
+	private Action copyAction;
+	private Action saveTableAction;
+	
+	// class to pass sample data to the save wizard
+    public class SaveSampleString implements ISaveSamples {
+    	boolean done = false;
+    	
+    	public SaveSampleString() {
+		}
+
+    	public String getData() {
+    		if (done)
+    			return null;
+    		
+			String returnString = getSampleString();
+			done = true;
+			return returnString;
+		}
+
+		public String getData(int size) {
+			return getData();
+		}
+
+		public int getIndex() {
+			return done ? 1 : 0;
+		}
+
+		public void clear() {
+			done = false;
+		}
+    }
+
+	/*
+	 * return the memory samples selected in the interval 
+	 */
+	protected String getSampleString()
+	{
+		int startTime = (int) (PIPageEditor.currentPageEditor().getStartTime() * 1000.0 + 0.0005);
+		int endTime   = (int) (PIPageEditor.currentPageEditor().getEndTime()   * 1000.0 + 0.0005);
+		
+		MemTrace trace = this.myGraph.getMemTrace();
+		ArrayList<MemSampleByTime> drawDataByTime = trace.getDrawDataByTime();
+		
+		if (drawDataByTime == null || drawDataByTime.size() == 0)
+			return "";	// should have been checked so this never happens //$NON-NLS-1$
+		
+		String returnString = Messages.getString("MemThreadTable.saveSamplesHeading"); //$NON-NLS-1$
+
+		if (drawDataByTime.get(0).getTime() > startTime) {
+			int graphIndex = this.myGraph.getGraphIndex();
+			TableItem[] items = this.table.getItems();
+			
+			for (int i = 0; i < items.length; i++) {
+				Object data = items[i].getData();
+				
+				if (!(data instanceof MemThread))
+					continue;
+				
+				MemThread pmt = (MemThread) data;
+				
+				if (!pmt.enabled[graphIndex])
+					continue;
+				
+				returnString +=   Messages.getString("MemThreadTable.notRecorded1") + items[i].getText() + Messages.getString("MemThreadTable.notRecorded2"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+		
+		// find least sampling time greater than or equal to the start time
+		int i = 0;
+		long sampleTime = 0;
+		for ( ; i < drawDataByTime.size(); i++)	{
+			sampleTime = drawDataByTime.get(i).getTime(); 
+			if (sampleTime > startTime)
+				break;
+		}
+		
+		if (i != 0)
+			i--;
+
+		int graphIndex = myGraph.getGraphIndex();
+		for ( ; i < drawDataByTime.size() && drawDataByTime.get(i).getTime() <= endTime; i++) {
+			ArrayList<MemSample> samples = drawDataByTime.get(i).getSamples();
+			for (MemSample sample : samples) {
+				if (!sample.thread.enabled[graphIndex])
+					continue;
+					
+				returnString +=   sample.sampleSynchTime + Messages.getString("MemThreadTable.comma") + sample.thread.fullName //$NON-NLS-1$
+								+ Messages.getString("MemThreadTable.comma") + (sample.heapSize / 1024) + Messages.getString("MemThreadTable.comma") + (sample.stackSize / 1024) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			}
+		}
+
+		return returnString;
+	}
+
+	protected MenuItem getSaveSamplesItem(Menu menu, boolean enabled) {
+	    MenuItem saveSamplesItem = new MenuItem(menu, SWT.PUSH);
+
+		saveSamplesItem.setText(Messages.getString("MemThreadTable.saveCheckedSamples")); //$NON-NLS-1$
+		saveSamplesItem.setEnabled(enabled);
+		
+		if (enabled) {
+			saveSamplesItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+					action("saveSamples"); //$NON-NLS-1$
+				}
+			});
+		}
+	
+		return saveSamplesItem;
+	}
+
+	public MemThreadTable(MemTraceGraph myGraph, Composite parent)
+	{
+		this.myGraph = myGraph;
+		this.parent  = parent;
+
+		this.tableViewer = CheckboxTableViewer.newCheckList(parent,
+  				SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
+		this.table = this.tableViewer.getTable();
+		this.table.setLayoutData(new GridData(GridData.FILL_BOTH));
+		
+		// add the check state handler, label provider and content provider
+		this.tableViewer.addCheckStateListener(new CheckHandler());
+		this.tableViewer.setLabelProvider(new SharedLabelProvider(this.table));
+		this.tableViewer.setContentProvider(new MemoryTableContentProvider());
+		this.tableViewer.setSorter(new SharedSorter());
+
+		// give the table a heading for possible use in copying and exported
+		this.table.setData(Messages.getString("MemThreadTable.memory")); //$NON-NLS-1$
+		
+		// create the columns
+		TableColumn column;
+
+		// data associated with the TableViewer will note which columns contain hex values
+		// Keep this in the order in which columns have been created
+		boolean[] isHex = {false, false, false, false};
+		this.table.setData("isHex", isHex); //$NON-NLS-1$
+
+		// select/deselect column
+		column = new TableColumn(this.table, SWT.CENTER);
+		column.setText(COLUMN_HEAD_MEMORY_NAME);
+		column.setWidth(COLUMN_WIDTH_MEMORY_NAME + 15); // extra space for the checkbox
+		column.setData(new Integer(COLUMN_ID_MEMORY_NAME));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		column = new TableColumn(tableViewer.getTable(), SWT.RIGHT);
+		column.setText(COLUMN_HEAD_MEMORY_CHUNKS);
+		column.setWidth(COLUMN_WIDTH_MEMORY_CHUNKS);
+		column.setData(new Integer(COLUMN_ID_MEMORY_CHUNKS));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		column = new TableColumn(tableViewer.getTable(), SWT.RIGHT);
+		column.setText(COLUMN_HEAD_MEMORY_STACK);
+		column.setWidth(COLUMN_WIDTH_MEMORY_STACK);
+		column.setData(new Integer(COLUMN_ID_MEMORY_STACK));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+
+		column = new TableColumn(tableViewer.getTable(), SWT.RIGHT);
+		column.setText(COLUMN_HEAD_MEMORY_TOTAL);
+		column.setWidth(COLUMN_WIDTH_MEMORY_TOTAL);
+		column.setData(new Integer(COLUMN_ID_MEMORY_TOTAL));
+		column.setMoveable(true);
+		column.setResizable(true);
+		column.addSelectionListener(new ColumnSelectionHandler());
+		
+		// initially, all rows are checked
+		this.tableViewer.setAllChecked(true);
+
+		this.table.addMouseListener(new TableMouseListener());
+		this.table.setHeaderVisible(true);
+		this.table.setLinesVisible(true);
+		this.table.setRedraw(true);
+		
+		updateItemData(true);
+		((SharedSorter) tableViewer.getSorter()).doSort(COLUMN_ID_MEMORY_NAME);
+
+		// initially, all rows are checked
+		this.tableViewer.setAllChecked(true);
+		
+		createDefaultActions();
+
+		// listen for key sequences such as Ctrl-A and Ctrl-C
+		table.addKeyListener(new TableKeyListener());
+		
+		table.addFocusListener(new FocusListener() {
+			IAction oldSelectAllAction = null;
+			IAction oldCopyAction = null;
+
+			public void focusGained(org.eclipse.swt.events.FocusEvent arg0) {
+				IActionBars bars = PIPageEditor.getActionBars();
+				
+				oldSelectAllAction = PIPageEditor.getActionBars().getGlobalActionHandler(ActionFactory.SELECT_ALL.getId());
+				oldCopyAction = PIPageEditor.getActionBars().getGlobalActionHandler(ActionFactory.COPY.getId());
+
+				bars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
+				bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), selectAllAction);
+
+				copyAction.setEnabled(table.getSelectionCount() > 0);
+				selectAllAction.setEnabled(table.getItemCount() > 0);
+				bars.updateActionBars();
+				
+				// add to the Edit menu
+		        IMenuManager editMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_EDIT);
+
+		        if (editMenuManager instanceof SubMenuManager)
+		        {
+		        	IContributionManager editManager = ((SubMenuManager)editMenuManager).getParent();
+		        	ActionContributionItem item;
+
+					editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
+		        	copyTableAction.setEnabled(table.getItemCount() > 0);
+		        	item = new ActionContributionItem(copyTableAction);
+		        	item.setVisible(true);
+		        	editManager.prependToGroup(IIDEActionConstants.CUT_EXT, item);
+		        }
+				
+				// add to the File menu
+		        IMenuManager fileMenuManager = bars.getMenuManager().findMenuUsingPath(IIDEActionConstants.M_FILE);
+
+		        if (fileMenuManager instanceof SubMenuManager)
+		        {
+		        	IContributionManager fileManager = ((SubMenuManager)fileMenuManager).getParent();
+		        	ActionContributionItem item;
+
+		        	fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
+		        	saveTableAction.setEnabled(table.getItemCount() > 0);
+		        	item = new ActionContributionItem(saveTableAction);
+		        	item.setVisible(true);
+		        	fileManager.insertAfter("saveAll", item); //$NON-NLS-1$
+		        }
+			}
+
+			public void focusLost(org.eclipse.swt.events.FocusEvent arg0) {
+				IActionBars bars = PIPageEditor.getActionBars();
+				bars.setGlobalActionHandler(ActionFactory.COPY.getId(), oldCopyAction);
+				bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), oldSelectAllAction);
+				bars.updateActionBars();
+
+				SubMenuManager editMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_EDIT);
+				editMenuManager.remove("PICopyTable"); //$NON-NLS-1$
+				editMenuManager.update();
+
+				SubMenuManager fileMenuManager = (SubMenuManager) PIPageEditor.getMenuManager().find(IIDEActionConstants.M_FILE);
+				fileMenuManager.remove("PISaveTable"); //$NON-NLS-1$
+				fileMenuManager.update();
+			}
+		});
+
+		tableViewer.refresh();
+		table.redraw();
+	}
+
+	private class TableMouseListener implements MouseListener
+	{
+		public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) {
+			if (e.button == MouseEvent.BUTTON1)
+			{
+				TableItem[] selectedItems = table.getSelection();
+				if (selectedItems.length == 0)
+					return;
+
+				if (selectedItems[0].getData() instanceof MemThread)
+				{
+					MemThread pMemThread = (MemThread)(selectedItems[0].getData());
+				    if (pMemThread.isEnabled(myGraph.getGraphIndex()))
+				        action("remove"); //$NON-NLS-1$
+				    else
+				        action("add"); //$NON-NLS-1$
+				}
+			}
+			selectAllAction.setEnabled(table.getItemCount() > 0);
+			copyAction.setEnabled(table.getSelectionCount() > 0);
+			copyTableAction.setEnabled(table.getItemCount() > 0);
+		}
+
+		public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
+		}
+
+		public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
+
+			selectAllAction.setEnabled(table.getItemCount() > 0);
+			copyAction.setEnabled(table.getSelectionCount() > 0);
+			copyTableAction.setEnabled(table.getItemCount() > 0);
+
+			if (e.button == MouseEvent.BUTTON3) {
+				// get rid of last Menu created so we don't have double menu
+				// on click
+				if (contextMenu != null) {
+					contextMenu.dispose();
+				}
+
+				contextMenu = new Menu(table.getShell(), SWT.POP_UP);
+				getCheckRows(contextMenu, table.getSelectionCount() > 0);
+
+				// select all, copy, and copy all
+				new MenuItem(contextMenu, SWT.SEPARATOR);
+				getSelectAllItem(contextMenu, table.getItemCount() > 0);
+				getCopyItem(contextMenu, table.getSelectionCount() > 0);
+				getCopyTableItem(contextMenu, table.getItemCount() > 0);
+				selectAllAction.setEnabled(table.getItemCount() > 0);
+				copyAction.setEnabled(table.getSelectionCount() > 0);
+				copyTableAction.setEnabled(table.getItemCount() > 0);
+				
+				// save all
+				new MenuItem(contextMenu, SWT.SEPARATOR);
+				getSaveTableItem(contextMenu, table.getItemCount() > 0);
+				saveTableAction.setEnabled(table.getItemCount() > 0);
+
+				// save samples
+				int startTime = (int) (PIPageEditor.currentPageEditor().getStartTime() * 1000.0f);
+				int endTime   = (int) (PIPageEditor.currentPageEditor().getEndTime()   * 1000.0f);
+
+				getSaveSamplesItem(contextMenu,
+					myGraph.haveEnabled() && (startTime != -1) && (endTime != -1) && (startTime != endTime));
+
+				contextMenu.setLocation(parent.toDisplay(e.x + table.getLocation().x, e.y + table.getLocation().y));
+			    contextMenu.setVisible(true);
+
+				new MenuItem(contextMenu, SWT.SEPARATOR);
+
+				MenuItem memoryStatsItem = new MenuItem(contextMenu, SWT.PUSH);
+				memoryStatsItem.setText(Messages.getString("MemoryPlugin.memoryStats")); //$NON-NLS-1$
+				memoryStatsItem.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {
+						new MemoryStatisticsDialog(Display.getCurrent());
+					}
+				});
+
+				table.setMenu(contextMenu);
+			}
+		}
+	}
+
+	private static class MemoryTableContentProvider implements IStructuredContentProvider {
+
+		public MemoryTableContentProvider() {
+			super();
+		}
+
+		public Object[] getElements(Object inputElement) {
+			return ((Vector<MemThread>) inputElement).toArray();
+		}
+
+		public void dispose() {
+		}
+
+		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		}
+	}
+
+	private class CheckHandler implements ICheckStateListener
+	{
+		public void checkStateChanged(CheckStateChangedEvent event) {
+
+       		if (!(event.getElement() instanceof MemThread))
+       			return;
+       		
+       		// set the stored value to the checkbox value
+       		MemThread pMemThread = (MemThread)event.getElement();
+       		pMemThread.setEnabled(myGraph.getGraphIndex(), event.getChecked());
+
+       		selectionChangeNotify();
+
+       		table.deselectAll();
+		}
+	}
+
+	void selectionChangeNotify() {
+		this.tableViewer.refresh();
+		this.table.redraw();
+		PIEvent be = new PIEvent(null, PIEvent.CHANGED_MEMORY_TABLE);
+		myGraph.piEventReceived(be);
+    }
+
+	private class SharedLabelProvider extends LabelProvider implements ITableLabelProvider {
+		
+        private DecimalFormat decimalFormat = new DecimalFormat(Messages.getString("MemThreadTable.kbFormat")); //$NON-NLS-1$
+
+        Table table;
+
+		public SharedLabelProvider(Table table) {
+			super();
+			this.table = table;
+		}
+
+		public String getColumnText(Object element, int columnIndex) {
+	        int columnId = ((Integer) table.getColumn(columnIndex).getData()).intValue();
+
+			if (!(element instanceof MemThread))
+				return ""; //$NON-NLS-1$
+
+			MemThread profiledItem = (MemThread) element;
+			
+			switch (columnId)
+			{
+				case COLUMN_ID_MEMORY_NAME:
+				{
+					return profiledItem.fullName;
+				}
+				case COLUMN_ID_MEMORY_CHUNKS:
+			    {
+					double startTime = PIPageEditor.currentPageEditor().getStartTime();
+					double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+
+					if ((startTime == -1) || (endTime   == -1) || (startTime == endTime))
+						return ""; //$NON-NLS-1$
+
+					return decimalFormat.format((profiledItem.maxMemoryItem.maxChunks + 512)/1024);
+			    }
+				case COLUMN_ID_MEMORY_STACK:
+			    {
+					double startTime = PIPageEditor.currentPageEditor().getStartTime();
+					double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+
+					if ((startTime == -1) || (endTime   == -1) || (startTime == endTime))
+						return ""; //$NON-NLS-1$
+
+					return decimalFormat.format((profiledItem.maxMemoryItem.maxStackHeap + 512)/1024);
+			    }
+				case COLUMN_ID_MEMORY_TOTAL:
+			    {
+					double startTime = PIPageEditor.currentPageEditor().getStartTime();
+					double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+
+					if ((startTime == -1) || (endTime   == -1) || (startTime == endTime))
+						return ""; //$NON-NLS-1$
+					
+					return decimalFormat.format((profiledItem.maxMemoryItem.maxTotal + 512)/1024);
+			    }
+				default:
+				{
+					break;
+				}
+			}
+			// should never get here
+			return ""; //$NON-NLS-1$
+		}
+
+		public Image getColumnImage(Object element, int columnIndex) {
+			return null;
+		}
+	}
+
+	
+	/*
+	 * TableViewer sorter for the called-by and called function tableviewers
+	 */
+	private class SharedSorter extends ViewerSorter {
+		// last column sorted
+		private int column = -1;
+		
+		/* 
+		 * decide on which column to sort by, and the sort ordering
+		 */
+		public void doSort(int column) {
+			// ignore the column passed in and use the id set by the column selection handler
+			if (column == this.column) {
+				// sort in other order
+				sortAscending = !sortAscending;
+			} else {
+				// changed columns, so sort in the default order
+				switch (column) {
+					case COLUMN_ID_MEMORY_NAME:
+					{
+		            	// sort in ascending order
+		            	sortAscending = true;
+		                break;
+					}
+					case COLUMN_ID_MEMORY_CHUNKS:
+					case COLUMN_ID_MEMORY_STACK:
+					case COLUMN_ID_MEMORY_TOTAL:
+					{
+		            	// sort in descending order
+		            	sortAscending = false;
+		                break;
+					}
+					default:
+					{
+						// ignore the column
+						return;
+					}
+				}
+				this.column = column;
+			}
+
+			// find the TableColumn corresponding to column, and give it a column direction
+			TableColumn sortByColumn = null;
+			for (int i = 0; i < table.getColumnCount(); i++) {
+				if (table.getColumn(i).getData() instanceof Integer) {
+					if (((Integer)table.getColumn(i).getData()) == column) {
+						sortByColumn = table.getColumn(i);
+						break;
+					}
+				}
+			}
+
+			if (sortByColumn != null) {
+				table.setSortColumn(sortByColumn);
+				table.setSortDirection(sortAscending ? SWT.UP : SWT.DOWN);
+			}
+		}
+		
+		/*
+		 * compare two items from a table column
+		 */
+		public int compare(Viewer viewer, Object e1, Object e2) {
+			int returnCode = 0;
+			
+			MemThread elem1 = (MemThread)e1;
+			MemThread elem2 = (MemThread)e2;
+
+			// find the memory information for the two threads
+			
+			// compare based on the memory information
+			switch (column) {
+			case COLUMN_ID_MEMORY_CHUNKS:
+				
+				returnCode = elem1.maxMemoryItem.maxChunks >
+									elem2.maxMemoryItem.maxChunks ? 1 : -1;
+				break;
+			case COLUMN_ID_MEMORY_STACK:
+				returnCode = elem1.maxMemoryItem.maxStackHeap >
+									elem2.maxMemoryItem.maxStackHeap ? 1 : -1;
+				break;
+			case COLUMN_ID_MEMORY_TOTAL:
+				returnCode = elem1.maxMemoryItem.maxTotal >
+									elem2.maxMemoryItem.maxTotal ? 1 : -1;
+				break;
+			case COLUMN_ID_MEMORY_NAME:
+			{
+				returnCode = this.getComparator().compare(elem1.fullName, elem2.fullName);
+				break;
+			}
+			default:
+				break;
+			}
+
+			// for descending order, reverse the sense of the compare
+			if (!sortAscending)
+				returnCode = -returnCode;
+
+			return returnCode;
+		}
+	}
+
+	public void actionPerformed(ActionEvent e) {}
+	
+	public void action(String actionString)
+	{
+		int graphIndex = this.myGraph.getGraphIndex();
+
+		if (   actionString.equals("add") //$NON-NLS-1$
+			|| actionString.equals("remove")) //$NON-NLS-1$
+	    {
+			actionAddRemove(actionString, graphIndex);
+	    }
+		else if (   actionString.equals("addall") //$NON-NLS-1$
+				 || actionString.equals("removeall")) //$NON-NLS-1$
+	    {
+			actionAddRemoveAll(actionString, graphIndex);
+	    }
+	    else if (actionString.equals("copy")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, this.table, CHECKBOX_TEXT, false, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return; // no redraw needed
+	    }
+	    else if (actionString.equals("copyTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(true, this.table, CHECKBOX_TEXT, true, "\t", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return; // no redraw needed
+	    }
+		else if (actionString.equals("selectAll")) //$NON-NLS-1$
+	    {
+	    	actionSelectAll();
+	        return;
+	    }
+	    else if (actionString.equals("saveTable")) //$NON-NLS-1$
+	    {
+	    	actionCopyOrSave(false, this.table, CHECKBOX_TEXT, true, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        return; // no redraw needed
+	    }
+	    else if (actionString.equals("saveSamples")) //$NON-NLS-1$
+	    {
+	    	SaveSampleString saveSampleString = new SaveSampleString();
+	    	actionSaveSamples(saveSampleString); //$NON-NLS-1$
+	        return;
+	    }
+	    else if (actionString.equals("saveTableTest")) //$NON-NLS-1$
+	    {
+			// copy save file contents to the clipboard for easy viewing
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+			SaveTableString getString = new SaveTableString(this.table, CHECKBOX_TEXT, ",", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+	        String copyString = getString.getData();
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+	        return;
+	    }
+
+		tableViewer.refresh();
+	    table.redraw();
+	    this.myGraph.repaint();
+	}
+
+	private void actionAddRemove(String actionString, int graphIndex)
+	{
+		MemThread memThread;
+		
+		// true for "add", false for "remove"
+		boolean addIt = actionString.equals("add"); //$NON-NLS-1$
+
+		TableItem[] selectedItems = this.table.getSelection();
+		for (int i = 0; i < selectedItems.length; i++)
+		{
+			selectedItems[i].setChecked(addIt);
+			memThread = (MemThread)((TableItem)selectedItems[i]).getData();
+			memThread.setEnabled(graphIndex, addIt);
+		}
+
+        // this table's set of checkbox-selected rows has changed,
+		// so propagate that information
+  		if (selectedItems.length != 0)
+   			selectionChangeNotify();
+
+  		this.table.deselectAll();
+	}
+	
+	private void actionAddRemoveAll(String actionString, int graphIndex)
+	{
+		MemThread memThread;
+
+		// true for "add", false for "remove"
+		boolean addIt = actionString.equals("addall"); //$NON-NLS-1$
+
+		TableItem[] selectedItems = this.table.getItems();
+		for (int i = 0; i < selectedItems.length; i++)
+		{
+			selectedItems[i].setChecked(addIt);
+			memThread = (MemThread)((TableItem)selectedItems[i]).getData();
+			memThread.setEnabled(graphIndex, addIt);
+		}
+
+        // this table's set of checkbox-selected rows has changed,
+		// so propagate that information
+		selectionChangeNotify();
+
+		this.table.deselectAll();
+	}
+
+	public void focusGained(FocusEvent e) {}
+
+	public void focusLost(FocusEvent e)	{}
+
+	public void piEventReceived(PIEvent be) 
+	{
+	    if (be.getType() == PIEvent.SELECTION_AREA_CHANGED2)
+		{
+			this.tableViewer.refresh();
+			this.table.redraw();
+		}
+	    else if (be.getType() == PIEvent.CHANGED_MEMORY_TABLE)
+		{
+//			this.tableViewer.refresh();
+//			this.table.redraw();
+		}
+	}
+
+	public void updateItemData(boolean setInput)
+	{
+		HashSet<MemThread> noDuplicateMemThreads = myGraph.getMemTrace().getNoDuplicateMemThreads();
+		if (tableItemData == null)
+			tableItemData = new Vector<MemThread>(noDuplicateMemThreads.size());
+		else
+			tableItemData.clear();
+		
+		// tableItemData contains one entry per table row
+		// the first profiled thread is the system-wide total memory information
+		for (Iterator<MemThread> iter = noDuplicateMemThreads.iterator(); iter.hasNext(); )
+		{
+			MemThread memThread = iter.next();
+			if (   (memThread.threadId != 0xffffffffbabbeaaaL)
+				&& (memThread.threadId != 0xffffffffbabbea20L))
+			{
+				tableItemData.add(memThread);
+			}
+		}
+
+		// refresh the table, if needed
+		if (setInput)
+			refreshTableViewer();
+	}
+
+	public void refreshTableViewer()
+	{
+		this.tableViewer.setInput(tableItemData);
+	}
+	
+	public void sortOnColumnSelection(TableColumn tableColumn) {
+    	int columnID = ((Integer) tableColumn.getData()).intValue();
+    	((SharedSorter) tableViewer.getSorter()).doSort(columnID);
+
+		tableViewer.refresh();
+    	table.redraw();
+	}
+	
+	private class ColumnSelectionHandler extends SelectionAdapter
+	{
+		public void widgetSelected(SelectionEvent e)
+        {
+        	if (!(e.widget instanceof TableColumn))
+        		return;
+        	
+        	sortOnColumnSelection((TableColumn) e.widget);
+        }
+	}
+	
+	public CheckboxTableViewer getTableViewer()
+	{
+		return this.tableViewer;
+	}
+
+	protected void createDefaultActions()
+	{
+		selectAllAction = new Action("SelectAll") { //$NON-NLS-1$
+			public void run() {
+				action("selectAll"); //$NON-NLS-1$
+			}
+		};
+		selectAllAction.setEnabled(true);
+
+		copyAction = new Action("Copy") { //$NON-NLS-1$
+			public void run() {
+				action("copy"); //$NON-NLS-1$
+			}
+		};
+		copyAction.setEnabled(false);
+
+		copyTableAction = new Action("CopyTable") { //$NON-NLS-1$
+			public void run() {
+				action("copyTable"); //$NON-NLS-1$
+			}
+		};
+		copyTableAction.setEnabled(true);
+		copyTableAction.setId("PICopyTable"); //$NON-NLS-1$
+		copyTableAction.setText(Messages.getString("MemThreadTable.copyTable")); //$NON-NLS-1$
+
+		saveTableAction = new Action("SaveTable") { //$NON-NLS-1$
+			public void run() {
+				action("saveTable"); //$NON-NLS-1$
+			}
+		};
+		saveTableAction.setEnabled(true);
+		saveTableAction.setId("PISaveTable"); //$NON-NLS-1$
+		saveTableAction.setText(Messages.getString("MemThreadTable.SaveTable")); //$NON-NLS-1$
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,656 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.memory;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+import org.eclipse.draw2d.IFigure;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.model.GenericThread;
+import com.nokia.carbide.cpp.internal.pi.model.TraceWithThreads;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+public class MemTrace extends GenericSampledTrace implements TraceWithThreads {
+	private static final long serialVersionUID = -2073732380166861141L;
+
+	// Symbian OS memory models
+	transient public static final long MEMORY_DIRECT = 0;
+	transient public static final long MEMORY_MOVING = 1;
+	transient public static final long MEMORY_MULTIPLE = 2;
+	transient public static final long MEMORY_UNKNOWN = -1;
+
+	transient private long memoryModel;
+
+	private transient MemTraceGraph[] graphs;
+
+	private Hashtable<Integer, Integer> firstSynchTimes;
+	private Hashtable<Integer, Integer> lastSynchTimes;
+	private MemThread[] threads;
+
+	// maximums for the entire trace
+	transient private int traceMaxChunks = 0;
+	transient private int traceMaxStackHeap = 0;
+	transient private int traceMaxTotal = 0;
+
+	// maximums found the last time setMaxMemDataByInterval was called
+	transient private int intervalMaxChunks = 0;
+	transient private int intervalMaxStackHeap = 0;
+	transient private int intervalMaxTotal = 0;
+
+	transient private Hashtable<String, TreeMap<Long, MemSample>> drawDataByMemThread = null;
+	transient private ArrayList<MemSampleByTime> drawDataByTime;
+	transient private HashSet<MemThread> noDuplicateMemThreads;
+
+	transient private long intervalStart = -1;
+	transient private long intervalEnd = -1;
+
+	private int version;
+
+	public MemTrace() {
+		firstSynchTimes = new Hashtable<Integer, Integer>();
+		lastSynchTimes = new Hashtable<Integer, Integer>();
+	}
+
+	public void addSample(MemSample sample) {
+		this.samples.add(sample);
+	}
+
+	public MemSample getMemSample(int number) {
+		return (MemSample) this.samples.elementAt(number);
+	}
+
+	public GenericThread[] getThreads() {
+		return threads;
+	}
+
+	public void setThreads(MemThread[] threads) {
+		this.threads = threads;
+	}
+
+	public int getTraceMaxChunks() {
+		return traceMaxChunks;
+	}
+
+	public int getTraceMaxStackHeap() {
+		return traceMaxStackHeap;
+	}
+
+	public int getTraceMaxTotal() {
+		return traceMaxTotal;
+	}
+
+	public void setTraceMaxStackHeap(int traceMaxStackHeap) {
+		this.traceMaxStackHeap = traceMaxStackHeap;
+	}
+
+	public void setTraceMaxTotal(int traceMaxTotal) {
+		this.traceMaxTotal = traceMaxTotal;
+	}
+
+	public void setTraceMaxChunks(int traceMaxChunks) {
+		this.traceMaxChunks = traceMaxChunks;
+	}
+
+	public int getIntervalMaxChunks() {
+		return intervalMaxChunks;
+	}
+
+	public int getIntervalMaxStackHeap() {
+		return intervalMaxStackHeap;
+	}
+
+	public int getIntervalMaxTotal() {
+		return intervalMaxTotal;
+	}
+
+	public int getVersion() {
+		return this.version;
+	}
+
+	public void setVersion(int version) {
+		this.version = version;
+	}
+
+	public void addFirstSynchTime(Integer id, Integer firstSynchTime) {
+		firstSynchTimes.put(id, firstSynchTime);
+	}
+
+	public void addLastSynchTime(Integer id, Integer lastSynchTime) {
+		lastSynchTimes.put(id, lastSynchTime);
+	}
+
+	public GenericTraceGraph getTraceGraph(int graphIndex) {
+		if (graphs == null) {
+			graphs = new MemTraceGraph[3];
+		}
+
+		// note that graphIndex need not match the index sent to MemTraceGraph
+		if ((graphIndex == PIPageEditor.THREADS_PAGE)
+				|| (graphIndex == PIPageEditor.BINARIES_PAGE)
+				|| (graphIndex == PIPageEditor.FUNCTIONS_PAGE)) {
+			if (graphs[graphIndex] == null) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				graphs[graphIndex] = new MemTraceGraph(graphIndex, this, uid);
+			}
+			return graphs[graphIndex];
+		}
+		return null;
+	}
+
+	public void gatherDrawData() {
+		if (version < 202) {
+			gatherSamplingBasedDrawData();
+		} else {
+			gatherEventBasedDrawData();
+		}
+	}
+
+	public void gatherSamplingBasedDrawData() {
+		if (drawDataByMemThread != null)
+			return; // already initialised
+
+		drawDataByMemThread = new Hashtable<String, TreeMap<Long, MemSample>>();
+		memoryModel = MemTrace.MEMORY_UNKNOWN;
+		getThreadsFromTrace();
+
+		if (drawDataByTime == null)
+			drawDataByTime = new ArrayList<MemSampleByTime>();
+
+		long lastTime = Integer.MIN_VALUE;
+		ArrayList<MemSample> memSamples = null;
+
+		traceMaxChunks = 0;
+		traceMaxStackHeap = 0;
+		traceMaxTotal = 0;
+
+		int currentChunks = 0;
+		int currentStackHeap = 0;
+		int currentTotal = 0;
+
+		long usedMemory = 0;
+		long freeMemory = 0;
+
+		// index each sample by thread/process name and by sample time
+		MemSample memSample;
+		for (Enumeration e = this.getSamples(); e.hasMoreElements();) {
+			memSample = (MemSample) e.nextElement();
+
+			if (lastTime != memSample.sampleSynchTime) {
+				// the first sample in each time period contains system-wide
+				// info
+				if (memSample.thread.threadId == 0xffffffffbabbeaaaL) {
+					usedMemory = memSample.heapSize;
+					freeMemory = memSample.stackSize;
+					memSample = (MemSample) e.nextElement();
+				}
+
+				// the 2nd sample in each time period has memory model and
+				// CodeSeg data
+				if (memSample.thread.threadId == 0xffffffffbabbea20L) {
+					usedMemory = memSample.heapSize;
+					freeMemory = memSample.stackSize;
+					memSample = (MemSample) e.nextElement();
+				}
+
+				// Create MemSampleByTime object based on sample
+				MemSampleByTime memSampleByTime = new MemSampleByTime(
+						memSample.sampleSynchTime, usedMemory + freeMemory,
+						usedMemory);
+
+				// add sample to drawn samples
+				drawDataByTime.add(memSampleByTime);
+
+				// add sample to array that contains all samples
+				memSamples = memSampleByTime.getSamples();
+
+				// save time
+				lastTime = memSample.sampleSynchTime;
+
+				// find the maximums for the entire graph
+				if (currentChunks > traceMaxChunks)
+					traceMaxChunks = currentChunks;
+				if (currentStackHeap > traceMaxStackHeap)
+					traceMaxStackHeap = currentStackHeap;
+				if (currentTotal > traceMaxTotal)
+					traceMaxTotal = currentTotal;
+
+				currentChunks = 0;
+				currentStackHeap = 0;
+				currentTotal = 0;
+			}
+
+			// Add sample to its thread's data hashtable
+			// drawDataByMemThread.get(memSample.thread.fullName).add(memSample);
+			drawDataByMemThread.get(memSample.thread.fullName).put(
+					memSample.sampleSynchTime, memSample);
+
+			// add sample sample array that contains all samples
+			memSamples.add(memSample);
+
+			currentChunks += memSample.heapSize;
+			currentStackHeap += memSample.stackSize;
+			currentTotal += memSample.heapSize + memSample.stackSize;
+		}
+
+		// find the maximums for the entire graph
+		if (currentChunks > traceMaxChunks)
+			traceMaxChunks = currentChunks;
+		if (currentStackHeap > traceMaxStackHeap)
+			traceMaxStackHeap = currentStackHeap;
+		if (currentTotal > traceMaxTotal)
+			traceMaxTotal = currentTotal;
+	}
+
+	public void gatherEventBasedDrawData() {
+		if (drawDataByMemThread != null)
+			return; // already initialised
+
+		drawDataByMemThread = new Hashtable<String, TreeMap<Long, MemSample>>();
+		memoryModel = MemTrace.MEMORY_UNKNOWN;
+		getThreadsFromTrace();
+
+		if (drawDataByTime == null)
+			drawDataByTime = new ArrayList<MemSampleByTime>();
+
+		long lastTime = Integer.MIN_VALUE;
+		ArrayList<MemSample> memSamples = null;
+
+		long usedMemory = 0;
+		long freeMemory = 0;
+
+		// index each sample by thread/process name and by sample time
+		MemSample memSample;
+		for (Enumeration e = this.getSamples(); e.hasMoreElements();) {
+			memSample = (MemSample) e.nextElement();
+
+			if (lastTime != memSample.sampleSynchTime) {
+				// the first sample in each time period contains system-wide
+				// info
+				if (memSample.thread.threadId == 0xffffffffbabbeaaaL) {
+					usedMemory = memSample.heapSize;
+					freeMemory = memSample.stackSize;
+					addSampleToThread(memSample);
+					memSample = (MemSample) e.nextElement();
+
+				}
+
+				// Create MemSampleByTime object based on sample
+				// MemSampleByTime memSampleByTime = new
+				// MemSampleByTime(memSample.sampleSynchTime, usedMemory +
+				// freeMemory, usedMemory);
+
+				// add sample to drawn samples
+				// drawDataByTime.add(memSampleByTime);
+
+				// add sample to array that contains all samples
+				// memSamples = memSampleByTime.getSamples();
+
+				// save time
+				lastTime = memSample.sampleSynchTime;
+
+			}
+
+			// Add sample to its thread's data hashtable
+			addSampleToThread(memSample);
+
+			// add sample sample array that contains all samples
+			// memSamples.add(memSample);
+		}
+
+	}
+
+	private void addSampleToThread(MemSample sample) {
+
+		// get sample array from thread
+		TreeMap<Long, MemSample> samples = drawDataByMemThread
+				.get(sample.thread.fullName);
+
+		if (sample.type == MemTraceParser.SAMPLE_CODE_DELETE_CHUNK) {
+			// event is delete event, set stack and heap size to zero
+			sample.stackSize = 0;
+			sample.heapSize = 0;
+		}
+
+		if (samples != null) {
+			// Add initial sample to thread
+			samples.put(sample.sampleSynchTime, sample);
+			return;
+		}
+
+		System.out.println("PI ERROR: Thread not found");
+
+	}
+
+	private void getThreadsFromTrace() {
+
+		noDuplicateMemThreads = new HashSet<MemThread>(131, 0.75f);
+
+		// the parser creates multiple copies of the same MemThread item,
+		// so we have to use the full name of the MemThread to access sample
+		// data
+		for (MemThread memThread : threads) {
+			String processedThreadName = memThread.threadName;
+
+			// Add Thread ID into processedThreadName
+			// looking for _T and _C suffixes and remove them for thread
+			if (processedThreadName.endsWith("_T")) //$NON-NLS-1$
+			{
+				processedThreadName = processedThreadName.substring(0,
+						processedThreadName.length() - 2)
+						+ "_" + memThread.threadId; //$NON-NLS-1$
+			} else if (processedThreadName.endsWith("_C")) { //$NON-NLS-1$
+				processedThreadName = processedThreadName.substring(0,
+						processedThreadName.length() - 2)
+						+ " [0x" + Integer.toHexString(memThread.threadId) + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+			} else {
+				processedThreadName += "_" + memThread.threadId; //$NON-NLS-1$
+			}
+
+			// Full name contains process name, thread name and thread id
+			memThread.fullName = memThread.processName
+					+ "::" + processedThreadName; //$NON-NLS-1$
+
+			memThread.enabled = new boolean[3];
+			memThread.enabled[0] = true;
+			memThread.enabled[1] = true;
+			memThread.enabled[2] = true;
+
+			memThread.maxMemoryItem = new MaxMemoryItem();
+			memThread.maxMemoryItem.maxChunks = 0;
+			memThread.maxMemoryItem.maxStackHeap = 0;
+			memThread.maxMemoryItem.maxTotal = 0;
+
+			if (drawDataByMemThread.get(memThread.fullName) == null) {
+				drawDataByMemThread.put(memThread.fullName,
+						new TreeMap<Long, MemSample>());
+				noDuplicateMemThreads.add(memThread);
+			}
+		}
+
+	}
+
+	public TreeMap<Long, MemSample> getDrawDataByMemThread(MemThread id) {
+		return this.drawDataByMemThread.get(id.fullName);
+	}
+
+	public ArrayList<MemSampleByTime> getDrawDataByTime() {
+		return this.drawDataByTime;
+	}
+
+	public HashSet<MemThread> getNoDuplicateMemThreads() {
+		return this.noDuplicateMemThreads;
+	}
+
+	public ArrayList<MemSample> getMemSampleDataByTime(long time) {
+		if ((this.drawDataByTime == null)
+				|| (time < this.drawDataByTime.get(0).getTime()))
+			return null;
+
+		int i = 0;
+		for (; i < this.drawDataByTime.size(); i++) {
+			MemSampleByTime sample = this.drawDataByTime.get(i);
+			if (sample.getTime() > time)
+				break;
+		}
+
+		return this.drawDataByTime.get(i - 1).getSamples();
+	}
+
+	public MemThread[] getMemThreads() {
+		return threads;
+	}
+
+	public MaxMemoryItem getSystemUseByInterval(long startTime, long endTime) {
+		MaxMemoryItem item = new MaxMemoryItem();
+
+		if ((this.drawDataByTime == null)
+				|| ((startTime == intervalStart) && (endTime == intervalEnd)))
+			return item;
+
+		if (this.getVersion() >= 202) {
+			TreeMap<Long, MemSample> events = drawDataByMemThread
+					.get("TOTAL_MEMORY::TOTAL_MEMORY_-1162089814");
+
+			Iterator<MemSample> values = events.values().iterator();
+
+			while (values.hasNext()) {
+				MemSample memSample = values.next();
+				// store system used memory as chunks and total memory as total
+				if (item.maxChunks < memSample.heapSize)
+					item.maxChunks = memSample.heapSize;
+
+				if (item.maxTotal < memSample.stackSize + memSample.heapSize)
+					item.maxTotal = memSample.stackSize + memSample.heapSize;
+
+				if (memSample.sampleSynchTime > endTime)
+					break;
+
+			}
+
+		} else {
+			long firstTime = this.drawDataByTime.get(0).getTime();
+			if ((startTime < firstTime) && (endTime < firstTime))
+				return item;
+
+			MemSampleByTime memSampleByTime;
+
+			int i = 0;
+
+			// find least sampling time greater than or equal to the start index
+			for (; i < this.drawDataByTime.size(); i++) {
+				if (((MemSampleByTime) this.drawDataByTime.get(i)).getTime() > startTime)
+					break;
+			}
+
+			if (i != 0)
+				i--;
+
+			for (; i < this.drawDataByTime.size(); i++) {
+				memSampleByTime = this.drawDataByTime.get(i);
+
+				// store system used memory as chunks and total memory as total
+				if (item.maxChunks < memSampleByTime.getUsedMemory())
+					item.maxChunks = memSampleByTime.getUsedMemory();
+
+				if (item.maxTotal < memSampleByTime.getTotalMemory())
+					item.maxTotal = memSampleByTime.getTotalMemory();
+
+				if (memSampleByTime.getTime() > endTime)
+					break;
+			}
+
+		}
+
+		return item;
+	}
+
+	public void setMaxMemDataByInterval(long startTime, long endTime) {
+
+		// Set all values to zero
+		for (int i = 0; i < threads.length; i++) {
+			MaxMemoryItem item = threads[i].maxMemoryItem;
+			item.maxChunks = 0;
+			item.maxStackHeap = 0;
+			item.maxTotal = 0;
+		}
+
+		// if no data is found between start and end time or start and end
+		// times are same with previous.
+		if ((this.drawDataByTime == null)
+				|| ((startTime == intervalStart) && (endTime == intervalEnd)))
+			return;
+
+		if (this.version >= 202) {
+
+			for (Enumeration e = drawDataByMemThread.elements(); e
+					.hasMoreElements();) {
+				TreeMap<Long, MemSample> memSamples = (TreeMap<Long, MemSample>) e
+						.nextElement();
+
+				if (memSamples.size() == 0) {
+					continue;
+				}
+
+				MemSample firstSample = (MemSample) memSamples.get(memSamples
+						.lastKey());
+
+				MemThread thread = firstSample.thread;
+
+				MaxMemoryItem maxMemoryItem = thread.maxMemoryItem;
+
+				SortedMap<Long, MemSample> subMap = memSamples.subMap(
+						startTime, endTime);
+
+				ArrayList<MemSample> samples = new ArrayList<MemSample>(subMap
+						.values());
+
+				MemSample floorSample = (MemSample) MemTrace
+						.getFloorEntryFromMap(startTime, memSamples);
+
+				if (floorSample != null) {
+
+					// TODO check these!
+					// MemSample firstSample = floorEntry.getValue();
+
+					if (firstSample != null) {
+						samples.add(firstSample);
+					}
+				}
+
+				for (MemSample item : samples) {
+					if (maxMemoryItem.maxChunks < item.heapSize) {
+						maxMemoryItem.maxChunks = item.heapSize;
+					}
+					if (maxMemoryItem.maxStackHeap < item.stackSize) {
+						maxMemoryItem.maxStackHeap = item.stackSize;
+					}
+					if (maxMemoryItem.maxTotal < item.heapSize + item.stackSize) {
+						maxMemoryItem.maxTotal = item.heapSize + item.stackSize;
+					}
+
+				}
+
+			}
+
+		} else {
+
+			// check that start time is not before first sample's time or end
+			// time is not before first sample time
+			long firstTime = this.drawDataByTime.get(0).getTime();
+			if ((startTime < firstTime) && (endTime < firstTime))
+				return;
+
+			MemSampleByTime memSampleByTime;
+
+			int i = 0;
+
+			// find first sample which is greater than start time
+			for (; i < this.drawDataByTime.size(); i++) {
+				memSampleByTime = this.drawDataByTime.get(i);
+				if (memSampleByTime.getTime() > startTime)
+					break;
+			}
+
+			if (i != 0)
+				--i;
+			memSampleByTime = this.drawDataByTime.get(i);
+
+			// 
+			int size = this.drawDataByTime.size();
+
+			// go thru samples and find max values for chunks and heapsandstacks
+			do {
+				ArrayList<MemSample> memSamples = memSampleByTime.getSamples();
+
+				for (int j = 0; j < memSamples.size(); j++) {
+					MemSample memSample = memSamples.get(j);
+					MemThread memThread = memSample.thread;
+					MaxMemoryItem maxMemoryItem = memThread.maxMemoryItem;
+
+					if (maxMemoryItem == null)
+						continue;
+
+					if (maxMemoryItem.maxChunks < memSample.heapSize)
+						maxMemoryItem.maxChunks = memSample.heapSize;
+					if (maxMemoryItem.maxStackHeap < memSample.stackSize)
+						maxMemoryItem.maxStackHeap = memSample.stackSize;
+					if (maxMemoryItem.maxTotal < memSample.heapSize
+							+ memSample.stackSize)
+						maxMemoryItem.maxTotal = memSample.heapSize
+								+ memSample.stackSize;
+
+					// find the maximums for all threads/processes in the
+					// interval
+					if (memSample.heapSize > traceMaxChunks)
+						intervalMaxChunks = memSample.heapSize;
+					if (memSample.stackSize > traceMaxStackHeap)
+						intervalMaxStackHeap = memSample.stackSize;
+					if (memSample.heapSize + memSample.stackSize > traceMaxTotal)
+						intervalMaxTotal = memSample.heapSize
+								+ memSample.stackSize;
+				}
+				i++;
+				if (i < size)
+					memSampleByTime = this.drawDataByTime.get(i);
+				else
+					break;
+			} while (memSampleByTime.getTime() <= endTime);
+
+		}
+
+		return;
+	}
+
+	public long getMemoryModel() {
+		return this.memoryModel;
+	}
+
+	public void setMemoryModel(long memoryModel) {
+		if (memoryModel == MemTrace.MEMORY_DIRECT
+				|| memoryModel == MemTrace.MEMORY_MOVING
+				|| memoryModel == MemTrace.MEMORY_MULTIPLE)
+			this.memoryModel = memoryModel;
+		else
+			this.memoryModel = MemTrace.MEMORY_UNKNOWN;
+	}
+
+	public static Object getFloorEntryFromMap(long key, TreeMap map) {
+		// TODO if JDK 6 is in use this should be used:
+		// return map.floorEntry(key).getValue();
+
+		// when JDK 5 in use use this:
+		try {
+			SortedMap headMap = map.headMap(key);
+			return headMap.get(headMap.lastKey());
+		} catch (Exception e) {
+			return null;
+		}
+
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemTraceGraph.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,1489 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.memory;
+
+import java.awt.Dimension;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.MouseEvent;
+import org.eclipse.draw2d.MouseMotionListener;
+import org.eclipse.draw2d.Panel;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.memory.actions.MemoryStatisticsDialog;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IContextMenu;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.internal.pi.visual.GraphComposite;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEventListener;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.ColorPalette;
+
+public class MemTraceGraph extends GenericTraceGraph implements FocusListener,
+		PIEventListener, MouseMotionListener, IContextMenu {
+	private enum UsageType {
+		CHUNKS, HEAPSTACK, CHUNKS_HEAPSTACK
+	};
+
+	private boolean dynamicMemoryVisualisation = false;
+
+	private MemThreadTable memThreadTable;
+	private CheckboxTableViewer memoryTableViewer;
+
+	Hashtable<Integer, Integer> threadList;
+
+	// 3 tabs can share the same trace, but they need different graphs
+	private MemTrace memTrace;
+
+	private FigureCanvas leftFigureCanvas;
+
+	// whether any table items are enabled
+	private boolean haveEnabled = false;
+
+	private boolean readyToDraw = false;
+	private int width = 600;
+	private int height = 400;
+
+	private final int defaultSamplingTime = 3000;
+	private int samplingTime;
+	private UsageType paintMode;
+	private int[] chunkListY;
+	private int[] stackListY;
+	private int[] chunkStackListY;
+	private int[] polyListX;
+
+	int[] stackAndHeapPoints;
+	int[] chunkPoints;
+
+	private TreeMap<Long, Integer> eventChunkListY;
+	private TreeMap<Long, Integer> eventStackListY;
+	private TreeMap<Long, Integer> eventChunkStackListY;
+
+	private int minStack = Integer.MAX_VALUE;
+	private int maxStack = 0;
+	private int minHeap = Integer.MAX_VALUE;
+	private int maxChunks = 0;
+	private int minStackHeap = Integer.MAX_VALUE;
+	private int maxStackHeap = 0;
+
+	private DecimalFormat memKBFormat = new DecimalFormat(Messages
+			.getString("MemTraceGraph.KBformat")); //$NON-NLS-1$
+	private DecimalFormat memMBFloatFormat = new DecimalFormat(Messages
+			.getString("MemTraceGraph.MBformat")); //$NON-NLS-1$
+
+	private static int xLegendHeight = 20;
+
+	private boolean firstTimeDrawThreadList = true;
+	
+	public MemTraceGraph(int graphIndex, MemTrace memTrace, int uid) {
+		super((GenericSampledTrace) memTrace);
+
+		// 
+
+		if (memTrace != null) {
+
+			// if no version number is found from trace, we can assume
+			// that sampling based memory model is in use
+			this.memTrace = memTrace;
+			if (memTrace.getVersion() == 0) {
+				memTrace.setVersion(156);
+			}
+		}
+
+		this.graphIndex = graphIndex;
+		this.memTrace = memTrace;
+		this.paintMode = UsageType.CHUNKS_HEAPSTACK;
+		this.setScale(10);
+
+		if (memTrace == null) {
+			System.out.print(Messages
+					.getString("MemTraceGraph.traceDataNotFound")); //$NON-NLS-1$
+			return;
+		}
+
+		samplingTime = calcSamplingTime();
+		memTrace.gatherDrawData();
+
+		// create the label and a tableviewer
+		Composite holder = new Composite(NpiInstanceRepository.getInstance()
+				.getProfilePage(uid, graphIndex).getBottomComposite(), SWT.NONE);
+
+		GridLayout gl = new GridLayout();
+		gl.marginHeight = 0;
+		gl.marginWidth = 0;
+		gl.marginLeft = 0;
+		gl.marginRight = 0;
+		holder.setLayout(gl);
+
+		Label label = new Label(holder, SWT.CENTER);
+		label
+				.setBackground(holder.getDisplay().getSystemColor(
+						SWT.COLOR_WHITE));
+		label.setFont(PIPageEditor.helvetica_8);
+		label.setText(Messages.getString("MemTraceGraph.graphTitle")); //$NON-NLS-1$
+		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		this.memThreadTable = new MemThreadTable(this, holder);
+		this.memoryTableViewer = this.memThreadTable.getTableViewer();
+
+		this.readyToDraw = true;
+	}
+
+	public void action(String actionString) {
+		if (actionString.equals("chunk_on")) //$NON-NLS-1$
+		{
+			paintMode = UsageType.CHUNKS;
+		} else if (actionString.equals("heapstack_on")) //$NON-NLS-1$
+		{
+			paintMode = UsageType.HEAPSTACK;
+		} else if (actionString.equals("chunk_heapstack_on")) //$NON-NLS-1$
+		{
+			paintMode = UsageType.CHUNKS_HEAPSTACK;
+		} else if (actionString.equals("rescale_on")) //$NON-NLS-1$
+		{
+			dynamicMemoryVisualisation = true;
+			makeThreadDrawLists();
+		} else if (actionString.equals("rescale_off")) //$NON-NLS-1$
+		{
+			dynamicMemoryVisualisation = false;
+			makeThreadDrawLists();
+		} else {
+			return;
+		}
+
+		this.repaint();
+		if (this.leftFigureCanvas != null)
+			this.leftFigureCanvas.redraw();
+	}
+
+	public void piEventReceived(PIEvent be) {
+		switch (be.getType()) {
+		// when the selection area changes, the maximum values shown for each
+		// thread/process
+		// may change; if dynamicMemoryVisualisation is on, we'll also have a
+		// new y-scaling factor
+		case PIEvent.SELECTION_AREA_CHANGED:
+
+			// before updating the tables, make sure that the memory trace has
+			// computing the
+			// maximum usage by each thread/process within the new time interval
+			double startTime = PIPageEditor.currentPageEditor().getStartTime();
+			double endTime = PIPageEditor.currentPageEditor().getEndTime();
+
+			memTrace.setMaxMemDataByInterval((int) (startTime * 1000),
+					(int) (endTime * 1000));
+
+			// send this message to the 2 other graphs
+			PIEvent be2 = new PIEvent(be.getValueObject(),
+					PIEvent.SELECTION_AREA_CHANGED2);
+
+			for (int i = 0; i < 3; i++) {
+				MemTraceGraph graph = (MemTraceGraph) memTrace.getTraceGraph(i);
+
+				if (graph != this) {
+					graph.piEventReceived(be2);
+				}
+			}
+
+			be = be2;
+
+			// FALL THROUGH
+		case PIEvent.SELECTION_AREA_CHANGED2:
+			double[] values = (double[]) be.getValueObject();
+			this.setSelectionStart(values[0]);
+			this.setSelectionEnd(values[1]);
+			this.memThreadTable.piEventReceived(be);
+			this.repaint();
+			break;
+
+		case PIEvent.CHANGED_MEMORY_TABLE:
+			this.makeThreadDrawLists();
+			this.repaint();
+			if (this.leftFigureCanvas != null)
+				this.leftFigureCanvas.redraw();
+			break;
+
+		case PIEvent.SCALE_CHANGED:
+			double scale = ((Double) be.getValueObject()).doubleValue();
+			this.setScale(scale);
+			this.repaint();
+			break;
+
+		case PIEvent.SCROLLED:
+			Event event = ((Event) be.getValueObject());
+			this.parentComponent.setScrolledOrigin(event.x, event.y);
+			this.repaint();
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	public void focusGained(FocusEvent fe) {
+	}
+
+	public void focusLost(FocusEvent fe) {
+	}
+
+	public void paint(Panel panel, Graphics graphics) {
+		if (!readyToDraw)
+			return;
+
+		this.setSize(this.getSize().width, getVisualSize().height);
+		this.makeThreadDrawLists();
+		this.paintThreads(graphics);
+		this.drawDottedLineBackground(graphics, MemTraceGraph.xLegendHeight);
+
+		// draw the same selection as the Address/Thread trace
+		this.drawSelectionSection(graphics, MemTraceGraph.xLegendHeight);
+	}
+
+	private void paintSampledChunks(Graphics graphics) {
+		if (chunkListY == null)
+			return;
+
+		int[] points = new int[chunkListY.length * 2];
+
+		for (int i = 0, j = 0; i < chunkListY.length; i++) {
+			points[j++] = polyListX[i];
+			points[j++] = chunkListY[i];
+		}
+
+		graphics.setBackgroundColor(ColorConstants.orange);
+		graphics.fillPolygon(points);
+		graphics.setBackgroundColor(ColorConstants.gray);
+	}
+
+	private void paintEventBasedChunks(Graphics graphics) {
+		/*
+		 * if (chunkListY == null) return;
+		 */
+
+		/*
+		 * int[] points = new int[chunkListY.length * 2];
+		 * 
+		 * for (int i = 0, j =0; i < chunkListY.length; i++) { points[j++] =
+		 * polyListX[i]; points[j++] = chunkListY[i]; }
+		 */
+
+		graphics.setBackgroundColor(ColorConstants.orange);
+		graphics.fillPolygon(chunkPoints);
+		graphics.setBackgroundColor(ColorConstants.gray);
+	}
+
+	private void paintSampledStack(Graphics graphics, UsageType paintMode) {
+		if (stackListY == null)
+			return;
+
+		// if needed, move every y-value that is 0 down a little so that the
+		// line is more visible
+		boolean increase0 = paintMode != UsageType.HEAPSTACK;
+
+		int[] points = new int[stackListY.length * 2];
+
+		for (int i = 0, j = 0; i < stackListY.length; i++) {
+			points[j++] = polyListX[i];
+			points[j] = stackListY[i];
+
+			if (increase0 && (points[j] == 0))
+				points[j] = 1;
+
+			j++;
+		}
+
+		if (paintMode == UsageType.HEAPSTACK) {
+			graphics.setBackgroundColor(ColorConstants.blue);
+			graphics.fillPolygon(points);
+			graphics.setBackgroundColor(ColorConstants.gray);
+		} else {
+			int lineWidth = graphics.getLineWidth();
+			Color color = graphics.getForegroundColor();
+
+			graphics.setForegroundColor(ColorConstants.blue);
+			graphics.setLineWidth(2);
+			graphics.drawPolyline(points);
+			graphics.setForegroundColor(color);
+			graphics.setLineWidth(lineWidth);
+		}
+	}
+
+	private void paintEventBasedStack(Graphics graphics, UsageType paintMode) {
+		if (eventStackListY == null)
+			return;
+
+		// if needed, move every y-value that is 0 down a little so that the
+		// line is more visible
+		boolean increase0 = paintMode != UsageType.HEAPSTACK;
+
+		/*
+		 * int[] points = new int[stackListY.length * 2];
+		 * 
+		 * for (int i = 0, j =0; i < stackListY.length; i++) { points[j++] =
+		 * polyListX[i]; points[j] = stackListY[i];
+		 * 
+		 * if (increase0 && (points[j] == 0)) points[j] = 1;
+		 * 
+		 * j++; }
+		 */
+
+		if (paintMode == UsageType.HEAPSTACK) {
+			graphics.setBackgroundColor(ColorConstants.blue);
+			graphics.fillPolygon(stackAndHeapPoints);
+			graphics.setBackgroundColor(ColorConstants.gray);
+		} else {
+			int lineWidth = graphics.getLineWidth();
+			Color color = graphics.getForegroundColor();
+
+			graphics.setForegroundColor(ColorConstants.blue);
+			graphics.setLineWidth(2);
+			graphics.drawPolyline(stackAndHeapPoints);
+			graphics.setForegroundColor(color);
+			graphics.setLineWidth(lineWidth);
+		}
+	}
+
+	private void paintThreads(Graphics graphics) {
+		if (memTrace.getVersion() >= 202) {
+			paintEventBasedThreads(graphics);
+		} else {
+			paintSampledThreads(graphics);
+		}
+	}
+
+	private void paintSampledThreads(Graphics graphics) {
+		// if there are no threads to draw
+		if (!haveEnabled)
+			return;
+
+		int maxBytes = 0;
+
+		double multiplier;
+
+		if (paintMode == UsageType.CHUNKS && chunkListY != null) {
+			if (dynamicMemoryVisualisation)
+				maxBytes = maxChunks;
+			else
+				maxBytes = memTrace.getTraceMaxChunks();
+
+			// multiplier is bytes / pixel in the graph
+			if (true)// !dynamicMemoryVisualisation)
+				multiplier = prettyMaxBytes(maxBytes) / height;
+			else
+				multiplier = maxBytes / height;
+			// System.out.println("maxBytes " + maxBytes + " multiplier " +
+			// multiplier + " height " + height);
+
+			for (int j = 1; j < chunkListY.length - 1; j++) {
+				chunkListY[j] = (int) (height - chunkListY[j] / multiplier);
+
+				if (chunkListY[j] < 0)
+					chunkListY[j] = 0;
+			}
+
+			this.paintSampledChunks(graphics);
+		} else if (paintMode == UsageType.HEAPSTACK && stackListY != null) {
+			if (dynamicMemoryVisualisation)
+				maxBytes = maxStack;
+			else
+				maxBytes = memTrace.getTraceMaxStackHeap();
+
+			// multiplier is bytes / pixel in the final graph
+			if (true)// !dynamicMemoryVisualisation)
+				multiplier = prettyMaxBytes(maxBytes) / height;
+			else
+				multiplier = maxBytes / height;
+			// System.out.println("maxBytes " + maxBytes + " multiplier " +
+			// multiplier + " height " + height);
+
+			for (int j = 1; j < stackListY.length - 1; j++) {
+				stackListY[j] = (int) (height - stackListY[j] / multiplier);
+
+				if (stackListY[j] < 0)
+					stackListY[j] = 0;
+			}
+
+			this.paintSampledStack(graphics, paintMode);
+		} else if (chunkStackListY != null) // heap and stack
+		{
+			if (dynamicMemoryVisualisation)
+				maxBytes = maxChunks > maxStack ? maxChunks : maxStack;
+			else
+				maxBytes = memTrace.getTraceMaxChunks() > memTrace
+						.getTraceMaxStackHeap() ? memTrace.getTraceMaxChunks()
+						: memTrace.getTraceMaxStackHeap();
+
+			// multiplier is bytes / pixel in the final graph
+			if (true)// !dynamicMemoryVisualisation)
+				multiplier = prettyMaxBytes(maxBytes) / height;
+			else
+				multiplier = maxBytes / height;
+			// System.out.println("maxBytes " + maxBytes + " multiplier " +
+			// multiplier + " height " + height);
+
+			int totalStackUsed = 0;
+
+			for (int j = 1; j < chunkListY.length - 1; j++) {
+				totalStackUsed += stackListY[j];
+
+				chunkListY[j] = (int) (height - chunkListY[j] / multiplier);
+				stackListY[j] = (int) (height - stackListY[j] / multiplier);
+
+				if (stackListY[j] < 0)
+					stackListY[j] = 0;
+
+				if (chunkListY[j] < 0)
+					chunkListY[j] = 0;
+			}
+
+			this.paintSampledChunks(graphics);
+			if (totalStackUsed > 0)
+				this.paintSampledStack(graphics, paintMode);
+		}
+	}
+
+	private void paintEventBasedThreads(Graphics graphics) {
+		// paints treads when using event based memory model
+
+		// if there are no threads to draw
+		if (!haveEnabled)
+			return;
+
+		int maxBytes = 0;
+
+		double yMultiplier;
+		double xMultiplier;
+		xMultiplier = this.getScale();
+
+		// get las x coordinate of trace
+		long lastEvent = ((MemSample) memTrace.samples.get(memTrace.samples
+				.size() - 1)).sampleSynchTime;
+		int lastXCoord = (int) (lastEvent / xMultiplier);
+
+		if (paintMode == UsageType.CHUNKS && eventChunkListY != null) {
+			chunkPoints = new int[eventChunkListY.size() * 4 + 6];
+
+			if (dynamicMemoryVisualisation)
+				maxBytes = maxChunks;
+			else
+				maxBytes = memTrace.getTraceMaxChunks();
+
+			// multiplier is bytes / pixel in the graph
+			if (true)// !dynamicMemoryVisualisation)
+				yMultiplier = prettyMaxBytes(maxBytes) / height;
+			else
+				yMultiplier = maxBytes / height;
+			// System.out.println("maxBytes " + maxBytes + " multiplier " +
+			// multiplier + " height " + height);
+
+			createGraphPolygon(this.eventChunkListY, chunkPoints, xMultiplier,
+					yMultiplier, lastXCoord);
+
+			this.paintEventBasedChunks(graphics);
+		} else if (paintMode == UsageType.HEAPSTACK && eventStackListY != null) {
+			stackAndHeapPoints = new int[eventStackListY.size() * 4 + 6];
+
+			if (dynamicMemoryVisualisation)
+				maxBytes = maxStack;
+			else
+				maxBytes = memTrace.getTraceMaxStackHeap();
+
+			// multiplier is bytes / pixel in the final graph
+			if (true)// !dynamicMemoryVisualisation)
+				yMultiplier = prettyMaxBytes(maxBytes) / height;
+			else
+				yMultiplier = (double) maxBytes / height;
+
+			createGraphPolygon(this.eventStackListY, stackAndHeapPoints,
+					xMultiplier, yMultiplier, lastXCoord);
+			this.paintEventBasedStack(graphics, paintMode);
+		} else if (eventChunkStackListY != null) // heap and stack
+		{
+			stackAndHeapPoints = new int[eventStackListY.size() * 4 + 6];
+			chunkPoints = new int[eventChunkListY.size() * 4 + 6];
+
+			if (dynamicMemoryVisualisation)
+				maxBytes = maxChunks > maxStack ? maxChunks : maxStack;
+			else
+				maxBytes = memTrace.getTraceMaxChunks() > memTrace
+						.getTraceMaxStackHeap() ? memTrace.getTraceMaxChunks()
+						: memTrace.getTraceMaxStackHeap();
+
+			// multiplier is bytes / pixel in the final graph
+			if (true)// !dynamicMemoryVisualisation)
+				yMultiplier = prettyMaxBytes(maxBytes) / height;
+			else
+				yMultiplier = maxBytes / height;
+			// System.out.println("maxBytes " + maxBytes + " multiplier " +
+			// multiplier + " height " + height);
+
+			int totalStackUsed = 1;
+
+			createGraphPolygon(this.eventStackListY, stackAndHeapPoints,
+					xMultiplier, yMultiplier, lastXCoord);
+			createGraphPolygon(this.eventChunkListY, chunkPoints, xMultiplier,
+					yMultiplier, lastXCoord);
+
+			this.paintEventBasedChunks(graphics);
+			if (totalStackUsed > 0)
+				this.paintEventBasedStack(graphics, paintMode);
+		}
+	}
+
+	public void createGraphPolygon(TreeMap<Long, Integer> map, int[] points,
+			double xMultiplier, double yMultiplier, int endXCoord) {
+		// Creates graph polygon from TreeMap that contains all x and y values
+		// of one graph.
+
+		int index = 2;
+		int xCoord = 0;
+		int yCoord = 0;
+		int previousYCoord = 0;
+
+		// get first event and key from map.
+		Iterator<Long> keys = map.keySet().iterator();
+		Iterator<Integer> values = map.values().iterator();
+		
+	
+		int previousXCoord = 0;
+		int countOfSameXCoords = 1;
+
+		// set first into zero so that polygon is drawn correctly
+		points[0] = 0;
+		points[1] = height;
+
+		while (keys.hasNext()) {
+			// create polygon's points so that each memory allocation is drawn
+			// as one leap in graph
+
+			// calculate new x coord's value and round it to integer
+			xCoord = (int) (((double) keys.next() / xMultiplier) + 0.5);
+
+			// calculate new y-coord's value and round it to integer
+			yCoord = (int) (((double) height - (double) values.next() / yMultiplier) + 0.5);
+
+			if (xCoord == previousXCoord && index > 3) {
+				// if more than one sample at one point in the screen, count
+				// average value
+				// for y coordinate
+
+				// count average value
+				double sum = ((double) yCoord + (double) previousYCoord
+						* (double) countOfSameXCoords);
+				countOfSameXCoords++;
+				yCoord = (int) (sum / (double) (countOfSameXCoords));
+
+				// add average coordinate to array
+				index = index - 4;
+				index = addCoordsToGraphArray(xCoord, yCoord, index, points);
+
+			} else {
+				countOfSameXCoords = 1;
+			}
+
+			index = addCoordsToGraphArray(xCoord, yCoord, index, points);
+
+			// save coordinates to previousValues
+			previousYCoord = yCoord;
+			previousXCoord = xCoord;
+		}
+
+		// Set last coordinates to zero so that polygon is drawn correctly
+		points[points.length - 4] = endXCoord;
+		points[points.length - 3] = points[points.length - 5];
+
+		points[points.length - 2] = endXCoord;
+		points[points.length - 1] = height;
+	}
+
+	private int addCoordsToGraphArray(int xCoord, int yCoord, int arrayIndex,
+			int[] array) {
+
+		// adds coordinates to array so that polygon can be drawn from that
+		// array
+
+		// instead of straight lines between points, we draw graph more
+		// realistically
+		// so that single memory events are shown as a leap in graph.
+
+		// first x coordinate
+		array[arrayIndex] = xCoord;
+		arrayIndex++;
+
+		// first y coordinate, if possible use same y-coord than previous value
+		if ((arrayIndex - 2) < 0) {
+			array[arrayIndex] = 0;
+		} else {
+			array[arrayIndex] = array[arrayIndex - 2];
+		}
+		arrayIndex++;
+
+		// second x coordinate
+		array[arrayIndex] = xCoord;
+		arrayIndex++;
+
+		// second y coordinate
+		array[arrayIndex] = yCoord;
+		arrayIndex++;
+
+		return arrayIndex;
+	}
+
+	private void makeThreadDrawLists() {
+		if (memTrace.getVersion() >= 202) {
+			makeEventBasedThreadDrawLists();
+		} else {
+			makeSamplingBasedThreadDrawLists();
+		}
+	}
+
+	private void makeEventBasedThreadDrawLists() {
+
+		// Get checked table items
+		Object[] checked = this.memoryTableViewer.getCheckedElements();
+
+		// if no items is checked do nothing
+		haveEnabled = (checked != null) && (checked.length > 0);
+		if (!haveEnabled) {
+			this.eventChunkListY = null;
+			this.eventStackListY = null;
+			this.eventChunkStackListY = null;
+			return;
+		}
+
+		// create maps for events for chunks, stacks and chunksandstacks
+		this.eventChunkListY = new TreeMap<Long, Integer>();
+		this.eventStackListY = new TreeMap<Long, Integer>();
+		this.eventChunkStackListY = new TreeMap<Long, Integer>();
+
+		// go thru checked items
+		for (int j = 0; j < checked.length; j++) {
+			// check that item is instance of memory thread
+			if (!(checked[j] instanceof MemThread))
+				continue;
+
+			MemThread memThread = (MemThread) checked[j];
+
+			// get all samples of the thread
+			TreeMap<Long, MemSample> memSamples = memTrace
+					.getDrawDataByMemThread(memThread);
+
+			// ensure that thread has samples
+			if ((memSamples == null) || (memSamples.size() == 0)) {
+				System.out
+						.println(Messages
+								.getString("MemTraceGraph.threadProcessNoSamples1") + memThread.fullName + Messages.getString("MemTraceGraph.threadProcessNoSamples")); //$NON-NLS-1$ //$NON-NLS-2$
+				continue;
+			}
+
+			// create empty sample
+			MemSample previousSample = new MemSample(new MemThread(0, "", ""),
+					0, 0, 0);
+
+			Iterator<MemSample> values = memSamples.values().iterator();
+
+			while (values.hasNext()) {
+				MemSample memSample = values.next(); 
+				// go thru samples from single threas
+				// save changes after last received sample into TreeMaps
+				addEventToTreeMap(this.eventStackListY,
+						memSample.sampleSynchTime, memSample.stackSize
+								- previousSample.stackSize);
+				addEventToTreeMap(this.eventChunkListY,
+						memSample.sampleSynchTime, memSample.heapSize
+								- previousSample.heapSize);
+				addEventToTreeMap(
+						this.eventChunkStackListY,
+						memSample.sampleSynchTime,
+						memSample.heapSize
+								+ memSample.stackSize
+								- (previousSample.stackSize + previousSample.heapSize));
+
+				previousSample = memSample;
+
+			}
+		}
+
+		// calculate max values and values in each event
+		this.maxStack = calculateValuesInEachEvent(eventStackListY);
+		this.maxStackHeap = calculateValuesInEachEvent(eventChunkStackListY);
+		this.maxChunks = calculateValuesInEachEvent(eventChunkListY);
+
+		if (this.memTrace.getTraceMaxChunks() == 0) {
+			this.memTrace.setTraceMaxChunks(maxChunks);
+			this.memTrace.setTraceMaxStackHeap(maxStack);
+			this.memTrace.setTraceMaxTotal(maxStackHeap);
+			
+			//repaint left legend if this is first time that tread lists are made
+			if(firstTimeDrawThreadList){
+				this.parentComponent.paintLeftLegend();
+				firstTimeDrawThreadList = false;
+			}
+
+		}
+
+	}
+
+	private int calculateValuesInEachEvent(TreeMap<Long, Integer> map) {
+		// this function calculates total sum memory in each event based
+		// on the change map it receives as a parameter
+
+		// function also returns maximum value in whole map
+
+		int maxValue = 0;
+		int previousValue = 0;
+
+		Iterator<Integer> values = map.values().iterator();
+		Iterator<Long> keys = map.keySet().iterator();
+
+		while (values.hasNext()) {
+			
+			int memValue = values.next();
+			long memKey = keys.next();
+			
+			// go thru array and count actual state of
+			// memory in each event
+			int value = previousValue + memValue;
+
+			// is value is greater that max value save
+			// it as max value
+			if (value > maxValue) {
+				maxValue = value;
+			}
+
+			map.put(memKey, value);
+			previousValue = value;
+		}
+		return maxValue;
+	}
+
+	private void addEventToTreeMap(TreeMap<Long, Integer> map, long key,
+			int item) {
+		// Adds event into tree map.
+		// If event with that same key(time code) already exists values are
+		// added.
+
+		int previousValue = 0;
+		if (map.containsKey(key)) {
+			previousValue = map.get(key);
+		}
+
+		map.put(key, previousValue + item);
+	}
+
+	private void makeSamplingBasedThreadDrawLists() {
+
+		// Get checked table items
+		Object[] checked = this.memoryTableViewer.getCheckedElements();
+
+		haveEnabled = (checked != null) && (checked.length > 0);
+
+		// is no items are checked do nothing
+		if (!haveEnabled) {
+			this.chunkListY = null;
+			this.stackListY = null;
+			this.chunkStackListY = null;
+			calculateMinAndMaxValues();
+			return;
+		}
+
+		// Get first and last sample from trace
+		int firstSample = memTrace.getFirstSampleNumber();
+		int lastSample = memTrace.getLastSampleNumber();
+
+		// Get number of sampling points
+		int samplesTotal = (int) 1 + (lastSample - firstSample) / samplingTime;
+
+		// create arrays for y axis values of chunks, stacks chunksandstacks +
+		// polylistx
+		this.chunkListY = new int[samplesTotal * 2 + 1];
+		this.stackListY = new int[samplesTotal * 2 + 1];
+		this.chunkStackListY = new int[samplesTotal * 2 + 1];
+		this.polyListX = new int[samplesTotal * 2 + 1];
+
+		// go thru checked items
+		for (int j = 0; j < checked.length; j++) {
+			// check that item is instance of memory thread
+			if (!(checked[j] instanceof MemThread))
+				continue;
+
+			MemThread memThread = (MemThread) checked[j];
+
+			// get all samples of the thread
+			TreeMap<Long, MemSample> memSamples = memTrace
+					.getDrawDataByMemThread(memThread);
+
+			// ensure that thread has samples
+			if ((memSamples == null) || (memSamples.size() == 0)) {
+				System.out
+						.println(Messages
+								.getString("MemTraceGraph.threadProcessNoSamples1") + memThread.fullName + Messages.getString("MemTraceGraph.threadProcessNoSamples")); //$NON-NLS-1$ //$NON-NLS-2$
+				continue;
+			}
+
+			int sampleCount = memSamples.size();
+			int[] tempListX = new int[sampleCount * 2 + 1];
+
+			int counter = 0;
+
+			Iterator<MemSample> values = memSamples.values().iterator();
+			while (values.hasNext()) {
+				MemSample memSample = values.next();
+				// get index where sample is located at x-axis
+				int index = (int) ((memSample.sampleSynchTime - firstSample) / samplingTime) * 2 + 1;
+
+				tempListX[counter + 1] = (int) (memSample.sampleSynchTime / getScale());
+
+				// add samples value to chunks, stacks chunksandstacks arrays
+				this.stackListY[index] += memSample.stackSize;
+				this.chunkListY[index] += memSample.heapSize;
+				this.chunkStackListY[index] += memSample.heapSize
+						+ memSample.stackSize;
+
+				counter++;
+				tempListX[counter + 1] = (int) ((memSample.sampleSynchTime + samplingTime) / getScale());
+
+				index++;
+				if (this.paintMode == UsageType.CHUNKS) {
+					this.chunkListY[index] += memSample.heapSize;
+					counter++;
+				} else if (this.paintMode == UsageType.HEAPSTACK) {
+					this.stackListY[index] += memSample.stackSize;
+					counter++;
+				} else // paint mode chunk and stack
+				{
+					this.stackListY[index] += memSample.stackSize;
+					this.chunkListY[index] += memSample.heapSize;
+					this.chunkStackListY[index] += memSample.heapSize
+							+ memSample.stackSize;
+					counter++;
+				}
+				
+			}
+
+			// tempListX[0] = (int)
+			// (((MemSample)memSamples.firstEntry().getValue()).sampleSynchTime
+			// / getScale());
+			MemSample firstMemSample = (MemSample)memSamples.get(memSamples.firstKey());
+			tempListX[0] = (int) ((firstMemSample.sampleSynchTime / getScale()));
+			tempListX[tempListX.length - 1] = tempListX[tempListX.length - 2];
+
+			// defaults the originating and ending points into window corners
+			this.stackListY[0] = height;
+			this.stackListY[stackListY.length - 1] = height;
+			this.chunkListY[0] = height;
+			this.chunkListY[chunkListY.length - 1] = height;
+			this.chunkStackListY[0] = height;
+			this.chunkStackListY[chunkStackListY.length - 1] = height;
+		}
+
+		calculatePolylistX();
+		calculateMinAndMaxValues();
+	}
+
+	private void calculateMinAndMaxValues() {
+		// find heapValue;
+		minHeap = Integer.MAX_VALUE;
+		maxChunks = 0;
+
+		if (chunkListY != null) {
+			for (int i = 1; i < chunkListY.length - 1; i++) {
+				if (chunkListY[i] < minHeap)
+					minHeap = chunkListY[i];
+				if (chunkListY[i] > maxChunks)
+					maxChunks = chunkListY[i];
+			}
+		}
+
+		// find stackValue;
+		minStack = Integer.MAX_VALUE;
+		maxStack = 0;
+
+		if (stackListY != null) {
+			for (int i = 1; i < stackListY.length - 1; i++) {
+				if (stackListY[i] < minStack)
+					minStack = stackListY[i];
+				if (stackListY[i] > maxStack)
+					maxStack = stackListY[i];
+			}
+		}
+
+		// find stackValue+HeapValue;
+		minStackHeap = Integer.MAX_VALUE;
+		maxStackHeap = 0;
+
+		if (stackListY != null && chunkListY != null) {
+			for (int i = 1; i < stackListY.length - 1; i++) {
+				if ((stackListY[i] + chunkListY[i]) < minStackHeap)
+					minStackHeap = stackListY[i] + chunkListY[i];
+
+				if ((stackListY[i] + chunkListY[i]) > maxStackHeap)
+					maxStackHeap = stackListY[i] + chunkListY[i];
+			}
+		}
+	}
+
+	private void calculatePolylistX() {
+		int currentSample = memTrace.getFirstSampleNumber();
+		int lastSample = memTrace.getLastSampleNumber();
+		int sampleCount = (int) 1 + (lastSample - currentSample) / samplingTime;
+
+		polyListX = new int[sampleCount * 2 + 1];
+
+		int i = 0;
+
+		for (Enumeration e = memTrace.getSamples(); e.hasMoreElements();) {
+			MemSample ms = (MemSample) e.nextElement();
+			if ((int) ms.sampleSynchTime != currentSample) {
+				i++;
+				currentSample = (int) ms.sampleSynchTime;
+				polyListX[i + 1] = (int) (ms.sampleSynchTime / getScale());
+				i++;
+				polyListX[i + 1] = polyListX[i];
+			}
+		}
+
+		polyListX[0] = (int) (memTrace.getFirstSampleNumber() / getScale());
+		polyListX[1] = (int) (memTrace.getFirstSampleNumber() / getScale());
+		polyListX[polyListX.length - 1] = polyListX[polyListX.length - 2];
+	}
+
+	public void setSize(int x, int y) {
+		this.width = x;
+		this.height = y - MemTraceGraph.xLegendHeight;
+
+		if (this.height <= 0)
+			this.height = 1;
+	}
+
+	public Dimension getSize() {
+		return new Dimension(width, height);
+	}
+
+	private int calcSamplingTime() {
+		long time = memTrace.getFirstSampleNumber();
+		for (Enumeration e = memTrace.getSamples(); e.hasMoreElements();) {
+			MemSample tmp = (MemSample) e.nextElement();
+			if (tmp.sampleSynchTime != time) {
+				time = tmp.sampleSynchTime - time;
+				return (int) time;
+			}
+		}
+		return defaultSamplingTime;
+	}
+
+	public void refreshDataFromTrace() {
+	}
+
+	public void repaint() {
+		this.parentComponent.repaintComponent();
+	}
+
+	public int getSamplingTime() {
+		return samplingTime;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @seecom.nokia.carbide.cpp.internal.pi.plugin.model.IContextMenu#
+	 * addContextMenuItems(org.eclipse.swt.widgets.Menu,
+	 * org.eclipse.swt.events.MouseEvent)
+	 */
+	public void addContextMenuItems(Menu menu,
+			org.eclipse.swt.events.MouseEvent me) {
+		new MenuItem(menu, SWT.SEPARATOR);
+
+		MenuItem memoryStatsItem = new MenuItem(menu, SWT.PUSH);
+		memoryStatsItem.setText(Messages.getString("MemoryPlugin.memoryStats")); //$NON-NLS-1$
+		memoryStatsItem.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				new MemoryStatisticsDialog(Display.getCurrent());
+			}
+		});
+
+		new MenuItem(menu, SWT.SEPARATOR);
+
+		boolean showChunk = true;
+		boolean showHeapStack = true;
+
+		Object obj;
+		// if there is a showChunk value associated with the current Analyser
+		// tab, then use it
+		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState(
+				"com.nokia.carbide.cpp.pi.memory.showChunk"); //$NON-NLS-1$
+		if ((obj != null) && (obj instanceof Boolean))
+			// retrieve the current value
+			showChunk = (Boolean) obj;
+		else
+			// set the initial value
+			NpiInstanceRepository.getInstance().activeUidSetPersistState(
+					"com.nokia.carbide.cpp.pi.memory.showChunk", showChunk); //$NON-NLS-1$
+
+		// if there is a showHeapStack value associated with the current
+		// Analyser tab, then use it
+		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState(
+				"com.nokia.carbide.cpp.pi.memory.showHeapStack"); //$NON-NLS-1$
+		if ((obj != null) && (obj instanceof Boolean))
+			// retrieve the current value
+			showHeapStack = (Boolean) obj;
+		else
+			// set the initial value
+			NpiInstanceRepository
+					.getInstance()
+					.activeUidSetPersistState(
+							"com.nokia.carbide.cpp.pi.memory.showHeapStack", showHeapStack); //$NON-NLS-1$
+
+		MenuItem showChunkItem = new MenuItem(menu, SWT.RADIO);
+		showChunkItem.setText(Messages.getString("MemoryPlugin.showChunks")); //$NON-NLS-1$
+		showChunkItem.setSelection(showChunk && !showHeapStack);
+		showChunkItem.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				NpiInstanceRepository.getInstance().activeUidSetPersistState(
+						"com.nokia.carbide.cpp.pi.memory.showChunk", true); //$NON-NLS-1$
+				NpiInstanceRepository.getInstance().activeUidSetPersistState(
+						"com.nokia.carbide.cpp.pi.memory.showHeapStack", false); //$NON-NLS-1$
+
+				for (int i = 0; i < 3; i++) {
+					MemTraceGraph graph = (MemTraceGraph) memTrace
+							.getTraceGraph(i);
+					graph.action("chunk_on"); //$NON-NLS-1$
+				}
+			}
+		});
+
+		MenuItem showHeapItem = new MenuItem(menu, SWT.RADIO);
+		showHeapItem.setText(Messages.getString("MemoryPlugin.showHeapStack")); //$NON-NLS-1$
+		showHeapItem.setSelection(showHeapStack && !showChunk);
+		showHeapItem.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				NpiInstanceRepository.getInstance().activeUidSetPersistState(
+						"com.nokia.carbide.cpp.pi.memory.showChunk", false); //$NON-NLS-1$
+				NpiInstanceRepository.getInstance().activeUidSetPersistState(
+						"com.nokia.carbide.cpp.pi.memory.showHeapStack", true); //$NON-NLS-1$
+
+				for (int i = 0; i < 3; i++) {
+					MemTraceGraph graph = (MemTraceGraph) memTrace
+							.getTraceGraph(i);
+					graph.action("heapstack_on"); //$NON-NLS-1$
+				}
+			}
+		});
+
+		MenuItem showBothItem = new MenuItem(menu, SWT.RADIO);
+		showBothItem.setText(Messages.getString("MemoryPlugin.showAll")); //$NON-NLS-1$
+		showBothItem.setSelection(showChunk && showHeapStack);
+		showBothItem.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				NpiInstanceRepository.getInstance().activeUidSetPersistState(
+						"com.nokia.carbide.cpp.pi.memory.showChunk", true); //$NON-NLS-1$
+				NpiInstanceRepository.getInstance().activeUidSetPersistState(
+						"com.nokia.carbide.cpp.pi.memory.showHeapStack", true); //$NON-NLS-1$
+
+				for (int i = 0; i < 3; i++) {
+					MemTraceGraph graph = (MemTraceGraph) memTrace
+							.getTraceGraph(i);
+					graph.action("chunk_heapstack_on"); //$NON-NLS-1$
+				}
+			}
+		});
+
+		new MenuItem(menu, SWT.SEPARATOR);
+
+		boolean rescale = false;
+
+		// if there is a rescale value associated with the current Analyser tab,
+		// then use it
+		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState(
+				"com.nokia.carbide.cpp.pi.memory.rescale"); //$NON-NLS-1$
+		if ((obj != null) && (obj instanceof Boolean))
+			// retrieve the current value
+			rescale = (Boolean) obj;
+		else
+			// set the initial value
+			NpiInstanceRepository.getInstance().activeUidSetPersistState(
+					"com.nokia.carbide.cpp.pi.memory.rescale", rescale); //$NON-NLS-1$
+
+		final boolean rescaleFinal = rescale;
+
+		MenuItem rescaleItem = new MenuItem(menu, SWT.CHECK);
+		rescaleItem.setText(Messages.getString("MemoryPlugin.dynamicRescale")); //$NON-NLS-1$
+		rescaleItem.setSelection(rescale);
+		rescaleItem.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				String action;
+				NpiInstanceRepository
+						.getInstance()
+						.activeUidSetPersistState(
+								"com.nokia.carbide.cpp.pi.memory.rescale", !rescaleFinal); //$NON-NLS-1$
+				if (!rescaleFinal) {
+					action = "rescale_on"; //$NON-NLS-1$
+				} else {
+					action = "rescale_off"; //$NON-NLS-1$
+				}
+
+				for (int i = 0; i < 3; i++) {
+					MemTraceGraph graph = (MemTraceGraph) memTrace
+							.getTraceGraph(i);
+					graph.action(action);
+				}
+			}
+		});
+	}
+
+	public void paintLeftLegend(FigureCanvas figureCanvas, GC gc) {
+		// System.out.println("MEM"); if (true)return;
+		// if there are no threads to draw
+		GC localGC = gc;
+
+		if (gc == null)
+			gc = new GC(PIPageEditor.currentPageEditor().getSite().getShell());
+
+		if (this.leftFigureCanvas == null)
+			this.leftFigureCanvas = figureCanvas;
+
+		Rectangle rect = ((GraphComposite) figureCanvas.getParent()).figureCanvas
+				.getClientArea();
+
+		double visY = rect.height - MemTraceGraph.xLegendHeight;
+
+		gc.setForeground(ColorPalette.getColor(new RGB(100, 100, 100)));
+		gc.setBackground(ColorPalette.getColor(new RGB(255, 255, 255)));
+
+		int maxBytes = 0;
+
+		if (paintMode == UsageType.CHUNKS) {
+			if (dynamicMemoryVisualisation)
+				maxBytes = maxChunks;
+			else
+				maxBytes = memTrace.getTraceMaxChunks();
+		} else if (paintMode == UsageType.HEAPSTACK) {
+			if (dynamicMemoryVisualisation)
+				maxBytes = maxStack;
+			else
+				maxBytes = memTrace.getTraceMaxStackHeap();
+		} else {
+			if (dynamicMemoryVisualisation)
+				maxBytes = maxChunks > maxStack ? maxChunks : maxStack;
+			else
+				maxBytes = memTrace.getTraceMaxChunks() > memTrace
+						.getTraceMaxStackHeap() ? memTrace.getTraceMaxChunks()
+						: memTrace.getTraceMaxStackHeap();
+		}
+
+		double multiplier = 0;
+
+		if (true)// !dynamicMemoryVisualisation)
+			multiplier = prettyMaxBytes(maxBytes) / visY;
+		else
+			multiplier = maxBytes / visY;
+
+		int previousBottom = 0; // bottom of the previous legend drawn
+		String legend;
+		double yIncrement = visY / 10;
+
+		// draw 11 value indicators (0..10) to the scale
+		for (int k = 10; k >= 0; k--) {
+			// location for the value indicator is k * 1/10 the height of the
+			// display
+			int y = (int) (visY - (yIncrement * k));
+
+			// calculate the exact byte value at the height by multiplying
+			// the height with the [bytes / pixel] value
+			int bytes = (int) ((visY * multiplier) / 10.0) * k;
+
+			// construct the text for each scale
+			legend = ""; //$NON-NLS-1$
+
+			// if the amount of data is less than 512KB, draw it as bytes
+			if (maxBytes < 10000) {
+				legend += bytes + Messages.getString("MemTraceGraph.byByte"); //$NON-NLS-1$
+			}
+			// if the amount is more than 512KB, draw it as KB
+			else if (maxBytes <= 500 * 1024) {
+				legend += (bytes / 1024)
+						+ Messages.getString("MemTraceGraph.byKB"); //$NON-NLS-1$
+			} else {
+				legend += memMBFloatFormat
+						.format(((float) bytes / (1024 * 1024)))
+						+ Messages.getString("MemTraceGraph.byMB"); //$NON-NLS-1$
+			}
+
+			Point extent = gc.stringExtent(legend);
+
+			gc.drawLine(GenericTraceGraph.yLegendWidth - 3, (int) y + 1,
+					GenericTraceGraph.yLegendWidth, (int) y + 1);
+
+			if (y >= previousBottom) {
+				gc.drawString(legend, GenericTraceGraph.yLegendWidth - extent.x
+						- 4, (int) y);
+				previousBottom = (int) y + extent.y;
+			}
+		}
+
+		if (localGC == null) {
+			gc.dispose();
+			figureCanvas.redraw();
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.draw2d.MouseMotionListener#mouseDragged(org.eclipse.draw2d
+	 * .MouseEvent)
+	 */
+	public void mouseDragged(MouseEvent me) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.draw2d.MouseMotionListener#mouseEntered(org.eclipse.draw2d
+	 * .MouseEvent)
+	 */
+	public void mouseEntered(MouseEvent me) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.draw2d.MouseMotionListener#mouseExited(org.eclipse.draw2d
+	 * .MouseEvent)
+	 */
+	public void mouseExited(MouseEvent me) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.draw2d.MouseMotionListener#mouseHover(org.eclipse.draw2d.
+	 * MouseEvent)
+	 */
+	public void mouseHover(MouseEvent me) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.draw2d.MouseMotionListener#mouseMoved(org.eclipse.draw2d.
+	 * MouseEvent)
+	 */
+	public void mouseMoved(MouseEvent me) {
+		double x = me.x * this.getScale();
+		double y = me.y;
+
+		if (y > this.getVisualSizeY() - MemTraceGraph.xLegendHeight) {
+			this.setToolTipText(null);
+			return;
+		}
+
+		// mouse event may return out of range X, that may
+		// crash when we use it to index data array
+		x = x >= 0 ? x : 0;
+		if (me.x >= this.getVisualSize().width
+				+ this.parentComponent.getScrolledOrigin().x) {
+			x = (this.getVisualSize().width - 1) * this.getScale();
+		}
+
+		if (x > PIPageEditor.currentPageEditor().getMaxEndTime() * 1000) {
+			this.setToolTipText(null);
+			return;
+		}
+
+		long chunkSize = 0;
+		long stackHeapSize = 0;
+		// long totalSize = 0;
+		Entry<Long, Integer> entry;
+		if (memTrace.getVersion() >= 202) {
+			if (eventStackListY != null) {
+				/*
+				 * TODO entry = eventStackListY.floorEntry((long)x); if(entry !=
+				 * null){ stackHeapSize = entry.getValue(); }
+				 */
+				Integer value = (Integer) MemTrace.getFloorEntryFromMap(
+						(long) x, eventStackListY);
+				if (value != null) {
+					stackHeapSize = value;
+				}
+			}
+			if (eventChunkListY != null) {
+				/*
+				 * TODO entry = eventChunkListY.floorEntry((long)x); if(entry !=
+				 * null){ chunkSize = entry.getValue(); }
+				 */
+				Integer value = (Integer) MemTrace.getFloorEntryFromMap(
+						(long) x, eventChunkListY);
+				if (value != null) {
+					chunkSize = value;
+				}
+
+			}/*
+			 * if(stackHeapSize == null){ this.setToolTipText(null); return; }
+			 */
+		} else {
+			ArrayList<MemSample> samples = memTrace
+					.getMemSampleDataByTime((long) x);
+
+			if (samples != null) {
+				// tooltip always shows totals for the threads/processes that
+				// are selected
+				for (int i = 0; i < samples.size(); i++) {
+					MemSample sample = samples.get(i);
+					MemThread memThread = sample.thread;
+					if (memThread.isEnabled(this.graphIndex)) {
+						chunkSize += sample.heapSize;
+						stackHeapSize += sample.stackSize;
+						// totalSize += sample.heapSize + sample.stackSize;
+					}
+				}
+			}
+		}
+
+		int time = (int) x;
+
+		if (this.paintMode == UsageType.CHUNKS_HEAPSTACK) {
+			this.setToolTipText((time / 1000.0)
+					+ Messages.getString("MemTraceGraph.totalTooltip1") //$NON-NLS-1$
+					+ memKBFormat.format((chunkSize + 512) / 1024)
+					+ Messages.getString("MemTraceGraph.totalTooltip2") //$NON-NLS-1$
+					+ memKBFormat.format((stackHeapSize + 512) / 1024));
+		} else if (this.paintMode == UsageType.CHUNKS) {
+			this.setToolTipText((time / 1000.0)
+					+ Messages.getString("MemTraceGraph.chunkTooltip1") //$NON-NLS-1$
+					+ (chunkSize + 512) / 1024
+					+ Messages.getString("MemTraceGraph.chunkTooltip2")); //$NON-NLS-1$
+		} else if (this.paintMode == UsageType.HEAPSTACK) {
+			this.setToolTipText((time / 1000.0)
+					+ Messages.getString("MemTraceGraph.stackHeapTooltip1") //$NON-NLS-1$
+					+ (stackHeapSize + 512) / 1024
+					+ Messages.getString("MemTraceGraph.stackHeapTooltip2")); //$NON-NLS-1$
+		} else
+			return;
+
+	}
+
+	public void setCurrentThreads(Hashtable<Integer, Integer> threadList) {
+		this.threadList = threadList;
+	}
+
+	public int getGraphIndex() {
+		return this.graphIndex;
+	}
+
+	public MemTrace getMemTrace() {
+		return this.memTrace;
+	}
+
+	public MemThreadTable getMemThreadTable() {
+		return this.memThreadTable;
+	}
+
+	public boolean haveEnabled() {
+		return this.haveEnabled;
+	}
+
+	private int prettyMaxBytes(int bytes) {
+		if (bytes < 1000)
+			bytes = 1000;
+		else if (bytes < 10000)
+			bytes = 10000;
+		else if (bytes <= 10 * 1024)
+			bytes = 10 * 1024;
+		else if (bytes <= 20 * 1024)
+			bytes = 20 * 1024;
+		else if (bytes <= 30 * 1024)
+			bytes = 30 * 1024;
+		else if (bytes <= 50 * 1024)
+			bytes = 50 * 1024;
+		else if (bytes <= 100 * 1024)
+			bytes = 100 * 1024;
+		else if (bytes <= 200 * 1024)
+			bytes = 200 * 1024;
+		else if (bytes <= 300 * 1024)
+			bytes = 300 * 1024;
+		else if (bytes <= 500 * 1024)
+			bytes = 500 * 1024;
+		else if (bytes <= 1000 * 1024)
+			bytes = 1000 * 1024;
+		else if (bytes <= 1 * 1024 * 1024)
+			bytes = 1 * 1024 * 1024;
+		else if (bytes <= 2 * 1024 * 1024)
+			bytes = 2 * 1024 * 1024;
+		else if (bytes <= 3 * 1024 * 1024)
+			bytes = 3 * 1024 * 1024;
+		else if (bytes <= 5 * 1024 * 1024)
+			bytes = 5 * 1024 * 1024;
+		else if (bytes <= 10 * 1024 * 1024)
+			bytes = 10 * 1024 * 1024;
+		else if (bytes <= 20 * 1024 * 1024)
+			bytes = 20 * 1024 * 1024;
+		else if (bytes <= 30 * 1024 * 1024)
+			bytes = 30 * 1024 * 1024;
+		else if (bytes <= 50 * 1024 * 1024)
+			bytes = 50 * 1024 * 1024;
+		else if (bytes <= 100 * 1024 * 1024)
+			bytes = 100 * 1024 * 1024;
+		else if (bytes <= 200 * 1024 * 1024)
+			bytes = 200 * 1024 * 1024;
+		else if (bytes <= 300 * 1024 * 1024)
+			bytes = 300 * 1024 * 1024;
+		else if (bytes <= 500 * 1024 * 1024)
+			bytes = 500 * 1024 * 1024;
+		else
+			bytes = ((bytes + 1024 * 1024 * 1024 - 1) / (1024 * 1024 * 1024))
+					* (1024 * 1024 * 1024);
+
+		return bytes;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemTraceParser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,1725 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.memory;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.Parser;
+import com.nokia.carbide.cpp.pi.priority.PriSample;
+import com.nokia.carbide.cpp.pi.priority.PriThread;
+import com.nokia.carbide.cpp.pi.priority.PriTrace;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+public class MemTraceParser extends Parser
+{
+    private boolean debug = false;
+    private String version;
+    
+	private Vector<MemThread> memSamples = new Vector<MemThread>();
+	private Vector<PriThread> priSamples = new Vector<PriThread>();
+	private char[] buffer = new char[80];
+	private String threadName;
+	private String processName;
+	private int threadId;
+	private int sampleTime;
+	private int heapSize;
+	private int stackSize;
+	private int processPriority;
+	private int threadPriority;
+	private int defaultSamplingTime = 3000;
+	private int samplingTime;
+	private MemSample sample;
+	private MemTrace memTrace;
+	private PriSample priSample;
+	private PriTrace priTrace;
+	private byte a, b, c, d;
+	private int readCount = 0;
+
+	// constants
+	public static int SAMPLE_CODE_INITIAL_CHUNK = 0;
+	public static int SAMPLE_CODE_NEW_CHUNK = 1;
+	public static int SAMPLE_CODE_UPDATE_CHUNK = 2;
+	public static int SAMPLE_CODE_DELETE_CHUNK = 3;
+	
+	public MemTraceParser() //throws Exception
+	{
+	}
+	
+	public ParsedTraceData parse(File file) throws Exception 
+	{
+		if (!file.exists() || file.isDirectory())
+	    {
+	      throw new Exception(Messages.getString("MemTraceParser.cannotOpenTraceFile")); //$NON-NLS-1$
+	    }
+		if (debug)
+			System.out.println(Messages.getString("MemTraceParser.traceFileLength") + file.length()); //$NON-NLS-1$
+
+	    parseMemTrace(file);
+	    int versionNumber = convertVersionStringToInt(version);
+	    memTrace.setVersion(versionNumber);
+	    
+	    samplingTime = calcSamplingTime();
+		
+		ParsedTraceData ptd = new ParsedTraceData();
+		ptd.traceData = this.getTrace();
+		
+		/* TODO some debug prints remove
+		MemTrace memTrace = (MemTrace)ptd.traceData;
+		int ii = 1;
+		for (Enumeration e = memTrace.getSamples(); e.hasMoreElements(); )
+		{
+			MemSample memSample = (MemSample) e.nextElement();
+
+			
+			if(memSample.thread.threadId == 0xc81dc318){
+				System.out.println("Threadname: " + memSample.thread.threadName +  ", time:" + Long.toString(memSample.sampleSynchTime) + ", stack:" + Integer.toString(memSample.stackSize) + ", heap:" + Integer.toString(memSample.heapSize));
+				ii++;
+			}
+		}*/
+		
+		return ptd;
+	}
+	
+	private void parseNewMemFile(String version,DataInputStream dis) throws Exception
+	{
+		if (version.equals("0.85") || version.equals("0.91") || version.equals("1.00")||version.equals("1.10")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+		{
+			parseV085MemFile(dis);
+		}
+		else throw new Exception(Messages.getString("MemTraceParser.traceVersionException1") + version //$NON-NLS-1$
+				                 + Messages.getString("MemTraceParser.traceVersionException2")); //$NON-NLS-1$
+	}
+	
+	private void parseV085MemFile(DataInputStream dis) throws Exception
+	{
+		// read the version again
+		byte[] version = readElementWithLength(dis);
+		if (debug)System.out.println(Messages.getString("MemTraceParser.readVersionDebug") + new String(version)); //$NON-NLS-1$
+		this.version = new String(version);
+		
+		this.readV085MemSample(dis);
+	}
+	
+	private void parseV110MemFile(DataInputStream dis) throws Exception
+	{
+		// read the version again
+		byte[] version = readElementWithLength(dis);
+		if (debug) System.out.println(Messages.getString("MemTraceParser.readVersionDebug") + new String(version)); //$NON-NLS-1$
+		this.version = new String(version);
+		
+		this.readV110MemSample(dis);
+	}
+
+	private void parseV155MemFile(DataInputStream dis) throws Exception
+	{
+		// read the version again
+		byte[] version = readElementWithLength(dis);
+		if (debug) System.out.println(Messages.getString("MemTraceParser.readVersion")+new String(version)); //$NON-NLS-1$
+		this.version = new String(version);
+		
+		this.readV155MemSample(dis);
+	}
+	
+	private void parseV157MemFile(DataInputStream dis) throws Exception
+	{
+		// read the version again
+		byte[] version = readElementWithLength(dis);
+		if (debug) System.out.println("Read version "+new String(version));
+		this.version = new String(version);
+		
+		this.readV157MemSample(dis);
+	}
+	
+	private void parseV110PriFile(DataInputStream dis) throws Exception
+	{
+		// read the version again
+		byte[] version = readElementWithLength(dis);
+		if (debug) System.out.println(Messages.getString("MemTraceParser.readVersionDebug") + new String(version)); //$NON-NLS-1$
+		this.version = new String(version);
+		
+		this.readV110PriSample(dis);
+	}
+
+	public String getProfilerVersion()
+	{
+	    return version;
+	}
+	
+	private void readV085MemSample(DataInputStream dis) throws Exception
+	{
+	    Vector<long[]> rawV085Samples = new Vector<long[]>();
+	    Vector<long[]> lastSampleRaw = new Vector<long[]>();
+
+		memTrace = new MemTrace();
+	    priTrace = new PriTrace();
+	   		
+		// first there should be 4 bytes of sample time
+		long sample = this.readTUintWithLength(dis);
+				
+		// then read if there is thread name data
+		int length = dis.readUnsignedByte();readCount++;
+		if (length != 1)
+			throw new Exception(Messages.getString("MemTraceParser.parseErrorTypeMissing")); //$NON-NLS-1$
+		
+		int mode = dis.readUnsignedByte(); readCount++;
+
+		try
+		{
+			// read the first length
+			length = dis.readUnsignedByte(); readCount++;
+
+			Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
+			
+			while(true)
+			{
+				//System.out.println("ReadCount:"+this.readCount);
+				if (length == 0) //haxor =)
+				{
+					// end of sample
+					// read new length
+					
+					// first there should be 4 bytes of sample time
+					sample = this.readTUintWithLength(dis);
+					
+					length = dis.readUnsignedByte(); readCount++;
+					
+					if (length == 4)
+					{
+						// there was only the sample header here
+						System.out.println(Messages.getString("MemTraceParser.missingSampleNumber") + sample); //$NON-NLS-1$
+						mode = 0x00;
+					}
+					else if (length != 1)
+					{
+						throw new Exception(Messages.getString("MemTraceParser.parseErrorWrongLength") + length); //$NON-NLS-1$
+					}
+					else
+					{
+						lastSampleRaw.clear();
+					}
+				}
+				
+				if (length == 1)
+				{
+					mode = dis.readUnsignedByte(); readCount++;
+
+					// read the next length
+					length = dis.readUnsignedByte(); readCount++;
+
+					lastSampleRaw.clear(); //lisätty 16.11.05 -aniskane
+				}
+				
+				if (mode == 0xaa)
+				{
+					// reading thread names
+					String rawName = readThreadName(dis,length);
+					long threadId = readTUint(dis);
+				   	int index = rawName.indexOf(':');
+				   	if (index != -1)
+				   	{
+				   		processName = rawName.substring(0,index);
+				   		threadName = rawName.substring(rawName.lastIndexOf(':')+ 1, rawName.length());
+				   	}
+				   	else
+				   	{
+				   		processName = rawName;
+				   		threadName = rawName;
+				   	}
+								    	
+					memTrace.addFirstSynchTime(new Integer((int)threadId),new Integer((int)sample));
+				   	memSamples.add(new MemThread(new Integer((int)threadId), threadName, processName));
+				   	priTrace.addFirstSynchTime(new Integer((int)threadId), new Integer(sampleTime));
+				   	priSamples.add(new PriThread(new Integer((int)threadId), threadName, processName));
+
+				   	// read the next length
+					length = dis.readUnsignedByte(); readCount++;
+					//System.out.println("Next length " + length);
+				}
+				else if (mode == 0xdd)
+				{
+					// reading data
+					long[] elements = this.readDataElements085Mem(dis, length, sample);
+					
+					rawV085Samples.add(elements);
+					lastSampleRaw.add(elements);
+
+					// read the next length
+					length = dis.readUnsignedByte(); readCount++;
+				}
+				else if (mode == 0x00)
+				{
+					// duplicate the previous sample to replace the missing sample
+					Enumeration<long[]> e = lastSampleRaw.elements();
+					while(e.hasMoreElements())
+					{
+						long[] element = e.nextElement();
+						long[] newElement = new long[7];
+						newElement[0] = element[0];
+						newElement[1] = element[1];
+						newElement[2] = element[2];
+						newElement[3] = element[3];
+						newElement[4] = element[4];
+						newElement[5] = element[5];
+						// replace the sample number with the missing one
+						newElement[6] = sample;
+						// add the duplicated sample
+						rawV085Samples.add(newElement);
+					}
+					
+					// read the length, it is already known
+					sample = readTUint(dis);
+					System.out.println(Messages.getString("MemTraceParser.sampleRead") + sample); //$NON-NLS-1$
+					length = dis.readUnsignedByte(); readCount++;;
+				}
+				else
+				{
+					throw new Exception(Messages.getString("MemTraceParser.parseErrorWrongMode") + mode); //$NON-NLS-1$
+				}
+			}
+		}
+		catch (EOFException e)
+		{
+			if (debug) System.out.println(Messages.getString("MemTraceParser.finishedReading")); //$NON-NLS-1$
+			this.addRawV085Samples(rawV085Samples);
+		}
+	}
+
+	private void readV110MemSample(DataInputStream dis) throws Exception
+	{
+	    Vector<long[]> rawV110MemSamples = new Vector<long[]>();
+	    Vector<long[]> lastSampleRaw = new Vector<long[]>();
+
+		memTrace = new MemTrace();
+
+		// first there should be 4 bytes of sample time
+		long sample = this.readTUintWithLength(dis);
+
+		// then read if there is thread name data
+		int length = dis.readUnsignedByte(); readCount++;
+		if (length != 1)
+			throw new Exception(Messages.getString("MemTraceParser.parseErrorTypeMissing")); //$NON-NLS-1$
+		
+		int mode = dis.readUnsignedByte(); readCount++;
+
+		try
+		{
+			length = dis.readUnsignedByte(); readCount++;
+			
+			while(true)
+			{
+				if (length == 0) 
+				{
+					// end of sample
+					// read new length
+					
+					// first there should be 4 bytes of sample time
+					sample = this.readTUintWithLength(dis);
+					
+					length = dis.readUnsignedByte(); readCount++;
+
+					if (length == 4)
+					{
+						// there was only the sample header here
+						System.out.println(Messages.getString("MemTraceParser.missingSampleNumber") + sample); //$NON-NLS-1$
+						mode = 0x00;
+					}
+					else if (length != 1)
+					{
+						throw new Exception(Messages.getString("MemTraceParser.parseErrorWrongLength") + length); //$NON-NLS-1$
+					}
+					else
+					{
+						lastSampleRaw.clear();
+					}
+				}
+				
+				if (length == 1)
+				{
+					mode = dis.readUnsignedByte(); readCount++;
+
+					// read the next length
+					length = dis.readUnsignedByte(); readCount++;
+
+					lastSampleRaw.clear(); //lisätty 16.11.05 -aniskane
+				}
+				
+				if (mode == 0xaa)
+				{
+					// reading thread names
+					String rawName = readThreadName(dis,length);
+					long threadId = readTUint(dis);
+
+				   	int index = rawName.indexOf(':');
+				   	if (index != -1)
+				   	{
+				   		processName = rawName.substring(0,index);
+				   		threadName = rawName.substring(rawName.lastIndexOf(':') + 1, rawName.length());
+				   	}
+				   	else
+				   	{
+				   		processName = rawName;
+				   		threadName = rawName;
+				   	}
+								    	
+					memTrace.addFirstSynchTime(new Integer((int)threadId), new Integer((int)sample));
+				   	memSamples.add(new MemThread(new Integer((int)threadId), threadName, processName));
+
+					length = dis.readUnsignedByte(); readCount++;
+				}
+				else if (mode == 0xdd)
+				{
+					// reading data
+					long[] elements = this.readDataElements110Mem(dis, length, sample);
+					
+					rawV110MemSamples.add(elements);
+					lastSampleRaw.add(elements);
+
+					// read the next length
+					length = dis.readUnsignedByte(); readCount++;
+				}
+				else if (mode == 0x00)
+				{
+					// duplicate the previous sample to replace the missing sample
+					Enumeration<long[]> e = lastSampleRaw.elements();
+					while(e.hasMoreElements())
+					{
+						long[] element = e.nextElement();
+						long[] newElement = new long[7];
+						newElement[0] = element[0];
+						newElement[1] = element[1];
+						newElement[2] = element[2];
+						newElement[3] = element[3];
+						newElement[4] = element[4];
+
+						// replace the sample number with the missing one
+						newElement[5] = sample;
+
+						// add the duplicated sample
+						rawV110MemSamples.add(newElement);
+					}
+					
+					// read the length, it is already known
+					sample = readTUint(dis);
+					if (debug) System.out.println(Messages.getString("MemTraceParser.sampleRead") + sample); //$NON-NLS-1$
+					length = dis.readUnsignedByte();readCount++;;
+				}
+				else
+				{
+					throw new Exception(Messages.getString("MemTraceParser.parseErrorWrongMode")+mode); //$NON-NLS-1$
+				}
+			}
+		}
+		catch (EOFException e)
+		{
+			System.out.println(Messages.getString("MemTraceParser.finishedReading")); //$NON-NLS-1$
+			this.addRawV110MemSamples(rawV110MemSamples);
+		}
+	}
+
+	private void readV155MemSample(DataInputStream dis) throws Exception
+	{
+	    Vector<long[]> rawV155MemSamples = new Vector<long[]>();
+	    Vector<long[]> lastSampleRaw = new Vector<long[]>();
+
+		memTrace = new MemTrace();
+
+		// first there should be 4 bytes of sample time
+		long sample = this.readTUintWithLength(dis);
+				
+		// then read if there is thread name data
+		int length = dis.readUnsignedByte();readCount++;
+		if (length != 1) throw new Exception(Messages.getString("MemTraceParser.missingType")); //$NON-NLS-1$
+		
+		int mode = dis.readUnsignedByte();readCount++;
+
+		try
+		{
+			length = dis.readUnsignedByte();readCount++;
+			
+			while(true)
+			{
+				if (length == 0) 
+				{
+					if (debug)System.out.println(Messages.getString("MemTraceParser.newSample")); //$NON-NLS-1$
+					// end of sample
+					// read new length
+					
+					// first there should be 4 bytes of sample time
+					sample = this.readTUintWithLength(dis);
+					
+					length = dis.readUnsignedByte();readCount++;
+					
+					if (length == 4)
+					{
+						// there was only the sample header here
+						System.out.println(Messages.getString("MemTraceParser.missingSampleNum")+sample); //$NON-NLS-1$
+						mode = 0x00;
+					}
+					else if (length != 1)
+					{
+						throw new Exception(Messages.getString("MemTraceParser.wrongLength")+length); //$NON-NLS-1$
+					}
+					else
+					{
+						lastSampleRaw.clear();
+					}
+				}
+				
+				if (length == 1)
+				{
+					mode = dis.readUnsignedByte();readCount++;
+
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					if (debug)System.out.println(Messages.getString("MemTraceParser.nextLength")+length); //$NON-NLS-1$
+					lastSampleRaw.clear(); //lisätty 16.11.05 -aniskane
+				}
+				
+				if (mode == 0xaa)
+				{
+					// reading thread names
+					String rawName = readThreadName(dis,length);
+					long threadId = readTUint(dis);
+					if (debug)System.out.println(Messages.getString("MemTraceParser.rawName1")+rawName+Messages.getString("MemTraceParser.rawName2")+threadId); //$NON-NLS-1$ //$NON-NLS-2$
+				   	int index = rawName.indexOf(':');
+				   	if (index != -1)
+				   	{
+				   		processName = rawName.substring(0,index);
+				   		//threadName = rawName.substring(rawName.lastIndexOf(':')+1,rawName.length());
+				   		threadName = rawName.substring(rawName.indexOf(':')+2,rawName.length());
+				   	}
+				   	else
+				   	{
+				   		processName = rawName;
+				   		threadName = rawName;
+				   	}
+					if (processName.startsWith("T_")) //$NON-NLS-1$
+					{
+						processName = processName.substring(2);
+						threadName += "_T"; //$NON-NLS-1$
+					}
+					else if (processName.startsWith("C_")) //$NON-NLS-1$
+					{
+						processName = processName.substring(2);
+						threadName += "_C"; //$NON-NLS-1$
+					}
+					memTrace.addFirstSynchTime(new Integer((int)threadId),new Integer((int)sample));
+				   	memSamples.add(new MemThread(new Integer((int)threadId), threadName, processName));
+
+					length = dis.readUnsignedByte();readCount++;
+				}
+				else if (mode == 0xdd)
+				{
+					// reading data
+					long[] elements = this.readDataElements110Mem(dis,length,sample);
+					
+					//if (debug)System.out.println(" sample: "+sample);
+//if ((elements[0] > 0xffff || elements[0] < 0) && ((int)elements[0] != 0xbabbeaaa))
+//					System.out.println(   "Chunk Data"
+//					+ ",pointer address,0x" + Integer.toHexString((int)elements[0])
+//					+ ",c.iSize," + elements[1]
+//					+ ",c.iAttributes,0x" + Integer.toHexString((int)elements[2])
+//					+ ",memory model," + (elements[4] & 0xf)
+//					+ ",time," + elements[5]);
+//else System.out.println(   "Thread Data"
+//		+ ",t.Id," + elements[0]
+//		+ ",t.iUserStackSize," + elements[1]
+//		+ ",t.iUserStackRunAddress,0x" + Integer.toHexString((int)elements[2])
+//		+ ",time," + elements[5]);
+					
+					rawV155MemSamples.add(elements);
+					lastSampleRaw.add(elements);
+					
+					// read the length, it is already known
+					//sample = readTUint(dis);
+
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+				}
+				else if (mode == 0x00)
+				{
+					// read the length, it is already known
+					sample = readTUint(dis);
+					System.out.println(Messages.getString("MemTraceParser.nextSampleNum")+sample); //$NON-NLS-1$
+					length = dis.readUnsignedByte();readCount++;;
+				}
+				else
+				{
+					throw new Exception(Messages.getString("MemTraceParser.wrongMode")+mode); //$NON-NLS-1$
+				}
+			}
+		}
+		catch (EOFException e)
+		{
+			System.out.println(Messages.getString("MemTraceParser.readingDone")); //$NON-NLS-1$
+			this.addRawV155MemSamples(rawV155MemSamples);
+		}
+	}
+	
+	@SuppressWarnings("unchecked")
+	private void readV157MemSample(DataInputStream dis) throws Exception {
+	    Vector rawV157MemSamples = new Vector();
+	    int counter = 0;
+	    String createdThread = "";
+	    
+		memTrace = new MemTrace();
+
+		MemThread thread;
+		
+		// first there should be 4 bytes of sample time
+		long sample = this.readTUintWithLength(dis);
+				
+		// then read if there is thread name data
+		int length = dis.readUnsignedByte();readCount++;
+		if(length != 1) throw new Exception("Parse error, type after sample missing");
+		
+		int mode = dis.readUnsignedByte();readCount++;
+
+		try {
+			length = dis.readUnsignedByte();readCount++;
+			
+			while(true) {
+				if(length == 0) {
+//					if(debug) System.out.println("Length = 0, New sample");
+					// end of sample
+					// read new length
+					
+					// first there should be 4 bytes of sample time
+					sample = this.readTUintWithLength(dis);
+					
+					length = dis.readUnsignedByte();readCount++;
+					
+					if(length == 4) {
+						// there was only the sample header here
+						System.out.println("Missing sample #"+sample);
+						mode = 0x00;
+					}
+					else if(length != 1) {
+						throw new Exception("Parse error, wrong length "+length+", readCount: "+readCount);
+					}
+//					else {
+//						lastSampleRaw.clear();
+//					}
+				}
+				
+				if(length == 1) {
+					mode = dis.readUnsignedByte();readCount++;
+
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+				}
+				
+				if(mode == 0xaa) {
+					// reading thread names
+					String rawName = readThreadName(dis,length);
+					long threadId = readTUint(dis);
+					
+					if(debug) System.out.println("New raw name "+rawName+" at #"+sample+", thread id: "+Long.toHexString(threadId));
+
+					int index = rawName.indexOf(':');
+				   	if(index != -1) {
+				   		processName = rawName.substring(0,index);
+				   		//threadName = rawName.substring(rawName.lastIndexOf(':')+1,rawName.length());
+				   		threadName = rawName.substring(rawName.indexOf(':')+2,rawName.length());
+				   	}
+				   	else {
+				   		processName = rawName;
+				   		threadName = rawName;
+				   	}
+					if (processName.startsWith("T_")) {
+						processName = processName.substring(2);
+						threadName += "_T";
+					}
+					else if (processName.startsWith("C_")) {
+						processName = processName.substring(2);
+						threadName += "_C";
+					}
+					
+					memTrace.addFirstSynchTime(new Integer((int)threadId),new Integer((int)sample));
+					thread = new MemThread(new Integer((int)threadId), threadName, processName);
+					memSamples.add(thread);
+			   		createdThread = processName+"::"+threadName;
+			   		if(debug)System.out.println("Name sample: "+sample+", created thread: "+createdThread+", vector size: "+memSamples.size());
+				   	length = dis.readUnsignedByte();readCount++;
+				}
+				else if(mode == 0xdd) {
+					long[] elements = this.readDataElements110Mem(dis,length,sample);
+					if(elements[0] != (int)0xffffffffbabbeaaaL || counter == 0) {
+						elements[6] = MemTraceParser.SAMPLE_CODE_INITIAL_CHUNK;
+					} else if (elements[0] == (int)0xffffffffbabbeaaaL){
+						elements[6] = MemTraceParser.SAMPLE_CODE_UPDATE_CHUNK;
+					}
+					MemThread tempThr = ((MemThread)memSamples.get(counter));
+					// reading data
+					elements[7] = sum(tempThr.processName+"::"+tempThr.threadName);
+					if(debug)System.out.println("Data sample: "+sample+", hash: "+elements[7]+", created thread: "+tempThr.processName+"::"+tempThr.threadName);
+					
+					rawV157MemSamples.add(elements);
+
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					createdThread = "";
+					
+					// hack since total memory code added for top of both thread and chunk lists
+					if(elements[0] != (int)0xffffffffbabbeaaaL || counter == 0) {
+						counter++;
+					}
+				}
+				else if(mode == 0xda) {	// new chunk code found
+					// read the chunk data
+					long[] elements = this.readDataElements110Mem(dis,length,sample);
+					elements[6] = MemTraceParser.SAMPLE_CODE_NEW_CHUNK;
+					elements[7] = sum(createdThread);
+					if(debug) System.out.println("New chunk #"+Long.toHexString(elements[0])+", with name: "+createdThread+" found @"+sample);
+					
+					rawV157MemSamples.add(elements);
+					
+					// read the next length
+				   	length = dis.readUnsignedByte();readCount++;
+				}
+				else if(mode == 0xdb) { // chunk update code found
+					// read the chunk data
+					long[] elements = this.readDataElements110Mem(dis,length,sample);
+					elements[6] = MemTraceParser.SAMPLE_CODE_UPDATE_CHUNK;
+					if(debug) System.out.println("Chunk #"+Long.toHexString(elements[0])+" update found #"+sample);
+					
+					rawV157MemSamples.add(elements);
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					createdThread = "";
+				}
+				else if(mode == 0xdc) { // chunk remove code found
+					// read the chunk data
+					long[] elements = this.readDataElements110Mem(dis,length,sample);
+					elements[6] = MemTraceParser.SAMPLE_CODE_DELETE_CHUNK;
+
+					if (debug) System.out.println("Chunk #"+Long.toHexString(elements[0])+" remove found #"+sample);
+					
+					rawV157MemSamples.add(elements);
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					createdThread = "";
+				}
+				else if(mode == 0x00) {
+					// duplicate the previous sample to replace the missing sample
+					
+					// read the length, it is already known
+					sample = readTUint(dis);
+					if(debug) System.out.println("Read next sample #"+sample);
+					length = dis.readUnsignedByte();readCount++;;
+				}
+				else
+				{
+					throw new Exception("Parse error, wrong mode "+mode);
+				}
+			}
+		}
+		catch (EOFException e)
+		{
+			System.out.println("Finished reading");
+			this.addRawV157MemSamples(rawV157MemSamples);
+		}
+	}
+	
+	/*
+	 * A method for calculating hash value for a string 
+	 */
+	public static long sum(String arg) {		
+		int total = 0;		
+		for(int i = 0; i < arg.length(); i++){			
+			total += (long)arg.charAt(i);		
+			}		return total; // returns the sum of the chars after cast	
+	}
+
+	@SuppressWarnings("unchecked")
+	private void addRawV157MemSamples(Vector rawV157MemSamples) {
+
+		Hashtable startedThreads;	// store the id/name of the thread for recognizing the right chunk (same chunk id may be reused)
+
+		String tempThreadName = "";
+		String str = "";
+		int chunkMode = MemTraceParser.SAMPLE_CODE_INITIAL_CHUNK;
+		long nameHash = 0;
+	    MemThread[] memThreads = new MemThread[memSamples.size()];
+	    memSamples.copyInto((MemThread[]) memThreads);
+	    memTrace.setThreads(memThreads);
+
+	    // container for started threads, some of the chunks may share the id (i.e. the chunk start address)
+	    startedThreads = new Hashtable(memSamples.size());
+	    
+	    Enumeration rawEnum = rawV157MemSamples.elements();
+	    
+	    while(rawEnum.hasMoreElements()) {
+	    	long[] element = (long[])rawEnum.nextElement();
+	    	threadId = (int)element[0];
+	    	heapSize = (int)element[3];
+	    	stackSize = (int)element[4];
+	    	sampleTime = (int)element[5];
+	    	chunkMode = (int)element[6];	// chunk mode for deciding the periods of memory usage per thread/chunk 
+	    	nameHash = element[7];			// for checking the right thread/raw sample pairs
+	    	
+	    	// total memory consumption
+	    	if(element[0] == 0xffffffffbabbeaaaL) {
+	    		int totalRam = (int)element[1];
+	    		int freeRam = (int)element[3];
+	    		
+	    		heapSize = totalRam-freeRam;
+	    		stackSize = freeRam;
+		    	if(debug) System.out.println("Used RAM: " + heapSize+" B, free RAM: "+stackSize+" B");
+	    	}
+	    	
+	    	// handle different sample types 
+	    	switch(chunkMode) {
+		    	case 0: // MemTraceParser.SAMPLE_CODE_INITIAL_CHUNK
+		    		// search for a correct sample for the ID of a raw sample
+			    	for (Enumeration e = memSamples.elements();e.hasMoreElements();) {
+			    		MemThread mt = (MemThread)e.nextElement();
+			    		
+			    		// find corresponding thread ID among the MemThreads
+			    		if (mt.threadId.intValue() == threadId ) {
+			    			// create a new sample to memory trace
+			    			sample = new MemSample(mt, heapSize, stackSize, sampleTime, MemTraceParser.SAMPLE_CODE_INITIAL_CHUNK);
+			    			tempThreadName = mt.processName+"::"+mt.threadName;
+			    			
+			    			// add the thread into started hash table
+			    			startedThreads.put((int)threadId, (String)tempThreadName);
+			    			
+		    				memTrace.addSample(sample);
+			    			break;
+			    		}
+			    	}
+		    		break;
+		    	case 1: // MemTraceParser.SAMPLE_CODE_NEW_CHUNK
+		    		// add to the started threads hash table
+			    	for (Enumeration e = memSamples.elements();e.hasMoreElements();) {
+			    		MemThread mt = (MemThread)e.nextElement();
+		    			tempThreadName = mt.processName+"::"+mt.threadName;
+			    		
+			    		// find corresponding thread ID among the MemThreads
+			    		if (mt.threadId.intValue() == threadId && sum(tempThreadName) == nameHash) {
+			    			// create a new sample to memory trace
+			    			sample = new MemSample(mt, heapSize, stackSize, sampleTime, MemTraceParser.SAMPLE_CODE_NEW_CHUNK);
+			    			
+			    			// add the thread into started hash table
+			    			startedThreads.put((int)threadId, (String)tempThreadName);
+
+			    			// add sample to main trace data structure
+		    				memTrace.addSample(sample);
+			    			break;
+			    		} 
+			    	}
+		    		break;
+		    	case 2: // MemTraceParser.SAMPLE_CODE_UPDATE_CHUNK
+		    		str = (String)startedThreads.get(threadId);
+		    		if(str == null)
+		    			str = "";
+		    		// add to the started threads hash table
+			    	for (Enumeration e = memSamples.elements();e.hasMoreElements();) {
+			    		MemThread mt = (MemThread)e.nextElement();
+		    			tempThreadName = mt.processName+"::"+mt.threadName;
+		    			
+			    		// find corresponding thread ID among the MemThreads
+			    		if (mt.threadId.intValue() == threadId ) {
+			    			if((str).equalsIgnoreCase(tempThreadName)) {
+				    			// create a new sample to memory trace
+				    			sample = new MemSample(mt, heapSize, stackSize, sampleTime, MemTraceParser.SAMPLE_CODE_UPDATE_CHUNK);
+				    			
+				    			// add sample to main trace data structure
+			    				memTrace.addSample(sample);
+				    			break;
+			    			}
+			    		} 
+			    	}
+		    		break;
+		    	case 3: // MemTraceParser.SAMPLE_CODE_DELETE_CHUNK
+		    		// add to the started threads hash table
+			    	for (Enumeration e = memSamples.elements();e.hasMoreElements();) {
+			    		MemThread mt = (MemThread)e.nextElement();
+		    			tempThreadName = mt.processName+"::"+mt.threadName;
+			    		
+			    		// find corresponding thread ID among the MemThreads
+			    		if (mt.threadId.intValue() == threadId) {
+			    			if(((String)startedThreads.get(threadId)).equalsIgnoreCase(tempThreadName)) {
+				    			// create a new sample to memory trace
+				    			sample = new MemSample(mt, heapSize, stackSize, sampleTime, MemTraceParser.SAMPLE_CODE_DELETE_CHUNK);
+				    			
+					    		// remove from the started threads hash table
+					    		if(startedThreads.remove(threadId) == null) {
+					    			System.out.println(" No match on started list");
+				    			}
+				    			
+				    			// add sample to main trace data structure
+			    				memTrace.addSample(sample);
+				    			break;
+			    			} 
+			    		}
+			    	}
+		    		break;
+		    	default:
+		    		break;
+	    	}
+	    	
+	    	// add end mark for the thread
+    		memTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleTime));
+
+	    }
+	    if (debug) System.out.println("Done parsing, size: "+memTrace.samples.size());
+	}
+	
+	private void addRawV110MemSamples(Vector<long[]> rawV110MemSamples)
+	{
+	    MemThread[] memTreads = new MemThread[memSamples.size()];
+	    memSamples.copyInto((MemThread[]) memTreads);
+	    memTrace.setThreads(memTreads);
+	    
+	    Enumeration<long[]> rawEnum = rawV110MemSamples.elements();
+	    while(rawEnum.hasMoreElements())
+	    {
+	    	long[] element = rawEnum.nextElement();
+	    	threadId = (int)element[0];
+	    	heapSize = (int)element[3];	// NOTE: in older versions this was element[1];
+	    	stackSize = (int)element[4];
+	    	sampleTime = (int)element[5]; 
+
+	    	for (Enumeration<MemThread> e = memSamples.elements(); e.hasMoreElements(); )
+	    	{
+	    		MemThread mt = e.nextElement();
+	    		if (mt.threadId.intValue() == threadId)
+	    		{
+	    			sample = new MemSample(mt, heapSize, stackSize, sampleTime);
+	    			memTrace.addSample(sample);
+	    			break;
+	    		}
+	    	}
+	    	
+	    	memTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleTime));
+	    }
+	    if (debug) System.out.println(Messages.getString("MemTraceParser.parsingDone")); //$NON-NLS-1$
+	}
+	
+	private int calcV155SamplingTime(Vector<long[]> rawV155MemSamples)
+	{
+		long[] element = rawV155MemSamples.firstElement();
+		int time = (int)element[5];
+		Enumeration<long[]> rawEnum = rawV155MemSamples.elements();
+	    while(rawEnum.hasMoreElements())
+	    {
+	    	element = rawEnum.nextElement();
+	    	if (time != (int)element[5])
+	    	{
+	    		time = (int)element[5] - time;
+	    		break;
+	    	}
+	    }
+	    return time;
+	}
+
+	private void addRawV155MemSamples(Vector<long[]> rawV155MemSamples) throws Exception
+	{
+		//int largest = 0;
+	    MemThread[] memTreads = new MemThread[memSamples.size()];
+	    memSamples.copyInto((MemThread[]) memTreads);
+	    memTrace.setThreads(memTreads);
+
+	    int samplingTime = calcV155SamplingTime(rawV155MemSamples);
+	    
+	    Enumeration<long[]> rawEnum = rawV155MemSamples.elements();
+	    
+	    while(rawEnum.hasMoreElements())
+	    {
+	    	long[] element = rawEnum.nextElement();
+	    	threadId = (int)element[0];
+	    	heapSize = (int)element[3];
+	    	stackSize = (int)element[4];
+	    	sampleTime = (int)element[5];
+	    	
+	    	if (element[0] == 0xffffffffbabbeaaaL)
+	    	{
+	    		int totalRam = (int)element[1];
+	    		int freeRam = (int)element[3];
+	    		
+	    		heapSize = totalRam-freeRam;
+	    		stackSize = freeRam;
+	    	}
+	    	else
+	    	{
+	    		if (element[0] == 0xffffffffbabbea20L && this.traceVersion.startsWith("Bappea_V2.01")) //$NON-NLS-1$
+	    		{
+		    		if (this.traceVersion.startsWith("Bappea_V2.01") && memTrace.getMemoryModel() == MemTrace.MEMORY_UNKNOWN) //$NON-NLS-1$
+		    		{
+		    			memTrace.setMemoryModel(element[2]);
+		    		}
+	    		}
+	    		else
+	    		{
+			    	if (Math.abs(threadId) > 10000)
+			    	{
+			    		sampleTime -= samplingTime;
+			    	}
+		    	
+			    	if (sampleTime % (samplingTime*2) != samplingTime) {
+			    		System.out.println(Messages.getString("MemTraceParser.invalidSampleNum") + sampleTime); //$NON-NLS-1$
+			    		throw new Exception(Messages.getString("MemTraceParser.invalidSample")); //$NON-NLS-1$
+			    	}
+	    		}
+	    	}
+
+	    	for (Enumeration<MemThread> e = memSamples.elements();e.hasMoreElements();)
+	    	{
+	    		MemThread mt = e.nextElement();
+	    		if (mt.threadId.intValue() == threadId)
+	    		{
+	    			sample = new MemSample(mt, heapSize, stackSize, sampleTime);
+
+	    			if (element[0] != 0xffffffffbabbeaaaL)
+	    			{
+	    				memTrace.addSample(sample);
+	    			}
+	    			else if ((sampleTime/samplingTime)%2 != 0)
+	    			{
+	    				memTrace.addSample(sample);
+	    			}
+	    			break;
+	    		}
+	    	}
+	    	
+	    	memTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleTime));
+	    }
+
+	    if (debug) System.out.println(Messages.getString("MemTraceParser.sizeOfParse")+memTrace.samples.size()/*+" largest "+largest*/); //$NON-NLS-1$
+	}
+	
+	private void addRawV085Samples(Vector<long[]> rawV085Samples)
+	{
+	    MemThread[] memTreads = new MemThread[memSamples.size()];
+	    memSamples.copyInto((MemThread[]) memTreads);
+	    memTrace.setThreads(memTreads);
+	    
+	    PriThread[] priThreads = new PriThread[priSamples.size()];
+	    priSamples.copyInto((PriThread[]) priThreads);
+	    priTrace.setThreads(priThreads);
+	    
+	    Enumeration<long[]> rawEnum = rawV085Samples.elements();
+	    while(rawEnum.hasMoreElements())
+	    {
+	    	long[] element = rawEnum.nextElement();
+	    	threadId = (int)element[0];
+	    	threadPriority = (int)element[5];
+
+	    	// for the null thread, converts 8bit unsigned to signed
+	    	if (threadPriority > 32768)
+	    	    threadPriority = threadPriority - 65536;
+	    	heapSize = (int)element[3];	// NOTE: in older versions this was element[1];
+	    	stackSize = (int)element[4];
+	    	sampleTime = (int)element[6]; 
+
+	    	for (Enumeration<MemThread> e = memSamples.elements(); e.hasMoreElements(); )
+	    	{
+	    		MemThread mt = e.nextElement();
+	    		if (mt.threadId.intValue() == threadId)
+	    		{
+	    			sample = new MemSample(mt, heapSize, stackSize, sampleTime);
+	    			memTrace.addSample(sample);
+	    			break;
+	    		}
+	    	}
+	    	
+	    	for (Enumeration<PriThread> e = priSamples.elements(); e.hasMoreElements(); )
+	    	{
+	    		PriThread pt = e.nextElement();
+	    		if (pt.threadId.intValue() == threadId)
+	    		{
+	    			//int priority = solveAbsolutPriority(processPriority, threadPriority);
+	    			priSample = new PriSample(pt, threadPriority, sampleTime);
+	    			priTrace.addSample(priSample);
+	    			break;
+	    		}
+	    	}
+	    	memTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleTime));
+	    	priTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleTime));
+	    }
+	    if (debug) System.out.println(Messages.getString("MemTraceParser.parsingDone")); //$NON-NLS-1$
+	}
+
+	private void readV110PriSample(DataInputStream dis) throws Exception
+	{
+	    Vector<long[]> rawV110PriSamples = new Vector<long[]>();
+	    Vector<long[]> lastSampleRaw = new Vector<long[]>();
+
+		//memTrace = new MemTrace();
+	    priTrace = new PriTrace();
+	   		
+		// first there should be 4 bytes of sample time
+		long sample = this.readTUintWithLength(dis);
+				
+		// then read if there is thread name data
+		int length = dis.readUnsignedByte(); readCount++;
+		if (length != 1)
+			throw new Exception(Messages.getString("MemTraceParser.parseErrorTypeMissing")); //$NON-NLS-1$
+		
+		int mode = dis.readUnsignedByte(); readCount++;
+
+		try
+		{
+			// read the first length
+			length = dis.readUnsignedByte(); readCount++;
+
+			Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
+
+			while(true)
+			{
+				if (length == 0)
+				{
+					// end of sample
+					// read new length
+					
+					// first there should be 4 bytes of sample time
+					sample = this.readTUintWithLength(dis);
+					
+					length = dis.readUnsignedByte(); readCount++;
+					
+					if (length == 4)
+					{
+						// there was only the sample header here
+						System.out.println(Messages.getString("MemTraceParser.missingSampleNumber") + sample); //$NON-NLS-1$
+						mode = 0x00;
+					}
+					else if (length != 1)
+					{
+						throw new Exception(Messages.getString("MemTraceParser.parseErrorWrongLength") + length); //$NON-NLS-1$
+					}
+					else
+					{
+						lastSampleRaw.clear();
+					}
+				}
+				
+				if (length == 1)
+				{
+					mode = dis.readUnsignedByte(); readCount++;
+
+					// read the next length
+					length = dis.readUnsignedByte(); readCount++;
+
+					lastSampleRaw.clear(); //lisätty 16.11.05 -aniskane
+				}
+				
+				if (mode == 0xaa)
+				{
+					// reading thread names
+					String rawName = readThreadName(dis,length);
+					long threadId = readTUint(dis);
+
+				   	int index = rawName.indexOf(':');
+				   	if (index != -1)
+				   	{
+				   		processName = rawName.substring(0,index);
+				   		threadName = rawName.substring(rawName.lastIndexOf(':') + 1, rawName.length());
+				   	}
+				   	else
+				   	{
+				   		processName = rawName;
+				   		threadName = rawName;
+				   	}
+
+				   	priTrace.addFirstSynchTime(new Integer((int)threadId), new Integer(sampleTime));
+				   	priSamples.add(new PriThread(new Integer((int)threadId), threadName, processName));
+
+				   	// read the next length
+					length = dis.readUnsignedByte(); readCount++;
+				}
+				else if (mode == 0xdd)
+				{
+					// reading data
+					long[] elements = this.readDataElements110Pri(dis, length, sample);
+					
+					rawV110PriSamples.add(elements);
+					lastSampleRaw.add(elements);
+
+					// read the next length
+					length = dis.readUnsignedByte(); readCount++;
+				}
+				else if (mode == 0x00)
+				{
+					// duplicate the previous sample to replace the missing sample
+					Enumeration<long[]> e = lastSampleRaw.elements();
+					while(e.hasMoreElements())
+					{
+						long[] element = e.nextElement();
+						long[] newElement = new long[7];
+						newElement[0] = element[0];
+						newElement[1] = element[1];
+						//newElement[2] = element[2];
+						//newElement[3] = element[3];
+						//newElement[4] = element[4];
+						//newElement[5] = element[5];
+						// replace the sample number with the missing one
+						newElement[2] = sample;
+						// add the duplicated sample
+						rawV110PriSamples.add(newElement);
+					}
+					
+					// read the length, it is already known
+					sample = readTUint(dis);
+					System.out.println(Messages.getString("MemTraceParser.sampleRead") + sample); //$NON-NLS-1$
+					length = dis.readUnsignedByte(); readCount++;;
+				}
+				else
+				{
+					throw new Exception(Messages.getString("MemTraceParser.parseErrorWrongMode") + mode); //$NON-NLS-1$
+				}
+			}
+		}
+		catch (EOFException e)
+		{
+			System.out.println(Messages.getString("MemTraceParser.finishedReading")); //$NON-NLS-1$
+			this.addRawV110PriSamples(rawV110PriSamples);
+		}
+	}
+
+	private void addRawV110PriSamples(Vector<long[]> rawV110PriSamples)
+	{
+	    PriThread[] priThreads = new PriThread[priSamples.size()];
+	    priSamples.copyInto((PriThread[]) priThreads);
+	    priTrace.setThreads(priThreads);
+	    
+	    Enumeration<long[]> rawEnum = rawV110PriSamples.elements();
+	    while(rawEnum.hasMoreElements())
+	    {
+	    	long[] element = rawEnum.nextElement();
+	    	threadId = (int)element[0];
+	    	threadPriority = (int)element[1];
+
+	    	// for the null thread, converts 8bit unsigned to signed
+	    	if (threadPriority > 32768)
+	    	    threadPriority = threadPriority - 65536;
+
+	    	sampleTime = (int)element[2]; 
+
+	    	for (Enumeration<PriThread> e = priSamples.elements(); e.hasMoreElements(); )
+	    	{
+	    		PriThread pt = e.nextElement();
+	    		if (pt.threadId.intValue() == threadId)
+	    		{
+	    			priSample = new PriSample(pt, threadPriority, sampleTime);
+	    			priTrace.addSample(priSample);
+	    			break;
+	    		}
+	    	}
+
+	    	priTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleTime));
+	    }
+	    if (debug) System.out.println(Messages.getString("MemTraceParser.parsingDone")); //$NON-NLS-1$
+	}
+
+	private long[] readDataElements085Mem(DataInputStream dis,int length,long sampleTime) throws Exception
+	{
+		if (length != 0)
+		{
+			long[] elements = new long[7];
+			elements[0] = this.readTUint(dis);
+			elements[1] = this.readTUint(dis);
+			elements[2] = this.readTUint(dis);
+			elements[3] = this.readTUint(dis);
+			elements[4] = this.readTUint(dis);
+			elements[5] = this.readShort(dis);
+			elements[6] = sampleTime;
+
+			return elements;
+		}
+		else 
+		{
+			System.out.println(Messages.getString("MemTraceParser.dataLengthIs0")); //$NON-NLS-1$
+			return null;
+		}
+	}
+
+	private long[] readDataElements110Mem(DataInputStream dis,int length,long sampleTime) throws Exception
+	{
+		if (length != 0)
+		{
+			long[] elements = new long[8]; // added two elements for sample type and name hash, 07092009
+			elements[0] = this.readTUint(dis);
+			elements[1] = this.readTUint(dis);
+			elements[2] = this.readTUint(dis);
+			elements[3] = this.readTUint(dis);
+			elements[4] = this.readTUint(dis);
+			elements[5] = sampleTime;
+			
+			if (elements[3] != 0 && elements[4] != 0)
+				if (debug) System.err.println(Messages.getString("MemTraceParser.bothHeapAndStack")); //$NON-NLS-1$
+
+			return elements;
+		}
+		else 
+		{
+			System.out.println(Messages.getString("MemTraceParser.dataLengthIs0")); //$NON-NLS-1$
+			return null;
+		}
+	}
+
+	private long[] readDataElements110Pri(DataInputStream dis, int length, long sampleTime) throws Exception
+	{
+		if (length != 0)
+		{
+			long[] elements = new long[3];
+			elements[0] = this.readTUint(dis);  //thread ID
+			elements[1] = this.readShort(dis);  //Priority
+			elements[2] = sampleTime;  //sample number
+
+			return elements;
+		}
+		else 
+		{
+			System.out.println(Messages.getString("MemTraceParser.dataLengthIs0")); //$NON-NLS-1$
+			return null;
+		}
+	}
+	
+	private String readThreadName(DataInputStream dis, int length) throws Exception
+	{
+		if (length != 0)
+		{
+			length -=4;
+
+			byte[] element = new byte[length];
+			dis.read(element, 0, length);
+			readCount+=length;
+			return new String(element);
+		}
+		else
+			return null;
+	}
+	
+	private byte[] readElementWithLength(DataInputStream dis) throws Exception
+	{
+		byte length = dis.readByte(); readCount++;
+		if (length != 0)
+		{
+
+			byte[] element = new byte[length];
+			dis.read(element, 0, length);
+			readCount += length;
+			return element;
+		}
+		else return null;
+	}
+	
+	private long readShort(DataInputStream dis) throws Exception
+	{
+		long result = dis.readUnsignedByte();
+		readCount++;
+		result += dis.readUnsignedByte() << 8;
+		readCount++;
+		return result;
+	}
+	
+	private long readTUint(DataInputStream dis) throws Exception
+	{
+		long result = dis.readUnsignedByte();
+		readCount++;
+		result += dis.readUnsignedByte() << 8;
+		readCount++;
+		result += dis.readUnsignedByte() << 16;
+		readCount++;
+		result += dis.readUnsignedByte() << 24;
+		readCount++;
+		return result;
+	}
+
+	private long readTUintWithLength(DataInputStream dis) throws Exception
+	{
+		byte length = (byte)dis.readUnsignedByte();
+		readCount++;
+
+		if (length != 4) 
+		{
+			throw new Exception(Messages.getString("MemTraceParser.parseErrorTUint1") + length + Messages.getString("MemTraceParser.parseErrorTUint2")); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		long result = dis.readUnsignedByte();
+		readCount++;
+		result += dis.readUnsignedByte() << 8;
+		readCount++;
+		result += dis.readUnsignedByte() << 16;
+		readCount++;
+		result += dis.readUnsignedByte() << 24;
+		readCount++;
+		
+		return result;
+	}
+
+	private void parseMemTrace(File file) throws Exception
+	{
+		DataInputStream dis = new DataInputStream(new FileInputStream(file));		
+	    byte[] traceArray = new byte[(int)file.length()];
+	    dis.readFully(traceArray);
+	    
+	    // test the mem trace version
+	    if (traceArray.length > 257)
+	    {
+	    	String s = new String(traceArray,1,traceArray[0]);
+	    	if (!s.startsWith("Bappea_V2.01") && !s.startsWith("Bappea_V1.56")) //up to 1.10 version //$NON-NLS-1$ //$NON-NLS-2$
+	    	{
+	    		if (s.startsWith("Bappea_V1.10")) //$NON-NLS-1$
+	    		{
+		    	    //String version = s.substring(8,12);
+		    	    parseVersion110Trace(traceArray,s);
+
+		    	    return;
+	    		} 	
+	    		else if(s.startsWith("Bappea_V2.02")) 
+	    		{
+		    		parseVersion157Trace(traceArray,s);
+		    		return;
+		    	} 
+
+	    		String version = s.substring(8, 12);
+	    		String traceType = s.substring(13, s.length());
+	    		System.out.println(Messages.getString("MemTraceParser.foundVersion1") + version + Messages.getString("MemTraceParser.foundVersion2") + traceType + Messages.getString("MemTraceParser.foundVersion3")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	    		if (!traceType.equals("MEM")) //$NON-NLS-1$
+	    		{
+	    			GeneralMessages.showErrorMessage(Messages.getString("MemTraceParser.wrongTraceType1") + traceType + Messages.getString("MemTraceParser.wrongTraceType2")); //$NON-NLS-1$ //$NON-NLS-2$
+	    			throw new Exception(Messages.getString("MemTraceParser.wrongTraceType1") + traceType + Messages.getString("MemTraceParser.wrongTraceType2")); //$NON-NLS-1$ //$NON-NLS-2$
+	    		}
+	    		else
+	    		{
+	    		    ByteArrayInputStream bais = new ByteArrayInputStream(traceArray);
+	    		    dis = new DataInputStream(bais);
+	    			parseNewMemFile(version,dis);
+	    			return;
+	    		}
+	    	}
+	    	else //handling 1.55 and newer versions
+	    	{
+	    		this.traceVersion = s;
+	    	    parseVersion155Trace(traceArray,s);
+
+	    	    return;
+	    	}
+	    }
+	    System.out.println(Messages.getString("MemTraceParser.parsingOldVersion")); //$NON-NLS-1$
+	    
+	    ByteArrayInputStream bais = new ByteArrayInputStream(traceArray);
+	    dis = new DataInputStream(bais);
+	    
+	    int listLength = this.findThreadListLength(dis, traceArray.length);
+	    if (listLength == -1)
+	    {
+	    	GeneralMessages.showErrorMessage(Messages.getString("MemTraceParser.invalidTraceFileOverflow")); //$NON-NLS-1$
+	    	System.out.println(Messages.getString("MemTraceParser.invalidTraceFile")); //$NON-NLS-1$
+	    	throw new Exception(Messages.getString("MemTraceParser.invalidTraceFile")); //$NON-NLS-1$
+	    }
+	    memTrace = new MemTrace();
+	    priTrace = new PriTrace();
+	    
+	    for (int i = 0; i < listLength; )
+	    {
+	    	int j = 0;
+	    	for (j = 0; j < buffer.length; j++)
+	    	{
+	    		byte tmpByte = dis.readByte();
+	    		if (tmpByte != 0)
+	    		{
+	    			buffer[j] = (char)tmpByte;
+	    		}
+	    		else
+	    		{
+	    			dis.skipBytes(buffer.length - j - 1);
+	    			break;
+	    		}
+	    	}
+	    	
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+	    	threadId = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff));
+	    			  
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+	    	sampleTime = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff));
+	    	String unparsedName = new String(buffer);
+	    	int index = 0;
+	    	while ((unparsedName.charAt(index++) != ':') && (index < buffer.length)){}
+	    	processName = unparsedName.substring(0, index - 1);
+	    	threadName = unparsedName.substring(index + 1,  j);
+
+	    	memTrace.addFirstSynchTime(new Integer(threadId), new Integer(sampleTime));
+	    	memSamples.add(new MemThread(new Integer(threadId), threadName, processName));
+	    	priTrace.addFirstSynchTime(new Integer(threadId), new Integer(sampleTime));
+	    	priSamples.add(new PriThread(new Integer(threadId), threadName, processName));
+
+	    	i += buffer.length + 8;
+	    }
+	    MemThread[] threads = new MemThread[memSamples.size()];
+	    memSamples.copyInto((MemThread[]) threads);
+	    memTrace.setThreads(threads);
+	    PriThread[] priThreads = new PriThread[priSamples.size()];
+	    priSamples.copyInto((PriThread[]) priThreads);
+	    priTrace.setThreads(priThreads);
+	    dis.skipBytes(8); //skipping "LIST_END" text
+	    for (int k = 0; k < traceArray.length - listLength - 8; )
+	    {
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+
+	    	threadId = ((c & 0xff) << 8) | (d & 0xff);
+	    	processPriority = b;
+			threadPriority = a;
+	    	
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+	    	heapSize = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff));
+	    	
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+	    	stackSize = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff));
+	    	
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+	    	sampleTime = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff));
+	    	for (Enumeration<MemThread> e = memSamples.elements(); e.hasMoreElements(); )
+	    	{
+	    		MemThread mt = e.nextElement();
+	    		if (mt.threadId.intValue() == threadId)
+	    		{
+	    			sample = new MemSample(mt, heapSize, stackSize, sampleTime);
+	    			memTrace.addSample(sample);
+	    			break;
+	    		}
+	    	}
+	    	for (Enumeration<PriThread> e = priSamples.elements(); e.hasMoreElements(); )
+	    	{
+	    		PriThread pt = e.nextElement();
+	    		if (pt.threadId.intValue() == threadId)
+	    		{
+	    			int priority = solveAbsolutPriority(processPriority, threadPriority);
+	    			priSample = new PriSample(pt, priority, sampleTime);
+	    			priTrace.addSample(priSample);
+	    			break;
+	    		}
+	    	}
+	    	memTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleTime));
+	    	priTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleTime));
+	    	k += 16;
+	    }
+	    if (debug) System.out.println(Messages.getString("MemTraceParser.parsingDone")); //$NON-NLS-1$
+	    
+	}
+	
+	private void parseVersion110Trace(byte[] traceArray, String version_data) throws Exception
+	{
+	    
+		String version = version_data.substring(8, 12);
+	    ByteArrayInputStream bais = new ByteArrayInputStream(traceArray);
+	    DataInputStream dis = new DataInputStream(bais);
+
+    	if (version_data.indexOf("MEM") > 0 && version_data.indexOf("PRI") > 0) //version 1.10 or newer //$NON-NLS-1$ //$NON-NLS-2$
+    	{
+    	    parseNewMemFile(version,dis);
+    	}
+    	else if (version_data.indexOf("MEM") > 0) //only memtrace //$NON-NLS-1$
+    	{
+    	    this.parseV110MemFile(dis);
+    	}
+    	else if (version_data.indexOf("PRI") > 0) //only pritrace //$NON-NLS-1$
+    	{
+    	    this.parseV110PriFile(dis);
+    	}
+	}
+	
+	private void parseVersion155Trace(byte[] traceArray, String version_data) throws Exception
+	{
+    	if (version_data.indexOf("MEM")>0) //version 1.55 or newer //$NON-NLS-1$
+    	{
+    	    ByteArrayInputStream bais = new ByteArrayInputStream(traceArray);
+    	    DataInputStream dis = new DataInputStream(bais);
+
+    	    this.parseV155MemFile(dis);
+    	}
+	}
+
+	private void parseVersion157Trace(byte[] traceArray, String version_data) throws Exception
+	{
+	    
+//		String version = version_data.substring(8,12);
+//		String traceType = version_data.substring(13,version_data.length());
+	    ByteArrayInputStream bais = new ByteArrayInputStream(traceArray);
+	    DataInputStream dis = new DataInputStream(bais);
+
+    	if (version_data.indexOf("MEM")>0) //version 1.57 or newer
+    	{
+    	    this.parseV157MemFile(dis);
+    	}
+	}
+	
+	private int calcSamplingTime()
+	{
+	    long time;
+	    
+	    if (memTrace != null) //if memtrace exists
+	    {
+	        time = memTrace.getFirstSampleNumber();
+	        for (Enumeration e = memTrace.getSamples(); e.hasMoreElements(); )
+	        {
+	            MemSample tmp = (MemSample) e.nextElement();
+	            if (tmp.sampleSynchTime != time)
+	            {
+	                time = tmp.sampleSynchTime - time;
+	                return (int) time;
+	            }
+	        }
+	    return defaultSamplingTime;
+	    }
+	    else if (priTrace != null) //if pritrace exists
+	    {
+	        time = priTrace.getFirstSampleNumber();
+	        for (Enumeration e = priTrace.getSamples(); e.hasMoreElements(); )
+	        {
+	            PriSample tmp = (PriSample) e.nextElement();
+	            if (tmp.sampleSynchTime != time)
+	            {
+	                time = tmp.sampleSynchTime - time;
+	                return (int) time;
+	            }
+	        }
+	    }
+	    //else
+	    System.out.println(Messages.getString("MemTraceParser.shouldNotHappen")); //$NON-NLS-1$
+	    return 0;
+	}
+	
+	private GenericSampledTrace getTrace()
+	{
+		return (GenericSampledTrace) memTrace;
+	}
+	
+	public ParsedTraceData getPriorityTrace()
+	{
+	    if (priTrace != null)
+	    {
+	        if (priTrace.getPriSample(0).priority != 0)
+	        {
+	            priTrace.setSamplingTime(samplingTime);
+	            ParsedTraceData ptd = new ParsedTraceData();
+	    		ptd.traceData = priTrace;
+	    		return ptd;
+	        }
+	    }
+
+		return null;
+	}
+	
+	private int solveAbsolutPriority(int processPriority, int threadPriority)
+	{
+		int tPriority = threadPriority * 10 - 30;
+		int pPriority = processPriority * 10;
+		switch (tPriority)
+		{
+			case 100:		//EPriorityAbsoluteVeryLow
+				return 100;
+			case 200:		//EPriorityAbsoluteLow
+				return 200;
+			case 300:		//EPriorityAbsoluteBackground
+				return 300;
+			case 400:		//EPriorityAbsoluteForeground
+				return 400;
+			case 500:		//EPriorityAbsoluteHigh
+				return 500;
+			case -30:		//EPriorityNull
+				return 0;
+			case 30:		//EPriorityRealTime
+				return 850;
+			case -20:		//EPriorityMuchLess
+				return pPriority - 20;
+			case -10:		//EPriorityLess
+				return pPriority - 10;
+			case 0:			//EPriorityNormal
+				return pPriority;
+			case 10:		//EPriorityMore
+				return pPriority + 10;
+			case 20:		//EPriorityMuchMore
+				return pPriority + 20;
+			default:
+				return 0;
+		}
+	}
+
+	private int findThreadListLength(DataInputStream dis, int traceLength) throws Exception
+	{
+		char[] buf = new char[8];
+		for (int i = 0; i < traceLength / 8; i++)
+		{
+			for (int j = 0; j < 8; j++)
+			{
+				buf[j % 8] = (char)dis.readByte();
+			}
+			if (new String(buf).matches("LIST_END")) //$NON-NLS-1$
+			{
+				dis.reset();
+				return i * 8;
+			}
+		}
+		dis.reset();
+		return -1;
+	}
+	
+	private int convertVersionStringToInt(String version){
+		// Coverts version number from string to int
+		int i = 0;
+		int versionInt = 0;
+		String versionString = "";
+		
+		// goes string thru and copies all digits into another string
+		while( i < version.length() ){
+			if( Character.isDigit(version.charAt(i)) ){
+				versionString += version.charAt(i);
+			}
+			i++;
+			
+		}
+		
+		// convert string to int
+		try {
+			versionInt = Integer.parseInt(versionString);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return versionInt;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemoryPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.memory;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Version;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.memory.actions.MemoryStatisticsDialog;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IReportable;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IViewMenu;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.internal.pi.visual.GraphDrawRequest;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class MemoryPlugin extends AbstractPiPlugin
+	implements IViewMenu, ITrace, IClassReplacer, IVisualizable, IEventListener, IReportable
+{
+	private static final String HELP_CONTEXT_ID = PIPageEditor.PI_ID + ".memory";  //$NON-NLS-1$
+
+	// There will be 1 graph for editor page 0
+	// This code may assume that page 0 has the threads graph
+	private final static int GRAPH_COUNT = 3;
+
+	//The shared instance.
+	private static MemoryPlugin plugin;
+	
+	// version number of profiler
+	private String profilerVersion = "";
+	
+	private static void setPlugin(MemoryPlugin newPlugin)
+	{
+		plugin = newPlugin;
+	}
+	
+	/**
+	 * The constructor.
+	 */
+	public MemoryPlugin() {
+		super();
+		setPlugin(this);
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		setPlugin(null);
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static MemoryPlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractPiPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi.memory", path); //$NON-NLS-1$
+	}
+
+	public Class getTraceClass() 
+	{
+		return MemTrace.class;
+	}
+
+	public Class getReplacedClass(String className)
+	{
+		if (   className.indexOf("com.nokia.carbide.cpp.pi.memory.MemTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("com.nokia.carbide.pi.memory.MemTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.model.MemTrace") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.memTracePlugin.MemTrace") != -1) //$NON-NLS-1$
+		{
+			return MemTrace.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.memory.MemSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.memory.MemSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.model.MemSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.memTracePlugin.MemSample") != -1) //$NON-NLS-1$
+		{
+			return MemSample.class;
+		}
+		else if (   className.indexOf("[Lcom.nokia.carbide.cpp.pi.memory.MemThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("[Lcom.nokia.carbide.pi.memory.MemThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("[Lfi.vtt.bappea.model.MemThread;") != -1 //$NON-NLS-1$
+				 || className.indexOf("[Lfi.vtt.bappea.memTracePlugin.MemThread") != -1) //$NON-NLS-1$
+		{
+			return MemThread[].class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.memory.MemThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.memory.MemThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.model.MemThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.memTracePlugin.MemThread") != -1) //$NON-NLS-1$
+		{
+			return MemThread.class;
+		}
+		else
+			return null;
+	}
+
+	public void initialiseTrace(GenericTrace trace) 
+	{
+		if (!(trace instanceof MemTrace))
+			return;
+
+		MemTrace memTrace = (MemTrace)trace;
+		
+		/*if(!profilerVersion.equalsIgnoreCase("")) {
+	        // set version, needed by mem trace graph to support event based trace data
+			// convert version number from string to double
+			int versionNumber = convertVersionStringToInt(profilerVersion);
+			memTrace.setVersion(versionNumber);
+		} */
+		
+		NpiInstanceRepository.getInstance().activeUidAddTrace("com.nokia.carbide.cpp.pi.memory", trace); //$NON-NLS-1$
+
+		memTrace.gatherDrawData();
+		
+	  	System.out.println(Messages.getString("MemoryPlugin.traceProcessed")); //$NON-NLS-1$
+	}
+
+	public String getTraceName() {
+		return "Memory"; //$NON-NLS-1$
+	}
+	
+	public int getTraceId() {
+		return 4;
+	}
+
+	public ParsedTraceData parseTraceFile(File file) throws Exception 
+	{
+		ParsedTraceData traceData = null;
+		try
+        {
+            MemTraceParser memParser = new MemTraceParser();
+            traceData = memParser.parse(file);
+            
+            //the profiler version data is stored in mem trace parser
+            //profilerVersion = memParser.getProfilerVersion();
+           
+            return traceData;
+        } catch (Exception e)
+        {
+            e.printStackTrace();
+            throw e;
+        }
+	}
+
+	public MenuManager getViewOptionManager() {
+		if (NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.memory") == null) //$NON-NLS-1$
+			return null;	// no trace, so no MenuManager
+		
+		boolean showChunk  = true;
+		boolean showHeapStack = true;
+		
+		// if there is a showChunk value associated with the current Analyser tab, then use it
+		Object obj;
+		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.memory.showChunk");	//$NON-NLS-1$
+		if ((obj != null) && (obj instanceof Boolean))
+			// retrieve the current value
+			showChunk = (Boolean)obj;
+		else
+			// set the initial value
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.memory.showChunk", showChunk);	//$NON-NLS-1$
+		
+		// if there is a showHeapStack value associated with the current Analyser tab, then use it
+		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.memory.showHeapStack"); //$NON-NLS-1$
+		if ((obj != null) && (obj instanceof Boolean))
+			// retrieve the current value
+			showHeapStack = (Boolean)obj;
+		else
+			// set the initial value
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.memory.showHeapStack", showHeapStack); //$NON-NLS-1$
+	
+		Action action;
+		
+		MenuManager manager = new MenuManager(Messages.getString("MemoryPlugin.memoryGraph")); //$NON-NLS-1$
+
+		action = new Action(Messages.getString("MemoryPlugin.memoryStats"), Action.AS_PUSH_BUTTON) { //$NON-NLS-1$
+			public void run() {
+				new MemoryStatisticsDialog(Display.getCurrent());
+			}
+		};
+		
+		action.setToolTipText(Messages.getString("MemoryPlugin.memoryStatsTooltip")); //$NON-NLS-1$
+		manager.add(action);
+		
+		manager.add(new Separator());
+
+		action = new Action(Messages.getString("MemoryPlugin.showChunks"), Action.AS_RADIO_BUTTON) { //$NON-NLS-1$
+			public void run() {
+				if (this.isChecked())
+					receiveSelectionEvent("chunk_on"); //$NON-NLS-1$
+			}
+		};
+		action.setChecked(showChunk && !showHeapStack);
+		action.setToolTipText(Messages.getString("MemoryPlugin.showChunksTooltip")); //$NON-NLS-1$
+		manager.add(action);
+
+		action = new Action(Messages.getString("MemoryPlugin.showHeapStack"), Action.AS_RADIO_BUTTON) { //$NON-NLS-1$
+			public void run() {
+				if (this.isChecked())
+					receiveSelectionEvent("heapstack_on");  //$NON-NLS-1$
+			}
+		};
+		action.setChecked(showHeapStack && !showChunk);
+		action.setToolTipText(Messages.getString("MemoryPlugin.showHeapStackTooltip")); //$NON-NLS-1$
+		manager.add(action);
+
+		action = new Action(Messages.getString("MemoryPlugin.showAll"), Action.AS_RADIO_BUTTON) { //$NON-NLS-1$
+			public void run() {
+				if (this.isChecked())
+					receiveSelectionEvent("chunk_heapstack_on"); //$NON-NLS-1$
+			}
+		};
+		action.setChecked(showChunk && showHeapStack);
+		action.setToolTipText(Messages.getString("MemoryPlugin.showAllTooltip")); //$NON-NLS-1$
+		manager.add(action);
+
+		manager.add(new Separator());
+
+		boolean rescale = false;
+		
+		// if there is a rescale value associated with the current Analyser tab, then use it
+		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.memory.rescale"); //$NON-NLS-1$
+		if ((obj != null) && (obj instanceof Boolean))
+			// retrieve the current value
+			rescale = (Boolean)obj;
+		else
+			// set the initial value
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.memory.rescale", rescale); //$NON-NLS-1$
+		
+		action = new Action(Messages.getString("MemoryPlugin.dynamicRescale"), Action.AS_CHECK_BOX) { //$NON-NLS-1$
+			public void run() {
+				if (this.isChecked())
+					receiveSelectionEvent("rescale_on"); //$NON-NLS-1$
+				else
+					receiveSelectionEvent("rescale_off"); //$NON-NLS-1$
+			}
+		};
+		action.setChecked(rescale);
+		action.setToolTipText(Messages.getString("MemoryPlugin.dynamicRescaleTooltip")); //$NON-NLS-1$
+		manager.add(action);
+
+		return manager;
+	}
+
+	public void receiveEvent(String actionString, Event event) {
+		MemTrace trace = (MemTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.memory"); //$NON-NLS-1$
+
+		if (trace == null)
+			return;
+
+		if (   actionString.equals("chunk_on")  //$NON-NLS-1$
+			|| actionString.equals("heapstack_on")  //$NON-NLS-1$
+			|| actionString.equals("chunk_heapstack_on")  //$NON-NLS-1$
+			|| actionString.equals("rescale_on")  //$NON-NLS-1$
+			|| actionString.equals("rescale_off")) //$NON-NLS-1$
+		{
+			((MemTraceGraph)trace.getTraceGraph(PIPageEditor.THREADS_PAGE)).action(actionString);
+			((MemTraceGraph)trace.getTraceGraph(PIPageEditor.BINARIES_PAGE)).action(actionString);
+			((MemTraceGraph)trace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).action(actionString);
+		} else if (actionString.equals("scroll")) //$NON-NLS-1$
+		{
+			if (   !(event.data instanceof String)
+				|| !((String)event.data).equals("FigureCanvas")) //$NON-NLS-1$
+				return;
+			
+			PIEvent be = new PIEvent(event, PIEvent.SCROLLED);
+			
+			((MemTraceGraph)trace.getTraceGraph(PIPageEditor.THREADS_PAGE)).piEventReceived(be);
+			((MemTraceGraph)trace.getTraceGraph(PIPageEditor.BINARIES_PAGE)).piEventReceived(be);
+			((MemTraceGraph)trace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).piEventReceived(be);
+		}
+	}
+
+	public void receiveSelectionEvent(String actionString) 
+	{
+		if (actionString == null)
+			return;
+
+		if (actionString.equals("chunk_on")) { //$NON-NLS-1$
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.memory.showChunk", true); //$NON-NLS-1$
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.memory.showHeapStack", false); //$NON-NLS-1$
+		} else if (actionString.equals("heapstack_on")) { //$NON-NLS-1$
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.memory.showChunk", false); //$NON-NLS-1$
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.memory.showHeapStack", true); //$NON-NLS-1$
+		} else if (actionString.equals("chunk_heapstack_on")) { //$NON-NLS-1$
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.memory.showChunk", true); //$NON-NLS-1$
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.memory.showHeapStack", true); //$NON-NLS-1$
+		} else if (actionString.equals("rescale_on")) { //$NON-NLS-1$
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.memory.rescale", true); //$NON-NLS-1$
+		} else if (actionString.equals("rescale_off")) { //$NON-NLS-1$
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.memory.rescale", false); //$NON-NLS-1$
+		} else {
+			return;
+		}
+
+		((MemTraceGraph)this.getTraceGraph(PIPageEditor.THREADS_PAGE)).action(actionString);
+		((MemTraceGraph)this.getTraceGraph(PIPageEditor.BINARIES_PAGE)).action(actionString);
+		((MemTraceGraph)this.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE)).action(actionString);
+	}
+
+//	public GenericTraceGraph getTraceGraph() {
+//		MemTrace trace = (MemTrace) PIPageEditor.currentTab().getData("com.nokia.carbide.cpp.pi.memory.trace"); //$NON-NLS-1$
+//
+//		if (trace != null)
+//			return trace.getTraceGraph();
+//		else
+//			return null;
+//	}
+
+	public GenericTraceGraph getTraceGraph(int graphIndex) {
+		MemTrace trace = (MemTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.memory"); //$NON-NLS-1$
+
+		if (trace != null)
+			return trace.getTraceGraph(graphIndex);
+		else
+			return null;
+	}
+
+	public Integer getLastSample(int graphIndex) {
+		MemTrace trace = (MemTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.memory"); //$NON-NLS-1$
+
+		if (trace != null)
+			return new Integer(trace.getLastSampleNumber());
+		else
+			return null;
+	}
+
+	public Hashtable<Integer,Object> getSummaryTable(double start, double end) 
+	{
+//		MemTrace trace = (MemTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.memory"); //$NON-NLS-1$
+//		return ((MemTraceGraph)trace.getTraceGraph(PIPageEditor.currentPageIndex(),PIPageEditor.currentTab())).getTableData();
+		return null;
+	}
+
+	public String getGeneralInfo() {
+		return null;
+	}
+
+	public ArrayList<String> getColumnNames() 
+	{
+		ArrayList<String> names = new ArrayList<String>();
+		names.add(Messages.getString("MemoryPlugin.namesThread")); //$NON-NLS-1$
+		names.add(Messages.getString("MemoryPlugin.namesAvgChunk")); //$NON-NLS-1$
+		names.add(Messages.getString("MemoryPlugin.namesAvgStack")); //$NON-NLS-1$
+		names.add(Messages.getString("MemoryPlugin.namesTotal")); //$NON-NLS-1$
+		return names;
+	}
+	
+	public ArrayList<Boolean> getColumnSortTypes() 
+	{
+		ArrayList<Boolean> sortTypes = new ArrayList<Boolean>();
+		sortTypes.add(SORT_BY_NAME);
+		sortTypes.add(SORT_BY_NUMBER);
+		sortTypes.add(SORT_BY_NUMBER);
+		sortTypes.add(SORT_BY_NUMBER);
+		return sortTypes;
+	}
+
+	public String getActiveInfo(Object arg0, double startTime, double endTime) {
+		return null;
+	}
+
+	public MenuManager getReportGeneratorManager() {
+		return null;
+	}
+
+	public GraphDrawRequest getDrawRequest(int graphIndex) {
+		return null;
+	}
+
+	public int getGraphCount() {
+		return GRAPH_COUNT;
+	}
+
+	public int getPageNumber(int graphIndex) {
+		// Assumes page 0 has the threads graph, 1 has the binaries, and 2 has the functions
+		if (graphIndex == 0)
+			return PIPageEditor.THREADS_PAGE;
+		else if (graphIndex == 1)
+			return PIPageEditor.BINARIES_PAGE;
+		else if (graphIndex == 2)
+			return PIPageEditor.FUNCTIONS_PAGE;
+
+		return PIPageEditor.NEXT_AVAILABLE_PAGE;
+	}
+
+	// return whether this plugin's editor pages have been created
+	public boolean arePagesCreated() {
+		return false;
+	}
+
+	public void setPagesCreated(boolean pagesCreated) {
+		return;
+	}
+
+	public int getCreatePageCount() {
+		return 0;
+	}
+
+	public int getCreatePageIndex(int index) {
+		return 0;
+	}
+
+	public ProfileVisualiser createPage(int index) {
+		return null;
+	}
+
+	public void setPageIndex(int index, int pageIndex) {
+		return;
+	}
+
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable#getGraphTitle(int)
+	 */
+	public String getGraphTitle(int graphIndex) {
+		return Messages.getString("MemoryPlugin.pluginTitle"); //$NON-NLS-1$
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/MemoryReturnPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.memory;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IReturnPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+
+
+public class MemoryReturnPlugin implements IReturnPlugin {
+	public AbstractPiPlugin getPlugin() {
+		return MemoryPlugin.getDefault();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.memory;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.memory.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.memory/src/com/nokia/carbide/cpp/pi/memory/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,100 @@
+MemoryPlugin.memoryGraph=Memory Graph
+MemoryPlugin.memoryStats=Memory Usage Statistics
+MemoryPlugin.memoryStatsTooltip=Show memory usage statistics for the selected interval
+MemoryPlugin.namesThread=Thread
+MemoryPlugin.pluginTitle=Memory Usage
+MemThreadTable.kbFormat=\#,\#\#\#\#,\#\#\# KB
+MemThreadTable.copyTable=Copy Table
+MemThreadTable.SaveTable=Save Table...
+MemThreadTable.notRecorded1=0,
+MemThreadTable.notRecorded2=,*not recorded*,*not recorded*\n
+MemThreadTable.saveCheckedSamples=Save Memory Samples for Checked Table Entries...
+MemThreadTable.saveSamplesHeading=Time (ms),Thread/Chunk,Chunk Size (KB),Stack/Heap Size (KB)\n
+MemThreadTable.memory=Memory
+MemThreadTable.comma=,
+MemoryPlugin.showChunks=Show Chunk Usage
+MemoryPlugin.namesTotal=Total
+MemTraceParser.sampleRead=Read next sample \#
+MemTraceParser.newSample=Length = 0, New sample
+MemTraceParser.nextLength=Next length 
+MemTraceParser.rawName1=Raw name 
+MemTraceParser.rawName2=\ id 
+MemTraceGraph.KBformat=\#\#,\#\#\#,\#\#\# KB
+MemTraceGraph.MBformat=\#\#\#\#\#.0
+MemTraceGraph.graphTitle=Memory Usage
+MemoryPlugin.showAll=Show Chunk and Stack/Heap Usage
+MemoryPlugin.showHeapStack=Show Stack/Heap Usage
+MemoryPlugin.namesAvgChunk=Average Chunk
+MemoryPlugin.namesAvgStack=Average Stack
+MemoryPlugin.showAllTooltip=Show chunk and heap/stack memory usage
+MemoryPlugin.dynamicRescale=Dynamically Rescale Based on Selected Threads
+MemoryPlugin.dynamicRescaleTooltip=Rescale graph based on the currently selected threads
+MemTraceParser.parsingDone=Memory trace parsing done
+MemTraceParser.missingType=Parse error, type after sample missing
+MemTraceParser.readingDone=Finished reading
+MemTraceParser.sizeOfParse=Done parsing, size: 
+MemTraceGraph.byKB=\ KB
+MemTraceGraph.byMB=\ MB
+MemoryPlugin.traceProcessed=memory trace parsed
+MemTraceParser.dataLengthIs0=Data element length is 0
+MemTraceParser.foundVersion1=Found version 
+MemTraceParser.foundVersion2=\ 
+MemTraceParser.foundVersion3=\ trace file 
+MemTraceParser.nextSampleNum=Read next sample \#
+MemTraceGraph.totalTooltip1=s:   chunks 
+MemTraceGraph.totalTooltip2=\ \ \ stack/heap 
+MemTraceGraph.chunkTooltip1=s: chunks 
+MemTraceGraph.chunkTooltip2=KB
+MemoryPlugin.showChunksTooltip=Show only chunk usage memory usage
+MemTraceParser.traceFileLength=Memory trace file length 
+MemTraceParser.readVersionDebug=Read version 
+MemTraceParser.readVersion=Read version 
+MemTraceParser.finishedReading=Finished reading
+MemTraceParser.parseErrorTUint1=Parse error, TUint length other than 32 bits (it is 
+MemTraceParser.parseErrorTUint2=\ )
+MemTraceParser.wrongTraceType1=Wrong trace type 
+MemTraceParser.wrongTraceType2=\ as memory trace file
+MemTraceParser.wrongLength=Parse error, wrong length 
+MemTraceParser.wrongMode=Parse error, wrong mode 
+MemTraceParser.invalidTraceFile=Not valid memory trace file
+MemTraceParser.invalidSampleNum=Invalid sample number: 
+MemTraceParser.invalidSample=Parse error, invalid memory sample
+MemTraceParser.bothHeapAndStack=Element has both heap and stack\!\!
+MemTraceGraph.traceDataNotFound=Memory trace data not found\!
+MemTraceGraph.stackHeapTooltip1=s: stack/heap 
+MemTraceGraph.stackHeapTooltip2=KB
+MemTraceParser.shouldNotHappen=Should not happen, memory trace
+MemoryPlugin.showHeapStackTooltip=Show only heap/stack memory usage
+MemTraceParser.parsingOldVersion=Parsing old (v.0.85 or older) type memory trace file
+MemTraceGraph.byByte=\ B
+MemTraceParser.cannotOpenTraceFile=Unable to open memory trace file
+MemTraceParser.traceVersionException1=Memory trace format version 
+MemTraceParser.traceVersionException2=\ is not supported by this version of analyser
+MemTraceGraph.threadProcessNoSamples1=Thread/chunk 
+MemTraceParser.parseErrorTypeMissing=Memory trace parse error, type after sample missing
+MemTraceParser.missingSampleNumber=Memory trace missing sample \#
+MemTraceParser.missingSampleNum=Missing sample \#
+MemTraceParser.parseErrorWrongLength=Memory trace parse error, wrong length 
+MemTraceGraph.threadProcessNoSamples=\ has no samples\!
+MemTraceParser.parseErrorWrongMode=Memory trace parse error, wrong mode 
+MemTraceParser.invalidTraceFileOverflow=Not valid memory trace file, possible profiler Buffer Overflow during trace?
+MemoryStatisticsDialog.KBformat=\#\#\#\#\#\#,\#\#0 KB
+MemoryStatisticsDialog.BytesFormat=\ (\#\#\#\#\#\#\#\#\#\#\#\#\#,\#\#\# bytes)
+MemoryStatisticsDialog.statistics=Memory Usage Statistics
+MemoryStatisticsDialog.interval=Interval
+MemoryStatisticsDialog.used=Used  
+MemoryStatisticsDialog.free=Free  
+MemoryStatisticsDialog.total=Total 
+MemoryStatisticsDialog.chunks=Chunks     
+MemoryStatisticsDialog.stackHeap=Stack/Heap 
+MemoryStatisticsDialog.close=Close
+MemoryStatisticsDialog.currentSelection=Current Selection
+MemoryStatisticsDialog.interval1=s  to  
+MemoryStatisticsDialog.interval2=s  =  
+MemoryStatisticsDialog.interval3=s
+#MemoryStatisticsDialog.memoryModel=Memory Model
+#MemoryStatisticsDialog.direct=Direct
+#MemoryStatisticsDialog.moving=Moving
+#MemoryStatisticsDialog.multiple=Multiple
+MemoryStatisticsDialog.notRecorded=*not recorded*
+MemoryStatisticsDialog.onDevice=On Device
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,22 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Power Usage
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.power;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.power.PowerPlugin
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.jface.text,
+ org.eclipse.ui.editors,
+ org.eclipse.ui.workbench.texteditor,
+ org.eclipse.core.resources,
+ org.eclipse.ui.ide,
+ org.eclipse.draw2d,
+ com.nokia.carbide.cpp.pi,
+ com.nokia.carbide.cpp.pi.address,
+ com.nokia.carbide.cpp.pi.core,
+ com.nokia.carbide.cpp.pi.util
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.pi.power;x-friends:="com.nokia.carbide.cpp.pi.power.tests"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+   <extension
+         point="com.nokia.carbide.cpp.pi.piPluginData">
+      <plugin pluginClass="com.nokia.carbide.cpp.pi.power.PowerReturnPlugin"/>
+   </extension>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/internal/pi/power/actions/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.power.actions;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.power.actions.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/internal/pi/power/actions/PowerSettingsDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.power.actions;
+
+import java.text.DecimalFormat;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.power.PwrTrace;
+
+
+public class PowerSettingsDialog {
+
+	private Shell shell;
+	private GridData gridData;
+	private PwrTrace trace;
+	private int batterySize;
+
+	private Text voltageText;
+	private Text batteryText;
+	private DecimalFormat voltageFormat = new DecimalFormat(Messages.getString("PowerSettingsDialog.voltageFormat")); //$NON-NLS-1$
+//	private DecimalFormat batteryFormat = new DecimalFormat("###0");
+	private float newVoltage;
+	private float newBatterySize;
+	
+	public PowerSettingsDialog(Display display)
+	{
+		shell = new Shell(display, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+		shell.setText(Messages.getString("PowerSettingsDialog.powerSettingsTitle")); //$NON-NLS-1$
+		shell.setLayout(new GridLayout(4, false));
+		
+		trace = (PwrTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.power"); //$NON-NLS-1$
+		
+		float voltage = trace.getVoltage();
+		newVoltage = voltage;
+
+		Label voltLabel = new Label(shell, SWT.LEFT);
+		voltLabel.setFont(PIPageEditor.helvetica_9);
+		voltLabel.setText(Messages.getString("PowerSettingsDialog.voltageLabel")); //$NON-NLS-1$
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 2;
+		voltLabel.setLayoutData(gridData);
+
+		voltageText = new Text(shell, SWT.BORDER | SWT.RIGHT);
+		voltageText.setFont(PIPageEditor.helvetica_9);
+		voltageText.setText(voltageFormat.format(voltage));
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.minimumWidth = 60;
+		voltageText.setLayoutData(gridData);
+		
+		Label voltUnitsLabel = new Label(shell, SWT.LEFT);
+		voltUnitsLabel.setFont(PIPageEditor.helvetica_9);
+		voltUnitsLabel.setText(Messages.getString("PowerSettingsDialog.voltageUnits")); //$NON-NLS-1$
+
+		batterySize = (int) trace.getBatterySize();
+		newBatterySize = batterySize;
+
+		Label batteryLabel = new Label(shell, SWT.LEFT);
+		batteryLabel.setFont(PIPageEditor.helvetica_9);
+		batteryLabel.setText(Messages.getString("PowerSettingsDialog.batteryLabel")); //$NON-NLS-1$
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 2;
+		batteryLabel.setLayoutData(gridData);
+
+		batteryText = new Text(shell, SWT.BORDER | SWT.RIGHT);
+		batteryText.setFont(PIPageEditor.helvetica_9);
+		batteryText.setText("" + batterySize);//batteryFormat.format(batterySize)); //$NON-NLS-1$
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.minimumWidth = 60;
+		batteryText.setLayoutData(gridData);
+
+		Label batteryUnitsLabel = new Label(shell, SWT.LEFT);
+		batteryUnitsLabel.setFont(PIPageEditor.helvetica_9);
+		batteryUnitsLabel.setText(Messages.getString("PowerSettingsDialog.batteryUnits")); //$NON-NLS-1$
+
+		// add the voltage listeners
+		voltageText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				double currentVoltage = convert(voltageText, trace.getVoltage(), 0, Float.MAX_VALUE, voltageFormat);
+				newVoltage = (float) (Math.ceil(currentVoltage * 1000) / 1000.0);
+			}
+		});
+
+		voltageText.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				double currentVoltage = convert(voltageText, trace.getVoltage(), 0, Float.MAX_VALUE, voltageFormat);
+				newVoltage = (float) (Math.ceil(currentVoltage * 100) / 100.0);
+			}
+		});
+
+		batteryText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				newBatterySize = convert(batteryText, (int)Math.ceil(trace.getBatterySize()), 0, Integer.MAX_VALUE); 
+			}
+		});
+
+		batteryText.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				newBatterySize = convert(batteryText, (int)Math.ceil(trace.getBatterySize()), 0, Integer.MAX_VALUE); 
+			}
+		});
+
+		Label line = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 4;
+		gridData.minimumHeight = 10;
+		line.setLayoutData(gridData);
+
+		// create the OK button
+		Button ok = new Button(shell, SWT.NONE);
+		ok.setText(Messages.getString("PowerSettingsDialog.ok")); //$NON-NLS-1$
+		gridData = new GridData(SWT.CENTER, SWT.CENTER, true, true);
+		gridData.minimumWidth = 60;
+		gridData.horizontalSpan = 2;
+		ok.setLayoutData(gridData);
+		ok.addSelectionListener(new SelectionListener(){
+
+			public void widgetSelected(SelectionEvent e) {
+				// Update plugins with actions, if voltage of battery size has changed
+				boolean changedVoltage  = trace.getVoltage() != newVoltage;
+				boolean changedSize     = trace.getBatterySize() != newBatterySize;
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+
+				if (changedVoltage) {
+					trace.setVoltage(newVoltage);
+					trace.getPowerGraph(PIPageEditor.THREADS_PAGE,   uid).action("changeVoltage"); //$NON-NLS-1$
+					trace.getPowerGraph(PIPageEditor.BINARIES_PAGE,  uid).action("changeVoltage"); //$NON-NLS-1$
+					trace.getPowerGraph(PIPageEditor.FUNCTIONS_PAGE, uid).action("changeVoltage"); //$NON-NLS-1$
+				}
+
+				if (changedSize) {
+					trace.setBatterySize(newBatterySize);
+					trace.getPowerGraph(PIPageEditor.THREADS_PAGE,   uid).action("changeBatterySize"); //$NON-NLS-1$
+					trace.getPowerGraph(PIPageEditor.BINARIES_PAGE,  uid).action("changeBatterySize"); //$NON-NLS-1$
+					trace.getPowerGraph(PIPageEditor.FUNCTIONS_PAGE, uid).action("changeBatterySize"); //$NON-NLS-1$
+				}
+
+				shell.close();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+		});
+
+		// create the Cancel button
+		Button cancel = new Button(shell, SWT.NONE);
+		cancel.setText(Messages.getString("PowerSettingsDialog.cancel")); //$NON-NLS-1$
+		gridData = new GridData(SWT.LEFT, SWT.CENTER, true, true);
+		gridData.minimumWidth = 60;
+		gridData.horizontalSpan = 2;
+		cancel.setLayoutData(gridData);
+		cancel.addSelectionListener(new SelectionListener(){
+
+			public void widgetSelected(SelectionEvent e) {
+				shell.close();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+		});
+
+		shell.pack();
+		shell.open();
+
+		while (!shell.isDisposed()) {
+			if (!shell.getDisplay().readAndDispatch()) {
+				shell.getDisplay().sleep();
+			}
+		}
+	}
+
+	private double convert(Text text, double currentDouble, double minimum, double maximum, DecimalFormat format)
+	{
+		double new_double;
+
+		// convert, catch (NumberFormatException e1)
+		try {
+			new_double = Double.parseDouble(text.getText().replace(',','.'));
+			if (new_double >= 0)
+				currentDouble = new_double;
+		} catch (NumberFormatException exc) {
+			// just keep the old value
+		}
+
+		if (currentDouble > maximum)
+			currentDouble = maximum;
+		else if (currentDouble < minimum)
+			currentDouble = minimum;
+
+		text.setText(format.format(currentDouble));
+
+		return currentDouble;
+	}
+
+	private int convert(Text text, int currentInt, int minimum, int maximum)
+	{
+		int new_int;
+
+		// convert, catch (NumberFormatException e1)
+		try {
+			new_int = Integer.parseInt(text.getText().replace(',','.'));
+			if (new_int >= 0)
+				currentInt = new_int;
+		} catch (NumberFormatException exc) {
+			// just keep the old value
+		}
+
+		if (currentInt > maximum)
+			currentInt = maximum;
+		else if (currentInt < minimum)
+			currentInt = minimum;
+
+		text.setText("" + currentInt); //$NON-NLS-1$
+
+		return currentInt;
+	}
+
+	public void dispose()
+	{
+		if (this.shell != null) {
+			if (!this.shell.isDisposed()) {
+				this.shell.close();				
+			}
+			this.shell.dispose();
+		}
+
+		this.shell = null;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/internal/pi/power/actions/PowerStatisticsDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.power.actions;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Hashtable;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.power.PowerTraceGraph;
+import com.nokia.carbide.cpp.pi.power.PwrTrace;
+
+
+public class PowerStatisticsDialog {
+
+	private Shell shell;
+	private GridData gridData;
+	private DecimalFormat voltageFormat     = new DecimalFormat(Messages.getString("PowerStatisticsDialog.voltageFormat")); //$NON-NLS-1$
+	private DecimalFormat powerFormat       = new DecimalFormat(Messages.getString("PowerStatisticsDialog.powerFormat")); //$NON-NLS-1$
+
+	private PwrTrace trace;
+	private double startTime;
+	private double endTime;
+	
+	private double levelMaxPower;
+	private double level90Power;
+	private double level75Power;
+	private double level50Power;
+	private double level25Power;
+	private double level10Power;
+	private double levelMinPower;
+	private double levelVarPower;
+
+	public PowerStatisticsDialog(Display display)
+	{
+		int batterySize;
+		float voltage;
+		Group group;
+		
+		shell = new Shell(display, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+		shell.setText(Messages.getString("PowerStatisticsDialog.statsTitle")); //$NON-NLS-1$
+		shell.setLayout(new GridLayout(4, false));
+
+    	startTime = PIPageEditor.currentPageEditor().getStartTime();
+    	endTime   = PIPageEditor.currentPageEditor().getEndTime();
+
+		trace = (PwrTrace)NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.power"); //$NON-NLS-1$
+	
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+
+		PowerTraceGraph graph = trace.getPowerGraph(0, uid); // since they are in lockstep, any graph will do
+
+		voltage = trace.getVoltage();
+		batterySize = (int) trace.getBatterySize();
+
+		calculateStats();
+		
+		group = new Group(shell, SWT.SHADOW_NONE);
+		group.setText(Messages.getString("PowerStatisticsDialog.interval")); //$NON-NLS-1$
+		group.setFont(PIPageEditor.helvetica_9);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 4;
+		group.setLayoutData(gridData);
+		group.setLayout(new GridLayout(4, false));//new FillLayout());
+		textGrid(group, showTimeInterval(startTime, endTime), SWT.CENTER, SWT.CENTER, 4);
+
+		group = new Group(shell, SWT.NONE);
+		group.setText(Messages.getString("PowerStatisticsDialog.battery")); //$NON-NLS-1$
+		group.setFont(PIPageEditor.helvetica_9);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 4;
+		group.setLayoutData(gridData);
+		group.setLayout(new GridLayout(4, false));//new FillLayout());
+		textGrid(group, batterySize + Messages.getString("PowerStatisticsDialog.capacityVoltage2"), SWT.LEFT, SWT.CENTER, 2); //$NON-NLS-1$ //$NON-NLS-2$
+		textGrid(group, Messages.getString("PowerStatisticsDialog.capacityVoltage3") + voltageFormat.format(voltage) + Messages.getString("PowerStatisticsDialog.capacityVoltage4"), SWT.RIGHT, SWT.CENTER, 2); //$NON-NLS-1$ //$NON-NLS-2$
+		
+		group = new Group(shell, SWT.NONE);
+		group.setText(Messages.getString("PowerStatisticsDialog.currentSelection")); //$NON-NLS-1$
+		group.setFont(PIPageEditor.helvetica_9);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 4;
+		group.setLayoutData(gridData);
+		group.setLayout(new GridLayout(4, false));//new FillLayout());
+
+		double meanPower;
+		double meanEnergy;
+		long   meanLife;
+
+		meanPower  = graph.getAverageConsumption();
+		meanEnergy = graph.getCumulativeConsumption();
+		
+		if (meanPower == 0)
+			meanLife = 0;
+		else
+			meanLife = Math.round((float) graph.getBatterySize() * 3600 * graph.getVoltage() / meanPower);
+
+		textGrid(group, Messages.getString("PowerStatisticsDialog.energy1"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$
+		textGrid(group, (int) (meanEnergy + 0.5)
+						+ Messages.getString("PowerStatisticsDialog.energy2"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$
+
+		long hours   = meanLife / 3600;
+		long minutes = (meanLife - hours * 3600) / 60;
+		textGrid(group, Messages.getString("PowerStatisticsDialog.life1"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$
+		textGrid(group, hours + Messages.getString("PowerStatisticsDialog.life2") //$NON-NLS-1$
+						+ minutes + Messages.getString("PowerStatisticsDialog.life3"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$
+
+		textGrid(group, "", SWT.RIGHT, SWT.RIGHT, 4); //$NON-NLS-1$
+
+		textGrid(group, Messages.getString("PowerStatisticsDialog.avgPower1"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$
+		textGrid(group, powerFormat.format(meanPower) + Messages.getString("PowerStatisticsDialog.avgPower2"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$
+
+		textGrid(group, Messages.getString("PowerStatisticsDialog.maxa"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$
+		textGrid(group, powerFormat.format(levelMaxPower / 1000) + Messages.getString("PowerStatisticsDialog.maxb"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$
+
+		textGrid(group, Messages.getString("PowerStatisticsDialog.90a"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$
+		textGrid(group, powerFormat.format(level90Power / 1000) + Messages.getString("PowerStatisticsDialog.90b"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$
+
+		textGrid(group, Messages.getString("PowerStatisticsDialog.75a"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$
+		textGrid(group, powerFormat.format(level75Power / 1000) + Messages.getString("PowerStatisticsDialog.75b"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$
+
+		textGrid(group, Messages.getString("PowerStatisticsDialog.50a"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$
+		textGrid(group, powerFormat.format(level50Power / 1000) + Messages.getString("PowerStatisticsDialog.50b"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$
+
+		textGrid(group, Messages.getString("PowerStatisticsDialog.25a"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$
+		textGrid(group, powerFormat.format(level25Power / 1000) + Messages.getString("PowerStatisticsDialog.25b"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$
+
+		textGrid(group, Messages.getString("PowerStatisticsDialog.10a"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$
+		textGrid(group, powerFormat.format(level10Power / 1000) + Messages.getString("PowerStatisticsDialog.10b"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$
+
+		textGrid(group, Messages.getString("PowerStatisticsDialog.mina"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$
+		textGrid(group, powerFormat.format(levelMinPower / 1000) + Messages.getString("PowerStatisticsDialog.minb"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$
+
+		textGrid(group, Messages.getString("PowerStatisticsDialog.variancea"), SWT.RIGHT, SWT.RIGHT, 2); //$NON-NLS-1$
+		textGrid(group, powerFormat.format(levelVarPower / 1000) + Messages.getString("PowerStatisticsDialog.varianceb"), SWT.CENTER, SWT.CENTER, 2); //$NON-NLS-1$
+
+		// create the Close button
+		Button close = new Button(shell, SWT.NONE);
+		close.setText(Messages.getString("PowerStatisticsDialog.close")); //$NON-NLS-1$
+		gridData = new GridData(SWT.CENTER, SWT.CENTER, true, true);
+		gridData.minimumWidth = 60;
+		gridData.horizontalSpan = 4;
+		close.setLayoutData(gridData);
+		close.addSelectionListener(new SelectionListener(){
+
+			public void widgetSelected(SelectionEvent e) {
+				shell.close();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+		});
+
+		shell.pack();
+		shell.open();
+
+		while (!shell.isDisposed()) {
+			if (!shell.getDisplay().readAndDispatch()) {
+				shell.getDisplay().sleep();
+			}
+		}
+	}
+	
+	private void textGrid(Composite parent, String text, int labelStyle, int gridStyle, int gridSpan)
+	{
+		Label label = new Label(parent, labelStyle);
+		label.setFont(PIPageEditor.helvetica_9);
+		label.setText(text);
+		gridData = new GridData(SWT.FILL, gridStyle, true, true);
+		gridData.horizontalSpan = gridSpan;
+		label.setLayoutData(gridData);		
+	}
+
+	public void dispose()
+	{
+		if (this.shell != null) {
+			if (!this.shell.isDisposed()) {
+				this.shell.close();				
+			}
+			this.shell.dispose();
+		}
+
+		this.shell = null;
+	}
+
+	private static String showTimeInterval(double startTime, double endTime)
+	{
+		return ProfileVisualiser.timeFormat.format(startTime)
+		     + Messages.getString("PowerStatisticsDialog.interval1") + ProfileVisualiser.timeFormat.format(endTime) //$NON-NLS-1$
+		     + Messages.getString("PowerStatisticsDialog.interval2")  + ProfileVisualiser.timeFormat.format(endTime - startTime) //$NON-NLS-1$
+		     + Messages.getString("PowerStatisticsDialog.interval3"); //$NON-NLS-1$
+	}
+
+	private class PowerStat {
+		public double power;
+		public int count;
+		
+		PowerStat(double power) {
+			this.power = power;
+			this.count = 0;
+		}
+		
+		PowerStat(double power, int count) {
+			this.power = power;
+			this.count = count;
+		}
+	}
+	
+	private void calculateStats()
+	{
+		PowerStat powerStat;
+		Object[] powerLevelArray;
+		ArrayList<PowerStat> powerLevel = new ArrayList<PowerStat>();
+		Hashtable<Double,PowerStat> powerStatHash = new Hashtable<Double,PowerStat>();
+		double sumOfSquares = 0.0;
+		double sum = 0.0;
+		int count = 0;
+
+		int selStart = (int)(this.startTime * 1000 + 0.0005) + 1;
+		int selEnd   = (int)(this.endTime * 1000 + 0.0005);
+		int totalCount = selEnd - selStart + 1;
+
+		levelVarPower = 0.0;
+
+		if (selEnd < trace.getFirstSampleNumber() || selStart > selEnd)
+		{
+			powerLevelArray = new PowerStat[1];
+			powerLevelArray[0] = new PowerStat(0.0, 1);
+			totalCount = 1;
+		}
+		else
+		{
+			PowerTraceGraph graph = trace.getPowerGraph(0, NpiInstanceRepository.getInstance().activeUid()); // since graphs are in lockstep, any will do
+
+			int index = graph.timeIndex(selStart);
+
+	        // count time before the first sample as a bunch of zeros
+	        if (selStart < trace.getFirstSampleNumber()) {
+	        	count = trace.getFirstSampleNumber() - selStart;
+				powerStat = new PowerStat(0, count);
+				powerLevel.add(powerStat);
+				powerStatHash.put(0.0, powerStat);
+	        	index = 0;
+	        }
+	        
+	        int[] sampleTimes = trace.getSampleTimes();
+	        int[] ampValues   = trace.getAmpValues();
+	        
+			for (int j = index; j < sampleTimes.length; j++)
+			{	
+				int time = sampleTimes[j] + 1;
+				if (time < selStart)
+					time = selStart;
+				
+				int nextTime = j == sampleTimes.length - 1 ? Integer.MAX_VALUE : sampleTimes[j + 1];
+				
+				count = Math.min(nextTime - time + 1, selEnd - time + 1);
+				double power = ampValues[j] * this.trace.getVoltage() * 1000.0;
+				sumOfSquares += power * power * count;
+				sum += power * count;
+				time += count;
+				
+				powerStat = powerStatHash.get(power);
+				if (powerStat == null) {
+					powerStat = new PowerStat(power,count);
+					powerLevel.add(powerStat);
+					powerStatHash.put(power, powerStat);
+				} else {
+					powerStat.count += count;
+				}
+				
+				if (time > selEnd)
+					break;
+			}
+
+			powerLevelArray = powerLevel.toArray();
+			Arrays.sort(powerLevelArray, new Comparator<Object>() {
+
+				public int compare(Object o1, Object o2) {
+					if (!(o1 instanceof PowerStat) || !(o2 instanceof PowerStat))
+						return 0;
+
+					double powerDiff = ((PowerStat)o1).power - ((PowerStat)o2).power;
+					
+					return powerDiff == 0.0 ? 0	: (powerDiff < 0.0 ? -1 : 1);
+				}
+			});
+		}
+		
+		levelMaxPower = ((PowerStat) powerLevelArray[powerLevelArray.length - 1]).power;
+
+		level90Power  = getPowerLevel(powerLevelArray, (totalCount * 90) / 100);
+		level75Power  = getPowerLevel(powerLevelArray, (totalCount * 75) / 100);
+		level50Power  = getPowerLevel(powerLevelArray, (totalCount * 50) / 100);
+		level25Power  = getPowerLevel(powerLevelArray, (totalCount * 25) / 100);
+		level10Power  = getPowerLevel(powerLevelArray, (totalCount * 10) / 100);
+
+		levelMinPower = ((PowerStat) powerLevelArray[0]).power;
+
+		levelVarPower = (sumOfSquares - (sum * sum)/totalCount)/totalCount;
+	}
+	
+	// given array powerLevelArray of PowerStat elements (each representing PowerStat.count entries), find
+	// power value of entry number index
+	private double getPowerLevel(Object[] powerLevelArray, int index)
+	{
+		if (index == 0 || powerLevelArray == null || powerLevelArray.length == 0)
+			return 0.0;
+		
+		for (int i = 0; (i < powerLevelArray.length) && (powerLevelArray[i] instanceof PowerStat); i++) {
+			PowerStat powerStat = (PowerStat) powerLevelArray[i];
+			if (index <= powerStat.count)
+				return powerStat.power;
+			index -= powerStat.count;
+		}
+		
+		return 0.0;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/internal/pi/power/actions/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,44 @@
+PowerSettingsDialog.voltageFormat=\#0.0\#\#
+PowerStatisticsDialog.voltageFormat=\#0.0\#\#
+PowerStatisticsDialog.powerFormat=\#0.0
+PowerSettingsDialog.powerSettingsTitle=Power Usage Settings
+PowerStatisticsDialog.capacityVoltage2=\ mAh
+PowerStatisticsDialog.capacityVoltage3=\ \ \ \ \ 
+PowerStatisticsDialog.capacityVoltage4=\ V     
+PowerStatisticsDialog.currentSelection=Current Selection
+PowerSettingsDialog.voltageLabel=Voltage:
+PowerSettingsDialog.voltageUnits=V
+PowerSettingsDialog.batteryLabel=Battery capacity:
+PowerSettingsDialog.batteryUnits=mAh
+PowerStatisticsDialog.statsTitle=Power Usage Statistics
+PowerStatisticsDialog.avgPower1=Average power
+PowerStatisticsDialog.avgPower2=\ mW
+PowerStatisticsDialog.variancea=Variance
+PowerStatisticsDialog.varianceb=\ mW^2
+PowerStatisticsDialog.interval1=s  to  
+PowerStatisticsDialog.interval2=s  =  
+PowerStatisticsDialog.interval3=s
+PowerStatisticsDialog.interval=Interval
+PowerSettingsDialog.ok=OK
+PowerSettingsDialog.cancel=Cancel
+PowerStatisticsDialog.energy1=Energy estimate
+PowerStatisticsDialog.energy2=\ mJ
+PowerStatisticsDialog.battery=Battery
+PowerStatisticsDialog.life1=Battery life estimate
+PowerStatisticsDialog.life2=\ h  
+PowerStatisticsDialog.life3=\ m
+PowerStatisticsDialog.maxa=Maximum
+PowerStatisticsDialog.maxb=\ mW
+PowerStatisticsDialog.90a=90%
+PowerStatisticsDialog.90b=\ mW
+PowerStatisticsDialog.75a=75%
+PowerStatisticsDialog.75b=\ mW
+PowerStatisticsDialog.50a=50%
+PowerStatisticsDialog.50b=\ mW
+PowerStatisticsDialog.25a=25%
+PowerStatisticsDialog.25b=\ mW
+PowerStatisticsDialog.10a=10%
+PowerStatisticsDialog.10b=\ mW
+PowerStatisticsDialog.mina=Minimum
+PowerStatisticsDialog.minb=\ mW
+PowerStatisticsDialog.close=Close
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.power;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.power.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PowerPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.power;
+
+import java.io.File;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.osgi.framework.BundleContext;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IViewMenu;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable;
+import com.nokia.carbide.cpp.internal.pi.power.actions.PowerSettingsDialog;
+import com.nokia.carbide.cpp.internal.pi.power.actions.PowerStatisticsDialog;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.internal.pi.visual.GraphDrawRequest;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+public class PowerPlugin extends AbstractPiPlugin
+		implements IViewMenu, ITrace, IClassReplacer, IVisualizable, IEventListener
+{
+	private static final String HELP_CONTEXT_ID = PIPageEditor.PI_ID + ".power";  //$NON-NLS-1$
+
+	// There will be three graphs - one each for editor pages 0, 1, 2
+	// This code may assume that page 0 has the threads graph, 1 the binaries, and 2 the functions
+	private final static int GRAPH_COUNT = 3;
+
+	// the shared instance
+	private static PowerPlugin plugin;
+	
+	private static void setPlugin(PowerPlugin newPlugin)
+	{
+		plugin = newPlugin;
+	}
+
+	/**
+	 * The constructor.
+	 */
+	public PowerPlugin() {
+		super();
+		setPlugin(this);
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		setPlugin(null);
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static PowerPlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractPiPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi.power", path); //$NON-NLS-1$
+	}
+
+	public Class getTraceClass()
+	{
+		return PwrTrace.class;
+	}
+
+	public Class getReplacedClass(String className)
+	{
+		if (   (className.indexOf("com.nokia.carbide.cpp.pi.power.PwrTrace") != -1) //$NON-NLS-1$
+			|| (className.indexOf("com.nokia.carbide.pi.power.PwrTrace") != -1) //$NON-NLS-1$
+			|| (className.indexOf("fi.vtt.bappea.pwrTracePlugin.PwrTrace") != -1)) //$NON-NLS-1$
+		{
+			return PwrTrace.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.power.PwrSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.power.PwrSample") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.pwrTracePlugin.PwrSample") != -1) //$NON-NLS-1$
+		{
+			return PwrSample.class;
+		}
+		else
+			return null;
+	}
+	
+	public void initialiseTrace(GenericTrace trace) 
+	{
+		if (!(trace instanceof PwrTrace))
+			return;
+
+		PwrTrace pwrTrace = (PwrTrace)trace;
+		
+		pwrTrace.setComplete();
+		
+		// because of the way these traces used to be created, the sample vector may be much too large
+		pwrTrace.samples.trimToSize();
+		
+		NpiInstanceRepository.getInstance().activeUidAddTrace("com.nokia.carbide.cpp.pi.power", trace); //$NON-NLS-1$
+	}	
+
+	public String getTraceName() {
+		return "Power"; //$NON-NLS-1$
+	}
+
+	public int getTraceId() {
+		return 11;
+	}
+
+	public ParsedTraceData parseTraceFile(File file) throws Exception 
+	{
+		try
+        {
+            PwrTraceParser pwrParser = new PwrTraceParser();
+            return pwrParser.parse(file);
+        } catch (Exception e)
+        {
+            e.printStackTrace();
+            throw e;
+        }
+	}
+
+	public MenuManager getViewOptionManager() {
+		if (NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.power") == null) //$NON-NLS-1$
+			return null;	// no trace, so no MenuManager
+
+		Action action;
+		
+		MenuManager manager = new MenuManager(Messages.getString("PowerPlugin.powerGraph")); //$NON-NLS-1$
+
+		action = new Action(Messages.getString("PowerPlugin.powerSettingsAction"), Action.AS_PUSH_BUTTON) { //$NON-NLS-1$
+			public void run() {
+				new PowerSettingsDialog(Display.getCurrent());
+			}
+		};
+		
+		action.setToolTipText(Messages.getString("PowerPlugin.powerSettingsTooltip")); //$NON-NLS-1$
+		manager.add(action);
+
+		action = new Action(Messages.getString("PowerPlugin.powerStatsAction"), Action.AS_PUSH_BUTTON) { //$NON-NLS-1$
+			public void run() {
+				new PowerStatisticsDialog(Display.getCurrent());
+			}
+		};
+		
+		action.setToolTipText(Messages.getString("PowerPlugin.PowerStatsTooltip")); //$NON-NLS-1$
+		manager.add(action);
+		
+		manager.add(new Separator());
+
+		Boolean showLine   = Boolean.TRUE;	// by default, show the interval average power as a line
+
+		// if there is are values associated with the current Analyser tab, then use them
+		Object obj;
+		// do we show any average line?
+		obj = NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.power.showLine"); //$NON-NLS-1$
+		if ((obj != null) && (obj instanceof Boolean))
+			// retrieve the current value
+			showLine = (Boolean)obj;
+		else
+			// set the initial value
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.power.showLine", showLine); //$NON-NLS-1$
+
+		action = new Action(Messages.getString("PowerPlugin.showIntervalLineAction"), Action.AS_CHECK_BOX) { //$NON-NLS-1$
+			public void run() {
+				if (this.isChecked())
+					receiveSelectionEvent("show_average"); //$NON-NLS-1$
+				else
+					receiveSelectionEvent("hide_average"); //$NON-NLS-1$
+			}
+		};
+		
+		action.setChecked(showLine);
+		action.setToolTipText(Messages.getString("PowerPlugin.showIntervalLineTooltip")); //$NON-NLS-1$
+		manager.add(action);
+	
+		return manager;
+	}
+		
+	public void receiveEvent(String actionString, Event event) 
+	{
+		PwrTrace trace = (PwrTrace) NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.power"); //$NON-NLS-1$
+
+		if (trace == null)
+			return;
+
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+		if (   actionString.equals("show_average") //$NON-NLS-1$
+			|| actionString.equals("hide_average")) //$NON-NLS-1$
+		{
+			((PowerTraceGraph)trace.getTraceGraph(PIPageEditor.THREADS_PAGE,   uid)).action(actionString);	
+			((PowerTraceGraph)trace.getTraceGraph(PIPageEditor.BINARIES_PAGE,  uid)).action(actionString);	
+			((PowerTraceGraph)trace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE, uid)).action(actionString);	
+		} else if (actionString.equals("scroll")) //$NON-NLS-1$
+		{
+			if (   !(event.data instanceof String)
+				|| !((String)event.data).equals("FigureCanvas")) //$NON-NLS-1$
+				return;
+			
+			PIEvent be = new PIEvent(event, PIEvent.SCROLLED);
+			
+			((PowerTraceGraph)trace.getTraceGraph(PIPageEditor.THREADS_PAGE,   uid)).piEventReceived(be);
+			((PowerTraceGraph)trace.getTraceGraph(PIPageEditor.BINARIES_PAGE,  uid)).piEventReceived(be);
+			((PowerTraceGraph)trace.getTraceGraph(PIPageEditor.FUNCTIONS_PAGE, uid)).piEventReceived(be);
+		}
+	}
+
+	public void receiveSelectionEvent(String eventString)
+	{
+		if (eventString == null)
+			return;
+
+		PwrTrace trace = (PwrTrace) NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.power"); //$NON-NLS-1$
+
+		if (eventString.equals("show_average")) { //$NON-NLS-1$
+			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.power.showLine", Boolean.TRUE); //$NON-NLS-1$
+ 		} else if (eventString.equals("hide_average")){ //$NON-NLS-1$
+ 			NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.power.showLine", Boolean.FALSE); //$NON-NLS-1$
+		} else {
+			return;
+		}
+
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+    	trace.getPowerGraph(PIPageEditor.THREADS_PAGE,   uid).action(eventString);
+    	trace.getPowerGraph(PIPageEditor.BINARIES_PAGE,  uid).action(eventString);
+    	trace.getPowerGraph(PIPageEditor.FUNCTIONS_PAGE, uid).action(eventString);
+	}
+
+	public GenericTraceGraph getTraceGraph(int graphIndex) 
+	{
+		PwrTrace trace = (PwrTrace) NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.power"); //$NON-NLS-1$
+
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+		
+		if (trace != null)
+			return trace.getTraceGraph(graphIndex, uid);
+		else
+			return null;
+	}
+
+	/*
+	public GenericTraceGraph getTraceGraph(int graphIndex, int uid) {
+		PwrTrace trace = (PwrTrace) NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.power"); //$NON-NLS-1$
+
+		if (trace != null)
+			return trace.getTraceGraph(graphIndex, uid);
+		else
+			return null;
+	}
+	*/
+
+	public Integer getLastSample(int graphIndex) {
+		PwrTrace trace = (PwrTrace) NpiInstanceRepository.getInstance().activeUidGetTrace("com.nokia.carbide.cpp.pi.power"); //$NON-NLS-1$
+
+		if (trace != null)
+			return new Integer(trace.getLastSampleNumber());
+		else
+			return null;
+	}
+
+	public GraphDrawRequest getDrawRequest(int graphIndex) {
+		return null;
+	}
+
+	public int getGraphCount() {
+		return GRAPH_COUNT;
+	}
+
+	public int getPageNumber(int graphIndex) {
+		// Assumes page 0 has the threads graph, 1 has the binaries, and 2 has the functions
+		if (graphIndex == 0)
+			return PIPageEditor.THREADS_PAGE;
+		else if (graphIndex == 1)
+			return PIPageEditor.BINARIES_PAGE;
+		else if (graphIndex == 2)
+			return PIPageEditor.FUNCTIONS_PAGE;
+
+		return PIPageEditor.NEXT_AVAILABLE_PAGE;
+	}
+
+	// return whether this plugin's editor pages have been created
+	public boolean arePagesCreated() {
+		return false;
+	}
+	
+	// set whether this plugin's editor pages have been created
+	public void setPagesCreated(boolean pagesCreated) {
+		return;
+	}
+
+	// number of editor pages to create
+	public int getCreatePageCount() {
+		return 0;
+	}
+
+	public int getCreatePageIndex(int index) {
+		return 0;
+	}
+
+	public ProfileVisualiser createPage(int index) {
+		return null;
+	}
+
+	public void setPageIndex(int index, int pageIndex) {
+		return;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable#getGraphTitle(int)
+	 */
+	public String getGraphTitle(int graphIndex) {
+		return Messages.getString("PowerPlugin.pluginTitle"); //$NON-NLS-1$
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PowerReturnPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.power;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IReturnPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+
+
+public class PowerReturnPlugin  implements IReturnPlugin {
+	public AbstractPiPlugin getPlugin() {
+		return PowerPlugin.getDefault();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PowerTraceGraph.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,1155 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.power;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.text.DecimalFormat;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.MouseEvent;
+import org.eclipse.draw2d.MouseMotionListener;
+import org.eclipse.draw2d.Panel;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+
+import com.nokia.carbide.cpp.internal.pi.actions.SaveSamples;
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IContextMenu;
+import com.nokia.carbide.cpp.internal.pi.power.actions.PowerSettingsDialog;
+import com.nokia.carbide.cpp.internal.pi.power.actions.PowerStatisticsDialog;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.internal.pi.visual.GraphComposite;
+import com.nokia.carbide.cpp.internal.pi.visual.PICompositePanel;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEventListener;
+import com.nokia.carbide.cpp.pi.address.GppSample;
+import com.nokia.carbide.cpp.pi.address.GppTrace;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.ColorPalette;
+
+
+public class PowerTraceGraph extends GenericTraceGraph implements ActionListener,
+																  PIEventListener,
+																  MouseMotionListener,
+																  IContextMenu
+{
+	
+    private int[] DTrace; // used for synchronizing the power and gpptraces.
+	private int[] DPower;
+	
+	// 3 tabs can share the same trace, but they need different graphs
+    private PwrTrace trace;
+    
+	private FigureCanvas leftFigureCanvas;
+	
+	// used to draw the text for the power line in the graph window.
+	private int mPowerLineY = 0;
+	
+    public int x = 400;
+    public int y = 800;
+
+    private double averageConsumption = (float)0.0;
+	private int averageComsumptionLastOffset = Integer.MAX_VALUE;
+    private double cumulative = (float)0.0;
+    private double energy = 0.0f;
+    private int[] sampleTimes;
+    private int[] ampValues;
+    private int[] voltValues;
+//    private int[] capaValues;
+    private double maxAmps = Integer.MIN_VALUE;
+	private double minAmps = Integer.MAX_VALUE;
+	private double maxPower = 0.0;
+    private boolean mSelecting = false;
+	
+	// used when determining when to draw the text over the power bar.
+	private int leftBorder = 0;
+	
+	private static int xLegendHeight = 20;
+	
+	boolean mShowPowerLine = true;
+	
+	private static DecimalFormat powerFormat   = new DecimalFormat(Messages.getString("powerFormat")); //$NON-NLS-1$
+	private static DecimalFormat voltageFormat = new DecimalFormat(Messages.getString("voltageFormat")); //$NON-NLS-1$
+	
+	private int uid;
+	
+	protected static int SAMPLES_AT_ONE_TIME = 1000;
+	protected int stringTime;
+
+	
+	// class to pass sample data to the save wizard
+    public class SaveSampleString implements ISaveSamples {
+		int startTime;
+		int endTime;
+    	
+    	public SaveSampleString() {
+		}
+
+    	public String getData() {
+    		return getSampleString(SAMPLES_AT_ONE_TIME, this.startTime, this.endTime);
+		}
+
+		public int getIndex() {
+			if (stringTime == (int) (getSelectionStart() + 0.0005))
+				return 0;
+
+			return stringTime;
+		}
+
+		public void clear() {
+			this.startTime = (int) (getSelectionStart() + 0.0005);
+			this.endTime   = (int) (getSelectionEnd() + 0.0005);
+			stringTime = startTime;
+		}
+    }
+
+	/*
+	 * return the power samples selected in the interval 
+	 */
+	protected String getSampleString(int count, int startTime, int endTime)
+	{
+		Vector sampleVector = ((PwrTrace) this.getTrace()).samples;
+		PwrSample lastSample = (PwrSample) sampleVector.get(sampleVector.size() - 1);
+		
+		String returnString = null;
+		
+		if (this.stringTime == startTime) {
+			returnString = Messages.getString("PowerTraceGraph.saveSamplesHeading"); //$NON-NLS-1$
+		}
+
+		this.stringTime++;
+
+		// check if we have returned everything
+		if ((this.stringTime > lastSample.sampleSynchTime) || (this.stringTime > endTime)) {
+			this.stringTime = endTime + 1;
+			return returnString;
+		}
+		
+		double oldCurrent  = -1;
+		double oldVoltage  = -1;
+		double oldCapacity = -1;
+		String string = ""; //$NON-NLS-1$
+
+		if (this.trace.isComplete()) {
+			for ( ;
+				 (this.stringTime < endTime + 1) && (count > 0) && (this.stringTime < sampleVector.size());
+				 this.stringTime++) {
+				PwrSample sample = (PwrSample) sampleVector.get(stringTime);
+				double current  = sample.current;
+				double voltage  = sample.voltage;
+				double capacity = sample.capacity;
+				
+				if ((oldCurrent != current) || (oldVoltage != voltage) || (oldCapacity != capacity)) {
+					string = Messages.getString("PowerTraceGraph.comma") + (int) current + Messages.getString("PowerTraceGraph.comma")  + (int) voltage + Messages.getString("PowerTraceGraph.comma") + (int) capacity + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+					oldCurrent  = current;
+					oldVoltage  = voltage;
+					oldCapacity = capacity;
+				}
+	
+				returnString += sample.sampleSynchTime + string;
+				count--;
+			}
+		} else {
+			int i = 0;
+			
+			//find least sampling time greater than or equal to the start index
+			for ( ; i < sampleVector.size(); i++) {
+				if (((PwrSample) sampleVector.get(i)).sampleSynchTime > this.stringTime)
+					break;
+			}
+
+			if (i != 0)
+				i--;
+
+			for ( ; i < sampleVector.size() && (count > 0); i++) {
+				PwrSample sample = (PwrSample) sampleVector.get(i);
+				
+				this.stringTime = (int) sample.sampleSynchTime;
+				if (sample.sampleSynchTime > endTime)
+					break;
+				
+				double current  = sample.current;
+				double voltage  = sample.voltage;
+				double capacity = sample.capacity;
+				
+				returnString += sample.sampleSynchTime + Messages.getString("PowerTraceGraph.comma") + (int) current + Messages.getString("PowerTraceGraph.comma")  + (int) voltage + Messages.getString("PowerTraceGraph.comma") + (int) capacity + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+				count--;
+			}
+		}
+
+		// check if we have returned everything
+		if (this.stringTime >= lastSample.sampleSynchTime) {
+			this.stringTime = endTime + 1;
+		}
+
+		return returnString;
+	}
+	
+	protected void actionSaveSamples(ISaveSamples saveSamples)
+	{
+		new SaveSamples(saveSamples);
+	}
+
+	protected MenuItem getSaveSamplesItem(Menu menu, boolean enabled) {
+	    MenuItem saveSamplesItem = new MenuItem(menu, SWT.PUSH);
+
+		saveSamplesItem.setText(Messages.getString("PowerTraceGraph.saveSamplesForInterval")); //$NON-NLS-1$
+		saveSamplesItem.setEnabled(enabled);
+		
+		if (enabled) {
+			saveSamplesItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+					saveEventSamples();
+				}
+			});
+		}
+	
+		return saveSamplesItem;
+	}
+	
+	public void saveEventSamples() {
+    	SaveSampleString saveSampleString = new SaveSampleString();
+    	actionSaveSamples(saveSampleString); //$NON-NLS-1$
+	}
+
+    public PowerTraceGraph( int graphIndex, int uid, PwrTrace trace )
+    {
+        super((GenericSampledTrace)trace);
+		this.graphIndex     = graphIndex;
+		this.uid			= uid;
+       
+        if ( trace != null ) 
+		{
+            this.trace = trace;
+
+            if (this.trace.getSampleTimes() == null)
+            	this.trace.initData();
+
+			this.sampleTimes = this.trace.getSampleTimes();
+			this.ampValues   = this.trace.getAmpValues();
+			this.voltValues  = this.trace.getVoltValues();
+//			this.capaValues  = this.trace.getCapaValues();
+			this.maxAmps  = this.trace.getMaxAmps();
+			this.minAmps  = this.trace.getMinAmps();
+			this.maxPower = this.trace.getMaxPower();
+        }
+    }
+    
+	public int getUid() {
+		return this.uid;
+	}
+    
+	// This method is called when widgets in the PowerInfoPanel are
+	// manipulated.
+	//
+	public void action(String actionString)
+	{   
+		if (actionString.equals("show_average")) //$NON-NLS-1$
+		{
+			// show average power as a line
+			mShowPowerLine = true;
+		}
+		else if (actionString.equals("hide_average")) //$NON-NLS-1$
+		{
+			// do not show average power as a line
+			mShowPowerLine = false;
+		}
+		else if (actionString.equals("changeVoltage")) //$NON-NLS-1$
+		{
+			// voltage changed, so compute new maximum power
+			this.trace.scaleMaxPower();
+			this.maxPower = this.trace.getMaxPower();
+        }
+		else if (actionString.equals("changeBatterySize"))  //$NON-NLS-1$
+		{
+			// battery size changed, so repaint
+        }
+		else
+			return;
+
+        this.repaint();
+		if (this.leftFigureCanvas != null)
+			this.leftFigureCanvas.redraw();
+    }
+
+    public void piEventReceived(PIEvent be)
+	{
+	    switch (be.getType())
+	    {
+	    case (PIEvent.SELECTION_AREA_CHANGED):
+
+			// send this message to the 2 other graphs
+			PIEvent be2 = new PIEvent(be.getValueObject(),
+					PIEvent.SELECTION_AREA_CHANGED2);
+
+	    	for (int i = 0; i < 3; i++)
+	    	{
+	    		PowerTraceGraph graph = trace.getPowerGraph(i, getUid());
+	    		
+	    		if (graph != this) {
+					graph.piEventReceived(be2);
+	    		}
+	    	}
+
+		// FALL THROUGH
+		case PIEvent.SELECTION_AREA_CHANGED2:
+			double[] values = (double[])be.getValueObject();
+			this.setSelectionStart(values[0]);
+			this.setSelectionEnd(values[1]);
+			this.calcValues();
+			mSelecting = true;
+            break;
+
+		case (PIEvent.MOUSE_PRESSED):
+			this.calcValues();	
+        	this.parentComponent.getSashForm().redraw();
+			break;
+
+		case PIEvent.SCROLLED:
+			Event event = ((Event)be.getValueObject());
+			this.parentComponent.setScrolledOrigin(event.x, event.y);
+			this.repaint();
+			break;
+
+		default:
+        	break;
+	    }
+	}
+	
+	public void refreshDataFromTrace()
+	{
+	}
+
+	public void enablePowerLine( boolean state )
+	{
+		mShowPowerLine = state;
+	}
+
+	public void actionPerformed ( ActionEvent ae ) 
+	{
+        if( ae.getActionCommand().equals("switch") )  //$NON-NLS-1$
+		{
+            parentComponent.piEventReceived( new PIEvent( "switch_gpp", PIEvent.PLUGIN_STRING_MESSAGE) ); //$NON-NLS-1$
+        } 
+        this.repaint();
+    }	
+    
+    public PICompositePanel getParentComponent() {
+        return this.parentComponent;
+    }
+    
+    public float getVoltage() 
+	{
+        if ( trace != null )
+            return trace.getVoltage();
+            
+        return 0.0f;
+    }
+    
+    public void setVoltage( float newVal ) 
+	{
+        if ( trace != null )
+            trace.setVoltage(newVal);
+    }
+    
+    public double getAverageConsumption() 
+	{	
+        if ( trace != null ) 
+		{
+			if( averageComsumptionLastOffset != trace.getOffset() )
+			{
+				averageComsumptionLastOffset = trace.getOffset();
+				// not calculated yet
+				calcValues();
+			}
+			
+            return this.averageConsumption * trace.getVoltage();
+        } 
+		
+		return 0.0f;
+    }
+    
+    public void setOffset( int newOffset ) 
+	{   
+	    if ( trace != null )
+			trace.setOffset( newOffset );
+	}
+    
+    public void increaseOffset() 
+	{
+        if ( trace != null )
+		{
+            trace.setOffset( trace.getOffset() + 50 );
+		}
+    }
+    
+    public void decreaseOffset() 
+	{
+        if ( trace != null )
+		{
+            trace.setOffset( trace.getOffset() - 50 );
+		}
+    }
+    
+    public void setSize(int x, int y)
+	{
+	    this.x = x;
+	    this.y = y;
+	}
+
+    public Dimension getSize()
+	{
+	    return new Dimension(x, y);
+	}
+
+	public void paint(Panel panel, Graphics graphics)
+	{
+		this.setSize(this.getSize().width, getVisualSize().height);
+	    this.drawDottedLineBackground(graphics, PowerTraceGraph.xLegendHeight);
+	    this.drawPowerData(graphics, PowerTraceGraph.xLegendHeight);
+
+	    // draws the same selection as the Address/Thread trace
+		this.drawSelectionSection(graphics, PowerTraceGraph.xLegendHeight);
+
+		if (mShowPowerLine)
+			this.drawPowerLine(graphics);		
+	}
+
+    public void repaint()
+	{   
+	    this.parentComponent.repaintComponent();
+	}
+    	
+	private void showPowerValueAtX(MouseEvent me)
+	{
+		if (me.y > this.getVisualSizeY() - PowerTraceGraph.xLegendHeight) {
+			this.setToolTipText(null);
+			return;
+		}
+		
+		// scale the value of x
+		int x = (int) (me.x * this.getScale() + 0.5);
+		
+		if (x > (int) (PIPageEditor.currentPageEditor().getMaxEndTime() * 1000 + 0.0005)) {
+			this.setToolTipText(null);
+			return;
+		}
+		
+		if (x > trace.getLastSampleNumber())
+			x = trace.getLastSampleNumber();
+
+		String textToShow = Double.toString(x / 1000.0)
+							+ Messages.getString("tooltip1"); //$NON-NLS-1$
+
+		// We could instead use the measured voltage: voltValues[x +/- movement]/1000.0 rather than the user-specified voltage?
+		double voltage = trace.getVoltage();
+
+		int movement = trace.getOffset();
+		int ampValue = 0;
+
+		// find the amperage for x
+		int index = -1;
+		if (movement == 0)
+		{
+			index = timeIndex(x);
+			if (index != -1)
+				ampValue = ampValues[index];
+		}
+		else if (movement < 0)
+		{
+			// make it positive
+			movement *= -1;
+			
+			// eat the first N=offset values.
+			if (x < sampleTimes.length - movement)
+			{
+				index = timeIndex(x + movement);
+				if (index != -1)
+					ampValue = ampValues[index];
+			}
+		}
+		else // movement > 0
+		{
+			if (x > movement)
+			{
+				index = timeIndex(x - movement);
+				if (index != -1)
+					ampValue = ampValues[index];
+			}
+		}
+
+		// determine the power = amps * voltage
+		textToShow += (int) ((ampValue * voltage) + 0.5);
+
+		this.setToolTipText(textToShow + Messages.getString("tooltip2") //$NON-NLS-1$
+							+ PowerTraceGraph.voltageFormat.format(voltage));
+	}
+	
+	public int timeIndex(int time) {
+		if (time < sampleTimes[0])
+			return -1;
+		
+		if (time >= sampleTimes[sampleTimes.length - 1])
+			return sampleTimes.length - 1;
+
+		int i = 0;
+		for ( ; sampleTimes[i] <= time; i++)
+			;
+		
+		if (sampleTimes[i] == time)
+			return i;
+		else
+			return i - 1;
+	}
+
+	private void drawPowerData(Graphics graphics, int yLegendSpace)
+	{
+		int visY = this.getVisualSize().height - yLegendSpace;
+		if (visY < 0)
+			visY = 0;
+		int sampleCount = this.sampleTimes.length;
+				
+		// arrays of values to draw
+		int points[] = new int[sampleCount * 4];
+		
+		// the offset changes when the user moves the graph or the traces are synched
+		int movement = trace.getOffset();
+		
+		// look for a move to the right ( > 0)
+		// the y value is in thisValue is the milliAmps	
+		// it doesn't matter if we render the milliAmps or mW, the graphs have the same
+		// form, it only matters when you show the values associated with the graph.
+		double maxAmps = this.maxPower / this.trace.getVoltage();
+
+		double cachedScale = this.getScale();
+		// or no movement (==0)
+		if( movement == 0 )
+		{
+			for( int i = 0, k = 0; i < sampleTimes.length; i++ )
+			{
+				points[k++] = (int)(sampleTimes[i] / cachedScale);
+				points[k++] = (int)(visY - (ampValues[i] / maxAmps) * visY);
+				if (i < sampleTimes.length - 1)
+				{
+					points[k++] = (int)(sampleTimes[i + 1] / cachedScale);
+				} else {
+					long lastTime = (int) (PIPageEditor.currentPageEditor().getMaxEndTime() * 1000 + 0.0005);
+					points[k++] = (int) (lastTime / cachedScale);
+				}
+				points[k++] = (int)(visY - (ampValues[i] / maxAmps) * visY);
+			}
+		} 
+		else if( movement > 0 )
+		{
+			// set the first N=offset values to be 0
+			for (int i = 0, k = movement * 2; i < sampleCount - movement; i++) {
+				points[k++] = sampleTimes[i];
+				points[k++] = ampValues[i];
+			}
+
+			for( int i = 0, k = 0; i < sampleCount; i++ )
+			{
+				if( i < movement )
+				{
+					points[k++] = (int)(i / cachedScale);
+					points[k++] = (int)(visY - ((float)1 / maxAmps) * visY);
+				}
+				else
+				{
+					points[k++] = (int)((points[2 * i] + movement)/cachedScale);
+					points[k++] = (int)(visY - ((float)points[1 + 2 * i] / maxAmps) * visY);
+				}
+			}
+		}
+		else
+		{
+			// make it positive
+			movement *= -1;
+			
+			// eat the first N=offset values.
+			int cutoff = sampleTimes.length - movement;
+			
+			for (int i = 0, k = movement * 2; i < sampleCount - movement; i++) {
+				points[k++] = sampleTimes[i];
+				points[k++] = ampValues[i];
+			}
+
+			for( int i = 0, k = 0; i < sampleCount; i++ )
+			{
+				if( i >= cutoff )
+				{
+					points[k++] = (int)(i / cachedScale);
+					points[k++] = (int)(visY - ((float)1 / maxAmps) * visY);
+				}
+				else
+				{
+					points[k++] = (int)((points[2 * i] - movement) / cachedScale);
+					points[k++] = (int)(visY - ((float)points[1 + 2 * i] / maxAmps) * visY);
+				}
+			}
+		}
+
+		graphics.setForegroundColor(ColorConstants.red);
+		// draw all the points at once.
+		graphics.drawPolyline(points);
+		points = null;
+	}
+
+	public double calcValueForY( int y )
+	{
+		double visY = this.getVisualSize().height - PowerTraceGraph.xLegendHeight;
+		if (visY <= 0)
+			return 0.0;
+		double maxAmps = this.maxPower / this.trace.getVoltage();
+		double yScalingFactor = maxAmps/(double)visY;
+		// visY-y to compensate for the transpose, * voltage to compenstate for the mA in the samples, we 
+		// want to show the mW values here.
+		return ( (double)(visY - (double)y) * yScalingFactor * (double)trace.getVoltage());
+	}
+	
+	public int calcYforValue( double value )
+	{
+		double visY = this.getVisualSize().height - PowerTraceGraph.xLegendHeight;
+		if ((visY <= 0) || (this.trace.getVoltage() == 0))
+			return 0;
+		double maxAmps = this.maxPower / this.trace.getVoltage();
+		double yScalingFactor = maxAmps / visY;
+
+		// visY-y to compensate for the transpose, * voltage to compenstate for the mA in the samples, we 
+		// want to show the mW values here.
+		if (yScalingFactor == 0)
+			return 0;
+
+		double tmp = value / (double)trace.getVoltage() / yScalingFactor;
+		
+		return (int)Math.ceil(visY - tmp);
+	}
+
+	private void drawPowerLine( Graphics graphics )
+	{
+		//mPowerLineY == 0  on startup.
+		boolean startup = (mPowerLineY == 0);
+
+		if( mPowerLineY == 0 || mSelecting )
+		{
+			if( mSelecting )
+			{
+				// still selecting?
+				if( ((super.getSelectionStart() == -1)  && (super.getSelectionEnd() == -1)) )
+				{
+					mSelecting = false;
+					// need to turn them back on. mouse drag events for drawing the power line.
+				}
+				else
+				{
+					mPowerLineY = calcYforValue( getAverageConsumption() );
+				}
+			}
+			
+			if( mPowerLineY == 0 )
+			{
+				mPowerLineY = calcYforValue( getAverageConsumption() );
+			}
+		}
+		
+		double powerValue = 0.0;
+		
+		String strValue = null;
+		
+		// requirement, if dragging power bar then print true power value. If
+		// selecting then print average of area not the true value of the y coordinate.
+		//
+		if( !mSelecting && !startup )
+			powerValue = calcValueForY(mPowerLineY);
+		else if( mSelecting || startup )
+			powerValue = getAverageConsumption();
+
+		strValue = PowerTraceGraph.powerFormat.format((int)(powerValue + 0.5));
+
+		// this does cause some overhead and could be removed since it only provides some aesthetics.
+		updateVisibleBorders();
+		leftBorder = this.parentComponent.getScrolledOrigin().x;
+//		leftBorder = this.getVisibleLeftBorder();
+		if( leftBorder < 0 )
+			leftBorder = 0;	
+		
+		// draw the average power line with a width of 3
+		int lineWidth = graphics.getLineWidth();
+
+		graphics.setForegroundColor(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
+		graphics.setLineWidth(2);
+		graphics.drawLine(leftBorder, mPowerLineY, this.getSize().width, mPowerLineY );
+
+		graphics.setLineWidth(lineWidth);
+
+		// figure out how big the box behind the text should be.
+		GC gc = new GC(PIPageEditor.currentPageEditor().getSite().getShell());
+		Point point = gc.stringExtent(strValue);
+		gc.dispose();
+
+		// clear the text rectangle
+		graphics.setBackgroundColor(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+		graphics.setForegroundColor(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+		graphics.fillRectangle(leftBorder + 20, mPowerLineY - (point.y / 2), point.x + 6, point.y );
+
+		graphics.setForegroundColor(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
+
+		// make the font bold 16, draw the text, and restore the font
+		int oldStyle  = graphics.getFont().getFontData()[0].getStyle();
+		int oldHeight = graphics.getFont().getFontData()[0].getHeight();
+
+		graphics.getFont().getFontData()[0].setStyle((oldStyle & SWT.NORMAL) | (oldStyle & SWT.ITALIC) | SWT.BOLD);
+		graphics.getFont().getFontData()[0].setHeight(16);
+		
+		graphics.drawString(strValue, leftBorder + 23, mPowerLineY - (point.y / 2));
+
+		graphics.getFont().getFontData()[0].setStyle(oldStyle);
+		graphics.getFont().getFontData()[0].setHeight(oldHeight);
+
+		if ( startup )
+			mPowerLineY = 0;
+	}
+
+    public void drawPwrGraphSelection(Graphics g)
+	{	
+	    int selectionStart = (int)super.getSelectionStart();
+	    int selectionEnd = (int)super.getSelectionEnd();
+	    double scale = super.getScale();
+		
+	    if(selectionStart != -1 && selectionEnd != -1)
+	    {
+	    	Color selectColor = new Color(Display.getCurrent(),123,156,178);
+	    	
+	    	g.setForegroundColor(selectColor);
+	    	g.fillRectangle((int)(selectionStart / scale + 0.5),
+	    					0,
+	    					(int)((selectionEnd - selectionStart) / scale + 0.5),
+	    					this.getVisualSize().height - PowerTraceGraph.xLegendHeight);
+	    	selectColor.dispose();
+	    }
+	}
+	
+	// synchronize the power and software traces
+	// logically:
+	// 1) digitize the GPP and power traces
+	// 2) align the traces so that the tail of the software trace is aligned with 
+	//	  the tail of the power trace.
+	// 3) slowly move software trace to the left ADDing the software and power trace
+	// 	  values together and performing a sum until the highest total is found.
+	// 4) using the index of the highest total, either add dummy values to the power trace or
+	//    remove values from the power trace.
+	// 5) finally update the samples and refresh turn off the wait cursor.
+    
+	public void doSynchronize( GppTrace gpp, PwrTrace power )
+	{
+//		System.err.println( "Starting synchronization process" );
+		digitizeGPPFile(gpp);
+		digitizePowerFile(power);
+		
+		int MAX = 0;
+		int MAX_POWER_INDEX = 0;
+		int MAX_TRACE_INDEX = 0;
+		int accum = 0;
+
+		int TOTAL_MOVEMENT = (DPower.length-DTrace.length) + (int)(0.25*DTrace.length) + 1;
+
+		// TI = trace index
+		int TI = 0;
+		// PI = power trace index
+		int PI = DPower.length-DTrace.length;
+
+		for( int j = 0; j < TOTAL_MOVEMENT; j++ )
+		{
+			for( int i = TI; i < DTrace.length; i++ )
+			{
+				if( (DTrace[i] & DPower[PI+i]) == 0 )
+				{
+					accum++;
+				}
+			}
+			if( accum > MAX )
+			{
+				MAX = accum;
+				MAX_POWER_INDEX = PI;
+				MAX_TRACE_INDEX = TI;
+			}
+			accum = 0;
+			PI--;
+			if( PI < 0 )
+			{
+				PI=0;
+				TI++;
+			}
+		}
+		// one more pass through the data to update the graphs.
+		//
+
+		if( MAX_TRACE_INDEX > 0 )
+		{
+			trace.setOffset( trace.getOffset() - MAX_TRACE_INDEX );
+		}
+		else
+		{
+			trace.setOffset( trace.getOffset() + MAX_POWER_INDEX );
+		}
+		parentComponent.getActiveGraph().getCompositePanel().getSashForm()
+								.setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_WAIT) );
+	}
+	// digitize the power trace
+	// basically:
+	// 1) find the min and max power values in the trace
+	// 2) for each value in the trace if the value is > Half the average range
+	//    then set that value to 1 else 0.
+	//
+	public void digitizePowerFile( PwrTrace power )
+	{
+		double MIN_Value = (double)minAmps/(double)1000;
+		double MAX_Value = (double)maxAmps/(double)1000;
+		
+		// find the min and max in the power
+		//
+		// we already have this data so we can simply divide by 1000 for the scale we need.
+
+		float Half_Avg_Range = (float)((MAX_Value - MIN_Value)/2);		
+		
+		DPower = new int[power.samples.size()];
+		int DPowerIndex = 0;
+
+		// as an aside, this tracks well with the application states.
+		//
+		for( Enumeration e = power.getSamples(); e.hasMoreElements() ; )
+		{
+			PwrSample current = (PwrSample)e.nextElement();
+			if( current.current > Half_Avg_Range )
+			{
+				DPower[DPowerIndex] = 1;
+			}
+			else
+			{
+				DPower[DPowerIndex] = 0;
+			}
+			DPowerIndex++;
+		}
+	}
+	
+	// digitize the gpp file
+	// basically:
+	// 1a) divide the run into windows and for each window:
+	// 1b) count the number of transitions i.e. different functions called in the windows by putting the process
+	//    name into a hashtable, if the add returns a null value then the insert 
+	//    did not collide and we transitioned.
+	// 1c) find the min and max number of transistions for all windows
+	//
+	// 2a) for each window if the number of transitions for that window are greater
+	//	   than the average number of transtitions then set the digitized version to be 1 else 0.
+	//
+	public void digitizeGPPFile( GppTrace thisTrace )
+	{		
+		int WINDOW_SIZE = 20;
+
+		int numSamples = thisTrace.samples.size();
+		int count = 1;
+		Hashtable<String,String> histogram = new Hashtable<String,String>();
+		int windowSizes[] = new int[numSamples/WINDOW_SIZE];
+		int min = Integer.MAX_VALUE;
+		int max = Integer.MIN_VALUE;
+
+		int numTransitions = 1;
+
+		int total = 0;
+//		String lastTrace = null;
+		for( int i = 0; i < numSamples; i++ )
+		{
+			GppSample sample = thisTrace.getGppSample(i);
+			if( count % WINDOW_SIZE == 0 )
+			{
+				windowSizes[i/WINDOW_SIZE] = histogram.size() + numTransitions;
+				if( windowSizes[i/WINDOW_SIZE] < min )
+					min = windowSizes[i/WINDOW_SIZE];
+				else if( windowSizes[i/WINDOW_SIZE] > max )
+					max = windowSizes[i/WINDOW_SIZE];
+
+				total += windowSizes[i/WINDOW_SIZE];
+
+				numTransitions = 1;
+				histogram.clear();
+				count = 0;
+			}
+			count++;
+			if( histogram.put( new String(sample.thread.process.name + Messages.getString("PowerTraceGraph.histogram1") //$NON-NLS-1$
+						                  + (sample.thread.threadName != null ? sample.thread.threadName
+											   : Messages.getString("PowerTraceGraph.11")) + Messages.getString("PowerTraceGraph.12") //$NON-NLS-1$ //$NON-NLS-2$
+					   							   + sample.thread.threadId + Messages.getString("PowerTraceGraph.13") //$NON-NLS-1$
+					   							   + sample.currentFunctionSym.functionName + Messages.getString("PowerTraceGraph.14") //$NON-NLS-1$
+					   							   + Long.toHexString(sample.currentFunctionSym.startAddress.longValue()) ),
+					   			Messages.getString("PowerTraceGraph.15") ) == null ) //$NON-NLS-1$
+			{
+				numTransitions++;
+			}
+		}
+		
+		int average = (max - min) /2 ;
+
+		DTrace = new int[windowSizes.length * WINDOW_SIZE];
+		int DTraceIndex = 0;
+		for( int i = 0; i < windowSizes.length; i++ )
+		{
+			for( int j = 0; j < WINDOW_SIZE; j++ )
+			{
+				// okay, so it seems that when there is more variablity in the trace there is more constant variablity in the power.
+				if( windowSizes[i] <= average /*halfAvgRange */ )	
+				{
+					DTrace[DTraceIndex] = 0;
+				}
+				else
+				{
+					DTrace[DTraceIndex] = 1;
+				}
+				DTraceIndex++;
+			}
+		}
+	}
+
+	// calculates the average power numbers of a selection.
+    private void calcValues() 
+	{
+        int selStart = (int)super.getSelectionStart(); 
+        int selEnd   = (int)super.getSelectionEnd();
+        int sum = 0;
+        int offset = trace.getOffset();
+        this.cumulative = 0;
+        this.averageConsumption = 0;
+        this.energy = 0;
+        
+        if (selStart < offset)
+        	selStart = offset;
+
+        if (selEnd < trace.getFirstSampleNumber() || selStart > selEnd)
+        	return;
+        
+        // find the first sample greater than or equal to selStart
+        int index = timeIndex(selStart);
+
+        // count time before the first sample as a bunch of zeros
+        if (selStart < trace.getFirstSampleNumber()) {
+        	sum = trace.getFirstSampleNumber() - selStart;
+        	index = 0;
+        }
+        
+		for (int j = index; j < sampleTimes.length; j++)
+		{	
+			int time = sampleTimes[j] + 1;
+			if (time < selStart)
+				time = selStart;
+			
+			int nextTime = j == sampleTimes.length - 1 ? Integer.MAX_VALUE : sampleTimes[j + 1];
+			
+			int count = Math.min(nextTime - time + 1, selEnd - time + 1);
+			this.energy += ((double)ampValues[j] * (double)this.voltValues[j])/(float)1000000.0 * count;
+			this.cumulative += ampValues[j] * count;
+			sum += count;
+			time += count;
+			
+			if (time > selEnd)
+				break;
+		}
+		
+		if (sum > 0)
+			this.averageConsumption = (double)this.cumulative / sum ;     		
+    }
+    
+    public double getCumulativeConsumption() 
+	{
+        return this.energy;
+    }
+     
+    public float getBatterySize() {
+        if ( trace != null ) {
+            return trace.getBatterySize();
+        } else
+            return 0.0f;
+    }
+    
+    public void setBatterySize( float newVal ) {
+        if ( trace != null )
+            trace.setBatterySize( newVal );
+    }
+	
+	public void mouseDragged(MouseEvent me)  
+	{
+		int tmpY = me.y;
+		int tmpX = me.x;
+
+		if( (tmpY < (this.getVisualSize().height - PowerTraceGraph.xLegendHeight)) && (tmpY > 0) && (!mSelecting))
+		{
+			mPowerLineY = tmpY;
+		}
+
+		this.repaint();
+	}
+
+	public void mouseMoved(MouseEvent me)  
+	{
+		showPowerValueAtX( me );
+	}
+
+	public void mouseEntered(MouseEvent arg0) {
+	}
+
+	public void mouseExited(MouseEvent arg0) {
+	}
+
+	public void mouseHover(MouseEvent arg0) {
+	}
+
+	public void addContextMenuItems(Menu menu, org.eclipse.swt.events.MouseEvent me) {
+		
+		new MenuItem(menu, SWT.SEPARATOR);
+		
+		Boolean showLine   = Boolean.TRUE;	// by default, show the interval average power as a line
+
+		// if there is a show average power line value associated with the current Analyser tab, then use it
+		Object obj = NpiInstanceRepository.getInstance().getPersistState(uid, "com.nokia.carbide.cpp.pi.power.showLine");  //$NON-NLS-1$
+		if ((obj != null) && (obj instanceof Boolean))
+			// retrieve the current value
+			showLine = (Boolean)obj;
+		else
+			// set the initial value
+			NpiInstanceRepository.getInstance().setPersistState(uid, "com.nokia.carbide.cpp.pi.power.showLine", showLine);  //$NON-NLS-1$
+
+		final Boolean showLineFinal = showLine;
+
+		MenuItem showLineItem = new MenuItem(menu, SWT.CHECK);
+		showLineItem.setText(Messages.getString("PowerTraceGraph.18")); //$NON-NLS-1$
+		showLineItem.setSelection(showLine);
+		showLineItem.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				String action;
+				NpiInstanceRepository.getInstance().setPersistState(uid, "com.nokia.carbide.cpp.pi.power.showLine", !showLineFinal);  //$NON-NLS-1$
+				if (!showLineFinal)
+				{
+					action = "show_average";  //$NON-NLS-1$
+				} else {
+					action = "hide_average";  //$NON-NLS-1$
+				}
+
+		    	for (int i = 0; i < 3; i++)
+		    	{
+		    		PowerTraceGraph graph = trace.getPowerGraph(i, getUid());
+					graph.action(action);
+		    	}
+			}
+		});
+
+		new MenuItem(menu, SWT.SEPARATOR);
+
+		int startTime = (int) this.getSelectionStart();
+		int endTime   = (int) this.getSelectionEnd();
+
+		// save raw samples
+		getSaveSamplesItem(menu, (startTime != -1) && (endTime != -1) && (startTime != endTime));
+		
+		new MenuItem(menu, SWT.SEPARATOR);
+
+		MenuItem powerSettingsItem = new MenuItem(menu, SWT.PUSH);
+		powerSettingsItem.setText(Messages.getString("PowerTraceGraph.22")); //$NON-NLS-1$
+		powerSettingsItem.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				new PowerSettingsDialog(Display.getCurrent());
+			}
+		});
+		
+		MenuItem powerStatsItem = new MenuItem(menu, SWT.PUSH);
+		powerStatsItem.setText(Messages.getString("PowerTraceGraph.23")); //$NON-NLS-1$
+		powerStatsItem.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				new PowerStatisticsDialog(Display.getCurrent());
+			}
+		});
+	}
+
+	public void paintLeftLegend(FigureCanvas figureCanvas, GC gc)
+	{
+		GC localGC = gc;
+		
+		if (gc == null)
+			gc = new GC(PIPageEditor.currentPageEditor().getSite().getShell());
+		
+		if (this.leftFigureCanvas == null)
+			this.leftFigureCanvas = figureCanvas;
+
+		Rectangle rect = ((GraphComposite) figureCanvas.getParent()).figureCanvas.getClientArea();
+		
+		double visY = rect.height - PowerTraceGraph.xLegendHeight;
+		if (visY < 0)
+			visY = 0;
+		double yIncrement = visY / 10;
+		
+		// this assumes maxPower is evenly divisible by 10
+		int maxPower = (int) this.maxPower;
+		int powerIncrement = maxPower / 10;
+
+		gc.setForeground(ColorPalette.getColor(new RGB(100, 100, 100)));
+		gc.setBackground(ColorPalette.getColor(new RGB(255, 255, 255)));
+
+		int previousBottom = 0;		// bottom of the previous legend drawn
+		String legend;
+
+		// draw 11 value indicators (0..10) to the scale  
+		int i = 0;
+		for (double y = 0; i < 11; i++, y += yIncrement, maxPower -= powerIncrement)
+		{
+			// construct the text for each scale
+			legend = (int)maxPower + Messages.getString("PowerTraceGraph.24"); //$NON-NLS-1$
+			
+			Point extent = gc.stringExtent(legend);
+			
+			gc.drawLine(GenericTraceGraph.yLegendWidth - 3, (int)y + 1, GenericTraceGraph.yLegendWidth, (int)y + 1);
+
+			if (y >= previousBottom)
+			{
+				gc.drawString(legend, GenericTraceGraph.yLegendWidth - extent.x - 4, (int)y);
+				previousBottom = (int)y + extent.y;
+			}
+		}
+
+		if (localGC == null) {
+			gc.dispose();
+			figureCanvas.redraw();
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PwrSample.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.power;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSample;
+
+/**
+ * A class representing a multimeter reading in amperes
+ */
+
+public class PwrSample extends GenericSample 
+{   
+	private static final long serialVersionUID = 3943366134331361386L;
+	public double current;
+    public double capacity;
+    public double voltage;
+    
+    public PwrSample( long time, double ampValue, double voltage, double capacity ) 
+	{
+        this.current = ampValue;
+        this.capacity = capacity;
+        this.voltage = voltage;
+        this.sampleSynchTime = time;
+    }
+
+    public String toString() 
+	{
+        return Messages.getString("PwrSample.toString1") + this.sampleSynchTime + Messages.getString("PwrSample.toString2") //$NON-NLS-1$ //$NON-NLS-2$
+        		+ this.current + Messages.getString("PwrSample.toString3") + this.voltage + Messages.getString("PwrSample.toString4") //$NON-NLS-1$ //$NON-NLS-2$
+        		+ this.capacity +Messages.getString("PwrSample.toString5"); //$NON-NLS-1$
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PwrTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.power;
+
+import java.util.ArrayList;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+public class PwrTrace extends GenericSampledTrace
+{
+	private static final long serialVersionUID = -2398791759386296139L;
+	
+	transient private PowerTraceGraph[] graphs = null;
+	transient private boolean complete = false;
+	transient private ArrayList<PwrSample> powerChangePoints;	// times when power samples change
+	transient private long maxEndTime;
+	
+    private float voltage = 3.7f;
+	
+    // used when manually positioning the trace
+    public int offset = 0; 
+	
+    public float batterySize = 1500f;
+    
+    private double scale = 0.0;
+	private double min = 0.0;
+	private double max = 0.0;
+	private double synchValue = 0.0;
+	
+	transient private int[] sampleTimes;
+    transient private int[] ampValues;
+    transient private int[] voltValues;
+    transient private int[] capaValues;
+    transient private double maxAmps = Double.MIN_VALUE;
+	transient private double minAmps = Double.MAX_VALUE;
+	transient private double maxPower = 0.0;
+
+    public GenericTraceGraph getTraceGraph(int graphIndex, int uid)
+	{		
+		return getPowerGraph(graphIndex, uid);
+	}
+	
+	public PowerTraceGraph getPowerGraph(int graphIndex, int uid)
+	{
+		if (graphs == null) {
+			graphs = new PowerTraceGraph[3];
+			maxEndTime = (long) ((PIPageEditor.currentPageEditor().getMaxEndTime() + .0005) * 1000); 
+		}
+
+		// note that graphIndex needs not match the index sent to GppTraceGraph
+		if (   (graphIndex == PIPageEditor.THREADS_PAGE)
+			|| (graphIndex == PIPageEditor.BINARIES_PAGE)
+			|| (graphIndex == PIPageEditor.FUNCTIONS_PAGE)) {
+			if (graphs[graphIndex] == null)
+				graphs[graphIndex] = new PowerTraceGraph(graphIndex, uid, this);
+			return graphs[graphIndex];
+		}
+	
+		return null;
+	}
+
+    public float getBatterySize() 
+	{
+        return batterySize;
+    }
+
+    public void setBatterySize(float newVal) 
+	{
+        batterySize = newVal;
+    }
+
+    public int getOffset() 
+	{
+        return offset;
+    }
+
+    public float getVoltage()
+    {
+    	return voltage;
+    }
+
+	public int[] getSampleTimes()
+    {
+    	return sampleTimes;
+    }
+
+	public int[] getAmpValues()
+    {
+    	return ampValues;
+    }
+
+    public int[] getVoltValues()
+    {
+    	return voltValues;
+    }
+
+    public int[] getCapaValues()
+    {
+    	return capaValues;
+    }
+
+    public double getMaxAmps()
+    {
+    	return maxAmps;
+    }
+
+    public double getMinAmps()
+    {
+    	return minAmps;
+    }
+
+	public double getMaxPower()
+    {
+    	return maxPower;
+    }
+
+	public void setVoltage(float voltage)
+    {
+    	this.voltage = voltage;
+    }
+    
+    public void setOffset( int newOffset ) 
+	{
+		int mySize = getSampleAmount();
+		
+		if( newOffset > mySize )
+			offset = mySize;
+		else if( (newOffset * -1) > mySize )
+			offset = (-1)*mySize;
+		else
+			offset = newOffset;
+    }
+    
+	public double getScale()
+	{
+		return scale;
+	}
+	
+	public double getMin()
+	{
+		return min;
+	}
+	
+	public double getMax()
+	{
+		return max;
+	}
+	
+	public long getMaxEndTime()
+	{
+		return maxEndTime;
+	}
+	
+	public double getSynchValue()
+	{
+		return synchValue;
+	}
+	
+	public void setSynchValue(double aSynchValue)
+	{
+		synchValue = aSynchValue;
+	}
+	
+	public void addSample(PwrSample sample)
+	{
+		this.samples.add(sample);
+	}
+
+	public PwrSample getPwrSample(int number)
+	{
+		return (PwrSample)this.samples.elementAt(number);
+	}
+
+	// compensate for different sampling speeds. 
+	// the software traces are done at 1KHz and the 
+	// power traces are typically done at 250Khz.
+	//
+	public void initData()
+	{
+		ArrayList<PwrSample> powerChangePoints = new ArrayList<PwrSample>();
+		PwrSample sample = (PwrSample) this.samples.get(0);
+			
+		long   currentTime     = sample.sampleSynchTime;
+		double currentCurrent  = sample.current;
+		double currentVoltage  = sample.voltage;
+		double currentCapacity = sample.capacity;
+				
+		for (int i = 1; i < this.samples.size(); i++) {
+			sample = (PwrSample) this.samples.get(i);
+			if (   sample.current  != currentCurrent
+				|| sample.voltage  != currentVoltage
+				|| sample.capacity != currentCapacity) {
+				PwrSample addSample = new PwrSample(currentTime, currentCurrent, currentVoltage, currentCapacity);
+				powerChangePoints.add(addSample);
+				currentTime     = sample.sampleSynchTime;
+				currentCurrent  = sample.current;
+				currentVoltage  = sample.voltage;
+				currentCapacity = sample.capacity;
+			}
+		}
+		
+		sample = powerChangePoints.get(powerChangePoints.size() - 1);
+		if (   sample.current  != currentCurrent
+			|| sample.voltage  != currentVoltage
+			|| sample.capacity != currentCapacity) {
+			powerChangePoints.add(new PwrSample(currentTime, currentCurrent, currentVoltage, currentCapacity));
+		}
+
+		this.powerChangePoints = powerChangePoints;
+		
+		sampleTimes = new int[this.powerChangePoints.size()];
+        ampValues   = new int[this.powerChangePoints.size()];
+        voltValues  = new int[this.powerChangePoints.size()];
+        capaValues  = new int[this.powerChangePoints.size()];
+
+		int localMaxAmps = Integer.MIN_VALUE;
+		int localMinAmps = Integer.MAX_VALUE;
+
+		for (int i = 0; i < this.powerChangePoints.size(); i++)
+	    {
+			PwrSample tmp = this.powerChangePoints.get(i);
+			sampleTimes[i] = (int)Math.abs(tmp.sampleSynchTime);		
+			ampValues[i]   = (int)Math.abs(tmp.current);	// in milliamps
+			voltValues[i]  = (int)Math.abs(tmp.voltage);	// in millivolts
+			capaValues[i]  = (int)Math.abs(tmp.capacity);
+
+			if (ampValues[i] > localMaxAmps)
+			{
+				localMaxAmps = ampValues[i];
+			}
+			else if (ampValues[i] < minAmps )
+			{
+				localMinAmps = ampValues[i];
+			}
+		}
+	    
+	    maxAmps = localMaxAmps;
+	    minAmps = localMinAmps;
+
+	    scaleMaxPower();
+	}
+	
+	public ArrayList<PwrSample> getPowerChangePoints()
+	{
+		return this.powerChangePoints;
+	}
+	
+	public void scaleMaxPower()
+	{
+		maxPower = maxAmps * this.voltage;
+
+		if (maxPower < 10)
+	    	maxPower =     10;
+		else if (maxPower <     20)
+	    	maxPower =     20;
+	    else if (maxPower <     50)
+	    	maxPower =     50;
+	    else if (maxPower <    100)
+	    	maxPower =    100;
+	    else if (maxPower <    200)
+	    	maxPower =    200;
+	    else if (maxPower <    500)
+	    	maxPower =    500;
+	    else if (maxPower <   1000)
+	    	maxPower =   1000;
+	    else if (maxPower <   2000)
+	    	maxPower =   2000;
+	    else if (maxPower <   5000)
+	    	maxPower =   5000;
+	    else if (maxPower <  10000)
+	    	maxPower =  10000;
+	    else if (maxPower <  20000)
+	    	maxPower =  20000;
+	    else if (maxPower <  50000)
+	    	maxPower =  50000;
+	    else if (maxPower < 100000)
+	    	maxPower = 100000;
+	}
+
+  	/*
+  	 * Check if the power trace is complete (first sample is at time 1, sample N is at time N)
+  	 */
+  	public void setComplete()
+  	{
+		int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+  		int size;
+  		
+  		this.complete = true;
+  		
+   		size = this.samples.size();
+  		for (int i = 0; i < size; i++) {
+  			PwrSample element = (PwrSample)this.samples.get(i);
+  			if (element.sampleSynchTime != i*samplingInterval) {
+  				this.complete = false;
+  				break;
+  			}
+  		}
+  	}
+  	
+  	public boolean isComplete() {
+  		return this.complete;
+  	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PwrTraceGraph.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.power;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.util.Enumeration;
+
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.Panel;
+import org.eclipse.swt.graphics.GC;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+
+
+public class PwrTraceGraph extends GenericTraceGraph implements MouseMotionListener, MouseListener
+{
+	private boolean selected = true;
+	
+	public PwrTraceGraph(PwrTrace trace)
+	{
+		super(trace);
+	}
+	
+	public void paint(Graphics g)
+	{
+		if(!selected) return;
+		
+		Enumeration samples = ((GenericSampledTrace)this.getTrace()).samples.elements();
+		g.setColor(Color.RED);
+		
+		while(samples.hasMoreElements())
+		{
+		}
+	}
+
+	public void repaint() 
+	{
+	}
+
+	public void refreshDataFromTrace() 
+	{
+	}
+
+	public void mouseMoved(MouseEvent me)
+	{
+		if(!selected) return;
+		
+		Enumeration samples = ((GenericSampledTrace)this.getTrace()).samples.elements();
+		while(samples.hasMoreElements())
+		{
+		}
+	}
+	
+	public void mouseClicked(MouseEvent me) //add custom tooltip to a pwrtrace tag
+	{
+		if(!selected || me.getClickCount() < 2) return;
+		
+		
+		Enumeration samples = ((GenericSampledTrace)this.getTrace()).samples.elements();
+		while(samples.hasMoreElements())
+		{
+		}
+	}
+	
+	public void action(String action) 
+	{
+  		if(action.equals("pwrsel_selected")) //$NON-NLS-1$
+  		{
+  			this.selected = true;
+  			this.repaint();
+  		}
+  	  	else if(action.equals("pwrsel_not_selected")) //$NON-NLS-1$
+  	  	{
+  	  		this.selected = false;
+  	  		this.repaint();
+  	  	}
+  	}
+  	
+	public void mouseDragged(MouseEvent arg0) {}
+	
+	public void mouseEntered(MouseEvent arg0) {}
+	
+	public void mouseExited(MouseEvent arg0) {}
+	
+	public void mousePressed(MouseEvent arg0) {}
+	
+	public void mouseReleased(MouseEvent arg0) {}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph#paint(org.eclipse.draw2d.Panel, org.eclipse.draw2d.Graphics)
+	 */
+	@Override
+	public void paint(Panel panel, org.eclipse.draw2d.Graphics graphics) {
+		this.setSize(this.getSize().width, getVisualSize().height);
+	}
+
+	public void paintLeftLegend(FigureCanvas figureCanvas, GC gc) {
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/PwrTraceParser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.power;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.Parser;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+public class PwrTraceParser extends Parser
+{
+	private boolean debug = false;
+	private PwrSample[] traceData;	
+
+	public PwrTraceParser() throws Exception
+	{
+	}
+	
+	public PwrTraceParser(File file) throws Exception
+	{
+		if (!file.exists() || file.isDirectory())
+		{
+			throw new Exception(Messages.getString("PwrTraceParser.cannotOpenTraceFile")); //$NON-NLS-1$
+		}
+		
+		FileInputStream fis = new FileInputStream(file);
+		byte[] data = new byte[(int)file.length()];
+		fis.read(data);
+		this.traceVersion = this.getVersion(data);
+		System.out.println(Messages.getString("PwrTraceParser.powerVersion") + this.traceVersion); //$NON-NLS-1$
+		if (traceVersion.indexOf("V1.57") != -1) //$NON-NLS-1$
+		    this.parse(file);
+		else
+		    System.out.println(Messages.getString("PwrTraceParser.unsupportedVersion") + this.traceVersion); //$NON-NLS-1$
+		fis.close();
+	}
+		
+	public ParsedTraceData parse(File file) throws Exception 
+	{
+		if (!file.exists() || file.isDirectory())
+		{
+			throw new Exception(Messages.getString("PwrTraceParser.cannotOpenTraceFile")); //$NON-NLS-1$
+		}
+		
+		Vector intermediateTraceData = new Vector();
+
+		try 
+		{
+			FileInputStream fis = new FileInputStream(file);
+			byte[] data = new byte[(int)file.length()];
+			fis.read(data);
+			
+			this.traceVersion = this.getVersion(data);
+			System.out.println(Messages.getString("PwrTraceParser.powerVersion") + this.traceVersion); //$NON-NLS-1$
+			if (traceVersion.indexOf("V1.57") == -1) //$NON-NLS-1$
+			{
+			    System.out.println(Messages.getString("PwrTraceParser.unsupportedVersion") + this.traceVersion); //$NON-NLS-1$
+			    fis.close();
+			    return null;
+			}
+			
+			ByteArrayInputStream bais = new ByteArrayInputStream(data);
+			DataInputStream dis = new DataInputStream(bais);
+			
+			// read the length of the header
+			int length = dis.readByte();
+			// skip the header
+			for (int i = 0; i < length; i++)
+				dis.readByte();
+			
+			long voltage = 0;
+			long current = 0;
+			long capacity = 0;
+			long sampleTime = 0;
+
+			try
+			{
+				while(true)
+				{
+					capacity = readTUint16(dis);
+					voltage = readTUint16(dis);
+					current = readTUint(dis);
+					sampleTime = readTUint(dis);
+
+					PwrSample sample = new PwrSample(sampleTime, current, voltage, capacity);
+
+					intermediateTraceData.add(sample);
+				}
+			}
+			catch (EOFException eof)
+			{
+				//return;
+			}
+			catch (Exception e)
+			{
+				GeneralMessages.showErrorMessage(Messages.getString("PwrTraceParser.errorReadingTraceFile")); //$NON-NLS-1$
+				throw e;				
+			}
+		}
+		
+		catch (Exception e)
+		{
+			GeneralMessages.showErrorMessage(Messages.getString("PwrTraceParser.errorReadingTraceFile")); //$NON-NLS-1$
+			throw e;				
+		}
+	
+		if (debug) System.out.println(Messages.getString("PwrTraceParser.traceFileParsed") + intermediateTraceData.size()); //$NON-NLS-1$
+		
+		// all samples have been parsed
+		intermediateTraceData.trimToSize();
+		this.traceData = new PwrSample[intermediateTraceData.size()];
+		
+		// store the trace data into an array
+		intermediateTraceData.toArray(this.traceData);
+		
+		ParsedTraceData ptd = new ParsedTraceData();
+		ptd.traceData = this.getTrace();
+		return ptd;
+	}
+	
+	private String getVersion(byte[] data)
+	{
+		int length = data[0];
+
+		String ver = Messages.getString("PwrTraceParser.unknown"); //$NON-NLS-1$
+		String verString = new String(data, 1, length);
+		if (debug)
+			System.out.println(Messages.getString("PwrTraceParser.versionStringDebug") + verString); //$NON-NLS-1$
+		
+		if(verString.indexOf("Bappea") != -1) //$NON-NLS-1$
+			if(verString.indexOf("PWR") != -1) //$NON-NLS-1$
+			{
+				int index = verString.indexOf("_"); //$NON-NLS-1$
+				ver = verString.substring(index + 1, length);
+			}
+		return ver;
+	}		
+	
+	private long readTUint(DataInputStream dis) throws Exception
+	{
+		long result = dis.readUnsignedByte();
+		result += dis.readUnsignedByte() << 8;
+		result += dis.readUnsignedByte() << 16;
+		result += dis.readUnsignedByte() << 24;
+		return result;
+	}
+
+	private long readTUint16(DataInputStream dis) throws Exception
+	{
+		int result = dis.readUnsignedByte();
+		result += dis.readUnsignedByte() << 8;
+		return result;
+	}
+
+	private GenericTrace getTrace()
+	{
+		PwrTrace trace = new PwrTrace();
+		for (int i = 0; i < traceData.length; i++)
+		{
+			trace.addSample(this.traceData[i]);
+		}
+		return trace;
+	}
+	
+    public static void main( String[] args ) 
+    {
+	    try {
+	        PwrTraceParser p = new PwrTraceParser(new File(Messages.getString("PwrTraceParser.tmpFilePath"))); //$NON-NLS-1$
+	    } catch ( Exception  e ) {
+	        System.out.println(Messages.getString("PwrTraceParser.exceptionMessage") + e.getMessage() ); //$NON-NLS-1$
+	    }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.power/src/com/nokia/carbide/cpp/pi/power/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+PwrTraceParser.cannotOpenTraceFile=Unable to open power trace file
+PwrTraceParser.powerVersion=Power trace version 
+PwrTraceParser.unsupportedVersion=Unsupported power trace version: 
+PwrTraceParser.errorReadingTraceFile=Error in reading power trace file
+PwrTraceParser.traceFileParsed=Power trace file parsed, size: 
+PwrTraceParser.unknown=Unknown
+PwrTraceParser.versionStringDebug=Version string: 
+PwrTraceParser.tmpFilePath=E:\\Temp\\Power_trace_4_file11030.dat
+PwrTraceParser.exceptionMessage=Exception: 
+PowerTraceGraph.histogram1=::
+PowerTraceGraph.11=>NULL<
+PowerTraceGraph.12=_
+PowerTraceGraph.13=\ 
+PowerTraceGraph.14=\ Addr: 0x
+PowerTraceGraph.15=\ 
+PowerTraceGraph.18=Show Selected Interval Average Power Line
+PowerTraceGraph.22=Power Usage Settings\u2026
+PowerTraceGraph.23=Power Usage Statistics
+PowerTraceGraph.24=mW
+PowerTraceGraph.comma=,
+PowerPlugin.powerGraph=Power Graph
+PowerPlugin.powerSettingsAction=Power Usage Settings\u2026
+PowerPlugin.powerSettingsTooltip=Change power usage graph settings
+PowerPlugin.powerStatsAction=Power Usage Statistics
+PowerPlugin.PowerStatsTooltip=Show power usage statistics for the selected interval
+PowerPlugin.showIntervalLineAction=Show Selected Interval Average Power Line
+PowerPlugin.showIntervalLineTooltip=Show line with average power usage for the selected interval
+PowerTraceGraph.saveSamplesForInterval=Save All Power Samples for Interval...
+PowerTraceGraph.saveSamplesHeading=Time (ms),Current (mA),Voltage (mV),Capacity (mAh)\n
+PowerPlugin.pluginTitle=Power Usage
+powerFormat=\#\#0 mW
+voltageFormat=\#0.0\#\# V
+tooltip1=s:   
+tooltip2=mW @ 
+PwrSample.toString1=[ 
+PwrSample.toString2=\ ms: 
+PwrSample.toString3=\ mA: 
+PwrSample.toString4=\ mV: 
+PwrSample.toString5=\ mAh]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/.settings/org.eclipse.core.resources.prefs	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,3 @@
+#Mon Feb 09 13:33:05 CST 2009
+eclipse.preferences.version=1
+encoding//src/com/nokia/carbide/cpp/pi/priority/messages.properties=8859_1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Thread Priorities
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.priority;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.priority.PriorityPlugin
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ com.nokia.carbide.cpp.pi,
+ com.nokia.carbide.cpp.pi.util
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.pi.priority;x-friends:="com.nokia.carbide.cpp.pi.memory,com.nokia.carbide.cpp.pi.priority.tests"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,6 @@
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .
+jars.compile.order = .
+source.. = src/
+output.. = bin/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+   <extension
+         point="com.nokia.carbide.cpp.pi.piPluginData">
+      <plugin pluginClass="com.nokia.carbide.cpp.pi.priority.PriorityReturnPlugin"/>
+   </extension>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.priority.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriSample.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSample;
+
+public class PriSample extends GenericSample
+{
+	private static final long serialVersionUID = -4474787388603984159L;
+	
+	public PriThread thread;
+	public int priority;
+	public int sampleNum;
+	
+	public PriSample(PriThread thread, int priority, int sampleNum)
+	{
+		this.thread = thread;
+		this.priority = priority;
+		this.sampleNum = sampleNum;
+		this.sampleSynchTime = sampleNum;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriThread.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericThread;
+
+
+public class PriThread extends GenericThread
+{
+	private static final long serialVersionUID = -7057416050237320718L;
+	
+	public PriThread(Integer threadId, String threadName, String processName)
+	{
+		this.threadId = threadId;
+		this.threadName = threadName;
+		this.processName = processName;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority;
+
+import java.util.Hashtable;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.model.GenericThread;
+import com.nokia.carbide.cpp.internal.pi.model.TraceWithThreads;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+
+
+public class PriTrace extends GenericSampledTrace implements TraceWithThreads
+{
+	private static final long serialVersionUID = 7929002387070527775L;
+	
+	private Hashtable firstSynchTimes;
+	private Hashtable lastSynchTimes;
+	private int samplingTime;
+	private PriThread[] threads;
+	
+	public PriTrace()
+	{
+		firstSynchTimes = new Hashtable();
+		lastSynchTimes = new Hashtable();
+	}
+	
+	public void addSample(PriSample sample)
+	{
+		this.samples.add(sample);
+	}
+	
+	public PriSample getPriSample(int number)
+	{
+		return (PriSample)this.samples.elementAt(number);
+	}
+	  
+	public GenericTraceGraph getTraceGraph()
+	{
+	  	return null;
+	}
+	  
+	public GenericThread[] getThreads()
+	{
+	  	return threads;
+	}
+	
+	public void setThreads(PriThread[] threads)
+	{
+		this.threads = threads;
+	}
+	  
+//	public long getLastSynchTimeForThread(GenericThread t)
+//	{
+//	  	return ((Integer) lastSynchTimes.get(t.threadId)).intValue();
+//	}
+//	  
+//	public long getFirstSynchTimeForThread(GenericThread t)
+//	{
+//		return ((Integer) firstSynchTimes.get(t.threadId)).intValue();
+//	}
+	
+	public void addFirstSynchTime(Integer id, Integer firstSynchTime)
+	{
+		firstSynchTimes.put(id, firstSynchTime);
+	}
+	
+	public void addLastSynchTime(Integer id, Integer lastSynchTime)
+	{
+		lastSynchTimes.put(id, lastSynchTime);
+	}
+	
+	public void setSamplingTime(int time)
+	{
+		this.samplingTime = time;
+	}
+	
+	public int getSamplingTime()
+	{
+		return samplingTime;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriTraceParser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,864 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.Parser;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+public class PriTraceParser extends Parser
+{
+    private boolean debug = false;
+
+    private String version;
+    
+	private Vector<PriThread> priSamples = new Vector<PriThread>();
+	private char[] buffer = new char[80];
+	private String threadName;
+	private String processName;
+	private int threadId;
+	private int sampleNum;
+	private int processPriority;
+	private int threadPriority;
+	private PriSample priSample;
+	private PriTrace priTrace;
+	private byte a, b, c, d;
+	private int readCount = 0;
+	
+	public PriTraceParser(File file) //throws Exception
+	{
+	}
+	
+	public ParsedTraceData parse(File f) throws Exception 
+	{
+		if (!f.exists() || f.isDirectory())
+	    {
+	      throw new Exception(Messages.getString("PriTraceParser.cannotOpenMemoryTrace")); //$NON-NLS-1$
+	    }
+		if (debug) System.out.println(Messages.getString("PriTraceParser.memoryTraceFileLength")+f.length()); //$NON-NLS-1$
+
+	    parsePriTrace(f);
+	    
+	    if (this.getTrace() == null)
+	    	return null;
+		
+		ParsedTraceData ptd = new ParsedTraceData();
+		ptd.traceData = this.getTrace();
+		return ptd;
+	}
+	
+	private void parseNewPriFile(String version,DataInputStream dis) throws Exception
+	{
+		if (version.equals("0.85") || version.equals("0.91") || version.equals("1.00")||version.equals("1.10")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+		{
+			parseV085MemFile(dis);
+		}
+		else if (version.equals("1.55")) //$NON-NLS-1$
+		{
+			return;
+		}
+		else
+			throw new Exception(Messages.getString("PriTraceParser.unsupportedMemoryTrace1")+version+Messages.getString("PriTraceParser.unsupportedMemoryTrace2")); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+	
+	private void parseV085MemFile(DataInputStream dis) throws Exception
+	{
+		// read the version again
+		byte[] version = readElementWithLength(dis);
+		System.out.println(Messages.getString("PriTraceParser.readVersion")+new String(version)); //$NON-NLS-1$
+		this.version = new String(version);
+		
+		this.readV085MemSample(dis);
+	}
+	
+	private void parseV110PriFile(DataInputStream dis) throws Exception
+	{
+		// read the version again
+		byte[] version = readElementWithLength(dis);
+		System.out.println(Messages.getString("PriTraceParser.readVersion")+new String(version)); //$NON-NLS-1$
+		this.version = new String(version);
+		
+		this.readV110PriSample(dis);
+	}
+
+	
+	
+	public String getProfilerVersion()
+	{
+	    return version;
+	}
+	
+	private void readV085MemSample(DataInputStream dis) throws Exception
+	{
+	    Vector<long[]> rawV085Samples = new Vector<long[]>();
+	    Vector<long[]> lastSampleRaw = new Vector<long[]>();
+
+		//memTrace = new MemTrace();
+	    priTrace = new PriTrace();
+	   		
+		// first there should be 4 bytes of sample time
+		long sample = this.readTUintWithLength(dis);
+		//System.out.println("Current sample "+sample);
+				
+		// then read if there is thread name data
+		int length = dis.readUnsignedByte();readCount++;
+		if (length != 1) throw new Exception(Messages.getString("PriTraceParser.typeMissing")); //$NON-NLS-1$
+		
+		int mode = dis.readUnsignedByte();readCount++;
+		//System.out.println("First mode "+Integer.toHexString(mode));
+		try
+		{
+			// read the first length
+			length = dis.readUnsignedByte();readCount++;
+			//System.out.println("First length "+length);
+			Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
+			
+			while(true)
+			{
+
+				//System.out.println("ReadCount:"+this.readCount);
+				if (length == 0) //haxor =)
+				{
+					//System.out.println("Length = 0, New sample");
+					// end of sample
+					// read new length
+					
+					// first there should be 4 bytes of sample time
+					sample = this.readTUintWithLength(dis);
+					//System.out.println("Sample number:"+sample);
+					
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("New length "+length);				
+					//break;
+					
+					if (length == 4)
+					{
+						// there was only the sample header here
+						System.out.println(Messages.getString("PriTraceParser.missingSample")+sample); //$NON-NLS-1$
+						mode = 0x00;
+					}
+					else if (length != 1)
+					{
+						throw new Exception(Messages.getString("PriTraceParser.wrongLength")+length); //$NON-NLS-1$
+					}
+					else
+					{
+						lastSampleRaw.clear();
+					}
+				}
+				
+				if (length == 1)
+				{
+					mode = dis.readUnsignedByte();readCount++;
+					//System.out.println("New Mode "+mode+" new length "+length);
+
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("Next length "+length);
+				}
+				
+				if (mode == 0xaa)
+				{
+					// reading thread names
+					String rawName = readThreadName(dis,length);
+					long threadId = readTUint(dis);
+					//System.out.println("Raw name "+rawName);
+				   	int index = rawName.indexOf(':');
+				   	if (index != -1)
+				   	{
+				   		processName = rawName.substring(0,index);
+				   		threadName = rawName.substring(rawName.lastIndexOf(':')+1,rawName.length());
+				   		//System.out.println("Thread: "+threadName+" process: "+processName+" id: "+threadId);
+				   	}
+				   	else
+				   	{
+				   		processName = rawName;
+				   		threadName = rawName;
+				   	}
+								    	
+				   	priTrace.addFirstSynchTime(new Integer((int)threadId), new Integer(sampleNum));
+				   	priSamples.add(new PriThread(new Integer((int)threadId), threadName, processName));
+
+				   	// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("Next length "+length);
+				}
+				else if (mode == 0xdd)
+				{
+					// reading data
+					long[] elements = this.readDataElements085Mem(dis,length,sample);
+					
+					rawV085Samples.add(elements);
+					lastSampleRaw.add(elements);
+
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("Next length "+length);
+				}
+				else if (mode == 0x00)
+				{
+					// duplicate the previous sample to replace the missing sample
+					Enumeration<long[]> e = lastSampleRaw.elements();
+					while(e.hasMoreElements())
+					{
+						long[] element = e.nextElement();
+						long[] newElement = new long[7];
+						newElement[0] = element[0];
+						newElement[1] = element[1];
+						newElement[2] = element[2];
+						newElement[3] = element[3];
+						newElement[4] = element[4];
+						newElement[5] = element[5];
+						// replace the sample number with the missing one
+						newElement[6] = sample;
+						// add the duplicated sample
+						rawV085Samples.add(newElement);
+					}
+					
+					// read the length, it is already known
+					sample = readTUint(dis);
+					System.out.println(Messages.getString("PriTraceParser.readNextSample")+sample); //$NON-NLS-1$
+					length = dis.readUnsignedByte();readCount++;;
+				}
+				else
+				{
+					throw new Exception(Messages.getString("PriTraceParser.wrongMode")+mode); //$NON-NLS-1$
+				}
+			}
+		}
+		catch (EOFException e)
+		{
+			System.out.println(Messages.getString("PriTraceParser.doneReading")); //$NON-NLS-1$
+			this.addRawV085Samples(rawV085Samples);
+		}
+	}
+	
+	private void addRawV085Samples(Vector<long[]> rawV085Samples)
+	{
+//	    MemThread[] memTreads = new MemThread[memSamples.size()];
+//	    memSamples.copyInto((MemThread[]) memTreads);
+//	    memTrace.setThreads(memTreads);
+	    
+	    PriThread[] priThreads = new PriThread[priSamples.size()];
+	    priSamples.copyInto((PriThread[]) priThreads);
+	    priTrace.setThreads(priThreads);
+	    
+	    Enumeration<long[]> rawEnum = rawV085Samples.elements();
+	    while(rawEnum.hasMoreElements())
+	    {
+	    	long[] element = rawEnum.nextElement();
+	    	threadId = (int)element[0];
+	    	threadPriority = (int)element[5];
+	    	// for the null thread, converts 8bit unsigned to signed
+	    	if (threadPriority > 32768)
+	    	    threadPriority = threadPriority - 65536;
+	    	sampleNum = (int)element[6]; 
+
+	    	for (Enumeration<PriThread> e = priSamples.elements();e.hasMoreElements();)
+	    	{
+	    		PriThread pt = e.nextElement();
+	    		if (pt.threadId.intValue() == threadId)
+	    		{
+	    			//int priority = solveAbsolutPriority(processPriority, threadPriority);
+	    			priSample = new PriSample(pt, threadPriority, sampleNum);
+	    			priTrace.addSample(priSample);
+	    			break;
+	    		}
+	    	}
+//	    	memTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleNum));
+	    	priTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleNum));
+	    }
+	    System.out.println(Messages.getString("PriTraceParser.done")); //$NON-NLS-1$
+	}
+
+	private void readV110PriSample(DataInputStream dis) throws Exception
+	{
+	    Vector<long[]> rawV110PriSamples = new Vector<long[]>();
+	    Vector<long[]> lastSampleRaw = new Vector<long[]>();
+
+		//memTrace = new MemTrace();
+	    priTrace = new PriTrace();
+	   		
+		// first there should be 4 bytes of sample time
+		long sample = this.readTUintWithLength(dis);
+		//System.out.println("Current sample "+sample);
+				
+		// then read if there is thread name data
+		int length = dis.readUnsignedByte();readCount++;
+		if (length != 1) throw new Exception(Messages.getString("PriTraceParser.typeMissing")); //$NON-NLS-1$
+		
+		int mode = dis.readUnsignedByte();readCount++;
+		//System.out.println("First mode "+Integer.toHexString(mode));
+		try
+		{
+			// read the first length
+			length = dis.readUnsignedByte();readCount++;
+			//System.out.println("First length "+length);
+			Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
+			
+			while(true)
+			{
+
+				//System.out.println("ReadCount:"+this.readCount);
+				if (length == 0)
+				{
+					//System.out.println("Length = 0, New sample");
+					// end of sample
+					// read new length
+					
+					// first there should be 4 bytes of sample time
+					sample = this.readTUintWithLength(dis);
+					//System.out.println("Sample number:"+sample);
+					
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("New length "+length);				
+					//break;
+					
+					if (length == 4)
+					{
+						// there was only the sample header here
+						System.out.println(Messages.getString("PriTraceParser.missingSample")+sample); //$NON-NLS-1$
+						mode = 0x00;
+					}
+					else if (length != 1)
+					{
+						throw new Exception(Messages.getString("PriTraceParser.wrongLength")+length); //$NON-NLS-1$
+					}
+					else
+					{
+						lastSampleRaw.clear();
+					}
+				}
+				
+				if (length == 1)
+				{
+					mode = dis.readUnsignedByte();readCount++;
+					//System.out.println("New Mode "+mode+" new length "+length);
+
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("Next length "+length);
+				}
+				
+				if (mode == 0xaa)
+				{
+					// reading thread names
+					String rawName = readThreadName(dis,length);
+					long threadId = readTUint(dis);
+					//System.out.println("Raw name "+rawName);
+				   	int index = rawName.indexOf(':');
+				   	if (index != -1)
+				   	{
+				   		processName = rawName.substring(0,index);
+				   		threadName = rawName.substring(rawName.lastIndexOf(':')+1,rawName.length());
+				   		//System.out.println("Thread: "+threadName+" process: "+processName+" id: "+threadId);
+				   	}
+				   	else
+				   	{
+				   		processName = rawName;
+				   		threadName = rawName;
+				   	}
+								    	
+					//memTrace.addFirstSynchTime(new Integer((int)threadId),new Integer((int)sample));
+				   	//memSamples.add(new MemThread(new Integer((int)threadId), threadName, processName));
+				   	priTrace.addFirstSynchTime(new Integer((int)threadId), new Integer(sampleNum));
+				   	priSamples.add(new PriThread(new Integer((int)threadId), threadName, processName));
+
+				   	// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("Next length "+length);
+				}
+				else if (mode == 0xdd)
+				{
+					// reading data
+					long[] elements = this.readDataElements110Pri(dis,length,sample);
+					
+					/*
+					System.out.println("Read elements "+elements);
+					if (elements != null)
+					{
+						for (int i=0;i<elements.length;i++)
+							System.out.println("Element #"+i+" "+Long.toHexString(elements[i]));
+					}
+					*/
+					rawV110PriSamples.add(elements);
+					lastSampleRaw.add(elements);
+
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("Next length "+length);
+				}
+				else if (mode == 0x00)
+				{
+					// duplicate the previous sample to replace the missing sample
+					Enumeration<long[]> e = lastSampleRaw.elements();
+					while(e.hasMoreElements())
+					{
+						long[] element = e.nextElement();
+						long[] newElement = new long[7];
+						newElement[0] = element[0];
+						newElement[1] = element[1];
+						//newElement[2] = element[2];
+						//newElement[3] = element[3];
+						//newElement[4] = element[4];
+						//newElement[5] = element[5];
+						// replace the sample number with the missing one
+						newElement[2] = sample;
+						// add the duplicated sample
+						rawV110PriSamples.add(newElement);
+					}
+					
+					// read the length, it is already known
+					sample = readTUint(dis);
+					System.out.println(Messages.getString("PriTraceParser.readNextSample")+sample); //$NON-NLS-1$
+					length = dis.readUnsignedByte();readCount++;;
+				}
+				else
+				{
+					throw new Exception(Messages.getString("PriTraceParser.wrongMode")+mode); //$NON-NLS-1$
+				}
+			}
+		}
+		catch (EOFException e)
+		{
+			System.out.println(Messages.getString("PriTraceParser.doneReading")); //$NON-NLS-1$
+			this.addRawV110PriSamples(rawV110PriSamples);
+		}
+	}
+
+	private void addRawV110PriSamples(Vector<long[]> rawV110PriSamples)
+	{
+	    //MemThread[] memTreads = new MemThread[memSamples.size()];
+	    //memSamples.copyInto((MemThread[]) memTreads);
+	    //memTrace.setThreads(memTreads);
+	    
+	    PriThread[] priThreads = new PriThread[priSamples.size()];
+	    priSamples.copyInto((PriThread[]) priThreads);
+	    priTrace.setThreads(priThreads);
+	    
+	    Enumeration<long[]> rawEnum = rawV110PriSamples.elements();
+	    while(rawEnum.hasMoreElements())
+	    {
+	    	long[] element = rawEnum.nextElement();
+	    	threadId = (int)element[0];
+	    	threadPriority = (int)element[1];
+	    	// for the null thread, converts 8bit unsigned to signed
+	    	if (threadPriority > 32768)
+	    	    threadPriority = threadPriority - 65536;
+	    	//heapSize = (int)element[1];
+	    	//stackSize = (int)element[4];
+	    	sampleNum = (int)element[2]; 
+	    	
+	    	for (Enumeration<PriThread> e = priSamples.elements();e.hasMoreElements();)
+	    	{
+	    		PriThread pt = e.nextElement();
+	    		if (pt.threadId.intValue() == threadId)
+	    		{
+	    			//int priority = solveAbsolutPriority(processPriority, threadPriority);
+	    			priSample = new PriSample(pt, threadPriority, sampleNum);
+	    			priTrace.addSample(priSample);
+	    			break;
+	    		}
+	    	}
+//	    	memTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleNum));
+	    	priTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleNum));
+	    }
+	    System.out.println(Messages.getString("PriTraceParser.done")); //$NON-NLS-1$
+	}
+
+//	private void readAndPrintData(DataInputStream dis, int length) throws Exception
+//	{
+//		for (int i=0;i<length;i++)
+//			System.out.print(" "+Integer.toHexString(dis.readUnsignedByte()));
+//		System.out.print("\n");
+//	}
+
+	private long[] readDataElements085Mem(DataInputStream dis,int length,long sampleNum) throws Exception
+	{
+		if (length != 0)
+		{
+			long[] elements = new long[7];
+			elements[0] = this.readTUint(dis);
+			elements[1] = this.readTUint(dis);
+			elements[2] = this.readTUint(dis);
+			elements[3] = this.readTUint(dis);
+			elements[4] = this.readTUint(dis);
+			elements[5] = this.readShort(dis);
+			//System.out.println("Priority: "+elements[5]);
+			elements[6] = sampleNum;
+
+			return elements;
+		}
+		else 
+		{
+			System.out.println(Messages.getString("PriTraceParser.zeroLength")); //$NON-NLS-1$
+			return null;
+		}
+	}
+
+	private long[] readDataElements110Pri(DataInputStream dis,int length,long sampleNum) throws Exception
+	{
+		if (length != 0)
+		{
+			long[] elements = new long[3];
+			elements[0] = this.readTUint(dis);  //thread ID
+			elements[1] = this.readShort(dis);  //Priority
+			elements[2] = sampleNum;  //sample number
+			//elements[3] = this.readTUint(dis);
+			//elements[4] = this.readTUint(dis);
+			//elements[5] = this.readShort(dis); //priority is not read
+			//elements[5] = sampleNum;
+
+			return elements;
+		}
+		else 
+		{
+			System.out.println(Messages.getString("PriTraceParser.zeroLength")); //$NON-NLS-1$
+			return null;
+		}
+	}
+	
+	private String readThreadName(DataInputStream dis,int length) throws Exception
+	{
+		if (length != 0)
+		{
+			length-=4;
+			//System.out.println("Thread name length "+length);
+			byte[] element = new byte[length];
+			dis.read(element,0,length);
+			readCount+=length;
+			return new String(element);
+		}
+		else return null;
+	}
+	
+	private byte[] readElementWithLength(DataInputStream dis) throws Exception
+	{
+		byte length = dis.readByte(); readCount++;
+		if (length != 0)
+		{
+			//System.out.println("Element length "+length);
+			byte[] element = new byte[length];
+			dis.read(element,0,length);
+			readCount += length;
+			return element;
+		}
+		else return null;
+	}
+	
+//	private long readReversedTUint(DataInputStream dis) throws Exception
+//	{
+//		long result = dis.readUnsignedByte() << 24;
+//		readCount++;
+//		result += dis.readUnsignedByte() << 16;
+//		readCount++;
+//		result += dis.readUnsignedByte() << 8;
+//		readCount++;
+//		result += dis.readUnsignedByte();
+//		readCount++;
+//		return result;
+//	}
+	
+//	private long readReversedShort(DataInputStream dis) throws Exception
+//	{
+//		long result = dis.readUnsignedByte() << 8;
+//		readCount++;
+//		result += dis.readUnsignedByte();
+//		readCount++;
+//		return result;
+//	}
+	
+	private long readShort(DataInputStream dis) throws Exception
+	{
+		long result = dis.readUnsignedByte();
+		readCount++;
+		result += dis.readUnsignedByte() << 8;
+		readCount++;
+		return result;
+	}
+	
+	private long readTUint(DataInputStream dis) throws Exception
+	{
+		long result = dis.readUnsignedByte();
+		readCount++;
+		result += dis.readUnsignedByte() << 8;
+		readCount++;
+		result += dis.readUnsignedByte() << 16;
+		readCount++;
+		result += dis.readUnsignedByte() << 24;
+		readCount++;
+		return result;
+	}
+
+	private long readTUintWithLength(DataInputStream dis) throws Exception
+	{
+		byte length = (byte)dis.readUnsignedByte();
+		readCount++;
+		//System.out.println("Pituus: "+length);
+		if (length != 4) 
+		{
+			throw new Exception(Messages.getString("PriTraceParser.TUINTLengthException1")+length+Messages.getString("PriTraceParser.TUINTLengthException2")); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		long result = dis.readUnsignedByte();
+		readCount++;
+		result += dis.readUnsignedByte() << 8;
+		readCount++;
+		result += dis.readUnsignedByte() << 16;
+		readCount++;
+		result += dis.readUnsignedByte() << 24;
+		readCount++;
+		
+		//System.out.println("Read length ok");
+		return result;
+	}
+
+	private void parsePriTrace(File file) throws Exception
+	{
+		DataInputStream dis = new DataInputStream(new FileInputStream(file));		
+	    byte[] traceArray = new byte[(int)file.length()];
+	    dis.readFully(traceArray);
+	    
+	    // test the mem trace version
+	    if (traceArray.length > 257)
+	    {
+	    	String s = new String(traceArray,1,traceArray[0]);
+	    	if (!s.startsWith("Bappea_V1.10") && !s.startsWith("Bappea_V2.01")) //up to 1.0 version  //$NON-NLS-1$ //$NON-NLS-2$
+	    	{
+	    		if(s.startsWith("Bappea_V1.5") || s.startsWith("Bappea_V2.0"))  //$NON-NLS-1$
+	    		{
+	    			return;
+	    		}
+	    		String version = s.substring(8,12);
+	    		String traceType = s.substring(13,s.length());
+	    		System.out.println(Messages.getString("PriTraceParser.foundVersion1")+version+Messages.getString("PriTraceParser.foundVersion2")+traceType+Messages.getString("PriTraceParser.foundVersion3")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	    		if (!traceType.equals("MEM"))  //$NON-NLS-1$
+	    		{
+	    			GeneralMessages.showErrorMessage(Messages.getString("PriTraceParser.wrongTraceType1")+traceType+Messages.getString("PriTraceParser.wrongTraceType2")); //$NON-NLS-1$ //$NON-NLS-2$
+	    			throw new Exception(Messages.getString("PriTraceParser.wrongTraceType1")+traceType+Messages.getString("PriTraceParser.wrongTraceType2")); //$NON-NLS-1$ //$NON-NLS-2$
+	    		}
+	    		else
+	    		{
+	    		    ByteArrayInputStream bais = new ByteArrayInputStream(traceArray);
+	    		    dis = new DataInputStream(bais);
+	    			parseNewPriFile(version,dis);
+	    			return;
+	    		}
+	    	}
+	    	else //handling 1.10 and newer versions
+	    	{
+	    	    parseVersion110Trace(traceArray,s);
+	    	    return;
+	    	}
+	    }
+	    System.out.println(Messages.getString("PriTraceParser.oldVersion")); //$NON-NLS-1$
+	    
+	    ByteArrayInputStream bais = new ByteArrayInputStream(traceArray);
+	    dis = new DataInputStream(bais);
+	    
+	    int listLength = this.findThreadListLength(dis, traceArray.length);
+	    if (listLength == -1)
+	    {
+	    	GeneralMessages.showErrorMessage(Messages.getString("PriTraceParser.invalidMemoryTraceFile1")); //$NON-NLS-1$
+	    	System.out.println(Messages.getString("PriTraceParser.invalidMemoryTraceFile")); //$NON-NLS-1$
+	    	throw new Exception(Messages.getString("PriTraceParser.invalidMemoryTraceFile")); //$NON-NLS-1$
+	    }
+
+	    priTrace = new PriTrace();
+	    
+	    for (int i=0;i<listLength;)
+	    {
+	    	int j = 0;
+	    	for (j=0;j<buffer.length;j++)
+	    	{
+	    		byte tmpByte = dis.readByte();
+	    		if (tmpByte != 0)
+	    		{
+	    			buffer[j] = (char)tmpByte;
+	    		}
+	    		else
+	    		{
+	    			dis.skipBytes(buffer.length-j-1);
+	    			break;
+	    		}
+	    	}
+	    	
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+	    	threadId = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff));
+	    			  
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+	    	sampleNum = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff));
+	    	String unparsedName = new String(buffer);
+	    	int index = 0;
+	    	while ((unparsedName.charAt(index++) != ':') && (index<buffer.length)){}
+	    	processName = unparsedName.substring(0,index-1);
+	    	threadName = unparsedName.substring(index+1, j);
+//	    	int tmp = threadName.length();
+//	    	memTrace.addFirstSynchTime(new Integer(threadId), new Integer(sampleNum));
+//	    	memSamples.add(new MemThread(new Integer(threadId), threadName, processName));
+	    	priTrace.addFirstSynchTime(new Integer(threadId), new Integer(sampleNum));
+	    	priSamples.add(new PriThread(new Integer(threadId), threadName, processName));
+	    	//buffer = null; int threadId, String threadName, String processName
+	    	i += buffer.length + 8;
+	    }
+//	    MemThread[] threads = new MemThread[memSamples.size()];
+//	    memSamples.copyInto((MemThread[]) threads);
+//	    memTrace.setThreads(threads);
+	    PriThread[] priThreads = new PriThread[priSamples.size()];
+	    priSamples.copyInto((PriThread[]) priThreads);
+	    priTrace.setThreads(priThreads);
+	    dis.skipBytes(8); //skipping "LIST_END" text
+	    for (int k=0;k<traceArray.length-listLength-8;)
+	    {
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+//	    	threadId = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff));
+	    	threadId = ((c & 0xff) << 8) | (d & 0xff);
+	    	processPriority = b;
+			threadPriority = a;
+	    	
+	    	
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+//	    	heapSize = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff));
+	    	
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+//	    	stackSize = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff));
+	    	
+	    	d = dis.readByte();
+	    	c = dis.readByte();
+	    	b = dis.readByte();
+	    	a = dis.readByte();
+	    	sampleNum = (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff));
+	    	for (Enumeration<PriThread> e = priSamples.elements();e.hasMoreElements();)
+	    	{
+	    		PriThread pt = e.nextElement();
+	    		if (pt.threadId.intValue() == threadId)
+	    		{
+	    			int priority = solveAbsolutPriority(processPriority, threadPriority);
+	    			priSample = new PriSample(pt, priority, sampleNum);
+	    			priTrace.addSample(priSample);
+	    			break;
+	    		}
+	    	}
+//	    	memTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleNum));
+	    	priTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleNum));
+	    	k += 16;
+	    }
+	    System.out.println(Messages.getString("PriTraceParser.done")); //$NON-NLS-1$
+	    
+	}
+	
+	private void parseVersion110Trace(byte[] traceArray, String version_data) throws Exception
+	{
+//		String version = version_data.substring(8,12);
+
+	    ByteArrayInputStream bais = new ByteArrayInputStream(traceArray);
+	    DataInputStream dis = new DataInputStream(bais);
+
+    	if (version_data.indexOf("PRI") > 0) //only pritrace  //$NON-NLS-1$
+    	{
+    	    this.parseV110PriFile(dis);
+    	}
+	}
+	
+	
+	private GenericSampledTrace getTrace()
+	{
+		//MemTrace trace = new MemTrace();
+		return (GenericSampledTrace) priTrace;
+	}
+	
+	private int solveAbsolutPriority(int processPriority, int threadPriority)
+	{
+		int tPriority = threadPriority*10 - 30;
+		int pPriority = processPriority*10;
+		switch (tPriority)
+		{
+			case 100:		//EPriorityAbsoluteVeryLow
+				return 100;
+			case 200:		//EPriorityAbsoluteLow
+				return 200;
+			case 300:		//EPriorityAbsoluteBackground
+				return 300;
+			case 400:		//EPriorityAbsoluteForeground
+				return 400;
+			case 500:		//EPriorityAbsoluteHigh
+				return 500;
+			case -30:		//EPriorityNull
+				return 0;
+			case 30:		//EPriorityRealTime
+				return 850;
+			case -20:		//EPriorityMuchLess
+				return pPriority - 20;
+			case -10:		//EPriorityLess
+				return pPriority - 10;
+			case 0:			//EPriorityNormal
+				return pPriority;
+			case 10:		//EPriorityMore
+				return pPriority + 10;
+			case 20:		//EPriorityMuchMore
+				return pPriority + 20;
+			default:
+				return 0;
+		}
+	}
+
+	private int findThreadListLength(DataInputStream dis, int traceLength) throws Exception
+	{
+		char[] buf = new char[8];
+		for (int i=0;i<traceLength/8;i++)
+		{
+			for (int j=0;j<8;j++)
+			{
+				buf[j%8] = (char)dis.readByte();
+//				int t = 0;
+			}
+			if (new String(buf).matches("LIST_END"))  //$NON-NLS-1$
+			{
+				dis.reset();
+				return i*8;
+			}
+
+		}
+		dis.reset();
+		return -1;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriorityPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority;
+
+import java.io.File;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Event;
+import org.osgi.framework.BundleContext;
+
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+import com.nokia.carbide.cpp.internal.pi.model.GenericThread;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IReportable;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class PriorityPlugin extends AbstractPiPlugin
+		implements ITrace, IClassReplacer, IReportable {
+
+	//The shared instance.
+	private static PriorityPlugin plugin;
+	
+	private static DecimalFormat format = new DecimalFormat(Messages.getString("PriorityPlugin.zeroFormat")); //$NON-NLS-1$
+
+	
+	private PriTrace trace = null;
+	private Hashtable<Integer,String> priStringById;
+
+	private static void setPlugin(PriorityPlugin newPlugin)
+	{
+		plugin = newPlugin;
+	}
+
+	/**
+	 * The constructor.
+	 */
+	public PriorityPlugin() {
+		setPlugin(this);
+	}
+
+	public Class getReplacedClass(String className)
+	{
+		if (   className.indexOf("com.nokia.carbide.cpp.pi.priority.PriSample") != -1 //$NON-NLS-1$
+			|| className.indexOf("com.nokia.carbide.pi.priority.PriSample") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.model.PriSample") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.priTracePlugin.PriSample") != -1) //$NON-NLS-1$
+		{
+			return PriSample.class;
+		}
+		else if (   className.indexOf("[Lcom.nokia.carbide.cpp.pi.priority.PriThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("[Lcom.nokia.carbide.pi.priority.PriThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("[Lfi.vtt.bappea.model.PriThread;") != -1 //$NON-NLS-1$
+				 || className.indexOf("[Lfi.vtt.bappea.priTracePlugin.PriThread") != -1) //$NON-NLS-1$
+		{
+			return PriThread[].class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.priority.PriThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.priority.PriThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.model.PriThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.priTracePlugin.PriThread") != -1) //$NON-NLS-1$
+		{
+			return PriThread.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.priority.PriTrace") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.priority.PriTrace") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.model.PriTrace") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.priTracePlugin.PriTrace") != -1) //$NON-NLS-1$
+		{
+			return PriTrace.class;
+		}
+		else return null;
+	}
+	
+	public Class getTraceClass() 
+	{
+		return PriTrace.class;
+	}
+
+	public void initialiseTrace(GenericTrace trace /*, ProfileVisualiser pv*/) 
+	{
+		if (trace == null)
+			return;
+		this.trace = (PriTrace)trace;
+
+	  	GenericThread[] threads =  this.trace.getThreads();
+		int threadCount = threads.length;
+
+		ArrayList<PriSample>[] priData = new ArrayList[threadCount];
+		Hashtable<Integer,ArrayList<PriSample>> priDataById = new Hashtable<Integer,ArrayList<PriSample>>();
+		priStringById = new Hashtable<Integer,String>();
+
+		//create priority data structure and inserts thread IDs into hashtable
+		for (int i = 0; i < threadCount; i++)
+		{
+			priData[i] = new ArrayList<PriSample>();
+			priDataById.put(threads[i].threadId, priData[i]);
+		}
+		
+		//insert priority data into hashtable based on thread id
+		for (Enumeration e = this.trace.getSamples(); e.hasMoreElements();)
+		{
+			PriSample tmp = (PriSample) e.nextElement();
+			priDataById.get(tmp.thread.threadId).add(tmp);
+		}
+		
+		for (Enumeration e = priDataById.keys(); e.hasMoreElements();)
+		{
+			Integer id = (Integer)e.nextElement();
+			priStringById.put(id, this.getPriorityString((ArrayList)priDataById.get(id)));
+		}
+		
+		priDataById.clear();
+		
+
+		Enumeration e = PluginInitialiser.getPluginInstances("com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+		if (e != null)
+		{
+			Event event = new Event();
+			event.data = priStringById;	
+
+			while (e.hasMoreElements())
+			{
+				IEventListener plugin = (IEventListener)e.nextElement();
+
+				plugin.receiveEvent("priority_init", event); //$NON-NLS-1$
+			}
+		}
+		
+	  	System.out.println(Messages.getString("PriorityPlugin.priorityTraceParsed")); //$NON-NLS-1$
+	}
+
+	public String getTraceName() {
+		return "Priority"; //$NON-NLS-1$
+	}
+
+	public int getTraceId() {
+		return 4;	//same id than MEM trace has because PRI trace is parsed from a MEM trace file
+	}
+
+	public ParsedTraceData parseTraceFile(File file /*, ProgressBar progressBar*/) throws Exception 
+	{
+		 try
+	        {
+	            PriTraceParser priParser;
+	            priParser = new PriTraceParser(file);
+	            return priParser.parse(file);
+	        } catch (Exception e)
+	        {
+	            e.printStackTrace();
+	            throw e;
+	        }
+	}
+	
+	private String getPriorityString(ArrayList priorityList)
+	{
+		if (priorityList == null || priorityList.size() == 0)
+		{
+			return Messages.getString("PriorityPlugin.unsolvedPriority"); //$NON-NLS-1$
+		}
+		else
+		{
+			String priorityString = ""; //$NON-NLS-1$
+			int priority = -1;
+			for (Iterator i = priorityList.iterator(); i.hasNext(); )
+			{
+				PriSample sample = (PriSample)i.next();
+				if (priority != sample.priority)
+				{
+					priority = sample.priority;
+					priorityString += Messages.getString("PriorityPlugin.priorityString1") + format.format(priority) + Messages.getString("PriorityPlugin.priorityString2") + sample.sampleNum/1000.0 + Messages.getString("PriorityPlugin.priorityString3"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				}
+			}
+			return priorityString;
+		}
+	}
+
+	public Hashtable<Integer,Object> getSummaryTable(double startTime, double endTime) 
+	{
+		PriThread[] pts = (PriThread[])trace.getThreads();
+		Hashtable<Integer,String> tmpTable = new Hashtable<Integer,String>();
+		for (int i = 0; i < pts.length; i++)
+		{
+			tmpTable.put(pts[i].threadId, pts[i].processName + "::" + pts[i].threadName + "_" + pts[i].threadId);   //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		if (this.priStringById != null)
+		{
+			Enumeration<Integer> e = priStringById.keys();
+			Hashtable<Integer,Object> summary = new Hashtable<Integer,Object>();
+			while (e.hasMoreElements())
+			{
+				Vector<Object> data = new Vector<Object>();
+				Integer key = e.nextElement();
+				data.add(tmpTable.get(key));
+				data.add(((String)priStringById.get(key)).trim());
+				summary.put(key, data);
+			}
+			return summary;
+		}
+		return null;
+	}
+
+	public String getGeneralInfo() 
+	{
+		return null;
+	}
+
+	public ArrayList<String> getColumnNames() 
+	{
+		ArrayList<String> names = new ArrayList<String>();
+		names.add(Messages.getString("PriorityPlugin.thread")); //$NON-NLS-1$
+		names.add(Messages.getString("PriorityPlugin.priority")); //$NON-NLS-1$
+		return names;
+	}
+	
+	public ArrayList<Boolean> getColumnSortTypes() 
+	{
+		ArrayList<Boolean> sortTypes = new ArrayList<Boolean>();
+		sortTypes.add(SORT_BY_NAME);
+		sortTypes.add(SORT_BY_NUMBER);
+		return sortTypes;
+	}
+
+	public String getActiveInfo(Object arg0, double startTime, double endTime) {
+		return null;
+	}
+
+	public MenuManager getReportGeneratorManager() {
+		return null;
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		setPlugin(null);
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static PriorityPlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractPiPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi.priority", path); //$NON-NLS-1$
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/PriorityReturnPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IReturnPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+
+
+public class PriorityReturnPlugin implements IReturnPlugin {
+	public AbstractPiPlugin getPlugin() {
+		return PriorityPlugin.getDefault();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority/src/com/nokia/carbide/cpp/pi/priority/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,31 @@
+PriTraceParser.cannotOpenMemoryTrace=Unable to open memory trace file
+PriTraceParser.memoryTraceFileLength=Memory trace file length 
+PriTraceParser.unsupportedMemoryTrace1=Memory trace format version 
+PriTraceParser.unsupportedMemoryTrace2=\ is not supported by this version of analyser
+PriTraceParser.readVersion=Read version 
+PriTraceParser.typeMissing=Parse error, type after sample missing
+PriTraceParser.missingSample=Missing sample \#
+PriTraceParser.wrongLength=Parse error, wrong length 
+PriTraceParser.readNextSample=Read next sample \#
+PriTraceParser.wrongMode=Parse error, wrong mode 
+PriTraceParser.doneReading=Finished reading
+PriTraceParser.done=Done parsing
+PriTraceParser.zeroLength=Data element length is 0
+PriTraceParser.TUINTLengthException1=Parse error, TUint length other than 32 bits (it is 
+PriTraceParser.TUINTLengthException2=\ )
+PriTraceParser.foundVersion1=Found version 
+PriTraceParser.foundVersion2=\ 
+PriTraceParser.foundVersion3=\ trace file 
+PriTraceParser.wrongTraceType1=Wrong trace type 
+PriTraceParser.wrongTraceType2=\ as memory trace file
+PriorityPlugin.unsolvedPriority=Unsolved
+PriorityPlugin.priorityString1=\ 
+PriorityPlugin.priorityString2=(
+PriorityPlugin.priorityString3=s)
+PriTraceParser.oldVersion=Parsing old (v.0.85 or older) type memory trace file
+PriTraceParser.invalidMemoryTraceFile1=Not valid memory trace file, possible profiler Buffer Overflow during trace?
+PriTraceParser.invalidMemoryTraceFile=Not valid memory trace file
+PriorityPlugin.zeroFormat=000
+PriorityPlugin.priorityTraceParsed=priority trace parsed
+PriorityPlugin.thread=Thread
+PriorityPlugin.priority=Priority
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Thread Priorities 2
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.priority2;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.priority2.Priority2Plugin
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ com.nokia.carbide.cpp.pi,
+ com.nokia.carbide.cpp.pi.util
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.pi.priority2;x-friends:="com.nokia.carbide.cpp.pi.priority2.tests"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .,\
+               html/,\
+               *.xml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+   <extension
+         point="com.nokia.carbide.cpp.pi.piPluginData">
+      <plugin
+            pluginClass="com.nokia.carbide.cpp.pi.priority2.Priority2ReturnPlugin"/>
+   </extension>
+
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority2;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.priority2.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/NewPriSample.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority2;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSample;
+
+
+public class NewPriSample extends GenericSample
+{
+	private static final long serialVersionUID = -4474787388603984159L;
+	
+	public NewPriThread thread;
+	public int priority;
+	public int sampleNum;
+	
+	public NewPriSample(NewPriThread thread, int priority, int sampleNum)
+	{
+		this.thread = thread;
+		this.priority = priority;
+		this.sampleNum = sampleNum;
+		this.sampleSynchTime = sampleNum;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/NewPriThread.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority2;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericThread;
+
+
+public class NewPriThread extends GenericThread
+{
+	private static final long serialVersionUID = 8411844143949264073L;
+	
+	public NewPriThread(Integer threadId, String threadName, String processName)
+	{
+		this.threadId = threadId;
+		this.threadName = threadName;
+		this.processName = processName;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/NewPriTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority2;
+
+import java.util.Hashtable;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.model.GenericThread;
+import com.nokia.carbide.cpp.internal.pi.model.TraceWithThreads;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+
+
+public class NewPriTrace extends GenericSampledTrace implements TraceWithThreads
+{
+	private static final long serialVersionUID = 7929002387070527775L;
+	
+	private Hashtable firstSynchTimes;
+	private Hashtable lastSynchTimes;
+	private int samplingTime;
+	private NewPriThread[] threads;
+	
+	public NewPriTrace()
+	{
+		firstSynchTimes = new Hashtable();
+		lastSynchTimes = new Hashtable();
+	}
+	
+	public void addSample(NewPriSample sample)
+	{
+		this.samples.add(sample);
+	}
+	
+	public NewPriSample getPriSample(int number)
+	{
+		return (NewPriSample)this.samples.elementAt(number);
+	}
+	  
+	public GenericTraceGraph getTraceGraph()
+	{
+	  	return null;
+	}
+	  
+	public GenericThread[] getThreads()
+	{
+	  	return threads;
+	}
+	
+	public void setThreads(NewPriThread[] threads)
+	{
+		this.threads = threads;
+	}
+	  
+//	public long getLastSynchTimeForThread(GenericThread t)
+//	{
+//	  	return ((Integer) lastSynchTimes.get(t.threadId)).intValue();
+//	}
+//	  
+//	public long getFirstSynchTimeForThread(GenericThread t)
+//	{
+//		return ((Integer) firstSynchTimes.get(t.threadId)).intValue();
+//	}
+	
+	public void addFirstSynchTime(Integer id, Integer firstSynchTime)
+	{
+		firstSynchTimes.put(id, firstSynchTime);
+	}
+	
+	public void addLastSynchTime(Integer id, Integer lastSynchTime)
+	{
+		lastSynchTimes.put(id, lastSynchTime);
+	}
+	
+	public void setSamplingTime(int time)
+	{
+		this.samplingTime = time;
+	}
+	
+	public int getSamplingTime()
+	{
+		return samplingTime;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/NewPriTraceParser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority2;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.Parser;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+public class NewPriTraceParser extends Parser
+{
+    private boolean debug = false;
+
+    private String version;
+    
+	private Vector<NewPriThread> priSamples = new Vector<NewPriThread>();
+	private String threadName;
+	private String processName;
+	private int threadId;
+	private int sampleNum;
+	private int threadPriority;
+	private NewPriSample priSample;
+	private NewPriTrace priTrace;
+	private int readCount = 0;
+	
+	public NewPriTraceParser(File file) throws Exception
+	{
+	}
+	
+	public ParsedTraceData parse(File f) throws Exception 
+	{
+		if (!f.exists() || f.isDirectory())
+	    {
+	      throw new Exception(Messages.getString("NewPriTraceParser.cannotOpenMemoryTrace")); //$NON-NLS-1$
+	    }
+		if (debug) System.out.println(Messages.getString("NewPriTraceParser.memoryTraceFileLength")+f.length()); //$NON-NLS-1$
+
+	    parsePriTrace(f);
+		
+		ParsedTraceData ptd = new ParsedTraceData();
+		ptd.traceData = this.getTrace();
+		return ptd;
+	}
+	
+	private void parseV155PriFile(DataInputStream dis) throws Exception
+	{
+		// read the version again
+		byte[] version = readElementWithLength(dis);
+		System.out.println(Messages.getString("NewPriTraceParser.readVersion")+new String(version)); //$NON-NLS-1$
+		this.version = new String(version);
+		
+		this.readV155PriSample(dis);
+	}
+	
+	public String getProfilerVersion()
+	{
+	    return version;
+	}
+
+	private void readV155PriSample(DataInputStream dis) throws Exception
+	{
+	    Vector<long[]> rawV155PriSamples = new Vector<long[]>();
+	    Vector<long[]> lastSampleRaw     = new Vector<long[]>();
+
+		//memTrace = new MemTrace();
+	    priTrace = new NewPriTrace();
+	   		
+		// first there should be 4 bytes of sample time
+		long sample = this.readTUintWithLength(dis);
+				
+		// then read if there is thread name data
+		int length = dis.readUnsignedByte();readCount++;
+		if(length != 1) throw new Exception(Messages.getString("NewPriTraceParser.missingType")); //$NON-NLS-1$
+		
+		int mode = dis.readUnsignedByte();readCount++;
+		System.out.println(Messages.getString("NewPriTraceParser.firstMode")+Integer.toHexString(mode)); //$NON-NLS-1$
+		try
+		{
+			// read the first length
+			length = dis.readUnsignedByte();readCount++;
+
+			Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
+			
+			while(true)
+			{
+				//System.out.println("ReadCount:"+this.readCount);
+				if(length == 0)
+				{
+					// end of sample
+					// read new length
+					
+					// first there should be 4 bytes of sample time
+					sample = this.readTUintWithLength(dis);
+					//System.out.println("Sample number:"+sample);
+					
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("New length "+length);				
+					//break;
+					
+					if(length == 4)
+					{
+						// there was only the sample header here
+						System.out.println(Messages.getString("NewPriTraceParser.missingSampleNum")+sample); //$NON-NLS-1$
+						mode = 0x00;
+					}
+					else if(length != 1)
+					{
+						throw new Exception(Messages.getString("NewPriTraceParser.wrongLength")+length); //$NON-NLS-1$
+					}
+					else
+					{
+						lastSampleRaw.clear();
+					}
+				}
+				
+				if(length == 1)
+				{
+					mode = dis.readUnsignedByte();readCount++;
+					//System.out.println("New Mode "+mode+" new length "+length);
+
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("Next length "+length);
+				}
+				
+				if(mode == 0xbb)
+				{
+					// reading thread names
+					String rawName = readThreadName(dis,length);
+					long threadId = readTUint(dis);
+					//System.out.println("Raw name "+rawName);
+				   	int index = rawName.indexOf(':');
+				   	if(index != -1)
+				   	{
+				   		processName = rawName.substring(0,index);
+				   		threadName = rawName.substring(rawName.lastIndexOf(':')+1,rawName.length());
+				   		//System.out.println("Thread: "+threadName+" process: "+processName+" id: "+threadId);
+				   	}
+				   	else
+				   	{
+				   		processName = rawName;
+				   		threadName = rawName;
+				   	}
+								    	
+				   	priTrace.addFirstSynchTime(new Integer((int)threadId), new Integer(sampleNum));
+				   	priSamples.add(new NewPriThread(new Integer((int)threadId), threadName, processName));
+
+				   	// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("Next length "+length);
+				}
+				else if(mode == 0xee)
+				{
+					// reading data
+					long[] elements = this.readDataElements155Pri(dis,length,sample);
+					
+					rawV155PriSamples.add(elements);
+					lastSampleRaw.add(elements);
+					
+					// read the next length
+					length = dis.readUnsignedByte();readCount++;
+					//System.out.println("Next length "+length);
+				}
+				else if(mode == 0x00)
+				{
+					// read the length, it is already known
+					sample = readTUint(dis);
+					System.out.println(Messages.getString("NewPriTraceParser.readNextSampleNum")+sample); //$NON-NLS-1$
+					length = dis.readUnsignedByte();readCount++;;
+				}
+				else
+				{
+					throw new Exception(Messages.getString("NewPriTraceParser.wrongMode")+mode); //$NON-NLS-1$
+				}
+			}
+		}
+		catch (EOFException e)
+		{
+			System.out.println(Messages.getString("NewPriTraceParser.finishedReading")); //$NON-NLS-1$
+			this.addRawV155PriSamples(rawV155PriSamples);
+		}
+	}
+
+	private void addRawV155PriSamples(Vector<long[]> rawV110PriSamples)
+	{
+		NewPriThread[] priThreads = new NewPriThread[priSamples.size()];
+	    priSamples.copyInto((NewPriThread[]) priThreads);
+	    priTrace.setThreads(priThreads);
+	    
+	    Enumeration<long[]> rawEnum = rawV110PriSamples.elements();
+	    while(rawEnum.hasMoreElements())
+	    {
+	    	long[] element = rawEnum.nextElement();
+	    	threadId = (int)element[0];
+	    	threadPriority = (int)element[1];
+	    	// for the null thread, converts 8bit unsigned to signed
+	    	if (threadPriority > 32768)
+	    	    threadPriority = threadPriority - 65536;
+
+	    	sampleNum = (int)element[2]; 
+
+	    	for (Enumeration<NewPriThread> e = priSamples.elements();e.hasMoreElements();)
+	    	{
+	    		NewPriThread pt = e.nextElement();
+	    		if (pt.threadId == threadId)
+	    		{
+	    			//int priority = solveAbsolutPriority(processPriority, threadPriority);
+	    			priSample = new NewPriSample(pt, threadPriority, sampleNum);
+	    			priTrace.addSample(priSample);
+	    			break;
+	    		}
+	    	}
+	    	priTrace.addLastSynchTime(new Integer(threadId), new Integer(sampleNum));
+	    }
+	    System.out.println(Messages.getString("NewPriTraceParser.doneParsing")); //$NON-NLS-1$
+	}
+
+	private long[] readDataElements155Pri(DataInputStream dis,int length,long sampleNum) throws Exception
+	{
+		if(length != 0)
+		{
+			long[] elements = new long[3];
+			elements[0] = this.readTUint(dis);  //thread ID
+			elements[1] = this.readShort(dis);  //Priority
+			elements[2] = sampleNum;  //sample number
+
+			return elements;
+		}
+		else 
+		{
+			System.out.println(Messages.getString("NewPriTraceParser.lengthIs0")); //$NON-NLS-1$
+			return null;
+		}
+	}
+	
+	
+	private String readThreadName(DataInputStream dis,int length) throws Exception
+	{
+		if (length != 0)
+		{
+			length-=4;
+			//System.out.println("Thread name length "+length);
+			byte[] element = new byte[length];
+			dis.read(element,0,length);
+			readCount+=length;
+			return new String(element);
+		}
+		else return null;
+	}
+	
+	private byte[] readElementWithLength(DataInputStream dis) throws Exception
+	{
+		byte length = dis.readByte(); readCount++;
+		if (length != 0)
+		{
+			//System.out.println("Element length "+length);
+			byte[] element = new byte[length];
+			dis.read(element,0,length);
+			readCount += length;
+			return element;
+		}
+		else return null;
+	}
+	
+	private long readShort(DataInputStream dis) throws Exception
+	{
+		long result = dis.readUnsignedByte();
+		readCount++;
+		result += dis.readUnsignedByte() << 8;
+		readCount++;
+		return result;
+	}
+	
+	private long readTUint(DataInputStream dis) throws Exception
+	{
+		long result = dis.readUnsignedByte();
+		readCount++;
+		result += dis.readUnsignedByte() << 8;
+		readCount++;
+		result += dis.readUnsignedByte() << 16;
+		readCount++;
+		result += dis.readUnsignedByte() << 24;
+		readCount++;
+		return result;
+	}
+
+	private long readTUintWithLength(DataInputStream dis) throws Exception
+	{
+		byte length = (byte)dis.readUnsignedByte();
+		readCount++;
+		//System.out.println("Pituus: "+length);
+		if (length != 4) 
+		{
+			throw new Exception(Messages.getString("NewPriTraceParser.TUINTLengthException1")+length+Messages.getString("NewPriTraceParser.TUINTLengthException2")); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		long result = dis.readUnsignedByte();
+		readCount++;
+		result += dis.readUnsignedByte() << 8;
+		readCount++;
+		result += dis.readUnsignedByte() << 16;
+		readCount++;
+		result += dis.readUnsignedByte() << 24;
+		readCount++;
+		
+		//System.out.println("Read length ok");
+		return result;
+	}
+
+	private void parsePriTrace(File file) throws Exception
+	{
+		DataInputStream dis = new DataInputStream(new FileInputStream(file));		
+	    byte[] traceArray = new byte[(int)file.length()];
+	    dis.readFully(traceArray);
+	    
+	    // test the mem trace version
+	    if (traceArray.length > 257)
+	    {
+	    	String s = new String(traceArray,1,traceArray[0]);
+
+	    	if (!s.startsWith("Bappea_V1.56")) //up to 1.0 version //$NON-NLS-1$
+	    	{
+	    		String version = s.substring(8,12);
+	    		String traceType = s.substring(13,s.length());
+	    		System.out.println(Messages.getString("NewPriTraceParser.foundVersion1")+version+Messages.getString("NewPriTraceParser.foundVersion2")+traceType+Messages.getString("NewPriTraceParser.foundVersion3")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+    			GeneralMessages.showErrorMessage(Messages.getString("NewPriTraceParser.wrongTraceType1")+traceType+Messages.getString("NewPriTraceParser.wrongTraceType2")); //$NON-NLS-1$ //$NON-NLS-2$
+    			throw new Exception(Messages.getString("NewPriTraceParser.wrongTraceType1")+traceType+Messages.getString("NewPriTraceParser.wrongTraceType2")); //$NON-NLS-1$ //$NON-NLS-2$
+	    	}
+	    	else //handling 1.10 and newer versions
+	    	{
+	    	    parseVersion155Trace(traceArray,s);
+	    	    return;
+	    	}
+	    }
+	    else 
+	    {
+			GeneralMessages.showErrorMessage(Messages.getString("NewPriTraceParser.wrongVersionforPRI")); //$NON-NLS-1$
+			throw new Exception(Messages.getString("NewPriTraceParser.wrongTypeforPRI")); //$NON-NLS-1$
+	    }	    
+	}
+	
+	private void parseVersion155Trace(byte[] traceArray, String version_data) throws Exception
+	{
+	    ByteArrayInputStream bais = new ByteArrayInputStream(traceArray);
+	    DataInputStream dis = new DataInputStream(bais);
+
+	    if (version_data.indexOf("PRI")>0) //only pritrace //$NON-NLS-1$
+	    {
+    	    	this.parseV155PriFile(dis);
+	    }
+	}
+
+	private GenericSampledTrace getTrace()
+	{
+		//MemTrace trace = new MemTrace();
+		return (GenericSampledTrace) priTrace;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/Priority2Plugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority2;
+
+import java.io.File;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Event;
+import org.osgi.framework.BundleContext;
+
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+import com.nokia.carbide.cpp.internal.pi.model.GenericThread;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IReportable;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Priority2Plugin extends AbstractPiPlugin
+		implements ITrace, IClassReplacer, IReportable {
+
+	// The shared instance
+	private static Priority2Plugin plugin;
+	
+	private static DecimalFormat format = new DecimalFormat(Messages.getString("Priority2Plugin.zeroFormat")); //$NON-NLS-1$
+	
+	private NewPriTrace trace = null;
+	private Hashtable<Integer,String> priStringById;
+
+	private static void setPlugin(Priority2Plugin newPlugin)
+	{
+		plugin = newPlugin;
+	}
+
+	/**
+	 * The constructor
+	 */
+	public Priority2Plugin() {
+		setPlugin(this);
+	}
+
+	public Class getReplacedClass(String className)
+	{
+		if (   className.indexOf("com.nokia.carbide.cpp.pi.priority2.NewPriSample") != -1 //$NON-NLS-1$
+			|| className.indexOf("com.nokia.carbide.pi.priority2.NewPriSample") != -1 //$NON-NLS-1$
+			|| className.indexOf("fi.vtt.bappea.newPriTracePlugin.NewPriSample") != -1) //$NON-NLS-1$
+		{
+			return NewPriSample.class;
+		}
+		else if (   className.indexOf("[Lcom.nokia.carbide.cpp.pi.priority2.NewPriThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("[Lcom.nokia.carbide.pi.priority2.NewPriThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("[Lfi.vtt.bappea.newPriTracePlugin.NewPriThread") != -1) //$NON-NLS-1$
+		{
+			return NewPriThread[].class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.priority2.NewPriThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.priority2.NewPriThread") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.newPriTracePlugin.NewPriThread") != -1) //$NON-NLS-1$
+		{
+			return NewPriThread.class;
+		}
+		else if (   className.indexOf("com.nokia.carbide.cpp.pi.priority2.NewPriTrace") != -1 //$NON-NLS-1$
+				 || className.indexOf("com.nokia.carbide.pi.priority2.NewPriTrace") != -1 //$NON-NLS-1$
+				 || className.indexOf("fi.vtt.bappea.newPriTracePlugin.NewPriTrace") != -1) //$NON-NLS-1$
+		{
+			return NewPriTrace.class;
+		}
+		else return null;
+	}
+	
+	public Class getTraceClass() 
+	{
+		return NewPriTrace.class;
+	}
+
+	public void initialiseTrace(GenericTrace trace /*, ProfileVisualiser pv*/) 
+	{
+		if (trace == null)
+			return;
+		this.trace = (NewPriTrace)trace;
+
+	  	GenericThread[] threads =  this.trace.getThreads();
+		int threadCount = threads.length;
+
+		ArrayList<NewPriSample>[] priData = new ArrayList[threadCount];
+		Hashtable<Integer,ArrayList<NewPriSample>> priDataById = new Hashtable<Integer,ArrayList<NewPriSample>>();
+		priStringById = new Hashtable<Integer,String>();
+
+		//create priority data structure and inserts thread IDs into hashtable
+		for (int i = 0; i < threadCount; i++)
+		{
+			priData[i] = new ArrayList<NewPriSample>();
+			priDataById.put(threads[i].threadId, priData[i]);
+		}
+		
+		//insert priority data into hashtable based on thread id
+		for (Enumeration e = this.trace.getSamples(); e.hasMoreElements();)
+		{
+			NewPriSample tmp = (NewPriSample) e.nextElement();
+			priDataById.get(tmp.thread.threadId).add(tmp);
+		}
+		
+		for (Enumeration e = priDataById.keys(); e.hasMoreElements();)
+		{
+			Integer id = (Integer)e.nextElement();
+			priStringById.put(id, this.getPriorityString((ArrayList)priDataById.get(id)));
+		}
+		
+		priDataById.clear();
+
+		Enumeration e = PluginInitialiser.getPluginInstances("com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+		if (e != null)
+		{
+			Event event = new Event();
+			event.data = priStringById;	
+
+			while (e.hasMoreElements())
+			{
+				IEventListener plugin = (IEventListener)e.nextElement();
+
+				plugin.receiveEvent("priority_init", event); //$NON-NLS-1$
+			}
+		}
+		
+	  	System.out.println(Messages.getString("Priority2Plugin.priorityTraceParsed")); //$NON-NLS-1$
+	}
+
+	public String getTraceName() {
+		return "Priority"; //$NON-NLS-1$
+	}
+
+	public int getTraceId() {
+		return 5;
+	}
+
+
+	public ParsedTraceData parseTraceFile(File file /*, ProgressBar progressBar*/) throws Exception 
+	{
+		 try
+	        {
+	            NewPriTraceParser priParser;
+	            priParser = new NewPriTraceParser(file);
+	            return priParser.parse(file);
+	        } catch (Exception e)
+	        {
+	            e.printStackTrace();
+	            throw e;
+	        }
+	}
+	
+	private String getPriorityString(ArrayList priorityList)
+	{
+		if (priorityList == null || priorityList.size() == 0)
+		{
+			return Messages.getString("Priority2Plugin.unsolvedPriority"); //$NON-NLS-1$
+		}
+		else
+		{
+			String priorityString = ""; //$NON-NLS-1$
+			int priority = -1;
+			for (Iterator i = priorityList.iterator(); i.hasNext(); )
+			{
+				NewPriSample sample = (NewPriSample)i.next();
+				if (priority != sample.priority)
+				{
+					priority = sample.priority;
+					priorityString += Messages.getString("Priority2Plugin.priorityString1") + format.format(priority) + Messages.getString("Priority2Plugin.priorityString2") + sample.sampleNum/1000.0 + Messages.getString("Priority2Plugin.priorityString3"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				}
+			}
+			return priorityString;
+		}
+	}
+
+	public Hashtable<Integer,Object> getSummaryTable(double startTime, double endTime) 
+	{
+		NewPriThread[] pts = (NewPriThread[])trace.getThreads();
+		Hashtable<Integer,String> tmpTable = new Hashtable<Integer,String>();
+		for (int i = 0; i < pts.length; i++)
+		{
+			tmpTable.put(pts[i].threadId, pts[i].processName + "::" + pts[i].threadName + "_" + pts[i].threadId);   //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		if (this.priStringById != null)
+		{
+			Enumeration<Integer> e = priStringById.keys();
+			Hashtable<Integer,Object> summary = new Hashtable<Integer,Object>();
+			while (e.hasMoreElements())
+			{
+				Vector<Object> data = new Vector<Object>();
+				Integer key = e.nextElement();
+				data.add(tmpTable.get(key));
+				data.add(((String)priStringById.get(key)).trim());
+				summary.put(key, data);
+			}
+			return summary;
+		}
+		return null;
+	}
+
+	public String getGeneralInfo() 
+	{
+		return null;
+	}
+
+	public ArrayList<String> getColumnNames() 
+	{
+		ArrayList<String> names = new ArrayList<String>();
+		names.add(Messages.getString("Priority2Plugin.thread")); //$NON-NLS-1$
+		names.add(Messages.getString("Priority2Plugin.priority")); //$NON-NLS-1$
+		return names;
+	}
+	
+	public ArrayList<Boolean> getColumnSortTypes() 
+	{
+		ArrayList<Boolean> sortTypes = new ArrayList<Boolean>();
+		sortTypes.add(SORT_BY_NAME);
+		sortTypes.add(SORT_BY_NUMBER);
+		return sortTypes;
+	}
+
+	public String getActiveInfo(Object arg0, double startTime, double endTime) {
+		return null;
+	}
+
+	public MenuManager getReportGeneratorManager() {
+		return null;
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		setPlugin(null);
+	}
+
+	/**
+	 * Returns the shared instance
+	 */
+	public static Priority2Plugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractPiPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi.priority2", path); //$NON-NLS-1$
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/Priority2ReturnPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.priority2;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IReturnPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+
+
+public class Priority2ReturnPlugin implements IReturnPlugin {
+	public AbstractPiPlugin getPlugin() {
+		return Priority2Plugin.getDefault();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/src/com/nokia/carbide/cpp/pi/priority2/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+NewPriTraceParser.cannotOpenMemoryTrace=Unable to open memory trace file
+NewPriTraceParser.memoryTraceFileLength=Memory trace file length 
+NewPriTraceParser.TUINTLengthException1=Parse error, TUint length other than 32 bits (it is 
+NewPriTraceParser.TUINTLengthException2=\ )
+NewPriTraceParser.foundVersion1=Found version 
+NewPriTraceParser.foundVersion2=\ 
+NewPriTraceParser.foundVersion3=\ trace file 
+NewPriTraceParser.wrongTraceType1=Wrong trace type 
+NewPriTraceParser.wrongTraceType2=\ as memory trace file
+NewPriTraceParser.readVersion=Read version 
+NewPriTraceParser.missingType=Parse error, type after sample missing
+NewPriTraceParser.firstMode=First mode 
+NewPriTraceParser.missingSampleNum=Missing sample \#
+NewPriTraceParser.wrongLength=Parse error, wrong length 
+NewPriTraceParser.readNextSampleNum=Read next sample \#
+NewPriTraceParser.wrongMode=Parse error, wrong mode 
+NewPriTraceParser.finishedReading=Finished reading
+NewPriTraceParser.doneParsing=Done parsing
+NewPriTraceParser.lengthIs0=Data element length is 0
+NewPriTraceParser.wrongVersionforPRI=Wrong trace version for PRI file
+NewPriTraceParser.wrongTypeforPRI=Wrong trace type for PRI file
+Priority2Plugin.unsolvedPriority=Unsolved
+Priority2Plugin.priorityString1=\ 
+Priority2Plugin.priorityString2=(
+Priority2Plugin.priorityString3=s)
+Priority2Plugin.zeroFormat=000
+Priority2Plugin.priorityTraceParsed=priority 2 trace parsed
+Priority2Plugin.thread=Thread
+Priority2Plugin.priority=Priority
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.priority2/toc.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<toc label="Sample Table of Contents">
+	<topic label="Main Topic"  href="html/maintopic.html"> 
+		<topic label="Sub Topic" href="html/subtopic.html"/> 
+	</topic>
+	<topic label="Main Topic 2"/>
+</toc>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/.settings/org.eclipse.core.resources.prefs	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,3 @@
+#Mon Feb 09 14:16:31 CST 2009
+eclipse.preferences.version=1
+encoding//src/com/nokia/carbide/cpp/internal/pi/ui/messages.properties=8859_1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator UI
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.ui;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.internal.pi.ui
+Bundle-Activator: com.nokia.carbide.cpp.internal.pi.ui.PIUiPlugin
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+bin.includes = META-INF/,\
+               plugin.xml,\
+               .,\
+               icons/
+jars.compile.order = .
+source.. = src/
+output.. = bin/
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/Carbide_c_icon_16x16.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/Carbide_c_icon_24x24.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/Carbide_c_icon_32x32.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/Carbide_c_icon_48x48.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/about.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/about_cpp.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/icons/pi_ovr.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+   <extension
+         point="org.eclipse.ui.ide.projectNatureImages">
+   </extension>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/src/com/nokia/carbide/cpp/internal/pi/ui/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.ui;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.ui.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/src/com/nokia/carbide/cpp/internal/pi/ui/PIUiPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.ui;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class PIUiPlugin extends AbstractUIPlugin {
+
+	public static final String PLUGIN_ID = "com.nokia.carbide.cpp.pi.ui"; //$NON-NLS-1$
+
+	//The shared instance.
+	private static PIUiPlugin plugin;
+
+	private static void setPlugin(PIUiPlugin newPlugin)
+	{
+		plugin = newPlugin;
+	}
+
+	/**
+	 * The constructor.
+	 */
+	public PIUiPlugin() {
+		setPlugin(this);
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		setPlugin(null);
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static PIUiPlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractUIPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi.ui", path); //$NON-NLS-1$
+	}
+
+	/**
+	 * Returns the standard display to be used. The method first checks, if
+	 * the thread calling this method has an associated display. If so, this
+	 * display is returned. Otherwise the method returns the default display.
+	 */
+	public static Display getStandardDisplay() {
+		Display display= Display.getCurrent();
+		if (display == null) {
+			display= Display.getDefault();
+		}
+		return display;		
+	}
+
+	public void log(Throwable e) {
+		log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, Messages.getString("PIUiPlugin.error"), e)); //$NON-NLS-1$
+	}
+
+	public void log(IStatus status) {
+		getLog().log(status);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.ui/src/com/nokia/carbide/cpp/internal/pi/ui/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,1 @@
+PIUiPlugin.error=Error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.update/site.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<site>
+   <feature url="features/com.nokia.carbide.cpp.pi_1.0.0.jar" id="com.nokia.carbide.cpp.pi" version="1.0.0"/>
+</site>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/.settings/org.eclipse.core.resources.prefs	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,4 @@
+#Mon Feb 09 13:45:20 CST 2009
+eclipse.preferences.version=1
+encoding//schema/PIConfig.xsd=UTF8
+encoding//src/com/nokia/carbide/cpp/pi/util/messages.properties=8859_1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,31 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Utilities
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.util;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.swt,
+ org.eclipse.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.core.resources,
+ org.eclipse.core.runtime,
+ org.eclipse.cdt.core,
+ org.eclipse.cdt.ui,
+ org.eclipse.jface.text,
+ org.eclipse.ui.workbench.texteditor,
+ com.nokia.carbide.cpp,
+ com.nokia.carbide.cdt.builder,
+ com.nokia.carbide.cpp.support,
+ com.nokia.carbide.cpp.ui,
+ com.nokia.cpp.utils.core,
+ org.eclipse.emf.common;bundle-version="2.4.0",
+ org.eclipse.emf.ecore;bundle-version="2.4.0",
+ org.eclipse.emf.ecore.xmi;bundle-version="2.4.0",
+ com.nokia.carbide.cpp.sdk.core;bundle-version="2.0.0"
+Export-Package: com.nokia.carbide.cpp.internal.pi.util.config,
+ com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig,
+ com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.util,
+ com.nokia.carbide.cpp.pi.util
+Bundle-Activator: com.nokia.carbide.cpp.pi.util.PIUtilPlugin
+Bundle-ActivationPolicy: lazy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,6 @@
+bin.includes = META-INF/,\
+               plugin.xml,\
+               .
+jars.compile.order = .
+source.. = src/
+output.. = bin/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/plugin.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2 @@
+pluginName = Profiles Model
+providerName = www.example.org
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/schema/PIConfig.ecore	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ecore:EPackage xmi:version="2.0"
+    xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="PIConfig"
+    nsURI="platform:/resource/com.nokia.carbide.cpp.pi.util/schema/PIConfig.xsd" nsPrefix="PIConfig">
+  <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+    <details key="qualified" value="false"/>
+  </eAnnotations>
+  <eClassifiers xsi:type="ecore:EClass" name="ButtonEventProfileListType">
+    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+      <details key="name" value="buttonEventProfileList_._type"/>
+      <details key="kind" value="elementOnly"/>
+    </eAnnotations>
+    <eStructuralFeatures xsi:type="ecore:EReference" name="buttonEventProfile" upperBound="-1"
+        eType="#//ButtonEventProfileType" containment="true" resolveProxies="false">
+      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+        <details key="kind" value="element"/>
+        <details key="name" value="buttonEventProfile"/>
+        <details key="namespace" value="##targetNamespace"/>
+      </eAnnotations>
+    </eStructuralFeatures>
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="buttonEventProfileVersion"
+        eType="ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//Decimal">
+      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+        <details key="kind" value="attribute"/>
+        <details key="name" value="buttonEventProfileVersion"/>
+        <details key="namespace" value="##targetNamespace"/>
+      </eAnnotations>
+    </eStructuralFeatures>
+  </eClassifiers>
+  <eClassifiers xsi:type="ecore:EClass" name="ButtonEventProfileType">
+    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+      <details key="name" value="buttonEventProfile_._type"/>
+      <details key="kind" value="elementOnly"/>
+    </eAnnotations>
+    <eStructuralFeatures xsi:type="ecore:EReference" name="mapping" lowerBound="1"
+        upperBound="-1" eType="#//MappingType" containment="true" resolveProxies="false">
+      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+        <details key="kind" value="element"/>
+        <details key="name" value="mapping"/>
+        <details key="namespace" value="##targetNamespace"/>
+      </eAnnotations>
+    </eStructuralFeatures>
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="profileId" eType="ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//String">
+      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+        <details key="kind" value="attribute"/>
+        <details key="name" value="profileId"/>
+        <details key="namespace" value="##targetNamespace"/>
+      </eAnnotations>
+    </eStructuralFeatures>
+  </eClassifiers>
+  <eClassifiers xsi:type="ecore:EClass" name="DocumentRoot">
+    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+      <details key="name" value=""/>
+      <details key="kind" value="mixed"/>
+    </eAnnotations>
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="mixed" unique="false" upperBound="-1"
+        eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFeatureMapEntry">
+      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+        <details key="kind" value="elementWildcard"/>
+        <details key="name" value=":mixed"/>
+      </eAnnotations>
+    </eStructuralFeatures>
+    <eStructuralFeatures xsi:type="ecore:EReference" name="xMLNSPrefixMap" upperBound="-1"
+        eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EStringToStringMapEntry"
+        transient="true" containment="true" resolveProxies="false">
+      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+        <details key="kind" value="attribute"/>
+        <details key="name" value="xmlns:prefix"/>
+      </eAnnotations>
+    </eStructuralFeatures>
+    <eStructuralFeatures xsi:type="ecore:EReference" name="xSISchemaLocation" upperBound="-1"
+        eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EStringToStringMapEntry"
+        transient="true" containment="true" resolveProxies="false">
+      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+        <details key="kind" value="attribute"/>
+        <details key="name" value="xsi:schemaLocation"/>
+      </eAnnotations>
+    </eStructuralFeatures>
+    <eStructuralFeatures xsi:type="ecore:EReference" name="buttonEventProfileList"
+        upperBound="-2" eType="#//ButtonEventProfileListType" volatile="true" transient="true"
+        derived="true" containment="true" resolveProxies="false">
+      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+        <details key="kind" value="element"/>
+        <details key="name" value="buttonEventProfileList"/>
+        <details key="namespace" value="##targetNamespace"/>
+      </eAnnotations>
+    </eStructuralFeatures>
+  </eClassifiers>
+  <eClassifiers xsi:type="ecore:EClass" name="MappingType">
+    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+      <details key="name" value="mapping_._type"/>
+      <details key="kind" value="empty"/>
+    </eAnnotations>
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="enumString" eType="ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//String">
+      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+        <details key="kind" value="attribute"/>
+        <details key="name" value="enumString"/>
+        <details key="namespace" value="##targetNamespace"/>
+      </eAnnotations>
+    </eStructuralFeatures>
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="keyCode" eType="ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//UnsignedInt"
+        unsettable="true">
+      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+        <details key="kind" value="attribute"/>
+        <details key="name" value="keyCode"/>
+        <details key="namespace" value="##targetNamespace"/>
+      </eAnnotations>
+    </eStructuralFeatures>
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="label" eType="ecore:EDataType http://www.eclipse.org/emf/2003/XMLType#//String">
+      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
+        <details key="kind" value="attribute"/>
+        <details key="name" value="label"/>
+        <details key="namespace" value="##targetNamespace"/>
+      </eAnnotations>
+    </eStructuralFeatures>
+  </eClassifiers>
+</ecore:EPackage>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/schema/PIConfig.genmodel	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<genmodel:GenModel xmi:version="2.0"
+    xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
+    xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel" modelDirectory="/com.nokia.carbide.cpp.pi.util/src"
+    modelPluginID="com.nokia.carbide.cpp.pi.util" modelName="PIConfig" importerID="org.eclipse.xsd.ecore.importer"
+    complianceLevel="5.0" copyrightFields="false">
+  <foreignModel>PIConfig.xsd</foreignModel>
+  <genPackages prefix="PIConfig" basePackage="com.nokia.carbide.cpp.pi.util.config.gen"
+      resource="XML" disposableProviderFactory="true" ecorePackage="PIConfig.ecore#/">
+    <genClasses ecoreClass="PIConfig.ecore#//ButtonEventProfileListType">
+      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference PIConfig.ecore#//ButtonEventProfileListType/buttonEventProfile"/>
+      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PIConfig.ecore#//ButtonEventProfileListType/buttonEventProfileVersion"/>
+    </genClasses>
+    <genClasses ecoreClass="PIConfig.ecore#//ButtonEventProfileType">
+      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference PIConfig.ecore#//ButtonEventProfileType/mapping"/>
+      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PIConfig.ecore#//ButtonEventProfileType/profileId"/>
+    </genClasses>
+    <genClasses ecoreClass="PIConfig.ecore#//DocumentRoot">
+      <genFeatures property="None" notify="false" createChild="false" ecoreFeature="ecore:EAttribute PIConfig.ecore#//DocumentRoot/mixed"/>
+      <genFeatures property="None" notify="false" createChild="false" ecoreFeature="ecore:EReference PIConfig.ecore#//DocumentRoot/xMLNSPrefixMap"/>
+      <genFeatures property="None" notify="false" createChild="false" ecoreFeature="ecore:EReference PIConfig.ecore#//DocumentRoot/xSISchemaLocation"/>
+      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference PIConfig.ecore#//DocumentRoot/buttonEventProfileList"/>
+    </genClasses>
+    <genClasses ecoreClass="PIConfig.ecore#//MappingType">
+      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PIConfig.ecore#//MappingType/enumString"/>
+      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PIConfig.ecore#//MappingType/keyCode"/>
+      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute PIConfig.ecore#//MappingType/label"/>
+    </genClasses>
+  </genPackages>
+</genmodel:GenModel>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/schema/PIConfig.xsd	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema">
+
+    <element name="buttonEventProfileList">
+    	<complexType>
+    		<sequence>
+    			<element maxOccurs="unbounded" minOccurs="0" name="buttonEventProfile">
+    				<complexType>
+    					<sequence>
+    						<element maxOccurs="unbounded" minOccurs="1" name="mapping">
+    							<complexType>
+    								<sequence/>
+    								<attribute name="keyCode" type="unsignedInt">
+    								</attribute>
+    								<attribute name="enumString" type="string">
+    								</attribute>
+    								<attribute name="label" type="string">
+    								</attribute>
+    							</complexType>
+    						</element>
+    					</sequence>
+    					<attribute name="profileId" type="string"/>
+    					    				</complexType>
+        </element>
+    		</sequence>
+    		<attribute name="buttonEventProfileVersion" type="decimal">
+    		</attribute>
+    	</complexType>
+    </element>
+</schema>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/schema/PIConfig.xsd2ecore	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="ASCII"?>
+<xsd2ecore:XSD2EcoreMappingRoot xmi:version="2.0"
+    xmlns:xmi="http://www.omg.org/XMI" xmlns:xsd2ecore="http://www.eclipse.org/emf/2002/XSD2Ecore" inputs="PIConfig.xsd#/"
+    outputs="PIConfig.ecore#/" topToBottom="true">
+  <nested inputs="bundleentry://257/cache/www.w3.org/2001/XMLSchema.xsd#//string;XSDSimpleTypeDefinition=9"
+      outputs="http://www.eclipse.org/emf/2003/XMLType#//String"/>
+  <nested inputs="bundleentry://257/cache/www.w3.org/2001/XMLSchema.xsd#//unsignedInt;XSDSimpleTypeDefinition=49"
+      outputs="http://www.eclipse.org/emf/2003/XMLType#//UnsignedInt"/>
+  <nested inputs="PIConfig.xsd#//buttonEventProfileList;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle/buttonEventProfile;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle/mapping;XSDElementDeclaration/XSDComplexTypeDefinition"
+      outputs="PIConfig.ecore#//MappingType">
+    <nested inputs="PIConfig.xsd#//buttonEventProfileList;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle/buttonEventProfile;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle/mapping;XSDElementDeclaration/XSDComplexTypeDefinition/XSDAttributeUse=1"
+        outputs="PIConfig.ecore#//MappingType/enumString"/>
+    <nested inputs="PIConfig.xsd#//buttonEventProfileList;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle/buttonEventProfile;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle/mapping;XSDElementDeclaration/XSDComplexTypeDefinition/XSDAttributeUse"
+        outputs="PIConfig.ecore#//MappingType/keyCode"/>
+    <nested inputs="PIConfig.xsd#//buttonEventProfileList;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle/buttonEventProfile;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle/mapping;XSDElementDeclaration/XSDComplexTypeDefinition/XSDAttributeUse=2"
+        outputs="PIConfig.ecore#//MappingType/label"/>
+  </nested>
+  <nested inputs="PIConfig.xsd#//buttonEventProfileList;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle/buttonEventProfile;XSDElementDeclaration/XSDComplexTypeDefinition"
+      outputs="PIConfig.ecore#//ButtonEventProfileType">
+    <nested inputs="PIConfig.xsd#//buttonEventProfileList;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle/buttonEventProfile;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle"
+        outputs="PIConfig.ecore#//ButtonEventProfileType/mapping"/>
+    <nested inputs="PIConfig.xsd#//buttonEventProfileList;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle/buttonEventProfile;XSDElementDeclaration/XSDComplexTypeDefinition/XSDAttributeUse"
+        outputs="PIConfig.ecore#//ButtonEventProfileType/profileId"/>
+  </nested>
+  <nested inputs="bundleentry://257/cache/www.w3.org/2001/XMLSchema.xsd#//decimal;XSDSimpleTypeDefinition=13"
+      outputs="http://www.eclipse.org/emf/2003/XMLType#//Decimal"/>
+  <nested inputs="PIConfig.xsd#//buttonEventProfileList;XSDElementDeclaration/XSDComplexTypeDefinition"
+      outputs="PIConfig.ecore#//ButtonEventProfileListType">
+    <nested inputs="PIConfig.xsd#//buttonEventProfileList;XSDElementDeclaration/XSDComplexTypeDefinition/XSDParticle/XSDModelGroup/XSDParticle"
+        outputs="PIConfig.ecore#//ButtonEventProfileListType/buttonEventProfile"/>
+    <nested inputs="PIConfig.xsd#//buttonEventProfileList;XSDElementDeclaration/XSDComplexTypeDefinition/XSDAttributeUse"
+        outputs="PIConfig.ecore#//ButtonEventProfileListType/buttonEventProfileVersion"/>
+  </nested>
+  <nested inputs="PIConfig.xsd#//buttonEventProfileList;XSDElementDeclaration" outputs="PIConfig.ecore#//DocumentRoot/buttonEventProfileList"/>
+</xsd2ecore:XSD2EcoreMappingRoot>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/PIConfigXMLLoader.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileListType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.DocumentRoot;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigFactory;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigPackage;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.util.PIConfigResourceFactoryImpl;
+
+
+public class PIConfigXMLLoader {
+	
+	static public ButtonEventProfileListType loadPiSettings (URL url) throws IOException {
+		if (url == null)
+			return null;
+
+		// blank file could cause IOException, which is unnecessary. Just return blank model
+		if (url.openStream().available() == 0) {
+			return PIConfigFactory.eINSTANCE.createButtonEventProfileListType();
+		}
+
+		URI xmlURI = URI.createURI(url.toString());
+
+		PIConfigResourceFactoryImpl resFactory = new PIConfigResourceFactoryImpl();
+		Resource r = resFactory.createResource(xmlURI);
+
+		r.load(null);
+		EList<EObject> contents = r.getContents();
+	
+		DocumentRoot root = (DocumentRoot) contents.get(0);
+		ButtonEventProfileListType list = root.getButtonEventProfileList();
+		
+		return list;
+
+	}
+	
+	static public boolean writePiSettings(ButtonEventProfileListType list, URL url) throws IOException {
+		if (url == null)
+			return false;
+		URI xmlURI = URI.createURI(url.toString());
+	
+		PIConfigResourceFactoryImpl resFactory = new PIConfigResourceFactoryImpl();
+		Resource r = resFactory.createResource(xmlURI);
+		EList<EObject> contents = r.getContents();
+	
+		PIConfigFactory factory = PIConfigPackage.eINSTANCE.getPIConfigFactory();
+		DocumentRoot root = factory.createDocumentRoot();
+		root.setButtonEventProfileList(list);
+		contents.add(root);
+						
+		// write to disk
+		r.save(null);
+		return true;
+
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/ButtonEventProfileListType.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig;
+
+import java.math.BigDecimal;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Button Event Profile List Type</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * <ul>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileListType#getButtonEventProfile <em>Button Event Profile</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileListType#getButtonEventProfileVersion <em>Button Event Profile Version</em>}</li>
+ * </ul>
+ * </p>
+ *
+ * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getButtonEventProfileListType()
+ * @model extendedMetaData="name='buttonEventProfileList_._type' kind='elementOnly'"
+ * @generated
+ */
+public interface ButtonEventProfileListType extends EObject {
+	/**
+	 * Returns the value of the '<em><b>Button Event Profile</b></em>' containment reference list.
+	 * The list contents are of type {@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType}.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>Button Event Profile</em>' containment reference list isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>Button Event Profile</em>' containment reference list.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getButtonEventProfileListType_ButtonEventProfile()
+	 * @model containment="true"
+	 *        extendedMetaData="kind='element' name='buttonEventProfile' namespace='##targetNamespace'"
+	 * @generated
+	 */
+	EList<ButtonEventProfileType> getButtonEventProfile();
+
+	/**
+	 * Returns the value of the '<em><b>Button Event Profile Version</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>Button Event Profile Version</em>' attribute isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>Button Event Profile Version</em>' attribute.
+	 * @see #setButtonEventProfileVersion(BigDecimal)
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getButtonEventProfileListType_ButtonEventProfileVersion()
+	 * @model dataType="org.eclipse.emf.ecore.xml.type.Decimal"
+	 *        extendedMetaData="kind='attribute' name='buttonEventProfileVersion' namespace='##targetNamespace'"
+	 * @generated
+	 */
+	BigDecimal getButtonEventProfileVersion();
+
+	/**
+	 * Sets the value of the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileListType#getButtonEventProfileVersion <em>Button Event Profile Version</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param value the new value of the '<em>Button Event Profile Version</em>' attribute.
+	 * @see #getButtonEventProfileVersion()
+	 * @generated
+	 */
+	void setButtonEventProfileVersion(BigDecimal value);
+
+} // ButtonEventProfileListType
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/ButtonEventProfileType.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Button Event Profile Type</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * <ul>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType#getMapping <em>Mapping</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType#getProfileId <em>Profile Id</em>}</li>
+ * </ul>
+ * </p>
+ *
+ * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getButtonEventProfileType()
+ * @model extendedMetaData="name='buttonEventProfile_._type' kind='elementOnly'"
+ * @generated
+ */
+public interface ButtonEventProfileType extends EObject {
+	/**
+	 * Returns the value of the '<em><b>Mapping</b></em>' containment reference list.
+	 * The list contents are of type {@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType}.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>Mapping</em>' containment reference list isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>Mapping</em>' containment reference list.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getButtonEventProfileType_Mapping()
+	 * @model containment="true" required="true"
+	 *        extendedMetaData="kind='element' name='mapping' namespace='##targetNamespace'"
+	 * @generated
+	 */
+	EList<MappingType> getMapping();
+
+	/**
+	 * Returns the value of the '<em><b>Profile Id</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>Profile Id</em>' attribute isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>Profile Id</em>' attribute.
+	 * @see #setProfileId(String)
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getButtonEventProfileType_ProfileId()
+	 * @model dataType="org.eclipse.emf.ecore.xml.type.String"
+	 *        extendedMetaData="kind='attribute' name='profileId' namespace='##targetNamespace'"
+	 * @generated
+	 */
+	String getProfileId();
+
+	/**
+	 * Sets the value of the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType#getProfileId <em>Profile Id</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param value the new value of the '<em>Profile Id</em>' attribute.
+	 * @see #getProfileId()
+	 * @generated
+	 */
+	void setProfileId(String value);
+
+} // ButtonEventProfileType
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/DocumentRoot.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig;
+
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.FeatureMap;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Document Root</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * <ul>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getMixed <em>Mixed</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getXMLNSPrefixMap <em>XMLNS Prefix Map</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getXSISchemaLocation <em>XSI Schema Location</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getButtonEventProfileList <em>Button Event Profile List</em>}</li>
+ * </ul>
+ * </p>
+ *
+ * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getDocumentRoot()
+ * @model extendedMetaData="name='' kind='mixed'"
+ * @generated
+ */
+public interface DocumentRoot extends EObject {
+	/**
+	 * Returns the value of the '<em><b>Mixed</b></em>' attribute list.
+	 * The list contents are of type {@link org.eclipse.emf.ecore.util.FeatureMap.Entry}.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>Mixed</em>' attribute list isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>Mixed</em>' attribute list.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getDocumentRoot_Mixed()
+	 * @model unique="false" dataType="org.eclipse.emf.ecore.EFeatureMapEntry" many="true"
+	 *        extendedMetaData="kind='elementWildcard' name=':mixed'"
+	 * @generated
+	 */
+	FeatureMap getMixed();
+
+	/**
+	 * Returns the value of the '<em><b>XMLNS Prefix Map</b></em>' map.
+	 * The key is of type {@link java.lang.String},
+	 * and the value is of type {@link java.lang.String},
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>XMLNS Prefix Map</em>' map isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>XMLNS Prefix Map</em>' map.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getDocumentRoot_XMLNSPrefixMap()
+	 * @model mapType="org.eclipse.emf.ecore.EStringToStringMapEntry<org.eclipse.emf.ecore.EString, org.eclipse.emf.ecore.EString>" transient="true"
+	 *        extendedMetaData="kind='attribute' name='xmlns:prefix'"
+	 * @generated
+	 */
+	EMap<String, String> getXMLNSPrefixMap();
+
+	/**
+	 * Returns the value of the '<em><b>XSI Schema Location</b></em>' map.
+	 * The key is of type {@link java.lang.String},
+	 * and the value is of type {@link java.lang.String},
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>XSI Schema Location</em>' map isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>XSI Schema Location</em>' map.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getDocumentRoot_XSISchemaLocation()
+	 * @model mapType="org.eclipse.emf.ecore.EStringToStringMapEntry<org.eclipse.emf.ecore.EString, org.eclipse.emf.ecore.EString>" transient="true"
+	 *        extendedMetaData="kind='attribute' name='xsi:schemaLocation'"
+	 * @generated
+	 */
+	EMap<String, String> getXSISchemaLocation();
+
+	/**
+	 * Returns the value of the '<em><b>Button Event Profile List</b></em>' containment reference.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>Button Event Profile List</em>' containment reference isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>Button Event Profile List</em>' containment reference.
+	 * @see #setButtonEventProfileList(ButtonEventProfileListType)
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getDocumentRoot_ButtonEventProfileList()
+	 * @model containment="true" upper="-2" transient="true" volatile="true" derived="true"
+	 *        extendedMetaData="kind='element' name='buttonEventProfileList' namespace='##targetNamespace'"
+	 * @generated
+	 */
+	ButtonEventProfileListType getButtonEventProfileList();
+
+	/**
+	 * Sets the value of the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getButtonEventProfileList <em>Button Event Profile List</em>}' containment reference.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param value the new value of the '<em>Button Event Profile List</em>' containment reference.
+	 * @see #getButtonEventProfileList()
+	 * @generated
+	 */
+	void setButtonEventProfileList(ButtonEventProfileListType value);
+
+} // DocumentRoot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/MappingType.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * <!-- begin-user-doc -->
+ * A representation of the model object '<em><b>Mapping Type</b></em>'.
+ * <!-- end-user-doc -->
+ *
+ * <p>
+ * The following features are supported:
+ * <ul>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getEnumString <em>Enum String</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getKeyCode <em>Key Code</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getLabel <em>Label</em>}</li>
+ * </ul>
+ * </p>
+ *
+ * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getMappingType()
+ * @model extendedMetaData="name='mapping_._type' kind='empty'"
+ * @generated
+ */
+public interface MappingType extends EObject {
+	/**
+	 * Returns the value of the '<em><b>Enum String</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>Enum String</em>' attribute isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>Enum String</em>' attribute.
+	 * @see #setEnumString(String)
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getMappingType_EnumString()
+	 * @model dataType="org.eclipse.emf.ecore.xml.type.String"
+	 *        extendedMetaData="kind='attribute' name='enumString' namespace='##targetNamespace'"
+	 * @generated
+	 */
+	String getEnumString();
+
+	/**
+	 * Sets the value of the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getEnumString <em>Enum String</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param value the new value of the '<em>Enum String</em>' attribute.
+	 * @see #getEnumString()
+	 * @generated
+	 */
+	void setEnumString(String value);
+
+	/**
+	 * Returns the value of the '<em><b>Key Code</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>Key Code</em>' attribute isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>Key Code</em>' attribute.
+	 * @see #isSetKeyCode()
+	 * @see #unsetKeyCode()
+	 * @see #setKeyCode(long)
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getMappingType_KeyCode()
+	 * @model unsettable="true" dataType="org.eclipse.emf.ecore.xml.type.UnsignedInt"
+	 *        extendedMetaData="kind='attribute' name='keyCode' namespace='##targetNamespace'"
+	 * @generated
+	 */
+	long getKeyCode();
+
+	/**
+	 * Sets the value of the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getKeyCode <em>Key Code</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param value the new value of the '<em>Key Code</em>' attribute.
+	 * @see #isSetKeyCode()
+	 * @see #unsetKeyCode()
+	 * @see #getKeyCode()
+	 * @generated
+	 */
+	void setKeyCode(long value);
+
+	/**
+	 * Unsets the value of the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getKeyCode <em>Key Code</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #isSetKeyCode()
+	 * @see #getKeyCode()
+	 * @see #setKeyCode(long)
+	 * @generated
+	 */
+	void unsetKeyCode();
+
+	/**
+	 * Returns whether the value of the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getKeyCode <em>Key Code</em>}' attribute is set.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return whether the value of the '<em>Key Code</em>' attribute is set.
+	 * @see #unsetKeyCode()
+	 * @see #getKeyCode()
+	 * @see #setKeyCode(long)
+	 * @generated
+	 */
+	boolean isSetKeyCode();
+
+	/**
+	 * Returns the value of the '<em><b>Label</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>Label</em>' attribute isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>Label</em>' attribute.
+	 * @see #setLabel(String)
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#getMappingType_Label()
+	 * @model dataType="org.eclipse.emf.ecore.xml.type.String"
+	 *        extendedMetaData="kind='attribute' name='label' namespace='##targetNamespace'"
+	 * @generated
+	 */
+	String getLabel();
+
+	/**
+	 * Sets the value of the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getLabel <em>Label</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param value the new value of the '<em>Label</em>' attribute.
+	 * @see #getLabel()
+	 * @generated
+	 */
+	void setLabel(String value);
+
+} // MappingType
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/PIConfigFactory.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig;
+
+import org.eclipse.emf.ecore.EFactory;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Factory</b> for the model.
+ * It provides a create method for each non-abstract class of the model.
+ * <!-- end-user-doc -->
+ * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage
+ * @generated
+ */
+public interface PIConfigFactory extends EFactory {
+	/**
+	 * The singleton instance of the factory.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	PIConfigFactory eINSTANCE = com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.impl.PIConfigFactoryImpl.init();
+
+	/**
+	 * Returns a new object of class '<em>Button Event Profile List Type</em>'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return a new object of class '<em>Button Event Profile List Type</em>'.
+	 * @generated
+	 */
+	ButtonEventProfileListType createButtonEventProfileListType();
+
+	/**
+	 * Returns a new object of class '<em>Button Event Profile Type</em>'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return a new object of class '<em>Button Event Profile Type</em>'.
+	 * @generated
+	 */
+	ButtonEventProfileType createButtonEventProfileType();
+
+	/**
+	 * Returns a new object of class '<em>Document Root</em>'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return a new object of class '<em>Document Root</em>'.
+	 * @generated
+	 */
+	DocumentRoot createDocumentRoot();
+
+	/**
+	 * Returns a new object of class '<em>Mapping Type</em>'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return a new object of class '<em>Mapping Type</em>'.
+	 * @generated
+	 */
+	MappingType createMappingType();
+
+	/**
+	 * Returns the package supported by this factory.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the package supported by this factory.
+	 * @generated
+	 */
+	PIConfigPackage getPIConfigPackage();
+
+} //PIConfigFactory
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/PIConfigPackage.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,563 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig;
+
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Package</b> for the model.
+ * It contains accessors for the meta objects to represent
+ * <ul>
+ *   <li>each class,</li>
+ *   <li>each feature of each class,</li>
+ *   <li>each enum,</li>
+ *   <li>and each data type</li>
+ * </ul>
+ * <!-- end-user-doc -->
+ * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigFactory
+ * @model kind="package"
+ *        extendedMetaData="qualified='false'"
+ * @generated
+ */
+public interface PIConfigPackage extends EPackage {
+	/**
+	 * The package name.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	String eNAME = "PIConfig";
+
+	/**
+	 * The package namespace URI.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	String eNS_URI = "platform:/resource/com.nokia.carbide.cpp.pi.util/schema/PIConfig.xsd";
+
+	/**
+	 * The package namespace name.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	String eNS_PREFIX = "PIConfig";
+
+	/**
+	 * The singleton instance of the package.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	PIConfigPackage eINSTANCE = com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.impl.PIConfigPackageImpl.init();
+
+	/**
+	 * The meta object id for the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileListTypeImpl <em>Button Event Profile List Type</em>}' class.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileListTypeImpl
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.PIConfigPackageImpl#getButtonEventProfileListType()
+	 * @generated
+	 */
+	int BUTTON_EVENT_PROFILE_LIST_TYPE = 0;
+
+	/**
+	 * The feature id for the '<em><b>Button Event Profile</b></em>' containment reference list.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE = 0;
+
+	/**
+	 * The feature id for the '<em><b>Button Event Profile Version</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE_VERSION = 1;
+
+	/**
+	 * The number of structural features of the '<em>Button Event Profile List Type</em>' class.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int BUTTON_EVENT_PROFILE_LIST_TYPE_FEATURE_COUNT = 2;
+
+	/**
+	 * The meta object id for the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileTypeImpl <em>Button Event Profile Type</em>}' class.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileTypeImpl
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.PIConfigPackageImpl#getButtonEventProfileType()
+	 * @generated
+	 */
+	int BUTTON_EVENT_PROFILE_TYPE = 1;
+
+	/**
+	 * The feature id for the '<em><b>Mapping</b></em>' containment reference list.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int BUTTON_EVENT_PROFILE_TYPE__MAPPING = 0;
+
+	/**
+	 * The feature id for the '<em><b>Profile Id</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int BUTTON_EVENT_PROFILE_TYPE__PROFILE_ID = 1;
+
+	/**
+	 * The number of structural features of the '<em>Button Event Profile Type</em>' class.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int BUTTON_EVENT_PROFILE_TYPE_FEATURE_COUNT = 2;
+
+	/**
+	 * The meta object id for the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.DocumentRootImpl <em>Document Root</em>}' class.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.DocumentRootImpl
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.PIConfigPackageImpl#getDocumentRoot()
+	 * @generated
+	 */
+	int DOCUMENT_ROOT = 2;
+
+	/**
+	 * The feature id for the '<em><b>Mixed</b></em>' attribute list.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int DOCUMENT_ROOT__MIXED = 0;
+
+	/**
+	 * The feature id for the '<em><b>XMLNS Prefix Map</b></em>' map.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int DOCUMENT_ROOT__XMLNS_PREFIX_MAP = 1;
+
+	/**
+	 * The feature id for the '<em><b>XSI Schema Location</b></em>' map.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int DOCUMENT_ROOT__XSI_SCHEMA_LOCATION = 2;
+
+	/**
+	 * The feature id for the '<em><b>Button Event Profile List</b></em>' containment reference.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int DOCUMENT_ROOT__BUTTON_EVENT_PROFILE_LIST = 3;
+
+	/**
+	 * The number of structural features of the '<em>Document Root</em>' class.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int DOCUMENT_ROOT_FEATURE_COUNT = 4;
+
+	/**
+	 * The meta object id for the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.MappingTypeImpl <em>Mapping Type</em>}' class.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.MappingTypeImpl
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.PIConfigPackageImpl#getMappingType()
+	 * @generated
+	 */
+	int MAPPING_TYPE = 3;
+
+	/**
+	 * The feature id for the '<em><b>Enum String</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int MAPPING_TYPE__ENUM_STRING = 0;
+
+	/**
+	 * The feature id for the '<em><b>Key Code</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int MAPPING_TYPE__KEY_CODE = 1;
+
+	/**
+	 * The feature id for the '<em><b>Label</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int MAPPING_TYPE__LABEL = 2;
+
+	/**
+	 * The number of structural features of the '<em>Mapping Type</em>' class.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int MAPPING_TYPE_FEATURE_COUNT = 3;
+
+
+	/**
+	 * Returns the meta object for class '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileListType <em>Button Event Profile List Type</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for class '<em>Button Event Profile List Type</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileListType
+	 * @generated
+	 */
+	EClass getButtonEventProfileListType();
+
+	/**
+	 * Returns the meta object for the containment reference list '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileListType#getButtonEventProfile <em>Button Event Profile</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the containment reference list '<em>Button Event Profile</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileListType#getButtonEventProfile()
+	 * @see #getButtonEventProfileListType()
+	 * @generated
+	 */
+	EReference getButtonEventProfileListType_ButtonEventProfile();
+
+	/**
+	 * Returns the meta object for the attribute '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileListType#getButtonEventProfileVersion <em>Button Event Profile Version</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the attribute '<em>Button Event Profile Version</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileListType#getButtonEventProfileVersion()
+	 * @see #getButtonEventProfileListType()
+	 * @generated
+	 */
+	EAttribute getButtonEventProfileListType_ButtonEventProfileVersion();
+
+	/**
+	 * Returns the meta object for class '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType <em>Button Event Profile Type</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for class '<em>Button Event Profile Type</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType
+	 * @generated
+	 */
+	EClass getButtonEventProfileType();
+
+	/**
+	 * Returns the meta object for the containment reference list '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType#getMapping <em>Mapping</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the containment reference list '<em>Mapping</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType#getMapping()
+	 * @see #getButtonEventProfileType()
+	 * @generated
+	 */
+	EReference getButtonEventProfileType_Mapping();
+
+	/**
+	 * Returns the meta object for the attribute '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType#getProfileId <em>Profile Id</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the attribute '<em>Profile Id</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType#getProfileId()
+	 * @see #getButtonEventProfileType()
+	 * @generated
+	 */
+	EAttribute getButtonEventProfileType_ProfileId();
+
+	/**
+	 * Returns the meta object for class '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot <em>Document Root</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for class '<em>Document Root</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot
+	 * @generated
+	 */
+	EClass getDocumentRoot();
+
+	/**
+	 * Returns the meta object for the attribute list '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getMixed <em>Mixed</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the attribute list '<em>Mixed</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getMixed()
+	 * @see #getDocumentRoot()
+	 * @generated
+	 */
+	EAttribute getDocumentRoot_Mixed();
+
+	/**
+	 * Returns the meta object for the map '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getXMLNSPrefixMap <em>XMLNS Prefix Map</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the map '<em>XMLNS Prefix Map</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getXMLNSPrefixMap()
+	 * @see #getDocumentRoot()
+	 * @generated
+	 */
+	EReference getDocumentRoot_XMLNSPrefixMap();
+
+	/**
+	 * Returns the meta object for the map '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getXSISchemaLocation <em>XSI Schema Location</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the map '<em>XSI Schema Location</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getXSISchemaLocation()
+	 * @see #getDocumentRoot()
+	 * @generated
+	 */
+	EReference getDocumentRoot_XSISchemaLocation();
+
+	/**
+	 * Returns the meta object for the containment reference '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getButtonEventProfileList <em>Button Event Profile List</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the containment reference '<em>Button Event Profile List</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot#getButtonEventProfileList()
+	 * @see #getDocumentRoot()
+	 * @generated
+	 */
+	EReference getDocumentRoot_ButtonEventProfileList();
+
+	/**
+	 * Returns the meta object for class '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType <em>Mapping Type</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for class '<em>Mapping Type</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType
+	 * @generated
+	 */
+	EClass getMappingType();
+
+	/**
+	 * Returns the meta object for the attribute '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getEnumString <em>Enum String</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the attribute '<em>Enum String</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getEnumString()
+	 * @see #getMappingType()
+	 * @generated
+	 */
+	EAttribute getMappingType_EnumString();
+
+	/**
+	 * Returns the meta object for the attribute '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getKeyCode <em>Key Code</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the attribute '<em>Key Code</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getKeyCode()
+	 * @see #getMappingType()
+	 * @generated
+	 */
+	EAttribute getMappingType_KeyCode();
+
+	/**
+	 * Returns the meta object for the attribute '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getLabel <em>Label</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the attribute '<em>Label</em>'.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType#getLabel()
+	 * @see #getMappingType()
+	 * @generated
+	 */
+	EAttribute getMappingType_Label();
+
+	/**
+	 * Returns the factory that creates the instances of the model.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the factory that creates the instances of the model.
+	 * @generated
+	 */
+	PIConfigFactory getPIConfigFactory();
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * Defines literals for the meta objects that represent
+	 * <ul>
+	 *   <li>each class,</li>
+	 *   <li>each feature of each class,</li>
+	 *   <li>each enum,</li>
+	 *   <li>and each data type</li>
+	 * </ul>
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	interface Literals {
+		/**
+		 * The meta object literal for the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileListTypeImpl <em>Button Event Profile List Type</em>}' class.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileListTypeImpl
+		 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.PIConfigPackageImpl#getButtonEventProfileListType()
+		 * @generated
+		 */
+		EClass BUTTON_EVENT_PROFILE_LIST_TYPE = eINSTANCE.getButtonEventProfileListType();
+
+		/**
+		 * The meta object literal for the '<em><b>Button Event Profile</b></em>' containment reference list feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EReference BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE = eINSTANCE.getButtonEventProfileListType_ButtonEventProfile();
+
+		/**
+		 * The meta object literal for the '<em><b>Button Event Profile Version</b></em>' attribute feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EAttribute BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE_VERSION = eINSTANCE.getButtonEventProfileListType_ButtonEventProfileVersion();
+
+		/**
+		 * The meta object literal for the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileTypeImpl <em>Button Event Profile Type</em>}' class.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileTypeImpl
+		 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.PIConfigPackageImpl#getButtonEventProfileType()
+		 * @generated
+		 */
+		EClass BUTTON_EVENT_PROFILE_TYPE = eINSTANCE.getButtonEventProfileType();
+
+		/**
+		 * The meta object literal for the '<em><b>Mapping</b></em>' containment reference list feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EReference BUTTON_EVENT_PROFILE_TYPE__MAPPING = eINSTANCE.getButtonEventProfileType_Mapping();
+
+		/**
+		 * The meta object literal for the '<em><b>Profile Id</b></em>' attribute feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EAttribute BUTTON_EVENT_PROFILE_TYPE__PROFILE_ID = eINSTANCE.getButtonEventProfileType_ProfileId();
+
+		/**
+		 * The meta object literal for the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.DocumentRootImpl <em>Document Root</em>}' class.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.DocumentRootImpl
+		 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.PIConfigPackageImpl#getDocumentRoot()
+		 * @generated
+		 */
+		EClass DOCUMENT_ROOT = eINSTANCE.getDocumentRoot();
+
+		/**
+		 * The meta object literal for the '<em><b>Mixed</b></em>' attribute list feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EAttribute DOCUMENT_ROOT__MIXED = eINSTANCE.getDocumentRoot_Mixed();
+
+		/**
+		 * The meta object literal for the '<em><b>XMLNS Prefix Map</b></em>' map feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EReference DOCUMENT_ROOT__XMLNS_PREFIX_MAP = eINSTANCE.getDocumentRoot_XMLNSPrefixMap();
+
+		/**
+		 * The meta object literal for the '<em><b>XSI Schema Location</b></em>' map feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EReference DOCUMENT_ROOT__XSI_SCHEMA_LOCATION = eINSTANCE.getDocumentRoot_XSISchemaLocation();
+
+		/**
+		 * The meta object literal for the '<em><b>Button Event Profile List</b></em>' containment reference feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EReference DOCUMENT_ROOT__BUTTON_EVENT_PROFILE_LIST = eINSTANCE.getDocumentRoot_ButtonEventProfileList();
+
+		/**
+		 * The meta object literal for the '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.MappingTypeImpl <em>Mapping Type</em>}' class.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.MappingTypeImpl
+		 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.PIConfigPackageImpl#getMappingType()
+		 * @generated
+		 */
+		EClass MAPPING_TYPE = eINSTANCE.getMappingType();
+
+		/**
+		 * The meta object literal for the '<em><b>Enum String</b></em>' attribute feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EAttribute MAPPING_TYPE__ENUM_STRING = eINSTANCE.getMappingType_EnumString();
+
+		/**
+		 * The meta object literal for the '<em><b>Key Code</b></em>' attribute feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EAttribute MAPPING_TYPE__KEY_CODE = eINSTANCE.getMappingType_KeyCode();
+
+		/**
+		 * The meta object literal for the '<em><b>Label</b></em>' attribute feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EAttribute MAPPING_TYPE__LABEL = eINSTANCE.getMappingType_Label();
+
+	}
+
+} //PIConfigPackage
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/ButtonEventProfileListTypeImpl.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig.impl;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.NotificationChain;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.impl.ENotificationImpl;
+import org.eclipse.emf.ecore.impl.EObjectImpl;
+import org.eclipse.emf.ecore.util.EObjectContainmentEList;
+import org.eclipse.emf.ecore.util.InternalEList;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileListType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigPackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Button Event Profile List Type</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * <ul>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileListTypeImpl#getButtonEventProfile <em>Button Event Profile</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileListTypeImpl#getButtonEventProfileVersion <em>Button Event Profile Version</em>}</li>
+ * </ul>
+ * </p>
+ *
+ * @generated
+ */
+public class ButtonEventProfileListTypeImpl extends EObjectImpl implements ButtonEventProfileListType {
+	/**
+	 * The cached value of the '{@link #getButtonEventProfile() <em>Button Event Profile</em>}' containment reference list.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getButtonEventProfile()
+	 * @generated
+	 * @ordered
+	 */
+	protected EList<ButtonEventProfileType> buttonEventProfile;
+
+	/**
+	 * The default value of the '{@link #getButtonEventProfileVersion() <em>Button Event Profile Version</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getButtonEventProfileVersion()
+	 * @generated
+	 * @ordered
+	 */
+	protected static final BigDecimal BUTTON_EVENT_PROFILE_VERSION_EDEFAULT = null;
+
+	/**
+	 * The cached value of the '{@link #getButtonEventProfileVersion() <em>Button Event Profile Version</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getButtonEventProfileVersion()
+	 * @generated
+	 * @ordered
+	 */
+	protected BigDecimal buttonEventProfileVersion = BUTTON_EVENT_PROFILE_VERSION_EDEFAULT;
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	protected ButtonEventProfileListTypeImpl() {
+		super();
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	protected EClass eStaticClass() {
+		return PIConfigPackage.Literals.BUTTON_EVENT_PROFILE_LIST_TYPE;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EList<ButtonEventProfileType> getButtonEventProfile() {
+		if (buttonEventProfile == null) {
+			buttonEventProfile = new EObjectContainmentEList<ButtonEventProfileType>(ButtonEventProfileType.class, this, PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE);
+		}
+		return buttonEventProfile;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public BigDecimal getButtonEventProfileVersion() {
+		return buttonEventProfileVersion;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void setButtonEventProfileVersion(BigDecimal newButtonEventProfileVersion) {
+		BigDecimal oldButtonEventProfileVersion = buttonEventProfileVersion;
+		buttonEventProfileVersion = newButtonEventProfileVersion;
+		if (eNotificationRequired())
+			eNotify(new ENotificationImpl(this, Notification.SET, PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE_VERSION, oldButtonEventProfileVersion, buttonEventProfileVersion));
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
+		switch (featureID) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE:
+				return ((InternalEList<?>)getButtonEventProfile()).basicRemove(otherEnd, msgs);
+		}
+		return super.eInverseRemove(otherEnd, featureID, msgs);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public Object eGet(int featureID, boolean resolve, boolean coreType) {
+		switch (featureID) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE:
+				return getButtonEventProfile();
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE_VERSION:
+				return getButtonEventProfileVersion();
+		}
+		return super.eGet(featureID, resolve, coreType);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@SuppressWarnings("unchecked")
+	@Override
+	public void eSet(int featureID, Object newValue) {
+		switch (featureID) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE:
+				getButtonEventProfile().clear();
+				getButtonEventProfile().addAll((Collection<? extends ButtonEventProfileType>)newValue);
+				return;
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE_VERSION:
+				setButtonEventProfileVersion((BigDecimal)newValue);
+				return;
+		}
+		super.eSet(featureID, newValue);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public void eUnset(int featureID) {
+		switch (featureID) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE:
+				getButtonEventProfile().clear();
+				return;
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE_VERSION:
+				setButtonEventProfileVersion(BUTTON_EVENT_PROFILE_VERSION_EDEFAULT);
+				return;
+		}
+		super.eUnset(featureID);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public boolean eIsSet(int featureID) {
+		switch (featureID) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE:
+				return buttonEventProfile != null && !buttonEventProfile.isEmpty();
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE_VERSION:
+				return BUTTON_EVENT_PROFILE_VERSION_EDEFAULT == null ? buttonEventProfileVersion != null : !BUTTON_EVENT_PROFILE_VERSION_EDEFAULT.equals(buttonEventProfileVersion);
+		}
+		return super.eIsSet(featureID);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public String toString() {
+		if (eIsProxy()) return super.toString();
+
+		StringBuffer result = new StringBuffer(super.toString());
+		result.append(" (buttonEventProfileVersion: ");
+		result.append(buttonEventProfileVersion);
+		result.append(')');
+		return result.toString();
+	}
+
+} //ButtonEventProfileListTypeImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/ButtonEventProfileTypeImpl.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig.impl;
+
+import java.util.Collection;
+
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.NotificationChain;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.impl.ENotificationImpl;
+import org.eclipse.emf.ecore.impl.EObjectImpl;
+import org.eclipse.emf.ecore.util.EObjectContainmentEList;
+import org.eclipse.emf.ecore.util.InternalEList;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.MappingType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigPackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Button Event Profile Type</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * <ul>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileTypeImpl#getMapping <em>Mapping</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.ButtonEventProfileTypeImpl#getProfileId <em>Profile Id</em>}</li>
+ * </ul>
+ * </p>
+ *
+ * @generated
+ */
+public class ButtonEventProfileTypeImpl extends EObjectImpl implements ButtonEventProfileType {
+	/**
+	 * The cached value of the '{@link #getMapping() <em>Mapping</em>}' containment reference list.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getMapping()
+	 * @generated
+	 * @ordered
+	 */
+	protected EList<MappingType> mapping;
+
+	/**
+	 * The default value of the '{@link #getProfileId() <em>Profile Id</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getProfileId()
+	 * @generated
+	 * @ordered
+	 */
+	protected static final String PROFILE_ID_EDEFAULT = null;
+
+	/**
+	 * The cached value of the '{@link #getProfileId() <em>Profile Id</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getProfileId()
+	 * @generated
+	 * @ordered
+	 */
+	protected String profileId = PROFILE_ID_EDEFAULT;
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	protected ButtonEventProfileTypeImpl() {
+		super();
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	protected EClass eStaticClass() {
+		return PIConfigPackage.Literals.BUTTON_EVENT_PROFILE_TYPE;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EList<MappingType> getMapping() {
+		if (mapping == null) {
+			mapping = new EObjectContainmentEList<MappingType>(MappingType.class, this, PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE__MAPPING);
+		}
+		return mapping;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public String getProfileId() {
+		return profileId;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void setProfileId(String newProfileId) {
+		String oldProfileId = profileId;
+		profileId = newProfileId;
+		if (eNotificationRequired())
+			eNotify(new ENotificationImpl(this, Notification.SET, PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE__PROFILE_ID, oldProfileId, profileId));
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
+		switch (featureID) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE__MAPPING:
+				return ((InternalEList<?>)getMapping()).basicRemove(otherEnd, msgs);
+		}
+		return super.eInverseRemove(otherEnd, featureID, msgs);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public Object eGet(int featureID, boolean resolve, boolean coreType) {
+		switch (featureID) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE__MAPPING:
+				return getMapping();
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE__PROFILE_ID:
+				return getProfileId();
+		}
+		return super.eGet(featureID, resolve, coreType);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@SuppressWarnings("unchecked")
+	@Override
+	public void eSet(int featureID, Object newValue) {
+		switch (featureID) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE__MAPPING:
+				getMapping().clear();
+				getMapping().addAll((Collection<? extends MappingType>)newValue);
+				return;
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE__PROFILE_ID:
+				setProfileId((String)newValue);
+				return;
+		}
+		super.eSet(featureID, newValue);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public void eUnset(int featureID) {
+		switch (featureID) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE__MAPPING:
+				getMapping().clear();
+				return;
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE__PROFILE_ID:
+				setProfileId(PROFILE_ID_EDEFAULT);
+				return;
+		}
+		super.eUnset(featureID);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public boolean eIsSet(int featureID) {
+		switch (featureID) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE__MAPPING:
+				return mapping != null && !mapping.isEmpty();
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE__PROFILE_ID:
+				return PROFILE_ID_EDEFAULT == null ? profileId != null : !PROFILE_ID_EDEFAULT.equals(profileId);
+		}
+		return super.eIsSet(featureID);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public String toString() {
+		if (eIsProxy()) return super.toString();
+
+		StringBuffer result = new StringBuffer(super.toString());
+		result.append(" (profileId: ");
+		result.append(profileId);
+		result.append(')');
+		return result.toString();
+	}
+
+} //ButtonEventProfileTypeImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/DocumentRootImpl.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig.impl;
+
+import org.eclipse.emf.common.notify.NotificationChain;
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.impl.EObjectImpl;
+import org.eclipse.emf.ecore.impl.EStringToStringMapEntryImpl;
+import org.eclipse.emf.ecore.util.BasicFeatureMap;
+import org.eclipse.emf.ecore.util.EcoreEMap;
+import org.eclipse.emf.ecore.util.FeatureMap;
+import org.eclipse.emf.ecore.util.InternalEList;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileListType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.DocumentRoot;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigPackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Document Root</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * <ul>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.DocumentRootImpl#getMixed <em>Mixed</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.DocumentRootImpl#getXMLNSPrefixMap <em>XMLNS Prefix Map</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.DocumentRootImpl#getXSISchemaLocation <em>XSI Schema Location</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.DocumentRootImpl#getButtonEventProfileList <em>Button Event Profile List</em>}</li>
+ * </ul>
+ * </p>
+ *
+ * @generated
+ */
+public class DocumentRootImpl extends EObjectImpl implements DocumentRoot {
+	/**
+	 * The cached value of the '{@link #getMixed() <em>Mixed</em>}' attribute list.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getMixed()
+	 * @generated
+	 * @ordered
+	 */
+	protected FeatureMap mixed;
+
+	/**
+	 * The cached value of the '{@link #getXMLNSPrefixMap() <em>XMLNS Prefix Map</em>}' map.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getXMLNSPrefixMap()
+	 * @generated
+	 * @ordered
+	 */
+	protected EMap<String, String> xMLNSPrefixMap;
+
+	/**
+	 * The cached value of the '{@link #getXSISchemaLocation() <em>XSI Schema Location</em>}' map.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getXSISchemaLocation()
+	 * @generated
+	 * @ordered
+	 */
+	protected EMap<String, String> xSISchemaLocation;
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	protected DocumentRootImpl() {
+		super();
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	protected EClass eStaticClass() {
+		return PIConfigPackage.Literals.DOCUMENT_ROOT;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public FeatureMap getMixed() {
+		if (mixed == null) {
+			mixed = new BasicFeatureMap(this, PIConfigPackage.DOCUMENT_ROOT__MIXED);
+		}
+		return mixed;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EMap<String, String> getXMLNSPrefixMap() {
+		if (xMLNSPrefixMap == null) {
+			xMLNSPrefixMap = new EcoreEMap<String,String>(EcorePackage.Literals.ESTRING_TO_STRING_MAP_ENTRY, EStringToStringMapEntryImpl.class, this, PIConfigPackage.DOCUMENT_ROOT__XMLNS_PREFIX_MAP);
+		}
+		return xMLNSPrefixMap;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EMap<String, String> getXSISchemaLocation() {
+		if (xSISchemaLocation == null) {
+			xSISchemaLocation = new EcoreEMap<String,String>(EcorePackage.Literals.ESTRING_TO_STRING_MAP_ENTRY, EStringToStringMapEntryImpl.class, this, PIConfigPackage.DOCUMENT_ROOT__XSI_SCHEMA_LOCATION);
+		}
+		return xSISchemaLocation;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public ButtonEventProfileListType getButtonEventProfileList() {
+		return (ButtonEventProfileListType)getMixed().get(PIConfigPackage.Literals.DOCUMENT_ROOT__BUTTON_EVENT_PROFILE_LIST, true);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public NotificationChain basicSetButtonEventProfileList(ButtonEventProfileListType newButtonEventProfileList, NotificationChain msgs) {
+		return ((FeatureMap.Internal)getMixed()).basicAdd(PIConfigPackage.Literals.DOCUMENT_ROOT__BUTTON_EVENT_PROFILE_LIST, newButtonEventProfileList, msgs);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void setButtonEventProfileList(ButtonEventProfileListType newButtonEventProfileList) {
+		((FeatureMap.Internal)getMixed()).set(PIConfigPackage.Literals.DOCUMENT_ROOT__BUTTON_EVENT_PROFILE_LIST, newButtonEventProfileList);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
+		switch (featureID) {
+			case PIConfigPackage.DOCUMENT_ROOT__MIXED:
+				return ((InternalEList<?>)getMixed()).basicRemove(otherEnd, msgs);
+			case PIConfigPackage.DOCUMENT_ROOT__XMLNS_PREFIX_MAP:
+				return ((InternalEList<?>)getXMLNSPrefixMap()).basicRemove(otherEnd, msgs);
+			case PIConfigPackage.DOCUMENT_ROOT__XSI_SCHEMA_LOCATION:
+				return ((InternalEList<?>)getXSISchemaLocation()).basicRemove(otherEnd, msgs);
+			case PIConfigPackage.DOCUMENT_ROOT__BUTTON_EVENT_PROFILE_LIST:
+				return basicSetButtonEventProfileList(null, msgs);
+		}
+		return super.eInverseRemove(otherEnd, featureID, msgs);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public Object eGet(int featureID, boolean resolve, boolean coreType) {
+		switch (featureID) {
+			case PIConfigPackage.DOCUMENT_ROOT__MIXED:
+				if (coreType) return getMixed();
+				return ((FeatureMap.Internal)getMixed()).getWrapper();
+			case PIConfigPackage.DOCUMENT_ROOT__XMLNS_PREFIX_MAP:
+				if (coreType) return getXMLNSPrefixMap();
+				else return getXMLNSPrefixMap().map();
+			case PIConfigPackage.DOCUMENT_ROOT__XSI_SCHEMA_LOCATION:
+				if (coreType) return getXSISchemaLocation();
+				else return getXSISchemaLocation().map();
+			case PIConfigPackage.DOCUMENT_ROOT__BUTTON_EVENT_PROFILE_LIST:
+				return getButtonEventProfileList();
+		}
+		return super.eGet(featureID, resolve, coreType);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public void eSet(int featureID, Object newValue) {
+		switch (featureID) {
+			case PIConfigPackage.DOCUMENT_ROOT__MIXED:
+				((FeatureMap.Internal)getMixed()).set(newValue);
+				return;
+			case PIConfigPackage.DOCUMENT_ROOT__XMLNS_PREFIX_MAP:
+				((EStructuralFeature.Setting)getXMLNSPrefixMap()).set(newValue);
+				return;
+			case PIConfigPackage.DOCUMENT_ROOT__XSI_SCHEMA_LOCATION:
+				((EStructuralFeature.Setting)getXSISchemaLocation()).set(newValue);
+				return;
+			case PIConfigPackage.DOCUMENT_ROOT__BUTTON_EVENT_PROFILE_LIST:
+				setButtonEventProfileList((ButtonEventProfileListType)newValue);
+				return;
+		}
+		super.eSet(featureID, newValue);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public void eUnset(int featureID) {
+		switch (featureID) {
+			case PIConfigPackage.DOCUMENT_ROOT__MIXED:
+				getMixed().clear();
+				return;
+			case PIConfigPackage.DOCUMENT_ROOT__XMLNS_PREFIX_MAP:
+				getXMLNSPrefixMap().clear();
+				return;
+			case PIConfigPackage.DOCUMENT_ROOT__XSI_SCHEMA_LOCATION:
+				getXSISchemaLocation().clear();
+				return;
+			case PIConfigPackage.DOCUMENT_ROOT__BUTTON_EVENT_PROFILE_LIST:
+				setButtonEventProfileList((ButtonEventProfileListType)null);
+				return;
+		}
+		super.eUnset(featureID);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public boolean eIsSet(int featureID) {
+		switch (featureID) {
+			case PIConfigPackage.DOCUMENT_ROOT__MIXED:
+				return mixed != null && !mixed.isEmpty();
+			case PIConfigPackage.DOCUMENT_ROOT__XMLNS_PREFIX_MAP:
+				return xMLNSPrefixMap != null && !xMLNSPrefixMap.isEmpty();
+			case PIConfigPackage.DOCUMENT_ROOT__XSI_SCHEMA_LOCATION:
+				return xSISchemaLocation != null && !xSISchemaLocation.isEmpty();
+			case PIConfigPackage.DOCUMENT_ROOT__BUTTON_EVENT_PROFILE_LIST:
+				return getButtonEventProfileList() != null;
+		}
+		return super.eIsSet(featureID);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public String toString() {
+		if (eIsProxy()) return super.toString();
+
+		StringBuffer result = new StringBuffer(super.toString());
+		result.append(" (mixed: ");
+		result.append(mixed);
+		result.append(')');
+		return result.toString();
+	}
+
+} //DocumentRootImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/MappingTypeImpl.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig.impl;
+
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.impl.ENotificationImpl;
+import org.eclipse.emf.ecore.impl.EObjectImpl;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.MappingType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigPackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Mapping Type</b></em>'.
+ * <!-- end-user-doc -->
+ * <p>
+ * The following features are implemented:
+ * <ul>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.MappingTypeImpl#getEnumString <em>Enum String</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.MappingTypeImpl#getKeyCode <em>Key Code</em>}</li>
+ *   <li>{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.impl.MappingTypeImpl#getLabel <em>Label</em>}</li>
+ * </ul>
+ * </p>
+ *
+ * @generated
+ */
+public class MappingTypeImpl extends EObjectImpl implements MappingType {
+	/**
+	 * The default value of the '{@link #getEnumString() <em>Enum String</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getEnumString()
+	 * @generated
+	 * @ordered
+	 */
+	protected static final String ENUM_STRING_EDEFAULT = null;
+
+	/**
+	 * The cached value of the '{@link #getEnumString() <em>Enum String</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getEnumString()
+	 * @generated
+	 * @ordered
+	 */
+	protected String enumString = ENUM_STRING_EDEFAULT;
+
+	/**
+	 * The default value of the '{@link #getKeyCode() <em>Key Code</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getKeyCode()
+	 * @generated
+	 * @ordered
+	 */
+	protected static final long KEY_CODE_EDEFAULT = 0L;
+
+	/**
+	 * The cached value of the '{@link #getKeyCode() <em>Key Code</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getKeyCode()
+	 * @generated
+	 * @ordered
+	 */
+	protected long keyCode = KEY_CODE_EDEFAULT;
+
+	/**
+	 * This is true if the Key Code attribute has been set.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	protected boolean keyCodeESet;
+
+	/**
+	 * The default value of the '{@link #getLabel() <em>Label</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getLabel()
+	 * @generated
+	 * @ordered
+	 */
+	protected static final String LABEL_EDEFAULT = null;
+
+	/**
+	 * The cached value of the '{@link #getLabel() <em>Label</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getLabel()
+	 * @generated
+	 * @ordered
+	 */
+	protected String label = LABEL_EDEFAULT;
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	protected MappingTypeImpl() {
+		super();
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	protected EClass eStaticClass() {
+		return PIConfigPackage.Literals.MAPPING_TYPE;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public String getEnumString() {
+		return enumString;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void setEnumString(String newEnumString) {
+		String oldEnumString = enumString;
+		enumString = newEnumString;
+		if (eNotificationRequired())
+			eNotify(new ENotificationImpl(this, Notification.SET, PIConfigPackage.MAPPING_TYPE__ENUM_STRING, oldEnumString, enumString));
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public long getKeyCode() {
+		return keyCode;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void setKeyCode(long newKeyCode) {
+		long oldKeyCode = keyCode;
+		keyCode = newKeyCode;
+		boolean oldKeyCodeESet = keyCodeESet;
+		keyCodeESet = true;
+		if (eNotificationRequired())
+			eNotify(new ENotificationImpl(this, Notification.SET, PIConfigPackage.MAPPING_TYPE__KEY_CODE, oldKeyCode, keyCode, !oldKeyCodeESet));
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void unsetKeyCode() {
+		long oldKeyCode = keyCode;
+		boolean oldKeyCodeESet = keyCodeESet;
+		keyCode = KEY_CODE_EDEFAULT;
+		keyCodeESet = false;
+		if (eNotificationRequired())
+			eNotify(new ENotificationImpl(this, Notification.UNSET, PIConfigPackage.MAPPING_TYPE__KEY_CODE, oldKeyCode, KEY_CODE_EDEFAULT, oldKeyCodeESet));
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public boolean isSetKeyCode() {
+		return keyCodeESet;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public String getLabel() {
+		return label;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void setLabel(String newLabel) {
+		String oldLabel = label;
+		label = newLabel;
+		if (eNotificationRequired())
+			eNotify(new ENotificationImpl(this, Notification.SET, PIConfigPackage.MAPPING_TYPE__LABEL, oldLabel, label));
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public Object eGet(int featureID, boolean resolve, boolean coreType) {
+		switch (featureID) {
+			case PIConfigPackage.MAPPING_TYPE__ENUM_STRING:
+				return getEnumString();
+			case PIConfigPackage.MAPPING_TYPE__KEY_CODE:
+				return new Long(getKeyCode());
+			case PIConfigPackage.MAPPING_TYPE__LABEL:
+				return getLabel();
+		}
+		return super.eGet(featureID, resolve, coreType);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public void eSet(int featureID, Object newValue) {
+		switch (featureID) {
+			case PIConfigPackage.MAPPING_TYPE__ENUM_STRING:
+				setEnumString((String)newValue);
+				return;
+			case PIConfigPackage.MAPPING_TYPE__KEY_CODE:
+				setKeyCode(((Long)newValue).longValue());
+				return;
+			case PIConfigPackage.MAPPING_TYPE__LABEL:
+				setLabel((String)newValue);
+				return;
+		}
+		super.eSet(featureID, newValue);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public void eUnset(int featureID) {
+		switch (featureID) {
+			case PIConfigPackage.MAPPING_TYPE__ENUM_STRING:
+				setEnumString(ENUM_STRING_EDEFAULT);
+				return;
+			case PIConfigPackage.MAPPING_TYPE__KEY_CODE:
+				unsetKeyCode();
+				return;
+			case PIConfigPackage.MAPPING_TYPE__LABEL:
+				setLabel(LABEL_EDEFAULT);
+				return;
+		}
+		super.eUnset(featureID);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public boolean eIsSet(int featureID) {
+		switch (featureID) {
+			case PIConfigPackage.MAPPING_TYPE__ENUM_STRING:
+				return ENUM_STRING_EDEFAULT == null ? enumString != null : !ENUM_STRING_EDEFAULT.equals(enumString);
+			case PIConfigPackage.MAPPING_TYPE__KEY_CODE:
+				return isSetKeyCode();
+			case PIConfigPackage.MAPPING_TYPE__LABEL:
+				return LABEL_EDEFAULT == null ? label != null : !LABEL_EDEFAULT.equals(label);
+		}
+		return super.eIsSet(featureID);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public String toString() {
+		if (eIsProxy()) return super.toString();
+
+		StringBuffer result = new StringBuffer(super.toString());
+		result.append(" (enumString: ");
+		result.append(enumString);
+		result.append(", keyCode: ");
+		if (keyCodeESet) result.append(keyCode); else result.append("<unset>");
+		result.append(", label: ");
+		result.append(label);
+		result.append(')');
+		return result.toString();
+	}
+
+} //MappingTypeImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/PIConfigFactoryImpl.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig.impl;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.impl.EFactoryImpl;
+import org.eclipse.emf.ecore.plugin.EcorePlugin;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileListType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.DocumentRoot;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.MappingType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigFactory;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigPackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model <b>Factory</b>.
+ * <!-- end-user-doc -->
+ * @generated
+ */
+public class PIConfigFactoryImpl extends EFactoryImpl implements PIConfigFactory {
+	/**
+	 * Creates the default factory implementation.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public static PIConfigFactory init() {
+		try {
+			PIConfigFactory thePIConfigFactory = (PIConfigFactory)EPackage.Registry.INSTANCE.getEFactory("platform:/resource/com.nokia.carbide.cpp.pi.util/schema/PIConfig.xsd"); 
+			if (thePIConfigFactory != null) {
+				return thePIConfigFactory;
+			}
+		}
+		catch (Exception exception) {
+			EcorePlugin.INSTANCE.log(exception);
+		}
+		return new PIConfigFactoryImpl();
+	}
+
+	/**
+	 * Creates an instance of the factory.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public PIConfigFactoryImpl() {
+		super();
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public EObject create(EClass eClass) {
+		switch (eClass.getClassifierID()) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE: return createButtonEventProfileListType();
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE: return createButtonEventProfileType();
+			case PIConfigPackage.DOCUMENT_ROOT: return createDocumentRoot();
+			case PIConfigPackage.MAPPING_TYPE: return createMappingType();
+			default:
+				throw new IllegalArgumentException("The class '" + eClass.getName() + "' is not a valid classifier");
+		}
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public ButtonEventProfileListType createButtonEventProfileListType() {
+		ButtonEventProfileListTypeImpl buttonEventProfileListType = new ButtonEventProfileListTypeImpl();
+		return buttonEventProfileListType;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public ButtonEventProfileType createButtonEventProfileType() {
+		ButtonEventProfileTypeImpl buttonEventProfileType = new ButtonEventProfileTypeImpl();
+		return buttonEventProfileType;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public DocumentRoot createDocumentRoot() {
+		DocumentRootImpl documentRoot = new DocumentRootImpl();
+		return documentRoot;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public MappingType createMappingType() {
+		MappingTypeImpl mappingType = new MappingTypeImpl();
+		return mappingType;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public PIConfigPackage getPIConfigPackage() {
+		return (PIConfigPackage)getEPackage();
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @deprecated
+	 * @generated
+	 */
+	@Deprecated
+	public static PIConfigPackage getPackage() {
+		return PIConfigPackage.eINSTANCE;
+	}
+
+} //PIConfigFactoryImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/impl/PIConfigPackageImpl.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig.impl;
+
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.impl.EPackageImpl;
+import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileListType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.DocumentRoot;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.MappingType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigFactory;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigPackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model <b>Package</b>.
+ * <!-- end-user-doc -->
+ * @generated
+ */
+public class PIConfigPackageImpl extends EPackageImpl implements PIConfigPackage {
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	private EClass buttonEventProfileListTypeEClass = null;
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	private EClass buttonEventProfileTypeEClass = null;
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	private EClass documentRootEClass = null;
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	private EClass mappingTypeEClass = null;
+
+	/**
+	 * Creates an instance of the model <b>Package</b>, registered with
+	 * {@link org.eclipse.emf.ecore.EPackage.Registry EPackage.Registry} by the package
+	 * package URI value.
+	 * <p>Note: the correct way to create the package is via the static
+	 * factory method {@link #init init()}, which also performs
+	 * initialization of the package, or returns the registered package,
+	 * if one already exists.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see org.eclipse.emf.ecore.EPackage.Registry
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage#eNS_URI
+	 * @see #init()
+	 * @generated
+	 */
+	private PIConfigPackageImpl() {
+		super(eNS_URI, PIConfigFactory.eINSTANCE);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	private static boolean isInited = false;
+
+	/**
+	 * Creates, registers, and initializes the <b>Package</b> for this
+	 * model, and for any others upon which it depends.  Simple
+	 * dependencies are satisfied by calling this method on all
+	 * dependent packages before doing anything else.  This method drives
+	 * initialization for interdependent packages directly, in parallel
+	 * with this package, itself.
+	 * <p>Of this package and its interdependencies, all packages which
+	 * have not yet been registered by their URI values are first created
+	 * and registered.  The packages are then initialized in two steps:
+	 * meta-model objects for all of the packages are created before any
+	 * are initialized, since one package's meta-model objects may refer to
+	 * those of another.
+	 * <p>Invocation of this method will not affect any packages that have
+	 * already been initialized.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #eNS_URI
+	 * @see #createPackageContents()
+	 * @see #initializePackageContents()
+	 * @generated
+	 */
+	public static PIConfigPackage init() {
+		if (isInited) return (PIConfigPackage)EPackage.Registry.INSTANCE.getEPackage(PIConfigPackage.eNS_URI);
+
+		// Obtain or create and register package
+		PIConfigPackageImpl thePIConfigPackage = (PIConfigPackageImpl)(EPackage.Registry.INSTANCE.getEPackage(eNS_URI) instanceof PIConfigPackageImpl ? EPackage.Registry.INSTANCE.getEPackage(eNS_URI) : new PIConfigPackageImpl());
+
+		isInited = true;
+
+		// Initialize simple dependencies
+		XMLTypePackage.eINSTANCE.eClass();
+
+		// Create package meta-data objects
+		thePIConfigPackage.createPackageContents();
+
+		// Initialize created meta-data
+		thePIConfigPackage.initializePackageContents();
+
+		// Mark meta-data to indicate it can't be changed
+		thePIConfigPackage.freeze();
+
+		return thePIConfigPackage;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EClass getButtonEventProfileListType() {
+		return buttonEventProfileListTypeEClass;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EReference getButtonEventProfileListType_ButtonEventProfile() {
+		return (EReference)buttonEventProfileListTypeEClass.getEStructuralFeatures().get(0);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EAttribute getButtonEventProfileListType_ButtonEventProfileVersion() {
+		return (EAttribute)buttonEventProfileListTypeEClass.getEStructuralFeatures().get(1);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EClass getButtonEventProfileType() {
+		return buttonEventProfileTypeEClass;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EReference getButtonEventProfileType_Mapping() {
+		return (EReference)buttonEventProfileTypeEClass.getEStructuralFeatures().get(0);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EAttribute getButtonEventProfileType_ProfileId() {
+		return (EAttribute)buttonEventProfileTypeEClass.getEStructuralFeatures().get(1);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EClass getDocumentRoot() {
+		return documentRootEClass;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EAttribute getDocumentRoot_Mixed() {
+		return (EAttribute)documentRootEClass.getEStructuralFeatures().get(0);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EReference getDocumentRoot_XMLNSPrefixMap() {
+		return (EReference)documentRootEClass.getEStructuralFeatures().get(1);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EReference getDocumentRoot_XSISchemaLocation() {
+		return (EReference)documentRootEClass.getEStructuralFeatures().get(2);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EReference getDocumentRoot_ButtonEventProfileList() {
+		return (EReference)documentRootEClass.getEStructuralFeatures().get(3);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EClass getMappingType() {
+		return mappingTypeEClass;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EAttribute getMappingType_EnumString() {
+		return (EAttribute)mappingTypeEClass.getEStructuralFeatures().get(0);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EAttribute getMappingType_KeyCode() {
+		return (EAttribute)mappingTypeEClass.getEStructuralFeatures().get(1);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EAttribute getMappingType_Label() {
+		return (EAttribute)mappingTypeEClass.getEStructuralFeatures().get(2);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public PIConfigFactory getPIConfigFactory() {
+		return (PIConfigFactory)getEFactoryInstance();
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	private boolean isCreated = false;
+
+	/**
+	 * Creates the meta-model objects for the package.  This method is
+	 * guarded to have no affect on any invocation but its first.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void createPackageContents() {
+		if (isCreated) return;
+		isCreated = true;
+
+		// Create classes and their features
+		buttonEventProfileListTypeEClass = createEClass(BUTTON_EVENT_PROFILE_LIST_TYPE);
+		createEReference(buttonEventProfileListTypeEClass, BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE);
+		createEAttribute(buttonEventProfileListTypeEClass, BUTTON_EVENT_PROFILE_LIST_TYPE__BUTTON_EVENT_PROFILE_VERSION);
+
+		buttonEventProfileTypeEClass = createEClass(BUTTON_EVENT_PROFILE_TYPE);
+		createEReference(buttonEventProfileTypeEClass, BUTTON_EVENT_PROFILE_TYPE__MAPPING);
+		createEAttribute(buttonEventProfileTypeEClass, BUTTON_EVENT_PROFILE_TYPE__PROFILE_ID);
+
+		documentRootEClass = createEClass(DOCUMENT_ROOT);
+		createEAttribute(documentRootEClass, DOCUMENT_ROOT__MIXED);
+		createEReference(documentRootEClass, DOCUMENT_ROOT__XMLNS_PREFIX_MAP);
+		createEReference(documentRootEClass, DOCUMENT_ROOT__XSI_SCHEMA_LOCATION);
+		createEReference(documentRootEClass, DOCUMENT_ROOT__BUTTON_EVENT_PROFILE_LIST);
+
+		mappingTypeEClass = createEClass(MAPPING_TYPE);
+		createEAttribute(mappingTypeEClass, MAPPING_TYPE__ENUM_STRING);
+		createEAttribute(mappingTypeEClass, MAPPING_TYPE__KEY_CODE);
+		createEAttribute(mappingTypeEClass, MAPPING_TYPE__LABEL);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	private boolean isInitialized = false;
+
+	/**
+	 * Complete the initialization of the package and its meta-model.  This
+	 * method is guarded to have no affect on any invocation but its first.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void initializePackageContents() {
+		if (isInitialized) return;
+		isInitialized = true;
+
+		// Initialize package
+		setName(eNAME);
+		setNsPrefix(eNS_PREFIX);
+		setNsURI(eNS_URI);
+
+		// Obtain other dependent packages
+		XMLTypePackage theXMLTypePackage = (XMLTypePackage)EPackage.Registry.INSTANCE.getEPackage(XMLTypePackage.eNS_URI);
+
+		// Create type parameters
+
+		// Set bounds for type parameters
+
+		// Add supertypes to classes
+
+		// Initialize classes and features; add operations and parameters
+		initEClass(buttonEventProfileListTypeEClass, ButtonEventProfileListType.class, "ButtonEventProfileListType", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+		initEReference(getButtonEventProfileListType_ButtonEventProfile(), this.getButtonEventProfileType(), null, "buttonEventProfile", null, 0, -1, ButtonEventProfileListType.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+		initEAttribute(getButtonEventProfileListType_ButtonEventProfileVersion(), theXMLTypePackage.getDecimal(), "buttonEventProfileVersion", null, 0, 1, ButtonEventProfileListType.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+
+		initEClass(buttonEventProfileTypeEClass, ButtonEventProfileType.class, "ButtonEventProfileType", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+		initEReference(getButtonEventProfileType_Mapping(), this.getMappingType(), null, "mapping", null, 1, -1, ButtonEventProfileType.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+		initEAttribute(getButtonEventProfileType_ProfileId(), theXMLTypePackage.getString(), "profileId", null, 0, 1, ButtonEventProfileType.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+
+		initEClass(documentRootEClass, DocumentRoot.class, "DocumentRoot", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+		initEAttribute(getDocumentRoot_Mixed(), ecorePackage.getEFeatureMapEntry(), "mixed", null, 0, -1, null, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, !IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+		initEReference(getDocumentRoot_XMLNSPrefixMap(), ecorePackage.getEStringToStringMapEntry(), null, "xMLNSPrefixMap", null, 0, -1, null, IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+		initEReference(getDocumentRoot_XSISchemaLocation(), ecorePackage.getEStringToStringMapEntry(), null, "xSISchemaLocation", null, 0, -1, null, IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+		initEReference(getDocumentRoot_ButtonEventProfileList(), this.getButtonEventProfileListType(), null, "buttonEventProfileList", null, 0, -2, null, IS_TRANSIENT, IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, IS_DERIVED, IS_ORDERED);
+
+		initEClass(mappingTypeEClass, MappingType.class, "MappingType", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
+		initEAttribute(getMappingType_EnumString(), theXMLTypePackage.getString(), "enumString", null, 0, 1, MappingType.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+		initEAttribute(getMappingType_KeyCode(), theXMLTypePackage.getUnsignedInt(), "keyCode", null, 0, 1, MappingType.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+		initEAttribute(getMappingType_Label(), theXMLTypePackage.getString(), "label", null, 0, 1, MappingType.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+
+		// Create resource
+		createResource(eNS_URI);
+
+		// Create annotations
+		// http:///org/eclipse/emf/ecore/util/ExtendedMetaData
+		createExtendedMetaDataAnnotations();
+	}
+
+	/**
+	 * Initializes the annotations for <b>http:///org/eclipse/emf/ecore/util/ExtendedMetaData</b>.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	protected void createExtendedMetaDataAnnotations() {
+		String source = "http:///org/eclipse/emf/ecore/util/ExtendedMetaData";		
+		addAnnotation
+		  (this, 
+		   source, 
+		   new String[] {
+			 "qualified", "false"
+		   });		
+		addAnnotation
+		  (buttonEventProfileListTypeEClass, 
+		   source, 
+		   new String[] {
+			 "name", "buttonEventProfileList_._type",
+			 "kind", "elementOnly"
+		   });		
+		addAnnotation
+		  (getButtonEventProfileListType_ButtonEventProfile(), 
+		   source, 
+		   new String[] {
+			 "kind", "element",
+			 "name", "buttonEventProfile",
+			 "namespace", "##targetNamespace"
+		   });		
+		addAnnotation
+		  (getButtonEventProfileListType_ButtonEventProfileVersion(), 
+		   source, 
+		   new String[] {
+			 "kind", "attribute",
+			 "name", "buttonEventProfileVersion",
+			 "namespace", "##targetNamespace"
+		   });		
+		addAnnotation
+		  (buttonEventProfileTypeEClass, 
+		   source, 
+		   new String[] {
+			 "name", "buttonEventProfile_._type",
+			 "kind", "elementOnly"
+		   });		
+		addAnnotation
+		  (getButtonEventProfileType_Mapping(), 
+		   source, 
+		   new String[] {
+			 "kind", "element",
+			 "name", "mapping",
+			 "namespace", "##targetNamespace"
+		   });		
+		addAnnotation
+		  (getButtonEventProfileType_ProfileId(), 
+		   source, 
+		   new String[] {
+			 "kind", "attribute",
+			 "name", "profileId",
+			 "namespace", "##targetNamespace"
+		   });		
+		addAnnotation
+		  (documentRootEClass, 
+		   source, 
+		   new String[] {
+			 "name", "",
+			 "kind", "mixed"
+		   });		
+		addAnnotation
+		  (getDocumentRoot_Mixed(), 
+		   source, 
+		   new String[] {
+			 "kind", "elementWildcard",
+			 "name", ":mixed"
+		   });		
+		addAnnotation
+		  (getDocumentRoot_XMLNSPrefixMap(), 
+		   source, 
+		   new String[] {
+			 "kind", "attribute",
+			 "name", "xmlns:prefix"
+		   });		
+		addAnnotation
+		  (getDocumentRoot_XSISchemaLocation(), 
+		   source, 
+		   new String[] {
+			 "kind", "attribute",
+			 "name", "xsi:schemaLocation"
+		   });		
+		addAnnotation
+		  (getDocumentRoot_ButtonEventProfileList(), 
+		   source, 
+		   new String[] {
+			 "kind", "element",
+			 "name", "buttonEventProfileList",
+			 "namespace", "##targetNamespace"
+		   });		
+		addAnnotation
+		  (mappingTypeEClass, 
+		   source, 
+		   new String[] {
+			 "name", "mapping_._type",
+			 "kind", "empty"
+		   });		
+		addAnnotation
+		  (getMappingType_EnumString(), 
+		   source, 
+		   new String[] {
+			 "kind", "attribute",
+			 "name", "enumString",
+			 "namespace", "##targetNamespace"
+		   });		
+		addAnnotation
+		  (getMappingType_KeyCode(), 
+		   source, 
+		   new String[] {
+			 "kind", "attribute",
+			 "name", "keyCode",
+			 "namespace", "##targetNamespace"
+		   });		
+		addAnnotation
+		  (getMappingType_Label(), 
+		   source, 
+		   new String[] {
+			 "kind", "attribute",
+			 "name", "label",
+			 "namespace", "##targetNamespace"
+		   });
+	}
+
+} //PIConfigPackageImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/util/PIConfigAdapterFactory.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig.util;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl;
+import org.eclipse.emf.ecore.EObject;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileListType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.DocumentRoot;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.MappingType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigPackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Adapter Factory</b> for the model.
+ * It provides an adapter <code>createXXX</code> method for each class of the model.
+ * <!-- end-user-doc -->
+ * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage
+ * @generated
+ */
+public class PIConfigAdapterFactory extends AdapterFactoryImpl {
+	/**
+	 * The cached model package.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	protected static PIConfigPackage modelPackage;
+
+	/**
+	 * Creates an instance of the adapter factory.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public PIConfigAdapterFactory() {
+		if (modelPackage == null) {
+			modelPackage = PIConfigPackage.eINSTANCE;
+		}
+	}
+
+	/**
+	 * Returns whether this factory is applicable for the type of the object.
+	 * <!-- begin-user-doc -->
+	 * This implementation returns <code>true</code> if the object is either the model's package or is an instance object of the model.
+	 * <!-- end-user-doc -->
+	 * @return whether this factory is applicable for the type of the object.
+	 * @generated
+	 */
+	@Override
+	public boolean isFactoryForType(Object object) {
+		if (object == modelPackage) {
+			return true;
+		}
+		if (object instanceof EObject) {
+			return ((EObject)object).eClass().getEPackage() == modelPackage;
+		}
+		return false;
+	}
+
+	/**
+	 * The switch that delegates to the <code>createXXX</code> methods.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	protected PIConfigSwitch<Adapter> modelSwitch =
+		new PIConfigSwitch<Adapter>() {
+			@Override
+			public Adapter caseButtonEventProfileListType(ButtonEventProfileListType object) {
+				return createButtonEventProfileListTypeAdapter();
+			}
+			@Override
+			public Adapter caseButtonEventProfileType(ButtonEventProfileType object) {
+				return createButtonEventProfileTypeAdapter();
+			}
+			@Override
+			public Adapter caseDocumentRoot(DocumentRoot object) {
+				return createDocumentRootAdapter();
+			}
+			@Override
+			public Adapter caseMappingType(MappingType object) {
+				return createMappingTypeAdapter();
+			}
+			@Override
+			public Adapter defaultCase(EObject object) {
+				return createEObjectAdapter();
+			}
+		};
+
+	/**
+	 * Creates an adapter for the <code>target</code>.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param target the object to adapt.
+	 * @return the adapter for the <code>target</code>.
+	 * @generated
+	 */
+	@Override
+	public Adapter createAdapter(Notifier target) {
+		return modelSwitch.doSwitch((EObject)target);
+	}
+
+
+	/**
+	 * Creates a new adapter for an object of class '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileListType <em>Button Event Profile List Type</em>}'.
+	 * <!-- begin-user-doc -->
+	 * This default implementation returns null so that we can easily ignore cases;
+	 * it's useful to ignore a case when inheritance will catch all the cases anyway.
+	 * <!-- end-user-doc -->
+	 * @return the new adapter.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileListType
+	 * @generated
+	 */
+	public Adapter createButtonEventProfileListTypeAdapter() {
+		return null;
+	}
+
+	/**
+	 * Creates a new adapter for an object of class '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType <em>Button Event Profile Type</em>}'.
+	 * <!-- begin-user-doc -->
+	 * This default implementation returns null so that we can easily ignore cases;
+	 * it's useful to ignore a case when inheritance will catch all the cases anyway.
+	 * <!-- end-user-doc -->
+	 * @return the new adapter.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.ButtonEventProfileType
+	 * @generated
+	 */
+	public Adapter createButtonEventProfileTypeAdapter() {
+		return null;
+	}
+
+	/**
+	 * Creates a new adapter for an object of class '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot <em>Document Root</em>}'.
+	 * <!-- begin-user-doc -->
+	 * This default implementation returns null so that we can easily ignore cases;
+	 * it's useful to ignore a case when inheritance will catch all the cases anyway.
+	 * <!-- end-user-doc -->
+	 * @return the new adapter.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.DocumentRoot
+	 * @generated
+	 */
+	public Adapter createDocumentRootAdapter() {
+		return null;
+	}
+
+	/**
+	 * Creates a new adapter for an object of class '{@link com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType <em>Mapping Type</em>}'.
+	 * <!-- begin-user-doc -->
+	 * This default implementation returns null so that we can easily ignore cases;
+	 * it's useful to ignore a case when inheritance will catch all the cases anyway.
+	 * <!-- end-user-doc -->
+	 * @return the new adapter.
+	 * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.MappingType
+	 * @generated
+	 */
+	public Adapter createMappingTypeAdapter() {
+		return null;
+	}
+
+	/**
+	 * Creates a new adapter for the default case.
+	 * <!-- begin-user-doc -->
+	 * This default implementation returns null.
+	 * <!-- end-user-doc -->
+	 * @return the new adapter.
+	 * @generated
+	 */
+	public Adapter createEObjectAdapter() {
+		return null;
+	}
+
+} //PIConfigAdapterFactory
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/util/PIConfigResourceFactoryImpl.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig.util;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.impl.EPackageRegistryImpl;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.impl.ResourceFactoryImpl;
+import org.eclipse.emf.ecore.util.BasicExtendedMetaData;
+import org.eclipse.emf.ecore.util.ExtendedMetaData;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigPackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Resource Factory</b> associated with the package.
+ * <!-- end-user-doc -->
+ * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.util.PIConfigResourceImpl
+ * @generated
+ */
+public class PIConfigResourceFactoryImpl extends ResourceFactoryImpl {
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	protected ExtendedMetaData extendedMetaData;
+
+	/**
+	 * Creates an instance of the resource factory.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public PIConfigResourceFactoryImpl() {
+		super();
+		extendedMetaData = new BasicExtendedMetaData(new EPackageRegistryImpl(EPackage.Registry.INSTANCE));
+		extendedMetaData.putPackage(null, PIConfigPackage.eINSTANCE);
+	}
+
+	/**
+	 * Creates an instance of the resource.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public Resource createResource(URI uri) {
+		XMLResource result = new PIConfigResourceImpl(uri);
+		result.getDefaultSaveOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, extendedMetaData);
+		result.getDefaultLoadOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, extendedMetaData);
+
+		result.getDefaultSaveOptions().put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
+
+		result.getDefaultLoadOptions().put(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE, Boolean.TRUE);
+		result.getDefaultSaveOptions().put(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE, Boolean.TRUE);
+
+		result.getDefaultLoadOptions().put(XMLResource.OPTION_USE_LEXICAL_HANDLER, Boolean.TRUE);
+		return result;
+	}
+
+} //PIConfigResourceFactoryImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/util/PIConfigResourceImpl.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig.util;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Resource </b> associated with the package.
+ * <!-- end-user-doc -->
+ * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.util.PIConfigResourceFactoryImpl
+ * @generated
+ */
+public class PIConfigResourceImpl extends XMLResourceImpl {
+	/**
+	 * Creates an instance of the resource.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param uri the URI of the new resource.
+	 * @generated
+	 */
+	public PIConfigResourceImpl(URI uri) {
+		super(uri);
+	}
+
+} //PIConfigResourceImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/util/PIConfigSwitch.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig.util;
+
+import java.util.List;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileListType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.DocumentRoot;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.MappingType;
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigPackage;
+
+/**
+ * <!-- begin-user-doc -->
+ * The <b>Switch</b> for the model's inheritance hierarchy.
+ * It supports the call {@link #doSwitch(EObject) doSwitch(object)}
+ * to invoke the <code>caseXXX</code> method for each class of the model,
+ * starting with the actual class of the object
+ * and proceeding up the inheritance hierarchy
+ * until a non-null result is returned,
+ * which is the result of the switch.
+ * <!-- end-user-doc -->
+ * @see com.nokia.carbide.cpp.pi.util.config.gen.PIConfig.PIConfigPackage
+ * @generated
+ */
+public class PIConfigSwitch<T> {
+	/**
+	 * The cached model package
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	protected static PIConfigPackage modelPackage;
+
+	/**
+	 * Creates an instance of the switch.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public PIConfigSwitch() {
+		if (modelPackage == null) {
+			modelPackage = PIConfigPackage.eINSTANCE;
+		}
+	}
+
+	/**
+	 * Calls <code>caseXXX</code> for each class of the model until one returns a non null result; it yields that result.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the first non-null result returned by a <code>caseXXX</code> call.
+	 * @generated
+	 */
+	public T doSwitch(EObject theEObject) {
+		return doSwitch(theEObject.eClass(), theEObject);
+	}
+
+	/**
+	 * Calls <code>caseXXX</code> for each class of the model until one returns a non null result; it yields that result.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the first non-null result returned by a <code>caseXXX</code> call.
+	 * @generated
+	 */
+	protected T doSwitch(EClass theEClass, EObject theEObject) {
+		if (theEClass.eContainer() == modelPackage) {
+			return doSwitch(theEClass.getClassifierID(), theEObject);
+		}
+		else {
+			List<EClass> eSuperTypes = theEClass.getESuperTypes();
+			return
+				eSuperTypes.isEmpty() ?
+					defaultCase(theEObject) :
+					doSwitch(eSuperTypes.get(0), theEObject);
+		}
+	}
+
+	/**
+	 * Calls <code>caseXXX</code> for each class of the model until one returns a non null result; it yields that result.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the first non-null result returned by a <code>caseXXX</code> call.
+	 * @generated
+	 */
+	protected T doSwitch(int classifierID, EObject theEObject) {
+		switch (classifierID) {
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_LIST_TYPE: {
+				ButtonEventProfileListType buttonEventProfileListType = (ButtonEventProfileListType)theEObject;
+				T result = caseButtonEventProfileListType(buttonEventProfileListType);
+				if (result == null) result = defaultCase(theEObject);
+				return result;
+			}
+			case PIConfigPackage.BUTTON_EVENT_PROFILE_TYPE: {
+				ButtonEventProfileType buttonEventProfileType = (ButtonEventProfileType)theEObject;
+				T result = caseButtonEventProfileType(buttonEventProfileType);
+				if (result == null) result = defaultCase(theEObject);
+				return result;
+			}
+			case PIConfigPackage.DOCUMENT_ROOT: {
+				DocumentRoot documentRoot = (DocumentRoot)theEObject;
+				T result = caseDocumentRoot(documentRoot);
+				if (result == null) result = defaultCase(theEObject);
+				return result;
+			}
+			case PIConfigPackage.MAPPING_TYPE: {
+				MappingType mappingType = (MappingType)theEObject;
+				T result = caseMappingType(mappingType);
+				if (result == null) result = defaultCase(theEObject);
+				return result;
+			}
+			default: return defaultCase(theEObject);
+		}
+	}
+
+	/**
+	 * Returns the result of interpreting the object as an instance of '<em>Button Event Profile List Type</em>'.
+	 * <!-- begin-user-doc -->
+	 * This implementation returns null;
+	 * returning a non-null result will terminate the switch.
+	 * <!-- end-user-doc -->
+	 * @param object the target of the switch.
+	 * @return the result of interpreting the object as an instance of '<em>Button Event Profile List Type</em>'.
+	 * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+	 * @generated
+	 */
+	public T caseButtonEventProfileListType(ButtonEventProfileListType object) {
+		return null;
+	}
+
+	/**
+	 * Returns the result of interpreting the object as an instance of '<em>Button Event Profile Type</em>'.
+	 * <!-- begin-user-doc -->
+	 * This implementation returns null;
+	 * returning a non-null result will terminate the switch.
+	 * <!-- end-user-doc -->
+	 * @param object the target of the switch.
+	 * @return the result of interpreting the object as an instance of '<em>Button Event Profile Type</em>'.
+	 * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+	 * @generated
+	 */
+	public T caseButtonEventProfileType(ButtonEventProfileType object) {
+		return null;
+	}
+
+	/**
+	 * Returns the result of interpreting the object as an instance of '<em>Document Root</em>'.
+	 * <!-- begin-user-doc -->
+	 * This implementation returns null;
+	 * returning a non-null result will terminate the switch.
+	 * <!-- end-user-doc -->
+	 * @param object the target of the switch.
+	 * @return the result of interpreting the object as an instance of '<em>Document Root</em>'.
+	 * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+	 * @generated
+	 */
+	public T caseDocumentRoot(DocumentRoot object) {
+		return null;
+	}
+
+	/**
+	 * Returns the result of interpreting the object as an instance of '<em>Mapping Type</em>'.
+	 * <!-- begin-user-doc -->
+	 * This implementation returns null;
+	 * returning a non-null result will terminate the switch.
+	 * <!-- end-user-doc -->
+	 * @param object the target of the switch.
+	 * @return the result of interpreting the object as an instance of '<em>Mapping Type</em>'.
+	 * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
+	 * @generated
+	 */
+	public T caseMappingType(MappingType object) {
+		return null;
+	}
+
+	/**
+	 * Returns the result of interpreting the object as an instance of '<em>EObject</em>'.
+	 * <!-- begin-user-doc -->
+	 * This implementation returns null;
+	 * returning a non-null result will terminate the switch, but this is the last case anyway.
+	 * <!-- end-user-doc -->
+	 * @param object the target of the switch.
+	 * @return the result of interpreting the object as an instance of '<em>EObject</em>'.
+	 * @see #doSwitch(org.eclipse.emf.ecore.EObject)
+	 * @generated
+	 */
+	public T defaultCase(EObject object) {
+		return null;
+	}
+
+} //PIConfigSwitch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/internal/pi/util/config/gen/PIConfig/util/PIConfigXMLProcessor.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.util.config.gen.PIConfig.util;
+
+import java.util.Map;
+
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.impl.EPackageRegistryImpl;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.xmi.util.XMLProcessor;
+
+import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigPackage;
+
+/**
+ * This class contains helper methods to serialize and deserialize XML documents
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated
+ */
+public class PIConfigXMLProcessor extends XMLProcessor {
+
+	/**
+	 * Public constructor to instantiate the helper.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public PIConfigXMLProcessor() {
+		super(new EPackageRegistryImpl(EPackage.Registry.INSTANCE));
+		extendedMetaData.putPackage(null, PIConfigPackage.eINSTANCE);
+	}
+	
+	/**
+	 * Register for "*" and "xml" file extensions the PIConfigResourceFactoryImpl factory.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	protected Map<String, Resource.Factory> getRegistrations() {
+		if (registrations == null) {
+			super.getRegistrations();
+			registrations.put(XML_EXTENSION, new PIConfigResourceFactoryImpl());
+			registrations.put(STAR_EXTENSION, new PIConfigResourceFactoryImpl());
+		}
+		return registrations;
+	}
+
+} //PIConfigXMLProcessor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/AWTColorPalette.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * Class for managing all Color resource for PI
+ * 
+ */
+
+public class AWTColorPalette {
+
+	private static CacheMap<RGB, java.awt.Color> palette = new CacheMap<RGB, java.awt.Color>();
+	
+	private static AWTColorPalette colorPalette = null;
+
+	private AWTColorPalette() {
+		// private so we can't new ColorPalette
+		// user getInstance() to access this class
+	}
+	
+	public static AWTColorPalette getInstance() {
+		if (colorPalette == null)
+	    {
+	    	colorPalette = new AWTColorPalette();
+	    }
+	    return colorPalette;		
+	}
+
+	public static void add(RGB rgb) {
+		synchronized(palette) {
+			palette.put(new RGB(rgb.red, rgb.green, rgb.blue), new java.awt.Color(rgb.red, rgb.green, rgb.blue));
+		}
+	}
+
+	public static java.awt.Color getColor(RGB rgb) {
+		synchronized(palette) {
+			if (palette.get(rgb) == null) {
+				add(rgb);
+			}
+			return (java.awt.Color) palette.get(rgb);
+		}
+	}
+
+	public static int size() {
+		return palette.size();
+	}
+
+	public static void dispose() {
+		// CacheMap.dispose() is going to free up resource
+		palette.dispose();
+	}
+	
+	protected void finalize() {
+		palette.dispose();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/BinaryColorPalette.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import org.eclipse.core.runtime.Path;
+import org.eclipse.swt.graphics.RGB;
+
+public class BinaryColorPalette extends TableColorPalette {
+
+	@Override
+	public RGB getConstantRGB(Object entry) {
+		assert (entry instanceof String);
+		String bin_name = new Path((String)entry).lastSegment().toLowerCase();
+
+		// EKA1 kernel
+		// Gray out Symbian kernel so user can look at their apps without Idle
+		if (bin_name.equals("ekern") || bin_name.equals("ekern.exe")) { //$NON-NLS-1$ //$NON-NLS-2$
+	    	return new RGB(192, 192, 192); // AWT Color.lightGray
+		}
+
+		// EKA2 kernel
+		// Gray out Symbian ekern so user can look at their apps without Idle
+		if (bin_name.startsWith("_reka2_")) { //$NON-NLS-1$
+			return new RGB(192, 192, 192); // AWT Color.lightGray
+		}
+
+		// CarbideProf
+		// Gray out Profiler so user can look at their apps without Idle
+		if (bin_name.startsWith("carbideprof")) { //$NON-NLS-1$
+			return new RGB(192, 192, 192); // AWT Color.lightGray
+		}
+
+		// CarbidePI
+		// Gray out Profiler so user can look at their apps without Idle
+		if (bin_name.startsWith("carbidepi")) { //$NON-NLS-1$
+			return new RGB(192, 192, 192); // AWT Color.lightGray
+		}
+
+		// default binary not found
+		if (bin_name.startsWith("binary not found")) { //$NON-NLS-1$
+			return new RGB(64, 64, 64);	// AWT Color.darkGray
+		}
+
+		return null;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/CacheMap.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+// import for com.nokai.sdt.utils
+//package com.nokia.sdt.utils;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.swt.graphics.Resource;
+
+/**
+ * Map-like class for managing disposable objects.
+ * <p>
+ * Entries are accessed via keys.  When the map is 
+ * released, all entries are released.  If entries
+ * implement IDisposable or like interfaces, we call
+ * their dispose() methods.  Null values are not allowed.
+ */
+public class CacheMap<K,V> implements IDisposable {
+	
+	private Map<Object,Object> map = new HashMap<Object,Object> ();
+
+    public Set keySet() {
+        return map.keySet();
+    }
+    
+	public void put(Object key, Object value) {
+		//Check.checkArg(value);
+		synchronized(map) {
+			map.put(key, value);
+		}
+	}
+	
+	public Object get(Object key) {
+		Object result;
+		synchronized(map) {
+			result = map.get(key);
+		}
+		return result;
+	}
+	
+	public void remove(Object key) {
+		synchronized(map) {
+			map.remove(key);
+		}
+	}
+	
+	public void dispose() {
+		if (map != null) {
+			// object should no longer be used after IDisposable.dispose
+			disposeAll();
+			map = null;
+		}
+	}
+	
+    private void disposeObject(Object value) {
+        if (value instanceof IDisposable) {
+            IDisposable disposable = (IDisposable) value;
+            disposable.dispose();
+        }
+        else if (value instanceof Resource) {
+        	Resource r = (Resource) value;
+        	r.dispose();
+        }
+    }
+    
+	public void disposeItem(Object key) {
+		Object item;
+		synchronized(map) {
+			item = map.remove(key);
+		}
+		if (item != null)
+            disposeObject(item);
+	}
+	
+	public void disposeAll() {
+		synchronized(map) {
+			for (Iterator iter = map.values().iterator(); iter.hasNext();) {
+				Object element = iter.next();
+                disposeObject(element);
+			}
+			map.clear();
+		}
+	}
+	
+	public int size() {
+		return map.size();
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/ColorPalette.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Class for managing all Color resource for PI
+ * 
+ */
+
+public class ColorPalette {
+
+	private static CacheMap<RGB, Color> palette = new CacheMap<RGB, Color>();
+	
+	private static ColorPalette colorPalette = null;
+
+	private ColorPalette() {
+		// private so we can't new ColorPalette
+		// user getInstance() to access this class
+	}
+	
+	public static ColorPalette getInstance() {
+		if (colorPalette == null)
+	    {
+	    	colorPalette = new ColorPalette();
+	    }
+	    return colorPalette;		
+	}
+
+	public static void add(RGB rgb) {
+		synchronized(palette) {
+			palette.put(new RGB(rgb.red, rgb.green, rgb.blue), new Color(Display.getCurrent(), rgb));
+		}
+	}
+
+	public static Color getColor(RGB rgb) {
+		synchronized(palette) {
+			if (palette.get(rgb) == null) {
+				add(rgb);
+			}
+			return (Color) palette.get(rgb);
+		}
+	}
+
+	public static int size() {
+		return palette.size();
+	}
+
+	public static void dispose() {
+		// CacheMap.dispose() is going to free up resource
+		palette.dispose();
+	}
+	
+	protected void finalize() {
+		palette.dispose();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/DataMiningPalette.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.ColorDialog;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+
+public class DataMiningPalette {
+
+	private Map<Object, RGB> palette = new HashMap<Object, RGB>();
+
+	private boolean haveEntry(Object entry) {
+		return palette.containsKey(entry);
+	}
+
+	private boolean haveColor(RGB color) {
+		return palette.containsValue(color);
+	}
+
+	private void add(Object entry, RGB color) {
+		palette.put(entry, color);
+	}
+
+	private void update(Object entry, RGB color) {
+		palette.remove(entry);
+		palette.put(entry, color);
+	}
+
+	private RGB hsv2rgb(int hue, double saturation, double value) {
+
+		if (hue >= 360)
+			hue %= 360;
+		int Hi = (hue / 60) % 6;
+		double f = (double) hue / (double) 60 - Hi;
+
+		int p = (int) ((value * (1 - saturation)) * 255);
+		int q = (int) ((value * (1 - f * saturation)) * 255);
+		int t = (int) ((value * (1 - (1 - f) * saturation)) * 255);
+		int V = (int) (value * 255);
+
+		switch (Hi) {
+		case 0:
+			return (new RGB(V, t, p));
+		case 1:
+			return (new RGB(q, V, p));
+		case 2:
+			return (new RGB(p, V, t));
+		case 3:
+			return (new RGB(p, q, V));
+		case 4:
+			return (new RGB(t, p, V));
+		case 5:
+			return (new RGB(V, p, q));
+		}
+		return (new RGB(0, 0, 0));
+	}
+
+	// returns if recolor of palette on specific entry if successful
+	public boolean recolorEntryDialog(Shell parent, Object entry) {
+		ColorDialog colorDialog = new ColorDialog(parent, SWT.NONE);
+		colorDialog.setRGB(new RGB(255, 255, 255));
+		RGB newRGB = colorDialog.open();
+		if (newRGB != null) {
+			if (haveColor(newRGB)) {
+				MessageBox errorDialog = new MessageBox(parent, SWT.ICON_ERROR
+						| SWT.OK);
+				errorDialog.setText(Messages
+						.getString("DataMiningPalette.change.denied")); //$NON-NLS-1$
+				errorDialog.setMessage(Messages
+						.getString("DataMiningPalette.color.exist")); //$NON-NLS-1$
+				errorDialog.open();
+			}
+			if (!haveEntry(entry)) {
+				MessageBox errorDialog = new MessageBox(parent, SWT.ICON_ERROR
+						| SWT.OK);
+				errorDialog.setText(Messages
+						.getString("DataMiningPalette.change.denied")); //$NON-NLS-1$
+				errorDialog
+						.setMessage(Messages
+								.getString("DataMiningPalette.item.does.not.exist.in.palette")); //$NON-NLS-1$
+				errorDialog.open();
+			}
+			update(entry, newRGB);
+			return true;
+		}
+		return false;
+	}
+
+	public RGB getRGB(Object entry) {
+//		if (!haveEntry(entry)) {
+//		}
+		return palette.get(entry);
+	}
+
+	public void assignSOSColor(List entryList) {
+//		if (entryList.size() > 256) {
+//			// We only want to reserve 216 color web-safe palette to SOS
+//			// thread/binary
+//		}
+		// Web-safe palette is a permuation of 0x00,0x33,0x66,0x99,0xCC,0xFF in
+		// RGB
+		int channelValue[] = { 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF };
+		
+		Iterator entryListItr = entryList.iterator();
+
+		Object entry = entryListItr.next();
+
+		for (int i = 0; i < 216; i++)
+		{
+			
+//			if (haveEntry(entry)) {
+//			}
+					
+			int index = i / 3 + (i % 3) * 72;
+			int indexR = index % 6;
+			int indexG = (index / 6) % 6;
+			int indexB = (index / 36) % 6;
+			
+			RGB myRGB = new RGB(channelValue[indexR], channelValue[indexG], channelValue[indexB]);
+
+			if (haveColor(myRGB))
+				continue;
+
+			add(entry, myRGB);
+			
+			if (!entryListItr.hasNext())
+				return;
+			else
+				entry = entryListItr.next();
+		}
+	}
+
+	/*
+	 * 
+	 * Use H and S (V = S) in HSV for different colors Attempt to evenly divide
+	 * into even amount of H circle, with different layer of S depth
+	 * 
+	 */
+
+	public void assignColor(List entryList) {
+		final double maxSaturation = 1;
+		final double minSaturation = 0.5;
+
+		// red, orange, yellow, green, cyan, blue, magenta
+		int hueEntry[] = { 0, 30, 60, 120, 180, 240, 300 };
+
+		double saturation = maxSaturation;
+		Iterator entryListItr = entryList.iterator();
+
+		Object entry = entryListItr.next();
+		int remain = entryList.size();
+
+		while (saturation > minSaturation && entryListItr.hasNext()) {
+
+			for (int i = 0; i < hueEntry.length; i++) {
+				
+//				if (haveEntry(entry)) {
+//				}
+
+				RGB myRGB = hsv2rgb(hueEntry[i], saturation, saturation);
+
+				if (haveColor(myRGB))
+					continue;
+
+				add(entry, myRGB);
+				--remain;
+
+				if (!entryListItr.hasNext())
+					return;
+				else
+					entry = entryListItr.next();
+			}
+
+			// Figure out size of S layer by expected layers + 1
+			// Always saving one layer in case we see more overlapping color
+			int expected_layers = (int) Math.ceil((double) (remain)
+					/ (double) hueEntry.length);
+			saturation -= (saturation - minSaturation) / (expected_layers + 1);
+		}
+
+//		if (entryList.size() != palette.size()) {
+//		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/FunctionColorPalette.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import org.eclipse.swt.graphics.RGB;
+
+public class FunctionColorPalette extends TableColorPalette {
+
+	@Override
+	public RGB getConstantRGB(Object entry) {
+		assert (entry instanceof String);
+		String func_name = ((String)entry).toLowerCase();
+		
+		// Gray out HAL Idle and RestoreIrqs that most of the empty cycle are spun
+		if (func_name.startsWith("imphal::idle")) { //$NON-NLS-1$
+	    	return new RGB(192,192,192); // AWT Color.lightGray
+		}
+		if (func_name.startsWith("imphal::restoreirqs")) { //$NON-NLS-1$
+	    	return new RGB(192,192,192); // AWT Color.lightGray
+		}
+		
+		// EKA2
+		if (func_name.startsWith("nkern::restoreinterrupts") || //$NON-NLS-1$
+				func_name.startsWith("a::nullthread") || //$NON-NLS-1$
+				func_name.startsWith("kernelmain") || //$NON-NLS-1$
+				func_name.contains("::cpuidle()") || //$NON-NLS-1$
+				func_name.startsWith("nkern::disableallinterrupts()") || //$NON-NLS-1$
+				func_name.startsWith("ntimerq::timeraddress")) { //$NON-NLS-1$
+	    	return new RGB(192,192,192); // AWT Color.lightGray			
+		}
+		
+		// default function not found
+		if (func_name.startsWith("function not found_")) { //$NON-NLS-1$
+			return new RGB(64, 64, 64);	// AWT Color.darkGray
+		}
+		
+	    return null;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/GeneralMessages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.cpp.internal.api.utils.core.Logging;
+
+/* This GeneralMessage displays message box using synchronized run
+ * from the UI thread, so it is safe to be called by non-UI thread 
+ * */
+
+public class GeneralMessages 
+{
+	public static final int OK = IStatus.OK;
+	public static final int INFO = IStatus.INFO;
+	public static final int WARNING = IStatus.WARNING;
+	public static final int ERROR = IStatus.ERROR;
+	public static final int CANCEL = IStatus.CANCEL;
+	public static final int USERDUMP = 0xff;
+	
+	static boolean result = false;
+	
+	public static void showErrorMessage(final String error) {
+		Display.getDefault().syncExec( new Runnable() {
+			public void run () {
+				String displayMessage;
+				MessageBox messageBox = new MessageBox(
+						PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+						SWT.ICON_ERROR | SWT.OK | SWT.SYSTEM_MODAL);
+				if (error == null)
+					displayMessage = Messages.getString("GeneralMessages.unknownError"); //$NON-NLS-1$
+				else
+					displayMessage = error;
+				messageBox.setMessage(displayMessage);
+				messageBox.setText(Messages.getString("GeneralMessages.piError")); //$NON-NLS-1$
+				messageBox.open();				
+			}
+		});
+	}
+
+	public static void showNotificationMessage(final String notification) {
+		Display.getDefault().syncExec( new Runnable() {
+			public void run () {
+				MessageBox messageBox = new MessageBox(
+						PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+						SWT.ICON_INFORMATION | SWT.OK | SWT.SYSTEM_MODAL);
+				messageBox.setMessage(notification);
+				messageBox.setText(Messages.getString("GeneralMessages.piMessage")); //$NON-NLS-1$
+				messageBox.open();
+			}
+		});
+	}
+
+	public static void showWarningMessage(final String notification) {
+		Display.getDefault().syncExec( new Runnable() {
+			public void run () {
+				MessageBox messageBox = new MessageBox(
+						PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+						SWT.ICON_WARNING | SWT.OK | SWT.SYSTEM_MODAL);
+				messageBox.setMessage(notification);
+				messageBox.setText(Messages.getString("GeneralMessages.piWarning")); //$NON-NLS-1$
+				messageBox.open();
+			}
+		});
+	}
+
+	public static boolean showProblemMessage(final String problem) {
+		Display.getDefault().syncExec( new Runnable() {
+			public void run () {
+				MessageBox messageBox = new MessageBox(
+						PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+						SWT.ICON_WARNING | SWT.OK | SWT.CANCEL | SWT.SYSTEM_MODAL);
+				messageBox.setMessage(problem);
+				messageBox.setText(Messages.getString("GeneralMessages.piWarning")); //$NON-NLS-1$
+				int returnCode = messageBox.open();
+
+				if (returnCode == SWT.CANCEL) {
+					System.out.println(Messages.getString("GeneralMessages.cancel")); //$NON-NLS-1$
+					result = false;
+				} else {
+					System.out.println(Messages.getString("GeneralMessages.ok")); //$NON-NLS-1$
+					result = true;
+				}
+			}
+		});
+		return result;
+	}
+
+	public static boolean showQuestionMessage(final String question)
+	{
+		Display.getDefault().syncExec( new Runnable() {
+			public void run () {
+				MessageBox messageBox = new MessageBox(
+						PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+						SWT.ICON_QUESTION | SWT.YES | SWT.NO | SWT.SYSTEM_MODAL);
+				messageBox.setMessage(question);
+				messageBox.setText(Messages.getString("GeneralMessages.piMessage")); //$NON-NLS-1$
+				int returnCode = messageBox.open();
+
+				if (returnCode == SWT.NO) {
+					System.out.println(Messages.getString("GeneralMessages.no")); //$NON-NLS-1$
+					result = false;					
+				} else {
+					System.out.println(Messages.getString("GeneralMessages.yes")); //$NON-NLS-1$
+					result = true;
+				}
+			}
+		});
+		return result;
+	}
+	
+	public static void PiLog(String message, int severity) {
+		PiLog(message, severity, new Throwable());
+	}
+	
+	public static void PiLog(String message, int severity, Throwable throwable) {
+
+		switch (severity) {
+			case IStatus.OK:
+			case IStatus.INFO:
+			case IStatus.WARNING:
+			case IStatus.ERROR:
+			case IStatus.CANCEL:
+				break;
+			case GeneralMessages.USERDUMP:
+				severity = IStatus.INFO;
+			default:
+				severity = IStatus.ERROR;
+				break;
+		}
+	
+		IStatus status = Logging.newSimpleStatus(1 /* our caller */, 
+				severity, 
+                Messages.getString("GeneralMessages.pi") + message, //$NON-NLS-1$
+                throwable);
+		Logging.log(PIUtilPlugin.getDefault(), status);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/GuessAndFixPath.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+// Sometime Symbian files are referring everything as root relative,
+// sometime there is reference to $(EPOCROOT) too
+// let's try to guess what it was. I hate windows drive letter
+
+public class GuessAndFixPath {
+	public static String fixPath(String path, String epocroot, String fileInPath) {
+		if (path.charAt(0) != '\\')
+			return path;
+
+		// currently what we get from the final .PKG seems to referring root directory
+		// to the root of the drive that EPOCROOT is on
+		if (path.substring(0, 11).equalsIgnoreCase("$(EPOCROOT)")) { //$NON-NLS-1$
+			return path.replace("\\$(EPOCROOT)", epocroot); //$NON-NLS-1$
+		}
+
+		String rootOfEpocRoot;
+
+		if (epocroot.indexOf('\\') > 0) {
+			// remove trailling '\\'
+			if (epocroot.endsWith("\\")) //$NON-NLS-1$
+			{
+				rootOfEpocRoot = epocroot.substring(0, epocroot.lastIndexOf('\\'));
+			}
+			else {
+				rootOfEpocRoot = epocroot;
+			}
+		} else {
+			rootOfEpocRoot = ""; //$NON-NLS-1$
+		}
+		return rootOfEpocRoot + path;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/IDisposable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+// imported from com.nokia.sdt.utils
+//package com.nokia.sdt.utils;
+
+/**
+ * Generic interface for disposable objects
+ *
+ */
+public interface IDisposable {
+
+/**
+ * Disposes of any resources held by the object.
+ * The object should not be used after dispose has been called.
+ */
+void dispose();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/ITableColorPalette.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import org.eclipse.swt.graphics.RGB;
+
+// Trace dependent way to get default color for SOS thread/binary/function
+public interface ITableColorPalette {
+	RGB getConstantRGB(Object entry);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.util.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/PIExceptionRuntime.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+public class PIExceptionRuntime extends RuntimeException{
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 5209871199262340065L;
+	
+	public PIExceptionRuntime () {
+		super();
+	}
+	
+	public PIExceptionRuntime (String message) {
+		super(message);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/PIUtilPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import org.eclipse.core.runtime.Plugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class PIUtilPlugin extends Plugin {
+
+	public static final String PLUGIN_ID = "com.nokia.carbide.cpp.pi.ui"; //$NON-NLS-1$
+
+	//The shared instance.
+	private static PIUtilPlugin plugin;
+
+	private static void setPlugin(PIUtilPlugin newPlugin)
+	{
+		plugin = newPlugin;
+	}
+
+	/**
+	 * The constructor.
+	 */
+	public PIUtilPlugin() {
+		setPlugin(this);
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		setPlugin(null);
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static PIUtilPlugin getDefault() {
+		return plugin;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/SourceLookup.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.dom.ILinkage;
+import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
+import org.eclipse.cdt.core.dom.ast.DOMException;
+import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
+import org.eclipse.cdt.core.dom.ast.IFunction;
+import org.eclipse.cdt.core.dom.ast.IParameter;
+import org.eclipse.cdt.core.dom.ast.IType;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
+import org.eclipse.cdt.core.index.IIndex;
+import org.eclipse.cdt.core.index.IIndexBinding;
+import org.eclipse.cdt.core.index.IIndexName;
+import org.eclipse.cdt.core.index.IndexFilter;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+import com.nokia.carbide.cdt.builder.CarbideBuilderPlugin;
+import com.nokia.carbide.cdt.builder.EpocEngineHelper;
+import com.nokia.carbide.cdt.builder.project.ICarbideBuildConfiguration;
+import com.nokia.carbide.cdt.builder.project.ICarbideProjectInfo;
+
+public class SourceLookup {
+	private static SourceLookup instance = null;
+	
+	public static SourceLookup getInstance() {
+		if (instance == null)
+			instance = new SourceLookup();
+		return instance;
+	}
+	
+	private SourceLookup () {
+		// singleton
+	}
+	
+	public void lookupAndopenEditorWithHighlight(String symbolName, String binaryName) {
+		IASTFileLocation[] locations = lookupLocations(symbolName, binaryName);
+		final Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+		if (locations.length <= 0) {
+			GeneralMessages.showErrorMessage(Messages.getString("SourceLookup.notfound") + "\n" + symbolName); //$NON-NLS-1$	//$NON-NLS-2$
+			return;
+		}
+		
+		if (locations.length > 1) {
+			SourceLookupFileChooserDialog dialog = new SourceLookupFileChooserDialog(shell, locations);
+			if (dialog.open() == Window.OK && dialog.getLocation() != null) {
+				openEditorWithHighlight(dialog.getLocation());
+			}
+		} else {
+			openEditorWithHighlight(locations[0]);
+		}
+	}
+	
+	private void openEditorWithHighlight(IASTFileLocation location) {
+		IPath path = new Path(location.getFileName());
+		IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
+
+		if (file == null) {
+			return;
+		}
+		
+		IEditorPart editor = null;
+
+		try {
+			editor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file);
+		} catch (PartInitException e) {
+			e.printStackTrace();
+		}
+
+		if (editor != null && editor instanceof ITextEditor) {
+			ITextEditor textEditor = (ITextEditor)editor;
+			int nodeOffset = location.getNodeOffset();
+			int nodeLength = location.getNodeLength();
+			int offset;
+			int length;
+			if (nodeLength == -1) {
+				// This means the offset is actually a line number
+				try {
+					IDocument document = textEditor.getDocumentProvider().getDocument(editor.getEditorInput());
+					offset = document.getLineOffset(nodeOffset);
+					length = document.getLineLength(nodeOffset);
+				} catch (BadLocationException e) {
+					CUIPlugin.getDefault().log(e);
+					return;
+				}
+		} else {
+				offset = nodeOffset;
+				length = nodeLength;
+		}
+		
+			textEditor.selectAndReveal(offset, length);
+		}
+	}
+	
+	private boolean typeEqual(String param, IType type) {
+
+		class TypeAttribute {
+			boolean isSigned = true;	// Symbian still default to signed
+			boolean isConst = true;
+			String typeWithoutModifier = "";	//$NON-NLS-1$
+			
+			TypeAttribute(String typeString) {
+				// In general we don't not have to care about too much, just trim out
+				// signed/unsigned/const modifier and take note. We take the rest of them
+				// and compare them after removing spaces
+				String[] typeStringSplit = typeString.split("[\t ]");	 //$NON-NLS-1$
+				int index = 0;
+				for (String chunk : typeStringSplit) {
+					if (chunk.equals("signed")) {	//$NON-NLS-1$
+						continue;
+					} else if (chunk.equals("unsigned")) {	//$NON-NLS-1$
+						isSigned = false;
+					}
+					if (index++ > 0 && chunk.equals("*") == false) {	//$NON-NLS-1$ // take out space before * consistently
+						typeWithoutModifier += " "; //$NON-NLS-1$
+					}
+					typeWithoutModifier += chunk;
+				}
+				
+				typeWithoutModifier = typeWithoutModifier.replaceAll("long int", "long"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			
+			boolean isSameType(TypeAttribute attribute) {
+				if (isSigned == attribute.isSigned &&
+						isConst == attribute.isConst &&
+						typeWithoutModifier != null &&
+						attribute.typeWithoutModifier != null &&
+						typeWithoutModifier.equals(attribute.typeWithoutModifier)) {
+					return true;
+				}
+				return false;
+			}
+		}
+		TypeAttribute cdtTypeAttribute = new TypeAttribute(ASTTypeUtil.getType(type));
+		TypeAttribute paramTypeAttribute = new TypeAttribute(param);
+		
+		return cdtTypeAttribute.isSameType(paramTypeAttribute);
+	}
+	
+	private IIndexBinding[] findBindingsForSignature(String Signature, IIndex index) {
+		ArrayList<IIndexBinding> bindingArrayList = new ArrayList<IIndexBinding>();
+		ArrayList<String> signaturesArrayList = new ArrayList<String>();
+		IIndexBinding[] bindings = null;
+		boolean needMatchingArg = true;
+		
+		// drop everything after )
+		if (Signature.indexOf(")") > 0 ) {	//$NON-NLS-1$
+			Signature = Signature.substring(0, Signature.indexOf(")"));	//$NON-NLS-1$
+		}
+		
+		String[] signatureSplit = Signature.split("[(),]"); //$NON-NLS-1$
+		for (String chunks: signatureSplit) {
+			chunks = chunks.trim();
+		}
+		
+		if (signatureSplit[0].contains(" ") || signatureSplit[0].contains("\t") || //$NON-NLS-1$ //$NON-NLS-2$
+				(signatureSplit[0].equals(Signature.trim()))) {	//$NON-NLS-1$	//$NON-NLS-2$
+			// -some RVCT function doesn't have arguments e.g. memset
+			// in the form of function_name<some space>lib.in(...)
+			// -std::nowthrow
+			signaturesArrayList.add(signatureSplit[0].split("[\t ]")[0]);	//$NON-NLS-1$
+			needMatchingArg = false;
+		} else {
+			// regular C++ functions/methods
+			for (String signature : signatureSplit) {
+				signaturesArrayList.add(signature);
+			}
+		}
+		
+		try {
+			index.acquireReadLock();
+			bindings = index.findBindings(Pattern.compile(signaturesArrayList.get(0)), false, IndexFilter.getFilter(ILinkage.CPP_LINKAGE_ID), new NullProgressMonitor());
+			if (bindings.length < 1) {
+				bindings = index.findBindings(Pattern.compile(signaturesArrayList.get(0)), false, IndexFilter.getFilter(ILinkage.C_LINKAGE_ID), new NullProgressMonitor());
+			}
+			if (bindings.length < 1) {
+				bindings = index.findBindings(Pattern.compile(signaturesArrayList.get(0)), false, IndexFilter.getFilter(ILinkage.NO_LINKAGE_ID), new NullProgressMonitor());
+			}
+			index.releaseReadLock();
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		} catch (CoreException e) {
+			e.printStackTrace();
+		}
+		
+		if (bindings != null) {
+
+			for (IIndexBinding binding : bindings) {
+				if (binding instanceof IFunction) {
+					IFunction function = (IFunction) binding;
+					if (needMatchingArg) {
+						boolean signatureMatch = true;
+						try {
+							IParameter[] params = function.getParameters();
+								if (params == null && signaturesArrayList.size() > 1) {	// no args, function name only
+									signatureMatch = false;	// # of arg differs
+								} else if (params.length == 1 && signaturesArrayList.size() == 1) {
+									// () is return as (void) in CDT
+									if (ASTTypeUtil.getType(params[0].getType()).equals("void") == false) {	//$NON-NLS-1$
+										signatureMatch = false;	// # of args differs
+									}
+								} else if (params.length != signaturesArrayList.size() -1) {
+								signatureMatch = false;	// # of args differs
+								} else {
+									for (int i = 0; i < params.length; i++) {
+										if (typeEqual(signaturesArrayList.get(i + 1), params[i].getType()) == false) {
+										signatureMatch = false;
+									}
+								}
+							}
+							if (signatureMatch) {
+								bindingArrayList.add(binding);
+							}
+						} catch (DOMException e) {
+							e.printStackTrace();
+						}
+					} else {
+						bindingArrayList.add(binding);
+					}
+				}	
+			}
+		}
+
+		return bindingArrayList.toArray(new IIndexBinding[0]);
+	}
+	
+	private IASTFileLocation[] lookupLocations(String symbolName, String binaryName) {
+		ArrayList<IASTFileLocation> locations = new ArrayList<IASTFileLocation>();
+		ArrayList<IProject> projectsMatchExe = new ArrayList<IProject>();
+		ArrayList<IProject> projectsNotMatchExe = new ArrayList<IProject>();
+		
+//		 just look up project that give the matching binary if there is binaryName
+		if (binaryName != null)
+		{
+			IProject[] projects= ResourcesPlugin.getWorkspace().getRoot().getProjects();
+			
+			for (IProject project: projects) {
+				if (CarbideBuilderPlugin.getBuildManager().isCarbideProject(project) == false) {
+					continue;
+				}
+				
+				ICarbideProjectInfo cpi = CarbideBuilderPlugin.getBuildManager().getProjectInfo(project);
+				if (cpi == null)
+					continue;
+				
+				List<ICarbideBuildConfiguration> allConfig = cpi.getBuildConfigurations();
+				
+				if (allConfig == null)
+					continue;
+				
+				boolean isEligibleProject = false;
+				for (ICarbideBuildConfiguration config : allConfig) {
+					String projectExePath = EpocEngineHelper.getPathToMainExecutable(config);
+					if (projectExePath != null && projectExePath.length() > 0) {
+						String projectFileName = new java.io.File(projectExePath).getName().toLowerCase();
+						String binaryFileName = new java.io.File(binaryName).getName().toLowerCase();
+
+						if (projectFileName.equals(binaryFileName) == true) {
+							isEligibleProject = true;
+						}
+					}
+				}
+				
+				if (isEligibleProject) {
+					projectsMatchExe.add(project);
+				} else {
+					projectsNotMatchExe.add(project);
+				}
+			}
+						
+			for (IProject project : projectsMatchExe) {
+				ICProject cProject = CoreModel.getDefault().getCModel().getCProject(project.getName());
+				try {
+					IIndex index = CCorePlugin.getIndexManager().getIndex(cProject);
+					IASTFileLocation[] locationsFound = lookupLocationsFromIndex(symbolName, index);
+					if (locationsFound != null) {
+						for (IASTFileLocation location : locationsFound) {
+							locations.add(location);
+						}
+					}
+				} catch (CoreException e) {
+					e.printStackTrace();
+				}
+			}
+		}
+		
+//		optionally look among all projects if not found
+		if (locations.size() == 0) {
+			for (IProject project : projectsNotMatchExe) {
+				ICProject cProject = CoreModel.getDefault().getCModel().getCProject(project.getName());
+		try {
+					IIndex index = CCorePlugin.getIndexManager().getIndex(cProject);
+					IASTFileLocation[] locationsFound = lookupLocationsFromIndex(symbolName, index);
+					if (locationsFound != null) {
+						for (IASTFileLocation location : locationsFound) {
+							locations.add(location);
+						}
+					}
+		} catch (CoreException e) {
+			e.printStackTrace();
+		}
+			}			
+		}
+		
+		return locations.toArray(new IASTFileLocation[0]);
+	}
+	
+	IASTFileLocation[] lookupLocationsFromIndex(String symbolName, IIndex index) {
+		IIndexBinding[] bindings = new IIndexBinding[0];
+		ArrayList<IASTFileLocation> locations = new ArrayList<IASTFileLocation>();
+		
+		// split by scoping operating ::, we will look for namespace and class later
+		String[] scopingOperatorSplit = symbolName.split ("::"); //$NON-NLS-1$
+		for (String chunks: scopingOperatorSplit) {
+			chunks = chunks.trim();
+		}
+		
+		// last element in scoping operator split is the function signature
+		bindings = findBindingsForSignature(scopingOperatorSplit[scopingOperatorSplit.length - 1], index);
+		
+		if (bindings.length > 0) {
+			for (IIndexBinding binding : bindings) {
+				try {
+					
+					index.acquireReadLock();
+					
+					boolean match = true;
+					if (binding instanceof ICPPFunction) {
+						ICPPFunction cppFunction = (ICPPFunction) binding;
+						String[] cdtQualifiedName = cppFunction.getQualifiedName();
+						if (scopingOperatorSplit.length == cdtQualifiedName.length) {
+							match = true;
+							// match namepace, class etc if there is, skip the function name which we
+							// already matched in reading back binding
+							for (int i = 0; i < cdtQualifiedName.length - 1; i++) {
+								if (scopingOperatorSplit[i].equals(cdtQualifiedName[i]) == false) {
+									match = false;
+									break;
+								}			
+							}
+						} else {
+							match = false;
+						}
+					} else if (binding instanceof IFunction) {
+						if (scopingOperatorSplit.length > 1) {
+							match = false;
+						}
+					}
+					
+					if (match) {
+						IIndexName[] defs= index.findDefinitions(binding);
+						for (IIndexName def : defs) {
+							locations.add(def.getFileLocation());
+						}
+						// we could end up not having any definition
+						// that is just because that code doesn't exist
+						// e.g. constructor is not exposed
+						// let's try pointing out the reference as it is
+						// useful for PI
+						if (locations.size() < 1) {
+							IIndexName[] refs = index.findReferences(binding);
+							for (IIndexName ref : refs) {
+								locations.add(ref.getFileLocation());
+							}
+						}
+					}
+					
+					index.releaseReadLock();
+					
+				} catch (InterruptedException e) {
+					e.printStackTrace();
+				} catch (CoreException e) {
+					e.printStackTrace();
+				} catch (DOMException e) {
+					e.printStackTrace();
+				}
+			}
+		}
+		
+		return locations.toArray(new IASTFileLocation[locations.size()]);
+	}
+/*	
+	void experiment()
+	{
+		IQuickParseCallback quickParseCallback = ParserFactory.createQuickParseCallback();
+		IParser parser = ParserFactory.createParser( 
+				ParserFactory.createScanner(new CodeReader("long int foo;".toCharArray()), 
+						new ScannerInfo(),
+						ParserMode.QUICK_PARSE,
+						ParserLanguage.CPP,
+						quickParseCallback,
+						null,
+						null ),
+				quickParseCallback, 
+				ParserMode.QUICK_PARSE, 
+				ParserLanguage.CPP, 
+				null );
+
+	}
+*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/SourceLookupFileChooserDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.swt.SWT;
+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.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.ui.CarbideUIPlugin;
+import com.nokia.carbide.cpp.ui.ICarbideSharedImages;
+
+public class SourceLookupFileChooserDialog extends TitleAreaDialog {
+
+	IASTFileLocation[] locations = null;
+	IASTFileLocation selectedLocation = null;
+	
+	// control
+	private Composite composite = null;
+	private Table table = null;
+
+	protected SourceLookupFileChooserDialog(Shell arg0, IASTFileLocation[] locs) {
+		super(arg0);
+		locations = locs;
+	}
+	
+	public Control createDialogArea(Composite parent) {
+		// use image from support plugin
+		setDefaultImage(CarbideUIPlugin.getSharedImages().getImageDescriptor(ICarbideSharedImages.IMG_CARBIDE_C_ICON_16_16).createImage());
+		getShell().setText(Messages.getString("SourceLookupFileChooserDialog.text")); //$NON-NLS-1$
+		setTitle(Messages.getString("SourceLookupFileChooserDialog.title")); //$NON-NLS-1$
+		setMessage(Messages.getString("SourceLookupFileChooserDialog.message")); //$NON-NLS-1$
+
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 1;
+		composite = new Composite(parent, SWT.NONE);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		composite.setLayout(gridLayout);
+				
+	    table = new Table(composite, SWT.SINGLE);
+	    table.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				selectedLocation = (IASTFileLocation)table.getSelection()[0].getData();
+			}
+	    	
+	    });
+	    table.addMouseListener(new MouseListener(){
+	    	// allow double click instead of OK
+			public void mouseDoubleClick(MouseEvent arg0) {
+				selectedLocation = (IASTFileLocation)table.getSelection()[0].getData();
+				okPressed();
+			}
+
+			public void mouseDown(MouseEvent arg0) {
+			}
+
+			public void mouseUp(MouseEvent arg0) {
+			}
+	    	
+	    });
+	    
+	    for(IASTFileLocation location : locations) {
+
+			IPath path = new Path(location.getFileName());
+			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
+
+			String fileName = null;
+			String containerName = null;
+			
+			if (file != null) {
+				fileName = file.getName();
+				containerName = "project " + file.getProject().getName();	//$NON-NLS-1$
+			} else {
+				fileName = path.segment(path.segmentCount() - 1);
+				containerName = path.uptoSegment(path.segmentCount() - 2).toString();	//$NON-NLS-1$
+			}
+	    	
+	    	TableItem item = new TableItem(table, SWT.NONE);
+	    	item.setText(fileName + " - " + containerName);	//$NON-NLS-1$
+	    	item.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE));
+	    	item.setData(location);
+	    }
+	    
+	    return composite;
+	}
+	
+	protected void okPressed() {
+		if (selectedLocation != null) {
+			super.okPressed();
+		}
+	}
+	
+	protected void cancelPressed() {
+		selectedLocation = null;
+		super.cancelPressed();
+	}
+	
+	public IASTFileLocation getLocation() {
+		return selectedLocation;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/TableColorPalette.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.ColorDialog;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+
+abstract public class TableColorPalette implements ITableColorPalette {
+
+	private final int channelValue[] = { 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF };
+	
+	private Map<Object, Color> palette = new HashMap<Object, Color>();
+	private int currentColorIndex = 0;
+	
+	abstract public RGB getConstantRGB(Object entry);
+
+	public TableColorPalette() {
+	}
+	
+	// Windows palette default from here
+	//http://www.mozilla.org/docs/refList/user-interface/visual/colorpalette/
+	int defaultPalette[][] = {{255,255,0}, {0,255,255}, {255,102,51},
+								{128,128,0}, {0,0,128}, {0,255,0},
+								{0,128,0}, {128,0,0}, {0,128,128},
+								{0,55,60}, {204,153,102}, {0,153,255},
+								{0,0,255}, {51,255,153}, {204,204,255},
+								{255,0,0}, {153,153,255}, {153,0,102},
+								{102,102,204}, {51,51,102}, {255,102,204}, 
+								{66,154,167},{153,102,153}};
+		
+	private void add(Object entry) {
+		RGB constantRGB = getConstantRGB(entry);
+		if (constantRGB != null){
+			// default color for SOS thread/binary/functions
+			palette.put(entry, ColorPalette.getColor(constantRGB));
+		} else {
+			// wrap around the table and assign the same color if we've done once
+			int i = currentColorIndex++ % 216;
+			int indexR, indexG, indexB;
+			if (i < 23){ // pick a bunch of color from Windows default palette first
+						// so user won't complain too much
+				indexR = defaultPalette[i][0];
+				indexG = defaultPalette[i][1];
+				indexB = defaultPalette[i][2];
+				palette.put(entry, ColorPalette.getColor(new RGB(indexR,indexG,indexB)));
+			}else {
+				int index;
+				i = 215 - i;	// start from lighter color for better contrast
+				index = i / 3 + (i % 3) * 72;
+				indexR = index % 6;
+				indexG = (index / 6) % 6;
+				indexB = (index / 36) % 6;
+			
+			palette.put(entry, ColorPalette.getColor(new RGB(channelValue[indexR],
+															channelValue[indexG],
+															channelValue[indexB])));
+			}
+		}
+	}
+	
+	public Color getColor(Object entry) {
+		if (palette.get(entry) == null) {
+			add(entry);
+		}
+		return palette.get(entry);
+	}
+
+	public java.awt.Color getAWTColor(Object entry) {
+		if (palette.get(entry) == null) {
+			add(entry);
+		}
+		Color swtColor = palette.get(entry);
+		return new java.awt.Color(
+								swtColor.getRed(),
+								swtColor.getGreen(),
+								swtColor.getBlue()
+								);
+	}
+	
+	public Color assignColor(Object entry, Color color) {
+		return assignColor(entry, color.getRGB());
+	}
+
+	public Color assignColor(Object entry, RGB rgb) {
+		if (palette.get(entry) == null) {
+			palette.remove(entry);
+		}
+		Color tmpColor;
+		if (rgb == null) {
+			// assign from 216 palette if nothing given
+			tmpColor = this.getColor (entry);
+		}
+		else {
+			tmpColor = ColorPalette.getColor(rgb);
+			palette.put(entry, ColorPalette.getColor(rgb));
+		}
+		return tmpColor;
+	}
+
+	// returns if recolor of palette on specific entry if successful
+	public boolean recolorEntryDialog(Shell parent, Object entry) {
+		ColorDialog colorDialog = new ColorDialog(parent, SWT.PRIMARY_MODAL);
+		colorDialog.setText(entry.toString());
+		if (palette.get(entry) != null) {
+			colorDialog.setRGB(palette.get(entry).getRGB());
+		} else {
+			colorDialog.setRGB(new RGB(255, 255, 255));
+		}
+		RGB newRGB = colorDialog.open();
+		if (newRGB != null) {
+			// allow duplicated color
+			if (palette.get(entry) == null) {
+				MessageBox errorDialog = new MessageBox(parent, SWT.ICON_ERROR
+						| SWT.OK);
+				errorDialog.setText(Messages
+						.getString("TableColorPalette.change.denied")); //$NON-NLS-1$
+				errorDialog
+						.setMessage(Messages
+								.getString("TableColorPalette.item.does.not.exist.in.palette")); //$NON-NLS-1$
+				errorDialog.open();
+			}
+			assignColor(entry, newRGB);
+			return true;
+		}
+		return false;
+	}
+	
+	// we can use this for export
+	public Map<Object, Color> getPaletteMap()
+	{
+		return palette;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/TestDataMiningPalette.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/* 
+ * 
+ * This class just make a list of numbers and assign color to them
+ * Testers should 
+ * 1.visually verify color if it looks good to them 
+ * 2.try to assign different color to different entries
+ * 3.try to assign the same color to different entries and observe error message
+ * 
+ * */
+
+public class TestDataMiningPalette {
+
+	private Shell sShell = null;
+
+	private Map<Button,CLabel> dataMiningColors = new HashMap<Button,CLabel>();
+	private DataMiningPalette palette = new DataMiningPalette();
+	private ArrayList<Integer> sosThreadlist = new ArrayList<Integer>();
+	private ArrayList<Integer> threadlist = new ArrayList<Integer>();
+
+	
+	/**
+	 * @param args
+	 */
+	public static void main(String[] args) {
+		Display display = Display.getDefault();
+		TestDataMiningPalette thisClass = new TestDataMiningPalette();
+		thisClass.createSShell();
+		thisClass.sShell.open();
+
+		while (!thisClass.sShell.isDisposed()) {
+			if (!display.readAndDispatch())
+				display.sleep();
+		}
+		display.dispose();
+	}
+
+	/**
+	 * This method initializes sShell
+	 */
+	private void createSShell() {
+		sShell = new Shell();
+		sShell.setText(Messages.getString("TestDataMiningPalette.shell")); //$NON-NLS-1$
+		sShell.setSize(new Point(1000, 700));
+
+		RowLayout layout = new RowLayout();
+		sShell.setLayout(layout);
+
+		for (int i = 0; i < 216; i++) {
+			sosThreadlist.add(i);
+		}
+		for (int i = 216; i < 216 + 255; i++) {
+			threadlist.add(i);
+		}
+		palette.assignSOSColor(sosThreadlist);
+		palette.assignColor(threadlist);
+		
+		sosThreadlist.addAll(threadlist);
+		
+		Iterator entryItr = sosThreadlist.iterator();
+
+		while(entryItr.hasNext())
+		{
+			Object entry = entryItr.next();
+			
+			final Button button = new Button(sShell, SWT.NONE);
+			button.setText(entry.toString());
+			button.setBackground(new Color(Display.getCurrent(), palette.getRGB(entry)));
+			button.addSelectionListener(new SelectionAdapter() {
+            	public void widgetSelected(SelectionEvent e) {
+            		Integer index = new Integer(button.getText());
+            		if(palette.recolorEntryDialog(sShell, index))
+            		{
+            			RGB newRGB = palette.getRGB(index);
+            			CLabel myLabel = dataMiningColors.get(button);
+            			myLabel.setBackground(new Color(Display.getCurrent(), newRGB));
+            		}
+            	}
+			});
+			CLabel cLabel = new CLabel(sShell, SWT.NONE);
+			cLabel.setText(entry.toString());
+			cLabel.setBackground(new Color(Display.getCurrent(), palette.getRGB(entry)));
+			dataMiningColors.put(button, cLabel);
+		}
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/TestTableColorPalette.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+public class TestTableColorPalette {
+	private Shell sShell = null;
+	
+	private Map<Button,CLabel> testColorsMap = new HashMap<Button,CLabel>();
+	private FunctionColorPalette palette = new FunctionColorPalette();
+	
+	public static void main(String[] args) {
+		Display display = Display.getDefault();
+		TestTableColorPalette thisClass = new TestTableColorPalette();
+		thisClass.createSShell();
+		thisClass.sShell.open();
+
+		while (!thisClass.sShell.isDisposed()) {
+			if (!display.readAndDispatch())
+				display.sleep();
+		}
+		display.dispose();
+	}
+
+	/**
+	 * This method initializes sShell
+	 */
+	private void createSShell() {
+		sShell = new Shell();
+		sShell.setText(Messages.getString("TestColorPalette.shell")); //$NON-NLS-1$
+		sShell.setSize(new Point(700, 700));
+
+		RowLayout layout = new RowLayout();
+		sShell.setLayout(layout);
+		
+		for (Integer i = 0; i < 6 * 6 * 7; i++)
+		{
+			final Integer finalI = i;
+			palette.getColor(i.toString());
+			final Button button = new Button(sShell, SWT.NONE);
+			button.setText(i.toString());
+			button.setBackground(palette.getColor(i.toString()));
+			button.addSelectionListener(new SelectionAdapter() {
+            	public void widgetSelected(SelectionEvent e) {
+            		if(palette.recolorEntryDialog(sShell, finalI))
+            		{
+            			Color myColor = palette.getColor(finalI);
+            			CLabel myLabel = testColorsMap.get(button);
+            			myLabel.setBackground(myColor);
+            		}
+            	}
+			});
+			CLabel cLabel = new CLabel(sShell, SWT.NONE);
+			cLabel.setText(i.toString());
+			cLabel.setBackground(palette.getColor(i.toString()));
+			testColorsMap.put(button, cLabel);
+		}
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/ThreadColorPalette.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.util;
+
+import org.eclipse.swt.graphics.RGB;
+
+public class ThreadColorPalette extends TableColorPalette {
+
+	@Override
+	public RGB getConstantRGB(Object entry) {
+		
+		assert (entry instanceof String);
+		//threadName   = sample.thread.process.name + "::" + sample.thread.threadName + "_" + sample.thread.threadId;
+
+		String string = (String)entry;
+		
+		int lastIndexOf = string.lastIndexOf("_");
+		
+		
+		String threadName[] = string.substring(0, lastIndexOf).split("::"); //$NON-NLS-1$ //$NON-NLS-2$
+		
+		int length = threadName.length;
+		
+		if(length == 1){
+			String newArray[] = new String[2];
+			newArray[0] = threadName[0];
+			newArray[1] = string.substring(lastIndexOf);
+			threadName = newArray;
+		}
+		
+		assert (threadName.length == 2);
+		
+		String pro_string = threadName[0];
+		String thr_string = threadName[1];
+		int mark;
+		if (pro_string.indexOf(".") != -1) //$NON-NLS-1$
+		    mark = pro_string.indexOf(".");  //EKA2 //$NON-NLS-1$
+		else if (pro_string.indexOf('[') != -1)
+		    mark = pro_string.indexOf('[');  //EKA1
+		else
+			return null;
+		
+		pro_string = pro_string.substring(0, mark);
+		
+	    if (pro_string.equalsIgnoreCase("EKern") && thr_string.equalsIgnoreCase("NULL")) { //$NON-NLS-1$ //$NON-NLS-2$
+	    	return new RGB(192,192,192); // AWT Color.lightGray
+	    }
+	    if (pro_string.equalsIgnoreCase("CarbideProf") && thr_string.equalsIgnoreCase("Profiler")) { //$NON-NLS-1$ //$NON-NLS-2$
+	    	return new RGB(0, 255, 255);	// AWT Color.cyan
+	    }
+	    if (pro_string.equalsIgnoreCase("C32exe") && thr_string.equalsIgnoreCase("EtelServer")) { //$NON-NLS-1$ //$NON-NLS-2$
+	        return new RGB(255, 200, 0);	// AWT Color.orange
+	    }
+	    if (pro_string.equalsIgnoreCase("C32exe") && thr_string.equalsIgnoreCase("SocketServer")) { //$NON-NLS-1$ //$NON-NLS-2$
+	        return new RGB(255, 175, 175);	// AWT Color.pink
+	    }
+	    if (pro_string.equalsIgnoreCase("DosServer") && thr_string.equalsIgnoreCase("DosServer")) { //$NON-NLS-1$ //$NON-NLS-2$
+	        return new RGB(255, 0, 255);	// AWT Color magenta
+	    }
+	    if (pro_string.equalsIgnoreCase("EFile") && thr_string.equalsIgnoreCase("FileServer")) { //$NON-NLS-1$ //$NON-NLS-2$
+	        return new RGB(0, 0, 255);	// AWT Color.blue
+	    }
+	    if (pro_string.equalsIgnoreCase("EKern") && thr_string.equalsIgnoreCase("Supervisor")) { //$NON-NLS-1$ //$NON-NLS-2$
+	        return new RGB(0, 0, 0);	// AWT Color.black
+	    }
+	    if (pro_string.equalsIgnoreCase("EikSrvs") && thr_string.equalsIgnoreCase("ViewServerThread")) { //$NON-NLS-1$ //$NON-NLS-2$
+	        return new RGB(64, 64, 64);	// AWT Color.darkGray
+	    }
+	    if (pro_string.equalsIgnoreCase("FbServ") && thr_string.equalsIgnoreCase("Fontbitmapserver")) { //$NON-NLS-1$ //$NON-NLS-2$
+	        return new RGB(255, 0, 0);	// AWT Color.red
+	    }
+	    if (pro_string.equalsIgnoreCase("Phone") && thr_string.equalsIgnoreCase("Phone")) { //$NON-NLS-1$ //$NON-NLS-2$
+	        return new RGB(128, 128, 128);	// AWT Color.gray
+	    }
+	    
+	    return null;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.util/src/com/nokia/carbide/cpp/pi/util/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,21 @@
+TestDataMiningPalette.shell=Data Mining Palette Test
+DataMiningPalette.change.denied=Change denied
+DataMiningPalette.color.exist=Choosen color overlap with existing color on palette
+DataMiningPalette.item.does.not.exist.in.palette=item does not exist in palette
+TableColorPalette.change.denied=Change denied
+TableColorPalette.item.does.not.exist.in.palette=item does not exist in palette
+TestColorPalette.shell=Color Palette Test
+GeneralMessages.unknownError=Unknown error
+GeneralMessages.cancel=CANCEL
+GeneralMessages.ok=OK
+GeneralMessages.no=NO
+GeneralMessages.pi=Performance Investigator: 
+GeneralMessages.yes=YES
+GeneralMessages.piError=Performance Investigator error
+GeneralMessages.piWarning=Performance Investigator warning
+GeneralMessages.piMessage=Performance Investigator message
+SourceLookup.notfound=Performance Investigator cannot find source file related to the following function:
+SourceLookupFileChooserDialog.text=Source Lookup Result
+SourceLookupFileChooserDialog.title=Multiple matches from projects:
+SourceLookupFileChooserDialog.message=Double click candidate or press OK after selecting candidate to open.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/.settings/org.eclipse.core.resources.prefs	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,4 @@
+#Mon Feb 09 13:35:52 CST 2009
+eclipse.preferences.version=1
+encoding//src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/messages.properties=8859_1
+encoding//src/com/nokia/carbide/pi/wizards/messages.properties=8859_1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,26 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator Import Wizards
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi.wizards;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.wizards.WizardsPlugin
+Bundle-Vendor: Nokia
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.ui.ide,
+ com.nokia.carbide.cpp.support,
+ com.nokia.carbide.cpp.pi.util,
+ org.eclipse.cdt.core,
+ org.eclipse.cdt.managedbuilder.core,
+ com.nokia.carbide.cdt.builder,
+ com.nokia.carbide.cpp.epoc.engine,
+ com.nokia.carbide.cpp.sdk.core,
+ com.nokia.carbide.cpp.sdk.ui,
+ com.nokia.carbide.cpp.ui,
+ com.nokia.carbide.cpp.pi.button,
+ com.nokia.carbide.cpp.pi,
+ com.nokia.cpp.utils.core
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.pi.wizards;x-friends:="com.nokia.carbide.cpp.pi.wizard.tests"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+bin.includes = plugin.xml,\
+               META-INF/,\
+               icons/,\
+               .
+jars.compile.order = .
+source.. = src/
+output.. = bin/
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/icons/PI_Meter_16x16.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/icons/PI_Meter_20x20.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/log/Logfile.1 has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/log/Snapshot.1 has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/log/Version_Number has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+   <extension
+         point="org.eclipse.ui.importWizards">
+      <category
+            id="com.nokia.carbide.cpp.importWizards.pi"
+            name="Performance Investigator">
+      </category>
+      <wizard
+            category="com.nokia.carbide.cpp.importWizards.pi"
+            class="com.nokia.carbide.cpp.internal.pi.wizards.ui.NewPIWizard"
+            icon="icons/PI_Meter_16x16.png"
+            id="com.nokia.carbide.cpp.pi.wizards.ui.NewPIWizard"
+            name="Performance Investigator Data">
+         <description>
+            Import a Carbide.c++ Profiler data file (*.dat).
+         </description>
+      </wizard>
+   </extension>
+   <extension
+         point="org.eclipse.ui.exportWizards">
+      <category
+            id="com.nokia.carbide.cpp.exportWizards.pi"
+            name="Performance Investigator">
+      </category>
+	</extension>
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/INewPIWizardSettings.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+public interface INewPIWizardSettings {
+	// Every Page should just write it's contribution
+	// to NewPIWizardSettings instead of handing out those
+	// data themselves
+	public void setupPageFromFromNewPIWizardSettings();
+	public void validatePage ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.wizards.ui.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizard.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.DialogSettings;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+
+import com.nokia.carbide.cdt.builder.builder.CarbideCPPBuilder;
+import com.nokia.carbide.cdt.builder.project.ICarbideBuildConfiguration;
+import com.nokia.carbide.cdt.builder.project.ISISBuilderInfo;
+import com.nokia.carbide.cpp.internal.api.sdk.SymbianBuildContext;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.IPkgEntry;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.RofsObySymbolPair;
+import com.nokia.carbide.cpp.pi.button.BupEventMapManager;
+import com.nokia.carbide.cpp.pi.button.ButtonPlugin;
+import com.nokia.carbide.cpp.pi.importer.SampleImporter;
+import com.nokia.carbide.cpp.pi.wizards.WizardsPlugin;
+import com.nokia.carbide.cpp.sdk.core.ISymbianBuildContext;
+import com.nokia.carbide.cpp.ui.CarbideUIPlugin;
+import com.nokia.carbide.cpp.ui.ICarbideSharedImages;
+import com.nokia.cpp.internal.api.utils.core.Check;
+import com.nokia.cpp.internal.api.utils.core.FileUtils;
+
+public class NewPIWizard extends Wizard implements IImportWizard, INewWizard{
+	
+	//	The shared instance.
+	private static NewPIWizard wizard;
+	
+	static final int PROGRESS_WORK_TOTAL = 10000; // handy total for progress
+													// indicator
+	static final String DIALOG_SETTING_FILE = WizardsPlugin.getDefault().getStateLocation().append("dialog_settings.xml").toOSString();	//$NON-NLS-1$
+	
+	private NewPIWizardPageInputTask pageInput;
+	private NewPIWizardPageConfigSelectorTask pageConfigSelector;
+	private NewPIWizardPagePkgListTask pagePkgList;
+	@SuppressWarnings("unused") //$NON-NLS-1$
+	private NewPIWizardPageRomSdkSubTask pageRomPkgSdk;
+	private NewPIWizardPageRomSubTask pageObySym;
+	private NewPIWizardPageCustomTask pageCustom;
+	private NewPIWizardPageBupMapTask pageBupMap;
+	private NewPIWizardPageOutputTask pageOutput;
+	private ArrayList<IFile> tmpPkgList = new ArrayList<IFile>();
+	private Set<Integer> traceSet;
+	
+	protected IProject piProject;
+	IWorkbench workbench;
+	
+	NewPIWizardSettings wizardSettings = NewPIWizardSettings.getInstance();
+
+	/**
+	 * Constructor for NewPIWizard.
+	 */
+	public NewPIWizard() {
+		super();
+		wizard = this;
+		setNeedsProgressMonitor(true);
+		ICarbideSharedImages carbideImages = CarbideUIPlugin.getDefault().getSharedImages();
+		setDefaultPageImageDescriptor(carbideImages.getImageDescriptor(carbideImages.IMG_PI_IMPORT_WIZARD_BANNER_75_66));
+		setWindowTitle(Messages.getString("NewPIWizard.window.title")); //$NON-NLS-1$
+
+		//DialogSettings dialogSettings = (DialogSettings) WizardsPlugin.getDefault().getDialogSettings();
+		IDialogSettings dialogSettings = new DialogSettings("import_wizard");	//$NON-NLS-1$
+		try {
+			dialogSettings.load(DIALOG_SETTING_FILE);
+		} catch (IOException e) {
+			// saving last session is not that important
+			//e.printStackTrace();
+		}
+
+		wizardSettings.clear();
+		wizardSettings.restoreState(dialogSettings);
+		setDialogSettings(dialogSettings);
+	}
+	
+	static public NewPIWizard getDefault() {
+		return wizard;
+	}
+	
+	/**
+	 * Adding the pages to the wizard.
+	 */
+
+	public void addPages() {
+		addPage(pageInput = new NewPIWizardPageInputTask(this));
+		addPage(pageConfigSelector = new NewPIWizardPageConfigSelectorTask());
+		addPage(pagePkgList = new NewPIWizardPagePkgListTask());
+		// merge SDK to symbol page
+		//addPage(pageRomPkgSdk = new NewPIWizardPageRomSdkSubTask());
+		addPage(pageObySym = new NewPIWizardPageRomSubTask());
+		addPage(pageBupMap = new NewPIWizardPageBupMapTask());
+		addPage(pageCustom = new NewPIWizardPageCustomTask(this));
+		addPage(pageOutput = new NewPIWizardPageOutputTask());		
+	}
+	
+	public void createPageControls(Composite pageContainer) {
+		super.createPageControls(pageContainer);
+		// flush out all settings for very page, so we can hit finish
+		IWizardPage[] pages = getPages();
+		for (IWizardPage page: pages) {
+			if (page instanceof INewPIWizardSettings) {
+				((INewPIWizardSettings)page).setupPageFromFromNewPIWizardSettings();
+			}
+		}
+
+	}
+
+	/**
+	 * This method is called when 'Finish' button is pressed in the wizard. We
+	 * will create an operation and run it using wizard as execution context.
+	 */
+	public boolean performFinish() {
+		pageOutput.regenerateOutputIfIntputChanged(); // this must stay out of asyncExec() since it require treeviewer selection
+		Display.getDefault().asyncExec( new Runnable() {
+			public void run () {
+				//DialogSettings dialogSettings = (DialogSettings) WizardsPlugin.getDefault().getDialogSettings();
+				IDialogSettings dialogSettings = getDialogSettings();
+				if (dialogSettings != null) {
+					NewPIWizardSettings.getInstance().saveState(dialogSettings);
+					setDialogSettings(dialogSettings);
+					try {
+						dialogSettings.save(DIALOG_SETTING_FILE);
+					} catch (IOException e) {
+						// saving last session is not that important
+						e.printStackTrace();
+					}
+				}
+				createNewProject();
+			
+			}
+		});
+		
+		return true;
+	}
+	
+	private IFile createTempPkgFile() {
+		try {
+			java.io.File prepocessedPkgFile;
+			prepocessedPkgFile = java.io.File.createTempFile("importpi", ".pkg", new java.io.File(wizardSettings.outputContainer.getLocation().toString()));	//$NON-NLS-1$ //$NON-NLS-2$
+			prepocessedPkgFile.deleteOnExit();
+			// force eclipse be be aware of the added file from the IFile refresh
+			wizardSettings.outputContainer.refreshLocal(0, null);
+			IFile tmpPkgFile = FileUtils.convertFileToIFile(wizardSettings.outputContainer, prepocessedPkgFile);
+			if (tmpPkgFile == null) {
+				Check.reportFailure(prepocessedPkgFile.getAbsolutePath() + Messages.getString("NewPIWizard.failed.convertFileToIFile"), new Throwable()); //$NON-NLS-1$
+				return null;
+			}
+			tmpPkgList.add(tmpPkgFile);
+			return tmpPkgFile;
+		} catch (IOException e1) {
+			e1.printStackTrace();
+		} catch (CoreException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+	
+	private void cleanTempPkgFile() {
+		for(IFile file : tmpPkgList) {
+			// just to delete using java.io as well for consistence
+			java.io.File javaFile = new java.io.File(file.getLocation().toString());
+			javaFile.delete();
+			try {
+				// force eclipse be be aware of the removed file from the IFile refresh
+				file.refreshLocal(0, null);
+			} catch (CoreException e) {
+				e.printStackTrace();
+			}
+		}
+		tmpPkgList.clear();
+	}
+
+	private void createNewProject() {
+		SampleImporter sampleImporter = SampleImporter.getInstance();
+		NewPIWizardSettings wizardSettings = NewPIWizardSettings.getInstance();
+		Map<Object, IFile> preprocessedMap = new HashMap<Object, IFile>();
+		sampleImporter.clear();
+		
+		sampleImporter.setDatFileName(wizardSettings.sampleFileName);
+		String container = wizardSettings.outputContainer.getFullPath().toString();
+		if (container.startsWith("/")) //$NON-NLS-1$
+			container = container.substring(1, container.length());
+		sampleImporter.setProjectName(container);
+		sampleImporter.setPiFileName(wizardSettings.piFileName);
+		if (wizardSettings.haveRomOnly || wizardSettings.haveAppRom) {
+			if (wizardSettings.romSdk != null && wizardSettings.romSdk.getEPOCROOT() != null) {
+				sampleImporter.setRomEpocroot(wizardSettings.romSdk.getEPOCROOT());
+			}
+			if (wizardSettings.romSymbolFile != null) {
+				sampleImporter.setRomSymbolFile(wizardSettings.romSymbolFile);
+			}
+			if (wizardSettings.romObyFile != null) {
+				sampleImporter.setRomObyFile(wizardSettings.romObyFile);
+			}
+			sampleImporter.clearRofsObyFileList();
+			sampleImporter.clearRofsSymbolFileList();
+			for (RofsObySymbolPair pair : wizardSettings.rofsObySymbolPairList) {
+				sampleImporter.addRofsObyFile(pair.getObyFile());
+				sampleImporter.addRofsSymbolFile(pair.getSymbolFile());
+			}
+		}
+		if (wizardSettings.haveAppOnly || wizardSettings.haveAppRom) {
+			for (IPkgEntry entry :wizardSettings.selectedAppFileList) {
+				java.io.File javaFile = new java.io.File(entry.getPkgFile());
+				if (javaFile.exists()) {
+					IFile tmpPkgFile = createTempPkgFile();
+					if (tmpPkgFile == null) {
+						Check.reportFailure(tmpPkgFile.getLocation().toString() + Messages.getString("NewPIWizard.failed.convertFileToIFile"), new Throwable()); //$NON-NLS-1$
+						return;
+					}
+					{
+						try {
+							char[] pkgFileBuf = FileUtils.readFileContents(javaFile, null);
+							String pkgFileStr = new String(pkgFileBuf);
+							FileUtils.writeFileContents(new java.io.File(tmpPkgFile.getLocation().toString()), pkgFileStr.toCharArray(), null);
+						} catch (CoreException e) {
+							e.printStackTrace();
+						}
+					}
+					preprocessedMap.put(entry, tmpPkgFile);
+				}
+			}
+			for (ICarbideBuildConfiguration config : wizardSettings.selectedBuildConfigList) {
+				ISymbianBuildContext context = SymbianBuildContext.getBuildContextFromDisplayName(config.getDisplayString());
+				IFile tmpPkgFile;
+				
+				
+				List<ISISBuilderInfo> sisBuilderInfoList = config.getSISBuilderInfoList();
+				for (ISISBuilderInfo sisBuildInfo :sisBuilderInfoList) {
+					tmpPkgFile= createTempPkgFile();
+					if (tmpPkgFile == null) {
+						Check.reportFailure(tmpPkgFile.getLocation().toString() + Messages.getString("NewPIWizard.failed.convertFileToIFile"), new Throwable()); //$NON-NLS-1$
+						return;
+					}
+					IPath tmpPkgPath = tmpPkgFile.getLocation();
+					CarbideCPPBuilder.resolvePKGFile(sisBuildInfo.getPKGFullPath(), 
+							context, 
+							tmpPkgPath);
+					preprocessedMap.put(config, tmpPkgFile);
+				}
+			}
+		}
+		if (preprocessedMap.size() > 0) {
+			for(Entry<Object, IFile> entry : preprocessedMap.entrySet()) {
+				String epocroot = ""; //$NON-NLS-1$
+				if (entry.getKey() instanceof IPkgEntry) {
+					epocroot = ((IPkgEntry)entry.getKey()).getSdk().getEPOCROOT();
+				} else if (entry.getKey() instanceof ICarbideBuildConfiguration) {
+					epocroot = ((ICarbideBuildConfiguration)entry.getKey()).getSDK().getEPOCROOT();
+				}
+				sampleImporter.addPkgObyFile(epocroot, entry.getValue().getLocation().toString());
+			}
+		}
+		
+		if (wizardSettings.keyMapProfile != null) {
+			//BUP key press profile
+			sampleImporter.setBupMapProfileId(wizardSettings.keyMapProfile.getProfileId());
+			if (wizardSettings.keyMapProfile.getSDK() != null) {
+				sampleImporter.setBupMapSymbianSDKId(wizardSettings.keyMapProfile.getSDK().getUniqueId());
+				sampleImporter.setBupMapIsBuiltIn(false);
+				sampleImporter.setBupMapIsWorkspace(false);
+			}
+			if (wizardSettings.keyMapProfile.getURI().equals(BupEventMapManager.DEFAULT_PROFILE_URI)) {
+				sampleImporter.setBupMapSymbianSDKId(""); //$NON-NLS-1$
+				sampleImporter.setBupMapIsBuiltIn(true);
+				sampleImporter.setBupMapIsWorkspace(false);
+			} else if (wizardSettings.keyMapProfile.getURI().equals(BupEventMapManager.WORKSPACE_PREF_KEY_MAP_URI)) {
+				sampleImporter.setBupMapSymbianSDKId(""); //$NON-NLS-1$
+				sampleImporter.setBupMapIsBuiltIn(false);
+				sampleImporter.setBupMapIsWorkspace(true);
+			}			
+		}
+
+		sampleImporter.importSamples(false);	// not waiting NPI save complete for responsive UI, save NPI on background
+		
+		cleanTempPkgFile();
+	}
+	
+	public void init(IWorkbench workbench, IStructuredSelection selection) {
+		this.workbench = workbench;
+		setNeedsProgressMonitor(true);
+	}
+
+	public void setInitializationData(IConfigurationElement config,
+			String propertyName, Object data) throws CoreException {
+	}
+			
+	NewPIWizardSettings getWizardData() {
+		return wizardSettings;
+	}
+	
+	public boolean canFinish() {
+		return isAllFollowingPagesComplete(getStartingPage());
+	}
+	
+	private boolean isAllFollowingPagesComplete(IWizardPage page) {
+		IWizardPage currentPage = page;
+		while (currentPage != null) {
+			if (currentPage.isPageComplete() == false) {
+				return false;
+			}
+			currentPage = getNextPage(currentPage);
+		}
+		// after ending page
+		return true;
+	}
+	
+	// all trace ID, we can check this for trace specific handling
+	public Set<Integer> getTraceSet() {
+		return traceSet;
+	}
+	
+	// all trace ID, we can do trace specific handling later
+	public void setTraceSet(Set<Integer> myTraceSet) {
+		traceSet = myTraceSet;
+	}
+	
+	public IWizardPage getPreviousPage (IWizardPage page) {
+		NewPIWizardSettings settings = NewPIWizardSettings.getInstance();
+		if (page == pageOutput && settings.enableCust == false) {
+			return getPreviousPage(pageCustom);
+		} else if (page == pageCustom && getTraceSet().contains(ButtonPlugin.getDefault().getTraceId()) == false){
+			return getPreviousPage(pageBupMap);
+		} else if (page == pageBupMap && wizardSettings.haveRomOnly == false && wizardSettings.haveAppRom == false) {
+			return getPreviousPage(pageObySym);
+		} else if (page == pageObySym && wizardSettings.haveAppOnly == false && wizardSettings.haveAppRom == false) {
+			return getPreviousPage(pagePkgList);
+		}
+
+		return super.getPreviousPage(page);
+	}
+
+	public IWizardPage getNextPage (IWizardPage page) {
+		if (page == pageConfigSelector && wizardSettings.haveAppOnly == false && wizardSettings.haveAppRom == false) {
+			return getNextPage(pagePkgList);
+		} else if (page == pagePkgList && wizardSettings.haveRomOnly == false && wizardSettings.haveAppRom == false) {
+			return getNextPage(pageObySym);
+		} else if (page == pageObySym && getTraceSet().contains(ButtonPlugin.getDefault().getTraceId()) == false) {
+			return getNextPage(pageBupMap);
+		} else if (page == pageBupMap && wizardSettings.enableCust == false) {
+			return getNextPage(pageCustom);
+		}
+		return super.getNextPage(page);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardObySymbolPairDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.RofsObySymbolPair;
+import com.nokia.carbide.cpp.ui.CarbideUIPlugin;
+import com.nokia.carbide.cpp.ui.ICarbideSharedImages;
+
+public class NewPIWizardObySymbolPairDialog extends TitleAreaDialog {
+	
+	private RofsObySymbolPair pair = new RofsObySymbolPair();
+
+	// control
+	private Composite composite = null;
+	private Label obyLabel = null;
+	private Composite obyComposite = null;
+	private Text obyText = null;
+	private Button obyButton = null;
+	private Label symbolLabel = null;
+	private Composite symbolComposite = null;
+	private Text symbolText = null;
+	private Button symbolButton = null;
+	
+	protected NewPIWizardObySymbolPairDialog(Shell arg0) {
+		super(arg0);
+		setHelpAvailable(false);
+	}
+	
+	public Control createDialogArea(Composite parent) {
+		setTitle(Messages.getString("NewPIWizardObySymbolPairDialog.rofs.oby.rofs.symbol")); //$NON-NLS-1$
+		setTitleImage(CarbideUIPlugin.getSharedImages().getImage(ICarbideSharedImages.IMG_PI_IMPORT_ROM_42_42));
+		getShell().setText(Messages.getString("NewPIWizardObySymbolPairDialog.shell.title")); //$NON-NLS-1$
+		
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 1;
+		composite = new Composite(parent, SWT.NONE);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		composite.setLayout(gridLayout);
+	
+		obyLabel = new Label (composite, SWT.NONE);
+		obyLabel.setText(Messages.getString("NewPIWizardObySymbolPairDialog.rofs.oby.file")); //$NON-NLS-1$
+		GridLayout obyGridLayout = new GridLayout();
+		obyGridLayout.numColumns = 2;
+		obyComposite = new Composite(composite, SWT.NONE);
+		obyComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		obyComposite.setLayout(obyGridLayout);
+		obyText = new Text (obyComposite, SWT.BORDER | SWT.SINGLE);
+		obyText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		obyText.addModifyListener(new ModifyListener() {
+
+			public void modifyText(ModifyEvent arg0) {
+				getButton(IDialogConstants.OK_ID).setEnabled(validateAll());
+				symbolText.setFocus();
+			}
+			
+		});
+		obyButton = new Button (obyComposite, SWT.NONE);
+		obyButton.setText(Messages.getString("NewPIWizardObySymbolPairDialog.browse")); //$NON-NLS-1$
+		obyButton.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				FileDialog dialog = new FileDialog(getShell());
+				String[] extensions = {"*.oby"};	//$NON-NLS-1$
+				String[] names = {Messages.getString("NewPIWizardObySymbolPairDialog.build.file.extension")}; //$NON-NLS-1$
+				dialog.setFilterExtensions(extensions);
+				dialog.setFilterNames(names);
+				String selectedFilePath = dialog.open();
+				if (selectedFilePath != null)  {
+					obyText.setText(selectedFilePath);
+				}
+			}
+			
+		});
+		
+		symbolLabel = new Label (composite, SWT.NONE);
+		symbolLabel.setText(Messages.getString("NewPIWizardObySymbolPairDialog.rofs.symbol.file")); //$NON-NLS-1$
+		GridLayout symbolGridLayout = new GridLayout();
+		symbolGridLayout.numColumns = 2;
+		symbolComposite = new Composite(composite, SWT.NONE);
+		symbolComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		symbolComposite.setLayout(obyGridLayout);
+		symbolText = new Text (symbolComposite, SWT.BORDER | SWT.SINGLE);
+		symbolText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		symbolText.addModifyListener(new ModifyListener() {
+
+			public void modifyText(ModifyEvent arg0) {
+				getButton(IDialogConstants.OK_ID).setEnabled(validateAll());
+				symbolText.setFocus();
+			}
+			
+		});
+		symbolButton = new Button (symbolComposite, SWT.NONE);
+		symbolButton.setText(Messages.getString("NewPIWizardObySymbolPairDialog.browse")); //$NON-NLS-1$
+		symbolButton.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+			
+			public void widgetSelected(SelectionEvent arg0) {
+				FileDialog dialog = new FileDialog(getShell());
+				String[] extensions = {"*.symbol"};	//$NON-NLS-1$
+				String[] names = {Messages.getString("NewPIWizardObySymbolPairDialog.symbol.file")}; //$NON-NLS-1$
+				dialog.setFilterExtensions(extensions);
+				dialog.setFilterNames(names);
+				String selectedFilePath = dialog.open();
+				if (selectedFilePath != null)  {
+					symbolText.setText(selectedFilePath);
+				}
+			}
+
+		});
+		
+		// initial state
+		validateAll();
+
+		return composite;
+	}
+	
+	boolean validateAll() {
+
+		setMessage(null);
+		setErrorMessage(null);
+		
+		symbolText.setEnabled(false);
+		symbolButton.setEnabled(false);
+		if (obyText.getText().length() > 0) {
+			if (obyText.getText().toLowerCase().endsWith(".oby") == false) {	//$NON-NLS-1$
+				setErrorMessage(Messages.getString("NewPIWizardObySymbolPairDialog.oby.file.extension.error")); //$NON-NLS-1$
+				return false;
+			}
+			if (new java.io.File(obyText.getText()).exists() == false) {
+				setErrorMessage(Dialog.shortenText(Messages.getString("NewPIWizardObySymbolPairDialog.oby.file") + obyText.getText() + Messages.getString("NewPIWizardObySymbolPairDialog.does.not.exist.in.file.system"), obyComposite)); //$NON-NLS-1$ //$NON-NLS-2$
+				return false;
+			}
+			symbolText.setEnabled(true);
+			symbolButton.setEnabled(true);
+		}
+		
+		if (symbolText.getText().length() > 0) {
+			if (symbolText.getText().toLowerCase().endsWith(".symbol") == false) {	//$NON-NLS-1$
+				setErrorMessage(Messages.getString("NewPIWizardObySymbolPairDialog.symbol.extension.error")); //$NON-NLS-1$
+				return false;
+			}
+			if (new java.io.File(symbolText.getText()).exists() == false) {
+				setErrorMessage(Dialog.shortenText(Messages.getString("NewPIWizardObySymbolPairDialog.symbol.file.2") + symbolText.getText() + Messages.getString("NewPIWizardObySymbolPairDialog.does.not.exist.in.file.system.2"), symbolComposite)); //$NON-NLS-1$ //$NON-NLS-2$
+				return false;
+			}
+		}
+		
+		return true;
+	}
+	
+	RofsObySymbolPair getPair() {
+		return pair;
+	}
+	
+	public void okPressed() {
+		pair.setObyFile(obyText.getText());
+		pair.setSymbolFile(symbolText.getText());
+		super.okPressed();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPage.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.widgets.Composite;
+
+// try to work around some strange behavior around setErrorMessage we don't understand
+
+public class NewPIWizardPage extends WizardPage {
+
+	protected NewPIWizardPage(String arg0) {
+		super(arg0);
+	}
+
+	public void createControl(Composite arg0) {
+	}
+	
+	public void setVisible(boolean visable) {
+		if (visable == true) {
+			// I have no idea why, setErrorMessage could mess up
+			// the title and flip to last page , force this in base 
+			// class every time we show
+			setTitle(this.getTitle());
+	    	setDescription(this.getDescription());
+		}
+		super.setVisible(visable);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageBupMapTask.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cdt.builder.project.ICarbideBuildConfiguration;
+import com.nokia.carbide.cpp.internal.pi.button.ui.BupProfileTreeViewer;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.CarbidePiWizardHelpIds;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.IPkgEntry;
+import com.nokia.carbide.cpp.pi.button.BupEventMapManager;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapProfile;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+
+
+public class NewPIWizardPageBupMapTask extends NewPIWizardPage implements
+		INewPIWizardSettings {
+	
+	private NewPIWizardSettings settings = NewPIWizardSettings.getInstance();
+
+	/**
+	 * @param arg0
+	 */
+	protected NewPIWizardPageBupMapTask() {
+		super(Messages.getString("NewPIWizardPageBupMapTask.0")); //$NON-NLS-1$
+		setTitle(Messages.getString("NewPIWizardPageBupMapTask.1")); //$NON-NLS-1$
+	    setDescription(Messages.getString("NewPIWizardPageBupMapTask.2")); //$NON-NLS-1$
+	}
+	
+	// controls
+	Composite container;
+	private Label profileLabel = null;
+	Composite treeViewerComposite;
+	private BupProfileTreeViewer profileTreeViewer = null;
+	private Label recommendedLabel = null;
+	private Text rationaleText = null;	
+	
+	public void createControl(Composite parent) {
+		super.createControl(parent);
+		container = new Composite(parent, SWT.NONE);
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(container);
+		GridLayoutFactory.fillDefaults().applyTo(container);
+
+		profileLabel = new Label(container, SWT.NONE);
+		profileLabel.setText(Messages.getString("NewPIWizardPageBupMapTask.3")); //$NON-NLS-1$
+		
+		treeViewerComposite = new Composite(container, SWT.NONE);
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(treeViewerComposite);
+		GridLayoutFactory.fillDefaults().applyTo(treeViewerComposite);
+		profileTreeViewer = new BupProfileTreeViewer(treeViewerComposite);
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(profileTreeViewer.getTree());
+		profileTreeViewer.addPostSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent arg0) {
+				validatePage();
+				IBupEventMapProfile profile = profileTreeViewer.getSelectedProfile();
+				if (profile != null) {
+					NewPIWizardSettings.getInstance().keyMapProfile = profile;
+				}
+			}
+		});
+		
+		recommendedLabel = new Label(container, SWT.NONE);
+		recommendedLabel.setText(Messages.getString("NewPIWizardPageBupMapTask.4")); //$NON-NLS-1$
+		
+		rationaleText = new Text(container, SWT.READ_ONLY);
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(rationaleText);
+		
+		setControl(container);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), CarbidePiWizardHelpIds.PI_IMPORT_WIZARD_BUP_MAP);
+		
+		validatePage();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.wizards.ui.INewPIWizardSettings#setupPageFromFromNewPIWizardSettings()
+	 */
+	public void setupPageFromFromNewPIWizardSettings() {
+		if (settings.keyMapProfile != null) {
+			profileTreeViewer.collapseAll();
+			profileTreeViewer.reveal(settings.keyMapProfile);
+			profileTreeViewer.setSelection(new StructuredSelection(settings.keyMapProfile));
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see com.nokia.carbide.cpp.internal.pi.wizards.ui.INewPIWizardSettings#validatePage()
+	 */
+	public void validatePage() {
+		IBupEventMapProfile profile = profileTreeViewer.getSelectedProfile();
+		if (profile == null) {
+			setErrorMessage(Messages.getString("NewPIWizardPageBupMapTask.5")); //$NON-NLS-1$
+			setPageComplete(false);
+		} else {
+			setErrorMessage(null);
+			setPageComplete(true);
+		}
+	}
+	
+	/*
+	 * Build the profile list will descending recommendation
+	 * Cust kit => SDK => workspace selection => workspace profiles => builtin profiles
+	 * 
+	 * If the top tier selection have only one profile, preselect it for user
+	 * otherwise use persisted setting.
+	 * 
+	 * e.g. for preselect
+	 * -If we have Cust kit and Cust kit have only one profile, select it
+	 * -If we have only one SDK and it only have one profile, select it
+	 * 
+	 * return if we should preselect for user
+	 */
+	private boolean buildBupMapProfileList() {
+		ArrayList<ICarbideBuildConfiguration> buildConfigList = settings.selectedBuildConfigList;
+		ArrayList<IPkgEntry> appFileList = settings.selectedAppFileList;
+		ISymbianSDK romSdk = null;
+		Set<ISymbianSDK> appSdks = new HashSet<ISymbianSDK>();
+		if (settings.haveRomOnly || settings.haveAppRom) {
+			romSdk = settings.romSdk;
+		}
+		
+		// update viewer
+		if (settings.haveAppRom || settings.haveAppOnly) {		
+			for (ICarbideBuildConfiguration config: buildConfigList) {
+				appSdks.add(config.getSDK());
+			}
+			
+			for (IPkgEntry pkgEntry : appFileList) {
+				appSdks.add(pkgEntry.getSdk());
+			}
+		}
+
+		BupProfileTreeViewer.BupProfileTreeData data = profileTreeViewer.new BupProfileTreeData(romSdk, appSdks);
+		profileTreeViewer.setInput(data);
+		profileTreeViewer.expandAll();
+		
+		// select profile or post rationale
+		// ROM CustKit
+		if (settings.haveRomOnly || settings.haveAppRom) {
+			ArrayList<IBupEventMapProfile> profiles = BupEventMapManager.getInstance().getProfilesFromSDK(settings.romSdk);
+			if (profiles.size() == 1) {
+				IBupEventMapProfile profile = profiles.get(0);
+				rationaleText.setText(Messages.getString("NewPIWizardPageBupMapTask.6") + profile.getProfileId() + Messages.getString("NewPIWizardPageBupMapTask.7") + profile.getSDK().getUniqueId()+ Messages.getString("NewPIWizardPageBupMapTask.8")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				profileTreeViewer.collapseAll();
+				profileTreeViewer.reveal(profile);
+				profileTreeViewer.setSelection(new StructuredSelection(profile));
+				return true;
+
+			} else {
+				if (profiles.size() == 0) {
+					if (new File(BupEventMapManager.getInstance().profileLocatationInSDK(settings.romSdk)).exists() == false) {
+						rationaleText.setText(Messages.getString("NewPIWizardPageBupMapTask.21") + settings.romSdk.getUniqueId() + Messages.getString("NewPIWizardPageBupMapTask.22")); //$NON-NLS-1$ //$NON-NLS-2$
+					} else {
+						rationaleText.setText(Messages.getString("NewPIWizardPageBupMapTask.16") + settings.romSdk.getUniqueId() + Messages.getString("NewPIWizardPageBupMapTask.20")); //$NON-NLS-1$ //$NON-NLS-2$
+					}
+				} else {
+					rationaleText.setText(Messages.getString("NewPIWizardPageBupMapTask.9") + settings.romSdk.getUniqueId() +Messages.getString("NewPIWizardPageBupMapTask.10")); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+		}
+		
+		if (settings.haveAppRom || settings.haveAppOnly) {
+			ArrayList<ISymbianSDK> sdks = new ArrayList<ISymbianSDK>();
+			
+			for (ICarbideBuildConfiguration config: buildConfigList) {
+				sdks.add(config.getSDK());
+			}
+			
+			for (IPkgEntry pkgEntry : appFileList) {
+				sdks.add(pkgEntry.getSdk());
+			}
+			
+			if (sdks.size() == 1) {
+				ArrayList<IBupEventMapProfile> profiles = BupEventMapManager.getInstance().getProfilesFromSDK(sdks.get(0));
+				if (profiles.size() == 1) {
+					IBupEventMapProfile profile = profiles.get(0);
+					rationaleText.setText(Messages.getString("NewPIWizardPageBupMapTask.11") + profile.getProfileId() + Messages.getString("NewPIWizardPageBupMapTask.12") + profile.getSDK().getUniqueId()+ Messages.getString("NewPIWizardPageBupMapTask.13")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					profileTreeViewer.collapseAll();
+					profileTreeViewer.reveal(profile);
+					profileTreeViewer.setSelection(new StructuredSelection(profile));
+					return true;
+				} else {
+					rationaleText.setText(Messages.getString("NewPIWizardPageBupMapTask.14") + sdks.get(0).getUniqueId()+ Messages.getString("NewPIWizardPageBupMapTask.15")); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			} else {
+				String sdkList = ""; //$NON-NLS-1$
+				for (ISymbianSDK sdk : sdks) {
+					sdkList += Messages.getString("NewPIWizardPageBupMapTask.17") + sdk.getUniqueId() + Messages.getString("NewPIWizardPageBupMapTask.18"); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				rationaleText.setText(Messages.getString("NewPIWizardPageBupMapTask.19") + sdkList); //$NON-NLS-1$
+			}	
+		}
+		
+		profileTreeViewer.collapseAll();
+		profileTreeViewer.reveal(BupEventMapManager.getInstance().getPrefSelectedProfile());
+		profileTreeViewer.setSelection(new StructuredSelection(BupEventMapManager.getInstance().getPrefSelectedProfile()));
+
+		return false;
+	}
+	
+	public void setVisible(boolean visable) {
+		super.setVisible(visable);
+		if (visable) {
+			buildBupMapProfileList();
+			// need this because treeviewer depend on info from previous pages
+			setupPageFromFromNewPIWizardSettings();
+		}
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageConfigSelectorTask.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.CarbidePiWizardHelpIds;
+import com.nokia.carbide.cpp.ui.CarbideUIPlugin;
+import com.nokia.carbide.cpp.ui.ICarbideSharedImages;
+
+
+public class NewPIWizardPageConfigSelectorTask 
+extends NewPIWizardPage
+implements INewPIWizardSettings
+{
+
+	// control
+	private Composite composite = null;
+	private Group optionGroup = null;
+	private Composite appComposite = null;
+	private Composite appLabelComposite = null;
+	private Button buttonApp = null;
+	private Label labelAppTitle = null;
+	private Label labelApp2 = null;
+	private Composite romAppComposite = null;
+	private Composite romAppLabelComposite = null;
+	private Button buttonRomApp = null;
+	private Label labelRomAppTitle = null;
+	private Label labelRomApp2 = null;
+	private Label labelRomApp3 = null;
+	private Composite romComposite = null;
+	private Composite romLabelComposite = null;
+	private Button buttonRom = null;
+	private Label labelRomTitle = null;
+	private Label labelRom2 = null;
+	private Composite noneComposite = null;
+	private Composite noneLabelComposite = null;
+	private Button buttonNone = null;
+	private Label labelNoneTitle = null;
+	private Label labelNone2 = null;
+	private Label labelNone3 = null;
+	@SuppressWarnings("unused") //$NON-NLS-1$
+	private Group customTraceGroup = null;
+	@SuppressWarnings("unused") //$NON-NLS-1$
+	private Button buttonCustomTrace = null;
+	@SuppressWarnings("unused") //$NON-NLS-1$
+	private Label labelCustomTrace = null;
+
+	private ICarbideSharedImages carbideImages = CarbideUIPlugin.getSharedImages();
+	private Image phonensisImage = carbideImages.getImage(ICarbideSharedImages.IMG_PI_IMPORT_ROM_AND_APP_100_42);
+	private Image phoneImage = carbideImages.getImage(ICarbideSharedImages.IMG_PI_IMPORT_ROM_42_42);
+	private Image sisImage = carbideImages.getImage(ICarbideSharedImages.IMG_PI_IMPORT_APP_42_42);
+	private Image noneImage = carbideImages.getImage(ICarbideSharedImages.IMG_PI_IMPORT_NONE_100_42);
+	private Image cusTraceImage = carbideImages.getImage(ICarbideSharedImages.IMG_CUSTOM_TRACE_BADGE_24_24);
+
+	protected NewPIWizardPageConfigSelectorTask() {
+		super(Messages.getString("NewPIWizardPageConfigSelectorTask.title"));	//$NON-NLS-1$
+		setTitle(Messages.getString("NewPIWizardPageConfigSelectorTask.title")); //$NON-NLS-1$
+	    setDescription(Messages.getString("NewPIWizardPageConfigSelectorTask.description")); //$NON-NLS-1$
+	}
+
+	SelectionListener buttonListener = new SelectionListener () {
+		// handle all buttons including radio behavior among toggle
+		
+		public void widgetDefaultSelected(SelectionEvent arg0) {
+		}
+
+		public void widgetSelected(SelectionEvent arg0) {
+			buttonApp.setSelection(false);
+			buttonRomApp.setSelection(false);
+			buttonRom.setSelection(false);
+			buttonNone.setSelection(false);
+			((Button)arg0.widget).setSelection(true);
+			// write back to our status
+			NewPIWizardSettings.getInstance().haveAppRom = false;
+			NewPIWizardSettings.getInstance().haveAppOnly = false;
+			NewPIWizardSettings.getInstance().haveRomOnly = false;
+			NewPIWizardSettings.getInstance().haveNothing = false;
+			if (((Button)arg0.widget) == buttonRomApp) {
+				NewPIWizardSettings.getInstance().haveAppRom = true;
+			} else if (((Button)arg0.widget) == buttonApp) {
+				NewPIWizardSettings.getInstance().haveAppOnly = true;
+			} else if (((Button)arg0.widget) == buttonRom) {
+				NewPIWizardSettings.getInstance().haveRomOnly = true;
+			} else if (((Button)arg0.widget) == buttonNone) {
+				NewPIWizardSettings.getInstance().haveNothing = true;
+			}
+			validatePage();
+		}
+	};
+
+	public void createControl(Composite parent) {
+		super.createControl(parent);
+		GridLayout gridLayout1 = new GridLayout();
+		gridLayout1.numColumns = 1;
+		composite = new Composite (parent, SWT.NONE);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		composite.setLayout(gridLayout1);
+		GridLayout gridLayout2 = new GridLayout();
+		gridLayout2.numColumns = 1;
+		optionGroup = new Group(composite, SWT.NONE);
+		optionGroup.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, true));
+		optionGroup.setLayout(gridLayout2);
+		optionGroup.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.option.group")); //$NON-NLS-1$
+		labelAppTitle = new Label(optionGroup, SWT.NONE);
+		labelAppTitle.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.labelAppTitle")); //$NON-NLS-1$
+		createAppComposite();
+		labelRomAppTitle = new Label(optionGroup, SWT.NONE);
+		labelRomAppTitle.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.labelRomAppTitle")); //$NON-NLS-1$		
+		createRomAppComposite();
+		labelRomTitle = new Label(optionGroup, SWT.NONE);
+		labelRomTitle.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.labelRomTitle")); //$NON-NLS-1$				
+		createRomComposite();
+		labelNoneTitle = new Label(optionGroup, SWT.NONE);
+		labelNoneTitle.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.labelNoneTitle")); //$NON-NLS-1$				
+		createNoneComposite();
+//		createCustomComposite();
+		
+		GridData buttonWidthGridData = new GridData();
+		buttonWidthGridData.widthHint = Math.max(Math.max(Math.max(phonensisImage.getBounds().width, phoneImage.getBounds().width), sisImage.getBounds().width), noneImage.getBounds().width) + 30;
+		buttonWidthGridData.heightHint = Math.max(Math.max(Math.max(phonensisImage.getBounds().height, phoneImage.getBounds().height), sisImage.getBounds().height), noneImage.getBounds().height) + 30;
+		buttonRomApp.setLayoutData(buttonWidthGridData);
+		buttonRom.setLayoutData(buttonWidthGridData);
+		buttonApp.setLayoutData(buttonWidthGridData);
+		buttonNone.setLayoutData(buttonWidthGridData);
+		
+		setControl(composite);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), CarbidePiWizardHelpIds.PI_IMPORT_WIZARD_CONFIG_SELECTOR);
+		
+		validatePage();
+	}
+	
+	void createAppComposite() {
+		GridLayout gridLayout1 = new GridLayout();
+		gridLayout1.numColumns = 2;
+		appComposite = new Composite (optionGroup, SWT.NONE);
+		appComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, true));
+		appComposite.setLayout(gridLayout1);
+		buttonApp = new Button(appComposite, SWT.TOGGLE);
+		buttonApp.setImage(sisImage);
+		buttonApp.addSelectionListener(buttonListener);
+		GridLayout gridLayout2 = new GridLayout();
+		gridLayout2.numColumns = 1;
+		appLabelComposite = new Composite (appComposite, SWT.NONE);
+		appLabelComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, true));
+		appLabelComposite.setLayout(gridLayout2);
+		labelApp2 = new Label(appLabelComposite, SWT.NONE);
+		labelApp2.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.labelApp2")); //$NON-NLS-1$
+	}
+	
+	void createRomAppComposite() {
+		GridLayout gridLayout1 = new GridLayout();
+		gridLayout1.numColumns = 2;
+		romAppComposite = new Composite (optionGroup, SWT.NONE);
+		romAppComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, true));
+		romAppComposite.setLayout(gridLayout1);
+		buttonRomApp = new Button(romAppComposite, SWT.TOGGLE);
+		buttonRomApp.setImage(phonensisImage);
+		buttonRomApp.addSelectionListener(buttonListener);
+		GridLayout gridLayout2 = new GridLayout();
+		gridLayout2.numColumns = 1;
+		romAppLabelComposite = new Composite (romAppComposite, SWT.NONE);
+		romAppLabelComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, true));
+		romAppLabelComposite.setLayout(gridLayout2);
+		labelRomApp2 = new Label(romAppLabelComposite, SWT.NONE);
+		labelRomApp2.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.labelRomApp2")); //$NON-NLS-1$		
+		labelRomApp3 = new Label(romAppLabelComposite, SWT.NONE);
+		labelRomApp3.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.labelRomApp3")); //$NON-NLS-1$		
+	}
+	
+	void createRomComposite() {
+		GridLayout gridLayout1 = new GridLayout();
+		gridLayout1.numColumns = 2;
+		romComposite = new Composite (optionGroup, SWT.NONE);
+		romComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, true));
+		romComposite.setLayout(gridLayout1);
+		buttonRom = new Button(romComposite, SWT.TOGGLE);
+		buttonRom.setImage(phoneImage);
+		buttonRom.addSelectionListener(buttonListener);
+		GridLayout gridLayout2 = new GridLayout();
+		gridLayout2.numColumns = 1;
+		romLabelComposite = new Composite (romComposite, SWT.NONE);
+		romLabelComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, true));
+		romLabelComposite.setLayout(gridLayout2);
+		labelRom2 = new Label(romLabelComposite, SWT.NONE);
+		labelRom2.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.labelRom2")); //$NON-NLS-1$				
+	}
+	
+	void createNoneComposite() {
+		GridLayout gridLayout1 = new GridLayout();
+		gridLayout1.numColumns = 2;
+		noneComposite = new Composite (optionGroup, SWT.NONE);
+		noneComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, true));
+		noneComposite.setLayout(gridLayout1);
+		buttonNone = new Button(noneComposite, SWT.TOGGLE);
+		buttonNone.setImage(noneImage);
+		buttonNone.addSelectionListener(buttonListener);
+		GridLayout gridLayout2 = new GridLayout();
+		gridLayout2.numColumns = 1;
+		noneLabelComposite = new Composite (noneComposite, SWT.NONE);
+		noneLabelComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, true));
+		noneLabelComposite.setLayout(gridLayout2);
+		labelNone2 = new Label(noneLabelComposite, SWT.NONE);
+		labelNone2.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.labelNone2")); //$NON-NLS-1$				
+		labelNone3 = new Label(noneLabelComposite, SWT.NONE);
+		labelNone3.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.labelNone3")); //$NON-NLS-1$				
+	}
+
+	void createCustomComposite() {
+		GridLayout gridLayout3 = new GridLayout();
+		gridLayout3.numColumns = 2;
+		customTraceGroup = new Group(composite, SWT.NONE);
+		customTraceGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		customTraceGroup.setLayout(gridLayout3);
+		buttonCustomTrace = new Button(customTraceGroup, SWT.CHECK);
+		buttonCustomTrace.setImage(cusTraceImage);
+		buttonCustomTrace.addSelectionListener(buttonListener);
+		labelCustomTrace = new Label(customTraceGroup, SWT.WRAP);
+		labelCustomTrace.setText(Messages.getString("NewPIWizardPageConfigSelectorTask.labelCustomTrace")); //$NON-NLS-1$
+	}
+	
+	public void validatePage() {
+		if (buttonRomApp.getSelection() == false &&
+			buttonApp.getSelection() == false &&
+			buttonRom.getSelection() == false 
+			&&
+			buttonNone.getSelection() == false
+			) {
+			setPageComplete(false);
+		} else {
+			setPageComplete(true);
+		}
+		setErrorMessage(null);
+	}
+
+	public void setupPageFromFromNewPIWizardSettings() {
+		if (NewPIWizardSettings.getInstance().haveAppRom == true) {
+//			buttonApp.setSelection(false);
+//			buttonRomApp.setSelection(true);
+//			buttonRom.setSelection(false);
+			// set focus, and block them
+			buttonRomApp.setFocus();
+		} else if (NewPIWizardSettings.getInstance().haveAppOnly == true) {
+//			buttonApp.setSelection(true);
+//			buttonRomApp.setSelection(false);
+//			buttonRom.setSelection(false);
+			// set focus, and block them
+			buttonApp.setFocus();
+		} else if (NewPIWizardSettings.getInstance().haveRomOnly == true) {
+//			buttonApp.setSelection(false);
+//			buttonRomApp.setSelection(false);
+//			buttonRom.setSelection(true);
+//			 set focus, and block them
+			buttonRom.setFocus();
+		} else {
+			buttonNone.setFocus();
+		}
+		
+//		buttonCustomTrace.setSelection(NewPIWizardSettings.getInstance().enableCust);
+		
+		validatePage();
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageCustomTask.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import java.io.File;
+
+import org.eclipse.swt.SWT;
+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.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.CarbidePiWizardHelpIds;
+
+
+public class NewPIWizardPageCustomTask
+extends NewPIWizardPage
+implements INewPIWizardSettings
+{
+private final static String UID_PROPERTY= ".uid"; //$NON-NLS-1$
+private final static String DAT_EXTENSION= "dat"; //$NON-NLS-1$
+
+protected NewPIWizardPageCustomTask(final NewPIWizard wizard) {
+	super(Messages.getString("NewPIWizardPageCustomTask.super.label")); //$NON-NLS-1$
+	setTitle(Messages.getString("NewPIWizardPageCustomTask.title")); //$NON-NLS-1$
+    setDescription(Messages.getString("NewPIWizardPageCustomTask.description")); //$NON-NLS-1$
+}
+
+// controls
+Composite container;
+Group formatGroup;
+Composite optionComposite;
+Group exampleGroup;
+Group baseGroup;
+Group seperatorGroup;
+Button buttonValue;
+Button buttonName;
+Button buttonSemicolon;
+Button buttonComma;
+Button buttonSpace;
+
+private Text sampleFileText;
+
+public void createControl(Composite parent) {
+	super.createControl(parent);
+	container = new Composite(parent, SWT.NULL);
+	container.setData(UID_PROPERTY, "container"); //$NON-NLS-1$
+	GridLayout layout = new GridLayout();
+	container.setLayout(layout);
+	layout.numColumns = 1;
+	layout.verticalSpacing = 9;
+
+	Label labelDetailLabel = new Label(container, SWT.NONE);
+	labelDetailLabel.setText(Messages.getString("NewPIWizardPageCustomTask.detail.label")); //$NON-NLS-1$
+
+	Label labelSampleFile = new Label(container, SWT.NONE);
+	labelSampleFile.setText(Messages.getString("NewPIWizardPageSampleFile.dat.file.name")); //$NON-NLS-1$
+	
+	// subcomposite with textbox/button
+	Composite subContainer = new Composite(container, SWT.NULL);
+	subContainer.setData(UID_PROPERTY, "subContainer"); //$NON-NLS-1$
+	GridLayout subLayout = new GridLayout();
+	subContainer.setLayout(subLayout);
+	subContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+	subLayout.numColumns = 2;
+	subLayout.verticalSpacing = 9;
+
+	sampleFileText = new Text(subContainer, SWT.BORDER | SWT.SINGLE);
+	sampleFileText.setData(UID_PROPERTY, "sampleFileText"); //$NON-NLS-1$
+	sampleFileText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+	sampleFileText.addModifyListener(new ModifyListener() {
+		public void modifyText(ModifyEvent e) {
+			validatePage();
+		}
+	});
+
+	Button button = new Button(subContainer, SWT.PUSH);
+	button.setText(Messages.getString("NewPIWizardPageSampleFile.browse")); //$NON-NLS-1$
+	button.addSelectionListener(new SelectionAdapter() {
+		public void widgetSelected(SelectionEvent e) {
+			handleBrowse();
+		}
+	});
+	
+	// group with the options
+	formatGroup = new Group(container, SWT.NONE);
+	GridLayout groupLayout = new GridLayout();
+	groupLayout.numColumns = 2;
+	groupLayout.verticalSpacing = 9;
+	formatGroup.setLayout(groupLayout);
+	formatGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+	formatGroup.setText(Messages.getString("NewPIWizardPageCustomTask.format.group")); //$NON-NLS-1$
+	optionComposite = new Composite (formatGroup, SWT.NONE);
+	GridLayout optionLayout = new GridLayout();
+	optionLayout.numColumns = 1;
+	optionLayout.verticalSpacing = 9;
+	optionComposite.setLayout(optionLayout);
+	optionComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+	
+	exampleGroup = new Group(formatGroup, SWT.NONE);
+	GridLayout exampleLayout = new GridLayout();
+	exampleLayout.numColumns = 2;
+	exampleLayout.verticalSpacing = 9;
+	exampleGroup.setLayout(groupLayout);
+	exampleGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+	exampleGroup.setText(Messages.getString("NewPIWizardPageCustomTask.example.group")); //$NON-NLS-1$
+	Text exampleText = new Text(exampleGroup, SWT.NONE);
+	exampleText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+	baseGroup = new Group(optionComposite, SWT.NONE);
+	GridLayout baseLayout = new GridLayout();
+	baseLayout.numColumns = 1;
+	baseLayout.verticalSpacing = 9;
+	baseGroup.setLayout(optionLayout);
+	baseGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+	baseGroup.setText(Messages.getString("NewPIWizardPageCustomTask.base.group")); //$NON-NLS-1$
+	buttonValue = new Button(baseGroup, SWT.RADIO);
+	buttonValue.setText(Messages.getString("NewPIWizardPageCustomTask.button.value")); //$NON-NLS-1$
+	buttonName = new Button(baseGroup, SWT.RADIO);
+	buttonName.setText(Messages.getString("NewPIWizardPageCustomTask.button.name")); //$NON-NLS-1$
+	seperatorGroup = new Group(optionComposite, SWT.NONE);
+	GridLayout seperatorLayout = new GridLayout();
+	seperatorLayout.numColumns = 1;
+	seperatorLayout.verticalSpacing = 9;
+	seperatorGroup.setLayout(optionLayout);
+	seperatorGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+	seperatorGroup.setText(Messages.getString("NewPIWizardPageCustomTask.seperator.group")); //$NON-NLS-1$
+	buttonSemicolon = new Button(seperatorGroup, SWT.RADIO);
+	buttonSemicolon.setText(Messages.getString("NewPIWizardPageCustomTask.button.semicolon")); //$NON-NLS-1$
+	buttonComma = new Button(seperatorGroup, SWT.RADIO);
+	buttonComma.setText(Messages.getString("NewPIWizardPageCustomTask.button.comma")); //$NON-NLS-1$
+	buttonSpace = new Button(seperatorGroup, SWT.RADIO);
+	buttonSpace.setText(Messages.getString("NewPIWizardPageCustomTask.button.space")); //$NON-NLS-1$
+	
+	// fake default for demo
+	sampleFileText.setText(Messages.getString("NewPIWizardPageCustomTask.13")); //$NON-NLS-1$
+	buttonValue.setSelection(true);
+	buttonName.setSelection(false);
+	buttonSemicolon.setSelection(true);
+	buttonComma.setSelection(false);
+	buttonSpace.setSelection(false);
+	exampleText.setText(Messages.getString("NewPIWizardPageCustomTask.14")); //$NON-NLS-1$
+	
+	
+	validatePage();
+	setControl(container);
+	PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), CarbidePiWizardHelpIds.PI_IMPORT_WIZARD_CUSTOM);
+}
+
+public void validatePage() {
+	if (sampleFileText.getText().length() == 0) {
+		updateStatus(Messages.getString("NewPIWizardCustomTask.dat.file.name.must.be.specified")); //$NON-NLS-1$
+		return;
+	}
+	int dotLoc = sampleFileText.getText().lastIndexOf('.');
+	if (dotLoc != -1) {
+		String ext = sampleFileText.getText().substring(dotLoc + 1);
+		if (ext.equalsIgnoreCase(DAT_EXTENSION) == false) {
+			updateStatus(Messages.getString("NewPIWizardPageSampleFile.dat.file.extension.must.be.dat")); //$NON-NLS-1$
+			return;
+		}
+	}
+
+
+	if (!(new File(sampleFileText.getText()).exists())) {
+		updateStatus(Messages.getString("NewPIWizardPageSampleFile.dat.file.name.does.not.exist")); //$NON-NLS-1$
+		return;
+	}
+	if (!(new File(sampleFileText.getText()).isFile())) {
+		updateStatus(Messages.getString("NewPIWizardPageSampleFile.dat.must.be.a.file")); //$NON-NLS-1$
+		return;		
+	}
+
+	updateStatus(null);
+}
+
+private void updateStatus(String message) {
+	// need to enable finish, setPageComplete eventually check global states
+	writePageDataToNewPIWizardSettings();
+	setErrorMessage(message);
+	setPageComplete(message == null);
+}
+	
+private void handleBrowse() {
+	FileDialog dialog = new FileDialog(getShell());
+	String[] datExtensions = {"*.dat", //$NON-NLS-1$
+//								"*.base64",
+								"*.*"}; //$NON-NLS-1$
+	String[] datNames = {Messages.getString("NewPIWizardPageSampleFile.sample.filter.name"), //$NON-NLS-1$
+//							"Profiler Sample Files (*.base64)",
+							Messages.getString("NewPIWizardPageSampleFile.all.filter.name")}; //$NON-NLS-1$
+	dialog.setFilterExtensions(datExtensions);
+	dialog.setFilterNames(datNames);
+	// Try guiding user to path user is trying to fill
+	File clueFile = new File(sampleFileText.getText());
+	String cluePath = null;
+	if (clueFile.isDirectory()) {
+		cluePath = clueFile.getAbsolutePath();
+	} else {
+		cluePath = clueFile.getParent();
+	}
+	if (cluePath != null) {
+		dialog.setFilterPath(cluePath);
+	}
+	String filePath = dialog.open();
+
+	if (filePath != null) {
+		if (filePath.length() > 0) {
+			sampleFileText.setText(filePath);
+		}
+	}		
+}
+
+public void writePageDataToNewPIWizardSettings() {
+}
+
+public void setupPageFromFromNewPIWizardSettings() {
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageInputTask.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.swt.SWT;
+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.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.StreamFileParser;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.CarbidePiWizardHelpIds;
+
+
+
+public class NewPIWizardPageInputTask
+extends NewPIWizardPage
+implements INewPIWizardSettings
+{
+	private final static String UID_PROPERTY= ".uid"; //$NON-NLS-1$
+	private final static String DAT_EXTENSION= "dat"; //$NON-NLS-1$
+	private boolean visableBefore = false;
+
+	protected NewPIWizardPageInputTask(final NewPIWizard wizard) {
+		super(Messages.getString("NewPIWizardPageSampleFile.name")); //$NON-NLS-1$
+		setTitle(Messages.getString("NewPIWizardPageSampleFile.title")); //$NON-NLS-1$
+	    setDescription(Messages.getString("NewPIWizardPageSampleFile.description")); //$NON-NLS-1$
+	}
+
+	// controls
+	Composite container;
+	private Text sampleFileTexti;
+	private Combo sampleFileCombo;
+
+	public void createControl(Composite parent) {
+		super.createControl(parent);
+		container = new Composite(parent, SWT.NULL);
+		container.setData(UID_PROPERTY, "container"); //$NON-NLS-1$
+		GridLayout layout = new GridLayout();
+		container.setLayout(layout);
+		layout.numColumns = 1;
+		layout.verticalSpacing = 9;
+
+		Label labelSampleFile = new Label(container, SWT.NONE);
+		labelSampleFile.setText(Messages.getString("NewPIWizardPageSampleFile.dat.file.name")); //$NON-NLS-1$
+		
+		// subcomposite with textbox/button
+		Composite subContainer = new Composite(container, SWT.NULL);
+		subContainer.setData(UID_PROPERTY, "subContainer"); //$NON-NLS-1$
+		GridLayout subLayout = new GridLayout();
+		subContainer.setLayout(subLayout);
+		subContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		subLayout.numColumns = 2;
+		subLayout.verticalSpacing = 9;
+
+		/*
+		sampleFileText = new Text(subContainer, SWT.BORDER | SWT.SINGLE);
+		sampleFileText.setData(UID_PROPERTY, "sampleFileText"); //$NON-NLS-1$
+		sampleFileText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		sampleFileText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				// write back to our status
+				NewPIWizardSettings.getInstance().sampleFileName = sampleFileText.getText();
+				NewPIWizardSettings.getInstance().sampleFileNameModifiedNanoTime = System.nanoTime();
+				validatePage();
+			}
+		});*/
+		
+		sampleFileCombo = new Combo(subContainer, SWT.BORDER | SWT.SINGLE);
+		sampleFileCombo.setData(UID_PROPERTY, "sampleFileText"); //$NON-NLS-1$
+		sampleFileCombo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		sampleFileCombo.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				// write back to our status
+				NewPIWizardSettings.getInstance().sampleFileName = sampleFileCombo.getText();
+				NewPIWizardSettings.getInstance().sampleFileNameModifiedNanoTime = System.nanoTime();
+				validatePage();
+			}
+		});
+
+		Button button = new Button(subContainer, SWT.PUSH);
+		button.setText(Messages.getString("NewPIWizardPageSampleFile.browse")); //$NON-NLS-1$
+		button.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				handleBrowse();
+			}
+		});
+			
+		// top tap get focus
+		sampleFileCombo.setFocus();
+
+
+		setControl(container);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), CarbidePiWizardHelpIds.PI_IMPORT_WIZARD_INPUT);
+	}
+
+	public void validatePage() {
+		if (sampleFileCombo.getText() == null || sampleFileCombo.getText().length() < 1) {
+			
+			updateStatus(null);
+			setPageComplete(false);
+			return;		// blank should be OK, consistent with Eclipse guideline
+		}
+		
+		int dotLoc = sampleFileCombo.getText().lastIndexOf('.');
+
+		if (dotLoc != -1) {
+			String ext = sampleFileCombo.getText().substring(dotLoc + 1);
+
+			if (ext.equalsIgnoreCase(DAT_EXTENSION) == false) {
+				updateStatus(Messages.getString("NewPIWizardPageSampleFile.dat.file.extension.must.be.dat")); //$NON-NLS-1$
+				return;
+			}
+		}
+
+		if (!(new File(sampleFileCombo.getText()).exists())) {
+			updateStatus(Messages.getString("NewPIWizardPageSampleFile.dat.file.name.does.not.exist")); //$NON-NLS-1$
+			return;
+		}
+		if (!(new File(sampleFileCombo.getText()).isFile())) {
+
+			updateStatus(Messages.getString("NewPIWizardPageSampleFile.dat.must.be.a.file")); //$NON-NLS-1$
+			return;		
+		}
+
+		try {
+			((NewPIWizard)getWizard()).setTraceSet(new StreamFileParser(new File(sampleFileCombo.getText())).allTraceType());
+
+		} catch (IOException e) {
+			// just ignore
+		}
+		setPageComplete(true);
+		updateStatus(null);
+	}
+
+	private void updateStatus(String message) {
+		// need to enable finish, setPageComplete eventually check global states
+		setErrorMessage(message);
+		setPageComplete(message == null);
+	}
+		
+	private void handleBrowse() {
+		FileDialog dialog = new FileDialog(getShell());
+		String[] datExtensions = {"*.dat", //$NON-NLS-1$
+//									"*.base64",
+									"*.*"}; //$NON-NLS-1$
+		String[] datNames = {Messages.getString("NewPIWizardPageSampleFile.sample.filter.name"), //$NON-NLS-1$
+//								"Profiler Sample Files (*.base64)",
+								Messages.getString("NewPIWizardPageSampleFile.all.filter.name")}; //$NON-NLS-1$
+		dialog.setFilterExtensions(datExtensions);
+		dialog.setFilterNames(datNames);
+		// Try guiding user to path user is trying to fill
+		File clueFile = new File(sampleFileCombo.getText());
+
+		String cluePath = null;
+		if (clueFile.isDirectory()) {
+			cluePath = clueFile.getAbsolutePath();
+		} else {
+			cluePath = clueFile.getParent();
+		}
+		if (cluePath != null) {
+			dialog.setFilterPath(cluePath);
+		}
+		String filePath = dialog.open();
+
+		if (filePath != null) {
+			if (filePath.length() > 0) {
+				sampleFileCombo.setText(filePath);
+
+			}
+		}		
+	}
+
+	public void setupPageFromFromNewPIWizardSettings() {
+		
+		String[] items = NewPIWizardSettings.getInstance().sampleFileNames;
+		if (items != null){
+			sampleFileCombo.setItems(items);
+			sampleFileCombo.select(0);
+		}
+	}
+
+	public void setVisible(boolean visable) {
+		super.setVisible(visable);
+		
+		if (visable) {
+			// block the text if it's wrong on startup, so user know what's wrong
+			if (visableBefore == false && getErrorMessage() != null) {
+				sampleFileCombo.select(0);
+
+			}
+		}
+		visableBefore = visable;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageOutputTask.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.viewers.DecoratingLabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
+
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.CarbidePiWizardHelpIds;
+
+public class NewPIWizardPageOutputTask extends NewPIWizardPage implements INewPIWizardSettings {
+	
+	private final static String DOT_NPI= ".npi"; //$NON-NLS-1$
+	private final static String EMPTY_STRING = ""; //$NON-NLS-1$
+
+	// Provides all folder in workspace
+	private class ProjectContentProvider
+	extends WorkbenchContentProvider
+	implements ITreeContentProvider
+	{
+		// local version just to prevent getChildren/hadChild stuck
+		// calling each other
+		private Object[] localGetChildren(Object arg0) {
+			ArrayList<Object> returnList = new ArrayList<Object>();
+			Object[] children = super.getChildren(arg0);
+			for (Object child: children) {
+				if (child instanceof IViewSite || 
+					child instanceof IWorkspaceRoot || 
+					child instanceof IFolder)
+				{
+					returnList.add(child);
+				} else if (child instanceof IProject) {
+					if (((IProject)child).isOpen()) {
+						returnList.add(child);
+					}
+				}
+			}
+			return returnList.toArray(new Object[returnList.size()]);
+		}
+
+		public Object[] getChildren(Object arg0) {
+			return localGetChildren(arg0);
+		}
+
+		public Object getParent(Object arg0) {
+			return super.getParent(arg0);
+		}
+
+		public boolean hasChildren(Object arg0) {
+			if (localGetChildren(arg0).length > 0) {
+				return true;
+			}
+			return false;
+		}
+
+		public Object[] getElements(Object arg0) {
+			return super.getElements(arg0);
+		}
+
+		public void dispose() {
+			super.dispose();
+		}
+
+		public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
+			super.inputChanged(arg0, arg1, arg2);
+		}
+	}
+	
+	// control
+	private Composite composite = null;
+	private Composite projectComposite = null;
+	private Composite buttonComposite = null;
+	private TreeViewer outputChooserTreeViewer = null;
+	private Button createButton = null;
+	private Label fileLabel = null;
+	private Text outputText = null;
+	
+	protected NewPIWizardPageOutputTask() {
+		super(""); //$NON-NLS-1$
+		setTitle(Messages.getString("NewPIWizardPageOutputTask.output.file.and.project")); //$NON-NLS-1$
+	    setDescription(Messages.getString("NewPIWizardPageOutputTask.select.folder.or.create.new.project.as.output.file.container")); //$NON-NLS-1$
+	}
+
+	public void validatePage() {
+		if (outputText.getText().length() < 1 || outputChooserTreeViewer.getTree().getSelection().length < 1) {
+			setErrorMessage(Messages.getString("NewPIWizardPageOutputTask.choose.output.project")); //$NON-NLS-1$
+			setPageComplete(false);
+			return;
+		}
+		setErrorMessage(null);
+		setPageComplete(true);
+		return;
+	}
+
+	public void createControl(Composite parent) {
+		super.createControl(parent);
+		GridLayout gridLayout1 = new GridLayout();
+		gridLayout1.numColumns = 1;
+		composite = new Composite(parent, SWT.NONE);
+		composite.setLayout(gridLayout1);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		createProjectComposite();
+		fileLabel = new Label (composite, SWT.NONE);
+		fileLabel.setText(Messages.getString("NewPIWizardPageOutputTask.output.file.name")); //$NON-NLS-1$
+		outputText = new Text(composite, SWT.BORDER);
+		outputText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		outputText.addSelectionListener(new SelectionListener () {
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				validatePage();
+			}	
+		});
+		outputText.addModifyListener(new ModifyListener() {
+
+			public void modifyText(ModifyEvent arg0) {
+				NewPIWizardSettings.getInstance().piFileName = outputText.getText();		
+				NewPIWizardSettings.getInstance().piFileNameModifiedNanoTime = System.nanoTime();
+			}
+			
+		});
+		
+		validatePage();
+
+		setControl(composite);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), CarbidePiWizardHelpIds.PI_IMPORT_WIZARD_OUTPUT);		
+	}
+	
+	/**
+	 * This method initializes projectComposite	
+	 *
+	 */
+	private void createProjectComposite() {
+		GridLayout gridLayout2 = new GridLayout();
+		gridLayout2.numColumns = 2;
+		projectComposite = new Composite(composite, SWT.NONE);
+		projectComposite.setLayout(gridLayout2);
+		projectComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		outputChooserTreeViewer = new TreeViewer(projectComposite, SWT.BORDER);
+		outputChooserTreeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		outputChooserTreeViewer.setContentProvider(new ProjectContentProvider());
+		outputChooserTreeViewer.setLabelProvider(new DecoratingLabelProvider(
+								new WorkbenchLabelProvider(), 
+								PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator()));
+		outputChooserTreeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot());
+		outputChooserTreeViewer.getTree().addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				outputText.setText(generateNpiFileName(outputText.getText()));
+				validatePage();
+			}
+		});
+		outputChooserTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+
+			public void selectionChanged(SelectionChangedEvent arg0) {
+				TreeSelection selection = (TreeSelection) outputChooserTreeViewer.getSelection();
+				if (selection != null) {
+					Object selected = selection.getFirstElement();
+					if (selected != null) {
+						if (selected instanceof IContainer) {
+							NewPIWizardSettings.getInstance().outputContainer = (IContainer) selected;
+						}
+					}
+				}
+			}
+		});
+
+		createButtonComposite();
+	}
+	
+	private void createButtonComposite() {
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 1;
+		buttonComposite = new Composite(projectComposite, SWT.NONE);
+		buttonComposite.setLayout(gridLayout);
+		buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
+		createButton = new Button(buttonComposite, SWT.PUSH);
+		createButton.setText(Messages.getString("NewPIWizardPageOutputTask.create.empty.project")); //$NON-NLS-1$
+		createButton.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				// get a standard Eclipse Wizard for creating folder
+				IWorkbenchWizard wizard = new BasicNewProjectResourceWizard();
+				wizard.init(PlatformUI.getWorkbench(), new TreeSelection());
+				WizardDialog dialog = new WizardDialog(getShell(), wizard);
+				dialog.open();
+				if (outputChooserTreeViewer.getTree().getItemCount() == 1) {
+					outputText.setText(generateNpiFileName(outputText.getText()));
+					validatePage();
+				}
+			}
+			
+		});
+	}
+	
+	private boolean isPositiveLong(String x) {
+		try {
+			if (Long.parseLong(x) >= 0) {
+				return true;
+			}
+		} catch (NumberFormatException e) {
+			return false;
+		}
+		return false;
+	}
+	
+	private String generateNpiFileName(String initialFilename) {
+		// First look for the container
+		IContainer container = NewPIWizardSettings.getInstance().outputContainer;
+		
+		TreeSelection selection = (TreeSelection) outputChooserTreeViewer.getSelection();
+		if (selection == null)
+			return EMPTY_STRING;
+		if (selection.getFirstElement() == null)
+			return EMPTY_STRING;
+		if ((selection.getFirstElement() instanceof IContainer) == false)
+			return EMPTY_STRING;
+		container = (IContainer) selection.getFirstElement();				
+		try {
+			// in case user dump a file of the same name without telling eclipse
+			container.refreshLocal(1, null);
+		} catch (CoreException e) {
+			// this is likely harmless
+			e.printStackTrace();
+		}
+
+		// Then see if we find a matching file name
+		initialFilename.trim();
+		if (initialFilename.length()==0) {
+			// generate from sample file if input file is empty
+			initialFilename = NewPIWizardSettings.getInstance().sampleFileName;
+		}
+		// get just the file name(last part)
+		initialFilename = new java.io.File(initialFilename).getName();
+		
+		String baseName;
+		Long suffixNumber = new Long(0);
+		
+		int dot = initialFilename.lastIndexOf("."); //$NON-NLS-1$
+		if (dot > 1) {
+			baseName = initialFilename.substring(0, dot); //$NON-NLS-1$
+		} else {
+			baseName = initialFilename;
+		}
+		
+		if (initialFilename.endsWith(".npi")) {	//$NON-NLS-1$
+			// the input is a .npi doesn't exist in container, user should have manually typed it
+			if (container.getFile(new Path(initialFilename)).exists() == false) {
+				return initialFilename;
+			}
+			
+			// this is probably an ***_<number>.npi we need to increament
+			// just suffix _<number> if the name was derived from input sample name
+			if (baseName.lastIndexOf("_") > 1 && 	//$NON-NLS-1$
+				isPositiveLong(baseName.substring(baseName.lastIndexOf("_") + 1)))	//$NON-NLS-1$
+			{
+				suffixNumber = Long.parseLong(baseName.substring(baseName.lastIndexOf("_") + 1)); //$NON-NLS-1$
+				baseName = baseName.substring(0, baseName.lastIndexOf("_"));	//$NON-NLS-1$
+			}
+		}
+				
+		// check existing npi and bump number
+		while (container.getFile(new Path(baseName + "_" + suffixNumber.toString() + DOT_NPI)).exists()) { //$NON-NLS-1$
+			suffixNumber++;
+		}
+
+		return baseName + "_" + suffixNumber.toString() + DOT_NPI; //$NON-NLS-1$
+	}
+
+	public void setupPageFromFromNewPIWizardSettings() {
+		outputChooserTreeViewer.getTree().deselectAll();
+		if (NewPIWizardSettings.getInstance().outputContainer == null || 
+				NewPIWizardSettings.getInstance().outputContainer.exists() == false ||
+				outputChooserTreeViewer.getSelection() == null ||
+				outputChooserTreeViewer.getSelection().isEmpty()) {
+			// stupid eclipse guideline for default container when we found out how to do it
+			NewPIWizardSettings.getInstance().outputContainer = findDefaultContainer();
+		}
+		if (NewPIWizardSettings.getInstance().outputContainer == null ) {
+			// select it if it's the only one output project
+			if (outputChooserTreeViewer.getTree().getItemCount() == 1) {
+				outputChooserTreeViewer.setSelection(new StructuredSelection(outputChooserTreeViewer.getTree().getItem(0)));
+			}
+		} else {
+			// highlight all items select by expanding to that level
+			// restoring from file system persist data could use this
+			outputChooserTreeViewer.expandToLevel(NewPIWizardSettings.getInstance().outputContainer, 0);
+			outputChooserTreeViewer.setSelection(new StructuredSelection(NewPIWizardSettings.getInstance().outputContainer));
+		}
+		// setup using last session persisted. If user changed input file, 
+		// regenerateOutputIfIntputChanged() will derive the new output name base on input 
+		// upon finish, or output page become visible
+		outputText.setText(generateNpiFileName(NewPIWizardSettings.getInstance().piFileName));
+		validatePage();
+	}
+
+	private IContainer findDefaultContainer() {
+		IContainer result = null;
+		ISelection selection = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection();
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+			Object firstElement = structuredSelection.getFirstElement();
+			if (firstElement instanceof IFile) {
+				result = ((IFile)firstElement).getParent();
+			} else if (firstElement instanceof IContainer) {
+				result = (IContainer) firstElement;
+			}
+		}
+		if (result == null) {
+			try {
+				IResource[] resources = ResourcesPlugin.getWorkspace().getRoot().members();
+				for (IResource resource : resources) {
+					if (resource instanceof IContainer) {
+						result = (IContainer) resource;
+						break;
+					}
+				}
+			} catch (CoreException e) {
+				e.printStackTrace();
+			}
+		}
+		return result;
+	}
+
+	public void regenerateOutputIfIntputChanged() {
+		// if both time stamps are set and input sample is later than NPI, regenerate it
+		if (NewPIWizardSettings.getInstance().sampleFileNameModifiedNanoTime != 0 &&
+			NewPIWizardSettings.getInstance().piFileNameModifiedNanoTime != 0 &&
+			NewPIWizardSettings.getInstance().sampleFileNameModifiedNanoTime - NewPIWizardSettings.getInstance().piFileNameModifiedNanoTime > 0) {
+			outputText.setText(generateNpiFileName(NewPIWizardSettings.getInstance().sampleFileName));
+		}
+	}
+	
+	public void setVisible(boolean visable) {
+		super.setVisible(visable);
+		if (visable) {
+			// see if we input changed
+			regenerateOutputIfIntputChanged();
+			validatePage();
+		}
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPagePkgListTask.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.viewers.DecoratingLabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.swt.SWT;
+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.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cdt.builder.project.ICarbideBuildConfiguration;
+import com.nokia.carbide.cdt.builder.project.ISISBuilderInfo;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.CarbidePiWizardHelpIds;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.IPkgEntry;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.PkgEntryList;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.PkgListTree;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.PkgListTreeContentProvider;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.PkgListTreeLabelProvider;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.PkgListTreeViewer;
+
+public class NewPIWizardPagePkgListTask 
+extends NewPIWizardPage 
+implements INewPIWizardSettings {
+
+	// control
+	private Composite composite = null;
+//	private Label label = null;
+	private PkgListTreeViewer projectTreeViewer;
+	private Composite filelistComposite = null;
+	private Composite buttonComposite = null;	
+	private Button addPkgButton = null;
+	private Button removeButton = null;
+	
+	// data model
+	PkgListTree pkgListRoot = null;
+
+	protected NewPIWizardPagePkgListTask() {
+		super(""); //$NON-NLS-1$
+		setTitle(Messages.getString("NewPIWizardPagePkgListTask.title")); //$NON-NLS-1$
+	    setDescription(Messages.getString("NewPIWizardPagePkgListTask.description"));	 //$NON-NLS-1$
+	}
+
+	public void createControl(Composite parent) {
+		super.createControl(parent);
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 1;
+		composite = new Composite(parent, SWT.NONE);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		composite.setLayout(gridLayout);
+//		label = new Label(composite, SWT.NONE);
+//		label.setText(Messages.getString("NewPIWizardPagePkgListTask.label")); //$NON-NLS-1$
+		createFilelistComposite();
+		setControl(composite);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), CarbidePiWizardHelpIds.PI_IMPORT_WIZARD_PKG_LIST);
+	}
+	
+	/**
+	 * This method initializes filelistComposite	
+	 *
+	 */
+	private void createFilelistComposite() {
+		GridLayout gridLayout2 = new GridLayout();
+		gridLayout2.numColumns = 2;
+		filelistComposite = new Composite(composite, SWT.NONE);
+		filelistComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		filelistComposite.setLayout(gridLayout2);
+		projectTreeViewer = new PkgListTreeViewer(filelistComposite, SWT.H_SCROLL | SWT.BORDER);
+		pkgListRoot = new PkgListTree();
+		projectTreeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		projectTreeViewer.setContentProvider(new PkgListTreeContentProvider(pkgListRoot));
+		projectTreeViewer.setLabelProvider(new DecoratingLabelProvider(
+				new PkgListTreeLabelProvider(), PlatformUI.getWorkbench()
+                        .getDecoratorManager().getLabelDecorator()));
+		projectTreeViewer.setInput(pkgListRoot);
+		projectTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+
+			public void selectionChanged(SelectionChangedEvent arg0) {
+				ISelection selection = arg0.getSelection();
+				// if selecting disabled item, ditch the selection and restore viewer
+				// selection using data object
+				if (selection instanceof TreeSelection) {
+					TreeSelection treeSelection = (TreeSelection) selection;
+					TreePath[] paths = treeSelection.getPaths();
+					if (paths.length == 1) {
+						if (projectTreeViewer.getElementEnabled(paths[0].getLastSegment()) == false) {
+							setupPageFromFromNewPIWizardSettings();
+						}
+					}
+				}
+				NewPIWizardSettings npiws = NewPIWizardSettings.getInstance();
+				npiws.selectedAppFileList.clear();
+				for (IPkgEntry pkg : projectTreeViewer.getSelectedPkgs()) {
+					npiws.selectedAppFileList.add(pkg);
+				}
+				npiws.selectedProjectList.clear();
+				for (IProject project : projectTreeViewer.getSelectedProjects()) {
+					npiws.selectedProjectList.add(project);
+				}
+				npiws.selectedBuildConfigList.clear();
+				for (ICarbideBuildConfiguration config : projectTreeViewer.getSelectedConfigs()) {
+					npiws.selectedBuildConfigList.add(config);
+				}
+				npiws.availableAppFileList.clear();
+				IPkgEntry[] allPkg = pkgListRoot.getPkgEntries();
+				for (IPkgEntry pkg: allPkg) {
+					npiws.availableAppFileList.add(pkg);
+				}
+			}	
+		});
+		projectTreeViewer.expandToLevel(2);	// just to project level
+				
+		createButtonComposite();
+	}
+
+	/**
+	 * This method initializes buttonComposite	
+	 *
+	 */
+	private void createButtonComposite() {
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 1;
+		buttonComposite = new Composite(filelistComposite, SWT.NONE);
+		buttonComposite.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
+		buttonComposite.setLayout(gridLayout);
+		addPkgButton = new Button(buttonComposite, SWT.PUSH);
+		addPkgButton.setText(Messages.getString("NewPIWizardPagePkgListTask.pkg.button")); //$NON-NLS-1$
+		removeButton = new Button(buttonComposite, SWT.PUSH);
+		removeButton.setText(Messages.getString("NewPIWizardPagePkgListTask.remove.button")); //$NON-NLS-1$
+
+		GridData buttonWidthGridData = new GridData();
+		buttonWidthGridData.widthHint = Math.max(addPkgButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x, removeButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
+		addPkgButton.setLayoutData(buttonWidthGridData);
+		removeButton.setLayoutData(buttonWidthGridData);
+		addPkgButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				handleAddPkg();
+			}	
+		});
+		removeButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				handleRemovePkg();
+			}	
+		});
+	}
+	
+	private void handleAddPkg() {
+		String pkgFilePath;
+		FileDialog dialog = new FileDialog(getShell());
+		String[] pkgExtensions = {"*.pkg", //$NON-NLS-1$
+									"*.*"}; //$NON-NLS-1$
+		String[] pkgNames = {Messages.getString("NewPIWizardPagePkgListTask.pkg.filter.name"), //$NON-NLS-1$
+								Messages.getString("NewPIWizardPagePkgListTask.all.filter.name")}; //$NON-NLS-1$
+		dialog.setFilterExtensions(pkgExtensions);
+		dialog.setFilterNames(pkgNames);
+		pkgFilePath = dialog.open();
+		
+		if (pkgFilePath != null) {
+			NewPIWizardPagePkgSdkDialog sdkDialog = new NewPIWizardPagePkgSdkDialog(getShell());
+			if (sdkDialog.open() == NewPIWizardPagePkgSdkDialog.OK) {
+				IPkgEntry pkgEntry = PkgEntryList.getInstance().getPkgEntry(pkgFilePath, sdkDialog.getSelection());
+				boolean found = false;
+				for (IPkgEntry entry : pkgListRoot.getPkgEntries()) {
+					if (pkgEntry.equals(entry)) {
+						found = true;
+						break;
+					}
+				}
+				if (found == false) {
+					pkgListRoot.addPkgEntry(pkgEntry);
+				}
+				removeButton.setEnabled(pkgListRoot.getPkgEntries().length != 0);
+				// only expanded/visible items are available for selecting programatically
+				projectTreeViewer.reveal(pkgEntry);		
+				// This shows the new PKG in UI and force associate of the new PKG, so we can select later
+				projectTreeViewer.refresh();
+				//projectTreeViewer.initializeSelectedItems(selectedObjects.toArray());
+				// reveal is not necessary, but we do it for safety
+			}
+		}
+	}
+
+	private void handleRemovePkg() {
+		NewPIWizardRemovePkgDialog removeDialog = new NewPIWizardRemovePkgDialog(getShell(), pkgListRoot.getPkgEntries());
+		removeDialog.open();
+		IPkgEntry[] removeList = removeDialog.getRemovedList();
+		if (removeList != null) {
+			for (int i = 0; i < removeList.length; i++) {
+				pkgListRoot.removePkgEntry(removeList[i]);
+			}
+			removeButton.setEnabled(pkgListRoot.getPkgEntries().length != 0);
+			projectTreeViewer.refresh();	
+		}
+	}
+	
+	public void setupPageFromFromNewPIWizardSettings() {
+		NewPIWizardSettings npiws = NewPIWizardSettings.getInstance();
+		ArrayList<TreePath> selectedPath = new ArrayList<TreePath>();
+		pkgListRoot.removeAllPkgEntries();
+		
+		// Build TreePath for all selected configurations and their project parent
+		ICarbideBuildConfiguration needToUnselect = null;
+		for (ICarbideBuildConfiguration selected : npiws.selectedBuildConfigList) {
+			List<ISISBuilderInfo> sisBuilderInfoList = selected.getSISBuilderInfoList();
+			boolean allPkgGood = true && sisBuilderInfoList.size() > 0;
+			for (ISISBuilderInfo sisBuilderInfo : sisBuilderInfoList)
+			{
+				if (sisBuilderInfo == null) {
+					allPkgGood = false;
+				} else if (sisBuilderInfo.getPKGFullPath().toFile().exists() == false) {
+					allPkgGood = false;
+				}
+		
+			}
+			if (allPkgGood) {
+				TreePath configPath = projectTreeViewer.getTreePathForElement(selected);
+				if (configPath != null) {
+					selectedPath.add(configPath);
+				}
+				// check the project as well
+				TreePath projectPath = projectTreeViewer.getTreePathForElement(selected.getCarbideProject().getProject());
+				if (projectPath != null) {
+					selectedPath.add(projectPath);
+				}
+			} else {
+				needToUnselect = selected;	// selected configuration have non-exist PKG, need to unselect this later
+			}
+		}
+		if(needToUnselect != null) {
+			npiws.selectedBuildConfigList.remove(needToUnselect);
+		}
+		for (IProject selected : npiws.selectedProjectList) {
+			// We deal with this when we set a build config
+		}
+		for (IPkgEntry entry : npiws.availableAppFileList) {
+			pkgListRoot.addPkgEntry(entry);
+			// only expanded/visible items are available for selecting programatically
+			projectTreeViewer.reveal(entry);
+		}
+		removeButton.setEnabled(pkgListRoot.getPkgEntries().length != 0);
+		// Build TreePath for all selected PKG
+		for (IPkgEntry selected : npiws.selectedAppFileList) {
+			TreePath pkgPath = projectTreeViewer.getTreePathForElement(selected);
+			if (pkgPath != null) {
+				selectedPath.add(pkgPath);
+			}
+		}
+
+		// This shows the change in model(e.g. adding PKG) and force associate of the new tree nodes, so we can select later
+		projectTreeViewer.refresh();
+		projectTreeViewer.initializeSelectedItems(selectedPath.toArray(new TreePath[selectedPath.size()]));
+		// Show the selection
+		projectTreeViewer.refresh();
+	}
+
+	public void validatePage() {
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPagePkgSdkDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.SdkChooserBase;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+
+public class NewPIWizardPagePkgSdkDialog  extends TrayDialog
+{
+	SdkChooserBase sdkCommon = new SdkChooserBase();
+	private Composite composite;
+	private ISymbianSDK selection; 
+
+	protected NewPIWizardPagePkgSdkDialog(Shell arg0) {
+		super(arg0);
+	}
+
+	public Control createDialogArea(Composite parent) {
+		selection = null;
+		composite = sdkCommon.layout(parent);
+		getShell().setText(Messages.getString("NewPIWizardPagePkgSdkDialog.shell.title")); //$NON-NLS-1$
+		return composite;
+	}
+	
+	public void okPressed() {
+		selection = sdkCommon.getSelectedSdk();
+		super.okPressed();
+	}
+	
+	public ISymbianSDK getSelection() {
+		return selection;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageRomSdkSubTask.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.CarbidePiWizardHelpIds;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.SdkChooserBase;
+
+public class NewPIWizardPageRomSdkSubTask extends NewPIWizardPage
+{
+	SdkChooserBase sdkCommon = new SdkChooserBase();
+	private Composite composite;
+	
+	protected NewPIWizardPageRomSdkSubTask() {
+		super(""); //$NON-NLS-1$
+		setTitle(Messages.getString("NewPIWizardPageRomSdkSubTask.title")); //$NON-NLS-1$
+	    setDescription(Messages.getString("NewPIWizardPageRomSdkSubTask.description")); //$NON-NLS-1$
+	}
+
+	public void createControl(Composite parent) {
+		super.createControl(parent);
+		composite = sdkCommon.layout (parent);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, CarbidePiWizardHelpIds.PI_IMPORT_WIZARD_ROM_SDK);
+		setControl(composite);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardPageRomSubTask.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.CarbidePiWizardHelpIds;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.RofsObySymbolPair;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.SdkChooserBase;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+
+public class NewPIWizardPageRomSubTask extends NewPIWizardPage implements INewPIWizardSettings
+{
+	private boolean visableBefore = false;
+	
+	protected NewPIWizardPageRomSubTask() {
+		super(""); //$NON-NLS-1$
+		setTitle(Messages.getString("NewPIWizardPageRomSubTask.title")); //$NON-NLS-1$
+	    setDescription(Messages.getString("NewPIWizardPageRomSubTask.description")); //$NON-NLS-1$
+	}
+	
+	// use base SDK chooser object for layout
+	private SdkChooserBase sdkCommon = new SdkChooserBase();
+	private static final String FILTER_EXT_KEY = "extension"; //$NON-NLS-1$
+	private static final String FILTER_NAME_KEY = "name"; //$NON-NLS-1$
+	private static final String MY_WIGET_KEY = "myWiget"; //$NON-NLS-1$
+	private static final String ROFS_ITEM_PAIR_KEY = "ROFS_ITEM_PAIR_KEY";	//$NON-NLS-1$
+	private static final int TEXT_MARGIN = 2;
+	private static final int ARC_WIDTH = 2;
+	private static String lastGoodDir = null;
+	private ModifyListener textModifyListener = new ModifyListener () {
+
+		public void modifyText(ModifyEvent arg0) {
+			Object source = arg0.getSource();
+			if (source instanceof Text) {
+				String pathString = ((Text)source).getText();
+				java.io.File file = new java.io.File(pathString);
+				if (file.exists()) {
+					if (file.isFile()) {
+						lastGoodDir = file.getParent();
+					} else if (file.isDirectory()){
+						lastGoodDir = pathString;
+					} else {
+						lastGoodDir = null;
+					}
+				}
+			}
+			if (source == symbolText) {
+				NewPIWizardSettings.getInstance().romSymbolFile = symbolText.getText();
+			}
+			if (source == obyText) {
+				NewPIWizardSettings.getInstance().romObyFile = obyText.getText();
+			}
+			validatePage();
+		}
+		
+	};
+	private SelectionListener browseSelectionListener = new SelectionListener() {
+
+		public void widgetDefaultSelected(SelectionEvent arg0) {
+		}
+
+		public void widgetSelected(SelectionEvent arg0) {
+			Button button = (Button) arg0.getSource();
+			String selectedFilePath;
+			FileDialog dialog = new FileDialog(getShell());
+			ArrayList<String> pkgExtensions = new ArrayList<String>();
+			ArrayList<String> pkgNames = new ArrayList<String>();
+			pkgExtensions.add((String)button.getData(FILTER_EXT_KEY));
+			pkgNames.add((String)button.getData(FILTER_NAME_KEY));
+			pkgExtensions.add("*.*"); //$NON-NLS-1$"
+			pkgNames.add(Messages.getString("NewPIWizardPageRomSubTask.name.filter")); //$NON-NLS-1$
+			dialog.setFilterExtensions(pkgExtensions.toArray(new String[pkgExtensions.size()]));
+			dialog.setFilterNames(pkgNames.toArray(new String[pkgNames.size()]));
+			ISymbianSDK sdk = sdkCommon.getSelectedSdk();
+			if (sdk != null) {
+				String epocroot = sdk.getEPOCROOT();
+				if (lastGoodDir != null) {
+					// pick last known good before EPOCROOT
+					dialog.setFilterPath(lastGoodDir);
+				} else if (epocroot != null) {
+					if (epocroot != "") { //$NON-NLS-1$
+						String romDir = epocroot;
+						if (romDir.endsWith(File.separator))
+							romDir += "epoc32" + File.separator + "rom";	//$NON-NLS-1$" //$NON-NLS-2$"
+						else
+							romDir += File.separator + "epoc32" + File.separator + "rom";	//$NON-NLS-1$" //$NON-NLS-2$"
+						// S60 and Techview symbol locations
+						dialog.setFilterPath(romDir);
+					}
+				}
+			}
+			
+			selectedFilePath = dialog.open();
+			
+			if (selectedFilePath != null) {
+				((Text)button.getData(MY_WIGET_KEY)).setText(selectedFilePath);
+			}
+		}
+		
+	};
+
+	//	 controls
+	private Composite composite = null;
+//	private Label headerLabel = null;
+	private Label symbolLabel = null;
+	private Composite symbolComposite = null;
+	private Text symbolText = null;
+	private Button symbolButton = null;
+	private Label obyLabel = null;
+	private Composite obyComposite = null;
+	private Text obyText = null;
+	private Button obyButton = null;
+	private Label rofsObySymbolLabel = null;
+	private Composite rofsObySymbolComposite = null;
+	private Table rofsObySymbolTable = null;
+	private Composite rofsObySymbolButtonComposite = null;
+	private Button rofsAddButton = null;
+	private Button rofsRemoveButton = null;
+//	private Label detailLabel = null;
+	
+	public void validatePage() {
+		if (symbolText.getText().length() > 1 ||
+				obyText.getText().length() > 1 ||
+				rofsObySymbolTable.getItemCount() > 1) {
+				if (sdkCommon.getSelectedSdk() == null) {
+					setErrorMessage(Messages.getString("NewPIWizardPageRomSubTask.error.1")); //$NON-NLS-1$
+					setPageComplete(false);
+					return;
+				}
+		}
+		if (symbolText.getText().length() > 0 ) {
+			java.io.File symFile = new java.io.File(symbolText.getText());
+			if (!symFile.exists() || !symFile.isFile()) {
+				setErrorMessage(Dialog.shortenText(Messages.getString("NewPIWizardPageRomSubTask.symbol.label") +  " " + symbolText.getText() + " " + Messages.getString("NewPIWizardPageRomSubTask.error.2"), symbolComposite)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+				setPageComplete(false);
+				return;
+			}
+		}
+		if (obyText.getText().length() > 0 ) {
+			java.io.File obyFile = new java.io.File(obyText.getText());
+			if (!obyFile.exists() || !obyFile.isFile()) {
+				setErrorMessage(Dialog.shortenText(Messages.getString("NewPIWizardPageRomSubTask.oby.label") +  " " + obyText.getText() + " " + Messages.getString("NewPIWizardPageRomSubTask.error.2"), obyComposite)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+				setPageComplete(false);
+				return;
+			}
+		}
+		
+		setErrorMessage(null);
+		setPageComplete(true);
+		return;
+	}
+	
+	private void writeRofsTableToStatus() {
+		NewPIWizardSettings npws = NewPIWizardSettings.getInstance();
+		npws.rofsObySymbolPairList.clear();
+		TableItem[] items = rofsObySymbolTable.getItems();
+		for (TableItem item : items) {
+			RofsObySymbolPair pair = (RofsObySymbolPair) item.getData(ROFS_ITEM_PAIR_KEY);
+			if (pair.haveObyFile() || pair.haveSymbolFile()) {
+				npws.rofsObySymbolPairList.add(pair);
+			}
+		}
+	}
+
+	public void createControl(Composite parent) {
+		super.createControl(parent);
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 1;
+		composite = new Composite(parent, SWT.NONE);
+		composite.setLayout(gridLayout);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		
+//		headerLabel = new Label(composite, SWT.NONE);
+//		headerLabel.setText(Messages.getString("NewPIWizardPageRomSubTask.header.label")); //$NON-NLS-1$
+
+		// the SDK top half of the page
+		sdkCommon.layout(composite);
+		sdkCommon.sdkTable.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				// write back our status
+				NewPIWizardSettings.getInstance().romSdk = sdkCommon.getSelectedSdk();
+				validatePage();
+			}
+		});
+
+//		detailLabel = new Label(composite, SWT.NONE);
+//		detailLabel.setText(Messages.getString("NewPIWizardPageRomSubTask.detail.label")); //$NON-NLS-1$
+		obyLabel = new Label(composite, SWT.NONE);
+		obyLabel.setText(Messages.getString("NewPIWizardPageRomSubTask.oby.label")); //$NON-NLS-1$
+		createObyControl();
+		symbolLabel = new Label(composite, SWT.NONE);
+		symbolLabel.setText(Messages.getString("NewPIWizardPageRomSubTask.symbol.label")); //$NON-NLS-1$
+		createSymbolControl();
+		rofsObySymbolLabel = new Label(composite, SWT.NONE);
+		rofsObySymbolLabel.setText(Messages.getString("NewPIWizardPageRomSubTask.rofs.pairs")); //$NON-NLS-1$
+		createRofsObySymbolControl();
+		validatePage();
+		
+		// top tap get focus
+		sdkCommon.sdkTable.setFocus();
+		
+		setControl(composite);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), CarbidePiWizardHelpIds.PI_IMPORT_WIZARD_ROM);
+	}
+	
+	public void createSymbolControl() {
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 2;
+		symbolComposite = new Composite(composite, SWT.NONE);
+		symbolComposite.setLayout(gridLayout);
+		symbolComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		symbolText = new Text(symbolComposite, SWT.BORDER | SWT.SINGLE);
+		symbolText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		symbolText.addModifyListener(textModifyListener);
+		symbolButton = new Button(symbolComposite, SWT.NONE);
+		symbolButton.setText(Messages.getString("NewPIWizardPageRomSubTask.symbol.button")); //$NON-NLS-1$
+		symbolButton.setData(FILTER_EXT_KEY, Messages.getString("NewPIWizardPageRomSubTask.symbol.filter")); //$NON-NLS-1$
+		symbolButton.setData(FILTER_NAME_KEY, Messages.getString("NewPIWizardPageRomSubTask.symbol.filter.text")); //$NON-NLS-1$
+		symbolButton.setData(MY_WIGET_KEY, symbolText);
+		symbolButton.addSelectionListener(browseSelectionListener);
+	}
+
+	public void createObyControl() {
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 2;
+		obyComposite = new Composite(composite, SWT.NONE);
+		obyComposite.setLayout(gridLayout);
+		obyComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		obyText = new Text(obyComposite, SWT.BORDER | SWT.SINGLE);
+		obyText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+		obyText.addModifyListener(textModifyListener);
+		obyButton = new Button(obyComposite, SWT.NONE);
+		obyButton.setText(Messages.getString("NewPIWizardPageRomSubTask.oby.button")); //$NON-NLS-1$
+		obyButton.setData(FILTER_EXT_KEY, Messages.getString("NewPIWizardPageRomSubTask.oby.filter")); //$NON-NLS-1$
+		obyButton.setData(FILTER_NAME_KEY, Messages.getString("NewPIWizardPageRomSubTask.oby.filter.text")); //$NON-NLS-1$
+		obyButton.setData(MY_WIGET_KEY, obyText);
+		obyButton.addSelectionListener(browseSelectionListener);
+	}
+	
+	public void createRofsObySymbolControl() {
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 2;
+		rofsObySymbolComposite = new Composite(composite, SWT.NONE);
+		rofsObySymbolComposite.setLayout(gridLayout);
+		rofsObySymbolComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		rofsObySymbolTable = new Table(rofsObySymbolComposite, SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.MULTI );
+		rofsObySymbolTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		GridLayout buttonGridLayout = new GridLayout();
+		buttonGridLayout.numColumns = 1;
+		// custom widget for multiple line
+		rofsObySymbolTable.addListener(SWT.MeasureItem, new Listener() {
+			public void handleEvent(Event event) {
+				TableItem item = (TableItem)event.item;
+				String text = item.getText(event.index);
+				Point size = event.gc.textExtent(text);
+				event.width = Math.max(event.width, size.x + 2 * TEXT_MARGIN);
+				event.height = Math.max(event.height, size.y + 2 * TEXT_MARGIN);
+			}});
+		rofsObySymbolTable.addListener(SWT.EraseItem, new Listener() {
+			public void handleEvent(Event event) {
+				event.detail &= ~SWT.FOREGROUND;
+			}
+		});
+		rofsObySymbolTable.addListener(SWT.PaintItem, new Listener() {
+
+			public void handleEvent(Event event) {
+				TableItem item = (TableItem)event.item;
+				String text = item.getText(event.index);
+				event.gc.drawText(text, event.x, event.y, true);
+				event.gc.drawLine(event.x , event.y + event.height - TEXT_MARGIN, event.x + rofsObySymbolTable.getSize().x , event.y + event.height - TEXT_MARGIN);
+			}});
+		
+		rofsObySymbolTable.pack();
+		rofsObySymbolButtonComposite = new Composite(rofsObySymbolComposite, SWT.NONE);
+		rofsObySymbolButtonComposite.setLayout(buttonGridLayout);
+		rofsObySymbolButtonComposite.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
+		rofsAddButton = new Button(rofsObySymbolButtonComposite, SWT.NONE);
+		rofsAddButton.setText(Messages.getString("NewPIWizardPageRomSubTask.add")); //$NON-NLS-1$
+		rofsAddButton.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				NewPIWizardObySymbolPairDialog dialog = new NewPIWizardObySymbolPairDialog(getShell());
+				dialog.open();
+				RofsObySymbolPair pair = dialog.getPair();
+				if (pair.haveObyFile() || pair.haveSymbolFile() ) {
+					boolean found = false;
+					TableItem[] items = rofsObySymbolTable.getItems();
+					for (TableItem item : items) {
+						if (((RofsObySymbolPair)item.getData(ROFS_ITEM_PAIR_KEY)).equals(pair)) {
+							found = true;
+							break;
+						}
+					}
+					// don't add new entry if it's already there
+					if (found == false) {
+						TableItem newItem = new TableItem(rofsObySymbolTable, SWT.NONE);
+						newItem.setData(ROFS_ITEM_PAIR_KEY, pair);
+						newItem.setText(pair.getDisplayString());	
+					} else {
+						MessageDialog.openInformation(getShell(), Messages.getString("NewPIWizardPageRomSubTask.add.rofs.pair"), Messages.getString("NewPIWizardPageRomSubTask.entry.already.exisits")); //$NON-NLS-1$ //$NON-NLS-2$
+					}
+				}
+				writeRofsTableToStatus();
+			}
+		
+		});
+		rofsRemoveButton = new Button(rofsObySymbolButtonComposite, SWT.NONE);
+		rofsRemoveButton.setText(Messages.getString("NewPIWizardPageRomSubTask.remove")); //$NON-NLS-1$
+		rofsRemoveButton.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				rofsObySymbolTable.remove(rofsObySymbolTable.getSelectionIndices());
+				writeRofsTableToStatus();
+			}
+			
+		});
+		
+		GridData buttonWidthGridData = new GridData();
+		buttonWidthGridData.widthHint = Math.max(rofsAddButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x, rofsRemoveButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
+		rofsAddButton.setLayoutData(buttonWidthGridData);
+		rofsRemoveButton.setLayoutData(buttonWidthGridData);
+	}
+		
+	public void setupPageFromFromNewPIWizardSettings() {
+		NewPIWizardSettings npws = NewPIWizardSettings.getInstance();
+		sdkCommon.setSelectedSdk(npws.romSdk);
+		symbolText.setText(npws.romSymbolFile);
+		obyText.setText(npws.romObyFile);
+		rofsObySymbolTable.removeAll();
+		for(RofsObySymbolPair pair:npws.rofsObySymbolPairList) {
+			TableItem newItem = new TableItem(rofsObySymbolTable, SWT.NONE);
+			newItem.setData(ROFS_ITEM_PAIR_KEY, pair);
+			newItem.setText(pair.getDisplayString());
+		}
+	}
+
+	public void setVisible(boolean visable) {
+		super.setVisible(visable);
+		if (visable) {
+//			 block the text if it's wrong on startup, so user know what's wrong
+			if (visableBefore == false) {
+				String errorMessage = getErrorMessage();
+				if (errorMessage != null) {
+					if (errorMessage.startsWith(Messages.getString("NewPIWizardPageRomSubTask.symbol.label"))) { //$NON-NLS-1$
+						symbolText.selectAll();
+						symbolText.setFocus();
+					} else if (errorMessage.startsWith(Messages.getString("NewPIWizardPageRomSubTask.oby.label"))) { //$NON-NLS-1$
+						obyText.selectAll();
+						symbolText.setFocus();
+					}
+				}
+			}
+			lastGoodDir = null;
+		}
+		visableBefore = visable;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardRemovePkgDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.swt.SWT;
+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.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.IPkgEntry;
+
+public class NewPIWizardRemovePkgDialog extends TrayDialog{
+	
+	private IPkgEntry[] entryList;
+	private IPkgEntry[] removeList;
+	
+	// control
+	private Composite composite = null;
+	private Table table = null;
+	private Label label = null;
+	
+	protected NewPIWizardRemovePkgDialog(Shell arg0, IPkgEntry[] pkgFiles) {
+		super(arg0);
+		entryList = pkgFiles;
+	}
+
+	public Control createDialogArea(Composite parent) {
+		getShell().setText(Messages.getString("NewPIWizardRemovePkgDialog.shell.title")); //$NON-NLS-1$
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 1;
+		composite = new Composite(parent, SWT.NONE);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		composite.setLayout(gridLayout);
+		label = new Label(composite, SWT.NONE);
+		label.setText(Messages.getString("NewPIWizardRemovePkgDialog.check.pkg.label")); //$NON-NLS-1$
+		table = new Table(composite, SWT.CHECK | SWT.H_SCROLL | SWT.BORDER);
+		
+		// load settings
+		if (entryList != null) {
+			for (int i = 0; i < entryList.length; i++) {
+				TableItem item = new TableItem(table, SWT.NONE);
+				String pkgText = Messages.getString("NewPIWizardRemovePkgDialog.sample.file") + entryList[i].getPkgFile(); //$NON-NLS-1$
+				if (entryList[i].getSdk() != null) {
+					pkgText += Messages.getString("NewPIWizardRemovePkgDialog.sdk") + entryList[i].getSdk().getUniqueId(); //$NON-NLS-1$
+				}
+				item.setText(pkgText);
+				item.setData(entryList[i]);	// bound the pkgFile to the button, so we can retrieve later
+				item.setChecked(false);
+			}
+		}
+		table.addSelectionListener(new SelectionAdapter() {
+
+			public void widgetSelected(SelectionEvent e) {
+				TableItem[] items = table.getItems();
+				getButton(IDialogConstants.OK_ID).setEnabled(false);
+				if (items != null) {
+					for (TableItem item : items) {
+						if (item.getChecked()) {
+							getButton(IDialogConstants.OK_ID).setEnabled(true);
+						}
+					}
+				}
+			}
+		});
+		
+		return composite;
+	}
+	
+	public void okPressed() {
+		ArrayList<IPkgEntry> removeArrayList = new ArrayList<IPkgEntry>();
+		TableItem[] items = table.getItems();
+		for (int i = 0; i < items.length; i++) {
+			if (items[i].getChecked()) {
+				removeArrayList.add((IPkgEntry) items[i].getData());
+			}
+		}
+		removeList = removeArrayList.toArray(new IPkgEntry[removeArrayList.size()]);
+		super.okPressed();
+	}
+	
+	public IPkgEntry[] getRemovedList () {
+		return removeList;
+	}
+	
+	protected void createButtonsForButtonBar(Composite parent) {
+		super.createButtonsForButtonBar(parent);
+		// now buttons are there, we can  disable key
+		getButton(IDialogConstants.OK_ID).setEnabled(false);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/NewPIWizardSettings.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.dialogs.IDialogSettings;
+
+import com.nokia.carbide.cdt.builder.CarbideBuilderPlugin;
+import com.nokia.carbide.cdt.builder.project.ICarbideBuildConfiguration;
+import com.nokia.carbide.cdt.builder.project.ICarbideProjectInfo;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.IPkgEntry;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.PkgEntryList;
+import com.nokia.carbide.cpp.internal.pi.wizards.ui.util.RofsObySymbolPair;
+import com.nokia.carbide.cpp.pi.button.BupEventMapManager;
+import com.nokia.carbide.cpp.pi.button.IBupEventMapProfile;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
+
+/*
+ *  Handles all import wizard's persist data
+ */
+
+public class NewPIWizardSettings {
+	static NewPIWizardSettings instance = null;
+	
+	static final int COMBO_MAX_ITEM_VALUES = 5;
+	
+	//This means something on Windows and Unix, should be good enough for file path not having this
+	static final String PKG_SEPERATOR = "<SDK>";									//$NON-NLS-1$
+	static final String ROFS_SEPERATOR = "<ROFSPAIR>";								//$NON-NLS-1$
+	
+	static final int CURRENT_VERSION = 5;
+	static final String IMPORTER_SETTING_VERSION = "version";						//$NON-NLS-1$
+	static final String SAMPLEFILENAME_KEY = "sampleFileName";						//$NON-NLS-1$
+	static final String ENABLE_APP_KEY = "enableApp";								//$NON-NLS-1$ 
+	static final String ENABLE_ROM_KEY = "enableRom";								//$NON-NLS-1$
+	static final String ENABLE_CUST_KEY = "enableCust";								//$NON-NLS-1$
+	static final String SELECTED_PKG_ENTRY_KEY = "selectedPkgEntry";				//$NON-NLS-1$
+	static final String UNSELECTED_PKG_ENTRY_KEY = "availablePkgEntry";				//$NON-NLS-1$
+	static final String PROJECT_KEY = "project";									//$NON-NLS-1$
+	static final String PROJECT_CONFIG_KEY = "projectConfig";						//$NON-NLS-1$
+	static final String ROM_SDK_KEY = "romSdk";										//$NON-NLS-1$
+	static final String ROM_SYMBOL_KEY = "romSymbol";								//$NON-NLS-1$
+	static final String ROM_OBY_KEY = "romOby";										//$NON-NLS-1$
+	static final String ROFS_SYMBOL_KEY = "rofsSymbol";								//$NON-NLS-1$
+	static final String ROFS_OBY_KEY = "romRofsOby";								//$NON-NLS-1$
+	static final String ROFS_OBY_SYMBOL_KEY = "romRofsObySymbol";					//$NON-NLS-1$
+	static final String CUST_SAMPLE_KEY = "custSample";								//$NON-NLS-1$
+	static final String CUST_VAL_BASED_KEY = "isValBased";							//$NON-NLS-1$
+	static final String CUST_NAME_BASED_KEY = "isNameBased";						//$NON-NLS-1$
+	static final String CUST_SEPARATOR_KEY = "separator";							//$NON-NLS-1$
+	static final String OUTPUT_PROJECT_KEY = "outputProject";						//$NON-NLS-1$
+	static final String OUTPUT_NPI_KEY = "piFileName";								//$NON-NLS-1$
+	static final String KEY_PROFILE_KEY = "keyProfile";								//$NON-NLS-1$
+	static final String SAMPLEFILENAMES_KEY = "sampleFileName";						//$NON-NLS-1$
+
+	
+//	start version 2
+	String sampleFileName;
+	String[] sampleFileNames;
+	boolean haveAppOnly = false;
+	boolean haveRomOnly = false;
+	boolean haveAppRom = false;
+	boolean haveNothing = false;
+	boolean enableCust;
+	ArrayList<IPkgEntry> selectedAppFileList = new ArrayList<IPkgEntry>();
+	ArrayList<IPkgEntry> availableAppFileList = new ArrayList<IPkgEntry>();
+	ArrayList<IProject> selectedProjectList = new ArrayList<IProject>();
+	ArrayList<ICarbideBuildConfiguration> selectedBuildConfigList = new ArrayList<ICarbideBuildConfiguration>();
+	ISymbianSDK romSdk;
+	String romSymbolFile;
+	String romObyFile;
+	ArrayList <RofsObySymbolPair> rofsObySymbolPairList = new ArrayList<RofsObySymbolPair>();
+	String custSampleFile;
+	boolean custValBased;
+	boolean custNameBased;
+	String custSeparator;	
+	IContainer outputContainer;
+//	end version 2
+//	start version 3
+	String piFileName;
+//	end version 3
+//	start version 4
+	IBupEventMapProfile keyMapProfile;
+//	end version 4
+//	start internal states not saved
+	long sampleFileNameModifiedNanoTime;	// timestamp java.lang.System.nanoTime()
+	long piFileNameModifiedNanoTime;		// timestamp java.lang.System.nanoTime()
+//	end internal states not saved
+	
+	public void clear() {
+		sampleFileName = "";			//$NON-NLS-1$
+		haveAppOnly = false;
+		haveRomOnly = false;
+		haveAppRom = false;
+		haveNothing = false;
+		enableCust = false;
+		selectedAppFileList.clear();
+		availableAppFileList.clear();
+		selectedProjectList.clear();
+		selectedBuildConfigList.clear();
+		romSdk = null;
+		romSymbolFile = "";			//$NON-NLS-1$
+		romObyFile = "";				//$NON-NLS-1$
+		rofsObySymbolPairList.clear();
+		custSampleFile = "";			//$NON-NLS-1$
+		custValBased = false;
+		custNameBased = false;
+		custSeparator = "";			//$NON-NLS-1$	
+		outputContainer = null;
+		piFileName= "";				//$NON-NLS-1$
+		keyMapProfile = null;
+		sampleFileNameModifiedNanoTime = 0;
+		piFileNameModifiedNanoTime = 0;
+	}
+	
+	private NewPIWizardSettings() {
+		clear();
+	}
+	
+	public static NewPIWizardSettings getInstance() {
+		if (instance == null)
+			instance = new NewPIWizardSettings();
+		return instance;
+	}
+		
+	public void saveState(IDialogSettings dialogSettings) {
+		try {
+			dialogSettings.put(IMPORTER_SETTING_VERSION, CURRENT_VERSION);
+			dialogSettings.put(SAMPLEFILENAME_KEY, sampleFileName);
+			saveFileNameToArray();
+			dialogSettings.put(SAMPLEFILENAMES_KEY, sampleFileNames);
+			dialogSettings.put(ENABLE_CUST_KEY, enableCust);
+			
+			{	// traverse all entries of app config and pkg file
+				ArrayList<String> projectStringArrayList = new ArrayList<String>();
+				for (IProject selectedProject: selectedProjectList) {
+					if (selectedProject.isOpen())
+						projectStringArrayList.add(selectedProject.getName());
+				}
+				dialogSettings.put(PROJECT_KEY, projectStringArrayList.toArray(new String[projectStringArrayList.size()]));		
+				
+				ArrayList<String> bcStringArrayList = new ArrayList<String>();
+				for (ICarbideBuildConfiguration currentConfig : selectedBuildConfigList) {
+					if (currentConfig.getCarbideProject().getProject().isOpen()) {
+						bcStringArrayList.add(currentConfig.getCarbideProject().getProject().getName() + PKG_SEPERATOR + currentConfig.getDisplayString());
+					}
+				}
+				dialogSettings.put(PROJECT_CONFIG_KEY, bcStringArrayList.toArray(new String[bcStringArrayList.size()]));
+				
+				ArrayList<String> pkgStringArrayList = new ArrayList<String>();
+				for (IPkgEntry currentPkgEntry : selectedAppFileList) {
+					pkgStringArrayList.add(currentPkgEntry.getPkgFile() + PKG_SEPERATOR + currentPkgEntry.getSdk().getUniqueId());			
+				}
+				dialogSettings.put(SELECTED_PKG_ENTRY_KEY, pkgStringArrayList.toArray(new String[pkgStringArrayList.size()]));
+
+				pkgStringArrayList.clear();
+				for (IPkgEntry currentPkgEntry : availableAppFileList) {
+					pkgStringArrayList.add(currentPkgEntry.getPkgFile() + PKG_SEPERATOR + currentPkgEntry.getSdk().getUniqueId());			
+				}
+				dialogSettings.put(UNSELECTED_PKG_ENTRY_KEY, pkgStringArrayList.toArray(new String[pkgStringArrayList.size()]));
+			}
+			if (romSdk != null) {
+				dialogSettings.put(ROM_SDK_KEY, romSdk.getUniqueId());
+			}
+			dialogSettings.put(ROM_SYMBOL_KEY, romSymbolFile);
+			dialogSettings.put(ROM_OBY_KEY, romObyFile);
+			{
+				ArrayList<String> rofsObySymbolStringArrayList = new ArrayList<String>();
+				for (RofsObySymbolPair pair : rofsObySymbolPairList) {
+					String setting = "";	//$NON-NLS-1$
+					if (pair.haveObyFile()) {
+						setting += pair.getObyFile();
+					}
+					setting += ROFS_SEPERATOR;
+					if (pair.haveSymbolFile()) {
+						setting += pair.getSymbolFile();
+					}
+					rofsObySymbolStringArrayList.add(setting);
+				}
+				dialogSettings.put(ROFS_OBY_SYMBOL_KEY, rofsObySymbolStringArrayList.toArray(new String[rofsObySymbolStringArrayList.size()]));
+			}
+			dialogSettings.put(CUST_SAMPLE_KEY, custSampleFile);
+			dialogSettings.put(CUST_VAL_BASED_KEY, custValBased);
+			dialogSettings.put(CUST_NAME_BASED_KEY, custNameBased);
+			dialogSettings.put(CUST_SEPARATOR_KEY, custSeparator);
+			String outProject = outputContainer.getFullPath().toString();
+			dialogSettings.put(OUTPUT_PROJECT_KEY, outProject);
+			dialogSettings.put(OUTPUT_NPI_KEY, piFileName);
+			dialogSettings.put(KEY_PROFILE_KEY, keyMapProfile != null ? keyMapProfile.toString() : "");	//$NON-NLS-1$
+//			 newer members go here
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	public void restoreState(IDialogSettings dialogSettings) {
+		try {
+			if (dialogSettings.get(IMPORTER_SETTING_VERSION) == null) {
+				return;
+			}
+			if (dialogSettings.getInt(IMPORTER_SETTING_VERSION) == CURRENT_VERSION) {
+				sampleFileName = dialogSettings.get(SAMPLEFILENAME_KEY);
+				sampleFileNames = dialogSettings.getArray(SAMPLEFILENAMES_KEY);
+//				if(!(new java.io.File(sampleFileName).exists()))
+//					sampleFileName = "";	//$NON-NLS-1$
+				enableCust = dialogSettings.getBoolean(ENABLE_CUST_KEY);
+				
+				{	// traverse all entries of app config and pkg file
+					String selectedProjectStringArray[];
+					String projectConfigStringArray[];
+					String pkgStringArray[];
+					selectedProjectStringArray = dialogSettings.getArray(PROJECT_KEY);
+					selectedProjectList.clear();
+					for (String selectedProjectString : selectedProjectStringArray) {
+						IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(selectedProjectString);
+						if (project != null) {
+							if (project.exists()) {
+								// project in persist data match one of the project in workspace
+								selectedProjectList.add(project);
+							}
+						}
+					}
+					
+					projectConfigStringArray = dialogSettings.getArray(PROJECT_CONFIG_KEY);
+					selectedBuildConfigList.clear();
+					for (String projectConfig : projectConfigStringArray) {
+						// attempt to match workspace with <project>:<config> entry in setting
+						String projectConfigDetail[] = projectConfig.split(PKG_SEPERATOR);
+						if (projectConfigDetail.length == 2) {
+							IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectConfigDetail[0]);
+							if (project != null) {
+								if (project.exists() && project.isOpen()) {
+									ICarbideProjectInfo cpi = CarbideBuilderPlugin.getBuildManager().getProjectInfo(project);
+									for (ICarbideBuildConfiguration currentConfig : cpi.getBuildConfigurations()) {
+										if (currentConfig.getDisplayString().equals(projectConfigDetail[1])) {
+											// Found Carbide.c++ config matching entry
+											selectedBuildConfigList.add(currentConfig);
+											break;
+										}
+									}
+								}
+							}
+						}
+					}
+					pkgStringArray = dialogSettings.getArray(SELECTED_PKG_ENTRY_KEY);
+					selectedAppFileList.clear();
+					for (String pkgString : pkgStringArray) {
+						// attempt to match file system with <PKG file>:<SDK> entry in setting
+						String pkgDetail[] = pkgString.split(PKG_SEPERATOR);
+						if (pkgDetail.length == 2) {
+							ISymbianSDK sdk = SDKCorePlugin.getSDKManager().getSDK(pkgDetail[1], true);
+							if (new java.io.File(pkgDetail[0]).exists() && sdk != null) {
+								IPkgEntry pkg = PkgEntryList.getInstance().getPkgEntry(pkgDetail[0], sdk);
+								selectedAppFileList.add(pkg);
+							}
+						}
+					}
+					pkgStringArray = dialogSettings.getArray(UNSELECTED_PKG_ENTRY_KEY);
+					availableAppFileList.clear();
+					for (String pkgString : pkgStringArray) {
+						// attempt to match file system with <PKG file>:<SDK> entry in setting
+						String pkgDetail[] = pkgString.split(PKG_SEPERATOR);
+						if (pkgDetail.length == 2) {
+							ISymbianSDK sdk = SDKCorePlugin.getSDKManager().getSDK(pkgDetail[1], true);
+							if (new java.io.File(pkgDetail[0]).exists() && sdk != null) {
+								IPkgEntry pkg = PkgEntryList.getInstance().getPkgEntry(pkgDetail[0], sdk);
+								availableAppFileList.add(pkg);
+							}
+						}
+					}
+				}
+				
+				String romSdkId = dialogSettings.get(ROM_SDK_KEY);
+				if (romSdkId != null) {
+					romSdk = SDKCorePlugin.getSDKManager().getSDK(romSdkId, true);
+				}
+				romSymbolFile = dialogSettings.get(ROM_SYMBOL_KEY);
+//				if(!(new java.io.File(romSymbolFile).exists()))
+//					romSymbolFile = "";		//$NON-NLS-1$
+				romObyFile = dialogSettings.get(ROM_OBY_KEY);
+//				if(!(new java.io.File(romObyFile).exists()))
+//					romObyFile = "";		//$NON-NLS-1$
+				{
+					String rofsObySymbolStringArray[];
+					rofsObySymbolStringArray = dialogSettings.getArray(ROFS_OBY_SYMBOL_KEY);
+					rofsObySymbolPairList.clear();
+					for (String rofsObySymbolString : rofsObySymbolStringArray) {
+						int seperator = rofsObySymbolString.indexOf(ROFS_SEPERATOR);
+						RofsObySymbolPair pair = new RofsObySymbolPair();
+						pair.setObyFile(rofsObySymbolString.substring(0, seperator));
+						pair.setSymbolFile(rofsObySymbolString.substring(seperator + ROFS_SEPERATOR.length()));
+						rofsObySymbolPairList.add(pair);
+					}
+				}
+				custSampleFile = dialogSettings.get(CUST_SAMPLE_KEY);
+//				if(!(new java.io.File(custSampleFile).exists()))
+//					custSampleFile = "";	//$NON-NLS-1$
+				custValBased = dialogSettings.getBoolean(CUST_VAL_BASED_KEY);
+				custNameBased = dialogSettings.getBoolean(CUST_NAME_BASED_KEY);
+				custSeparator = dialogSettings.get(CUST_SEPARATOR_KEY);
+				String outputFolder = dialogSettings.get(OUTPUT_PROJECT_KEY);
+				IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+				IResource resource = root.findMember(outputFolder);
+				if (resource instanceof IContainer) {
+					outputContainer = (IContainer) resource;
+				} else {
+					outputContainer = null;
+				}
+				piFileName = dialogSettings.get(OUTPUT_NPI_KEY);
+				String keyProfileString = dialogSettings.get(KEY_PROFILE_KEY);
+				ArrayList<IBupEventMapProfile> profiles = BupEventMapManager.getInstance().getAllProfiles();
+				keyMapProfile = null;
+				for (IBupEventMapProfile profile : profiles) {
+					if(profile.toString().equals(keyProfileString)) {
+						keyMapProfile = profile;
+					}
+				}
+			} // if (dialogSettings.getInt(IMPORTER_SETTING_VERSION) == CURRENT_VERSION)
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	
+	
+	
+	/**
+	 * @param sampleFileName path to save
+	 * @param array name of the array which contains correct values
+	 * @param section section which has array 
+	 */
+	protected void saveFileNameToArray() {
+			
+		// No previous values exist
+		if (sampleFileNames == null) {
+			sampleFileNames = new String[1];
+			sampleFileNames[0] = sampleFileName;
+		// Previous values exists
+		} else {
+			int valuesCount = sampleFileNames.length;
+			
+			boolean valueExisted = false;
+			// see if passed value already exist.
+			for (int i = 0; i < valuesCount; i++) {
+				if (sampleFileNames[i].compareToIgnoreCase(sampleFileName) == 0) {
+					valueExisted = true;
+					
+					// passed value exists, move it to first position
+					for (int j = i; j > 0; j--) {
+						sampleFileNames[j] = sampleFileNames[j-1];
+					}
+					sampleFileNames[0] = sampleFileName;
+					
+					break;
+				}
+			}
+			
+			// passed value did not exist, add it to first position (and move older values "down")
+			if (!valueExisted) {
+				if (valuesCount >= COMBO_MAX_ITEM_VALUES) {
+					for (int i = valuesCount-1; i > 0; i--) {
+						sampleFileNames[i] = sampleFileNames[i-1];
+					}
+					sampleFileNames[0] = sampleFileName;
+				} else {
+					String[] values = new String[valuesCount + 1];
+					values[0] = sampleFileName;
+					for (int i = 0; i < valuesCount; i++) {
+						values[i+1] = sampleFileNames[i];
+					}
+					sampleFileNames = values;
+				}
+			}
+		}
+		
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/UiFileFilter.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: 
+ *
+ */
+
+/*
+ * UiFileFilter.java
+ */
+package com.nokia.carbide.cpp.internal.pi.wizards.ui;
+//package com.nokia.carbide.cpp.internal.pi.utils;
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+public class UiFileFilter extends FileFilter
+{
+	static final String AXF_EXTENSION= "axf"; //$NON-NLS-1$
+	static final String ELF_EXTENSION= "elf"; //$NON-NLS-1$
+	static final String DOT_C_EXTENSION= ".c"; //$NON-NLS-1$
+	static final String DOT_CPP_EXTENSION= ".cpp"; //$NON-NLS-1$
+	static final String DOT_H_EXTENSION= ".h"; //$NON-NLS-1$
+	static final String EXE_EXTENSION= "exe"; //$NON-NLS-1$
+	static final String DLL_EXTENSION= "dll"; //$NON-NLS-1$
+	static final String PDD_EXTENSION= "pdd"; //$NON-NLS-1$
+	static final String SYMBOL_EXTENSION= "symbol"; //$NON-NLS-1$
+	static final String OBY_EXTENSION= "oby"; //$NON-NLS-1$
+	static final String BAP_EXTENSION= "bap"; //$NON-NLS-1$
+	static final String DAT_EXTENSION= "dat"; //$NON-NLS-1$
+	static final String CSV_EXTENSION= "csv"; //$NON-NLS-1$
+	static final String TXT_EXTENSION= "txt"; //$NON-NLS-1$
+
+	String myFilter;
+	public UiFileFilter(String filter)
+	{
+		this.myFilter = filter;
+	}
+	public boolean accept(File f)
+	{
+		if(f.isDirectory()) return true;
+		
+		if(f.getName().endsWith(myFilter)) 
+			return true;
+		else
+			return false;
+	}
+	
+	public String getDescription()
+	{
+		// Symbian build system file types
+		if(this.myFilter.equals(AXF_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.object.file.extensions"); //$NON-NLS-1$
+		}
+		else if(this.myFilter.equals(ELF_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.object.file.extensions"); //$NON-NLS-1$
+		}
+		else if(this.myFilter.equals(DOT_C_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.source.file.extensions"); //$NON-NLS-1$
+		}
+		else if(this.myFilter.equals(DOT_CPP_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.source.file.extensions"); //$NON-NLS-1$
+		}
+		else if(this.myFilter.equals(DOT_H_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.source.file.extensions"); //$NON-NLS-1$
+		}
+		else if(this.myFilter.equals(EXE_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.executable.file.extensions"); //$NON-NLS-1$
+		}
+		else if(this.myFilter.equals(DLL_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.executable.file.extensions"); //$NON-NLS-1$
+		}
+		else if(this.myFilter.equals(PDD_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.executable.file.extensions"); //$NON-NLS-1$
+		}
+		else if(this.myFilter.equals(SYMBOL_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.symbol.file.extensions"); //$NON-NLS-1$
+		}
+		else if(this.myFilter.equals(OBY_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.build.file.extensions"); //$NON-NLS-1$
+		}
+
+		// analyser file types
+		else if(this.myFilter.equals(BAP_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.pi.analysis.file.extensions");			 //$NON-NLS-1$
+		}		
+		else if(this.myFilter.equals(DAT_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.raw.pi.measurement.file.extensions"); //$NON-NLS-1$
+		}
+		else if(this.myFilter.equals(CSV_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.comma.separated.text.file.extensions"); //$NON-NLS-1$
+		}
+		else if(this.myFilter.equals(TXT_EXTENSION))
+		{
+			return Messages.getString("UiFileFilter.file.extensions"); //$NON-NLS-1$
+		}
+		else 
+		{
+			return Messages.getString("UiFileFilter.no.description.error1")+myFilter+Messages.getString("UiFileFilter.no.description.error2"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,135 @@
+NewPIWizard.window.title=Performance Investigator Import Wizard
+
+NewPIWizardPageBupMapTask.0=Select Key Press Mapping Profile
+NewPIWizardPageBupMapTask.1=Select Key Press Mapping Profile
+NewPIWizardPageBupMapTask.10=) associated
+NewPIWizardPageBupMapTask.11=Profile (
+NewPIWizardPageBupMapTask.12=) is the only profile in the SDK (
+NewPIWizardPageBupMapTask.13=) associated
+NewPIWizardPageBupMapTask.14=None, there are multiple profiles among associated SDK (
+NewPIWizardPageBupMapTask.15=).
+NewPIWizardPageBupMapTask.16=None, there is no valid profile among ROM SDK (
+NewPIWizardPageBupMapTask.17=(
+NewPIWizardPageBupMapTask.18=) 
+NewPIWizardPageBupMapTask.19=None, there are multiple SDKs associated. 
+NewPIWizardPageBupMapTask.2=Select the key press mapping profile reflecting your device
+NewPIWizardPageBupMapTask.20=) associated
+NewPIWizardPageBupMapTask.21=None, there is no key press profile among ROM SDK (
+NewPIWizardPageBupMapTask.22=) associated.
+NewPIWizardPageBupMapTask.3=Profile:
+NewPIWizardPageBupMapTask.4=Recommended Profile:
+NewPIWizardPageBupMapTask.5=Please select a key press profile corresponding to your device.
+NewPIWizardPageBupMapTask.6=Profile (
+NewPIWizardPageBupMapTask.7=) is the only profile in ROM SDK (
+NewPIWizardPageBupMapTask.8=) associated
+NewPIWizardPageBupMapTask.9=None, there are multiple profiles among ROM SDK (
+NewPIWizardPageRomSubTask.error.1=Please select a SDK that builds the ROM image.
+NewPIWizardPageRomSubTask.error.2=is not a valid filename.
+
+NewPIWizardPageSampleFile.name=Select Profiler Data File
+NewPIWizardPageSampleFile.title=Select Profiler Data File
+NewPIWizardPageSampleFile.description=Select the Carbide Profiler data file (.dat) for conversion to a Performance Investigator file (.npi).
+NewPIWizardPageSampleFile.browse=Profiler Sample File...
+NewPIWizardPageSampleFile.dat.file.name=&Profiler Sample File:
+NewPIWizardPageSampleFile.dat.file.extension.must.be.dat=Carbide.c++ Profiler data file extension must be "dat".
+NewPIWizardObySymbolPairDialog.does.not.exist.in.file.system=\ does not exist in file system.
+NewPIWizardObySymbolPairDialog.does.not.exist.in.file.system.2=\ does not exist in file system.
+NewPIWizardPageSampleFile.dat.file.name.does.not.exist=Carbide.c++ Profiler data file specified does not exist.
+NewPIWizardObySymbolPairDialog.oby.file.extension.error=OBY file must have .oby extension.
+NewPIWizardPageSampleFile.dat.must.be.a.file=Please enter a Carbide.c++ Profiler data file.
+NewPIWizardPageSampleFile.sample.filter.name=Profiler Sample Files (*.dat)
+NewPIWizardPageSampleFile.all.filter.name=All Files (*.*)
+
+NewPIWizardPageOutputTask.output.file.and.project=Output File And Project
+
+NewPIWizardPageRomSubTask.oby.label=ROM OBY File:
+NewPIWizardPageRomSdkSubTask.title=Select SDK or specify EPOCROOT
+
+NewPIWizardPageCustomTask.13=C:\\temp\\my_custom.trace.dat
+NewPIWizardPageCustomTask.14=0;name;1.4343;\n0;another_name;9.343
+NewPIWizardPageCustomTask.title=Select Custom Sample Data File
+NewPIWizardPageRomSubTask.title=Select build files for ROM
+NewPIWizardPageRomSubTask.add=Add...
+NewPIWizardPageRomSubTask.remove=Remove...
+NewPIWizardPageRomSubTask.symbol.filter.text=Symbol File(*.symbol)
+NewPIWizardObySymbolPairDialog.rofs.oby.file=ROFS OBY File (mandatory):
+
+NewPIWizardRemovePkgDialog.sdk=\ / SDK: 
+
+NewPIWizard.failed.convertFileToIFile=\ failed converFileToIFile
+NewPIWizardRemovePkgDialog.sample.file=sample file: 
+NewPIWizardRemovePkgDialog.shell.title=Remove PKG Files From Import
+
+UiFileFilter.object.file.extensions=Object file (.axf;.elf)
+UiFileFilter.source.file.extensions=Source file (.c;,cpp;.h)
+UiFileFilter.executable.file.extensions=Symbian executable (.exe;.dll;,.pdd)
+UiFileFilter.symbol.file.extensions=Symbian OS symbol files (.symbol)
+UiFileFilter.build.file.extensions=Build file (.oby)
+UiFileFilter.pi.analysis.file.extensions=Saved profiler analysis file (.bap)
+UiFileFilter.raw.pi.measurement.file.extensions=Raw profiler measurement file (.dat)
+UiFileFilter.comma.separated.text.file.extensions=Comma separated text file (.csv)
+UiFileFilter.file.extensions=Text file (.txt)
+UiFileFilter.no.description.error1=No description for the file type (.
+UiFileFilter.no.description.error2=)
+NewPIWizardPageConfigSelectorTask.title=Available Information
+NewPIWizardPageCustomTask.example.group=Example:
+NewPIWizardPageRomSubTask.rofs.pairs=ROFS OBY/Symbol File Pairs
+NewPIWizardPageRomSubTask.symbol.button=ROM Symbol File...
+NewPIWizardPageRomSubTask.symbol.filter=*.symbol
+NewPIWizardPageRomSubTask.add.rofs.pair=Add ROFS OBY/symbol file pair
+NewPIWizardObySymbolPairDialog.oby.file=OBY file 
+NewPIWizardPageConfigSelectorTask.description=Select an import method based on the information available.
+NewPIWizardPageConfigSelectorTask.option.group=Available information:
+NewPIWizardPageConfigSelectorTask.labelAppTitle=1. Project importer
+NewPIWizardPageConfigSelectorTask.labelApp2=Carbide project or package (.pkg) files of profiled application.
+NewPIWizardPageConfigSelectorTask.labelRomAppTitle=2. Project and ROM importer
+NewPIWizardPageConfigSelectorTask.labelRomApp2=Carbide project or package (.pkg) files of profiled application
+NewPIWizardPageConfigSelectorTask.labelRomApp3=+ ROM image symbol file of profiled phone.
+NewPIWizardPageRomSubTask.entry.already.exisits=Entry already exists
+NewPIWizardPageConfigSelectorTask.labelRomTitle=3. ROM importer
+NewPIWizardPageConfigSelectorTask.labelRom2=ROM image symbol file of profiled phone.
+NewPIWizardPageConfigSelectorTask.labelNoneTitle=4. Unknown importer
+NewPIWizardPageConfigSelectorTask.labelNone2=Have neither Carbide project or a ROM image.
+NewPIWizardPageConfigSelectorTask.labelNone3=NOTE: CPU load by function is unavailable, and by binary is incomplete.
+NewPIWizardPageCustomTask.seperator.group=Seperator:
+NewPIWizardPageRomSubTask.oby.filter.text=Build file (.oby)
+NewPIWizardPageCustomTask.button.semicolon=; Semicolon
+NewPIWizardPageConfigSelectorTask.labelCustomTrace=Have additional custom trace.
+NewPIWizardObySymbolPairDialog.rofs.oby.rofs.symbol=ROFS OBY/ROFS Symbol
+NewPIWizardObySymbolPairDialog.build.file.extension=Build file (.oby)
+NewPIWizardObySymbolPairDialog.symbol.extension.error=Symbol file must have .symbol extension.
+NewPIWizardPageOutputTask.choose.output.project=Choose Output Project.
+NewPIWizardObySymbolPairDialog.rofs.symbol.file=ROFS symbol file
+NewPIWizardPageOutputTask.create.empty.project=Create Empty Project...
+
+NewPIWizardPagePkgListTask.pkg.filter.name=PKG Files (*.pkg)
+NewPIWizardPagePkgListTask.all.filter.name=All Files (*.*)
+NewPIWizardPagePkgListTask.pkg.button=Add PKG File...
+NewPIWizardPageCustomTask.super.label=Select Custom Sample Data File
+NewPIWizardPageCustomTask.description=Custom data file (*.dat)
+NewPIWizardPageCustomTask.base.group=File type:
+NewPIWizardPageRomSubTask.oby.button=ROM OBY File...
+NewPIWizardPageRomSubTask.oby.filter=*.oby
+NewPIWizardPageCustomTask.button.name=Name based
+NewPIWizardPageRomSubTask.description=Select the build files corresponding to the ROM on the device.
+NewPIWizardPageRomSubTask.name.filter=All Files (*.*)
+NewPIWizardObySymbolPairDialog.browse=Browse...
+NewPIWizardPageOutputTask.output.file.name=Output File Name:
+NewPIWizardPagePkgListTask.title=Associated Project and Package(.pkg) File
+NewPIWizardPagePkgListTask.description=Add project configurations or package (.pkg) files that built installation files (.sis) used in Carbide.c++ Profiler session.\nOnly configurations that have been built may be selected.
+NewPIWizardPageCustomTask.detail.label=Select a custom sample data file (*.dat) produced by the on-device Carbide.c++ Profiler.
+NewPIWizardPageCustomTask.format.group=Custom trace data format
+NewPIWizardPageCustomTask.button.value=Value based
+NewPIWizardPageCustomTask.button.comma=, Comma
+NewPIWizardPageCustomTask.button.space=Space character
+NewPIWizardPageRomSubTask.symbol.label=ROM Symbol File:
+NewPIWizardPagePkgListTask.remove.button=Remove PKG Files...
+NewPIWizardPagePkgSdkDialog.shell.title=SDK Associated With This PKG File
+NewPIWizardPageRomSdkSubTask.description=Select the SDK or EPOCROOT of the SDK, if any, that was used to build the ROM of the phone profiled.
+NewPIWizardRemovePkgDialog.check.pkg.label=Please check PKG file you want to remove from the list.
+NewPIWizardObySymbolPairDialog.symbol.file=Symbol file (.symbol)
+NewPIWizardObySymbolPairDialog.shell.title=Add ROFS OBY/ROFS Symbol File
+NewPIWizardObySymbolPairDialog.symbol.file.2=Symbol file 
+NewPIWizardPageOutputTask.select.folder.or.create.new.project.as.output.file.container=Select the folder or create a new project to store the output file container.
+
+NewPIWizardCustomTask.dat.file.name.must.be.specified=File name must be specified.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/CarbidePiWizardHelpIds.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui.util;
+
+public class CarbidePiWizardHelpIds {
+	private static final String PI_PLUGIN_ID = "com.nokia.carbide.cpp.pi.wizards"; //$NON-NLS-1$
+	
+	// see com.nokia.carbide.cpp.pi.help/html/context_help/org_eclipse_ui.xml
+	public static final String PI_IMPORT_WIZARD_PAGE = PI_PLUGIN_ID + "." + "import_wizard_selection_wizard_page_context"; //$NON-NLS-1$ //$NON-NLS-2$
+	public static final String PI_IMPORT_WIZARD_CONFIG_SELECTOR = PI_PLUGIN_ID + "." + "import_wizard_config_selector_page_context"; //$NON-NLS-1$ //$NON-NLS-2$
+	public static final String PI_IMPORT_WIZARD_INPUT = PI_PLUGIN_ID + "." + "import_wizard_input_page_context"; //$NON-NLS-1$ //$NON-NLS-2$
+	public static final String PI_IMPORT_WIZARD_OUTPUT = PI_PLUGIN_ID + "." + "import_wizard_output_page_context"; //$NON-NLS-1$ //$NON-NLS-2$
+	public static final String PI_IMPORT_WIZARD_PKG_LIST = PI_PLUGIN_ID + "." + "import_wizard_pkg_list_page_context"; //$NON-NLS-1$ //$NON-NLS-2$
+	public static final String PI_IMPORT_WIZARD_ROM_SDK = PI_PLUGIN_ID + "." + "import_wizard_rom_sdk_page_context"; //$NON-NLS-1$ //$NON-NLS-2$
+	public static final String PI_IMPORT_WIZARD_ROM = PI_PLUGIN_ID + "." + "import_wizard_rom_page_context"; //$NON-NLS-1$ //$NON-NLS-2$
+	public static final String PI_IMPORT_WIZARD_BUP_MAP = PI_PLUGIN_ID + "." + "import_wizard_bup_map_page_context"; //$NON-NLS-1$ //$NON-NLS-2$
+	public static final String PI_IMPORT_WIZARD_CUSTOM = PI_PLUGIN_ID + "." + "import_wizard_custom_page_context"; //$NON-NLS-1$ //$NON-NLS-2$
+	public static final String PI_KEY_MAP_IMPORT_WIZARD_XML = PI_PLUGIN_ID + "." + "import_key_map_wizard_xml_context"; //$NON-NLS-1$ //$NON-NLS-2$
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/IPkgEntry.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui.util;
+
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+
+public interface IPkgEntry {
+	String getPkgFile();	
+	ISymbianSDK getSdk();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui.util;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.wizards.ui.util.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgEntryList.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui.util;
+
+import java.util.ArrayList;
+
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+
+public class PkgEntryList {
+	private static ArrayList<IPkgEntry> entries = new ArrayList<IPkgEntry>();
+	private static PkgEntryList instance = null;
+	
+	//PKG file and their SDK_ID or EPOCROOT
+	private final class PkgEntry implements IPkgEntry {
+		private String pkgFile;
+		private ISymbianSDK sdk;
+		
+		private PkgEntry(String myPkg, ISymbianSDK mySdk) {
+			pkgFile = myPkg;
+			sdk = mySdk;
+		}
+		
+		public String getPkgFile() {
+			return pkgFile;
+		}
+			
+		public ISymbianSDK getSdk() {
+			return sdk;
+		}
+	}
+
+	private PkgEntryList() {
+		// singleton
+	}
+	
+	public static PkgEntryList getInstance() {
+		if (instance == null) {
+			instance = new PkgEntryList();
+		}
+		return instance;
+	}
+	
+	public IPkgEntry getPkgEntry(String myPkg, ISymbianSDK mySdk) {
+		IPkgEntry found = null;
+		for (IPkgEntry entry : entries) {
+			if (entry.getPkgFile().equals(myPkg) &&
+					entry.getSdk().equals(mySdk)) {
+				found = entry;
+				break;
+			}
+		}
+		if (found == null) {
+			found = new PkgEntry(myPkg, mySdk);
+			entries.add(found);
+		}
+		return found;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgListBaseCustomItem.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui.util;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TreeEditor;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+
+public class PkgListBaseCustomItem {
+	private PkgListTreeViewer viewer;
+	private Object element;
+	private TreeItem treeItem;
+	private TreeEditor editor = null;
+	// hide button because Button.setSelection doesn't fire event
+	// but we need to catch the selection to fire event for the viewer
+	// , we can't subclass Button either... so we wrap button around and
+	// provide only limited access, so we can intercept setSelection()
+	private Button button = null;
+	
+	PkgListBaseCustomItem(PkgListTreeViewer myViewer, final Object myElement, TreeItem myTreeItem) {
+		viewer = myViewer;
+		element = myElement;
+		treeItem = myTreeItem;
+	}
+	
+	public void createButton(int buttonSytle, SelectionListener listener) {
+		Tree tree = viewer.getTree();
+		button = new Button(tree, buttonSytle);
+		editor = new TreeEditor(tree);
+		button.pack();
+		button.setBackground(tree.getBackground());
+		button.setText(((ILabelProvider) viewer.getLabelProvider()).getText(element));
+		button.addSelectionListener(listener);
+		editor.grabHorizontal = true;
+		editor.setEditor(button, treeItem);
+		editor.minimumWidth = button.getSize().x;
+		editor.horizontalAlignment = SWT.LEFT;		
+	}
+
+	public boolean getSelection() {
+		return button.getSelection();
+	}
+	
+	public void setSelection(boolean selection) {
+		button.setSelection(selection);
+	}
+	
+	public void setEnabled(boolean enabled) {
+		button.setEnabled(enabled);
+	}
+	
+	public boolean getEnabled() {
+		return button.getEnabled();
+	}
+	
+	public void dispose() {
+		if (editor != null) {
+			editor.dispose();
+		}
+		if (button != null) {
+			button.dispose();
+		}
+	}
+	
+	public TreeItem getTreeItem() {
+		return treeItem;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgListTree.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+
+import com.nokia.carbide.cdt.builder.project.ICarbideBuildConfiguration;
+
+// keep the tree like a content provider because we have a branch of specialized node
+// of workspace tree , tree access using content provider give us an edge of constitent 
+// interface for walking the tree
+public class PkgListTree {
+	private ArrayList<Object> root = new ArrayList<Object>();
+	
+	public PkgListTree() {
+		setupWorkspaceRoot();
+	}
+
+	private void setupWorkspaceRoot() {
+		root.add(ResourcesPlugin.getWorkspace().getRoot());
+	}
+	
+	public Object[] getRoot() {
+		return root.toArray();
+	}
+	
+	public void removeAllPkgEntries() {
+		root.clear();
+		setupWorkspaceRoot();
+	}
+	
+	public void addPkgEntry (IPkgEntry entry) {
+		root.add(entry);
+	}
+	
+	public void removePkgEntry (IPkgEntry entry) {
+		root.remove(entry);
+	}
+	
+	public IPkgEntry[] getPkgEntries () {
+		ArrayList<IPkgEntry> pkgEntryArrayList = new ArrayList<IPkgEntry>();
+		Iterator<Object> rootItr = root.iterator();
+		while(rootItr.hasNext()) {
+			Object current = rootItr.next();
+			if (current instanceof IPkgEntry) {
+				pkgEntryArrayList.add((IPkgEntry) current);
+			}
+		}
+		return pkgEntryArrayList.toArray(new IPkgEntry[pkgEntryArrayList.size()]);
+	}
+
+	public void dispose() {
+		root.clear();
+	}
+	
+	public static boolean isBuildConfigurationItem(Object element) {
+		if (element instanceof ICarbideBuildConfiguration)
+			return true;
+		return false;
+	}
+
+	public static boolean isFileItem(Object element) {
+		if (element instanceof IPkgEntry)
+			return true;
+		return false;
+	}
+
+	public static boolean isProjectItem(Object element) {
+		if (element instanceof IProject)
+			return true;
+		return false;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgListTreeContentProvider.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+
+import com.nokia.carbide.cdt.builder.CarbideBuilderPlugin;
+import com.nokia.carbide.cdt.builder.project.ICarbideBuildConfiguration;
+import com.nokia.carbide.cdt.builder.project.ICarbideProjectInfo;
+
+public class PkgListTreeContentProvider implements ITreeContentProvider {
+	PkgListTree tree;
+	// need to work around CarbideBuildConfiguration equal() that claims
+	// configuration objects are equal even when their projects are different
+	Map<IProject, ArrayList<Object>> configMap = new HashMap<IProject, ArrayList<Object>>();
+	WorkbenchContentProvider cp = new WorkbenchContentProvider();
+	
+	public PkgListTreeContentProvider(PkgListTree myTree) {
+		tree = myTree;
+	}
+	
+	public Object[] getChildren(Object parentElement) {
+		if (parentElement instanceof IPkgEntry) {
+			return null;
+		} else if (parentElement instanceof IViewSite) {
+			return getCarbideCppProjects();
+		} else if (parentElement instanceof IWorkspaceRoot) {
+			return getCarbideCppProjects();
+		} else if (parentElement instanceof IProject) {
+			return getConfigs((IProject)parentElement).toArray();
+		} else if (parentElement instanceof PkgListTree) {
+			return getElements(parentElement);
+		}
+		return null;
+	}
+
+	public Object getParent(Object element) {
+		if (element instanceof ICarbideBuildConfiguration) {
+			return ((ICarbideBuildConfiguration)element).getCarbideProject().getProject();
+		}
+		return cp.getParent(element);
+	}
+
+	public boolean hasChildren(Object element) {
+		if (element instanceof IPkgEntry) {
+			return false;
+		}else if (element instanceof ICarbideBuildConfiguration) {
+			return false;
+		}else if (element instanceof IProject) {
+			return true;
+		}else if (element instanceof PkgListTree) {
+			return true;
+		}
+		
+		return cp.hasChildren(element);
+	}
+
+	public Object[] getElements(Object inputElement) {
+		return tree.getRoot();
+	}
+
+	public void dispose() {
+		cp.dispose();
+	}
+
+	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		configMap.clear();
+		cp.inputChanged(viewer, oldInput, newInput);
+	}
+
+	private Object[] getCarbideCppProjects() {
+		// lifted from com.nokia.carbide.cpp.project.ui.views.SPNViewContentProvider
+		IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+		List<IProject> list = new ArrayList<IProject>();
+		for (int i = 0; i < projects.length; i++) {
+			try {
+				if (projects[i].isAccessible() && projects[i].hasNature(CarbideBuilderPlugin.CARBIDE_PROJECT_NATURE_ID)) {
+					if (projects[i].isOpen()) {
+						ICarbideProjectInfo cpi = CarbideBuilderPlugin.getBuildManager().getProjectInfo(projects[i]);
+						if (cpi == null)
+							continue; // must have valid Carbide project info
+						List<ICarbideBuildConfiguration> bc = cpi.getBuildConfigurations();
+						boolean haveConfigWithPKG = false;
+						// if this project have all configs with (none) PKG, don't show the project
+						for (ICarbideBuildConfiguration config : bc) {
+							if (config.getSISBuilderInfoList().size() > 0) {
+								haveConfigWithPKG = true;
+								break;
+							}
+						}
+						if (haveConfigWithPKG == false)
+							continue;	// must have buildconfig with good PKG to show up
+						list.add(projects[i]);
+					}
+				}
+			} catch (CoreException e) {
+				e.printStackTrace();
+			}
+		}
+		return list.toArray();
+	}
+	
+	private ArrayList<Object> getConfigs(IProject project) {
+		ArrayList<Object> configs = configMap.get(project);
+		if (configs == null) {
+			configs = new ArrayList<Object>();
+			configMap.put(project, configs);
+			if (project.exists() == false || project.isOpen() == false)
+				return configs;	// closed project do not have config
+			ICarbideProjectInfo cpi = CarbideBuilderPlugin.getBuildManager().getProjectInfo(project);
+			if (cpi == null)
+				return configs;
+			List<ICarbideBuildConfiguration> bc = cpi.getBuildConfigurations();
+			if (bc.size() < 1)
+				return configs;
+			for (ICarbideBuildConfiguration config : bc) {
+				// exclude configuration with (none) PKG
+				if (config.getSISBuilderInfoList().size() > 0) {
+					configs.add(config);
+				}
+			}
+		}
+		return configs;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgListTreeLabelProvider.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui.util;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+import com.nokia.carbide.cdt.builder.project.ICarbideBuildConfiguration;
+
+public class PkgListTreeLabelProvider implements ILabelProvider {
+	
+	WorkbenchLabelProvider lp = new WorkbenchLabelProvider();
+
+	public Image getImage(Object element) {
+		if (element instanceof IPkgEntry || element instanceof ICarbideBuildConfiguration)
+			return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE);
+
+		return lp.getImage(element);
+	}
+
+	public String getText(Object element) {
+		
+		if (element instanceof IPkgEntry) {
+			String result = Messages.getString("PkgListTreeLabelProvider.sample.file") + ((IPkgEntry)element).getPkgFile(); //$NON-NLS-1$
+			if (((IPkgEntry)element).getSdk() != null) {
+				result += Messages.getString("PkgListTreeLabelProvider.sdk") + ((IPkgEntry)element).getSdk().getUniqueId(); //$NON-NLS-1$
+			}
+			return result;
+		} else if (element instanceof ICarbideBuildConfiguration) {
+			return ((ICarbideBuildConfiguration)element).getDisplayString();
+		}
+
+		return lp.getText(element);
+
+	}
+
+	public void addListener(ILabelProviderListener listener) {
+		lp.addListener(listener);
+	}
+
+	public void dispose() {
+		lp.dispose();
+	}
+
+	public boolean isLabelProperty(Object element, String property) {
+		return lp.isLabelProperty(element, property);
+	}
+
+	public void removeListener(ILabelProviderListener listener) {
+		lp.removeListener(listener);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/PkgListTreeViewer.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.IElementComparer;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ITreeSelection;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.TreeItem;
+
+import com.nokia.carbide.cdt.builder.CarbideBuilderPlugin;
+import com.nokia.carbide.cdt.builder.project.ICarbideBuildConfiguration;
+import com.nokia.carbide.cdt.builder.project.ICarbideProjectInfo;
+import com.nokia.carbide.cdt.builder.project.ISISBuilderInfo;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+public class PkgListTreeViewer extends TreeViewer {
+	PkgListTreeContentProvider contentProvider;
+	
+	private class PkgListProjectItem extends PkgListBaseCustomItem {
+
+		PkgListProjectItem(PkgListTreeViewer myViewer, Object myElement,
+				TreeItem myTreeItem) {
+			super(myViewer, myElement, myTreeItem);
+		}
+	}
+	
+	private class PkgListBuildConfigurationItem extends PkgListBaseCustomItem {
+
+		PkgListBuildConfigurationItem(PkgListTreeViewer myViewer,
+				Object myElement, TreeItem myTreeItem) {
+			super(myViewer, myElement, myTreeItem);
+		}
+	}
+	
+	private class PkgListFileItem extends PkgListBaseCustomItem {
+
+		PkgListFileItem(PkgListTreeViewer myViewer, Object myElement,
+				TreeItem myTreeItem) {
+			super(myViewer, myElement, myTreeItem);
+		}
+	}
+	
+	private class PkgListTreeViewerComparer implements IElementComparer {
+
+		public boolean equals(Object a, Object b) {
+			// if they're both build configuration items, check that their packages and configurations match
+			if (   PkgListTree.isBuildConfigurationItem(a)
+				&& PkgListTree.isBuildConfigurationItem(b)) {
+				ICarbideBuildConfiguration configA = (ICarbideBuildConfiguration)a;
+				ICarbideBuildConfiguration configB = (ICarbideBuildConfiguration)b;
+				return (   configA.getCarbideProject().getProject() == configB.getCarbideProject().getProject()
+				        && configA.getDisplayString().equals(configB.getDisplayString()));
+			}
+			else if (PkgListTree.isFileItem(a) &&
+				PkgListTree.isFileItem(b)) {
+					IPkgEntry fileA = (IPkgEntry)a;
+					IPkgEntry fileB = (IPkgEntry)b;
+					if (fileA.getPkgFile().equals(fileB.getPkgFile()) &&
+							fileA.getSdk().equals(fileB.getSdk())) {
+						return true;
+					}
+					return false;
+				}
+			return a.equals(b);
+		}
+
+		public int hashCode(Object element) {
+			return element.hashCode();
+		}
+		
+	}
+
+	public PkgListTreeViewer(Composite arg0, int arg1) {
+		// Must use NO_RADIO_GROUP, otherwise SWT automatically handle unselect for only
+		// one item, I haven't find a way to create new composite for each project node.
+		// Plus we want want to handle that the not so normal interaction among 
+		// project checkbox/config radio button manually
+		super(arg0, arg1 | SWT.NO_RADIO_GROUP | SWT.V_SCROLL | SWT.MULTI);
+		super.setComparer(new PkgListTreeViewerComparer());
+	}
+	
+	@Override
+	public void setContentProvider(IContentProvider provider) {
+		super.setContentProvider(provider);
+		if (provider instanceof PkgListTreeContentProvider) {
+			contentProvider = (PkgListTreeContentProvider)provider;
+		} else {
+			GeneralMessages.showErrorMessage(Messages.getString("PkgListTreeViewer.invalid.content.provider")); //$NON-NLS-1$
+		}
+	}
+	
+	
+	private Map<Object, PkgListBaseCustomItem> itemMap = new HashMap<Object, PkgListBaseCustomItem>();
+	private int style = 0;
+
+	@Override
+	protected void inputChanged(Object input, Object oldInput) {
+//		collapseAll();	// just highlight the selected on, setSelectedItems() takes care of expand
+		super.inputChanged(input, oldInput);
+	}
+	
+	public void initializeSelectedItems(TreePath[] paths) {
+		for (TreePath path : paths) {
+			reveal(path);
+		}
+		TreeSelection elementSelection = new TreeSelection(paths);
+		setSelection(elementSelection, true);
+	}
+
+	public IPkgEntry[] getSelectedPkgs() {
+		List<Object> selectionList = getSelectionFromWidget();
+		ArrayList<IPkgEntry> selectedPkgItems = new ArrayList<IPkgEntry>();
+		for (Object item : selectionList) {
+			if (item instanceof IPkgEntry) {
+				selectedPkgItems.add((IPkgEntry) item);
+			}
+		}
+		return selectedPkgItems.toArray(new IPkgEntry[selectedPkgItems.size()]);
+	}
+
+	public IProject[] getSelectedProjects() {
+		List<Object> selectionList = getSelectionFromWidget();
+		ArrayList<IProject> selectedProjects = new ArrayList<IProject>();
+		for (Object item : selectionList) {
+			if (item instanceof IProject) {
+				selectedProjects.add((IProject) item);
+			}
+		}
+		return selectedProjects.toArray(new IProject[selectedProjects.size()]);
+	}
+
+	public ICarbideBuildConfiguration[] getSelectedConfigs() {
+		List<Object> selectionList = getSelectionFromWidget();
+		ArrayList<ICarbideBuildConfiguration> selectedConfigs = new ArrayList<ICarbideBuildConfiguration>();
+		for (Object item : selectionList) {
+			if (item instanceof ICarbideBuildConfiguration) {
+				selectedConfigs.add((ICarbideBuildConfiguration) item);
+			}
+		}
+		return selectedConfigs.toArray(new ICarbideBuildConfiguration[selectedConfigs.size()]);
+	}
+		
+	/**
+	 * Set additional style bits for radio button appearance.
+	 * Most likely style added may be FLAT when in a non-3D view.
+	 * @param style int
+	 * @see SWT#FLAT
+	 */
+	public void setStyle(int style) {
+		this.style  = style;
+	}
+		
+	/**
+	 * We override associate to maintain each items optional
+	 * radio button information.
+	 */
+	@Override
+	protected void associate(final Object element, Item item) {
+		super.associate(element, item);
+		if (!(item instanceof TreeItem)) {
+			return;
+		}
+		
+		TreeItem treeItem = (TreeItem)item;
+		
+		PkgListBaseCustomItem baseItem = itemMap.get(getItemMapKey(element));
+		if (baseItem == null) {
+			int buttonStyle = style;
+			SelectionAdapter selectionAdapter;
+			boolean enabled = true;
+			
+			if (PkgListTree.isBuildConfigurationItem(element)) {
+				baseItem = new PkgListBuildConfigurationItem(this, element, treeItem);
+				buttonStyle = buttonStyle | SWT.RADIO;
+				selectionAdapter = new SelectionAdapter() {
+					@Override
+					public void widgetSelected(SelectionEvent e) {
+						toggleSelectionAndUpdateSelectionToViewer(element);
+					}
+				};
+				// check for bad PKG, which may happen on regular Symbian stationary
+				List<ISISBuilderInfo> sisBuilderInfoList = ((ICarbideBuildConfiguration)element).getSISBuilderInfoList();
+				boolean allPkgGood = true && sisBuilderInfoList.size() > 0;
+				for (ISISBuilderInfo sisBuilderInfo : sisBuilderInfoList)
+				{
+					if (sisBuilderInfo == null) {
+						allPkgGood = false;
+					} else if (sisBuilderInfo.getPKGFullPath().toFile().exists() == false) {
+						allPkgGood = false;
+					}
+			
+				}
+				enabled = allPkgGood;
+			} else if (PkgListTree.isProjectItem(element)) {
+				baseItem = new PkgListProjectItem(this, element, treeItem);
+				buttonStyle = buttonStyle | SWT.CHECK;
+				selectionAdapter = new SelectionAdapter() {
+					@Override
+					public void widgetSelected(SelectionEvent e) {
+						toggleSelectionAndUpdateSelectionToViewer(element);
+					}						
+				};
+				ICarbideProjectInfo cpi = CarbideBuilderPlugin.getBuildManager().getProjectInfo((IProject)element);
+				if (cpi != null) {
+					enabled = false;
+					List<ICarbideBuildConfiguration> bc = cpi.getBuildConfigurations();
+					for (ICarbideBuildConfiguration config : bc) {
+						// exclude configuration with (none) PKG
+						List<ISISBuilderInfo> sisBuilderInfoList = ((ICarbideBuildConfiguration)config).getSISBuilderInfoList();
+						for (ISISBuilderInfo sisBuilderInfo : sisBuilderInfoList)
+						{
+							if (sisBuilderInfo == null) {
+								continue;
+							} else if (sisBuilderInfo.getPKGFullPath().toFile().exists()) {
+								enabled = true;
+								break;
+							}
+					
+						}					
+					}
+				}
+			} else if (PkgListTree.isFileItem(element)) {
+				baseItem = new PkgListFileItem(this, element, treeItem);
+				buttonStyle = buttonStyle | SWT.CHECK;
+				selectionAdapter = new SelectionAdapter() {
+					@Override
+					public void widgetSelected(SelectionEvent e) {
+						toggleSelectionAndUpdateSelectionToViewer(element);
+					}						
+				};
+			} else {
+				return;	// not a custom item
+			}
+
+			baseItem.createButton(buttonStyle, selectionAdapter);
+			baseItem.setEnabled(enabled);
+			
+			itemMap.put(getItemMapKey(element), baseItem);
+		}
+	}
+	
+	/**
+	 * We override disassociate to clean up any
+	 * allocated radio button information and to 
+	 * help implement force selection.
+	 */
+	@Override
+	protected void disassociate(Item item) {
+		Object element = item.getData();
+		if(PkgListTree.isBuildConfigurationItem(element) ||
+				PkgListTree.isFileItem(element) ||
+				PkgListTree.isProjectItem(element))
+		{	
+			PkgListBaseCustomItem baseItem = itemMap.get(getItemMapKey(element));
+			if (baseItem != null) {
+				if (baseItem instanceof PkgListBuildConfigurationItem ||
+						baseItem instanceof PkgListProjectItem ||
+						baseItem instanceof PkgListFileItem ) 
+				{
+					baseItem.dispose();
+					itemMap.remove(getItemMapKey(element));
+				}
+				else {
+//					shouldn't get here
+				}
+			}
+		}
+		super.disassociate(item);
+	}
+	
+	// We override this underlying selection to insert UI handling of our custom
+	// UI associated, can't use Listeners from TreeViewer to propagate because 
+	// we are not SWT.CHECKBOX
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.AbstractTreeViewer#setSelectionToWidget(java.util.List, boolean)
+	 */
+	@Override
+	protected void setSelectionToWidget(List l, boolean reveal) {
+		super.setSelectionToWidget(l, reveal);
+		// handle UI
+		refreshSelectionOnUI();
+	}
+	
+	public void refreshSelectionOnUI () {
+		for (Iterator<Entry<Object, PkgListBaseCustomItem>> iter = itemMap.entrySet().iterator(); iter.hasNext();) {
+			Entry<Object, PkgListBaseCustomItem> entry = iter.next();
+			entry.getValue().setSelection(false);
+		}
+		List selectedList = getSelectionFromWidget();
+		for (Object o : selectedList) {
+			reveal(o);		// only expanded/visible items are available for selecting programatically
+							// hidden items that never been expanded cannot
+			PkgListBaseCustomItem plbci = itemMap.get(getItemMapKey(o));
+			if(plbci != null) {
+				plbci.setSelection(true);
+			}
+		}
+	}
+	
+	private ArrayList<TreePath> buildArrayWithoutElement(TreePath[] selectedPaths, Object element) {
+		ArrayList<TreePath> returnPath = new ArrayList<TreePath> ();
+		for (TreePath path : selectedPaths) {
+			boolean skip = false;
+			for (int i = 0; i < path.getSegmentCount(); i++) {
+				if (path.getSegment(i).equals(element)) {
+					skip = true;
+					break;
+				}
+			}
+			if (skip == false) {
+				returnPath.add(path);
+			}
+		}
+		return returnPath;
+	}
+	
+	public TreePath getTreePathForElement(Object element) {
+		// go upward from element to root, then flip the list
+		ArrayList<Object> segments = new ArrayList<Object>();
+		Object current = element;
+		
+		do {
+			segments.add(current);
+			current = contentProvider.getParent(current);
+		} while (current != null);
+		
+		Object[] reverse = segments.toArray(new Object[segments.size()]);
+		Object[] inOrder = new Object[segments.size()];
+		
+		for (int i = 0; i < segments.size(); i++) {
+			inOrder[i] = reverse[segments.size() - 1 - i ];
+		}
+		
+		return new TreePath(inOrder);
+	}
+	
+	/*
+	 * Build and update the tree selection reflecting the element you want to toggle
+	 */
+	private void toggleSelectionAndUpdateSelectionToViewer(final Object element)
+	{
+		ArrayList<TreePath> myNewTreePath;
+		ISelection iSelection = this.getSelection();
+		ITreeSelection iTreeSelection;
+		if (iSelection instanceof TreeSelection) {
+			iTreeSelection = (TreeSelection)iSelection;
+		} else {
+			return;
+		}
+		TreePath[] selectedPaths = iTreeSelection.getPaths();
+
+		if (PkgListTree.isFileItem(element)) {
+			if (iTreeSelection.getPathsFor(element).length > 0) {
+				// file already selected, clear self
+				myNewTreePath = buildArrayWithoutElement(selectedPaths, element);
+			} else {
+				// file not yet selected, select self
+				myNewTreePath = new ArrayList<TreePath>();
+				for (TreePath path: selectedPaths) {
+					myNewTreePath.add(path);
+				}
+				TreePath self = getTreePathForElement(element);
+				if (self != null) {
+					myNewTreePath.add(self);
+				}
+			}
+		} else if (PkgListTree.isBuildConfigurationItem(element)) {
+			Object projectSelection = contentProvider.getParent(element);
+			myNewTreePath = buildArrayWithoutElement(selectedPaths, projectSelection);
+			if (iTreeSelection.getPathsFor(element).length > 0) {
+				// configuration already selected, clear self and parent project
+				// do nothing, myNewTreePath already copied without parent project and self
+			} else {
+				// configuration not yet selected, clear siblings, select self
+				TreePath self = getTreePathForElement(element);
+				// myNewTreePath already copied without parent project and self
+				if (self != null) {
+					myNewTreePath.add(self);	// add self back
+				}
+				TreePath projectPath = getTreePathForElement(projectSelection);
+				if (projectPath != null) {
+					myNewTreePath.add(projectPath);	// add project back
+				}
+			}
+		} else if (PkgListTree.isProjectItem(element)) {
+			myNewTreePath = buildArrayWithoutElement(selectedPaths, element);
+			if (iTreeSelection.getPathsFor(element).length > 0) {
+				// project already selected, clear self and all children configurations
+				// do nothing, myNewTreePath already copied without parent project and self
+			} else {
+				// project not yet selected, select self and a child configuration(default or next valid)
+				TreePath self = getTreePathForElement(element);
+				
+				// so children are associated
+				expandToLevel(self, 1);
+				// I don't know why it didn't repaint proper without this
+				collapseToLevel(self, 1);
+				
+				IProject project = (IProject) element;
+				Object[] children = this.getRawChildren(project);
+				
+				ICarbideProjectInfo cpi = CarbideBuilderPlugin.getBuildManager().getProjectInfo(project);
+				ICarbideBuildConfiguration configDefault = cpi.getDefaultConfiguration();
+				ICarbideBuildConfiguration configDefaultOrFirstGood = null;
+				
+				// enabled default or first enabled child
+				for (Object child : children) {
+					if (itemMap.get(getItemMapKey(child)) == null) {
+						continue;
+					}
+					if (itemMap.get(getItemMapKey(child)).getEnabled()) {
+						if (configDefaultOrFirstGood == null || 
+							((ICarbideBuildConfiguration)child).getDisplayString().equals(configDefault.getDisplayString())) {
+							configDefaultOrFirstGood = (ICarbideBuildConfiguration)child;
+						}
+					}
+				}
+				if (configDefaultOrFirstGood  != null) {
+					// myNewTreePath already copied without self and children
+					if (self != null) {
+						myNewTreePath.add(self);	// add self back
+					}
+					TreePath child = getTreePathForElement(configDefaultOrFirstGood);
+					// myNewTreePath already copied without self and children
+					if (child != null) {
+						myNewTreePath.add(child);	// add child back
+					}
+				}
+			}
+		} else {
+			myNewTreePath = new ArrayList<TreePath> ();
+			for (TreePath path : selectedPaths) {
+				myNewTreePath.add(path);
+			}
+		}
+
+		// fire event
+		//updateSelection(getSelection());
+		
+		// select from viewer, viewer will fire event and eventually change UI with our
+		// overrode routine
+		ITreeSelection treeSelection = new TreeSelection(myNewTreePath.toArray(new TreePath[myNewTreePath.size()]));
+		setSelection(treeSelection, true);
+	}
+	
+	public boolean getElementEnabled(Object element) {
+		PkgListBaseCustomItem item = itemMap.get(getItemMapKey(element));
+		if (item != null) {
+			return item.getEnabled();
+		}
+		return false;
+	}
+	
+	private Object getItemMapKey(Object element) {
+		// because ICarbideBuildConfiguration says keys are equal even when their projects
+		// do not match, use the project concatenated with configuration as the key for ICarbideBuildConfiguration
+		if (element instanceof ICarbideBuildConfiguration) {
+			ICarbideBuildConfiguration config = (ICarbideBuildConfiguration) element;
+			return config.getCarbideProject().getProject() + "/" + config.getDisplayString();
+		} else {
+			return element;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/RofsObySymbolPair.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui.util;
+
+public class RofsObySymbolPair {
+	private String obyFile = "";	//$NON-NLS-1$
+	private String symbolFile = "";	//$NON-NLS-1$
+	
+	public void setObyFile(String filename) {
+		if (filename == null) {
+			filename = "";	//$NON-NLS-1$
+		}
+		obyFile = filename;
+	}
+	
+	public String getObyFile() {
+		return obyFile;
+	}
+	
+	public boolean haveObyFile() {
+		return (obyFile.length() > 0);
+	}
+	
+	public void setSymbolFile(String filename) {
+		if (filename == null) {
+			filename = "";	//$NON-NLS-1$
+		}
+		symbolFile = filename;
+	}
+	
+	public String getSymbolFile() {
+		return symbolFile;
+	}
+	
+	public boolean haveSymbolFile() {
+		return (symbolFile.length() > 0);
+	}
+	
+	public String getDisplayString() {
+		String displayString = "";	//$NON-NLS-1$
+		if (obyFile.length() > 0) {
+			displayString += obyFile;
+		}
+		if (symbolFile.length() > 0) {
+			if (displayString.length() > 0) {
+				displayString += '\n';	//$NON-NLS-1$
+			}
+			displayString += symbolFile;
+		}
+		return displayString;
+	}
+
+	public boolean equals(RofsObySymbolPair pair) {
+		if (this.getObyFile().equals(pair.getObyFile()) == false) {
+			return false;
+		}
+		if (this.getSymbolFile().equals(pair.getSymbolFile()) == false) {
+			return false;
+		}
+		return true;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/SdkChooserBase.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.wizards.ui.util;
+
+import java.util.List;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+
+import com.nokia.carbide.cpp.sdk.core.ISDKManager;
+import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
+import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
+import com.nokia.carbide.cpp.sdk.ui.shared.AddSDKDialog;
+
+// just gather all composite layout stuff here, so both Dialog
+// and Wizard can be the same layout, they should call layout
+// in their layout code
+// Wizard would setControl(layout(parent)) in createControl
+// Dialog would return layout(parent); in layout code e.g. createDialogArea()
+public class SdkChooserBase {
+	// control
+	public Composite composite = null;
+	public Label label = null;
+	public Composite epocrootComposite = null;
+	public Table sdkTable = null;
+	public Composite buttonComposite = null;
+	public Button addSdkButton = null;
+	public Button removeSdkButton = null;
+	public Group sdkGroup = null;
+	public Label directoryDataLabel = null;
+	public Label epocrootLabel = null;
+	public Label osVersionDataLabel = null;
+	public Label osVersionLabel = null;
+	public Label platformDataLabel = null;
+	public Label platformLabel = null;
+
+	public Composite layout(Composite parent) {
+		SDKCorePlugin.getSDKManager();
+		GridLayout gridLayout1 = new GridLayout();
+		gridLayout1.numColumns = 1;
+		composite = new Composite(parent, SWT.NONE);
+		composite.setLayout(gridLayout1);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		label = new Label(composite, SWT.NONE);
+		label.setText(Messages.getString("SdkChooserBase.label")); //$NON-NLS-1$
+		createEpocrootComposite();
+		createSDKGroup();
+
+		return composite;
+	}
+	
+	/**
+	 * This method initializes epocrootComposite	
+	 *
+	 */
+	private void createEpocrootComposite() {
+		GridLayout gridLayout2 = new GridLayout();
+		gridLayout2.numColumns = 2;
+		epocrootComposite = new Composite(composite, SWT.NONE);
+		epocrootComposite.setLayout(gridLayout2);
+		GridData gridData1 = new GridData();
+		gridData1.horizontalAlignment = GridData.FILL;
+		gridData1.grabExcessHorizontalSpace = true;
+		epocrootComposite.setLayoutData(gridData1);
+		sdkTable = new Table(epocrootComposite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE);
+		sdkTable.setHeaderVisible(false);
+		GridData gridData2 = new GridData();
+		gridData2.horizontalAlignment = GridData.FILL;
+		gridData2.grabExcessHorizontalSpace = true;
+		sdkTable.setLayoutData(gridData2);
+		sdkTable.setLinesVisible(false);
+	
+		createButtonComposite();
+		
+		sdkTable.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				propagateSdkDetail();
+			}
+			
+		});
+	}
+	
+	private void createButtonComposite() {
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 1;
+		buttonComposite = new Composite(epocrootComposite, SWT.NONE);
+		buttonComposite.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
+		buttonComposite.setLayout(gridLayout);
+		addSdkButton = new Button (buttonComposite, SWT.NONE);
+		addSdkButton.setText(Messages.getString("SdkChooserBase.addsdk.button")); //$NON-NLS-1$
+		removeSdkButton = new Button (buttonComposite, SWT.NONE);
+		removeSdkButton.setText(Messages.getString("SdkChooserBase.removesdk.button")); //$NON-NLS-1$
+
+		GridData buttonWidthGridData = new GridData();
+		buttonWidthGridData.widthHint = Math.max(addSdkButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x, removeSdkButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
+		addSdkButton.setLayoutData(buttonWidthGridData);
+		removeSdkButton.setLayoutData(buttonWidthGridData);
+
+		addSdkButton.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				handleAddSdk();
+			}
+			
+		});
+		removeSdkButton.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				handleRemoveSdk();
+			}
+			
+		});
+		propagateSdkFromManager();
+	}
+	
+	private void createSDKGroup() {
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 2;
+		sdkGroup = new Group(composite, SWT.NONE);
+		sdkGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		sdkGroup.setLayout(gridLayout);
+		sdkGroup.setText(Messages.getString("SdkChooserBase.sdk.group")); //$NON-NLS-1$
+	
+		epocrootLabel = new Label(sdkGroup, SWT.NONE);
+		epocrootLabel.setText(Messages.getString("SdkChooserBase.epocroot.label")); //$NON-NLS-1$
+		directoryDataLabel = new Label(sdkGroup, SWT.WRAP);
+		directoryDataLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		directoryDataLabel.setText(Messages.getString("SdkChooserBase.directorydata.label")); //$NON-NLS-1$
+		osVersionLabel = new Label(sdkGroup, SWT.NONE);
+		osVersionLabel.setText(Messages.getString("SdkChooserBase.osversion.label")); //$NON-NLS-1$
+		osVersionDataLabel = new Label(sdkGroup, SWT.WRAP);
+		osVersionDataLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		osVersionDataLabel.setText(Messages.getString("SdkChooserBase.osversiondata.label")); //$NON-NLS-1$
+		platformLabel = new Label(sdkGroup, SWT.NONE);
+		platformLabel.setText(Messages.getString("SdkChooserBase.platform.label")); //$NON-NLS-1$
+		platformDataLabel = new Label(sdkGroup, SWT.WRAP);
+		platformDataLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		platformDataLabel.setText(Messages.getString("SdkChooserBase.platformdata.label")); //$NON-NLS-1$
+		
+	}
+	
+	public void propagateSdkFromManager() {
+		List<ISymbianSDK> sdkList = getSDKList();
+		sdkTable.removeAll();
+		for (ISymbianSDK sdk : sdkList) {
+			TableItem item = new TableItem(sdkTable, SWT.NONE);
+			item.setText(sdk.getUniqueId());
+			item.setData(sdk);
+		}
+		if (sdkList.size() == 1) {
+			sdkTable.select(0);
+		}
+	}
+	
+	public void propagateSdkDetail() {
+		TableItem[] items = sdkTable.getSelection();
+		if (items.length > 0) {
+			ISymbianSDK sdk = (ISymbianSDK) items[0].getData();
+			if (sdk != null) {
+				directoryDataLabel.setText(sdk.getEPOCROOT());
+				osVersionDataLabel.setText(sdk.getOSVersion().toString());
+				platformDataLabel.setText(sdk.getAvailablePlatforms().toString());
+			}
+		} else {
+			directoryDataLabel.setText(Messages.getString("SdkChooserBase.directorydata.label")); //$NON-NLS-1$
+			osVersionDataLabel.setText(Messages.getString("SdkChooserBase.osversiondata.label")); //$NON-NLS-1$
+			platformDataLabel.setText(Messages.getString("SdkChooserBase.platformdata.label2"));	 //$NON-NLS-1$
+		}
+	}
+	
+	private void handleAddSdk() {
+		AddSDKDialog dialog = new AddSDKDialog(composite.getShell());
+		if (dialog.open() == AddSDKDialog.OK){
+			getSDKManager().updateCarbideSDKCache();
+			propagateSdkFromManager();
+		}
+	}
+	
+	private void handleRemoveSdk() {
+		TableItem[] items = sdkTable.getSelection();
+		if (items.length > 0) {
+			ISymbianSDK sdk = (ISymbianSDK) items[0].getData();
+			if (sdk != null){
+				if (MessageDialog.openConfirm(composite.getShell(), Messages.getString("SdkChooserBase.confirm.delete") + sdk.getUniqueId() , Messages.getString("SdkChooserBase.confirm.message"))){ //$NON-NLS-1$ //$NON-NLS-2$
+					if (getSDKManager().removeSDK(sdk.getUniqueId())){
+						getSDKList().remove(sdk);
+						getSDKManager().updateCarbideSDKCache();
+						propagateSdkFromManager();
+					}
+				}
+			}			
+		}
+	}
+
+	public List<ISymbianSDK> getSDKList() {
+		return SDKCorePlugin.getSDKManager().getSDKList();
+	}
+
+	public ISDKManager getSDKManager() {
+		return SDKCorePlugin.getSDKManager();
+	}
+
+	public ISymbianSDK getSelectedSdk() {
+		TableItem[] items = sdkTable.getSelection();
+		if (items.length > 0) {
+			return ((ISymbianSDK) items[0].getData());
+		}
+		return null;
+	}
+
+	public void setSelectedSdk(ISymbianSDK romSdk) {
+		TableItem[] items = sdkTable.getItems();
+		sdkTable.deselectAll();
+		for (int i = 0; i < items.length; i++) {
+			if ((ISymbianSDK) items[i].getData() == romSdk) {
+				sdkTable.select(i);
+			}
+		}
+		propagateSdkDetail();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/internal/pi/wizards/ui/util/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,16 @@
+PkgListTreeLabelProvider.sample.file=sample file: 
+PkgListTreeViewer.invalid.content.provider=Invalid content provider in importer
+PkgListTreeLabelProvider.sdk=\ / SDK: 
+SdkChooserBase.label=Select an installed SDK, or add your directory as an installed SDK.
+SdkChooserBase.addsdk.button=Add SDK...
+SdkChooserBase.removesdk.button=Remove SDK...
+SdkChooserBase.sdk.group=SDK Information
+SdkChooserBase.epocroot.label=EPOCROOT:
+SdkChooserBase.directorydata.label=<Please select a SDK>
+SdkChooserBase.osversion.label=OS Version:
+SdkChooserBase.osversiondata.label=<Please select a SDK>
+SdkChooserBase.platform.label=Available Platforms:
+SdkChooserBase.platformdata.label=<Please select a SDK>                                                                                                                          
+SdkChooserBase.platformdata.label2=<Please select a SDK>
+SdkChooserBase.confirm.delete=Confirm Delete 
+SdkChooserBase.confirm.message=Are you sure you want to delete this SDK?\n\nThis entry will be remvoed from your devices.xml.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.wizards/src/com/nokia/carbide/cpp/pi/wizards/WizardsPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.wizards;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class WizardsPlugin extends AbstractUIPlugin {
+	public static final String PLUGIN_ID = "com.nokia.carbide.cpp.pi.wizards";	//$NON-NLS-1$
+	public static final String PHONENSIS_IMAGE_ID = "phonensis.image";	//$NON-NLS-1$
+	public static final String PHONE_IMAGE_ID = "phone.image";	//$NON-NLS-1$
+	public static final String SIS_IMAGE_ID = "sis.image";	//$NON-NLS-1$
+	public static final String CUSTRACE_IMAGE_ID = "custrace.image";	//$NON-NLS-1$
+
+	//The shared instance.
+	private static WizardsPlugin plugin;
+	
+	/**
+	 * The constructor.
+	 */
+	public WizardsPlugin() {
+		plugin = this;
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		plugin = null;
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static WizardsPlugin getDefault() {
+		return plugin;
+	}
+ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/.classpath	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/.settings/org.eclipse.core.resources.prefs	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,12 @@
+#Tue Feb 10 11:22:02 CST 2009
+eclipse.preferences.version=1
+encoding//src/com/nokia/carbide/cpp/internal/pi/actions/messages.properties=8859_1
+encoding//src/com/nokia/carbide/cpp/internal/pi/analyser/messages.properties=8859_1
+encoding//src/com/nokia/carbide/cpp/internal/pi/model/messages.properties=8859_1
+encoding//src/com/nokia/carbide/cpp/internal/pi/perspectives/messages.properties=8859_1
+encoding//src/com/nokia/carbide/cpp/internal/pi/properties/messages.properties=8859_1
+encoding//src/com/nokia/carbide/cpp/internal/pi/test/messages.properties=8859_1
+encoding//src/com/nokia/carbide/cpp/internal/pi/visual/messages.properties=8859_1
+encoding//src/com/nokia/carbide/cpp/pi/editors/messages.properties=8859_1
+encoding//src/com/nokia/carbide/cpp/pi/plugin/manager/messages.properties=8859_1
+encoding//src/com/nokia/carbide/cpp/pi/util/messages.properties=8859_1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/META-INF/MANIFEST.MF	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,30 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Carbide.c++ Performance Investigator
+Bundle-SymbolicName: com.nokia.carbide.cpp.pi;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: com.nokia.carbide.cpp.pi.PiPlugin
+Bundle-Vendor: Nokia
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.resources,
+ org.eclipse.core.runtime,
+ org.eclipse.ui.ide,
+ org.eclipse.draw2d,
+ com.nokia.carbide.cpp.featureTracker,
+ com.nokia.carbide.cpp.pi.core,
+ com.nokia.carbide.cpp.pi.util
+Bundle-ActivationPolicy: lazy
+Export-Package: com.nokia.carbide.cpp.internal.pi.actions,
+ com.nokia.carbide.cpp.internal.pi.analyser,
+ com.nokia.carbide.cpp.internal.pi.interfaces,
+ com.nokia.carbide.cpp.internal.pi.manager,
+ com.nokia.carbide.cpp.internal.pi.model,
+ com.nokia.carbide.cpp.internal.pi.plugin.model,
+ com.nokia.carbide.cpp.internal.pi.resolvers,
+ com.nokia.carbide.cpp.internal.pi.save,
+ com.nokia.carbide.cpp.internal.pi.test,
+ com.nokia.carbide.cpp.internal.pi.utils,
+ com.nokia.carbide.cpp.internal.pi.visual,
+ com.nokia.carbide.cpp.pi,
+ com.nokia.carbide.cpp.pi.editors,
+ com.nokia.carbide.cpp.pi.importer
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/build.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,8 @@
+
+jars.compile.order = .
+bin.includes = META-INF/,\
+               plugin.xml,\
+               icons/,\
+               .
+source.. = src/
+output.. = bin/
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Carbide_c_icon_16x16.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Carbide_c_icon_24x24.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Carbide_c_icon_32x32.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Carbide_c_icon_48x48.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/PI_Meter_16x16.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/PI_Meter_20x20.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Set_current_time_interval.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/Set_current_time_interval_16.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/about.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/about_cpp.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/show_entire_graph.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/show_entire_graph_16.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_in.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_in_16.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_out.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_out_16.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_to_time_interval.png has changed
Binary file sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/icons/zoom_to_time_interval_16.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/plugin.xml	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+   <extension-point id="piPluginData" name="piPluginData" schema="schema/piPluginData.exsd"/>
+
+   <extension
+         point="org.eclipse.ui.propertyPages">
+      <page
+            objectClass="org.eclipse.core.resources.IFile"
+            name="PI Properties"
+            nameFilter="*.npi"
+            class="com.nokia.carbide.cpp.internal.pi.properties.PIPropertyPage"
+            id="com.nokia.carbide.cpp.pi.properties.NPIPropertyPage">
+      </page>
+   </extension>
+   <extension
+         point="org.eclipse.ui.propertyPages">
+      <page
+            objectClass="org.eclipse.core.resources.IFile"
+            name="PI Properties"
+            nameFilter="*.bap"
+            class="com.nokia.carbide.cpp.internal.pi.properties.PIPropertyPage"
+            id="com.nokia.carbide.cpp.pi.properties.PIPropertyPageID">
+      </page>
+   </extension>
+  <extension
+     point="com.nokia.carbide.cpp.pi.piPluginData">
+      <plugin pluginClass="com.nokia.carbide.cpp.pi.PiReturnPlugin"/>
+   </extension>
+   <extension
+         point="org.eclipse.ui.editors">
+      <editor
+            class="com.nokia.carbide.cpp.pi.editors.PIPageEditor"
+            contributorClass="com.nokia.carbide.cpp.pi.editors.PIPageEditorContributor"
+            extensions="bap,npi"
+            icon="icons/PI_Meter_16x16.png"
+            id="com.nokia.carbide.cpp.pi.openEditor"
+            name="Carbide.c++ Performance Investigator"/>
+      <editor
+            class="com.nokia.carbide.cpp.pi.editors.PIPageEditor"
+            contributorClass="com.nokia.carbide.cpp.pi.editors.PIPageEditorContributor"
+            filenames=".picfg"
+            icon="icons/PI_Meter_16x16.png"
+            id="com.nokia.carbide.cpp.pi.ImportEditor"
+            name="Carbide.c++ Performance Investigator"/>
+   </extension>
+   <extension
+         point="org.eclipse.ui.popupMenus">
+   </extension>
+
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/schema/piPluginData.exsd	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,154 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="com.nokia.carbide.cpp.pi">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="com.nokia.carbide.cpp.pi" id="piPluginData" name="piPluginData"/>
+      </appInfo>
+      <documentation>
+         [Enter description of this extension point.]
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="plugin"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="plugin">
+      <complexType>
+         <attribute name="pluginName" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="pluginClass" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn="com.noki.pi.model.IReturnPlugin"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="pluginId" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="pluginVersion" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="pluginProvider" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="pluginLibrary" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="pluginPath" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="pluginRequiredLibraries" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         [Enter the first release in which this extension point appears.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         [Enter API information here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+</schema>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ActionDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class ActionDelegate implements IWorkbenchWindowActionDelegate {
+
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+	}
+
+	public void run(IAction action) {
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/AnalysisDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class AnalysisDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+		window = null;
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/AnalysisInfoDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+public class AnalysisInfoDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+		window = null;
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+
+		AnalysisInfoHandler analysisInfoHandler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+		
+		if (analysisInfoHandler != null)
+		{
+			Shell shell = new Shell(PIPageEditor.currentPageEditor().getEditorSite().getShell().getDisplay());
+			analysisInfoHandler.getAnalysisInfoTable(shell);
+			shell.setLayout(new FillLayout());
+			shell.pack();
+			shell.open();
+		}
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/EventDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import java.text.DecimalFormat;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+public class EventDialog
+{
+	private String eventName;
+	private String eventComment;
+	private long   eventTime;
+
+	private String newEventName;
+	private String newEventComment;
+	private long   newEventTime;
+
+	private Shell shell;
+	private Label label;
+	private GridData gridData;
+	DecimalFormat timeFormat = new DecimalFormat(Messages.getString("EventDialog.timeFormat")); //$NON-NLS-1$
+
+	private Text nameText;
+//	private Text typeText;
+	private Text commentText;
+	private Text timeText;
+
+	public EventDialog(Display display, String eventType, String name, String comment, long time)
+	{
+		showDialog(display, eventType, name, comment, time, false);
+	}
+
+	public EventDialog(Display display, String eventType, String name, String comment, long time, boolean timeChange)
+	{
+		showDialog(display, eventType, name, comment, time, timeChange);
+	}
+
+	private void showDialog(Display display, String type, String name, String comment, long time,
+							boolean timeChange)
+	{
+		// store original values
+		this.eventName    = name;
+		this.eventComment = comment;
+		this.eventTime    = time;
+
+		this.newEventName    = name;
+		this.newEventComment = comment;
+		this.newEventTime    = time;
+
+		// create the shell
+		shell = new Shell(display, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+		shell.setText(type + Messages.getString("EventDialog.event1") + eventName + Messages.getString("EventDialog.event2") + eventTime/1000d + Messages.getString("EventDialog.event3")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		shell.setLayout(new GridLayout(2, true));
+
+		// do let them change the name
+		label = new Label(shell, SWT.LEFT);
+		label.setText(Messages.getString("EventDialog.eventName")); //$NON-NLS-1$
+		label.setFont(PIPageEditor.helvetica_9);
+
+		nameText = new Text(shell, SWT.BORDER);
+		gridData = new GridData(GridData.FILL_HORIZONTAL);
+		nameText.setLayoutData(gridData);
+		nameText.setFont(PIPageEditor.helvetica_9);
+		nameText.setData(Messages.getString("EventDialog.typeName")); //$NON-NLS-1$
+
+		if (eventName == null)
+			nameText.setText(""); //$NON-NLS-1$
+		else
+			nameText.setText(eventName);
+		nameText.setEditable(true);
+
+		// add the listener(s)
+		nameText.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				newEventName = nameText.getText();
+			}
+		});
+		nameText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				newEventName = nameText.getText();
+			}
+		});
+
+//		// do not let them change the event type
+//		label = new Label(shell, SWT.LEFT);
+//		label.setText("Type:");
+//		label.setFont(PIPageEditor.helvetica_9);
+//
+//		typeText = new Text(shell, SWT.NONE);
+//		gridData = new GridData(GridData.FILL_HORIZONTAL);
+//		typeText.setLayoutData(gridData);
+//		typeText.setFont(PIPageEditor.helvetica_9);
+//		typeText.setData("Type a type");
+//		typeText.setText(type);
+//		typeText.setEditable(false);
+
+		// do let them change the comment
+		label = new Label(shell, SWT.LEFT);
+		label.setText(Messages.getString("EventDialog.comment")); //$NON-NLS-1$
+		label.setFont(PIPageEditor.helvetica_9);
+
+		commentText = new Text(shell, SWT.BORDER);
+		gridData = new GridData(GridData.FILL_HORIZONTAL);
+		commentText.setLayoutData(gridData);
+		commentText.setFont(PIPageEditor.helvetica_9);
+		commentText.setData(Messages.getString("EventDialog.typeComment")); //$NON-NLS-1$
+
+		if (eventComment == null)
+			commentText.setText(""); //$NON-NLS-1$
+		else
+			commentText.setText(eventComment);
+		commentText.setEditable(true);
+
+		// add the listener(s)
+		commentText.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				newEventComment = commentText.getText();
+			}
+		});
+		commentText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				newEventComment = commentText.getText();
+			}
+		});
+
+		// maybe let them change the time
+		label = new Label(shell, SWT.LEFT);
+		label.setText(Messages.getString("EventDialog.time")); //$NON-NLS-1$
+		label.setFont(PIPageEditor.helvetica_9);
+
+		timeText = new Text(shell, SWT.NONE);
+		gridData = new GridData(GridData.FILL_HORIZONTAL);
+		timeText.setLayoutData(gridData);
+		timeText.setFont(PIPageEditor.helvetica_9);
+		timeText.setData(Messages.getString("EventDialog.typeTime")); //$NON-NLS-1$
+		timeText.setText(timeFormat.format(eventTime/1000d));
+		timeText.setEditable(false);
+
+		// add the listener(s)
+		timeText.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				newEventTime = convert(timeText, newEventTime);
+			}
+		});
+		timeText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				newEventTime = convert(timeText, newEventTime);
+			}
+		});
+
+		// create the OK button
+		Button okButton = new Button(shell, SWT.NONE);
+		okButton.setText(Messages.getString("EventDialog.ok")); //$NON-NLS-1$
+		gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
+		okButton.setLayoutData(gridData);
+
+		// add the listener(s)
+		okButton.addSelectionListener(new SelectionListener(){
+			public void widgetSelected(SelectionEvent e) {
+				if (   ((eventName == null) && (newEventName != null))
+					|| ((eventName != null) && !eventName.equals(newEventName))
+					|| ((eventComment == null) && (newEventComment != null))
+					|| ((eventComment != null) && !eventComment.equals(newEventComment))
+					|| eventTime != newEventTime)
+				{
+					// the file has changed
+					PIPageEditor.currentPageEditor().setDirty();
+				}
+				shell.close();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+		});
+
+		// create the Cancel button
+		Button cancelButton = new Button(shell, SWT.NONE);
+		cancelButton.setText(Messages.getString("EventDialog.cancel")); //$NON-NLS-1$
+		gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
+		cancelButton.setLayoutData(gridData);
+
+		// add the listener(s)
+		cancelButton.addSelectionListener(new SelectionListener(){
+			public void widgetSelected(SelectionEvent e) {
+				newEventName    = eventName;
+				newEventComment = eventComment;
+				newEventTime    = eventTime;
+				shell.close();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+		});
+
+		shell.pack();
+		shell.open();
+		
+		GC gc = new GC(shell);
+		Point point = gc.stringExtent(shell.getText());
+		gc.dispose();
+
+		Rectangle bounds = shell.getBounds();
+		bounds.width = point.x + 100;
+		shell.setBounds(bounds);
+
+		while (!shell.isDisposed()) {
+			if (!display.readAndDispatch()) {
+				display.sleep();
+			}
+		}
+	}
+
+	private long convert(Text text, long currentTime)
+	{
+		double new_double;
+
+		// convert, catch (NumberFormatException e1)
+		try {
+			new_double = Double.parseDouble(text.getText().replace(',','.'));
+			if (new_double >= 0)
+				currentTime = (long) (new_double * 1000);
+		} catch (NumberFormatException exc) {
+			// just keep the old value
+		}
+
+		text.setText(timeFormat.format(currentTime/10/100d));
+
+		return currentTime;
+	}
+
+	public String getName()
+	{
+		return this.eventName;
+	}
+	public String getComment()
+	{
+		return this.eventComment;
+	}
+
+	public long   getTime()
+	{
+		return this.eventTime;
+	}
+
+	public String getNewName()
+	{
+		return this.newEventName;
+	}
+
+	public String getNewComment()
+	{
+		return this.newEventComment;
+	}
+
+	public long   getNewTime()
+	{
+		return this.newEventTime;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.actions.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/SaveListScreenShot.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
+
+
+public class SaveListScreenShot implements IWorkbenchWindowActionDelegate {
+
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+	}
+
+	public void run(IAction action) {
+		PIChangeEvent.action("listscreenshot"); //$NON-NLS-1$
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/SaveSamples.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
+import com.nokia.carbide.cpp.internal.pi.save.SaveSamplesWizard;
+
+
+public class SaveSamples {
+	public SaveSamples(ISaveSamples saveSamples) {
+		WizardDialog dialog;
+		Wizard wizard = new SaveSamplesWizard(saveSamples);
+		dialog = new WizardDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), wizard);
+    	dialog.open();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/SaveScreenShotDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
+
+
+public class SaveScreenShotDelegate implements IWorkbenchWindowActionDelegate {
+
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+	}
+
+	public void run(IAction action) {
+		PIChangeEvent.action("screenshot"); //$NON-NLS-1$
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/SetThresholdsDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import java.text.DecimalFormat;
+import java.util.Enumeration;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+public class SetThresholdsDialog {
+
+	private Shell shell;
+
+	private Group threadGroup;
+	private Label threadLoadLabel;
+	private Label threadCountLabel;
+	private Text  threadLoadText;
+	private Text  threadCountText;
+
+	private Button button;
+
+	private Group binaryGroup;
+	private Label binaryLoadLabel;
+	private Label binaryCountLabel;
+	private Text  binaryLoadText;
+	private Text  binaryCountText;
+
+	private Group functionGroup;
+	private Label functionLoadLabel;
+	private Label functionCountLabel;
+	private Text  functionLoadText;
+	private Text  functionCountText;
+
+	private Button ok;
+	private Button cancel;
+	private GridData gridData;
+	private DecimalFormat timeFormat = new DecimalFormat(Messages.getString("SetThresholdsDialog.decimalFormat")); //$NON-NLS-1$
+
+	private double thresholdLoadThread;
+	private double thresholdLoadBinary;
+	private double thresholdLoadFunction;
+	private int thresholdCountThread;
+	private int thresholdCountBinary;
+	private int thresholdCountFunction;
+
+	public SetThresholdsDialog(Display display)
+	{
+		thresholdLoadThread    = (Double) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdLoadThread");			//$NON-NLS-1$
+		thresholdLoadBinary    = (Double) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdLoadBinary");		//$NON-NLS-1$
+		thresholdLoadFunction  = (Double) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdLoadFunction");		//$NON-NLS-1$
+		thresholdCountThread   = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread");		//$NON-NLS-1$
+		thresholdCountBinary   = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary");		//$NON-NLS-1$
+		thresholdCountFunction = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction");		//$NON-NLS-1$
+
+		shell = new Shell(display, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+		shell.setText(Messages.getString("SetThresholdsDialog.thresholdTitle")); //$NON-NLS-1$
+		shell.setLayout(new GridLayout(4, false));
+
+		// thread threshold
+		threadGroup = new Group(shell, SWT.NONE);
+		threadGroup.setText(Messages.getString("SetThresholdsDialog.threadThreshold")); //$NON-NLS-1$
+		threadGroup.setFont(PIPageEditor.helvetica_10);
+		gridData = new GridData(SWT.FILL, SWT.CENTER, true, true);
+		gridData.horizontalSpan = 4;
+		threadGroup.setLayoutData(gridData);
+		threadGroup.setLayout(new FillLayout());
+
+		threadLoadLabel = new Label(threadGroup, SWT.RIGHT);
+		threadLoadLabel.setText(Messages.getString("SetThresholdsDialog.averageLoad")); //$NON-NLS-1$
+		threadLoadLabel.setFont(PIPageEditor.helvetica_9);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 1;
+
+		threadLoadText = new Text(threadGroup, SWT.BORDER | SWT.RIGHT);
+		threadLoadText.setFont(PIPageEditor.helvetica_9);
+		threadLoadText.setData(Messages.getString("SetThresholdsDialog.minimumPercent")); //$NON-NLS-1$
+		threadLoadText.setText(timeFormat.format(thresholdLoadThread * 100.0));
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 1;
+
+		threadCountLabel = new Label(threadGroup, SWT.LEFT);
+		threadCountLabel.setText(Messages.getString("SetThresholdsDialog.totalSamples")); //$NON-NLS-1$
+		threadCountLabel.setFont(PIPageEditor.helvetica_9);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 1;
+
+		threadCountText = new Text(threadGroup, SWT.BORDER | SWT.RIGHT);
+		threadCountText.setFont(PIPageEditor.helvetica_9);
+		threadCountText.setData(Messages.getString("SetThresholdsDialog.minimumSamples")); //$NON-NLS-1$
+		threadCountText.setText("" + thresholdCountThread); //$NON-NLS-1$
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 1;
+
+		// add the thread listeners
+		threadLoadText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdLoadThread  = convert(threadLoadText, thresholdLoadThread, 0, 100, timeFormat) / 100.0;
+				thresholdCountThread = (int) ((totalSampleCount / samplingInterval) * thresholdLoadThread + 0.5);
+				threadLoadText.setText(timeFormat.format(thresholdLoadThread * 100.0));
+				threadCountText.setText("" + thresholdCountThread); //$NON-NLS-1$
+				
+				Boolean useOnlyThreadThresholds = (Boolean) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.useOnlyThreadThresholds");  //$NON-NLS-1$
+				if (useOnlyThreadThresholds) {
+					copyThreadThresholds();
+				}
+			}
+		});
+
+		threadLoadText.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdLoadThread  = convert(threadLoadText, thresholdLoadThread, 0, 100, timeFormat) / 100.0;
+				thresholdCountThread = (int) ((totalSampleCount / samplingInterval) * thresholdLoadThread + 0.5);
+				threadLoadText.setText(timeFormat.format(thresholdLoadThread * 100.0));
+				threadCountText.setText("" + thresholdCountThread); //$NON-NLS-1$
+
+				Boolean useOnlyThreadThresholds = (Boolean) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.useOnlyThreadThresholds"); //$NON-NLS-1$
+				if (useOnlyThreadThresholds) {
+					copyThreadThresholds();
+				}
+			}
+		});
+
+		threadCountText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdCountThread = convert(threadCountText, thresholdCountThread, 0, totalSampleCount / samplingInterval);
+				thresholdLoadThread  = ((double)thresholdCountThread * samplingInterval) / ((double)totalSampleCount);
+				threadLoadText.setText(timeFormat.format(thresholdLoadThread * 100.0));
+				threadCountText.setText("" + thresholdCountThread); //$NON-NLS-1$
+
+				Boolean useOnlyThreadThresholds = (Boolean) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.useOnlyThreadThresholds");	//$NON-NLS-1$
+				if (useOnlyThreadThresholds) {
+					copyThreadThresholds();
+				}
+			}
+		});
+
+		threadCountText.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdCountThread = convert(threadCountText, thresholdCountThread, 0, totalSampleCount / samplingInterval);
+				thresholdLoadThread  = ((double)thresholdCountThread * samplingInterval) / ((double)totalSampleCount);
+				threadLoadText.setText(timeFormat.format(thresholdLoadThread * 100.0));
+				threadCountText.setText("" + thresholdCountThread); //$NON-NLS-1$
+
+				Boolean useOnlyThreadThresholds = (Boolean) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.useOnlyThreadThresholds");	 //$NON-NLS-1$
+				if (useOnlyThreadThresholds) {
+					copyThreadThresholds();
+				}
+			}
+		});
+
+		threadGroup.pack();
+
+		button = new Button(shell, SWT.LEFT | SWT.CHECK);
+		button.setText(Messages.getString("SetThresholdsDialog.useThreadForAll")); //$NON-NLS-1$
+		button.setFont(PIPageEditor.helvetica_8);
+		button.setSelection((Boolean) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.useOnlyThreadThresholds"));	 //$NON-NLS-1$
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 10;
+		button.setLayoutData(gridData);
+
+		// add the button listeners
+		button.addSelectionListener(new SelectionListener() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.useOnlyThreadThresholds", button.getSelection()); //$NON-NLS-1$
+				Boolean useOnlyThreadThresholds = (Boolean) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.useOnlyThreadThresholds"); //$NON-NLS-1$
+				
+				if (useOnlyThreadThresholds) {
+					// disable the other numbers
+					binaryLoadText.setEnabled(false);
+					binaryCountText.setEnabled(false);
+					functionLoadText.setEnabled(false);
+					functionCountText.setEnabled(false);
+					copyThreadThresholds();
+				} else {
+					binaryLoadText.setEnabled(true);
+					binaryCountText.setEnabled(true);
+					functionLoadText.setEnabled(true);
+					functionCountText.setEnabled(true);
+				}
+			}
+
+			public void widgetSelected(SelectionEvent e) {
+				widgetDefaultSelected(e);
+			}
+		});
+
+		// binary threshold
+		binaryGroup = new Group(shell, SWT.LEFT);
+		binaryGroup.setText(Messages.getString("SetThresholdsDialog.binaryThreshold")); //$NON-NLS-1$
+		binaryGroup.setFont(PIPageEditor.helvetica_10);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 4;
+		binaryGroup.setLayoutData(gridData);
+		binaryGroup.setLayout(new FillLayout());
+
+		binaryLoadLabel = new Label(binaryGroup, SWT.RIGHT);
+		binaryLoadLabel.setText(Messages.getString("SetThresholdsDialog.averageLoad")); //$NON-NLS-1$
+		binaryLoadLabel.setFont(PIPageEditor.helvetica_9);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 1;
+
+		binaryLoadText = new Text(binaryGroup, SWT.BORDER | SWT.RIGHT);
+		binaryLoadText.setFont(PIPageEditor.helvetica_9);
+		binaryLoadText.setData(Messages.getString("SetThresholdsDialog.minimumPercent")); //$NON-NLS-1$
+		binaryLoadText.setText(timeFormat.format(thresholdLoadBinary * 100.0));
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 1;
+
+		binaryCountLabel = new Label(binaryGroup, SWT.LEFT);
+		binaryCountLabel.setText(Messages.getString("SetThresholdsDialog.totalSamples")); //$NON-NLS-1$
+		binaryCountLabel.setFont(PIPageEditor.helvetica_9);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 1;
+
+		binaryCountText = new Text(binaryGroup, SWT.BORDER | SWT.RIGHT);
+		binaryCountText.setFont(PIPageEditor.helvetica_9);
+		binaryCountText.setData(Messages.getString("SetThresholdsDialog.minimumSamples")); //$NON-NLS-1$
+		binaryCountText.setText("" + thresholdCountBinary); //$NON-NLS-1$
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 1;
+
+		// add the listeners
+		binaryLoadText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdLoadBinary  = convert(binaryLoadText, thresholdLoadBinary, 0, 100, timeFormat) / 100.0;
+				thresholdCountBinary = (int) ((totalSampleCount / samplingInterval) * thresholdLoadBinary + 0.5);
+				binaryLoadText.setText(timeFormat.format(thresholdLoadBinary * 100.0));
+				binaryCountText.setText("" + thresholdCountBinary); //$NON-NLS-1$
+			}
+		});
+
+		binaryLoadText.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdLoadBinary  = convert(binaryLoadText, thresholdLoadBinary, 0, 100, timeFormat) / 100.0;
+				thresholdCountBinary = (int) ((totalSampleCount / samplingInterval) * thresholdLoadBinary + 0.5);
+				binaryLoadText.setText(timeFormat.format(thresholdLoadBinary * 100.0));
+				binaryCountText.setText("" + thresholdCountBinary); //$NON-NLS-1$
+			}
+		});
+
+		binaryCountText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdCountBinary = convert(binaryCountText, thresholdCountBinary, 0, totalSampleCount / samplingInterval);
+				thresholdLoadBinary = ((double)thresholdCountBinary * samplingInterval) / ((double)totalSampleCount);
+				binaryLoadText.setText(timeFormat.format(thresholdLoadBinary * 100.0));
+				binaryCountText.setText("" + thresholdCountBinary); //$NON-NLS-1$
+			}
+		});
+
+		binaryCountText.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdCountBinary = convert(binaryCountText, thresholdCountBinary, 0, totalSampleCount / samplingInterval);
+				thresholdLoadBinary = ((double)thresholdCountBinary * samplingInterval) / ((double)totalSampleCount);
+				binaryLoadText.setText(timeFormat.format(thresholdLoadBinary * 100.0));
+				binaryCountText.setText("" + thresholdCountBinary); //$NON-NLS-1$
+			}
+		});
+
+		binaryGroup.pack();
+
+		// function threshold
+		functionGroup = new Group(shell, SWT.LEFT);
+		functionGroup.setText(Messages.getString("SetThresholdsDialog.functionThreshold")); //$NON-NLS-1$
+		functionGroup.setFont(PIPageEditor.helvetica_10);
+		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+		gridData.horizontalSpan = 4;
+		functionGroup.setLayoutData(gridData);
+		functionGroup.setLayout(new FillLayout());
+
+		functionLoadLabel = new Label(functionGroup, SWT.RIGHT);
+		functionLoadLabel.setText(Messages.getString("SetThresholdsDialog.averageLoad")); //$NON-NLS-1$
+		functionLoadLabel.setFont(PIPageEditor.helvetica_9);
+
+		functionLoadText = new Text(functionGroup, SWT.BORDER | SWT.RIGHT);
+		functionLoadText.setFont(PIPageEditor.helvetica_9);
+		functionLoadText.setData(Messages.getString("SetThresholdsDialog.minimumPercent")); //$NON-NLS-1$
+		functionLoadText.setText(timeFormat.format(thresholdLoadFunction * 100.0));
+
+		functionCountLabel = new Label(functionGroup, SWT.LEFT);
+		functionCountLabel.setText(Messages.getString("SetThresholdsDialog.totalSamples")); //$NON-NLS-1$
+		functionCountLabel.setFont(PIPageEditor.helvetica_9);
+
+		functionCountText = new Text(functionGroup, SWT.BORDER | SWT.RIGHT);
+		functionCountText.setFont(PIPageEditor.helvetica_9);
+		functionCountText.setData(Messages.getString("SetThresholdsDialog.minimumSamples")); //$NON-NLS-1$
+		functionCountText.setText("" + thresholdCountFunction); //$NON-NLS-1$
+
+		// add the listeners
+		functionLoadText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdLoadFunction  = convert(functionLoadText, thresholdLoadFunction, 0, 100, timeFormat) / 100.0;
+				thresholdCountFunction = (int) ((totalSampleCount / samplingInterval) * thresholdLoadFunction + 0.5);
+				functionLoadText.setText(timeFormat.format(thresholdLoadFunction * 100.0));
+				functionCountText.setText("" + thresholdCountFunction); //$NON-NLS-1$
+			}
+		});
+
+		functionLoadText.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdLoadFunction  = convert(functionLoadText, thresholdLoadFunction, 0, 100, timeFormat) / 100.0;
+				thresholdCountFunction = (int) ((totalSampleCount / samplingInterval) * thresholdLoadFunction + 0.5);
+				functionLoadText.setText(timeFormat.format(thresholdLoadFunction * 100.0));
+				functionCountText.setText("" + thresholdCountFunction); //$NON-NLS-1$
+			}
+		});
+
+		functionCountText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdCountFunction = convert(functionCountText, thresholdCountFunction, 0, totalSampleCount / samplingInterval);
+				thresholdLoadFunction = ((double)thresholdCountFunction * samplingInterval) / ((double)totalSampleCount);
+				functionLoadText.setText(timeFormat.format(thresholdLoadFunction * 100.0));
+				functionCountText.setText("" + thresholdCountFunction); //$NON-NLS-1$
+			}
+		});
+
+		functionCountText.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				int uid = NpiInstanceRepository.getInstance().activeUid();
+				int totalSampleCount = NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.THREADS_PAGE).getLastSampleX();
+				int samplingInterval = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.samplingInterval"); //$NON-NLS-1$
+				thresholdCountFunction = convert(functionCountText, thresholdCountFunction, 0, totalSampleCount / samplingInterval);
+				thresholdLoadFunction = ((double)thresholdCountFunction * samplingInterval) / ((double)totalSampleCount);
+				functionLoadText.setText(timeFormat.format(thresholdLoadFunction * 100.0));
+				functionCountText.setText("" + thresholdCountFunction); //$NON-NLS-1$
+			}
+		});
+
+		functionGroup.pack();
+
+		// create the OK button
+		ok = new Button(shell, SWT.NONE);
+		ok.setEnabled(false);
+		ok.setVisible(false);
+
+		ok = new Button(shell, SWT.NONE);
+		ok.setText(Messages.getString("SetThresholdsDialog.ok")); //$NON-NLS-1$
+		gridData = new GridData(SWT.CENTER, SWT.CENTER, true, true);
+		gridData.minimumWidth = 60;
+		ok.setLayoutData(gridData);
+		ok.addSelectionListener(new SelectionListener(){
+
+			public void widgetSelected(SelectionEvent e) {
+				boolean changedThread   = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread") != thresholdCountThread;	//$NON-NLS-1$
+				boolean changedBinary   = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary")  != thresholdCountBinary;	//$NON-NLS-1$
+				boolean changedFunction = (Integer) NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction") != thresholdCountFunction;	//$NON-NLS-1$
+
+				if (changedThread) {
+					NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.thresholdLoadThread", new Double(thresholdLoadThread)); //$NON-NLS-1$
+					NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountThread", new Integer(thresholdCountThread)); //$NON-NLS-1$
+					PIChangeEvent.action("changeThresholdThread"); //$NON-NLS-1$
+					PIChangeEvent.action("changeSelection"); //$NON-NLS-1$
+				}
+
+				if (changedBinary) {
+					NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.thresholdLoadBinary", new Double(thresholdLoadBinary)); //$NON-NLS-1$
+					NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountBinary", new Integer(thresholdCountBinary)); //$NON-NLS-1$
+					PIChangeEvent.action("changeThresholdBinary"); //$NON-NLS-1$
+					PIChangeEvent.action("changeSelection"); //$NON-NLS-1$
+				}
+
+				if (changedFunction) {
+					NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.thresholdLoadFunction", new Double(thresholdLoadFunction)); //$NON-NLS-1$
+					NpiInstanceRepository.getInstance().activeUidSetPersistState("com.nokia.carbide.cpp.pi.address.thresholdCountFunction", new Integer(thresholdCountFunction)); //$NON-NLS-1$
+					PIChangeEvent.action("changeThresholdFunction"); //$NON-NLS-1$
+					PIChangeEvent.action("changeSelection"); //$NON-NLS-1$
+				}
+
+				// after the graphs have been updated, notify plugins that might have tables but no graphs
+        		Enumeration enu = PluginInitialiser.getPluginInstances(
+        									"com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+        		if (enu != null) {
+        			Event event = new Event();
+
+            		while (enu.hasMoreElements())
+            		{
+            			IEventListener plugin = (IEventListener)enu.nextElement();
+            			if (changedThread) {
+            				event.data  = new Double(thresholdLoadThread);
+            				event.count = thresholdCountThread;
+                			plugin.receiveEvent("changeThresholdThread", event); //$NON-NLS-1$
+            			}
+
+            			if (changedBinary) {
+            				event.data  = new Double(thresholdLoadBinary);
+            				event.count = thresholdCountBinary;
+                			plugin.receiveEvent("changeThresholdBinary", event); //$NON-NLS-1$
+            			}
+
+            			if (changedFunction) {
+            				event.data  = new Double(thresholdLoadFunction);
+            				event.count = thresholdCountFunction;
+                			plugin.receiveEvent("changeThresholdFunction", event); //$NON-NLS-1$
+            			}
+            		}
+        		}
+
+				shell.close();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+		});
+
+		ok = new Button(shell, SWT.NONE);
+		ok.setEnabled(false);
+		ok.setVisible(false);
+
+		// create the Cancel button
+		cancel = new Button(shell, SWT.NONE);
+		cancel.setText(Messages.getString("SetThresholdsDialog.cancel")); //$NON-NLS-1$
+		gridData = new GridData(SWT.LEFT, SWT.CENTER, true, true);
+		gridData.minimumWidth = 60;
+		cancel.setLayoutData(gridData);
+		cancel.addSelectionListener(new SelectionListener(){
+
+			public void widgetSelected(SelectionEvent e) {
+				shell.close();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+		});
+
+		if ((Boolean)NpiInstanceRepository.getInstance().activeUidGetPersistState("com.nokia.carbide.cpp.pi.address.useOnlyThreadThresholds") == true) { //$NON-NLS-1$
+			// disable the other numbers
+			binaryLoadText.setEnabled(false);
+			binaryCountText.setEnabled(false);
+			functionLoadText.setEnabled(false);
+			functionCountText.setEnabled(false);
+		}
+
+		shell.pack();
+		shell.open();
+
+		while (!shell.isDisposed()) {
+			if (!shell.getDisplay().readAndDispatch()) {
+				shell.getDisplay().sleep();
+			}
+		}
+	}
+
+	private double convert(Text text, double currentDouble, double minimum, double maximum, DecimalFormat format)
+	{
+		double new_double;
+
+		// convert, catch (NumberFormatException e1)
+		try {
+			new_double = Double.parseDouble(text.getText().replace(',','.'));
+			if (new_double >= 0)
+				currentDouble = new_double;
+		} catch (NumberFormatException exc) {
+			// just keep the old value
+		}
+
+		if (currentDouble > maximum)
+			currentDouble = maximum;
+		else if (currentDouble < minimum)
+			currentDouble = minimum;
+
+		text.setText(format.format(currentDouble));
+
+		return currentDouble;
+	}
+
+	private int convert(Text text, int currentInt, int minimum, int maximum)
+	{
+		int new_int;
+
+		// convert, catch (NumberFormatException e1)
+		try {
+			new_int = Integer.parseInt(text.getText().replace(',','.'));
+			if (new_int >= 0)
+				currentInt = new_int;
+		} catch (NumberFormatException exc) {
+			// just keep the old value
+		}
+
+		if (currentInt > maximum)
+			currentInt = maximum;
+		else if (currentInt < minimum)
+			currentInt = minimum;
+
+		text.setText("" + currentInt); //$NON-NLS-1$
+
+		return currentInt;
+	}
+	
+	private void copyThreadThresholds() {
+		thresholdLoadBinary    = thresholdLoadThread;
+		thresholdCountBinary   = thresholdCountThread;
+		thresholdLoadFunction  = thresholdLoadThread;
+		thresholdCountFunction = thresholdCountThread;
+		binaryLoadText.setText(timeFormat.format(thresholdLoadBinary * 100.0));
+		binaryCountText.setText("" + thresholdCountBinary); //$NON-NLS-1$
+		functionLoadText.setText(timeFormat.format(thresholdLoadFunction * 100.0));
+		functionCountText.setText("" + thresholdCountFunction); //$NON-NLS-1$
+	}
+
+	public void dispose()
+	{
+		if (this.shell != null) {
+			if (!this.shell.isDisposed()) {
+				this.shell.close();				
+			}
+			this.shell.dispose();
+		}
+
+		this.shell = null;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ShowEndDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class ShowEndDelegate implements IWorkbenchWindowActionDelegate {
+
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+	}
+
+	public void run(IAction action) {
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ShowStartDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class ShowStartDelegate implements IWorkbenchWindowActionDelegate {
+
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+	}
+
+	public void run(IAction action) {
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/SynchronizeDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.internal.pi.model.PiManager;
+
+
+public class SynchronizeDelegate implements IWorkbenchWindowActionDelegate {
+
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+	}
+
+	public void run(IAction action) {
+	      PiManager.getManager().synchronizePI();
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/TimeSetAction.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import java.text.DecimalFormat;
+import java.util.Enumeration;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+
+
+public class TimeSetAction extends org.eclipse.jface.action.ControlContribution {
+
+	double startTime = 0;
+	double endTime   = 0;
+	
+	private Text  startTimeText;
+	private Text  endTimeText;
+	
+	private DecimalFormat timeFormat = new DecimalFormat(Messages.getString("TimeSetAction.decimalFormat")); //$NON-NLS-1$
+	
+	public TimeSetAction(String id) {
+		super(id);
+	}
+	
+	public void setTime(double start, double end) {
+		if (start < 0f)
+			start = 0f;
+		
+		if (end < 0f)
+			end = 0f;
+		
+		if (start <= end) {
+			this.startTime = start;
+			this.endTime   = end;
+		} else {
+			// swap start and end
+			double temp = start;
+			this.startTime = end;
+			this.endTime   = temp;
+		}
+
+		if ((startTimeText == null) || (endTimeText == null))
+			return;
+
+		startTimeText.setText(timeFormat.format(startTime));
+		endTimeText.setText(timeFormat.format(endTime));
+	}
+	
+	public void setStartTime(double start) {
+		setTime(start, this.endTime);
+	}
+	
+	public void setEndTime(double end) {
+		setTime(this.startTime, end);
+	}
+	
+	public double getStartTime() {
+		return this.startTime;
+	}
+
+	public double getEndTime() {
+		return this.endTime;
+	}
+
+	protected Control createControl(Composite parent) {
+		Composite control;
+		Label label;
+
+		// create a composite where the user can enter a start time and an end time
+		control = new Composite(parent, SWT.BORDER);
+		parent.setLayout(new FillLayout(SWT.HORIZONTAL));
+		control.setLayout(new FillLayout(SWT.HORIZONTAL));
+
+		label = new Label(control, SWT.RIGHT);
+		label.setText(Messages.getString("TimeSetAction.startTime")); //$NON-NLS-1$
+		label.pack();
+
+		startTimeText = new Text(control, SWT.BORDER);
+		
+		if (startTime >= 0.0f)
+			startTimeText.setText(timeFormat.format(startTime));
+		else
+			startTimeText.setText(""); //$NON-NLS-1$
+
+		startTimeText.addFocusListener(new FocusListener() {
+
+			double initialStartTime = -1;
+			
+			public void focusGained(FocusEvent e) {
+				initialStartTime = startTime;
+			}
+
+			public void focusLost(FocusEvent e) {
+				double new_double;
+				
+				// convert, catch (NumberFormatException e1)
+				try {
+					new_double = Double.parseDouble(startTimeText.getText().replace(',','.'));
+					if (new_double >= 0)
+						startTime = new_double;
+				} catch (NumberFormatException exc) {
+					// just keep the old value
+				}					
+
+				// redisplay the time
+				setTime(startTime, endTime);
+				
+				if (startTime != initialStartTime) {
+					PIChangeEvent.action("changeSelection"); //$NON-NLS-1$
+					
+					// after the graphs have been updated, notify plugins that might have tables but no graphs
+            		Enumeration enu = PluginInitialiser.getPluginInstances(
+            									"com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+            		if (enu != null) {
+            			Event event = new Event();
+            			event.start = (int) startTime;
+            			event.end   = (int) endTime;
+            			
+	            		while (enu.hasMoreElements())
+	            		{
+	            			IEventListener plugin = (IEventListener)enu.nextElement();
+	            			plugin.receiveEvent("changeSelection", event); //$NON-NLS-1$
+	            		}
+            		}
+				}
+			}
+
+		});
+		
+		startTimeText.addSelectionListener(new SelectionListener() {
+
+			public void widgetSelected(SelectionEvent e) {
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				double new_double;
+
+				// convert, catch (NumberFormatException e1)
+				try {
+					new_double = Double.parseDouble(startTimeText.getText().replace(',','.'));
+					if (new_double >= 0)
+						startTime = new_double;
+				} catch (NumberFormatException exc) {
+					// just keep the old value
+				}					
+
+				// redisplay the time
+				setTime(startTime, endTime);
+			}
+
+		});
+
+		label = new Label(control, SWT.RIGHT);
+		label.setText(Messages.getString("TimeSetAction.endTime")); //$NON-NLS-1$
+		label.pack();
+
+		endTimeText   = new Text(control, SWT.BORDER);
+
+		if (endTime >= 0.0f)
+			endTimeText.setText(timeFormat.format(endTime));
+		else
+			endTimeText.setText(""); //$NON-NLS-1$
+
+		endTimeText.addFocusListener(new FocusListener() {
+			
+			double initialEndTime   = -1;
+
+			public void focusGained(FocusEvent e) {
+				initialEndTime = endTime;
+			}
+
+			public void focusLost(FocusEvent e) {
+				double new_double;
+				
+				// convert, catch (NumberFormatException e1)
+				try {
+					new_double = Double.parseDouble(endTimeText.getText().replace(',','.'));
+					if (new_double >= 0)
+						endTime = new_double;
+				} catch (NumberFormatException exc) {
+					// just keep the old value
+				}					
+
+				// redisplay the time
+				setTime(startTime, endTime);
+				if (endTime != initialEndTime) {
+					PIChangeEvent.action("changeSelection"); //$NON-NLS-1$
+					
+					// after the graphs have been updated, notify plugins that might have tables but no graphs
+            		Enumeration enu = PluginInitialiser.getPluginInstances(
+            									"com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+            		if (enu != null) {
+            			Event event = new Event();
+            			event.start = (int) startTime;
+            			event.end   = (int) endTime;
+            			
+	            		while (enu.hasMoreElements())
+	            		{
+	            			IEventListener plugin = (IEventListener)enu.nextElement();
+	            			plugin.receiveEvent("changeSelection", event); //$NON-NLS-1$
+	            		}
+            		}
+				}
+			}
+
+		});
+		
+		endTimeText.addSelectionListener(new SelectionListener() {
+
+			public void widgetSelected(SelectionEvent e) {
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				double new_double;
+			
+				// convert, catch (NumberFormatException e1)
+				try {
+					new_double = Double.parseDouble(endTimeText.getText().replace(',','.'));
+					if (new_double >= 0)
+						endTime = new_double;
+				} catch (NumberFormatException exc) {
+					// just keep the old value
+				}					
+
+				// redisplay the time
+				setTime(startTime, endTime);
+			}
+			
+		});
+
+		control.addFocusListener(new FocusListener() {
+
+			public void focusGained(FocusEvent e) {
+			}
+
+			public void focusLost(FocusEvent e) {
+				if (startTime >= 0.0f)
+					startTimeText.setText(timeFormat.format(startTime));
+				else
+					startTimeText.setText(""); //$NON-NLS-1$
+				
+				if (endTime >= 0.0f)
+					endTimeText.setText(timeFormat.format(endTime));
+				else
+					endTimeText.setText(""); //$NON-NLS-1$
+			}
+			
+		});
+
+		return control;
+	}
+	
+	public void dispose() {
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/TimeSetDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import java.text.DecimalFormat;
+import java.util.Enumeration;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+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.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+public class TimeSetDialog {
+
+	private Shell shell;
+	private Label label;
+	private Text startTimeText;
+	private Text endTimeText;
+	private Label labelMsg;
+	private Button ok;
+	private Button cancel;
+	private GridData gridData;
+	private double startTime;
+	private double endTime;
+	private DecimalFormat timeFormat = new DecimalFormat(Messages.getString("TimeSetDialog.decimalFormat")); //$NON-NLS-1$
+	
+	public TimeSetDialog(Display display, double start, double end)
+	{
+		this.startTime = start;
+		this.endTime   = end;
+		
+		shell = new Shell(display, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
+		shell.setText(Messages.getString("TimeSetDialog.selectInterval")); //$NON-NLS-1$
+		shell.setLayout(new GridLayout(2, true));
+		
+		// create the start time label and input box
+		label = new Label(shell, SWT.LEFT);
+		label.setText(Messages.getString("TimeSetDialog.startTime")); //$NON-NLS-1$
+		label.setFont(PIPageEditor.helvetica_9);
+		
+		startTimeText = new Text(shell, SWT.BORDER);
+		gridData = new GridData(GridData.FILL_HORIZONTAL);
+		startTimeText.setLayoutData(gridData);
+		startTimeText.setFont(PIPageEditor.helvetica_9);
+		startTimeText.setData(Messages.getString("TimeSetDialog.startMustBeFloat")); //$NON-NLS-1$
+		startTimeText.setText(timeFormat.format(startTime));
+		
+		// add the listeners
+		startTimeText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				startTime = convert(startTimeText, startTime);
+				startTimeText.setText(timeFormat.format(startTime));
+			}
+		});
+		startTimeText.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				startTime = convert(startTimeText, startTime);
+				startTimeText.setText(timeFormat.format(startTime));
+			}
+		});
+		startTimeText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent arg0) {
+				startTime = convert(startTimeText, startTime);
+				checkOk();
+			}
+		});
+		
+		// create the start time label and input box
+		label = new Label(shell, SWT.LEFT);
+		label.setText(Messages.getString("TimeSetDialog.endTime")); //$NON-NLS-1$
+		label.setFont(PIPageEditor.helvetica_9);
+
+		endTimeText = new Text(shell, SWT.BORDER);
+		gridData = new GridData(GridData.FILL_HORIZONTAL);
+		endTimeText.setLayoutData(gridData);
+		endTimeText.setData(Messages.getString("TimeSetDialog.endMustBeFloat")); //$NON-NLS-1$
+		endTimeText.setFont(PIPageEditor.helvetica_9);
+		endTimeText.setText(timeFormat.format(endTime));
+		
+		// add the listeners
+		endTimeText.addFocusListener(new FocusAdapter() {
+			public void focusLost(FocusEvent e) {
+				endTime = convert(endTimeText, endTime);
+				endTimeText.setText(timeFormat.format(endTime));
+			}
+		});
+		endTimeText.addSelectionListener(new SelectionAdapter() {
+			public void widgetDefaultSelected(SelectionEvent e) {
+				endTime = convert(endTimeText, endTime);
+				endTimeText.setText(timeFormat.format(endTime));
+			}
+		});
+		endTimeText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent arg0) {
+				endTime = convert(endTimeText, endTime);
+				checkOk();
+			}
+		});
+
+		label = new Label(shell, SWT.LEFT);
+		gridData = new GridData(GridData.FILL_BOTH);
+		gridData.horizontalSpan = 2;
+		gridData.verticalAlignment = GridData.CENTER;
+		label.setLayoutData(gridData);
+
+		double maxEndTime = PIPageEditor.currentPageEditor().getMaxEndTime(); 
+		labelMsg = new Label(shell, SWT.LEFT);
+		gridData = new GridData(GridData.FILL_BOTH);
+		gridData.horizontalSpan = 2;
+		gridData.verticalAlignment = GridData.CENTER;
+		labelMsg.setLayoutData(gridData);
+		labelMsg.setFont(PIPageEditor.helvetica_9);
+		labelMsg.setText(Messages.getString("TimeSetDialog.maxEndTime1") + maxEndTime + Messages.getString("TimeSetDialog.maxEndTime2")); //$NON-NLS-1$ //$NON-NLS-2$
+		
+		// create the OK button
+		ok = new Button(shell, SWT.NONE);
+		ok.setText(Messages.getString("TimeSetDialog.ok")); //$NON-NLS-1$
+		gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
+		ok.setLayoutData(gridData);
+		ok.addSelectionListener(new SelectionListener(){
+
+			public void widgetSelected(SelectionEvent e) {
+				PIPageEditor.currentPageEditor().setLocalTime(startTime, endTime);
+				PIChangeEvent.action("changeSelection"); //$NON-NLS-1$
+				
+				// after the graphs have been updated, notify plugins that might have tables but no graphs
+        		Enumeration enu = PluginInitialiser.getPluginInstances(
+        									"com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+        		if (enu != null) {
+        			Event event = new Event();
+        			event.start = (int) (startTime * 1000);
+        			event.end   = (int) (endTime   * 1000);
+        			
+            		while (enu.hasMoreElements())
+            		{
+            			IEventListener plugin = (IEventListener)enu.nextElement();
+            			plugin.receiveEvent("changeSelection", event); //$NON-NLS-1$
+            		}
+        		}
+
+				shell.close();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+		});
+		
+		// create the Cancel button
+		cancel = new Button(shell, SWT.NONE);
+		cancel.setText(Messages.getString("TimeSetDialog.cancel")); //$NON-NLS-1$
+		gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
+		cancel.setLayoutData(gridData);
+		cancel.addSelectionListener(new SelectionListener(){
+
+			public void widgetSelected(SelectionEvent e) {
+				shell.close();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				widgetSelected(e);
+			}
+		});
+		
+		shell.pack();
+		shell.open();
+		
+		while (!shell.isDisposed()) {
+			if (!shell.getDisplay().readAndDispatch()) {
+				shell.getDisplay().sleep();
+			}
+		}
+	}
+
+	private void checkOk() {
+		double maxEndTime = PIPageEditor.currentPageEditor().getMaxEndTime(); 
+		boolean isOk = false;
+		
+		if (startTime > endTime) {
+			labelMsg.setText(Messages.getString("TimeSetDialog.endTimeMustBeGreater")); //$NON-NLS-1$
+			labelMsg.setForeground(shell.getDisplay().getSystemColor(SWT.COLOR_RED));
+		} else if (!isValidPositive(startTimeText) || !isValidPositive(endTimeText)) {
+			labelMsg.setText(Messages.getString("TimeSetDialog.timesMustBePositiveValues")); //$NON-NLS-1$
+			labelMsg.setForeground(shell.getDisplay().getSystemColor(SWT.COLOR_RED));
+		} else if (startTime > maxEndTime || endTime > maxEndTime) {
+			labelMsg.setText(Messages.getString("TimeSetDialog.maxEndTime1") + maxEndTime + Messages.getString("TimeSetDialog.maxEndTime2")); //$NON-NLS-1$ //$NON-NLS-2$
+			labelMsg.setForeground(shell.getDisplay().getSystemColor(SWT.COLOR_RED));
+		} else {
+			isOk = true;
+			labelMsg.setText(Messages.getString("TimeSetDialog.maxEndTime1") + maxEndTime + Messages.getString("TimeSetDialog.maxEndTime2")); //$NON-NLS-1$ //$NON-NLS-2$
+			labelMsg.setForeground(shell.getDisplay().getSystemColor(SWT.COLOR_BLACK));
+		}
+		ok.setEnabled(isOk);
+	}
+	
+	private double convert(Text text, double currentTime)
+	{
+		double new_double;
+		
+		// convert, catch (NumberFormatException e1)
+		try {
+			new_double = Double.parseDouble(text.getText().replace(',','.'));
+			if (new_double == -0.0)
+				currentTime = 0.0f;
+			else if (new_double >= 0)
+				currentTime = new_double;
+		} catch (NumberFormatException exc) {
+			// just keep the old value
+		}
+		
+		return currentTime;
+	}
+	
+	private boolean isValidPositive(Text text) {
+		try {
+			return Double.parseDouble(text.getText().replace(',','.')) >= 0;
+		} catch (NumberFormatException exc) {
+			return false;
+		}
+	}
+	
+	public void dispose()
+	{
+		if (this.shell != null) {
+			if (!this.shell.isDisposed()) {
+				this.shell.close();				
+			}
+			this.shell.dispose();
+		}
+		
+		this.shell = null;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/TooltipsDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.pi.core.SessionPreferences;
+
+public class TooltipsDelegate implements IWorkbenchWindowActionDelegate {
+
+	private boolean toolTipsEnabled  = true;
+
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+		toolTipsEnabled = SessionPreferences.getInstance().getToolTipsEnabled();
+	}
+
+	public void run(IAction action) {
+		toolTipsEnabled = !toolTipsEnabled;
+		SessionPreferences.getInstance().setToolTipsEnabled(toolTipsEnabled);
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ViewDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class ViewDelegate implements IWorkbenchWindowActionDelegate {
+
+	private IWorkbenchWindow window;
+	
+	public void dispose() {
+		window = null;
+	}
+
+	public void init(IWorkbenchWindow window) {
+		this.window = window;
+	}
+
+	public void run(IAction action) {
+		// get the active page
+		if (window == null)
+			return;
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ZoomInDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
+
+
+public class ZoomInDelegate implements IWorkbenchWindowActionDelegate {
+
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+	}
+
+	public void run(IAction action) {
+		PIChangeEvent.action("-"); //$NON-NLS-1$
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ZoomOutDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
+
+
+public class ZoomOutDelegate implements IWorkbenchWindowActionDelegate {
+
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+	}
+
+	public void run(IAction action) {
+		PIChangeEvent.action("+"); //$NON-NLS-1$
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ZoomToSelectionDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
+
+
+public class ZoomToSelectionDelegate implements IWorkbenchWindowActionDelegate {
+
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+	}
+
+	public void run(IAction action) {
+		PIChangeEvent.action("--"); //$NON-NLS-1$
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/ZoomToTraceDelegate.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
+
+
+public class ZoomToTraceDelegate implements IWorkbenchWindowActionDelegate {
+	
+	public void dispose() {
+	}
+
+	public void init(IWorkbenchWindow window) {
+	}
+
+	public void run(IAction action) {
+		PIChangeEvent.action("++"); //$NON-NLS-1$
+	}
+
+	public void selectionChanged(IAction action, ISelection selection) {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/actions/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+SetThresholdsDialog.decimalFormat=\#\#0.00
+SetThresholdsDialog.thresholdTitle=Set Thread, Binary, or Function Thresholds
+SetThresholdsDialog.threadThreshold=Thread threshold
+SetThresholdsDialog.averageLoad=\ \ \ \ \ Average load  < 
+SetThresholdsDialog.minimumPercent=Type the minimum percentage load
+SetThresholdsDialog.totalSamples=\ %          Total samples  < 
+SetThresholdsDialog.minimumSamples=Type the minimum total samples in the graph
+SetThresholdsDialog.useThreadForAll=Use thread threshold for binaries and functions also
+SetThresholdsDialog.binaryThreshold=Binary threshold
+SetThresholdsDialog.functionThreshold=Function threshold
+SetThresholdsDialog.ok=OK
+SetThresholdsDialog.cancel=Cancel
+TimeSetDialog.decimalFormat=\#\#\#0.000
+TimeSetAction.decimalFormat=\#\#\#0.000
+TimeSetDialog.selectInterval=Select Time Interval
+TimeSetDialog.startTime=Start time (seconds):
+TimeSetAction.startTime=\ Start time (seconds): 
+TimeSetDialog.startMustBeFloat=Type a floating-point start time in seconds.
+TimeSetDialog.endTime=End time  (seconds):
+TimeSetAction.endTime=\ End time (seconds): 
+TimeSetDialog.endMustBeFloat=Type a floating-point end time in seconds
+TimeSetDialog.ok=OK
+TimeSetDialog.endTimeMustBeGreater=End time must be greater than start time.
+TimeSetDialog.timesMustBePositiveValues=Start time and end time must be positive values.
+TimeSetDialog.maxEndTime1=Start time and end time maximum is 
+TimeSetDialog.maxEndTime2=\ seconds.
+TimeSetDialog.cancel=Cancel
+EventDialog.timeFormat=\#\#0.0\#\#s
+EventDialog.event1=\ "
+EventDialog.event2=" at 
+EventDialog.event3=s
+EventDialog.eventName=Name:
+EventDialog.typeName=Type a name
+EventDialog.comment=Comment:
+EventDialog.typeComment=Type a comment
+EventDialog.time=Time:
+EventDialog.typeTime=Type a time
+EventDialog.ok=OK
+EventDialog.cancel=Cancel
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/AnalyserDataProcessor.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,854 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.analyser;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.IJobChangeListener;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.progress.IProgressService;
+
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.RefinableTrace;
+import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IVisualizable;
+import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
+import com.nokia.carbide.cpp.internal.pi.test.IProvideTraceAdditionalInfo;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.internal.pi.visual.GraphDrawRequest;
+import com.nokia.carbide.cpp.internal.pi.visual.PICompositePanel;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.importer.SampleImporter;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+import com.nokia.carbide.cpp.pi.util.PIExceptionRuntime;
+
+
+/*
+ * Class for abstracting data processing core routine for open and import
+ */
+
+public class AnalyserDataProcessor {
+	// whether the profile file was read correctly
+	public static int STATE_OK				= 0;
+	public static int STATE_IMPORTING		= 1;
+	public static int STATE_OPENING			= 2;
+	public static int STATE_TIMESTAMP		= 3;
+	public static int STATE_CANCELED		= 4;
+	public static int STATE_INVALID			= 5;
+	public static int TOTAL_PROGRESS_COUNT	= 10000;
+
+	static AnalyserDataProcessor instance = null;
+
+	// following states should be cleanup for every run
+	
+	// There should be only one progress monitor used by data processor
+	// regardless the task, and we don't want to expose public interface
+	// that juggle around progress monitor, to avoid messy situation of
+	// multiple progress indicator
+	static IProgressMonitor mp = null;
+	static Exception lastException = null;
+	private static int analyserDataProcessorState = STATE_INVALID;
+		
+	private AnalyserDataProcessor() {
+		// singleton
+	}
+	
+	public static AnalyserDataProcessor getInstance() {
+		if (instance == null) {
+			instance = new AnalyserDataProcessor();
+		}
+		return instance;
+	}
+	
+	// return whether the processed data file was successfully read
+	public int getState() {
+		return analyserDataProcessorState;
+	}
+	
+	public void setImportFailed() {
+		analyserDataProcessorState = STATE_INVALID;
+	}
+	
+	private void setProgressMonitor (IProgressMonitor progressMonitor) {
+		mp = progressMonitor;
+	}
+	
+	private IProgressMonitor getProgressMonitor() {
+		return mp;
+	}
+		
+	public Exception getLastException() {
+		return lastException;
+	}
+	
+	private void importNewAnalysis(Hashtable<Integer,String> traceFileNames, int uid) throws InterruptedException, InvocationTargetException {
+		analyserDataProcessorState = STATE_IMPORTING;
+		final int workUnitsForImport = TOTAL_PROGRESS_COUNT * 60 / 100;
+		int workUnitsLeft = workUnitsForImport * 99 / 100;
+		
+		checkCancelledThrowIE();
+			
+		// loop through all the plugins associated with traces
+		Enumeration<AbstractPiPlugin> enumer = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
+		Enumeration<AbstractPiPlugin> tmpEnum = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
+		int numberOfPlugins = 0;
+		while (tmpEnum.hasMoreElements()) {
+			numberOfPlugins++;
+			tmpEnum.nextElement();
+		}
+		while (enumer.hasMoreElements())
+    	{
+    		ITrace plugin = (ITrace)enumer.nextElement();
+    		int traceId = plugin.getTraceId();
+    		AbstractPiPlugin p = (AbstractPiPlugin)plugin;
+    		
+    		// map trace plugins to this analysis data
+    		NpiInstanceRepository.getInstance().addPlugin(uid, p);
+    		if (traceId != -1)
+    		{
+    			String fileName = traceFileNames.get(traceId);
+    			if (fileName != null)
+    			{
+    				File traceFile = new File(fileName);
+    				if (traceFile.exists()) 
+						if (traceFile.getName().endsWith(".dat"))  //$NON-NLS-1$
+							ProfileReader.getInstance().readTraceFile(plugin, traceFile, this,uid);
+    			}
+    		}
+            // assume this load takes 39%
+    		getProgressMonitor().worked((workUnitsForImport * 39 / 100) / numberOfPlugins);
+    		checkCancelledThrowIE();
+            workUnitsLeft -= (workUnitsForImport * 39 / 100) / numberOfPlugins;
+    	}
+		getProgressMonitor().worked((workUnitsForImport * 60 / 100) - workUnitsLeft);
+		checkCancelledThrowIE();
+		workUnitsLeft = (workUnitsForImport * 60 / 100);
+    	
+		// refine any traces whose addresses can be refined
+		Iterator<ParsedTraceData> traces = TraceDataRepository.getInstance().getTraceCollectionIter(uid);
+    	if (traces == null) {
+    		throw new InvocationTargetException(new PIExceptionRuntime(Messages.getString("AnalyserDataProcessor.0") + uid + Messages.getString("AnalyserDataProcessor.1")));     //$NON-NLS-1$ //$NON-NLS-2$
+    	}
+    	while (traces.hasNext())
+    	{
+    		ParsedTraceData trace = (ParsedTraceData)traces.next();
+    		// for those trace data items that can be refined
+    		if (trace.traceData instanceof RefinableTrace)
+    		{
+    			Iterator<ParsedTraceData> traces2 = TraceDataRepository.getInstance().getTraceCollectionIter(uid);
+    		
+    			while (traces2.hasNext())
+    			{
+    				ParsedTraceData trace2 = traces2.next();
+
+    				// refine with other resolvers but not with own (which has been used already)
+    				if (!trace2.equals(trace) && trace2.functionResolvers != null)
+    				{
+    					for (int i = 0; i < trace2.functionResolvers.length; i++)
+    					{
+    						FunctionResolver fr = trace2.functionResolvers[i];
+    						System.out.println(Messages.getString("AnalyserDataProcessor.2") + trace.traceData.getClass().getName() + Messages.getString("AnalyserDataProcessor.3") + fr.getResolverString());     //$NON-NLS-1$ //$NON-NLS-2$
+
+    						((RefinableTrace)trace.traceData).refineTrace(fr);
+    					}
+    				}
+    				checkCancelledThrowIE();
+    			}
+    			
+    			// after all refinement is done, do any final touches to the samples
+    			((RefinableTrace)trace.traceData).finalizeTrace();
+    		}
+    		getProgressMonitor().worked(workUnitsLeft / 2);
+    		checkCancelledThrowIE();
+    		workUnitsLeft -= workUnitsLeft / 2;
+    	}
+    	// Should move resolver out of trace, PI only need resolver in import phase, trace is more of a
+    	// core data in NPI file; before that, we would just strip all resolvers here
+    	Iterator<ParsedTraceData> tracesItr = TraceDataRepository.getInstance().getTraceCollectionIter(uid);
+    	while (tracesItr.hasNext()) {
+    		ParsedTraceData ptd = tracesItr.next();
+    		ptd.functionResolvers = null;
+    	}
+    	System.gc();
+	}
+	
+	private void loadExistingAnalysis(final Composite parent, final String analysisFilename, final String displayName, final int uid) throws InvocationTargetException, InterruptedException {
+		assertThrowITE(NpiInstanceRepository.getInstance().activeUid() == uid, Messages.getString("AnalyserDataProcessor.4"));   //$NON-NLS-1$
+		
+		// do the loading part with indicator in non-UI thread
+		final IProgressMonitor pm = getProgressMonitor();
+		pm.worked(1);
+		class LoadRunnable implements Runnable {
+			IOException myIOE = null;
+			InterruptedException myIE  =null;
+			
+			public void handleException () throws InvocationTargetException, InterruptedException {
+				if (myIOE != null) {
+					String reason = Messages.getString("AnalyserDataProcessor.12") + analysisFilename; //$NON-NLS-1$
+					if (myIOE.getMessage() != null) {
+						reason += " " + myIOE.getMessage(); //$NON-NLS-1$
+					}
+					assertThrowITE(myIOE, reason);
+				}
+				if (myIE != null) {
+					throw myIE;
+				}
+			}
+			
+			public void run() {
+				try {
+					ProfileReader.getInstance().loadAnalysisFile(analysisFilename, displayName, pm, uid);
+				} catch (IOException e) {
+					myIOE = e;
+				} catch (InterruptedException e) {
+					myIE = e;
+				}	
+			}
+		}
+		LoadRunnable loadRunnable = new LoadRunnable();
+		new Thread(loadRunnable).run();
+		loadRunnable.handleException();
+		checkCancelledThrowIE();
+		
+		processTraceDrawAndResize(parent, false);
+	}
+	
+	// called by createPage() of PIPageEditor
+	public void openNpiForPIPageEditor(final URI analysisFileURI, final Composite parent, final int uid) {
+		boolean isImport = analyserDataProcessorState == STATE_IMPORTING;
+		final String displayName = new java.io.File(analysisFileURI).getName();
+		
+		if (isImport && getProgressMonitor() != null) {
+			//import is already wrapped in runnable, and we should have progressmonitor
+			getProgressMonitor().setTaskName(Messages.getString("AnalyserDataProcessor.5") + displayName);   //$NON-NLS-1$
+			try {
+				analyserDataProcessorState = STATE_OPENING;
+				// by saying isImport true, we assume trace is set up proper in repository
+				processTraceDrawAndResize(parent, true);
+				analyserDataProcessorState = STATE_OK;
+				if (false)
+				internalOpenNPI (analysisFileURI, parent, uid);
+			} catch (InvocationTargetException e) {
+				analyserDataProcessorState = STATE_INVALID;
+				String error = Messages.getString("AnalyserDataProcessor.6") + e.getTargetException().getMessage() + Messages.getString("AnalyserDataProcessor.7");   //$NON-NLS-1$ //$NON-NLS-2$
+				if (e.getTargetException().getStackTrace() != null) {
+					StringWriter sw = new StringWriter ();
+					PrintWriter pw = new PrintWriter(sw);
+					e.getTargetException().printStackTrace(pw);
+					error += sw.toString() + "\n"; //$NON-NLS-1$
+				}
+				GeneralMessages.showErrorMessage(error);
+			} catch (InterruptedException e) {
+				String error = Messages.getString("AnalyserDataProcessor.8") + e.getMessage() + Messages.getString("AnalyserDataProcessor.9");   //$NON-NLS-1$ //$NON-NLS-2$
+				analyserDataProcessorState = STATE_CANCELED;
+			} catch (Exception e) {
+				analyserDataProcessorState = STATE_INVALID;
+				String error = Messages.getString("AnalyserDataProcessor.6") + e.getMessage() + Messages.getString("AnalyserDataProcessor.7");   //$NON-NLS-1$ //$NON-NLS-2$
+				if (e.getStackTrace() != null) {
+					StringWriter sw = new StringWriter ();
+					PrintWriter pw = new PrintWriter(sw);
+					e.printStackTrace(pw);
+					error += sw.toString() + "\n"; //$NON-NLS-1$
+				}
+				GeneralMessages.showErrorMessage(error);
+			}
+		} else {
+			setUp();
+			//open need to be wrapped in runnable, and we should set progressmonitor
+			IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
+			IRunnableWithProgress runnable= new IRunnableWithProgress() {
+
+				public void run(IProgressMonitor progressMonitor)
+				throws InvocationTargetException, InterruptedException {
+					setProgressMonitor(progressMonitor);
+					progressMonitor.beginTask(Messages.getString("AnalyserDataProcessor.10") + displayName, AnalyserDataProcessor.TOTAL_PROGRESS_COUNT * 20 / 100); //$NON-NLS-1$
+					internalOpenNPI (analysisFileURI, parent, uid);
+				}
+
+			};
+			
+			try {
+				progressService.busyCursorWhile(runnable);
+			} catch (InvocationTargetException e) {
+				analyserDataProcessorState = STATE_INVALID;
+			} catch (InterruptedException e) {
+				analyserDataProcessorState = STATE_CANCELED;
+			}
+		}
+		
+		getProgressMonitor().done();
+	}
+	
+	private void internalOpenNPI(final URI analysisFileURI, final Composite parent, final int uid) throws InvocationTargetException, InterruptedException {
+	
+		analyserDataProcessorState = STATE_OPENING;
+		
+		if (analysisFileURI == null) {
+			assertThrowITE(false, Messages.getString("AnalyserDataProcessor.11")); //$NON-NLS-1$
+			return;
+		}
+		
+		String filePath = null;
+		String displayName = null;
+		
+		filePath = analysisFileURI.getPath();
+		displayName = new java.io.File(analysisFileURI).getName();
+		
+		loadExistingAnalysis(parent, filePath, displayName, uid);
+		analyserDataProcessorState = STATE_OK;
+
+	}
+		
+	public void importSaveAndOpen(final IFile analysisFile, boolean pollTillNpiSaved) {
+		analyserDataProcessorState = STATE_IMPORTING;
+		setProgressMonitor(null);
+		
+		final int uid = NpiInstanceRepository.getInstance().register(null);
+
+		setUp();
+		IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
+		IRunnableWithProgress runnableImportAndSave = new IRunnableWithProgress() {
+
+			public void run(IProgressMonitor progressMonitor)
+					throws InvocationTargetException, InterruptedException {
+				setProgressMonitor(progressMonitor);
+				progressMonitor.beginTask(Messages.getString("AnalyserDataProcessor.17") + analysisFile.getName(), TOTAL_PROGRESS_COUNT);   //$NON-NLS-1$
+				// open a profile data file that should contain at least thread/address information
+
+				// import new .dat
+				assertThrowITE(SampleImporter.getInstance().validate(), Messages.getString("AnalyserDataProcessor.18"));	  //$NON-NLS-1$
+				
+				// invoke analysis-specific plugin instances
+				PluginInitialiser.invokePluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
+
+				StreamFileParser stp;
+				try {
+					stp = new StreamFileParser(new File(SampleImporter.getInstance().getDatFileName()));
+					Hashtable<Integer,String> traceFileNames = new Hashtable<Integer,String>();
+					ArrayList<File> tracesForCleanUp = new ArrayList<File>();
+
+					// loop through all the plugins associated with traces and note their trace IDs names
+					Enumeration<AbstractPiPlugin> enumer = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
+					while (enumer.hasMoreElements())
+					{
+						File tempFile;
+						ITrace plugin = (ITrace)enumer.nextElement();
+						int traceId = plugin.getTraceId();
+						if (traceId != -1)
+						{
+							try {
+								tempFile = stp.getTempFileForTraceType(traceId);
+								if (tempFile != null)
+								{
+									tempFile.deleteOnExit();
+									traceFileNames.put(traceId, tempFile.getAbsolutePath());
+									tracesForCleanUp.add(tempFile);
+								}
+
+							} catch (IOException e) {
+								throw new InvocationTargetException(e, Messages.getString("AnalyserDataProcessor.25")); //$NON-NLS-1$
+							}
+						}
+					}
+					
+					// import a new analysis
+					importNewAnalysis(traceFileNames, uid);
+
+					// clean up temp file for each trace
+					for (File traceFile : tracesForCleanUp) {
+						traceFile.delete();
+					}
+				} catch (IOException e) {
+					throw new InvocationTargetException(e, Messages.getString("AnalyserDataProcessor.26") + SampleImporter.getInstance().getDatFileName()); //$NON-NLS-1$
+				}
+
+				if (progressMonitor.isCanceled()) {
+					throw new InterruptedException(Messages.getString("AnalyserDataProcessor.19"));   //$NON-NLS-1$
+				}
+
+				// give the .NPI file null contents
+				byte[] b = new byte[0];
+				try {
+					analysisFile.create(new ByteArrayInputStream(b), true, null);
+					// make sure we can open an input stream to the trace file
+					analysisFile.getContents();
+				} catch (CoreException e) {
+					throw new InvocationTargetException(e, Messages.getString("AnalyserDataProcessor.14") + analysisFile.getName()); //$NON-NLS-1$
+				}
+				
+				// extract additional info from importer
+				int numberOfTraces = 0;
+				Iterator<ParsedTraceData> enuTraces = TraceDataRepository.getInstance().getTraceCollectionIter(uid);
+				AnalysisInfoHandler handler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+
+				// for all traces exist in .dat set up their additional info
+			    while (enuTraces.hasNext()) {
+			    	Object object = enuTraces.next();
+
+			    	numberOfTraces++;
+			    	
+			    	if (object instanceof ParsedTraceData) {
+			    		ParsedTraceData parsedTraceData = (ParsedTraceData) object;
+			    		if (parsedTraceData.traceData != null) {
+				    		Class traceClass = parsedTraceData.traceData.getClass();
+
+							// this code is clumsy because the plugin, not the trace, has the trace ID info
+				    		Enumeration<AbstractPiPlugin> enuPlugins = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
+							while (enuPlugins.hasMoreElements())
+							{
+								ITrace plugin = (ITrace)enuPlugins.nextElement();
+								// only do when trace exist in .data
+								if (traceClass == plugin.getTraceClass()) {
+							    	if (plugin instanceof IProvideTraceAdditionalInfo) {
+										((IProvideTraceAdditionalInfo)plugin).setupInfoHandler(handler);						    		
+							    	}
+								}
+							}			
+			    		}
+			    	}
+			    }
+				
+				// refresh so project know the update done by Java(non-Eclipse API)
+				try {
+					analysisFile.refreshLocal(0, null);
+				} catch (CoreException e) {
+					throw new InvocationTargetException(e, Messages.getString("AnalyserDataProcessor.15") + analysisFile.getName()); //$NON-NLS-1$
+				}		
+			}
+		};
+		
+		IRunnableWithProgress runnableOpen = new IRunnableWithProgress() {
+
+			public void run(IProgressMonitor arg0)
+					throws InvocationTargetException, InterruptedException {
+				// open the saved file
+				if (analysisFile.exists() && AnalyserDataProcessor.getInstance().getState() == STATE_IMPORTING ) {
+						// open the file itself
+					
+					// need to open in UI context
+					Display.getDefault().syncExec(new Runnable() {
+
+						public void run() {
+							IEditorPart editor = null;
+							try {
+								editor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() , analysisFile, true);
+							} catch (PartInitException e) {
+								try {
+									assertThrowITE(e, analysisFile.getName() + Messages.getString("AnalyserDataProcessor.24")); //$NON-NLS-1$
+								} catch (InvocationTargetException e1) {
+									//already set data structure proper, do nothing
+								}
+							}
+							if (AnalyserDataProcessor.getInstance().getState() == STATE_CANCELED) {
+								// close the editor file view
+								editor.getSite().getPage().closeEditor(editor, false);
+							} else if (AnalyserDataProcessor.getInstance().getState() != STATE_OK ) {
+								// close the editor file view
+								editor.getSite().getPage().closeEditor(editor, false);
+							}							
+						}
+					});
+				}
+			}
+			
+		};
+		
+		try {
+			progressService.busyCursorWhile(runnableImportAndSave);
+		
+			final WorkspaceJob saveNpi = new WorkspaceJob (Messages.getString("AnalyserDataProcessor.savingImportedFile")) { //$NON-NLS-1$
+
+				public IStatus runInWorkspace(IProgressMonitor monitor)
+						throws CoreException {
+					try {
+						ProfileReader.getInstance().writeAnalysisFile(analysisFile.getLocation().toString(), monitor, uid);
+					} catch (InvocationTargetException e) {
+						return new Status(IStatus.ERROR, "com.nokia.carbide.cpp.pi", Messages.getString("AnalyserDataProcessor.invocationTargetException"), e); //$NON-NLS-1$ //$NON-NLS-2$
+					} catch (InterruptedException e) {
+						return new Status(IStatus.CANCEL, "com.nokia.carbide.cpp.pi", Messages.getString("AnalyserDataProcessor.interruptedException"), e); //$NON-NLS-1$ //$NON-NLS-2$
+					}
+					return new Status(IStatus.OK, "com.nokia.carbide.cpp.pi", Messages.getString("AnalyserDataProcessor.ok"), null); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				
+			};
+		
+			progressService.busyCursorWhile(runnableOpen);
+
+			saveNpi.setPriority(Job.DECORATE);
+			saveNpi.addJobChangeListener(new IJobChangeListener () {
+				
+				public void aboutToRun(IJobChangeEvent event) {
+				}
+
+				public void awake(IJobChangeEvent event) {
+				}
+
+				public void done(IJobChangeEvent event) {
+					if (saveNpi.getResult().getSeverity()  != IStatus.OK) {
+						HandleRunnableException (saveNpi.getResult().getException(), uid, analysisFile);
+					}
+				}
+
+				public void running(IJobChangeEvent event) {
+				}
+
+				public void scheduled(IJobChangeEvent event) {
+				}
+
+				public void sleeping(IJobChangeEvent event) {
+				}
+				
+			});
+			
+			saveNpi.schedule();
+			
+			if (pollTillNpiSaved) {
+				while (saveNpi.getState() != Job.NONE) {
+					// until it's done
+				}
+			}
+			
+		} catch (InvocationTargetException e) {
+			HandleRunnableException(e, uid, analysisFile);
+		} catch (InterruptedException e) {
+			HandleRunnableException(e, uid, analysisFile);
+		}							
+	}
+	
+	private void HandleRunnableException(Throwable throwable, final int uid, IFile analysisFile) {
+		NpiInstanceRepository.getInstance().unregister(uid);
+		if (throwable instanceof InvocationTargetException) {
+			String error = Messages.getString("AnalyserDataProcessor.20"); //$NON-NLS-1$
+			if (throwable.getMessage() != null) {
+				error += throwable.getMessage() + "\n"; //$NON-NLS-1$
+			}
+			error += Messages.getString("AnalyserDataProcessor.21");   //$NON-NLS-1$ //$NON-NLS-2$
+			if (((InvocationTargetException)throwable).getTargetException().getStackTrace() != null) {
+				StringWriter sw = new StringWriter ();
+				PrintWriter pw = new PrintWriter(sw);
+				((InvocationTargetException)throwable).printStackTrace(pw);
+				error += sw.toString() + "\n"; //$NON-NLS-1$
+			}
+			GeneralMessages.showErrorMessage(error);
+			analyserDataProcessorState = STATE_INVALID;
+		} else if (throwable instanceof InterruptedException) {
+			GeneralMessages.showErrorMessage(Messages.getString("AnalyserDataProcessor.22"));  //$NON-NLS-1$
+			analyserDataProcessorState = STATE_CANCELED;
+		} else {
+			String error = Messages.getString("AnalyserDataProcessor.20"); //$NON-NLS-1$
+			if (throwable.getStackTrace() != null) {
+				StringWriter sw = new StringWriter ();
+				PrintWriter pw = new PrintWriter(sw);
+				((InvocationTargetException)throwable).printStackTrace(pw);
+				error += sw.toString() + "\n"; //$NON-NLS-1$
+			}
+			GeneralMessages.showErrorMessage(error);
+			analyserDataProcessorState = STATE_INVALID;		
+		}
+		// don't leave any garbage behind if we failed or bailed
+		if (analysisFile != null && AnalyserDataProcessor.getInstance().getState() != STATE_OK ) {
+			java.io.File javaFile = new java.io.File(analysisFile.getLocation().toString());
+			boolean deleted = javaFile.delete();
+				
+			if (deleted == false){
+				try {
+					analysisFile.delete(true, null);
+				} catch (CoreException ce) {
+					ce.printStackTrace();
+				}
+			}
+
+			try {
+				// force Eclipse to be aware of the removed file by doing an IFile refresh
+				analysisFile.refreshLocal(0, null);
+			} catch (CoreException ce) {
+				ce.printStackTrace();
+			}
+		}	
+	}
+	
+	// standalone for save as
+	public void saveAnalysis(final String filename, final int uid) throws InvocationTargetException, InterruptedException {
+		IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
+		IRunnableWithProgress runnable= new IRunnableWithProgress() {
+
+			public void run(IProgressMonitor progressMonitor)
+					throws InvocationTargetException, InterruptedException {
+				saveAnalysisInternal(filename, uid);
+			}
+			
+		};
+		try {
+			progressService.busyCursorWhile(runnable);
+		} catch (InvocationTargetException e) {
+			analyserDataProcessorState = STATE_INVALID;
+		} catch (InterruptedException e) {
+			analyserDataProcessorState = STATE_CANCELED;
+		}
+	}
+
+	// save profiling data to NPI file
+	private void saveAnalysisInternal(final String filename, final int uid) throws InvocationTargetException, InterruptedException {
+		ProfileReader.getInstance().writeAnalysisFile(filename, getProgressMonitor(), uid);
+	}
+	
+	private void processVisualizableItem(ITrace plugin)
+	{
+		IVisualizable visualizable = (IVisualizable)plugin;
+		
+		if (!visualizable.arePagesCreated())
+		{
+			// create any editor pages
+			for (int i = 0; i < visualizable.getCreatePageCount(); i++)
+			{
+				int index = visualizable.getCreatePageIndex(i);
+				ArrayList<ProfileVisualiser> pages = NpiInstanceRepository.getInstance().activeUidGetProfilePages();
+				if (pages != null) {
+					// if we don't care what the page index is, or the index is too big, add it to the end
+					if ((index == PIPageEditor.NEXT_AVAILABLE_PAGE) || (index > pages.size())) {
+						index = pages.size();
+						
+						// let the plugin know what index we assigned
+						visualizable.setPageIndex(i, index);
+					}
+					
+					ProfileVisualiser pV = visualizable.createPage(index);
+					
+					// add the page to the editor
+					if (pV != null)
+						pages.add(index, pV);					
+				}
+			}
+		}
+		
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+		
+		// determine how many graphs to draw (several may get added to the same page)
+		for (int i = 0; i < visualizable.getGraphCount(); i++)
+		{
+			GraphDrawRequest gdr   = visualizable.getDrawRequest(i);
+			GenericTraceGraph gtg  = visualizable.getTraceGraph(i);
+			String title           = visualizable.getGraphTitle(i);
+			int	pageNumber         = visualizable.getPageNumber(i);
+			
+			ProfileVisualiser page = NpiInstanceRepository.getInstance().getProfilePage(uid, pageNumber);
+
+			if (gtg != null)
+			{
+				page.getTopComposite().addGraphComponent(gtg, title, visualizable.getClass(), gdr);
+			}
+
+			Integer lastSample = visualizable.getLastSample(i);
+			if (lastSample != null)
+			{
+				page.setLastSampleX(lastSample.intValue());
+			}
+		}
+	}
+	
+	private void processTraceDrawAndResize(final Composite parent, boolean isImport) {
+		// if it is import, everything is already read in place, otherwise
+		// setup those from object file read
+		if (!isImport) {
+			ProfileReader.getInstance().processDataReadFromNpiFile(this);
+		}
+		
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+		
+		// initialize trace and do visual
+		ArrayList<AbstractPiPlugin> plugins = NpiInstanceRepository.getInstance().getPlugins(uid);
+		for (final AbstractPiPlugin plugin : plugins) {
+			if (plugin instanceof ITrace) {
+				final ParsedTraceData parsedData = TraceDataRepository.getInstance().getTrace(uid, ((ITrace)plugin).getTraceClass());
+				if (parsedData != null) {
+					final ITrace pluginTrace = (ITrace)plugin;
+					pluginTrace.initialiseTrace(parsedData.traceData);
+	    			// do the graphic painting with indicator, SWT require it to be in UI thread
+					if (plugin instanceof IVisualizable) {
+						Display.getDefault().syncExec( new Runnable() {
+							public void run() {
+								processVisualizableItem(pluginTrace);
+							}
+		    			});	
+					}
+				}
+			}
+		}
+		
+		if (!isImport) {
+			ProfileReader.getInstance().setAddtionalDataForRecordable();
+		}
+		
+		ProfileReader.getInstance().setTraceMenus(NpiInstanceRepository.getInstance().getPlugins(uid), uid);
+		// do the graphic painting with indicator, SWT require it to be in UI thread
+		Display.getDefault().syncExec( new Runnable() {
+			public void run() {
+				parent.addPaintListener( new PaintListener () {
+		  			
+					public void paintControl(PaintEvent arg0) {
+
+						if(parent.getBounds().width > 0) {
+							ArrayList<ProfileVisualiser> pages = NpiInstanceRepository.getInstance().activeUidGetProfilePages();
+							
+							// make sure we are called after the pages have been created?
+							if (pages.size() > 0) {
+								for (final ProfileVisualiser page : pages) {
+									// NOTE: This assumes that the first profile page has a graph
+						        	final PICompositePanel visibleComposite = page.getTopComposite();
+						        	visibleComposite.performZoomToGraph(visibleComposite, parent.getBounds().width);
+						        	
+						        	//TODO uncomment when performance issues relating to gfc are solved
+						        	//Select whole graph
+						        	//visibleComposite.selectWholeGraph();
+								}
+			
+								// scale to whole trace only once
+					        	parent.removePaintListener(this);
+							}
+						}
+					}
+		  		});
+			}
+		});
+	}
+	
+	// This is for test automation, removing time stamps, so we can diff .npi
+	public void importForStrippingTimeStamp(final Composite parent) {
+		if (SampleImporter.getInstance().isStrippingTimeStamp()) {
+			// had to do this monkey business for pi validation because
+			// serialization is an untestable format
+			// read file
+			final SampleImporter sampleImporter = SampleImporter.getInstance();
+
+			IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
+			IRunnableWithProgress runnable= new IRunnableWithProgress() {
+
+				public void run(IProgressMonitor progressMonitor)
+						throws InvocationTargetException,
+						InterruptedException {
+					setProgressMonitor(progressMonitor);
+					progressMonitor.beginTask(Messages.getString("AnalyserDataProcessor.23"), 100);   //$NON-NLS-1$
+					try {
+						int uid = NpiInstanceRepository.getInstance().activeUid();
+						loadExistingAnalysis(parent, sampleImporter.getDatFileName(), sampleImporter.getDatFileName(), uid);
+						// time stample differs for every save, take it out
+						AnalysisInfoHandler infoHandler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+						if (infoHandler != null) {
+							infoHandler.eraseTimeStamp();
+						}
+						// write file
+						saveAnalysisInternal(sampleImporter.getPiFileName(), uid);
+					} catch (Exception e) {
+						e.printStackTrace();
+					}
+				}
+			};
+			try {
+				progressService.busyCursorWhile(runnable);
+			} catch (InvocationTargetException e) {
+				analyserDataProcessorState = STATE_INVALID;
+				e.printStackTrace();
+			} catch (InterruptedException e) {
+				analyserDataProcessorState = STATE_CANCELED;
+				e.printStackTrace();
+			}
+			setProgressMonitor(null);
+		}
+	}
+	
+	// catch all for any exception, so we can print an error stack trace page later
+	private void assertThrowITE(boolean cond, String message) throws InvocationTargetException {
+		if (!cond) {
+			PIExceptionRuntime pire = new PIExceptionRuntime(message);	//$NON-NLS-1$
+			InvocationTargetException ite = new InvocationTargetException(pire);
+			lastException = ite;
+			analyserDataProcessorState = STATE_INVALID;
+			if (getProgressMonitor() != null) {
+				getProgressMonitor().done();
+			}
+			GeneralMessages.showErrorMessage(message);
+			throw ite;
+		}
+	}
+	
+	private void assertThrowITE(Exception e, String message) throws InvocationTargetException {
+		InvocationTargetException ite;
+		if (message != null) {
+			ite = new InvocationTargetException(e, message);
+		} else {
+			ite = new InvocationTargetException(e);
+		}
+		lastException = ite;
+		analyserDataProcessorState = STATE_INVALID;
+		if (getProgressMonitor() != null) {
+			getProgressMonitor().done();
+		}
+		GeneralMessages.showErrorMessage(message);
+		throw ite;
+
+	}
+
+	
+	// General handling for Cancel operation
+	public void checkCancelledThrowIE() throws InterruptedException {
+		if (getProgressMonitor() != null && getProgressMonitor().isCanceled()) {
+			InterruptedException ie = new InterruptedException();
+			analyserDataProcessorState = STATE_CANCELED;
+			throw ie;
+		}
+	}
+	
+	private void setUp() {
+		if (getProgressMonitor() != null) {
+			getProgressMonitor().done();
+			setProgressMonitor(null);
+		}
+		lastException = null;
+		analyserDataProcessorState = STATE_OK;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/AnalyserException.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.analyser;
+
+public abstract class AnalyserException extends Exception {
+	public AnalyserException() {}
+	public AnalyserException(String msg)
+	{
+		super(msg);
+	}
+}
+
+class SymbolFileException extends AnalyserException {
+	private static final long serialVersionUID = 8733886871246504119L;
+	public SymbolFileException() {}
+		public SymbolFileException(String msg) {
+			super(msg);
+		}
+	}
+
+class DatFileException extends AnalyserException {
+	private static final long serialVersionUID = -437564833942616104L;
+	public DatFileException() {}
+		public DatFileException(String msg) {
+			super(msg);
+		}
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/CancelException.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.analyser;
+
+class CancelException extends AnalyserException {
+	private static final long serialVersionUID = -2812034378863055838L;
+	public CancelException() {}
+		public CancelException(String msg) {
+			super(msg);
+		}
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/EventHandler.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.analyser;
+
+import java.util.Enumeration;
+
+import org.eclipse.swt.widgets.Event;
+
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+
+
+
+public class EventHandler
+{
+	private static EventHandler instance = null;
+	
+	private EventHandler ()
+	{}
+	
+	public static EventHandler getInstance()
+	{
+		if (instance == null)
+		{
+			instance = new EventHandler();
+		}
+		return instance;
+	}
+	
+	public void broadcastEvent(String eventString, Event event)
+	{
+		Enumeration e = PluginInitialiser.getPluginInstances(NpiInstanceRepository.getInstance().activeUid(), "com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+		if (e == null) return;
+		while (e.hasMoreElements())
+		{
+			IEventListener plugin = (IEventListener)e.nextElement();
+			plugin.receiveEvent(eventString, event);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.analyser;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.analyser.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/NpiInstanceRepository.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.analyser;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.widgets.Composite;
+
+import com.nokia.carbide.cpp.internal.pi.manager.PluginRegisterer;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+/*
+ * Try to encapsulate data related to each opened NPI file (e.g. AnalysTab and NPI related data) 
+ * in one centralized location, instead of tossing around classes within UI/processing code
+ */
+
+public class NpiInstanceRepository {
+	
+	static public final int DISPOSED_UID = -1;
+	
+	private class UidObject {
+		// this is just for generating UID
+	};
+	
+	static private NpiInstanceRepository instance;
+	
+	// the UID of current UI
+	private static int activeInstance;
+	
+	// all these maps are maintained by UID of instances
+	private static HashMap<Integer, UidObject> uidObjectMap = new HashMap<Integer, UidObject>();
+	private static HashMap<Integer, HashMap<String,GenericTrace>> traceCollectionMap = new HashMap<Integer, HashMap<String,GenericTrace>>();
+	private static HashMap<Integer, HashMap<String,Object>> persistCollectionMap = new HashMap<Integer, HashMap<String,Object>>();
+	private static HashMap<Integer, ArrayList<AbstractPiPlugin>> pluginListMap = new HashMap<Integer, ArrayList<AbstractPiPlugin>>();
+	private static HashMap<Integer, ArrayList<ProfileVisualiser>> profilePagesMap = new  HashMap<Integer, ArrayList<ProfileVisualiser>>();
+	private static HashMap<Integer, Composite> parentCompositeMap = new HashMap<Integer, Composite>();
+	private static HashMap<Integer, AnalysisInfoHandler> analysisInfoHandlerMap = new HashMap<Integer, AnalysisInfoHandler>();
+
+	private NpiInstanceRepository() {
+		// singleton
+	}
+
+	public static NpiInstanceRepository getInstance() {
+		if (instance == null) {
+			instance = new NpiInstanceRepository();
+		}
+		
+		return instance;
+	}
+	
+	public int register(Composite composite) {
+		UidObject uidObject = new UidObject();
+		Integer uid = new Integer(uidObject.hashCode());
+		uidObjectMap.put(uid, uidObject);
+		HashMap<String,GenericTrace> traceCollection = new HashMap<String,GenericTrace>();
+		traceCollectionMap.put(uid, traceCollection);
+		HashMap<String,Object> persistCollection = new HashMap<String,Object>();
+		persistCollectionMap.put(uid, persistCollection);
+		ArrayList<AbstractPiPlugin> pluginList = new ArrayList<AbstractPiPlugin>();
+		pluginListMap.put(uid, pluginList);
+		ArrayList<ProfileVisualiser> profilePages = new ArrayList<ProfileVisualiser>();
+		profilePagesMap.put(uid, profilePages);
+		parentCompositeMap.put(uid, composite);
+		AnalysisInfoHandler analysisInfoHandler = new AnalysisInfoHandler();
+		analysisInfoHandlerMap.put(uid, analysisInfoHandler);
+		TraceDataRepository.getInstance().registerTraces(uid.intValue());
+		PluginRegisterer.registerAllPlugins();
+		switchActiveUid(uid);
+		return uid;	
+	}
+	
+	public void unregister(int instanceUid) {
+		Integer uidInteger = new Integer(instanceUid);
+		uidObjectMap.remove(uidInteger);
+		HashMap<String,GenericTrace> traceCollection = traceCollectionMap.get(uidInteger);
+		traceCollection.clear();
+		traceCollectionMap.remove(uidInteger);
+		HashMap<String,Object> persistCollection =  persistCollectionMap.get(uidInteger);
+		persistCollection.clear();
+		persistCollectionMap.remove(uidInteger);
+		ArrayList<AbstractPiPlugin> pluginList =  pluginListMap.get(uidInteger);
+		pluginList.clear();
+		pluginListMap.remove(uidInteger);
+		ArrayList<ProfileVisualiser> profilePages = profilePagesMap.get(uidInteger);
+		profilePages.clear();
+		profilePagesMap.remove(uidInteger);
+		parentCompositeMap.remove(uidInteger);
+		analysisInfoHandlerMap.remove(uidInteger);
+		TraceDataRepository.getInstance().removeTraces(instanceUid);
+		// In general it's a good idea to keep memory footprint low
+		System.runFinalization();
+		System.gc();
+	}
+	
+	public int size() {
+		return uidObjectMap.size();
+	}
+	
+	public void setParentComposite(int instanceUid, Composite parent) {
+		parentCompositeMap.remove(instanceUid);
+		parentCompositeMap.put(instanceUid, parent);
+	}
+	
+	public void activeUidAddTrace(String className, GenericTrace trace) {
+		int instanceUid = activeUid();
+		instance.addTrace(instanceUid, className, trace);
+	}
+
+	private void addTrace(int instanceUid, String className, GenericTrace trace) {
+		HashMap<String,GenericTrace> newEntry = traceCollectionMap.get(instanceUid);
+		newEntry.put(className + ".trace", trace); //$NON-NLS-1$
+		traceCollectionMap.put(instanceUid, newEntry);
+	}
+
+	public GenericTrace activeUidGetTrace(String className) {
+		int instanceUid = activeUid();
+		return getTrace(instanceUid, className);
+	}
+	
+	private GenericTrace getTrace(int instanceUid, String className) {
+		HashMap<String,GenericTrace> entry = traceCollectionMap.get(instanceUid);
+		assertLog(entry != null, Messages.getString("NpiInstanceRepository.0") + instanceUid); //$NON-NLS-1$
+		if (entry == null) {
+			entry = new HashMap<String,GenericTrace>();
+		}
+		return entry.get(className + ".trace"); //$NON-NLS-1$
+	}
+
+	
+	public void activeUidRemoveTrace(String className) {
+		int instanceUid = activeUid();
+		removeTrace(instanceUid, className);
+	}
+	
+	private void removeTrace(int instanceUid, String className) {
+		HashMap<String,GenericTrace> entry = traceCollectionMap.get(instanceUid);
+		// if we don't have any opened NPI, the active one == disposed and trace will be
+		// harmlessly removed one more time upon exit
+		if (instanceUid != DISPOSED_UID) {
+			assertLog(entry != null, Messages.getString("NpiInstanceRepository.1") + instanceUid); //$NON-NLS-1$
+		}
+		if (entry == null) {
+			return;
+		}
+		entry.remove(className);
+	}
+	
+	public void switchActiveUid(int instanceUid) {
+		activeInstance = instanceUid;
+	}
+	
+	public int activeUid() {
+		return activeInstance;
+	}
+	
+	// return array list of this tab's plugins
+	public ArrayList<AbstractPiPlugin> getPlugins(int instanceUid)	{
+		ArrayList<AbstractPiPlugin> pluginList = pluginListMap.get(instanceUid);
+		assertLog(pluginList != null, Messages.getString("NpiInstanceRepository.2") + instanceUid); //$NON-NLS-1$
+		if (pluginList == null) {
+			pluginList = new ArrayList<AbstractPiPlugin>();
+		}
+		return pluginList;
+	}
+	
+	// add the plugin to this tab's list
+	public void addPlugin(int instanceUid, AbstractPiPlugin plugin) {
+		ArrayList<AbstractPiPlugin> pluginList = pluginListMap.get(instanceUid);
+		assertLog(pluginList != null, Messages.getString("NpiInstanceRepository.3") + instanceUid); //$NON-NLS-1$
+		if (pluginList != null && !pluginList.contains(plugin))
+			pluginList.add(plugin);
+	}
+	
+	// return array list of this tab's pages
+	public ArrayList<ProfileVisualiser> activeUidGetProfilePages() {
+		int instanceUid = activeUid();
+		return getProfilePages(instanceUid);
+	}
+	
+	// return array list of this tab's pages
+	private ArrayList<ProfileVisualiser> getProfilePages(int instanceUid) {
+		ArrayList<ProfileVisualiser> pages = profilePagesMap.get(instanceUid);
+		assertLog(pages != null, Messages.getString("NpiInstanceRepository.4") + instanceUid); //$NON-NLS-1$
+		if (pages == null) {
+			pages = new ArrayList<ProfileVisualiser>();
+		}
+		return pages;
+	}
+	
+	// return a particular page
+	public ProfileVisualiser getProfilePage(int instanceUid, int index) {
+		ArrayList<ProfileVisualiser> pages  = profilePagesMap.get(instanceUid);
+		
+		assertLog(pages != null, Messages.getString("NpiInstanceRepository.5") + instanceUid); //$NON-NLS-1$
+		if (pages == null) {
+			pages = new ArrayList<ProfileVisualiser>();
+		}
+		
+		ProfileVisualiser visualizer;
+		
+		try {
+			visualizer = pages.get(index);
+		} catch (IndexOutOfBoundsException e) {
+			return null;
+		} catch (Exception e) {
+			return null;
+		}
+		
+		return visualizer;
+	}
+
+	public Composite activeUidGetParentComposite() {
+		int instanceUid = activeUid();
+		Composite parent = parentCompositeMap.get(instanceUid);
+		return parent;
+	}
+	
+	public AnalysisInfoHandler activeUidGetAnalysisInfoHandler() {
+		int instanceUid = activeUid();
+	    return getAnalysisInfoHandler(instanceUid);
+	}
+
+	public AnalysisInfoHandler getAnalysisInfoHandler(int instanceUid) {
+		return analysisInfoHandlerMap.get(instanceUid);
+	}
+	
+	public void activeUidSetPersistState (String key, Object state) {
+		int instanceUid = activeUid();
+		setPersistState(instanceUid, key, state);
+	}
+	
+	public void setPersistState (int instanceUid, String key, Object state) {
+		HashMap<String, Object> entry = persistCollectionMap.get(instanceUid);
+		entry.put(key, state);
+	}
+	
+	private Object getPersistDefault (String key) {
+		if (key.equals("com.nokia.carbide.cpp.pi.address.thresholdCountThread") || //$NON-NLS-1$
+				key.equals("com.nokia.carbide.cpp.pi.address.thresholdCountBinary") || //$NON-NLS-1$
+				key.equals("com.nokia.carbide.cpp.pi.address.thresholdCountFunction") ) { //$NON-NLS-1$
+			return new Integer(-1);
+		}
+		if (key.equals("com.nokia.carbide.cpp.pi.address.thresholdLoadThread") || //$NON-NLS-1$
+				key.equals("com.nokia.carbide.cpp.pi.address.thresholdLoadBinary")) { //$NON-NLS-1$
+			return new Double(0.001);
+		}
+		if (key.equals("com.nokia.carbide.cpp.pi.address.thresholdLoadFunction")) { //$NON-NLS-1$
+			return new Double(0.0001);
+		}
+		if (key.equals("com.nokia.carbide.cpp.pi.address.useOnlyThreadThresholds")) {	//$NON-NLS-1$
+			return new Boolean(false);
+		}
+		return null;
+	}
+	
+	public Object activeUidGetPersistState (String key) {
+		int instanceUid = activeUid();
+		return getPersistState(instanceUid, key);
+	}
+	
+	public Object getPersistState (int instanceUid, String key) {
+		HashMap<String, Object> entry = persistCollectionMap.get(instanceUid);
+		Object object = entry.get(key);
+		if (object != null) {
+			return object;
+		}
+		return getPersistDefault(key);
+	}
+	
+	private void assertLog(boolean cond, String message) {
+		if (!cond) {
+			GeneralMessages.PiLog(message, IStatus.ERROR);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/PIChangeEvent.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.analyser;
+
+import java.util.ArrayList;
+
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+public class PIChangeEvent {
+
+	private PIChangeEvent() {
+		/* this class can only have static method */
+	}
+	
+	public static void action(String actionString) {
+		processEvent(actionString);
+	}
+	
+	public static void processEvent(String actionString) {
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+		if (   actionString.equals("+") //$NON-NLS-1$
+			 || actionString.equals("-") //$NON-NLS-1$
+			 || actionString.equals("++") //$NON-NLS-1$
+			 || actionString.equals("--")) //$NON-NLS-1$
+		{
+			ArrayList<ProfileVisualiser> list = NpiInstanceRepository.getInstance().activeUidGetProfilePages();
+			
+			// for zoom to selected time interval, there must be a selected time interval
+			if (   actionString.equals("--") //$NON-NLS-1$
+				&& !NpiInstanceRepository.getInstance().getProfilePage(uid, 0).getTopComposite().validInterval()) {
+				// let the first page supply the error message
+				NpiInstanceRepository.getInstance().getProfilePage(uid, 0).action(actionString);
+				return;
+			}
+			
+			for (int i = 0; i < list.size(); i++)
+				NpiInstanceRepository.getInstance().getProfilePage(uid, i).action(actionString);
+		}
+		else if (   actionString.equals("changeInterval") //$NON-NLS-1$
+				 || actionString.equals("changeSelection") //$NON-NLS-1$
+				 || actionString.equals("changeThresholdThread") //$NON-NLS-1$
+				 || actionString.equals("changeThresholdBinary") //$NON-NLS-1$
+				 || actionString.equals("changeThresholdFunction")) //$NON-NLS-1$
+		{
+			ArrayList<ProfileVisualiser> list = NpiInstanceRepository.getInstance().activeUidGetProfilePages();
+			
+			for (int i = 0; i < list.size(); i++)
+				NpiInstanceRepository.getInstance().getProfilePage(uid, i).action(actionString);
+		}
+		else
+		{
+			NpiInstanceRepository.getInstance().getProfilePage(uid, PIPageEditor.currentPageIndex()).action(actionString);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/ParserRepository.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.analyser;
+
+import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
+
+public class ParserRepository
+{
+    private AnalysisInfoHandler analysisInfoHandler;
+
+    public ParserRepository()
+    {
+        this.analysisInfoHandler = new AnalysisInfoHandler();
+    }
+
+    public AnalysisInfoHandler getPIAnalysisInfoHandler()
+    {
+        return analysisInfoHandler;
+    }
+    
+    public void setPIAnalysisInfoHandler(AnalysisInfoHandler analysisInfoHandler)
+    {
+        this.analysisInfoHandler = analysisInfoHandler;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/ProfileReader.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,926 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.analyser;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Vector;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.ILock;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.swt.widgets.Display;
+
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+import com.nokia.carbide.cpp.internal.pi.manager.PluginRegistry;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+import com.nokia.carbide.cpp.internal.pi.model.RefinableTrace;
+import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IAnalysisItem;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IExportItem;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IImportMenu;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IRecordable;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IViewMenu;
+import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
+import com.nokia.carbide.cpp.internal.pi.test.EnabledTrace;
+import com.nokia.carbide.cpp.internal.pi.test.IProvideTraceAdditionalInfo;
+import com.nokia.carbide.cpp.internal.pi.test.PIAnalyser;
+import com.nokia.carbide.cpp.internal.pi.test.PIAnalysisInfo;
+import com.nokia.carbide.cpp.internal.pi.test.BappeaAnalysisInfo;
+import com.nokia.carbide.cpp.internal.pi.test.TraceAdditionalInfo;
+import com.nokia.carbide.cpp.internal.pi.utils.PluginClassLoader;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+import com.nokia.carbide.cpp.pi.util.PIExceptionRuntime;
+
+
+/*
+ * Class for reading a processed profile data file and setting up the
+ * editor pages, initial graphs, and initial tables
+ */
+public class ProfileReader
+{
+	// objects (mainly traces) read, it's lifetime exist between loadAnalysisFile for last usage in loadAnalysisFile
+	static private ArrayList<Object> readObjects = new ArrayList<Object>();
+	static private ArrayList<Hashtable> recObjects = new ArrayList<Hashtable>();
+	static private ProfileReader instance;
+	private static ILock lock = WorkspaceJob.getJobManager().newLock();
+
+	public static ProfileReader getInstance() {
+		if (instance == null) {
+			instance = new ProfileReader();
+		}
+		
+		return instance;
+	}
+	
+	private ProfileReader()
+	{
+		//singleton
+	}
+
+	// read a plugin's information from a profile data file
+	public boolean readTraceFile(ITrace plugin, File traceFile, AnalyserDataProcessor dataInstance, int instanceUID)
+	{
+		// prepare the trace repository
+		try 
+		{
+			ParsedTraceData parsedTraceData = plugin.parseTraceFile(traceFile);
+			
+			if (parsedTraceData != null) 
+			{
+				// each resolvable trace is primarily resolved first 
+				// with its own functionresolver(s)
+				if (parsedTraceData.traceData instanceof RefinableTrace)
+				{
+					if (parsedTraceData.functionResolvers != null && parsedTraceData.functionResolvers.length > 0)
+					{
+						for (int i = 0; i < parsedTraceData.functionResolvers.length; i++)
+						{
+							FunctionResolver fr = parsedTraceData.functionResolvers[i];
+							((RefinableTrace)parsedTraceData.traceData).refineTrace(fr);
+						}
+					}
+				}
+				
+				TraceDataRepository.getInstance().insertTraceCollection(plugin.getTraceClass(), parsedTraceData, instanceUID);	
+				addToMenus(plugin);
+			}
+		} 
+		catch (Exception e) 
+		{
+			e.printStackTrace();
+			return false;
+		}
+		return true;
+	}
+	
+	public void loadAnalysisFile(String filePath, String displayName, IProgressMonitor progressMonitor, int instanceUID) throws IOException, InterruptedException
+	{
+		final int workUnitsForLoad = AnalyserDataProcessor.TOTAL_PROGRESS_COUNT * 20 / 100;
+		int workUnitsLeft = workUnitsForLoad;
+		progressMonitor.worked(1); // kick it start to please user
+		AnalyserDataProcessor.getInstance().checkCancelledThrowIE();
+		
+	    System.out.println(Messages.getString("ProfileReader.0") + displayName);  //$NON-NLS-1$
+
+	    // find and record all PI plugins that implement the specified interface
+	    PluginInitialiser.invokePluginInstances(instanceUID, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
+
+		// the file contains Java objects that have been gziped
+	    FileInputStream fis = new FileInputStream(filePath);
+		GZIPInputStream ziss = new GZIPInputStream(fis);
+		BufferedInputStream bis = new BufferedInputStream(ziss);
+
+		ObjectInputStream ois = new ObjectInputStream(bis)
+	    {   	
+	        @SuppressWarnings("unchecked") //$NON-NLS-1$
+			protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException
+	        {
+	        	// each object read must have a class corresponding to a plugin class
+	        	String name = desc.getName();
+	        	
+                Class c = PluginInitialiser.getPluginClass(name);
+	    		
+	    		if (c == null)
+	    		{
+	    			try {
+						c = Class.forName(name);
+					} catch (ClassNotFoundException e) {
+						// see if we have a replacement
+						PluginClassLoader pcl = (PluginClassLoader)PluginInitialiser.getPluginClassLoader();
+						// don't catch for class not found exception, they did it on purpose 
+						// to back out of this missing plugin that exist in data file
+						c = pcl.findClass(name);
+					}	
+	    		}
+	    		
+	       		return c;
+	        }
+	    };
+
+	    readObjects.clear();
+
+	    String notFoundMessage = ""; //$NON-NLS-1$
+	    
+		//loads all objects
+	    try
+	    {
+	        while(true)
+	        {
+            	Object ou = null;
+            	try
+            	{
+	                ou = ois.readObject();
+            	}
+	    	    catch (ClassNotFoundException cnfe)
+	    	    {
+	    		    //probably the plugin which has this class is not loaded
+    	        	ou = null;
+    	        	if (notFoundMessage.length() != 0)
+    	        		notFoundMessage += "\n";  //$NON-NLS-1$
+    	        	notFoundMessage += "Cannot find class " + cnfe.getMessage() //$NON-NLS-1$
+					+ Messages.getString("ProfileReader.1");  //$NON-NLS-1$
+	    	    }
+    	        if (ou != null)
+    	        	readObjects.add(ou);
+	            // allocate what's left to roughly all plugins loaded, even some of them may not be in profiled sample
+	            progressMonitor.worked(workUnitsLeft / PluginRegistry.getInstance().getRegistrySize());
+	            workUnitsLeft -= workUnitsLeft / PluginRegistry.getInstance().getRegistrySize();
+	            AnalyserDataProcessor.getInstance().checkCancelledThrowIE();
+	        }
+	    }
+	    catch(EOFException eof)
+	    {
+	    	if (eof.getMessage() == null)
+	        System.out.println(Messages.getString("ProfileReader.2"));  //$NON-NLS-1$
+		    	else
+		    	{
+		    		System.out.println(Messages.getString("ProfileReader.3") + eof.getMessage());  //$NON-NLS-1$
+		    		eof.printStackTrace();
+		    	}
+	    }
+	    catch (InvalidClassException ie)
+	    {
+	    	// assume that the reason you got here was a UID mismatch
+	    	
+	        // close the readers
+	        System.out.println(Messages.getString("ProfileReader.4"));  //$NON-NLS-1$
+	        ois.close();
+	        fis.close();
+	        bis.close();
+	        ziss.close();
+	        
+	        notFoundMessage = ""; //$NON-NLS-1$
+
+	        // fix the UID mismatch problem
+	        fis = new FileInputStream(filePath);
+	        
+	        ziss = new GZIPInputStream(fis);
+
+	        InputStream fixedStream = fixUIDProblem(ziss);
+
+	        bis = new BufferedInputStream(fixedStream);
+
+	        ois = new ObjectInputStream(bis)
+	        {       
+	            @SuppressWarnings("unchecked") //$NON-NLS-1$
+				protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException
+	            {
+		        	// each object read must have a class corresponding to a plugin class
+		        	String className = desc.getName();
+		        	
+		        	Class c = PluginInitialiser.getPluginClass(className);
+	                
+	                if (c == null)
+	                {
+	                    try {
+	                        c = Class.forName(className);
+	                    }
+	                    catch (ClassNotFoundException e1) {
+	                            throw e1;
+	                    }
+	                }
+	                
+	                return c;
+	            }
+	        };
+
+	        // try again to read the objects
+            readObjects.clear();
+	        try
+	        {
+	            while (true)
+	            {
+	            	Object ou = null;
+	            	try
+	            	{
+		                ou = ois.readObject();
+	            	}
+	    	        catch (ClassNotFoundException cnfe)
+	    	        {
+	    			    //probably the plugin which has this class is not loaded
+	    	        	ou = null;
+	    	        	if (notFoundMessage.length() != 0)
+	    	        		notFoundMessage += "\n";  //$NON-NLS-1$
+	    	        	notFoundMessage += Messages.getString("ProfileReader.5") + cnfe.getMessage()  //$NON-NLS-1$
+	    	        			+ Messages.getString("ProfileReader.6");  //$NON-NLS-1$
+	    	        }
+	    	        if (ou != null)
+	    	        	readObjects.add(ou);
+		            // allocate what's left to roughly all plugins loaded, even some of them may not be in profiled sample
+		            progressMonitor.worked(workUnitsLeft / PluginRegistry.getInstance().getRegistrySize());
+		            workUnitsLeft -= workUnitsLeft / PluginRegistry.getInstance().getRegistrySize();
+		            AnalyserDataProcessor.getInstance().checkCancelledThrowIE();
+	            }
+	        }   
+	        catch (EOFException eof)
+	        {
+	            System.out.println(Messages.getString("ProfileReader.7"));  //$NON-NLS-1$
+	        }
+	        catch (Exception eih)
+	        {
+	        	eih.printStackTrace();
+	        }
+	    }
+	    catch(Exception e)
+	    {
+	        e.printStackTrace();
+	    }
+	    
+	    // close the readers
+	    ois.close();
+	    fis.close();
+	    bis.close();
+	    ziss.close();
+	    
+	    progressMonitor.worked((workUnitsForLoad * 98 / 100) - workUnitsLeft);	// assume reading takes 98%
+	    AnalyserDataProcessor.getInstance().checkCancelledThrowIE();
+	    workUnitsLeft = workUnitsForLoad * 2 / 100;
+
+	    // display routine wants to see Analysis info first,
+	    // and the rest in the order of what you want it to
+	    // be displayed, GPP first, and then MEM
+		Iterator<Object> readObjectsItr = readObjects.iterator();
+		Object analysisInfoObj = null;
+		Object gppObj = null;
+		Object memObj = null;
+		while (readObjectsItr.hasNext())
+		{
+			Object objFromFile = readObjectsItr.next();
+			if (objFromFile.getClass().getName().endsWith("PIAnalysisInfo")) //$NON-NLS-1$
+			{
+				readObjectsItr.remove();
+				analysisInfoObj = objFromFile;
+			}
+			if (objFromFile.getClass().getName().endsWith("BappeaAnalysisInfo")) //$NON-NLS-1$
+			{
+				readObjectsItr.remove();
+				
+				if (analysisInfoObj == null)
+					analysisInfoObj = objFromFile;
+			}
+			if (objFromFile.getClass().getName().endsWith("GppTrace")) //$NON-NLS-1$
+			{
+				readObjectsItr.remove();
+				gppObj = objFromFile;
+			}
+			if (objFromFile.getClass().getName().endsWith("MemTrace")) //$NON-NLS-1$
+			{
+				readObjectsItr.remove();
+				memObj = objFromFile;
+			}
+		}
+		if (memObj != null)
+		{
+			readObjects.add(0, memObj);
+		}
+		if (gppObj != null)
+		{
+			readObjects.add(0, gppObj);
+		}
+		if (analysisInfoObj != null)
+		{
+			readObjects.add(0, analysisInfoObj);
+		}
+		progressMonitor.worked(workUnitsForLoad - workUnitsLeft);
+		AnalyserDataProcessor.getInstance().checkCancelledThrowIE();
+
+		// if any problems were found, print them
+	    if (notFoundMessage.length() != 0) {
+	    	GeneralMessages.showWarningMessage(notFoundMessage);
+	    }
+	}
+	  
+	// setup data from all objects in NPI file, e.g. setup trace repository
+	public void processDataReadFromNpiFile(AnalyserDataProcessor dataInstance)
+	{
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+    	AnalysisInfoHandler infoHandler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+
+		if (readObjects == null)
+			return;
+		
+		recObjects.clear();
+		
+		Object o;
+		int nextTrace = 1;
+	    
+	    if (readObjects.size() > 0) 
+	    	o = readObjects.get(0);
+	    else
+	    	o = new Object();
+
+		// the first element must identify the analysis info type
+	    String className = o.getClass().getCanonicalName();
+	    if (o instanceof PIAnalysisInfo)
+	    {
+	        try
+	        {
+	            PIAnalysisInfo info = (PIAnalysisInfo) o;
+	            infoHandler.analysisDataReader(info);
+	            System.out.println(Messages.getString("ProfileReader.8") + infoHandler.getFileVersion());  //$NON-NLS-1$
+	        }
+	        catch (Exception eu)
+	        {
+	            System.out.println(Messages.getString("ProfileReader.9"));  //$NON-NLS-1$
+	            return;
+	        }
+	    }
+	    else if (className.indexOf("BappeaAnalysisInfo") != -1) //$NON-NLS-1$
+	    {
+	        try
+	        {
+	        	// Old-style analysis info
+	            BappeaAnalysisInfo info = (BappeaAnalysisInfo) o;
+	            infoHandler.analysisDataReader(info);
+	            System.out.println(Messages.getString("ProfileReader.10") + infoHandler.getFileVersion());  //$NON-NLS-1$
+	        }
+	        catch (Exception eu)
+	        {
+	            System.out.println(Messages.getString("ProfileReader.11"));  //$NON-NLS-1$
+	            return;
+	        }
+	    }
+	    else
+	    {
+		    //analysis info was not stored in old files
+	        System.out.println(Messages.getString("ProfileReader.12"));  //$NON-NLS-1$
+            nextTrace = 0;
+            PIAnalysisInfo info = null;
+            infoHandler.analysisDataReader(info);	// try this and make updater attempts conversion
+	    }
+
+	    LinkedHashMap<Class, ParsedTraceData> traces = TraceDataRepository.getInstance().getTraceCollection(uid);
+
+		// Note: The first trace encountered MUST be the address/thread (GPP) trace
+	    while (nextTrace < readObjects.size() && o != null)
+	    {
+	    	o = readObjects.get(nextTrace++);
+	    	
+	    	if (o instanceof GenericTrace)
+	    	{
+	    		GenericTrace trace = (GenericTrace)o;
+	    		
+	    		// iterate through all PI plugins that implement the given interface
+	    		Enumeration<AbstractPiPlugin> enumeration = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace");  //$NON-NLS-1$
+		    	while (enumeration.hasMoreElements())
+		        {
+		    		final ITrace plugin = (ITrace)enumeration.nextElement();
+		    		AbstractPiPlugin p = (AbstractPiPlugin)plugin;
+		    		NpiInstanceRepository.getInstance().addPlugin(uid, p);
+
+		        	if (plugin.getTraceClass() != null && plugin.getTraceClass().isInstance(o))
+		        	{
+		        		// add this trace to the trace repository
+		        		ParsedTraceData ptd = new ParsedTraceData();
+		        		ptd.traceData = trace;
+		        		TraceDataRepository.getInstance().insertTraceCollection(plugin.getTraceClass(), ptd, uid);
+		        	}
+		        }
+	    	}
+	    	else if (o instanceof Hashtable)
+	    	{
+	    		recObjects.add((Hashtable)o);
+	    	}
+        } 
+	    
+	    // We are done with this
+	    readObjects.clear();
+	    
+		// In general it's a good idea to keep memory footprint low
+		// most plugin allocate locals with new in initialiseTrace(GenericTrace)
+		// so there should be a bunch of memory to be collected here
+		System.runFinalization();
+		System.gc();
+	}
+	
+	public void setAddtionalDataForRecordable() {
+		final int uid = NpiInstanceRepository.getInstance().activeUid();
+		// do the graphic painting with indicator, SWT require it to be in UI thread
+		Display.getDefault().syncExec( new Runnable() {
+			public void run() {
+				Enumeration<AbstractPiPlugin> enumeration = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.plugin.model.IRecordable"); //$NON-NLS-1$
+				while (enumeration.hasMoreElements())
+				{
+					IRecordable recPlugin = (IRecordable)enumeration.nextElement();
+					ITrace tracePlugin = (ITrace)recPlugin;
+					for (Hashtable table : recObjects) {
+						Object data = table.get(tracePlugin.getTraceClass());
+						if (data != null && data instanceof Serializable)
+						{
+							for (int i = 0; i < recPlugin.getGraphCount(); i++)
+								recPlugin.setAdditionalData(i, (Serializable)data);
+						}
+					}
+				}	
+			}
+		});
+		recObjects.clear();
+	}
+	  
+	private static final long UID1 = -6477250745688244253L;
+	private static final long UID1Correct = -8144591614894549185L;
+	private static final long UID2 = -7847355697200551872L;
+	private static final long UID2Correct = -8082342532211331507L;
+	private static final long UID3 = -7057416050237320718L;
+	private static final long UID3Correct = 8411844143949264073L;
+
+
+	private InputStream fixUIDProblem(InputStream inputStream) throws IOException
+	{
+		int[] UID1Array = {
+				(int) ((UID1 >>> 56) & 0xff), (int) ((UID1 >>> 48) & 0xff),
+				(int) ((UID1 >>> 40) & 0xff), (int) ((UID1 >>> 32) & 0xff),
+				(int) ((UID1 >>> 24) & 0xff), (int) ((UID1 >>> 16) & 0xff),
+				(int) ((UID1 >>>  8) & 0xff), (int)  (UID1 & 0xff)
+		};
+		int[] UID1CorrectArray = {
+				(int) ((UID1Correct >>> 56) & 0xff), (int) ((UID1Correct >>> 48) & 0xff),
+				(int) ((UID1Correct >>> 40) & 0xff), (int) ((UID1Correct >>> 32) & 0xff),
+				(int) ((UID1Correct >>> 24) & 0xff), (int) ((UID1Correct >>> 16) & 0xff),
+				(int) ((UID1Correct >>>  8) & 0xff), (int)  (UID1Correct & 0xff)
+		};
+		int[] UID2Array = {
+				(int) ((UID2 >>> 56) & 0xff), (int) ((UID2 >>> 48) & 0xff),
+				(int) ((UID2 >>> 40) & 0xff), (int) ((UID2 >>> 32) & 0xff),
+				(int) ((UID2 >>> 24) & 0xff), (int) ((UID2 >>> 16) & 0xff),
+				(int) ((UID2 >>>  8) & 0xff), (int)  (UID2 & 0xff)
+		};
+		int[] UID2CorrectArray = {
+				(int) ((UID2Correct >>> 56) & 0xff), (int) ((UID2Correct >>> 48) & 0xff),
+				(int) ((UID2Correct >>> 40) & 0xff), (int) ((UID2Correct >>> 32) & 0xff),
+				(int) ((UID2Correct >>> 24) & 0xff), (int) ((UID2Correct >>> 16) & 0xff),
+				(int) ((UID2Correct >>>  8) & 0xff), (int)  (UID2Correct & 0xff)
+		};
+		int[] UID3Array = {
+				(int) ((UID3 >>> 56) & 0xff), (int) ((UID3 >>> 48) & 0xff),
+				(int) ((UID3 >>> 40) & 0xff), (int) ((UID3 >>> 32) & 0xff),
+				(int) ((UID3 >>> 24) & 0xff), (int) ((UID3 >>> 16) & 0xff),
+				(int) ((UID3 >>>  8) & 0xff), (int)  (UID3 & 0xff)
+		};
+		int[] UID3CorrectArray = {
+				(int) ((UID3Correct >>> 56) & 0xff), (int) ((UID3Correct >>> 48) & 0xff),
+				(int) ((UID3Correct >>> 40) & 0xff), (int) ((UID3Correct >>> 32) & 0xff),
+				(int) ((UID3Correct >>> 24) & 0xff), (int) ((UID3Correct >>> 16) & 0xff),
+				(int) ((UID3Correct >>>  8) & 0xff), (int)  (UID3Correct & 0xff)
+		};
+		
+		// puukko-based solution
+		BufferedInputStream bis = new BufferedInputStream(inputStream);
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		int[] temp = new int[8];
+
+		int tempIndex = 0;
+
+		int UID1Index = 0;
+		int UID2Index = 0;
+		int UID3Index = 0;
+		
+		int data = -1;
+
+		// Now we have exactly three UID problems, which is tricky
+		// since a mismatch in one might be a match in the other
+		while (true)
+		{
+			data = bis.read();
+	        if (data == -1)
+	        	break;
+	        
+	        if (data == UID1Array[UID1Index])
+	        	UID1Index++;
+	        else
+	        	UID1Index = 0;
+	        
+	        if (data == UID2Array[UID2Index])
+	        	UID2Index++;
+	        else
+	        	UID2Index = 0;
+	        
+	        if (data == UID3Array[UID3Index])
+	        	UID3Index++;
+	        else
+	        	UID3Index = 0;
+
+        	// no matches
+        	if (UID1Index + UID2Index + UID3Index == 0)
+        	{
+        		// write the match buffer bytes & the new one, clear the buffer, and restart the matches 
+        		if (tempIndex != 0) {
+        			for (int i = 0; i < tempIndex; i++)
+        				baos.write(temp[i]);
+        			tempIndex = 0;
+        		}
+
+        		baos.write(data);
+        	} else {
+        		// store the byte
+        		temp[tempIndex++] = data;
+
+        		// if any counter is at 8, we have a match - only look for one
+        		// if the buffer is full, write any unmatched strings
+            	if (UID1Index == 8)
+            	{
+            		for (int i = 0; i < 8; i++)
+            			baos.write(UID1CorrectArray[i]);
+                    System.out.println(Messages.getString("ProfileReader.13"));  //$NON-NLS-1$
+                    
+                    UID1Index = 0;
+                    tempIndex = 0;
+                    break;
+            	}
+            	else if (UID2Index == 8)
+            	{
+            		for (int i = 0; i < 8; i++)
+            			baos.write(UID2CorrectArray[i]);
+                    System.out.println(Messages.getString("ProfileReader.14"));  //$NON-NLS-1$
+                    UID2Index = 0;
+                    tempIndex = 0;
+                    break;
+            	}
+            	else if (UID3Index == 8)
+            	{
+            		for (int i = 0; i < 8; i++)
+            			baos.write(UID3CorrectArray[i]);
+                    System.out.println(Messages.getString("ProfileReader.priorityTraceUIDconflict")); //$NON-NLS-1$
+ 
+                    UID3Index = 0;
+                    tempIndex = 0;
+                    break;
+            	} else if (tempIndex == 8) {
+            		// write all the bytes not in a match
+            		int least = UID1Index < UID2Index ? UID1Index : UID2Index;
+            		least = least < UID3Index ? least : UID3Index;
+            		
+            		for (int i = 0; i < least; i++)
+	        			baos.write(temp[i]);
+            		
+	        		// move the remaining unwritten bytes to start of the temp array
+	        		int k = 0;
+	        		for (int i = least; i < 8; i++)
+	        		{
+	        			tempIndex--;
+	        			temp[k++] = temp[i];
+	        		}
+            	}
+        	}
+		}
+		
+		// write the match buffer bytes & the new one, clear the buffer, and restart the matches 
+		if (tempIndex != 0) {
+			for (int i = 0; i < tempIndex; i++)
+				baos.write(temp[i]);
+		}
+		
+		while (data != -1) {
+			data = bis.read();
+			
+			if (data != -1)
+				baos.write(data);
+		}
+	      
+		ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+	    baos.close();
+	    bis.close();
+	    return bais;
+	}
+	
+	private void closeOutputStreams(FileOutputStream fos, GZIPOutputStream gzo, ObjectOutputStream oos) {
+		try {
+			if (oos != null) {
+				oos.flush();
+				oos.close();
+			}
+			if (gzo != null) {
+				gzo.flush();
+				gzo.close();
+			}
+			if (fos != null) {
+				fos.flush();
+				fos.close();
+			}
+		} catch (IOException e) {
+			GeneralMessages.showErrorMessage(e.getMessage());
+		}
+	}
+
+	void writeAnalysisFile(String fileName, IProgressMonitor monitor, int instanceUID) throws InvocationTargetException, InterruptedException {
+		final int workUnitsForSave = AnalyserDataProcessor.TOTAL_PROGRESS_COUNT * 20 / 100;
+		FileOutputStream fos = null;
+		GZIPOutputStream gzo = null;
+		ObjectOutputStream oos = null;
+
+		try {
+			lock.acquire();
+			File f = new File(fileName);
+		    if (f.exists())
+		    {
+		        f.delete();
+		    }
+		    fos = new FileOutputStream(f);
+		    gzo = new GZIPOutputStream(fos);
+		    oos = new ObjectOutputStream(gzo);
+
+		    monitor.setTaskName(Messages.getString("ProfileReader.15") + f.getName());  //$NON-NLS-1$
+		    monitor.worked(workUnitsForSave * 1 / 100);
+			int workUnitsLeft = workUnitsForSave;
+			monitor.worked(workUnitsForSave * 1 / 100); // kick it start to please user
+			if (monitor.isCanceled()) {
+				throw new InterruptedException();
+			}
+			
+			// even other update routine among traces are not activated, any save should be in the newest version number
+			NpiInstanceRepository.getInstance().getAnalysisInfoHandler(instanceUID).setFileVersion(PIAnalyser.NPIFileFormat);
+			AnalysisInfoHandler analysisInfoHandler = NpiInstanceRepository.getInstance().activeUidGetAnalysisInfoHandler();
+			PIAnalysisInfo info = analysisInfoHandler.getAnalysisInfo();
+			
+			if (info.trace_info == null)
+				info.trace_info = new Vector<Object>();
+			else
+				info.trace_info.clear();
+			
+			if (info.additional_info == null)
+				info.additional_info = new Vector<Object>();
+			else
+				info.additional_info.clear();
+			
+			// count the number of traces and create the list of enabled traces
+		    int numberOfTraces = 0;
+		    Iterator<ParsedTraceData> enuTraces = TraceDataRepository.getInstance().getTraceCollectionIter(instanceUID);
+		    AnalysisInfoHandler handler = NpiInstanceRepository.getInstance().getAnalysisInfoHandler(instanceUID);
+		    TraceAdditionalInfo traceAdditionalInfos = new TraceAdditionalInfo();
+
+		    while (enuTraces.hasNext()) {
+		    	Object object = enuTraces.next();
+
+		    	numberOfTraces++;
+		    	
+		    	if (object instanceof ParsedTraceData) {
+		    		ParsedTraceData parsedTraceData = (ParsedTraceData) object;
+		    		if (parsedTraceData.traceData != null) {
+			    		Class traceClass = parsedTraceData.traceData.getClass();
+
+						// this code is clumsy because the plugin, not the trace, has the trace ID info
+			    		Enumeration<AbstractPiPlugin> enuPlugins = PluginInitialiser.getPluginInstances(instanceUID, "com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace"); //$NON-NLS-1$
+						while (enuPlugins.hasMoreElements())
+						{
+							ITrace plugin = (ITrace)enuPlugins.nextElement();
+							if (   (traceClass == plugin.getTraceClass())
+								|| (   (plugin instanceof IClassReplacer)
+									&& (((IClassReplacer)plugin).getReplacedClass(traceClass.getCanonicalName()) == traceClass))) {
+						    	info.trace_info.add(new EnabledTrace(plugin.getTraceId(), plugin.getTraceName()));
+						    	if (plugin instanceof IProvideTraceAdditionalInfo) {
+									((IProvideTraceAdditionalInfo)plugin).analysisInfoHandlerToAdditonalInfo(traceAdditionalInfos, handler);						    		
+						    	}
+							}
+						}			
+		    		}
+		    	}
+		    }
+		    
+		    // write trace specific info if exist
+		    if (traceAdditionalInfos.size() > 0) {
+		    	info.additional_info.add(traceAdditionalInfos);
+		    }
+		    
+		    // no traces were found in the DAT or NPI file
+		    if (numberOfTraces == 0) {
+		    	throw new PIExceptionRuntime(Messages.getString("ProfileReader.16"));  //$NON-NLS-1$
+		    }
+
+		    // write the analysis data
+			try {
+				oos.writeObject(info);
+			}catch (Exception oops) {
+				oops.printStackTrace();
+			}
+
+			Iterator<ParsedTraceData> e = TraceDataRepository.getInstance().getTraceCollectionIter(instanceUID);
+		    while (e.hasNext())
+		    {
+		    	ParsedTraceData ptd = (ParsedTraceData)e.next();
+		    	if (ptd != null)
+		    	{
+		    		GenericTrace gt = ptd.traceData;
+		    		if (gt != null)
+		    		{
+		    			try {
+		    			  oos.writeObject(gt);
+			    		}catch (Exception oops) {
+			    			  oops.printStackTrace();
+			    		}
+		    		}
+		    	}
+		        // let's assume this loading take 94
+		    	monitor.worked((workUnitsForSave * 94 / 100) / numberOfTraces);
+	    		if (monitor.isCanceled()) {
+	    			throw new InterruptedException(Messages.getString("ProfileReader.17"));  //$NON-NLS-1$
+	    		}
+	            workUnitsLeft -= 94 / numberOfTraces;
+		    }
+		    // assume writing traces takes 90%
+		    monitor.worked((workUnitsForSave * 9 / 10) - workUnitsLeft);
+			if (monitor.isCanceled()) {
+				throw new InterruptedException(Messages.getString("ProfileReader.18"));  //$NON-NLS-1$
+			}
+	        workUnitsLeft = 10;
+
+		    Hashtable<Class,Serializable> additionalData = new Hashtable<Class,Serializable>();
+		      
+		    // iterate through PI plugins that implement the given interface
+		    Enumeration<AbstractPiPlugin> enumeration = PluginInitialiser.getPluginInstances(instanceUID, "com.nokia.carbide.cpp.internal.pi.plugin.model.IRecordable"); //$NON-NLS-1$
+			while (enumeration.hasMoreElements())
+			{
+				IRecordable recPlugin = (IRecordable)enumeration.nextElement();
+				Serializable data = recPlugin.getAdditionalData();
+				ITrace tracePlugin = (ITrace)recPlugin;
+				if (data != null && tracePlugin.getTraceName() != null)
+					additionalData.put(tracePlugin.getTraceClass(), data);
+			}
+			
+			oos.writeObject(additionalData);
+		    
+			if (monitor.isCanceled()) {
+				throw new InterruptedException(Messages.getString("ProfileReader.19")); //$NON-NLS-1$
+			}
+			
+		    monitor.worked(workUnitsForSave * 5 / 100);
+		} catch (InterruptedException e) {
+			lock.release();
+			throw e;
+		} catch (Exception e){
+			lock.release();
+			throw new InvocationTargetException(e);
+		} finally {
+			lock.release();
+		}
+
+		closeOutputStreams(fos, gzo, oos);
+	}
+	  
+	private void addToMenus(ITrace plugin) {
+		if (plugin instanceof IExportItem) {
+			((IExportItem)plugin).getExportAction();
+		}
+
+		if (plugin instanceof IImportMenu)
+		{
+			((IImportMenu)plugin).getIncludeAction();
+		}
+		
+		if (plugin instanceof IAnalysisItem) {
+			((IAnalysisItem)plugin).getAnalysisAction();
+		}
+
+		if (plugin instanceof IViewMenu) {
+			((IViewMenu)plugin).getViewOptionManager();
+		}
+	}
+	
+	public void setTraceMenus(ArrayList<AbstractPiPlugin> plugins, int instanceUID)
+	{
+		// Note: This ignores at least:
+		// 			com.nokia.carbide.cpp.internal.pi.plugin.model.IOpenOtherMenu
+		//			com.nokia.carbide.cpp.internal.pi.plugin.model.IOpenOtherTrace
+		
+		Enumeration<AbstractPiPlugin> enu;
+		AbstractPiPlugin plugin;
+		Action action;
+		MenuManager manager;
+		
+		PIPageEditor.initialiseMenuManager();
+		
+		enu = PluginInitialiser.getPluginInstances(instanceUID, "com.nokia.carbide.cpp.internal.pi.plugin.model.IExportItem"); //$NON-NLS-1$
+		while (enu.hasMoreElements())
+		{
+			// can only add export items if the plugin is associated with this tab
+			plugin = (AbstractPiPlugin)enu.nextElement();
+			if (   (plugin instanceof IExportItem)
+				&& (plugins != null)
+				&& (plugins.indexOf(plugin) >= 0)) {
+				action = ((IExportItem)plugin).getExportAction();
+				PIPageEditor.addExportAction(action);
+			}
+		}
+		
+		enu = PluginInitialiser.getPluginInstances(instanceUID, "com.nokia.carbide.cpp.internal.pi.plugin.model.IImportMenu"); //$NON-NLS-1$
+		while (enu.hasMoreElements())
+		{
+			// can add import items for any tab
+			plugin = (AbstractPiPlugin)enu.nextElement();
+			if (plugin instanceof IImportMenu) {
+				action = ((IImportMenu)plugin).getIncludeAction();
+				PIPageEditor.addIncludeAction(action);
+			}
+		}
+		
+		enu = PluginInitialiser.getPluginInstances(instanceUID, "com.nokia.carbide.cpp.internal.pi.plugin.model.IAnalysisItem"); //$NON-NLS-1$
+		while (enu.hasMoreElements())
+		{
+			// can only add analysis items if the plugin is associated with this tab
+			plugin = (AbstractPiPlugin)enu.nextElement();
+			if (   (plugin instanceof IAnalysisItem)
+				&& (plugins != null)
+				&& (plugins.indexOf(plugin) >= 0)) {
+				action = ((IAnalysisItem)plugin).getAnalysisAction();
+				PIPageEditor.addReportAction(action);
+			}
+		}
+
+		enu = PluginInitialiser.getPluginInstances(instanceUID, "com.nokia.carbide.cpp.internal.pi.plugin.model.IViewMenu"); //$NON-NLS-1$
+		while (enu.hasMoreElements())
+		{
+			// can only add view items if the plugin is associated with this tab
+			plugin = (AbstractPiPlugin)enu.nextElement();
+			if (   (plugin instanceof IViewMenu)
+				&& (plugins != null)
+				&& (plugins.indexOf(plugin) >= 0)) {
+					manager = ((IViewMenu)plugin).getViewOptionManager();
+					if (manager != null)
+						PIPageEditor.addViewOptionManager(manager);
+				}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/ProfileVisualiser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,472 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.analyser;
+
+import java.awt.Component;
+import java.io.File;
+import java.io.IOException;
+import java.text.DecimalFormat;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Sash;
+
+import com.nokia.carbide.cpp.internal.pi.utils.PIUtilities;
+import com.nokia.carbide.cpp.internal.pi.visual.PICompositePanel;
+import com.nokia.carbide.cpp.internal.pi.visual.PIEvent;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+public class ProfileVisualiser {
+	// rather than abitrary topologies, we will support pages containing:
+	//	only a top composite
+	//  a top composite and a bottom composite separated by a sash
+	public static final int TOP_ONLY       = 1;
+	public static final int TOP_AND_BOTTOM = 2;
+
+	private ProfileVisualiser thisVisualiser;
+	
+	// page for this visualiser
+	private Composite page;
+	
+	// title
+	private Label title;
+	
+	// secondary title
+	private Label title2;
+	
+	// current time selection string
+	private Label timeInterval;
+	private static final String noInterval = Messages.getString("ProfileVisualiser.noInterval"); //$NON-NLS-1$
+
+	public static final DecimalFormat timeFormat = new DecimalFormat(Messages.getString("ProfileVisualiser.decimalFormat")); //$NON-NLS-1$
+
+	// composite at the top of the page
+	private PICompositePanel topComposite;
+	
+	// composite at the bottom of the page (optional)
+	private SashForm bottomComposite;
+	
+	private Component currentInfoComponent;
+	private ParserRepository parserRepository;
+	private String pageName = null;
+		
+	public boolean visualiserEnabled = true;
+  
+//	public ProfileVisualiser(int topology, Composite parent, AnalyseTab tab)
+//	{
+//		initialize(parent, tab, "");
+//	}
+	
+	public ProfileVisualiser(int topology, Composite parent, String pageName)
+	{
+		this.thisVisualiser = this;
+		this.pageName = pageName;
+		this.page = new Composite(parent, SWT.NONE);
+
+		initialize(topology, page);
+	}
+
+	private void initialize(int topology, Composite newPage)
+	{
+		// newPage (Composite)
+		//		titleBar (Composite)
+		//		holder   (Composite)
+		FormData formData;
+		
+		if (   (topology != TOP_ONLY)
+			&& (topology != TOP_AND_BOTTOM)) {
+			return;
+		}
+		
+		this.parserRepository = new ParserRepository();
+		
+		
+		// add the title bar at the top
+		Composite titleBar = addTitleBar(newPage);
+		
+		// all graphs and tables go into a composite below the title
+		Composite holder = new Composite(newPage, SWT.NONE);
+		
+    	// FormData for the title bar
+		formData = new FormData();
+		formData.top    = new FormAttachment(0);
+		formData.left   = new FormAttachment(0);
+		formData.right  = new FormAttachment(100);
+		titleBar.setLayoutData(formData);
+		titleBar.setLayout(new FormLayout());
+		
+		// FormData for the overall holder composite
+		formData = new FormData();
+		formData.top    = new FormAttachment(titleBar);
+		formData.bottom = new FormAttachment(100);
+		formData.left   = new FormAttachment(0);
+		formData.right  = new FormAttachment(100);
+		holder.setLayoutData(formData);
+		holder.setLayout(new FormLayout());
+
+		newPage.setLayout(new FormLayout());
+		
+		setGraphsAndTablesHolder(holder, topology, formData);
+	}
+
+	private Composite addTitleBar(Composite newPage)
+	{
+		// titleBar (Composite)
+		//		title2 (Label)  title (Label) timeInterval (Label)
+
+		FormData formData;
+		Composite titleBar = new Composite(newPage, SWT.NONE);
+		
+		title2 = new Label(titleBar, SWT.LEFT);
+		title2.setBackground(newPage.getDisplay().getSystemColor(SWT.COLOR_YELLOW));
+		title2.setFont(PIPageEditor.helvetica_9);
+		
+		title = new Label(titleBar, SWT.CENTER);
+		title.setBackground(newPage.getDisplay().getSystemColor(SWT.COLOR_YELLOW));
+		title.setFont(PIPageEditor.helvetica_9);
+
+		timeInterval = new Label(titleBar, SWT.RIGHT);
+		timeInterval.setBackground(newPage.getDisplay().getSystemColor(SWT.COLOR_YELLOW));
+		timeInterval.setText(noInterval);
+		timeInterval.setFont(PIPageEditor.helvetica_9);
+
+		formData = new FormData();
+		formData.left   = new FormAttachment(0);
+		formData.right  = new FormAttachment(30);
+		title2.setLayoutData(formData);
+		
+		formData = new FormData();
+		formData.left   = new FormAttachment(30);
+		formData.right  = new FormAttachment(70);
+		title.setLayoutData(formData);
+		
+		formData = new FormData();
+		formData.left   = new FormAttachment(70);
+		formData.right  = new FormAttachment(100);
+		timeInterval.setLayoutData(formData);
+
+		return titleBar;
+	}
+
+	private void setGraphsAndTablesHolder(Composite holder, int topology, FormData formData)
+	{
+		// holder (Composite)
+		//		topComposite (PICompositePanel/ScrolledComposite/SashForm)
+		//		bottomComposite (SashForm)
+
+		// create a top composite that can hold graphs and/or tables
+		// NOTE: Sometimes we really only need a Composite(newPage, SWT.NONE)
+		this.topComposite = new PICompositePanel(holder, thisVisualiser);
+		
+		if (topology == TOP_ONLY) {
+			formData.left   = new FormAttachment(0);
+			formData.right  = new FormAttachment(100);
+			this.topComposite.getSashForm().setLayoutData(formData);
+			this.topComposite.getSashForm().setLayout(new FormLayout());
+			return;
+		}
+		
+		// create a bottom composite only suitable for holding tables
+		this.bottomComposite = new SashForm(holder, SWT.VERTICAL);
+		
+		// A sash separates top composite from bottom composite
+		final Sash acrossSash = new Sash(holder, SWT.HORIZONTAL);
+		
+		// FormData for top
+		formData = new FormData();
+		formData.top    = new FormAttachment(0);
+		formData.bottom = new FormAttachment(acrossSash);
+		formData.left   = new FormAttachment(0);
+		formData.right  = new FormAttachment(100);
+		this.topComposite.getSashForm().setLayoutData(formData);
+		this.topComposite.getSashForm().setLayout(new FormLayout());
+		
+		// FormData for bottom
+		formData = new FormData();
+		formData.top    = new FormAttachment(acrossSash);
+		formData.bottom = new FormAttachment(100);
+		formData.left   = new FormAttachment(0);
+		formData.right  = new FormAttachment(100);
+		bottomComposite.setLayoutData(formData);
+		bottomComposite.setLayout(new FormLayout());
+		
+		// FormData for acrossSash
+		// Put it initially in the middle
+		formData = new FormData();
+		formData.top    = new FormAttachment(50);
+		formData.left   = new FormAttachment(0);
+		formData.right  = new FormAttachment(100);
+		acrossSash.setLayoutData(formData);
+
+		final FormData acrossSashData = formData;
+		final Composite parentFinal = acrossSash.getParent();
+		acrossSash.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				if (event.detail != SWT.DRAG) {
+					acrossSashData.top = new FormAttachment(0, event.y);
+					parentFinal.layout();
+				}
+			}
+		});
+	}
+
+	public void setTimeInterval(final double start, final double end)
+	{
+		Display.getDefault().syncExec(new Runnable() {
+			public void run() {
+				PIPageEditor.currentPageEditor().setLocalTime(start, end);
+			}
+		});
+	}
+
+	public void fetchSelection()
+	{
+		double start = this.topComposite.getSelectionStart() / 1000;
+		double end =   this.topComposite.getSelectionEnd() / 1000;
+		PIPageEditor.currentPageEditor().setLocalTime(start, end);
+	}
+	  
+	public String getPageName()
+	{
+		return this.pageName;
+	}
+	
+	public void setPageName(String pageName)
+	{
+		this.pageName = pageName;
+	}
+	
+	public void saveScreenshot() throws IOException
+	{
+	  	File filePath = null;
+	  	
+	  	try
+		{
+	  	    filePath = PIUtilities.getAFile(true, "jpg"); //$NON-NLS-1$
+		}
+	  	catch (Exception e)
+		{
+	  		return;
+		}
+	  	
+	    if (filePath == null)
+	    {
+	      System.out.println(Messages.getString("ProfileVisualiser.noPath")); //$NON-NLS-1$
+	      return;
+	    }
+	    System.out.println(Messages.getString("ProfileVisualiser.savingScreenshot")); //$NON-NLS-1$
+	}
+
+	public void saveListScreenshot() throws IOException
+	{
+	  	if (this.currentInfoComponent == null) return;
+	  		
+	   	File filePath = null;
+	  	
+	  	try
+		{
+	  	    filePath = PIUtilities.getAFile(true, "jpg"); //$NON-NLS-1$
+		}
+	  	catch (Exception e)
+		{
+	  		return;
+		}
+	  	
+	    if (filePath == null)
+	    {
+	      System.out.println(Messages.getString("ProfileVisualiser.noPath")); //$NON-NLS-1$
+	      return;
+	    }
+	    System.out.println(Messages.getString("ProfileVisualiser.savingScreenshot")); //$NON-NLS-1$
+	}
+
+	public void action(String actionString)
+	{
+		// if there is any action that is applicable for panel without
+		// a graph put it here
+		
+		// below actions are only applicable for panels that have a graph
+    	if (this.topComposite.getActiveGraph() == null)
+    		return;
+
+	    if (actionString.equals("screenshot")) //$NON-NLS-1$
+	  	{
+	  		try
+			{
+	  			this.saveScreenshot();
+		    }
+		    catch (Exception e)
+		    {
+		        e.printStackTrace();
+		    }
+	  	}
+	  	else if (actionString.equals("listscreenshot")) //$NON-NLS-1$
+	  	{
+	  		try
+		    {
+		       this.saveListScreenshot();
+		    }
+		    catch (Exception e)
+		    {
+		        e.printStackTrace();
+		    }
+	  	}
+	  	else if (actionString.equals("+")) //$NON-NLS-1$
+	  	{
+	  		this.topComposite.performZoomCommand("+"); //$NON-NLS-1$
+	  	}
+	  	else if (actionString.equals("-")) //$NON-NLS-1$
+	  	{
+	  		this.topComposite.performZoomCommand("-"); //$NON-NLS-1$
+	  	}
+	  	else if (actionString.equals("++")) //$NON-NLS-1$
+	  	{
+	  		this.topComposite.performZoomCommand("++"); //$NON-NLS-1$
+	  	}
+	  	else if (actionString.equals("--")) //$NON-NLS-1$
+	  	{
+	  		this.topComposite.performZoomCommand("--"); //$NON-NLS-1$
+	  	}
+		else if (actionString.equals("changeSelection")) //$NON-NLS-1$
+	  	{
+			// change the time interval selected
+	  	    this.topComposite.selectionChanged();
+	  	}		
+	  	else if (actionString.equals("changeInterval")) //$NON-NLS-1$
+	  	{
+	  		// change the time interval displayed
+        	double startTime = PIPageEditor.currentPageEditor().getStartTime();
+        	double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+
+            if (startTime == -1 || endTime == -1)
+            {
+                this.timeInterval.setText(noInterval);
+            }
+            else
+            {
+            	this.timeInterval.setText(ProfileVisualiser.getTimeInterval(startTime, endTime));
+            }
+            // now the data are updated, let the zoomCommand of the panel 
+            // handle the selection centering and refresh
+            this.topComposite.performZoomCommand("changeInterval"); //$NON-NLS-1$
+	  	}
+	  	else if (actionString.equals("stretch")) //$NON-NLS-1$
+	  	{
+	  	}
+		else if (actionString.equals("changeResolution")) //$NON-NLS-1$
+		{
+		}
+		else if (actionString.equals("fetchSelection")) //$NON-NLS-1$
+	  	{
+	  	    this.fetchSelection();
+	  	}
+		else if (actionString.equals("changeThresholdThread")) //$NON-NLS-1$
+		{
+	        PIEvent be = new PIEvent(
+	        		null, PIEvent.THRESHOLD_THREAD_CHANGED);
+	        this.topComposite.piEventReceived(be); 
+		}
+		else if (actionString.equals("changeThresholdBinary")) //$NON-NLS-1$
+		{
+	        PIEvent be = new PIEvent(
+	        		null, PIEvent.THRESHOLD_BINARY_CHANGED);
+	        this.topComposite.piEventReceived(be); 
+		}
+		else if (actionString.equals("changeThresholdFunction")) //$NON-NLS-1$
+		{
+	        PIEvent be = new PIEvent(
+	        		null, PIEvent.THRESHOLD_FUNCTION_CHANGED);
+	        this.topComposite.piEventReceived(be); 
+		}
+	}
+
+	public Composite getContentPane()
+	{
+		return this.page;
+	}
+
+	public ParserRepository getParserRepository()
+	{
+		return this.parserRepository;
+	}
+	  
+	public int getLastSampleX()
+	{
+		return this.topComposite.lastSampleX;
+	}
+
+	public void setLastSampleX(int aksa)
+	{
+	  	if (this.topComposite.lastSampleX < aksa)
+	  		this.topComposite.lastSampleX = aksa;
+	  	
+	  	// do the set even if nothing has changed except that a new graph was added to the tab
+  		this.topComposite.setSizeX(true);
+	}
+	  
+	public void vPanelRepaint(Component infoComponent)
+	{
+		//make this   
+		if (infoComponent != null &&  infoComponent != this.currentInfoComponent)
+		{
+			this.currentInfoComponent = infoComponent;
+		}
+	}
+	  
+	public SashForm getBottomComposite()
+	{
+		return this.bottomComposite;
+	}
+	  
+	public PICompositePanel getTopComposite()
+	{
+		return this.topComposite;
+	}
+	
+	public Label getTitle()
+	{
+		return this.title;
+	}
+	
+	public Label getTitle2()
+	{
+		return this.title2;
+	}
+	
+	public Label getTimeString()
+	{
+		return this.timeInterval;
+	}
+	
+	public static String getTimeInterval(double startTime, double endTime)
+	{
+		return Messages.getString("ProfileVisualiser.interval1") + timeFormat.format(startTime) //$NON-NLS-1$
+		     + Messages.getString("ProfileVisualiser.interval2") + timeFormat.format(endTime) //$NON-NLS-1$
+		     + Messages.getString("ProfileVisualiser.interval3") + timeFormat.format(endTime - startTime) //$NON-NLS-1$
+		     + Messages.getString("ProfileVisualiser.interval4"); //$NON-NLS-1$
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/StreamFileParser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: 
+ *
+ */
+
+/*
+ * StreamFileParser.java
+ */
+package com.nokia.carbide.cpp.internal.pi.analyser;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Set;
+
+
+public class StreamFileParser 
+{
+	private int readOffset = 0;
+	private int currentLength = 0;
+	private int currentType = -1;
+	private byte[] streamData;
+	private Hashtable<Integer,ByteArrayOutputStream> dataBlocks;
+	
+	public StreamFileParser(File streamFile) throws IOException
+	{
+		dataBlocks = new Hashtable<Integer,ByteArrayOutputStream>();
+		
+		if (!streamFile.exists()) throw new IOException(Messages.getString("StreamFileParser.fileNotFound")); //$NON-NLS-1$
+		
+		streamData = new byte[(int)streamFile.length()];
+		FileInputStream fis = new FileInputStream(streamFile);
+		fis.read(streamData);
+		
+		readLoop();
+	}
+	
+	public byte[] getDataForTraceType(int traceType)
+	{
+		Integer type = new Integer(traceType);
+		if (dataBlocks.containsKey(type))
+		{
+			ByteArrayOutputStream baos = 
+				(ByteArrayOutputStream)dataBlocks.get(type);
+			return baos.toByteArray();
+		}
+		else 
+		{
+			return null;
+		}
+	}
+	
+	public File getTempFileForTraceType(int traceType) throws IOException
+	{
+		byte[] data = getDataForTraceType(traceType);
+		if (data == null) return null;
+		File f = File.createTempFile("type_" + traceType + "_trace_file",".dat");    //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		//File f = File.createTempFile(getTypeString(new Integer(traceType)),".dat");
+		f.deleteOnExit();
+		
+		FileOutputStream fos = new FileOutputStream(f);
+		fos.write(data);
+		fos.flush();
+		fos.close();
+		
+		return f;
+	}
+		
+	private void readLoop()
+	{
+		while(setLengthAndMode() == true)
+		{
+			copyDataBlock();
+		}
+	}
+
+	/*public void writeToFiles(String path) throws Exception
+	{
+		Enumeration enumer = dataBlocks.keys();
+		while(enumer.hasMoreElements())
+		{
+			Integer type = (Integer)enumer.nextElement();
+			ByteArrayOutputStream baos = (ByteArrayOutputStream)dataBlocks.get(type);
+			String typeString = getTypeString(type);
+		
+			File f = new File(path+typeString+"_trace_file.dat");
+			if (f.exists()) f.delete();
+			FileOutputStream fos = new FileOutputStream(f);
+			System.out.println("Writing "+f.getAbsolutePath());
+			fos.write(baos.toByteArray());						
+		}
+	}*/
+	/*private String getTypeString(Integer typeValue)
+	{
+		if (typeValue.intValue() == 1) return "GPP";
+		if (typeValue.intValue() == 2) return "GFC";
+		if (typeValue.intValue() == 3) return "ITT";
+		if (typeValue.intValue() == 4) return "MEM";
+		if (typeValue.intValue() == 5) return "TIP";
+		if (typeValue.intValue() == 6) return "IRQ";
+		if (typeValue.intValue() == 7) return "BUP";
+		
+		else return "undefined_type";
+	}*/
+	
+	public boolean setLengthAndMode()
+	{
+		if (readOffset+4 >= streamData.length)
+		{
+			// end of data buffer reached
+			streamData = null;
+			return false;
+		}
+		else
+		{
+			int b1 = (streamData[readOffset++]<<24)>>>24;
+			int b2 = (streamData[readOffset++]<<24)>>>24;
+			int b3 = (streamData[readOffset++]<<24)>>>24;
+			//System.out.println(" b1:"+b1+" b2:"+b2+" b3:"+b3);
+			currentLength = (int)(b1 | b2<<8 | b3 <<16);
+			
+			currentType = streamData[readOffset++];
+			//System.out.println("Length "+currentLength+" mode "+currentType);
+						
+			return true;
+		}
+	}
+	
+	private void copyDataBlock()
+	{
+		Integer typeInt = new Integer(currentType);
+		ByteArrayOutputStream baos = null;
+		
+		if (dataBlocks.containsKey(typeInt))
+		{
+			baos = (ByteArrayOutputStream)dataBlocks.get(typeInt);
+		}
+		else
+		{
+			baos = new ByteArrayOutputStream();
+			dataBlocks.put(typeInt, baos);
+		}
+
+		baos.write(streamData,readOffset,currentLength);
+		readOffset += currentLength;
+	}
+	
+	/* Support for reading available traces */
+	public Set<Integer> allTraceType() {
+		return dataBlocks.keySet();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/TestGUI.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.analyser;
+
+import java.awt.Frame;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+
+public class TestGUI extends Frame {
+
+	private static final long serialVersionUID = -7535470144323980407L;
+
+	private static TestGUI thisFrame;
+
+	// recent files
+	public static final int NUMBER_RECENT_FILES = 6;
+
+	// status panel containing progressPanel
+//	private static JPanel statusPanel = null;
+
+	// progress panel containing progressBar
+//	private static JPanel progressPanel = null;
+//	private static ProgressBar progressBar;
+
+	// graph popup menu and its items
+    private transient Menu	 graphPopupMenu;	 
+    private transient MenuItem zoomInItem;
+    private transient MenuItem zoomOutItem;
+    private transient MenuItem zoomToSelectionItem;
+    private transient MenuItem zoomToTraceItem;
+
+	/**
+	 * This is the default constructor
+	 */
+	private TestGUI() {
+		super();
+	}
+	
+	/**
+	 * This method initializes this
+	 *
+	 * @return void
+	 */
+	public static TestGUI getInstance() {
+		if (thisFrame == null)
+		{
+			thisFrame = new TestGUI();
+		}
+		return thisFrame;
+	}
+
+	public static void action(String actionString) {
+		PIChangeEvent.action(actionString);
+	}
+
+	/**
+	 * This method initializes graphPopupMenu
+	 *
+	 */
+	public Menu getGraphPopupMenu(Decorations parent, boolean forceCreate) {
+		if ((graphPopupMenu == null) || forceCreate) {
+			if (graphPopupMenu != null)
+				graphPopupMenu.dispose();
+			
+			graphPopupMenu = new Menu(parent, SWT.POP_UP);
+			getZoomInItem(graphPopupMenu, forceCreate);
+			getZoomOutItem(graphPopupMenu, forceCreate);
+			getZoomToSelectionItem(graphPopupMenu, forceCreate);
+			getZoomToTraceItem(graphPopupMenu, forceCreate);
+//			new MenuItem(graphPopupMenu, SWT.SEPARATOR);
+//			getSynchroniseItem(graphPopupMenu, forceCreate);
+			graphPopupMenu.setVisible(true);
+		}
+		return graphPopupMenu;
+	}
+
+//	/**
+//	 * This method initializes synchroniseItem
+//	 *
+//	 */
+//	private MenuItem getSynchroniseItem(Menu menu, boolean forceCreate) {
+//		if ((synchroniseItem == null) || forceCreate) {
+//			if (synchroniseItem != null)
+//				synchroniseItem.dispose();
+//			
+//			synchroniseItem = new MenuItem(menu, SWT.PUSH);
+//			synchroniseItem.setText("Synchronize Graph Displays");
+//			synchroniseItem.addSelectionListener(new SelectionAdapter() { 
+//				public void widgetSelected(SelectionEvent e) {
+//				    action("synchronise");
+//				}
+//			});
+//		}
+//		return synchroniseItem;
+//	}
+
+	/**
+	 * This method initializes zoomInItem
+	 *
+	 */
+	private MenuItem getZoomInItem(Menu menu, boolean forceCreate) {
+		if ((zoomInItem == null) || forceCreate) {
+			if (zoomInItem != null)
+				zoomInItem.dispose();
+			
+			zoomInItem = new MenuItem(menu, SWT.PUSH);
+			zoomInItem.setText(Messages.getString("TestGUI.zoomIn")); //$NON-NLS-1$
+			zoomInItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("-"); //$NON-NLS-1$
+				}
+			});
+		}
+		return zoomInItem;
+	}
+
+	/**
+	 * This method initializes zoomOutItem
+	 */
+	private MenuItem getZoomOutItem(Menu menu, boolean forceCreate) {
+		if ((zoomOutItem == null) || forceCreate) {
+			if (zoomOutItem != null)
+				zoomOutItem.dispose();
+			
+			zoomOutItem = new MenuItem(menu, SWT.PUSH);
+			zoomOutItem.setText(Messages.getString("TestGUI.zoomOut")); //$NON-NLS-1$
+			zoomOutItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("+"); //$NON-NLS-1$
+				}
+			});
+		}
+		return zoomOutItem;
+	}
+
+	/**
+	 * This method initializes zoomAreaItem
+	 */
+	private MenuItem getZoomToSelectionItem(Menu menu, boolean forceCreate) {
+		if ((zoomToSelectionItem == null) || forceCreate) {
+			if (zoomToSelectionItem != null)
+				zoomToSelectionItem.dispose();
+			
+			zoomToSelectionItem = new MenuItem(menu, SWT.PUSH);
+			zoomToSelectionItem.setText(Messages.getString("TestGUI.showSelected")); //$NON-NLS-1$
+			zoomToSelectionItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("--"); //$NON-NLS-1$
+				}
+			});
+		}
+		return zoomToSelectionItem;
+	}
+
+	/**
+	 * This method initializes zoomTraceItem
+	 */
+	private MenuItem getZoomToTraceItem(Menu menu, boolean forceCreate) {
+		if ((zoomToTraceItem == null) || forceCreate) {
+			if (zoomToTraceItem != null)
+				zoomToTraceItem.dispose();
+			
+			zoomToTraceItem = new MenuItem(menu, SWT.PUSH);
+			zoomToTraceItem.setText(Messages.getString("TestGUI.showGraph")); //$NON-NLS-1$
+			zoomToTraceItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("++"); //$NON-NLS-1$
+				}
+			});
+		}
+		return zoomToTraceItem;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/analyser/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,69 @@
+AnalyserDataProcessor.0=TraceDataRepository for UID
+AnalyserDataProcessor.1=is empty
+AnalyserDataProcessor.10=Opening 
+AnalyserDataProcessor.11=PI internal error: Could not open output file
+AnalyserDataProcessor.12=Error opening  
+AnalyserDataProcessor.14=Importer Error: Cannot write to 
+AnalyserDataProcessor.15=Importer Error: Cannot read 
+AnalyserDataProcessor.17=Importing 
+AnalyserDataProcessor.18=PI internal error: Invalid profiler data file
+AnalyserDataProcessor.19=User cancelled opening
+AnalyserDataProcessor.2=Refining 
+AnalyserDataProcessor.20=Import failed\n
+AnalyserDataProcessor.21=\nException stack:\n
+AnalyserDataProcessor.22=User cancelled import
+AnalyserDataProcessor.23=importing for stripping timestamp
+AnalyserDataProcessor.24=failed to on IDE.openEditor()
+AnalyserDataProcessor.25=temp trace file creation error
+AnalyserDataProcessor.26=failed creating StreamFileParser for 
+AnalyserDataProcessor.3=\ with 
+AnalyserDataProcessor.4=Import UID does not match active UI
+AnalyserDataProcessor.5=Opening  
+AnalyserDataProcessor.6=Import failed\n
+AnalyserDataProcessor.7=\nException stack:\n
+AnalyserDataProcessor.8=Import file was corrupted\n
+AnalyserDataProcessor.9=\nException stack:\n
+AnalyserDataProcessor.interruptedException=InterruptedException
+AnalyserDataProcessor.invocationTargetException=InvocationTargetException
+AnalyserDataProcessor.ok=OK
+AnalyserDataProcessor.savingImportedFile=Saving Imported File
+StreamFileParser.fileNotFound=File not found
+ProfileReader.0=Loading file 
+ProfileReader.1=\nCheck that related Performance Investigator plugin is available\n
+ProfileReader.10=Loaded PI analysis info: 
+ProfileReader.11=Failed to load PI analysis info
+ProfileReader.12=PI analysis info not found in input file
+ProfileReader.13=Converted function call trace UID conflict
+ProfileReader.14=Converted function call trace UID conflict
+ProfileReader.priorityTraceUIDconflict=Converted priority trace UID conflict
+ProfileReader.15=Saving 
+ProfileReader.16=no traces in file
+ProfileReader.17=user cancelled
+ProfileReader.18=user cancelled
+ProfileReader.19=user cancelled
+ProfileReader.2=Read OK
+ProfileReader.3=Error:
+ProfileReader.4=Read failed
+ProfileReader.5=Cannot find class 
+ProfileReader.6=\nCheck that related plugin is available\n
+ProfileReader.7=File corrected
+ProfileReader.8=Loaded PI analysis info: 
+ProfileReader.9=Failed to load PI analysis info
+ProfileVisualiser.decimalFormat=\#\#\#0.000
+ProfileVisualiser.noPath=No file path\!
+ProfileVisualiser.interval1=\ [ 
+ProfileVisualiser.interval2=s to 
+ProfileVisualiser.interval3=s = 
+ProfileVisualiser.interval4=s ]
+ProfileVisualiser.savingScreenshot=Saving screenshot picture
+ProfileVisualiser.noInterval=[ 0.000s to 0.000s = 0.0s ]
+TestGUI.zoomIn=Zoom In
+TestGUI.zoomOut=Zoom Out
+TestGUI.showSelected=Zoom to Selected Time Interval
+TestGUI.showGraph=Show Entire Graph
+NpiInstanceRepository.0=getTrace failed on UID 
+NpiInstanceRepository.1=removeTrace failed on UID 
+NpiInstanceRepository.2=getPlugins failed on UID 
+NpiInstanceRepository.3=addPlugin failed on UID 
+NpiInstanceRepository.4=getProfilePages failed on UID 
+NpiInstanceRepository.5=getProfilePage failed on UID 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/IPiItem.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.interfaces;
+
+import com.nokia.carbide.cpp.internal.pi.model.PiItemType;
+
+
+public interface IPiItem
+{
+	String getName();
+	void setName(String newName);
+	String getLocation();
+	boolean isPIFor(Object obj);
+	PiItemType getType();
+	String getInfo();
+	
+	static IPiItem[] NONE = new IPiItem[] {};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/IReturnPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.interfaces;
+
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+public interface IReturnPlugin {
+	public AbstractPiPlugin getPlugin();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/ISaveSamples.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.interfaces;
+
+public interface ISaveSamples {
+	public String getData();
+	public int getIndex();
+	public void clear();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/ISaveTable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.interfaces;
+
+public interface ISaveTable {
+	public String getData();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/IToolBarActionListener.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.interfaces;
+
+public interface IToolBarActionListener {
+	// 
+	public void setActions(boolean entering, int pageIndex);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/interfaces/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.interfaces;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.interfaces.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/BackgroundLoader.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.manager;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * A utility for predictively resolving classes
+ * This can be used to help offset one of the biggest detractors from
+ * the Java language:  Class loading delays.
+ *
+ **/
+
+public class BackgroundLoader implements Runnable
+{
+	/**
+	 * Thread used to load classes in the background
+	 **/
+
+	private static Thread controlThread;
+
+	/**
+	 * Storage for the class names still to be resolved
+	 **/
+
+	private static Vector queue;
+
+	static
+	{
+		try
+		{
+			// This is an IBM-specific code that prevents a nasty error in the IBM resource lookup code -JDM
+			java.text.DateFormat.getDateInstance();
+		}
+		catch (Exception e)
+		{
+		}
+
+		queue = new Vector();
+	}
+
+    /**
+     * Private constructor, to enforce singleton status
+     * Creation date: (12/20/99 3:10:32 PM)
+     **/
+
+    private BackgroundLoader()
+    {
+    }
+
+    /**
+     * Enqueue a class for background loading
+     * Creation date: (12/20/99 3:23:28 PM)
+     * @param className java.lang.String
+     **/
+
+    public static void enqueueClass(String className)
+    {
+    	synchronized(queue)
+    	{
+    		queue.addElement(className);
+
+    		if (controlThread == null)
+    			start();
+    		else
+    			queue.notify();
+    	}
+    }
+
+    /**
+     * Start loading
+     * Creation date: (12/20/99 3:15:29 PM)
+     **/
+
+    public void run()
+    {
+    	if (Thread.currentThread() != controlThread)
+    		return;
+
+    	Hashtable done = new Hashtable();
+
+    	while (controlThread.isAlive())
+    	{
+    		String className;
+
+    		synchronized(queue)
+    		{
+    			if (queue.isEmpty())
+    			{
+    				try
+    				{
+    					queue.wait();
+    				}
+    				catch (InterruptedException ie)
+    				{
+    				}
+    			}
+
+    			if (!queue.isEmpty())
+    			{
+    				className = (String) queue.elementAt(0);
+    				queue.removeElementAt(0);
+    			}
+    			else
+    				continue;
+    		}
+
+    		if (!done.containsKey(className))
+    		{
+    			try
+    			{
+    				Class resolved = Class.forName(className);
+    				done.put(resolved.getName(), resolved);
+    			}
+    			catch (Exception e)
+    			{
+    				e.printStackTrace();
+    			}
+    		}
+
+    		className = null;
+    	}
+
+    	controlThread = null;
+    }
+
+    /**
+     * Insert the method's description here.
+     * Creation date: (4/5/00 3:24:04 PM)
+     */
+
+    private static void start()
+    {
+    	controlThread = new Thread(new BackgroundLoader());
+
+    	try
+    	{
+    		controlThread.setName(Messages.getString("BackgroundLoader.backgroundLoader")); //$NON-NLS-1$
+    		controlThread.setPriority((Thread.MIN_PRIORITY + Thread.NORM_PRIORITY) / 2);
+    	}
+    	catch (Exception e)
+    	{
+    	}
+
+    	controlThread.start();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.manager;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.manager.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/PluginInitialiser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.manager;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
+import com.nokia.carbide.cpp.internal.pi.utils.PluginClassLoader;
+import com.nokia.carbide.cpp.pi.PiPlugin;
+
+
+public class PluginInitialiser 
+{
+	/*
+	 * contains vectors which are each mapped to hashcodes of analysis instances
+	 * vectors contains analysis specific plugin instances
+	 * also one vector for top level plugin instances is included which is mapped to 0 
+	 */ 
+	private static Hashtable<Integer,Vector<AbstractPiPlugin>> pluginInstanceReferences;
+	
+	/*
+	 * Contains class loaders for the plugins
+	 */
+	private static ClassLoader pluginClassLoader;
+	
+	private PluginInitialiser(){}
+	
+	/**
+	 * This method takes a plugin interface name as a parameter (e.g. com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace)
+	 * and returns instances of the plugins which implement that interface
+	 */
+	public static Enumeration<AbstractPiPlugin> invokePluginInstances(int id, String pluginInterfaceName)
+	{
+		Vector<AbstractPiPlugin> pluginInstances = new Vector<AbstractPiPlugin>();
+		AbstractPiPlugin plugin = null;
+		java.lang.Class matchClass = null;
+
+		// make sure interface name is a valid class
+		try {
+			matchClass = java.lang.Class.forName(pluginInterfaceName);
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+		}
+
+		// find all plugins that are instances of the interface
+		Enumeration<AbstractPiPlugin> enu = PluginRegistry.getInstance().getRegistryEntries();
+		while (enu.hasMoreElements())
+		{
+			// make sure the cast is valid
+			try {
+				plugin = (AbstractPiPlugin) enu.nextElement();
+			} catch (ClassCastException e) {
+				e.printStackTrace();
+			}
+
+			// record and return matches
+			if (matchClass.isInstance(plugin)) {
+				pluginInstances.add(plugin);
+				addInstanceReference(id, plugin);
+			}
+		}
+
+		return pluginInstances.elements();
+	}
+	
+	public static ClassLoader getPluginClassLoader()
+	{
+		if (pluginClassLoader != null)
+			return pluginClassLoader;
+		
+		AbstractPiPlugin plugin = null;
+		Vector<AbstractPiPlugin> vec = new Vector<AbstractPiPlugin>();
+		
+		Enumeration<AbstractPiPlugin> e = PluginRegistry.getInstance().getRegistryEntries();
+		while(e.hasMoreElements())
+		{
+			// make sure the cast is valid
+			try {
+				plugin = (AbstractPiPlugin) e.nextElement();
+			} catch (ClassCastException e1) {
+				e1.printStackTrace();
+			}
+			vec.add(plugin);
+		}
+		
+		AbstractPiPlugin[] array = vec.toArray(new AbstractPiPlugin[vec.size()]);
+		pluginClassLoader = new PluginClassLoader(array);
+		return pluginClassLoader;
+	}
+	
+	//returns all invoked plugin instances mapped to given id number
+	public static Enumeration<AbstractPiPlugin> getPluginInstances(int id)
+	{
+		Vector<AbstractPiPlugin> tmp = new Vector<AbstractPiPlugin>();
+
+		if (pluginInstanceReferences != null)
+		{
+			// make sure the cast is valid
+			try {
+				tmp = pluginInstanceReferences.get(new Integer(id));
+			} catch (ClassCastException e1) {
+				e1.printStackTrace();
+			}
+		}
+		return tmp.elements();
+	}
+	
+	// returns invoked plugin instances mapped to the given id number which implement an interface with the given name
+	public static Enumeration<AbstractPiPlugin> getPluginInstances(int id, String pluginInterfaceName)
+	{
+		Vector<AbstractPiPlugin> instances = new Vector<AbstractPiPlugin>();
+
+		if (pluginInstanceReferences == null)
+			return instances.elements();
+
+		Vector<AbstractPiPlugin> tmp = pluginInstanceReferences.get(new Integer(id));
+		if (tmp != null)
+		{
+			AbstractPiPlugin plugin = null;
+			java.lang.Class matchClass = null;
+
+			// make sure the interface name is a valid class
+			try {
+				matchClass = java.lang.Class.forName(pluginInterfaceName);
+			} catch (ClassNotFoundException e1) {
+				System.out.println(Messages.getString("PluginInitialiser.pluginInterfaces")); //$NON-NLS-1$
+				e1.printStackTrace();
+			}
+			
+			// find all plugins that are instances of the interface
+			Enumeration<AbstractPiPlugin> enu = tmp.elements();
+			while (enu.hasMoreElements())
+			{
+				// make sure the cast is valid
+				try {
+					plugin = (AbstractPiPlugin) enu.nextElement();
+				} catch (ClassCastException e1) {
+					e1.printStackTrace();
+				}
+				
+				if (matchClass.isInstance(plugin))
+				{
+					instances.add(plugin);
+				}
+			}
+		}
+		return instances.elements();
+	}
+	
+	// returns all invoked plugin instances which implement an interface with the given name
+	public static Enumeration<AbstractPiPlugin> getPluginInstances(String pluginInterfaceName)
+	{
+		Vector<AbstractPiPlugin> instances = new Vector<AbstractPiPlugin>();
+
+		if (pluginInstanceReferences == null)
+			return instances.elements();
+
+		AbstractPiPlugin plugin = null;
+		java.lang.Class matchClass = null;
+
+		// make sure the interface name is a valid class
+		try {
+			matchClass = java.lang.Class.forName(pluginInterfaceName);
+		} catch (ClassNotFoundException e1) {
+			System.out.println(Messages.getString("PluginInitialiser.pluginInterfaces")); //$NON-NLS-1$
+			e1.printStackTrace();
+		}
+		
+		Enumeration<Vector<AbstractPiPlugin>> enu = pluginInstanceReferences.elements();
+		while (enu.hasMoreElements())
+		{
+			// make sure the cast is valid
+			Vector<AbstractPiPlugin> tmp = null;
+			try {
+				tmp = enu.nextElement();
+			} catch (ClassCastException e1) {
+				e1.printStackTrace();
+			}
+
+			if (tmp != null)
+			{
+				Enumeration<AbstractPiPlugin> e = tmp.elements();
+				while (e.hasMoreElements())
+				{
+					// make sure the cast is valid
+					try {
+						plugin = (AbstractPiPlugin)e.nextElement();
+					} catch (ClassCastException e1) {
+						e1.printStackTrace();
+					}
+
+					if (matchClass.isInstance(plugin))
+					{
+						instances.add(plugin);
+					}
+				}
+			}
+		}
+
+		return instances.elements();
+	}
+	
+	public static Class getPluginClass(String className)
+	{
+		// because only trace types will be returned by getPluginInstances(),
+		// and PiPlugin is not a trace type, call its class replacer explicitly 
+		Class c = PiPlugin.getReplacedClass(className);
+		if (c != null)
+			return c;
+
+		Enumeration<AbstractPiPlugin> e = getPluginInstances("com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer"); //$NON-NLS-1$
+		while(e.hasMoreElements())
+		{
+			IClassReplacer rep = (IClassReplacer)e.nextElement();
+			c = rep.getReplacedClass(className);
+			if (c != null)
+				return c;
+		}
+		
+		return null;
+	}
+	
+	public static void removeTraceInstances(int id) 
+	{
+		if (id == 0) return; //not removing top level plugin instances
+		if (pluginInstanceReferences != null)
+		{
+			pluginInstanceReferences.remove(new Integer(id));
+		}
+	}
+	
+	public static void removeAllTraceInstances()
+	{
+		if (pluginInstanceReferences != null)
+		{
+			Enumeration<Integer> e = pluginInstanceReferences.keys();
+			while (e.hasMoreElements())
+			{
+				Integer i = (Integer)e.nextElement();
+				if (i != 0)
+					pluginInstanceReferences.remove(i);
+			}
+		}
+	}
+	
+	private static void addInstanceReference(int id, AbstractPiPlugin plugin)
+	{
+		if (pluginInstanceReferences == null)
+			pluginInstanceReferences = new Hashtable<Integer, Vector<AbstractPiPlugin>>();
+		Vector<AbstractPiPlugin> tmp = pluginInstanceReferences.get(new Integer(id));
+		if (tmp != null)
+		{
+			// do not allow duplicate plugins
+			if (!tmp.contains(plugin))
+				tmp.add(plugin);
+		}
+		else
+		{
+			Vector<AbstractPiPlugin> tmp2 = new Vector<AbstractPiPlugin>();
+			tmp2.add(plugin);
+			pluginInstanceReferences.put(new Integer(id), tmp2);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/PluginRegisterer.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.manager;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IReturnPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.pi.PiPlugin;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+
+
+public class PluginRegisterer
+{
+	private static final String extensionName = "com.nokia.carbide.cpp.pi.piPluginData"; //$NON-NLS-1$
+	
+	private static boolean alreadyRegistered = false;
+
+	public PluginRegisterer()
+	{
+	}
+	
+	public static void registerAllPlugins()
+	{
+		if (alreadyRegistered)
+			return;
+		
+		// start all PI plugins that have their dependencies resolved
+		if (!PIPageEditor.arePluginsStarted()) {
+			PIPageEditor.startPlugins();
+
+			Bundle[] bundles = PiPlugin.getDefault().getBundle().getBundleContext().getBundles();
+			for (int i = 0; i < bundles.length; i++) {
+				Bundle bundle = bundles[i];
+				if (bundle.getSymbolicName().matches(".*com\\.nokia\\.carbide\\.cpp\\.pi\\..*")) { //$NON-NLS-1$
+					int state = bundle.getState();
+					if (state == Bundle.RESOLVED)
+						try {
+							bundle.start(Bundle.START_TRANSIENT);
+						} catch (Exception ex) {
+						}
+				}
+			}
+		}
+
+		IExtensionRegistry registry    = Platform.getExtensionRegistry();
+        IExtensionPoint extensionPoint = registry.getExtensionPoint(extensionName);
+
+        if (extensionPoint == null)
+        	return;
+        
+        IExtension[] extensions        = extensionPoint.getExtensions();
+        // For each extension ...
+    	for (int i = 0; i < extensions.length; i++) {
+			IExtension extension             = extensions[i];
+			IConfigurationElement[] elements = extension.getConfigurationElements();
+            // For each member of the extension ...
+			if (elements != null && elements.length >= 1) {
+				IConfigurationElement element = elements[0];
+				AbstractPiPlugin plugin;
+				IReturnPlugin getPlugin;
+				try {
+					getPlugin = (IReturnPlugin) element.createExecutableExtension("pluginClass");  //$NON-NLS-1$
+					plugin = getPlugin.getPlugin();
+					PluginRegistry.getInstance().addRegistryEntry(plugin);
+				} catch (CoreException e) {
+					e.printStackTrace();
+				}
+			}
+		}
+    	
+    	alreadyRegistered = true;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/PluginRegistry.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.manager;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+public class PluginRegistry 
+{
+	private static PluginRegistry pluginRegistry = null;
+	private Vector<AbstractPiPlugin> plugins;
+
+	private PluginRegistry()
+	{
+		plugins = new Vector<AbstractPiPlugin>();
+	}
+	
+	public static PluginRegistry getInstance()
+	{
+		if (pluginRegistry != null)
+			return pluginRegistry;
+		else
+		{
+			pluginRegistry = new PluginRegistry();
+			return pluginRegistry;
+		}
+	}
+	
+	protected void addRegistryEntry(AbstractPiPlugin plugin)
+	{
+		if (plugin instanceof ITrace)
+		{
+			ITrace testPlugin = (ITrace) plugin;
+			if (testPlugin.getTraceId() == 1)
+			{
+				// This is a workaround.
+				// must have GPP run first because ITT
+				// parsing assume the symbolparser of GPP
+				// is already registered, which in turn 
+				// register during GPP parsing
+				plugins.add(0, plugin);
+				return;
+			} else {
+				int index = plugins.size() > 0 ? plugins.size() - 1 : 0;
+				for (int i = 0; i < plugins.size(); i++) {
+					AbstractPiPlugin thisPlugin = plugins.get(i);
+					if (thisPlugin instanceof ITrace) {
+						if (testPlugin.getTraceId() > ((ITrace)thisPlugin).getTraceId()) {
+							index = i + 1;
+							continue;
+						} else if (testPlugin.getTraceId() < ((ITrace)thisPlugin).getTraceId()) {
+							index = i;	// found insert location
+							break;
+						} else if (testPlugin.getTraceId() == 4) {
+							// priority before memory for 4
+							if (((ITrace)thisPlugin).getTraceName().equals("Memory")) {	//$NON-NLS-1$
+								index = i;
+								break;
+							} else {
+								index = i + 1;
+								break;
+							}
+						} else {
+							// only priority and memory share ID = 4
+							GeneralMessages.showErrorMessage(Messages.getString("PluginRegistry.DuplicatedTraceID")); //$NON-NLS-1$
+						}
+					}
+				}
+				plugins.insertElementAt(plugin, index);
+				return;
+			}
+		}
+		plugins.add(plugin);
+	}
+
+	public Enumeration<AbstractPiPlugin> getRegistryEntries()
+	{
+		return plugins.elements();
+	}
+	
+	public int getRegistrySize()
+	{
+		return plugins.size();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/RegisterEntry.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.manager;
+
+public class RegisterEntry 
+{
+	private String pluginName;
+	private String id;
+	private String pluginClassName;
+	private String libraryName;
+	private String pluginPath;
+	private String[] requiredLibrarys;
+	
+	public RegisterEntry(String pluginName, String id, String version, String providerName, String pluginClassName,
+			String libraryName, String pluginPath, String[] requiredLibrarys)
+	{
+		this.pluginName = pluginName;
+		this.id = id;
+		this.pluginClassName = pluginClassName;
+		this.libraryName = libraryName;
+		this.pluginPath = pluginPath;
+		this.requiredLibrarys = requiredLibrarys;
+	}
+	
+	public String getId() 
+	{
+		return id;
+	}
+	public String getLibraryName() 
+	{
+		return libraryName;
+	}
+	public String getPluginClassName() 
+	{
+		return pluginClassName;
+	}
+	public String getPluginName() 
+	{
+		return pluginName;
+	}
+	public String getPluginPath() 
+	{
+		return pluginPath;
+	}
+
+	public String[] getReguiredLibrarys() 
+	{
+		return requiredLibrarys;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/TraceTypePreviewer.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.manager;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.StreamFileParser;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+
+
+/**
+ * 
+ * Load a .dat file and preview all the traces available
+ *
+ */
+public class TraceTypePreviewer {
+	private HashMap<Integer, String> availableTraces = new HashMap<Integer, String>();
+	
+	public TraceTypePreviewer(File file) {
+		try {
+			StreamFileParser inputFile;
+			inputFile = new StreamFileParser(file);
+			Set<Integer> allTraceSet = inputFile.allTraceType();
+			// dispose it
+			inputFile = null;
+			
+			Enumeration<AbstractPiPlugin> e = PluginRegistry.getInstance().getRegistryEntries();
+			while(e.hasMoreElements()) {
+				AbstractPiPlugin plugin = e.nextElement();
+				if (plugin instanceof ITrace) {
+					ITrace tracePlugin = (ITrace) plugin;
+					if (allTraceSet.contains(tracePlugin.getTraceId())) {
+						availableTraces.put(tracePlugin.getTraceId(), tracePlugin.getTraceName());
+					}
+				}
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		}	
+	}
+	
+	public Map<Integer, String> getAllAvailableTraces() {
+		return availableTraces;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/manager/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,3 @@
+BackgroundLoader.backgroundLoader=BackgroundLoader
+PluginInitialiser.pluginInterfaces=See package com.nokia.carbide.cpp.internal.pi.plugin.model for available plugin interfaces
+PluginRegistry.DuplicatedTraceID=Duplicated trace ID found
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/Binary.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.io.Serializable;
+
+public class Binary implements Serializable
+{
+  private static final long serialVersionUID = 3278912646658026030L;
+	
+  public long startAddress;
+  public int length;
+  public String binaryName;
+  public long offsetToCodeStart = 0;
+  public String type;
+  
+  public Binary(String binaryName)
+  {
+    this.binaryName = binaryName;
+  }
+  
+  public long findOverlapLentghWith(Binary other)
+  {
+	long cSt = other.startAddress;
+	long cEn = other.startAddress+other.length;
+	long bSt = this.startAddress;
+	long bEn = this.startAddress+this.length;
+	long overLap = 0;
+	
+	if (bSt >= cSt && bSt <= cEn)
+	{
+		// starts within the current bin
+		if (bEn <= cEn)
+		{
+			// also ends within the current bin
+			overLap = this.length;
+		}
+		else
+		{
+			// ends outside the current 
+			// binary but starts within it
+			overLap = cEn-bSt;
+		}
+		
+	}
+	else if (bEn >= cSt && bEn <= cEn)
+	{
+		// ends into the current bin
+		// but starts before it
+		overLap = bEn - cSt;
+	}
+	
+	else if (bSt <= cSt && bEn >= cSt)
+	{
+		// starts before and ends after
+		// the current bin
+		overLap = other.length;
+	}
+	
+	return overLap;
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/CusSample.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.awt.Color;
+
+public class CusSample extends GenericSample {
+	
+	private static final long serialVersionUID =-7966954495413654189L;
+	
+	public String name;
+	public double value;
+	public Color color;
+	public String comment;
+	
+	public CusSample(long p_sampleNum, String p_name, double p_value, Color p_color)
+	{
+		sampleSynchTime = p_sampleNum;
+		name = p_name;
+		value = p_value;
+		color = p_color;
+	}
+	
+	public String toString()
+	{
+		String sampleNum = new Long(sampleSynchTime).toString();
+		String valueString = new Double(value).toString();
+		return sampleNum+" "+name+" "+valueString+" "+color.toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/Function.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+import java.io.Serializable;
+
+public class Function implements Serializable
+{
+  private static final long serialVersionUID = -3261268206319782647L;
+	
+  public Binary functionBinary;
+  public Long startAddress;
+  public long offsetFromBinaryStart;
+  public long length;
+  
+  public String functionName;
+
+  public Function(String functionName, Long functionStart, String functionBinary)
+  {
+    this.functionName = functionName;
+    this.startAddress = functionStart;
+    this.functionBinary = new Binary(functionBinary);
+  }
+  
+  public String toString()
+  {
+  	return this.functionName+" @"+Long.toHexString(this.startAddress.intValue()); //$NON-NLS-1$
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/FunctionResolver.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+public interface FunctionResolver 
+{
+	// find the function corresponding to an address
+	public Function findFunctionForAddress(long address);
+
+	// find the function name corresponding to an address
+	public String findFunctionNameForAddress(long address);
+	
+	// find the binary corresponding to an address
+	public Binary findBinaryForAddress(long address);
+
+	// find the binary name corresponding to an address
+	public String findBinaryNameForAddress(long address);
+	
+	// get the brief name of the resolver
+	public String getResolverName();
+	
+	// get a long version of the name of the resolver
+	public String getResolverString();
+	
+	// whether resolution will change anything (e.g., a symbol file resolver with no symbols should return false)
+	public boolean canResolve();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GUITooltips.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,677 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+public class GUITooltips {
+
+	private static String absolutePercentage = Messages.getString("GUITooltips.percentagesInFunctionList"); //$NON-NLS-1$
+	private static String addButton = Messages.getString("GUITooltips.addSelectedToGraph"); //$NON-NLS-1$
+	private static String addObyOrBinary = Messages.getString("GUITooltips.addObyAndIby"); //$NON-NLS-1$
+	private static String bothButton = Messages.getString("GUITooltips.showTotalMemory"); //$NON-NLS-1$
+	private static String browseAnalyseEXEButton = Messages.getString("GUITooltips.locationOfAnalyse.Exe"); //$NON-NLS-1$
+	private static String browseDatButton = Messages.getString("GUITooltips.tempFilesFolder"); //$NON-NLS-1$
+	private static String browseMMCButton = Messages.getString("GUITooltips.MMCCardDriveLetter"); //$NON-NLS-1$
+	private static String browseSymbolButton = Messages.getString("GUITooltips.locationOfROMSymbolFile"); //$NON-NLS-1$
+	private static String callerLoadButton = Messages.getString("GUITooltips.sortByCallerLoad"); //$NON-NLS-1$
+	private static String clearSelectedBinariesButton = Messages.getString("GUITooltips.clearsBinaryListSelections"); //$NON-NLS-1$
+	private static String closeTabButton = Messages.getString("GUITooltips.closeTab"); //$NON-NLS-1$
+	private static String configTab = Messages.getString("GUITooltips.toolConfiguration"); //$NON-NLS-1$
+	private static String deeperKernelAnalyseButton = Messages.getString("GUITooltips.deeperKernelAnalyseButton"); //$NON-NLS-1$
+	private static String endTextField = Messages.getString("GUITooltips.setEndTime"); //$NON-NLS-1$
+	private static String fileNewButton = Messages.getString("GUITooltips.combineTraceAndStreamFiles"); //$NON-NLS-1$
+	private static String functionAnalyseButton = Messages.getString("GUITooltips.doSelectedFunctionAnalysis"); //$NON-NLS-1$
+	private static String heapButton = Messages.getString("GUITooltips.showHeapMemory"); //$NON-NLS-1$
+	private static String kernelAnalyseButton = Messages.getString("GUITooltips.useOnlyWithKRNFile"); //$NON-NLS-1$
+	private static String linkedFunctionAnalyseButton = Messages.getString("GUITooltips.useOnlyWithCallTrace"); //$NON-NLS-1$
+	private static String loadAlreadyCreatedAnalysisButton = Messages.getString("GUITooltips.openExistingBapFile"); //$NON-NLS-1$
+	private static String minusButton = Messages.getString("GUITooltips.zoomIn"); //$NON-NLS-1$
+	private static String minusMinusButton = Messages.getString("GUITooltips.showSelection"); //$NON-NLS-1$
+	private static String newFileAnalysisButton = Messages.getString("GUITooltips.openTraceFilesFromFileSystem"); //$NON-NLS-1$
+	private static String openAllFilesButton = Messages.getString("GUITooltips.openTraceFilesFromLocation"); //$NON-NLS-1$
+	private static String openCusFileButton = Messages.getString("GUITooltips.openCustomTraceFile"); //$NON-NLS-1$
+	private static String openDSPFileButton = Messages.getString("GUITooltips.openDSPTraceFile"); //$NON-NLS-1$
+	private static String openGFCFileButton = Messages.getString("GUITooltips.openCallTraceFile"); //$NON-NLS-1$
+	private static String openGPPFileButton = Messages.getString("GUITooltips.openAddressThreadTraceFile"); //$NON-NLS-1$
+	private static String openISAFileButton = Messages.getString("GUITooltips.openISAMapFile"); //$NON-NLS-1$
+	private static String openITTFileButton = Messages.getString("GUITooltips.openInstrTraceFile"); //$NON-NLS-1$
+//	private static String openKRNFileButton = "Open KRN trace file, enables kernel analysis option";
+	private static String openMEMFileButton = Messages.getString("GUITooltips.openMemoryPriorityTraceFile"); //$NON-NLS-1$
+	private static String openTIPFileButton = Messages.getString("GUITooltips.openTIPTraceFile"); //$NON-NLS-1$
+	private static String plusButton = Messages.getString("GUITooltips.zoomOut"); //$NON-NLS-1$
+	private static String plusPlusButton = Messages.getString("GUITooltips.showGraph"); //$NON-NLS-1$
+	private static String previousSelectionButton = Messages.getString("GUITooltips.goBack"); //$NON-NLS-1$
+	private static String readMMCCardButton = Messages.getString("GUITooltips.openTraceFilesFromMMCCard"); //$NON-NLS-1$
+	private static String recolorButton = Messages.getString("GUITooltips.recolor"); //$NON-NLS-1$
+	private static String recursiveLoadButton = Messages.getString("GUITooltips.sortByRecursiveLoad"); //$NON-NLS-1$
+	private static String removeButton = Messages.getString("GUITooltips.removeSelectedFromGraph"); //$NON-NLS-1$
+	private static String removeObyOrBinary = Messages.getString("GUITooltips.removeSelectedFromList"); //$NON-NLS-1$
+	private static String renameTab = Messages.getString("GUITooltips.renameTab"); //$NON-NLS-1$
+	private static String reportButton = Messages.getString("GUITooltips.generateReportForInterval"); //$NON-NLS-1$
+	private static String rofsSettingsButton = Messages.getString("GUITooltips.configureInstrTrace"); //$NON-NLS-1$
+	private static String saveAnalysisButton = Messages.getString("GUITooltips.saveAnalysis"); //$NON-NLS-1$
+	private static String saveConfiguration = Messages.getString("GUITooltips.saveConfiguration"); //$NON-NLS-1$
+	private static String saveIttSettings = Messages.getString("GUITooltips.saveSettings"); //$NON-NLS-1$
+	private static String saveListScreenshotButton = Messages.getString("GUITooltips.saveListScreenshot"); //$NON-NLS-1$
+	private static String saveScreenshotButton = Messages.getString("GUITooltips.saveGraphScreenshot"); //$NON-NLS-1$
+	private static String selectButton = Messages.getString("GUITooltips.selectTimeInterval"); //$NON-NLS-1$
+	private static String selectionTabButton = Messages.getString("GUITooltips.createNewAnalysis"); //$NON-NLS-1$
+	private static String serialAnalyseButton = Messages.getString("GUITooltips.getTracesViaSerialPort"); //$NON-NLS-1$
+	private static String setOriginalThreads = Messages.getString("GUITooltips.selectAddressThreadItems"); //$NON-NLS-1$
+	private static String setReleaseRootLetter = Messages.getString("GUITooltips.rootLetterOfEpoc32Folder"); //$NON-NLS-1$
+	private static String showFunctionInformationButton = Messages.getString("GUITooltips.showSamplesAndStatistics"); //$NON-NLS-1$
+	private static String stackButton = Messages.getString("GUITooltips.showStackMemory"); //$NON-NLS-1$
+	private static String startTextField = Messages.getString("GUITooltips.setStartTime"); //$NON-NLS-1$
+	private static String threadList = Messages.getString("GUITooltips.selectThreads"); //$NON-NLS-1$
+	private static String totalLoadButton = Messages.getString("GUITooltips.sortByTotalLoad"); //$NON-NLS-1$
+	private static String usePrimarilyItt = Messages.getString("GUITooltips.resolveByITTFirst"); //$NON-NLS-1$
+	private static String usePrimarilySymbol = Messages.getString("GUITooltips.resolveBySymbolFileFirst"); //$NON-NLS-1$
+	private static String visualiserPanel = Messages.getString("GUITooltips.dragMouse"); //$NON-NLS-1$
+	private static String xminusDeepButton = Messages.getString("GUITooltips.xminusDeepButton"); //$NON-NLS-1$
+	private static String xplusDeepButton = Messages.getString("GUITooltips.xplusDeepButton"); //$NON-NLS-1$
+	private static String yminusButton = Messages.getString("GUITooltips.yminusButton"); //$NON-NLS-1$
+	private static String yminusDeepButton = Messages.getString("GUITooltips.yminusDeepButton"); //$NON-NLS-1$
+	private static String yminusminusButton = Messages.getString("GUITooltips.yminusminusButton"); //$NON-NLS-1$
+	private static String yplusButton = Messages.getString("GUITooltips.yplusButton"); //$NON-NLS-1$
+	private static String yplusDeepButton = Messages.getString("GUITooltips.yplusDeepButton"); //$NON-NLS-1$
+	private static String yplusplusButton = Messages.getString("GUITooltips.yplusplusButton"); //$NON-NLS-1$
+
+	private static boolean tooltipsOn = true;
+
+	public GUITooltips(){}
+	
+	// set whether to return a message or a null for the tooltips value
+	public static void setTooltipsOn(boolean tooltipsOn){
+		GUITooltips.tooltipsOn = tooltipsOn;
+	}
+
+	/**
+	 * return a message or null, depending on tooltipsOn
+	 */
+
+	public static String getAbsolutePercentage() {
+		return tooltipsOn ? absolutePercentage : null;
+	}
+
+	public static String getAddObyOrBinary() {
+		return tooltipsOn ? addObyOrBinary : null;
+	}
+
+	public static String getAddButton() {
+		return tooltipsOn ? addButton : null;
+	}
+
+	public static String getBothButton() {
+		return tooltipsOn ? bothButton : null;
+	}
+
+	public static String getBrowseAnalyseEXEButton() {
+		return tooltipsOn ? browseAnalyseEXEButton : null;
+	}
+
+	public static String getBrowseDatButton() {
+		return tooltipsOn ? browseDatButton : null;
+	}
+
+	public static String getBrowseMMCButton() {
+		return tooltipsOn ? browseMMCButton : null;
+	}
+
+	public static String getBrowseSymbolButton() {
+		return tooltipsOn ? browseSymbolButton : null;
+	}
+
+	public static String getCallerLoadButton() {
+		return tooltipsOn ? callerLoadButton : null;
+	}
+
+	public static String getClearSelectedBinariesButton() {
+		return tooltipsOn ? clearSelectedBinariesButton : null;
+	}
+
+	public static String getCloseTabButton() {
+		return tooltipsOn ? closeTabButton : null;
+	}
+
+	public static String getConfigTab() {
+		return tooltipsOn ? configTab : null;
+	}
+
+	public static String getDeeperKernelAnalyseButton() {
+		return tooltipsOn ? deeperKernelAnalyseButton : null;
+	}
+
+	public static String getEndTextField() {
+		return tooltipsOn ? endTextField : null;
+	}
+
+	public static String getFileNewButton() {
+		return tooltipsOn ? fileNewButton : null;
+	}
+
+	public static String getFunctionAnalyseButton() {
+		return tooltipsOn ? functionAnalyseButton : null;
+	}
+
+	public static String getHeapButton() {
+		return tooltipsOn ? heapButton : null;
+	}
+
+	public static String getKernelAnalyseButton() {
+		return tooltipsOn ? kernelAnalyseButton : null;
+	}
+
+	public static String getLinkedFunctionAnalyseButton() {
+		return tooltipsOn ? linkedFunctionAnalyseButton : null;
+	}
+	
+	public static String getLoadAlreadyCreatedAnalysisButton() {
+		return tooltipsOn ? loadAlreadyCreatedAnalysisButton : null;
+	}
+
+	public static String getMinusButton() {
+		return tooltipsOn ? minusButton : null;
+	}
+
+	public static String getMinusMinusButton() {
+		return tooltipsOn ? minusMinusButton : null;
+	}
+
+	public static String getNewFileAnalysisButton() {
+		return tooltipsOn ? newFileAnalysisButton : null;
+	}
+
+	public static String getOpenAllFilesButton() {
+		return tooltipsOn ? openAllFilesButton : null;
+	}
+	
+	public static String getOpenCusFileButton() {
+		return tooltipsOn ? openCusFileButton : null;
+	}	
+
+	public static String getOpenDSPFileButton() {
+		return tooltipsOn ? openDSPFileButton : null;
+	}
+
+	public static String getOpenGFCFileButton() {
+		return tooltipsOn ? openGFCFileButton : null;
+	}
+
+	public static String getOpenGPPFileButton() {
+		return tooltipsOn ? openGPPFileButton : null;
+	}
+	
+	public static String getOpenISAFileButton() {
+		return tooltipsOn ? openISAFileButton : null;
+	}
+
+	public static String getOpenITTFileButton() {
+		return tooltipsOn ? openITTFileButton : null;
+	}
+	
+	//kernel analysis is not planned
+	/*
+	public static String getOpenKRNFileButton() {
+		return tooltipsOn ? openKRNFileButton : null;
+	}*/
+
+	public static String getOpenMEMFileButton() {
+		return tooltipsOn ? openMEMFileButton : null;
+	}
+
+	public static String getOpenTIPFileButton() {
+		return tooltipsOn ? openTIPFileButton : null;
+	}
+
+	public static String getPlusButton() {
+		return tooltipsOn ? plusButton : null;
+	}
+
+	public static String getPlusPlusButton() {
+		return tooltipsOn ? plusPlusButton : null;
+	}
+
+	public static String getPreviousSelectionButton() {
+		return tooltipsOn ? previousSelectionButton : null;
+	}
+
+	public static String getReadMMCCardButton() {
+		return tooltipsOn ? readMMCCardButton : null;
+	}
+
+	public static String getRecolorButton() {
+		return tooltipsOn ? recolorButton : null;
+	}
+
+	public static String getRecursiveLoadButton() {
+		return tooltipsOn ? recursiveLoadButton : null;
+	}
+
+	public static String getRemoveObyOrBinary() {
+		return tooltipsOn ? removeObyOrBinary : null;
+	}
+
+	public static String getRemoveButton() {
+		return tooltipsOn ? removeButton : null;
+	}
+
+	public static String getRenameTab()
+    {
+	   return tooltipsOn ? renameTab : null;
+    }
+
+	public static String getReportButton() {
+		return tooltipsOn ? reportButton : null;
+	}
+
+	public static String getRofsSettingsButton() {
+		return tooltipsOn ? rofsSettingsButton : null;
+	}
+
+	public static String getSaveAnalysisButton() {
+		return tooltipsOn ? saveAnalysisButton : null;
+	}
+
+	public static String getSaveConfiguration() {
+		return tooltipsOn ? saveConfiguration : null;
+	}
+
+	public static String getSaveIttSettings() {
+		return tooltipsOn ? saveIttSettings : null;
+	}
+
+	public static String getSaveListScreenshotButton() {
+		return tooltipsOn ? saveListScreenshotButton : null;
+	}
+
+	public static String getSaveScreenshotButton() {
+		return tooltipsOn ? saveScreenshotButton : null;
+	}
+
+	public static String getSelectButton() {
+		return tooltipsOn ? selectButton : null;
+	}
+
+	public static String getSelectionTabButton() {
+		return tooltipsOn ? selectionTabButton : null;
+	}
+
+	public static String getSerialAnalyseButton() {
+		return tooltipsOn ? serialAnalyseButton : null;
+	}
+
+	public static String getSetOriginalThreads() {
+		return tooltipsOn ? setOriginalThreads : null;
+	}
+
+	public static String getSetReleaseRootLetter() {
+		return tooltipsOn ? setReleaseRootLetter : null;
+	}
+
+	public static String getShowFunctionInformationButton() {
+		return tooltipsOn ? showFunctionInformationButton : null;
+	}
+
+	public static String getStackButton() {
+		return tooltipsOn ? stackButton : null;
+	}
+
+	public static String getStartTextField() {
+		return tooltipsOn ? startTextField : null;
+	}
+
+	public static String getThreadList() {
+		return tooltipsOn ? threadList : null;
+	}
+
+	public static String getTotalLoadButton() {
+		return tooltipsOn ? totalLoadButton : null;
+	}
+
+	public static String getUsePrimarilyItt() {
+		return tooltipsOn ? usePrimarilyItt : null;
+	}
+
+	public static String getUsePrimarilySymbol() {
+		return tooltipsOn ? usePrimarilySymbol : null;
+	}
+
+	public static String getVisualiserPanel() {
+		return tooltipsOn ? visualiserPanel : null;
+	}
+
+	public static String getXminusDeepButton() {
+		return tooltipsOn ? xminusDeepButton : null;
+	}
+
+	public static String getXplusDeepButton() {
+		return tooltipsOn ? xplusDeepButton : null;
+	}
+
+	public static String getYminusButton() {
+		return tooltipsOn ? yminusButton : null;
+	}
+
+	public static String getYminusDeepButton() {
+		return tooltipsOn ? yminusDeepButton : null;
+	}
+
+	public static String getYminusminusButton() {
+		return tooltipsOn ? yminusminusButton : null;
+	}
+
+	public static String getYplusButton() {
+		return tooltipsOn ? yplusButton : null;
+	}
+
+	public static String getYplusDeepButton() {
+		return tooltipsOn ? yplusDeepButton : null;
+	}
+
+	public static String getYplusplusButton() {
+		return tooltipsOn ? yplusplusButton : null;
+	}
+
+	/**
+	 *  Set tooltip strings
+	 */
+
+	public static void setAbsolutePercentage(String absolutePercentage) {
+		GUITooltips.absolutePercentage = absolutePercentage;
+	}
+
+	public static void setAddObyOrBinary(String addObyOrBinary) {
+		GUITooltips.addObyOrBinary = addObyOrBinary;
+	}
+
+	public static void setAddButton(String addButton) {
+		GUITooltips.addButton = addButton;
+	}
+
+	public static void setBothButton(String bothButton) {
+		GUITooltips.bothButton = bothButton;
+	}
+
+	public static void setBrowseAnalyseEXEButton(String browseAnalyseEXEButton) {
+		GUITooltips.browseAnalyseEXEButton = browseAnalyseEXEButton;
+	}
+
+	public static void setBrowseDatButton(String browseDatButton) {
+		GUITooltips.browseDatButton = browseDatButton;
+	}
+
+	public static void setBrowseMMCButton(String browseMMCButton) {
+		GUITooltips.browseMMCButton = browseMMCButton;
+	}
+
+	public static void setBrowseSymbolButton(String browseSymbolButton) {
+		GUITooltips.browseSymbolButton = browseSymbolButton;
+	}
+
+	public static void setCallerLoadButton(String callerLoadButton) {
+		GUITooltips.callerLoadButton = callerLoadButton;
+	}
+
+	public static void setClearSelectedBinariesButton(
+			String clearSelectedBinariesButton) {
+		GUITooltips.clearSelectedBinariesButton = clearSelectedBinariesButton;
+	}
+
+	public static void setCloseTabButton(String closeTabButton) {
+		GUITooltips.closeTabButton = closeTabButton;
+	}
+
+	public static void setConfigTab(String configTab) {
+		GUITooltips.configTab = configTab;
+	}
+
+	public static void setDeeperKernelAnalyseButton(
+			String deeperKernelAnalyseButton) {
+		GUITooltips.deeperKernelAnalyseButton = deeperKernelAnalyseButton;
+	}
+
+	public static void setEndTextField(String endTextField) {
+		GUITooltips.endTextField = endTextField;
+	}
+
+	public static void setFileNewButton(String fileNewButton) {
+		GUITooltips.fileNewButton = fileNewButton;
+	}
+
+	public static void setFunctionAnalyseButton(String functionAnalyseButton) {
+		GUITooltips.functionAnalyseButton = functionAnalyseButton;
+	}
+
+	public static void setHeapButton(String heapButton) {
+		GUITooltips.heapButton = heapButton;
+	}
+
+	public static void setKernelAnalyseButton(String kernelAnalyseButton) {
+		GUITooltips.kernelAnalyseButton = kernelAnalyseButton;
+	}
+
+	public static void setLinkedFunctionAnalyseButton(String linkedFunctionAnalyseButton) {
+		GUITooltips.linkedFunctionAnalyseButton = linkedFunctionAnalyseButton;
+	}
+
+	public static void setLoadAlreadyCreatedAnalysisButton(String loadAlreadyCreatedAnalysisButton) {
+		GUITooltips.loadAlreadyCreatedAnalysisButton = loadAlreadyCreatedAnalysisButton;
+	}
+
+	public static void setMinusButton(String minusButton) {
+		GUITooltips.minusButton = minusButton;
+	}
+
+	public static void setMinusMinusButton(String minusMinusButton) {
+		GUITooltips.minusMinusButton = minusMinusButton;
+	}
+
+	public static void setNewFileAnalysisButton(String newFileAnalysisButton) {
+		GUITooltips.newFileAnalysisButton = newFileAnalysisButton;
+	}
+
+	public static void setOpenAllFilesButton(String openAllFilesButton) {
+		GUITooltips.openAllFilesButton = openAllFilesButton;
+	}
+
+	public static void setOpenCusFileButton(String openCusFileButton) {
+		GUITooltips.openCusFileButton = openCusFileButton;
+	}	
+
+	public static void setOpenDSPFileButton(String openDSPFileButton) {
+		GUITooltips.openDSPFileButton = openDSPFileButton;
+	}
+
+	public static void setOpenGFCFileButton(String openGFCFileButton) {
+		GUITooltips.openGFCFileButton = openGFCFileButton;
+	}
+
+	public static void setOpenGPPFileButton(String openGPPFileButton) {
+		GUITooltips.openGPPFileButton = openGPPFileButton;
+	}
+
+	public static void setOpenISAFileButton(String openISAFileButton) {
+		GUITooltips.openISAFileButton = openISAFileButton;
+	}
+
+	public static void setOpenITTFileButton(String openITTFileButton) {
+		GUITooltips.openITTFileButton = openITTFileButton;
+	}
+
+	//kernel analysis is not planned
+	/*
+	public static void setOpenKRNFileButton(String openKRNFileButton) {
+		GUITooltips.openKRNFileButton = openKRNFileButton;
+	}*/
+
+	public static void setOpenMEMFileButton(String openMEMFileButton) {
+		GUITooltips.openMEMFileButton = openMEMFileButton;
+	}
+
+	public static void setOpenTIPFileButton(String openTIPFileButton) {
+		GUITooltips.openTIPFileButton = openTIPFileButton;
+	}
+
+	public static void setPlusButton(String plusButton) {
+		GUITooltips.plusButton = plusButton;
+	}
+
+	public static void setPlusPlusButton(String plusPlusButton) {
+		GUITooltips.plusPlusButton = plusPlusButton;
+	}
+
+	public static void setPreviousSelectionButton(String previousSelectionButton) {
+		GUITooltips.previousSelectionButton = previousSelectionButton;
+	}
+
+	public static void setReadMMCCardButton(String readMMCCardButton) {
+		GUITooltips.readMMCCardButton = readMMCCardButton;
+	}
+
+	public static void setRecolorButton(String recolorButton) {
+		GUITooltips.recolorButton = recolorButton;
+	}
+
+	public static void setRecursiveLoadButton(String recursiveLoadButton) {
+		GUITooltips.recursiveLoadButton = recursiveLoadButton;
+	}
+
+	public static void setRemoveObyOrBinary(String removeObyOrBinary) {
+		GUITooltips.removeObyOrBinary = removeObyOrBinary;
+	}
+
+	public static void setRemoveButton(String removeButton) {
+		GUITooltips.removeButton = removeButton;
+	}
+
+	public static void setRenameTab(String renameTab)
+    {
+        GUITooltips.renameTab = renameTab;
+    }
+
+	public static void setReportButton(String reportButton) {
+		GUITooltips.reportButton = reportButton;
+	}
+
+    public static void setRofsSettingsButton(String rofsSettingsButton) {
+		GUITooltips.rofsSettingsButton = rofsSettingsButton;
+	}
+
+	public static void setSaveAnalysisButton(String saveAnalysisButton) {
+		GUITooltips.saveAnalysisButton = saveAnalysisButton;
+	}
+
+	public static void setSaveConfiguration(String saveConfiguration) {
+		GUITooltips.saveConfiguration = saveConfiguration;
+	}
+
+	public static void setSaveIttSettings(String saveIttSettings) {
+		GUITooltips.saveIttSettings = saveIttSettings;
+	}
+
+	public static void setSaveListScreenshotButton(String saveListScreenshotButton) {
+		GUITooltips.saveListScreenshotButton = saveListScreenshotButton;
+	}
+
+	public static void setSaveScreenshotButton(String saveScreenshotButton) {
+		GUITooltips.saveScreenshotButton = saveScreenshotButton;
+	}
+
+	public static void setSelectButton(String selectButton) {
+		GUITooltips.selectButton = selectButton;
+	}
+
+	public static void setSelectionTabButton(String selectionTabButton) {
+		GUITooltips.selectionTabButton = selectionTabButton;
+	}
+
+	public static void setSerialAnalyseButton(String serialAnalyseButton) {
+		GUITooltips.serialAnalyseButton = serialAnalyseButton;
+	}
+
+	public static void setSetOriginalThreads(String setOriginalThreads) {
+		GUITooltips.setOriginalThreads = setOriginalThreads;
+	}
+
+	public static void setSetReleaseRootLetter(String setReleaseRootLetter) {
+		GUITooltips.setReleaseRootLetter = setReleaseRootLetter;
+	}
+
+	public static void setShowFunctionInformationButton(String showFunctionInformationButton) {
+		GUITooltips.showFunctionInformationButton = showFunctionInformationButton;
+	}
+
+	public static void setStackButton(String stackButton) {
+		GUITooltips.stackButton = stackButton;
+	}
+
+	public static void setStartTextField(String startTextField) {
+		GUITooltips.startTextField = startTextField;
+	}
+
+	public static void setThreadList(String threadList) {
+		GUITooltips.threadList = threadList;
+	}
+
+	public static void setTotalLoadButton(String totalLoadButton) {
+		GUITooltips.totalLoadButton = totalLoadButton;
+	}
+
+	public static void setUsePrimarilyItt(String usePrimarilyItt) {
+		GUITooltips.usePrimarilyItt = usePrimarilyItt;
+	}
+
+	public static void setUsePrimarilySymbol(String usePrimarilySymbol) {
+		GUITooltips.usePrimarilySymbol = usePrimarilySymbol;
+	}
+
+	public static void setVisualiserPanel(String visualiserPanel) {
+		GUITooltips.visualiserPanel = visualiserPanel;
+	}
+
+	public static void setXminusDeepButton(String xminusDeepButton) {
+		GUITooltips.xminusDeepButton = xminusDeepButton;
+	}
+
+	public static void setXplusDeepButton(String xplusDeepButton) {
+		GUITooltips.xplusDeepButton = xplusDeepButton;
+	}
+
+	public static void setYminusButton(String yminusButton) {
+		GUITooltips.yminusButton = yminusButton;
+	}
+
+	public static void setYminusDeepButton(String yminusDeepButton) {
+		GUITooltips.yminusDeepButton = yminusDeepButton;
+	}
+
+	public static void setYminusminusButton(String yminusminusButton) {
+		GUITooltips.yminusminusButton = yminusminusButton;
+	}
+
+	public static void setYplusButton(String yplusButton) {
+		GUITooltips.yplusButton = yplusButton;
+	}
+
+	public static void setYplusDeepButton(String yplusDeepButton) {
+		GUITooltips.yplusDeepButton = yplusDeepButton;
+	}
+
+	public static void setYplusplusButton(String yplusplusButton) {
+		GUITooltips.yplusplusButton = yplusplusButton;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericEvent.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.io.Serializable;
+
+public abstract class GenericEvent implements Serializable
+{
+	static final long serialVersionUID = -7891790813095786064L;
+	
+	public double eventTime;
+    
+    //time in milliseconds
+	public GenericEvent(double time)
+	{
+		this.eventTime = time;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericEventTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+public abstract class GenericEventTrace extends GenericTrace
+{
+	private Vector<GenericEvent> events;
+	
+	static final long serialVersionUID = -5793331074508392029L;
+	
+	public GenericEventTrace()
+	{
+		this.events = new Vector<GenericEvent>();
+	}
+	
+	public void addEvent(GenericEvent e)
+	{
+		this.events.add(e);
+	}
+	
+	public Vector<GenericEvent> getEvents()
+	{
+		return this.events;
+	}
+    
+    public Vector<GenericEvent> getEventsInsideTimePeriod(double start, double end)
+    {
+        Enumeration<GenericEvent> eEnum = events.elements();
+        Vector<GenericEvent> okEvents = new Vector<GenericEvent>();
+          
+        while(eEnum.hasMoreElements())
+        {
+            GenericEvent e = eEnum.nextElement();
+            if (e.eventTime >= start)
+            {
+                if (e.eventTime <= end)
+                {
+                    okEvents.add(e);
+                }
+            }
+        }
+        return okEvents;
+    }
+    
+    public double getTimeForFirstEvent()
+    {
+        GenericEvent e = events.firstElement();
+        return e.eventTime;
+        
+    }
+    
+    public double getTimeForLastEvent()
+    {
+        GenericEvent e = events.lastElement();
+        return e.eventTime;
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericSample.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.io.Serializable;
+
+public abstract class GenericSample implements Serializable
+{
+	  private static final long serialVersionUID =-2599062307182141301L;
+	
+	  public long sampleSynchTime;
+	  
+	  public GenericSample()
+	  {
+	  } 
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericSampleWithFunctions.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+public abstract class GenericSampleWithFunctions extends GenericSample 
+{
+	  private static final long serialVersionUID = -1866320305622783242L;
+	  
+	  public abstract void resolveFunction(FunctionResolver res);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericSampledTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+public abstract class GenericSampledTrace extends GenericTrace
+{
+	private static final long serialVersionUID = -5030416972125713453L;
+	
+	public Vector samples;
+	
+	public GenericSampledTrace()
+	{
+	  this.samples = new Vector();
+	}
+	
+	public void addSample(GenericSample sample)
+	{
+	  this.samples.add(sample);
+	}
+	
+	public Enumeration getSamples()
+	{
+	  return samples.elements();
+	}
+	
+	public GenericSample getSample(int number)
+	{
+	  return (GenericSample)this.samples.elementAt(number);
+	}
+	
+	public Vector<GenericSample> getSamplesInsideTimePeriod(long start, long end)
+	{
+		Enumeration sEnum = samples.elements();
+		Vector<GenericSample> okSamples = new Vector<GenericSample>();
+		
+		while(sEnum.hasMoreElements())
+		{
+			GenericSample s = (GenericSample)sEnum.nextElement();
+			if (s.sampleSynchTime >= start)
+			{
+				if (s.sampleSynchTime <= end)
+				{
+					okSamples.add(s);
+				}
+			}
+		}
+		
+		return okSamples;
+	}
+	
+	public GenericSample[] getSamplesForTime(long time)
+	{
+		// start the search from the middle of the sample set
+		long location = this.samples.size() / 2;
+		
+		// next, add or remove 1/4 of the length of the sample set
+		int div = 4;
+		
+		// boolean value indicating that the search proceeds now one step at a time
+		boolean saturated = false;
+		
+		// search algorithm, proceed until a value is found or 
+		// reached the boundaries of the search area
+
+		// note that the sample numbers MUST increase with growing
+		// indices within the samples vector in order for this 
+		// algorithm to work!
+		while (true)
+		{
+			// take the sample from the location
+			GenericSample s = (GenericSample)samples.elementAt((int)location);
+			
+			// if the searched value is larger than the value at the proposed location
+			// increment the proposed location with the length of the data set divided
+			// by the divisor
+			if (s.sampleSynchTime < time)
+			{
+				if (!saturated)
+				{
+					int change = this.samples.size() / div;
+					if (change >= 1)
+					{
+						location += change;
+						div *= 2;
+					}
+					else 
+					{
+						saturated = true;
+					}
+				}
+				else
+				{
+					// already saturated, go one step at a time
+					location++;
+				}				
+			}
+			// similarly, decrement the proposed location 
+			// if the value is smaller than the searched value
+			else if (s.sampleSynchTime > time)
+			{
+				if (!saturated)
+				{					
+					int change = this.samples.size() / div;
+					if (change >= 1)
+					{
+						location -= change;
+						div *= 2;
+					}
+					else 
+					{
+						saturated = true;
+					}
+				}
+				else
+				{
+					// already saturated, go one step at a time
+					location--;
+				}
+			}
+			else if (s.sampleSynchTime == time)
+			{
+				return this.getSamplesWithSameTimeFrom(location);
+			}
+			
+			// reached the end of the sample set without a match
+			if (location < 0 || location >= this.samples.size())
+				return null;
+		}
+		
+	}
+	
+	private GenericSample[] getSamplesWithSameTimeFrom(long location)
+	{
+		long sameTime = ((GenericSample)samples.elementAt((int)location)).sampleSynchTime;
+		int lowBound = (int)location;
+		int highBound = (int)location;
+		
+		if (lowBound-1 >=0)
+		{	
+			// go backwards as long as there are samples with the same samplenumber
+			while ( ((GenericSample)samples.elementAt(lowBound - 1)).sampleSynchTime == sameTime 
+					&& (lowBound - 1) >= 0)
+			{
+				lowBound--;
+			}
+		}
+		
+		if (highBound + 1 < this.samples.size())
+		{	
+			// go backwards as long as there are samples with the same samplenumber
+			while ( ((GenericSample)samples.elementAt(highBound + 1)).sampleSynchTime == sameTime 
+					&& (highBound + 1) < this.samples.size())
+			{
+				highBound++;
+			}
+		}
+		
+		GenericSample[] sa = new GenericSample[highBound - lowBound + 1];
+		for (int i = 0; i < sa.length; i++)
+		{
+			sa[i] = (GenericSample)samples.elementAt(lowBound + i);
+		}
+		
+		return sa;
+	}
+	
+	public int getSampleAmount()
+	{
+	  return this.samples.size();
+	}
+	
+	public int getFirstSampleNumber()
+	{
+		if (this.samples.size() > 0)
+			return (int)this.getSample(0).sampleSynchTime;
+		else
+			return 0;
+	}
+	
+	public int getLastSampleNumber()
+	{
+		if (this.samples.size() > 0)
+			return (int)((GenericSample)this.samples.lastElement()).sampleSynchTime;
+		else
+			return 0;
+	}
+	
+	public String toString()
+	{
+		Enumeration sEnum = this.getSamples();
+	  	Vector strings = new Vector();
+	  	int totalLength = 0;
+	  	while(sEnum.hasMoreElements())
+	  	{	
+	  		GenericSample s = (GenericSample)sEnum.nextElement();
+	  		String uus = s.toString() + "\n"; //$NON-NLS-1$
+	  		totalLength += uus.getBytes().length;
+	  		strings.add(uus);
+	  	}
+	  	
+	  	System.out.println(Messages.getString("GenericSampledTrace.totalLength") + totalLength); //$NON-NLS-1$
+	  	byte[] bytes = new byte[totalLength];
+	  	sEnum = strings.elements();
+	  	int index = 0;
+	  	while(sEnum.hasMoreElements())
+	  	{
+	  		String s = (String)sEnum.nextElement();
+	  		byte[] sB = s.getBytes();
+	  		for (int i = index; i < index + sB.length; i++)
+	  		{
+	  			bytes[i] = sB[i - index];
+	  		}
+	  		index += sB.length;
+	  	}
+	  	
+	  	String total = new String(bytes);
+	  	return total;
+	  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericSampledTraceWithFunctions.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+
+import java.util.Enumeration;
+
+public abstract class GenericSampledTraceWithFunctions extends GenericSampledTrace implements RefinableTrace
+{
+	private static final long serialVersionUID = 8246297583039760015L;
+
+	public void refineTrace(FunctionResolver resolver)
+	{
+		if (!resolver.canResolve())
+			return;
+
+		Enumeration sEnum = this.samples.elements();
+		while (sEnum.hasMoreElements())
+		{
+			GenericSampleWithFunctions s = (GenericSampleWithFunctions)sEnum.nextElement();
+			s.resolveFunction(resolver);
+		}
+	}
+
+	public void finalizeTrace() {
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericThread.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: 
+ *
+ */
+
+/*
+ * GenericThread.java
+ */
+package com.nokia.carbide.cpp.internal.pi.model;
+
+import java.io.Serializable;
+
+public class GenericThread implements Serializable
+{
+	private static final long serialVersionUID = 4939943291132317194L;
+	
+	public Integer threadId;
+	public String threadName;
+	public Integer processId;
+	public String processName;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/GenericTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.io.Serializable;
+
+public class GenericTrace implements Serializable
+{
+	static final long serialVersionUID = -7635675212966937258L;
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.model.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ParsedTraceData.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+public class ParsedTraceData 
+{
+	public GenericTrace traceData;
+	public FunctionResolver[] functionResolvers;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/Parser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.io.File;
+
+public abstract class Parser {
+
+    protected String traceVersion;    
+	private boolean stateOk = true;
+
+	public Parser()
+	{
+	}
+		
+	public abstract ParsedTraceData parse(File file) throws Exception;
+		
+	public boolean isStateOk() 
+	{
+		return stateOk;
+	}
+	
+	public void setStateOk(boolean flag)
+	{
+		stateOk = flag;
+	}
+	
+	public String getTraceVersion()
+	{
+	    return traceVersion;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/PiItemType.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import org.eclipse.swt.graphics.Image;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IPiItem;
+
+
+public abstract class PiItemType
+	implements Comparable
+{
+	//// Constant Types ////
+	public static final PiItemType UNKNOWN =
+		new PiItemType(Messages.getString("PiItemType.unknown"), Messages.getString("PiItemType.unknown"), 0) {   //$NON-NLS-1$ //$NON-NLS-2$
+			public Image getImage() {
+				return null;
+			}
+			public IPiItem newFavorite(Object Obj) {
+				return null;
+			}
+			public IPiItem loadFavorite(String info) {
+				return null;
+			}
+			public int compareTo(Object arg0) {
+				return 0;
+			}
+	};
+	
+	//// Type Lookup ///
+	private static final PiItemType[] TYPES = {
+		UNKNOWN,
+	};
+	
+	public static PiItemType[] getTypes() {
+		return TYPES;
+	}
+	
+	//// Instance Members
+	
+	private final String id;
+	private final String printName;
+	private final int ordinal;
+	
+	private PiItemType(String id, String name, int position) {
+		this.id        = id;
+		this.ordinal   = position;
+		this.printName = name;
+	}
+	
+	public int compareTo(Object arg) {
+		return this.ordinal
+			- ((PiItemType) arg).ordinal;
+	}
+	
+	public String getID() {
+		return id;
+	}
+	
+	public String getName() {
+		return printName;
+	}
+	
+	public abstract Image getImage();
+	public abstract IPiItem newFavorite(Object obj);
+	public abstract IPiItem loadFavorite(String info);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/PiManager.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.XMLMemento;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
+import com.nokia.carbide.cpp.internal.pi.interfaces.IPiItem;
+import com.nokia.carbide.cpp.pi.PiPlugin;
+
+
+
+public class PiManager {
+	private static PiManager manager;
+	private Collection<IPiItem> favorites;
+	private ArrayList<PiManagerListener> listeners = new ArrayList<PiManagerListener>();
+	
+	private PiManager() {
+	}
+	
+   ///////////// IPiItem accessors ///////////////////////
+
+	public static PiManager getManager() {
+		if (manager == null)
+			manager = new PiManager();
+		return manager;
+	}
+	
+	public void synchronizePI() {
+		PIChangeEvent.action("synchronise"); //$NON-NLS-1$
+	}
+
+	public IPiItem[] getFavorites() {
+		if (favorites == null)
+			loadFavorites();
+		return favorites.toArray(
+			new IPiItem[favorites.size()]);
+	}
+	
+	public IPiItem newFavoriteFor(Object obj) {
+		PiItemType[] types =
+			PiItemType.getTypes();
+		for (int i = 0; i < types.length; i++) {
+			IPiItem item = types[i].newFavorite(obj);
+			if (item != null)
+				return item;
+		}
+		return null;
+	}
+
+	public IPiItem[] newFavoritesFor(Iterator iter) {
+		if (iter == null)
+			return IPiItem.NONE;
+		Collection<IPiItem> items = new HashSet<IPiItem>(20);
+		while (iter.hasNext()) {
+			IPiItem item =
+				newFavoriteFor((Object) iter.next());
+			if (item != null)
+				items.add(item);
+		}
+		return (IPiItem[]) items.toArray(
+			new IPiItem[items.size()]);
+	}
+
+	public IPiItem[] newFavoritesFor(Object[] objects) {
+		if (objects == null)
+			return IPiItem.NONE;
+		return newFavoritesFor(
+			Arrays.asList(objects).iterator());
+	}
+	
+	public IPiItem existingFavoriteFor(Object obj) {
+		if (obj == null)
+			return null;
+		Iterator<IPiItem> iter = favorites.iterator();
+		while (iter.hasNext()) {
+			IPiItem item = iter.next();
+			if (item.isPIFor(obj))
+				return item;
+		}
+		return null;
+	}
+
+	public IPiItem[] existingFavoritesFor(Iterator iter)
+	{
+		ArrayList<IPiItem> result = new ArrayList<IPiItem>(10);
+		while (iter.hasNext()) {
+			IPiItem item =
+				existingFavoriteFor(iter.next());
+			if (item != null)
+				result.add(item);
+		}
+		return (IPiItem[]) result.toArray(
+			new IPiItem[result.size()]);
+	}
+	
+	public void addFavorites(IPiItem[] items) {
+		if (favorites == null)
+			loadFavorites();
+		if (favorites.addAll(Arrays.asList(items)))
+			fireFavoritesChanged(items, IPiItem.NONE);
+	}
+	
+	public void removeFavorites(IPiItem[] items) {
+		if (favorites == null)
+			loadFavorites();
+		if (favorites.removeAll(Arrays.asList(items)))
+			fireFavoritesChanged(IPiItem.NONE, items);
+	}
+
+   /////////// Loading and Saving Favorites /////////////////
+
+   private static final String TAG_FAVORITES = "Favorites"; //$NON-NLS-1$
+   private static final String TAG_FAVORITE = "Favorite"; //$NON-NLS-1$
+   private static final String TAG_TYPEID = "TypeId"; //$NON-NLS-1$
+   private static final String TAG_INFO = "Info"; //$NON-NLS-1$
+   
+   private void loadFavorites() {
+      favorites = new HashSet<IPiItem>(20);
+      FileReader reader = null;
+      try {
+         reader = new FileReader(getFavoritesFile());
+         loadFavorites(XMLMemento.createReadRoot(reader));
+      }
+      catch (FileNotFoundException e) {
+         // ignored... no favorites exist yet
+      }
+      catch (Exception e) {
+         // log the exception and move on
+//         PILog.logError(e);
+      }
+      finally {
+         try {
+            if (reader != null)
+               reader.close();
+         }
+         catch (IOException e) {
+//            PILog.logError(e);
+         }
+      }
+   }
+   
+   private void loadFavorites(XMLMemento memento) {
+      IMemento[] children =
+         memento.getChildren(TAG_FAVORITE);
+      for (int i = 0; i < children.length; i++) {
+         IPiItem item =
+            newFavoriteFor(
+               children[i].getString(TAG_TYPEID),
+               children[i].getString(TAG_INFO));
+         if (item != null)
+            favorites.add(item);
+      }
+   }
+   
+   public IPiItem newFavoriteFor(String typeId, String info) {
+      PiItemType[] types = PiItemType.getTypes();
+      for (int i = 0; i < types.length; i++)
+         if (types[i].getID().equals(typeId))
+            return types[i].loadFavorite(info);
+      return null;
+   }
+   
+   public void saveFavorites() {
+      if (favorites == null)
+         return;
+      XMLMemento memento =
+         XMLMemento.createWriteRoot(TAG_FAVORITES);
+      saveFavorites(memento);
+      FileWriter writer = null;
+      try {
+         writer = new FileWriter(getFavoritesFile());
+         memento.save(writer);
+      }
+      catch (IOException e) {
+ //        PILog.logError(e);
+      }
+      finally {
+         try {
+            if (writer != null)
+               writer.close();
+         }
+         catch (IOException e) {
+//            PILog.logError(e);
+         }
+      }
+   }
+   
+   private void saveFavorites(XMLMemento memento) {
+      Iterator iter = favorites.iterator();
+      while (iter.hasNext()) {
+         IPiItem item = (IPiItem) iter.next();
+         IMemento child = memento.createChild(TAG_FAVORITE);
+         child.putString(TAG_TYPEID, item.getType().getID());
+         child.putString(TAG_INFO, item.getInfo());
+      }
+   }
+   
+   private File getFavoritesFile() {
+      return PiPlugin
+         .getDefault()
+         .getStateLocation()
+         .append(Messages.getString("PiManager.favoritesXmlFile")) //$NON-NLS-1$
+         .toFile();
+	}
+	
+   ///////////// FavoriteManagerListener methods ///////////////////////
+
+	public void addFavoritesManagerListener(PiManagerListener listener) {
+		if (!listeners.contains(listener))
+			listeners.add(listener);
+	}
+	
+	public void removeFavoritesManagerListener(PiManagerListener listener) {
+		listeners.remove(listener);
+	}
+	
+	private void fireFavoritesChanged(IPiItem[] itemsAdded, IPiItem[] itemsRemoved) {
+		PiManagerEvent event = new PiManagerEvent(this, itemsAdded, itemsRemoved);
+		for (Iterator<PiManagerListener> iter = listeners.iterator(); iter.hasNext();)
+			iter.next().piChanged(event);
+	}
+
+   ///////////// IResourceChangeListener //////////////////////
+   
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/PiManagerEvent.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.util.EventObject;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IPiItem;
+
+
+public class PiManagerEvent extends EventObject
+{
+	private static final long serialVersionUID = 419533445045955384L;
+	private final IPiItem[] added;
+	private final IPiItem[] removed;
+
+	public PiManagerEvent(
+		PiManager source,
+		IPiItem[] itemsAdded,
+		IPiItem[] itemsRemoved) {
+         
+		super(source);
+		added = itemsAdded;
+		removed = itemsRemoved;
+	}
+   
+	public IPiItem[] getItemsAdded() {
+	   return added;
+	}
+   
+	public IPiItem[] getItemsRemoved() {
+		return removed;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/PiManagerListener.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+public interface PiManagerListener
+{
+	public void piChanged(PiManagerEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledBinary.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+public class ProfiledBinary extends ProfiledGeneric
+{
+    public ProfiledBinary()
+    {
+        super();
+   }
+   
+    public String toString(int graphIndex)
+    {
+    	if (this.isEnabled(graphIndex))
+    	{
+    		return "true  " + this.getAverageLoadValueString(graphIndex) + getNameString(); //$NON-NLS-1$
+	  	}
+		else
+		{
+	      	return "false " + this.getAverageLoadValueString(graphIndex) + getNameString(); //$NON-NLS-1$
+		}
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledDspHook.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.awt.Color;
+
+
+public class ProfiledDspHook
+{
+	private Long timeStamp;	
+	private Color color = null;
+	private boolean enableValue = true;
+	private String nameString;
+	private int eventCount = 0;
+	
+    public ProfiledDspHook()
+    {
+//        super();
+        this.color = new Color(
+                (int)(Math.random()*255),
+                (int)(Math.random()*255),
+                (int)(Math.random()*255));
+    }
+    
+    public ProfiledDspHook(String name, int ec)
+    {
+//        super();
+        this.color = new Color(
+                (int)(Math.random()*255),
+                (int)(Math.random()*255),
+                (int)(Math.random()*255));
+        this.nameString = name;
+        this.eventCount = ec;
+    }
+
+    public ProfiledDspHook(String name, long ts)
+    {
+//        super();
+        this.color = new Color(
+                (int)(Math.random()*255),
+                (int)(Math.random()*255),
+                (int)(Math.random()*255));
+        this.nameString = name;
+        this.timeStamp = new Long(ts);
+    }
+
+    public void setEventTimeString(Long ts)
+    {
+    	this.timeStamp = ts;
+    }
+    
+    public String getEventTimeString()
+    {
+    	return this.timeStamp.toString();
+    }
+
+   
+    public void setColor(Color c)
+    {
+      this.color = c;
+    }
+
+    public void setEnabled(boolean enableValue)
+    {
+      this.enableValue = enableValue;
+    }
+    
+    public void setEventCount(int c)
+    {
+    	this.eventCount = c;
+    }
+
+    public boolean isEnabled()
+    {
+      return enableValue;
+    }
+
+    public Color getColor()
+    {
+      return this.color;
+    }
+    
+    public String getNameString()
+    {
+      return this.nameString;
+    }
+    public int getEventCount()
+    {
+      return this.eventCount;
+    }
+    
+    public String toString()
+    {
+    	if (this.isEnabled())
+  	{
+    		return "true  " + nameString + this.getEventTimeString(); //$NON-NLS-1$
+  	}
+      else
+      {
+      	return "false " + nameString + this.getEventTimeString(); //$NON-NLS-1$
+      }
+    }   
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledFunction.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.util.Vector;
+
+public class ProfiledFunction extends ProfiledGeneric
+{
+	long   functionAddress;
+    String functionBinaryName;
+//	String functionBinaryPathName;
+    Vector threadIds;
+    
+    public ProfiledFunction()
+    {
+        super();
+        this.threadIds = new Vector();
+        //setEnabled(false);
+    }
+    /**
+     * @return Returns the functionAddress.
+     */
+    public long getFunctionAddress()
+    {
+        return functionAddress;
+    }
+
+    /**
+     * @param functionAddress The functionAddress to set.
+     */
+    public void setFunctionAddress(long functionAddress)
+    {
+        this.functionAddress = functionAddress;
+    }
+
+    /**
+     * @return Returns the functionBinaryName.
+     */
+    public String getFunctionBinaryName()
+    {
+        //return this.nameString;
+        return functionBinaryName;
+    }
+
+    /**
+     * @param functionBinaryName The functionBinaryName to set.
+     */
+    public void setFunctionBinaryName(String functionBinaryName)
+    {
+        //this.nameString = functionBinaryName;
+        this.functionBinaryName = functionBinaryName;
+    }
+//
+//    public String getFunctionBinaryPathName()
+//    {
+//        //return this.nameString;
+//        return functionBinaryPathName;
+//    }
+//
+//    public void setFunctionBinaryPathName(String functionBinaryPathName)
+//    {
+//        //this.nameString = functionBinaryName;
+//        this.functionBinaryPathName = functionBinaryPathName;
+//    }
+    
+    public void addThreadId(int id)
+    {
+    	Integer integer = new Integer(id);
+    	if (!this.threadIds.contains(integer))
+    	{
+    		this.threadIds.add(integer);
+    	}
+    }
+    
+    public boolean containsThreadId(int id)
+    {
+    	return this.threadIds.contains(new Integer(id));
+    }
+
+    public boolean equals(Object anObject)
+    {
+        if (anObject == null)
+            return false;
+        if (!(anObject instanceof ProfiledFunction))
+            return false;
+        ProfiledFunction pfTmp = (ProfiledFunction)anObject;
+        if (this.getNameString().equals(pfTmp.getNameString()))
+            return true;
+        else
+            return false;
+    }
+    
+    public int hashCode()
+    {
+    	return this.getNameString().hashCode();
+    }
+    
+    public String toString(int graphIndex)
+    {
+    	if (this.isEnabled(graphIndex))
+    	{
+    		return "true  " + this.getAverageLoadValueString(graphIndex) + getNameString(); //$NON-NLS-1$
+	  	}
+		else
+		{
+	      	return "false " + this.getAverageLoadValueString(graphIndex) + getNameString(); //$NON-NLS-1$
+		}
+    }   
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledGeneric.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.text.DecimalFormat;
+
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+
+import com.nokia.carbide.cpp.pi.util.ColorPalette;
+
+public abstract class ProfiledGeneric
+{
+    protected int index = -1;
+    private String nameString;
+    protected Color color;
+    protected int totalSampleCount;
+    protected int firstSample = -1;
+    protected int lastSample = -1;
+    private int   recentSample = -1;
+    private int   recentSampleCount = 0;
+    private int   recentPercentage = -1;
+    protected int[] activityList;
+    private int[] sampleList;
+    private int[][] cumulativeList = new int[3][];
+    
+	// since each instance may be used by table viewers for multiple graphs,
+	// keep per graph (for a maximum of 3 graphs):
+    //	whether the thread/binary/function is currently enabled
+    //	sample count in the selected graph area
+    //	% load in the selected graph area
+	//  string version of graph percent load
+    protected boolean[] enableValue = {true, true, true};
+	protected int[]   graphSampleCount = { 0, 0, 0 };
+	protected float[] graphPercentLoad = { 0.0f, 0.0f, 0.0f };
+    private String[]  averageLoadValueString = { "", "", "" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	
+    private PointList[] pointList  = {new PointList(), new PointList(), new PointList()};
+    protected int[] activityP = null;
+    private int[] activityT = null;
+    protected int activityIndx = 0;
+    
+    public ProfiledGeneric()
+    {
+      // default to light gray
+      this.color = ColorPalette.getColor(new RGB(192, 192, 192));
+     }
+    
+    public void setNameString(String nameString)
+    {
+    	this.nameString = nameString;
+    }
+    
+    public void addPointToPolyline(int graphIndex, int x, int y)
+    {
+    	pointList[graphIndex].addPoint(x, y);
+    }
+    
+    public void resetPolyline(int graphIndex)
+    {
+    	pointList[graphIndex].removeAllPoints();
+    }
+    
+    public PointList getPointList(int graphIndex)
+    {
+    	return pointList[graphIndex];
+    }
+    
+    public int getIndex()
+    {
+    	return this.index;
+    }
+    
+    public void setActivityMarkCount(int size)
+    {
+    	this.activityP = new int[size];
+    	this.activityT = new int[size];
+    }
+    
+    // zero the samples of this profiled generic in the time range starting at the time stamp
+    public void zeroActivityMarkValues(int timeStamp)
+    {
+        addActivityMarkValues(timeStamp, 0, 0);
+    }
+
+    // set the samples of of this profiled generic in the time range starting at the time stamp
+    public void addActivityMarkValues(int timeStamp, int percentage, int sampleCount)
+    {
+      this.activityT[this.activityIndx] = timeStamp;
+      this.activityP[this.activityIndx] = percentage;
+
+      if (this.firstSample == -1 && percentage != 0)
+      {
+    	  this.firstSample = this.recentSample;
+      }
+
+   	  if (this.recentSampleCount > 0)
+   		  this.lastSample = timeStamp;
+
+      this.recentSample      = timeStamp;
+      this.recentSampleCount = sampleCount;
+      this.recentPercentage  = percentage;
+      this.activityIndx++;
+    }
+
+    public void addActivityMark(int timeStamp, int percentage)
+    {
+      this.activityT[this.activityIndx] = timeStamp;
+      this.activityP[this.activityIndx] = percentage;
+      this.activityIndx++;
+    }
+
+  	public void setupCumulativeList(int graphIndex)
+  	{
+  		if (this.activityIndx != 0)
+  		{	
+  			if (cumulativeList[graphIndex] == null)
+  				cumulativeList[graphIndex] = new int[this.activityIndx];
+  			else
+  			{
+  				for (int i = 0; i < cumulativeList[graphIndex].length; i++)
+  				{
+  					cumulativeList[graphIndex][i] = 0;
+  				}
+  			}
+  		}
+  	}
+
+  	public int[] getCumulativeList(int graphIndex)
+  	{
+  		return this.cumulativeList[graphIndex];
+  	}
+
+  	public void setCumulativeValue(int graphIndex, int index, int value)
+  	{
+  		this.cumulativeList[graphIndex][index] = value;
+  	}
+  	
+  	//returns x-coordinates
+  	public int[] getSampleList()
+  	{
+  		if (sampleList == null && this.activityIndx != 0)
+  		{
+  			sampleList = new int[this.activityIndx];
+ 
+  			for (int i = 0; i < this.activityIndx; i++)
+  			{
+  				this.sampleList[i] = this.activityT[i];
+  			}
+  			this.activityT = null;
+  		}
+  		return this.sampleList;
+  	}
+  	
+  	// returns y-coordinates
+  	public int[] getActivityList()
+  	{
+  		if (activityList == null && this.activityIndx != 0)
+  		{
+  			activityList = new int[this.activityIndx];
+
+  			for (int i = 0; i < this.activityIndx; i++)
+  			{
+  			  activityList[i] = this.activityP[i];
+  			}
+  			this.activityP = null;
+  		}
+
+  		return this.activityList;
+  	}
+
+    public int getFirstSample()
+    {
+      if (this.firstSample == -1)
+    	  return 0;
+      else
+    	  return this.firstSample;
+    }
+
+    public int getRealFirstSample()
+    {
+   	  return this.firstSample;
+    }
+
+    public int getLastSample()
+    {
+      if (this.lastSample == -1)
+    	  return 0;
+      else
+    	  return this.lastSample;
+    }
+
+    public int getRealLastSample()
+    {
+   	  return this.lastSample;
+    }
+    
+    public void setLastSample(int lastSample)
+    {
+    	this.lastSample = lastSample;
+    }
+
+    private int findNearestSampleIndexFromStart(int sampleNum)
+    {
+    	int i = 0;
+    	while (i < this.sampleList.length && this.sampleList[i] < sampleNum)
+    	{
+    		i++;
+    	}    
+    	return i;
+    }
+
+    private int findNearestSampleIndexFromEnd(int sampleNum)
+    {
+    	int i = sampleList.length - 1;
+    	while (this.sampleList[i] > sampleNum && i > 0)
+    	{
+    		i--;
+    	}
+    	return i;
+    }
+
+    public float getAverageLoad(double startTime, double endTime)
+    {
+        return getAverageLoad((int) startTime,(int) endTime);
+    }
+    
+    public float getAverageLoad(int startSample,int endSample)
+    {
+    	if (startSample == -1 || endSample == -1) return -666;
+    	if (endSample < startSample) return -777;
+
+    	if (this.activityList == null || this.sampleList == null) return -888;
+
+    	int firstSampleIndx = 0;
+    	int lastSampleIndx = 0;
+
+    	firstSampleIndx = this.findNearestSampleIndexFromStart(startSample) + 1;
+    	lastSampleIndx  = this.findNearestSampleIndexFromEnd(endSample) + 1;
+   
+    	if (firstSampleIndx < 0)
+    		firstSampleIndx = 0;
+    	if (firstSampleIndx >= activityList.length)
+    		firstSampleIndx = activityList.length - 1;
+    	
+    	if (lastSampleIndx < 0)
+    		lastSampleIndx = 0;
+    	if (lastSampleIndx >= activityList.length)
+    		lastSampleIndx = activityList.length - 1;
+      
+    	if (firstSampleIndx > lastSampleIndx)
+    	{
+    		int temp = firstSampleIndx;
+    		firstSampleIndx = lastSampleIndx;
+    		lastSampleIndx = temp;
+    	}
+    	
+    	int totalTime = sampleList[lastSampleIndx - 1] - sampleList[firstSampleIndx - 1];
+    	int totalLoad = 0;
+    	
+    	for (int i = firstSampleIndx; i < lastSampleIndx; i++)
+    	{
+    		totalLoad += this.activityList[i];
+    	}
+     	
+    	totalLoad *= (sampleList[1] - sampleList[0]);
+
+    	if (totalTime == 0)
+    	{
+    		return 0;
+    	}
+    	else
+    	{
+    		return (float)(((float)totalLoad) / ((float)totalTime));
+    	}
+    }
+    
+    public int getTotalLoad(int startSample,int endSample)
+    {
+    	if (startSample == -1 || endSample == -1) return -666;
+    	if (endSample < startSample) return -777;
+
+    	if (this.activityList == null || this.sampleList == null) return -888;
+
+    	int firstSampleIndx = 0;
+    	int lastSampleIndx = 0;
+
+    	firstSampleIndx = this.findNearestSampleIndexFromStart(startSample) + 1;
+    	lastSampleIndx  = this.findNearestSampleIndexFromEnd(endSample) + 1;
+  
+    	if (firstSampleIndx < 0)
+    		firstSampleIndx = 0;
+    	if (firstSampleIndx >= activityList.length)
+    		firstSampleIndx = activityList.length - 1;
+    	
+    	if (lastSampleIndx < 0)
+    		lastSampleIndx = 0;
+    	if (lastSampleIndx >= activityList.length)
+    		lastSampleIndx = activityList.length - 1;
+      
+    	if (firstSampleIndx > lastSampleIndx)
+    	{
+    		int temp = firstSampleIndx;
+    		firstSampleIndx = lastSampleIndx;
+    		lastSampleIndx = temp;
+    	}
+    	
+    	int totalTime = sampleList[lastSampleIndx - 1] - sampleList[firstSampleIndx - 1];
+    	int totalLoad = 0;
+   	
+    	for (int i = firstSampleIndx; i < lastSampleIndx; i++)
+    	{
+    		totalLoad += this.activityList[i];
+    	}
+     	
+    	if (totalTime == 0)
+    	{
+    		return 0;
+    	}
+    	else
+    	{
+    		return (int) totalLoad;
+    	}
+    }
+    
+    public void setIndex(int index)
+    {
+    	this.index = index;
+    }
+    
+    public void setAverageLoadValueString(int graphIndex, String valueString)
+    {
+    	this.averageLoadValueString[graphIndex] = valueString;
+    }
+
+    public void setAverageLoadValueString(int graphIndex, float value)
+    {
+    	this.averageLoadValueString[graphIndex] = (new DecimalFormat(Messages.getString("ProfiledGeneric.decimalFormat"))).format(value); //$NON-NLS-1$
+    }
+
+    public void setAverageLoadValueString(int graphIndex)
+    {
+    	this.averageLoadValueString[graphIndex] = (new DecimalFormat(Messages.getString("ProfiledGeneric.decimalFormat"))).format(this.graphPercentLoad[graphIndex]); //$NON-NLS-1$
+    }
+
+    public String getAverageLoadValueString(int graphIndex)
+    {
+    	return this.averageLoadValueString[graphIndex];
+    }
+
+    public void setColor(Color c)
+    {
+    	this.color = c;
+    }
+
+    public void setEnabled(int graphIndex, boolean enableValue)
+    {
+    	this.enableValue[graphIndex] = enableValue;
+    }
+
+    public boolean isEnabled(int graphIndex)
+    {
+    	return enableValue[graphIndex];
+    }
+
+    public Color getColor()
+    {
+    	return this.color;
+    }
+    
+    public String getNameString()
+    {
+    	return this.nameString;
+    }
+    
+    public int getTotalSampleCount()
+    {
+    	return this.totalSampleCount;
+    }
+    
+    public void incTotalSampleCount()
+    {
+    	this.totalSampleCount++;
+    }
+
+	public int getSampleCount(int graphIndex)
+	{
+		return this.graphSampleCount[graphIndex];
+	}
+	
+	public void setSampleCount(int graphIndex, int sampleCount)
+	{
+		this.graphSampleCount[graphIndex] = sampleCount;
+	}
+	
+	public void incSampleCount(int graphIndex)
+	{
+		this.graphSampleCount[graphIndex]++;
+	}
+	
+	public void setSampleCounts(int sampleCount0, int sampleCount1, int sampleCount2)
+	{
+		this.graphSampleCount[0] = sampleCount0;
+		this.graphSampleCount[1] = sampleCount1;
+		this.graphSampleCount[2] = sampleCount2;
+	}
+	
+	public float getPercentLoad(int graphIndex)
+	{
+		return this.graphPercentLoad[graphIndex];
+	}
+	
+	public void setLoadAndString(int graphIndex, float percentLoad)
+	{
+		this.graphPercentLoad[graphIndex] = percentLoad;
+
+		// doesn't hurt to set the string here, too.
+		// you may not need to set the string when you set the float
+		if (percentLoad >= 0.005f)
+			this.averageLoadValueString[graphIndex] = (new DecimalFormat(Messages.getString("ProfiledGeneric.decimalFormat"))).format(percentLoad); //$NON-NLS-1$
+		else
+			this.averageLoadValueString[graphIndex] = Messages.getString("ProfiledGeneric.zeroFormat"); //$NON-NLS-1$
+	}
+	
+	public void setPercentLoads(float percentLoad0, float percentLoad1, float percentLoad2)
+	{
+		this.graphPercentLoad[0] = percentLoad0;
+		this.graphPercentLoad[1] = percentLoad1;
+		this.graphPercentLoad[2] = percentLoad2;
+
+		// doesn't hurt to set the strings here, too
+		// you may not need to set the strings when you set the float
+		if (percentLoad0 >= 0.005f)
+			this.averageLoadValueString[0] = (new DecimalFormat(Messages.getString("ProfiledGeneric.decimalFormat"))).format(percentLoad0); //$NON-NLS-1$
+		else
+			this.averageLoadValueString[0] = Messages.getString("ProfiledGeneric.zeroFormat"); //$NON-NLS-1$
+		if (percentLoad1 >= 0.005f)
+			this.averageLoadValueString[1] = (new DecimalFormat(Messages.getString("ProfiledGeneric.decimalFormat"))).format(percentLoad1); //$NON-NLS-1$
+		else
+			this.averageLoadValueString[1] = Messages.getString("ProfiledGeneric.zeroFormat"); //$NON-NLS-1$
+		if (percentLoad2 >= 0.005f)
+			this.averageLoadValueString[2] = (new DecimalFormat(Messages.getString("ProfiledGeneric.decimalFormat"))).format(percentLoad2); //$NON-NLS-1$
+		else
+			this.averageLoadValueString[2] = Messages.getString("ProfiledGeneric.zeroFormat"); //$NON-NLS-1$
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledThread.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.io.Serializable;
+
+/*
+ *
+ * PRI HOMMAT KOMMENTOITU TÄSTÄ FILESTÄ TOISTAISEKSI
+ *
+ */
+
+public class ProfiledThread extends ProfiledGeneric implements Serializable
+{
+	private static final long serialVersionUID = 20150633093396772L;
+
+	private char name; //char symbol of the thread
+
+	private int threadId; //thread's real id
+ 
+	public ProfiledThread()
+	{
+		super();
+	}
+  
+	public void setNameValues(char symbol,String nameString)
+	{
+		this.name = symbol;
+		setNameString(nameString);
+	}
+ 
+	public String toString(int graphIndex)
+	{
+		if (this.isEnabled(graphIndex))
+		{
+			return "true  " + this.getAverageLoadValueString(graphIndex) + getNameString(); //$NON-NLS-1$
+		}
+		else
+		{
+			return "false " + this.getAverageLoadValueString(graphIndex) + getNameString(); //$NON-NLS-1$
+		}
+	}
+  
+	public Character getName(){
+		return new Character(this.name);
+	}
+
+	public int getThreadId() 
+	{
+		return threadId;
+	}
+
+	public void setThreadId(int threadId) 
+	{
+		this.threadId = threadId;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProfiledThreshold.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+public class ProfiledThreshold extends ProfiledGeneric implements Serializable
+{
+	private static final long serialVersionUID = 4902799424564460641L;
+	
+	// number of items (threads, binaries, functions) represented by this object 
+	private int[] itemCount = new int[3];
+	
+	// lists of items (threads, binaries, functions) represented by this object
+	private ArrayList<ProfiledGeneric>[] items = new ArrayList[3];
+	
+	public ProfiledThreshold(String name) {
+		this.setNameString(name);
+	}
+	
+	public void setItemCount(int graphIndex, int itemCount) {
+		this.itemCount[graphIndex] = itemCount;
+	}
+
+	public void incItemCount(int graphIndex) {
+		this.itemCount[graphIndex]++;
+	}
+	
+	public int getItemCount(int graphIndex) {
+		return this.itemCount[graphIndex];
+	}
+	
+	public void init(int graphIndex) {
+		this.enableValue[graphIndex]      = false;
+		this.itemCount[graphIndex]        = 0;
+		this.graphSampleCount[graphIndex] = 0;
+
+		if (this.items[graphIndex] != null)
+			this.items[graphIndex].clear();
+
+		if (this.activityList == null)
+			this.activityList = new int[this.activityIndx];
+
+		for (int i = 0; i < this.activityIndx; i++) {
+			this.activityList[i] = 0;
+			this.activityP[i] = 0;
+		}
+	}
+	
+	public void initAll() {
+		this.enableValue[0]      = false;
+		this.itemCount[0]        = 0;
+		this.graphSampleCount[0] = 0;
+		this.enableValue[1]      = false;
+		this.itemCount[1]        = 0;
+		this.graphSampleCount[1] = 0;
+		this.enableValue[2]      = false;
+		this.itemCount[2]        = 0;
+		this.graphSampleCount[2] = 0;
+
+		if (this.activityList == null)
+			this.activityList = new int[this.activityIndx];
+
+		for (int i = 0; i < this.activityIndx; i++) {
+			this.activityList[i] = 0;
+			this.activityP[i] = 0;
+		}
+	}
+	
+	public void addItem(int graphIndex, ProfiledGeneric pGeneric, int count)
+	{
+		if (pGeneric instanceof ProfiledThreshold)
+			this.totalSampleCount += count;	// this assumes that threshold only has one non-zero graphIndex element
+
+		this.itemCount[graphIndex]++;
+		this.graphSampleCount[graphIndex] += count;
+
+		// add to the activity list
+		if (this.activityList == null)
+			this.activityList = new int[this.activityIndx];
+
+		int[] activityList = pGeneric.getActivityList();
+		for (int i = 0; i < activityList.length; i++)
+			this.activityList[i] += activityList[i];
+
+		// add to the list of items associated with this threshold object
+		if (items[graphIndex] == null)
+			items[graphIndex] = new ArrayList<ProfiledGeneric>();
+		
+		items[graphIndex].add(pGeneric);
+
+		this.enableValue[graphIndex] = true;
+	}
+	
+	public ArrayList<ProfiledGeneric> getItems(int graphIndex)
+	{
+		return items[graphIndex];
+	}
+	
+    public void setEnabled(int graphIndex, boolean enableValue)
+    {
+    	this.enableValue[graphIndex] = enableValue;
+    	
+    	if (items[graphIndex] == null)
+    		return;
+    	
+    	for (int i = 0; i < items[graphIndex].size(); i++)
+    		items[graphIndex].get(i).enableValue[graphIndex] = enableValue;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/ProgressBar.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import javax.swing.JProgressBar;
+
+public class ProgressBar extends JProgressBar {
+
+	private static final long serialVersionUID = 4862691591715531894L;
+
+	public ProgressBar() {
+        super();
+        this.setValue(0);
+        this.setStringPainted(true);
+        this.setIndeterminate(true);
+        this.setBorder(javax.swing.BorderFactory.createEtchedBorder(javax.swing.border.EtchedBorder.RAISED));
+        this.setFont(new java.awt.Font(Messages.getString("ProgressBar.defaultFont"), java.awt.Font.PLAIN, 10)); //$NON-NLS-1$
+    }
+    
+	public void addValue(int value)
+	{
+		this.setValue(this.getValue() + value);
+		this.validate();
+	}
+	
+	public int getMaxValue()
+	{
+		return this.getMaximum();
+	}
+	
+	public void advanceTo(int value)
+	{
+		try
+		{
+		  for (int i = this.getValue(); i < value; i++)
+		  {
+			addValue(1);
+			Thread.sleep(10);
+		  }
+		}
+		catch (Exception e) {}
+	}
+	
+	public void runToEnd()
+	{
+		try
+		{
+		  for (int i = getValue(); i < getMaxValue(); i++)
+		  {
+			addValue(1);
+			Thread.sleep(10);
+		  }
+		}
+		catch (Exception e) {}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/RefinableTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+public interface RefinableTrace 
+{
+	// resolve or further resolve addresses to entities like binaries and functions
+	public void refineTrace(FunctionResolver resolver);
+	
+	// after all refinement is done, do any final touches to the samples
+	public void finalizeTrace();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/TraceDataContainer.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+public class TraceDataContainer 
+{
+	private Hashtable columns;
+	private String name;
+	
+	private static class InternalColumn
+	{		
+		ArrayList columnData;
+
+		InternalColumn(String columnName)
+		{
+			columnData = new ArrayList();
+		}
+	}
+	
+	public TraceDataContainer(String containerName, String[] initialColumnNames)
+	{
+		this.name = containerName;
+		this.columns = new Hashtable();
+		for (int i = 0; i < initialColumnNames.length; i++)
+		{
+			InternalColumn c = new InternalColumn(initialColumnNames[i]);
+			this.columns.put(initialColumnNames[i], c);
+		}
+	}
+	
+	public String getName()
+	{
+		return name;
+	}
+	
+	public void addDataToColumn(String columnName, Object data)
+	{
+		InternalColumn ic = (InternalColumn)this.columns.get(columnName);
+		
+		if (ic == null)
+			throw new NullPointerException(Messages.getString("TraceDataContainer.columnNotFound1") + columnName + Messages.getString("TraceDataContainer.columnNotFound2")); //$NON-NLS-1$ //$NON-NLS-2$
+		ic.columnData.add(data);
+	}
+	
+	public Iterator getColumn(String columnName)
+	{
+		InternalColumn ic = (InternalColumn)this.columns.get(columnName);
+		
+		if (ic == null) throw new NullPointerException(Messages.getString("TraceDataContainer.columnNotFound1") + columnName + Messages.getString("TraceDataContainer.columnNotFound2")); //$NON-NLS-1$ //$NON-NLS-2$
+		
+		return ((InternalColumn)this.columns.get(columnName)).columnData.iterator();
+	}
+	
+	private ArrayList getColumnInternal(String columnName)
+	{
+		InternalColumn ic = (InternalColumn)this.columns.get(columnName);
+		
+		if (ic == null)
+			throw new NullPointerException(Messages.getString("TraceDataContainer.columnNotFound1") + columnName + Messages.getString("TraceDataContainer.columnNotFound2")); //$NON-NLS-1$ //$NON-NLS-2$
+		
+		return ((InternalColumn)this.columns.get(columnName)).columnData;		
+	}
+	
+	public ArrayList getColumnMatch(String knownColumn, String searchedColumn, Object knownObject)
+	{
+		ArrayList c1 = this.getColumnInternal(knownColumn);
+		ArrayList c2 = this.getColumnInternal(searchedColumn);
+		
+		ArrayList found = new ArrayList();
+		
+		for (int i = 0; i < c1.size(); i++)
+		{
+			 Object o = c1.get(i);
+			 if (o.equals(knownObject))
+			 {
+				 if (i < c2.size())
+				 {
+					 found.add(c2.get(i));
+				 }
+			 }
+		}
+		return found;
+	}
+	
+	public static void main(String[] a)
+	{
+		TraceDataContainer t = new TraceDataContainer("taulukko",new String[]{"nimi","puh","osoite"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+		t.addDataToColumn("nimi","teemu"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("nimi","kaapo"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("nimi","erkki"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("nimi","kaapo"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("nimi","teemu"); //$NON-NLS-1$ //$NON-NLS-2$
+		
+		t.addDataToColumn("puh","1"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("puh","2"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("puh","3"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("puh","4"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("puh","24398243987"); //$NON-NLS-1$ //$NON-NLS-2$
+
+		t.addDataToColumn("osoite","tie 1"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("osoite","tie 2"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("osoite","tie 3"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("osoite","tie 4"); //$NON-NLS-1$ //$NON-NLS-2$
+		t.addDataToColumn("osoite","tie 243982473987"); //$NON-NLS-1$ //$NON-NLS-2$
+
+		
+		ArrayList al = t.getColumnMatch("nimi","osoite","teemu");		 //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		Iterator i = al.iterator();
+		while(i.hasNext())
+		{
+			System.out.println((String)i.next());
+		}
+			
+	}
+	
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/TraceDataRepository.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Vector;
+
+public class TraceDataRepository 
+{	
+	private static Hashtable<Integer,LinkedHashMap<Class,ParsedTraceData>> analysisSpecificTraces;
+	private static TraceDataRepository instance;
+	
+	public static TraceDataRepository getInstance() {
+		if (instance == null) {
+			instance = new TraceDataRepository();
+		}
+		return instance;
+	}
+	
+	// singleton
+	private TraceDataRepository()
+	{
+		if (analysisSpecificTraces == null)
+			analysisSpecificTraces = new Hashtable<Integer,LinkedHashMap<Class,ParsedTraceData>>();
+	}
+	
+	public void registerTraces(int analysisId) {
+		if (analysisSpecificTraces.get(analysisId) == null) {
+			analysisSpecificTraces.put(new Integer(analysisId), new LinkedHashMap<Class,ParsedTraceData>());
+		}
+	}
+	
+	public void insertTraceCollection(Class traceClass, ParsedTraceData traceData, int analysisId)
+	{
+		LinkedHashMap<Class,ParsedTraceData> tracesForMyId = getTraceCollection(analysisId);
+		if (tracesForMyId == null)
+		{
+			tracesForMyId = new LinkedHashMap<Class,ParsedTraceData>();
+		}
+		if (traceClass != null && traceData != null && traceData.traceData != null)
+		{
+			tracesForMyId.put(traceClass, traceData);
+			analysisSpecificTraces.put(new Integer(analysisId), tracesForMyId);
+		}
+	}
+	
+//	public ParsedTraceData getTrace(Class traceClass)
+//	{
+//		return traces.get(traceClass);
+//	}
+	
+	public ParsedTraceData getTrace(int analysisId, Class traceClass)
+	{
+		if (analysisSpecificTraces == null || traceClass == null)
+			return null;
+
+		LinkedHashMap<Class,ParsedTraceData> tmp = analysisSpecificTraces.get(new Integer(analysisId));
+
+		if (tmp == null)
+			return null;
+
+		return tmp.get(traceClass);
+	}
+	
+	public Enumeration<FunctionResolver> getResolvers(int analysisId)
+	{
+		Vector<FunctionResolver> resolvers = new Vector<FunctionResolver>();
+		
+		if (analysisSpecificTraces == null) 
+			return resolvers.elements();
+
+		LinkedHashMap<Class,ParsedTraceData> tmp = analysisSpecificTraces.get(new Integer(analysisId));
+
+		Iterator<ParsedTraceData> e = tmp.values().iterator();
+		while (e.hasNext())
+		{
+			ParsedTraceData data = (ParsedTraceData)e.next();
+			if (data.functionResolvers != null)
+			{
+				for (int i = 0; i < data.functionResolvers.length; i++)
+				{
+					resolvers.add(data.functionResolvers[i]);
+				}
+			}
+		}
+		
+		return resolvers.elements();
+	}
+	
+	public ParsedTraceData getTrace(int analysisId, String className)
+	{
+		Class traceClass;
+		try 
+		{
+			traceClass = Class.forName(className);
+		} 
+		catch (ClassNotFoundException e2)
+		{
+			return null;
+		}
+
+		if (analysisSpecificTraces == null)
+			return null;
+
+		LinkedHashMap<Class,ParsedTraceData> tmp = analysisSpecificTraces.get(new Integer(analysisId));
+
+		if (tmp == null)
+			return null;
+
+		return (ParsedTraceData)tmp.get(traceClass);
+	}
+	
+	public Iterator<ParsedTraceData> getTraceCollectionIter(int analysisId)
+	{
+		if (analysisSpecificTraces == null)
+			return null;
+
+		LinkedHashMap<Class,ParsedTraceData> tmp = analysisSpecificTraces.get(new Integer(analysisId));
+
+		if (tmp == null)
+			return null;
+		
+		return tmp.values().iterator();
+	}
+
+	public LinkedHashMap<Class,ParsedTraceData> getTraceCollection(int analysisId)
+	{
+		if (analysisSpecificTraces == null)
+			return null;
+
+		LinkedHashMap<Class,ParsedTraceData> tmp = analysisSpecificTraces.get(new Integer(analysisId));
+
+		if (tmp == null)
+			return null;
+
+		return tmp;
+	}
+	
+	public void removeTraces(int analysisId)
+	{
+		if (analysisSpecificTraces != null)
+			analysisSpecificTraces.remove(new Integer(analysisId));
+	}
+	
+	public void removeAll()
+	{
+		if (analysisSpecificTraces != null)
+			analysisSpecificTraces.clear();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/TraceTimeWindow.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.model;
+
+public class TraceTimeWindow
+{
+    public double traceStartTime = 0;
+    public double traceEndTime = 0;
+    
+    public TraceTimeWindow()
+    {
+        
+    }
+    
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/TraceWithThreads.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: 
+ *
+ */
+
+/*
+ * TraceWithThreads.java
+ */
+package com.nokia.carbide.cpp.internal.pi.model;
+
+public interface TraceWithThreads 
+{
+	  public GenericThread[] getThreads();
+//	  public long getLastSynchTimeForThread(GenericThread t);
+//	  public long getFirstSynchTimeForThread(GenericThread t);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/model/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,77 @@
+PiItemType.unknown=Unknown
+PiManager.favoritesXmlFile=favorites.xml
+ProfiledGeneric.zeroFormat=0.00
+ProgressBar.defaultFont=Arial
+ProfiledGeneric.decimalFormat=\#\#0.00
+GenericSampledTrace.totalLength=TotalLength = 
+TraceDataContainer.columnNotFound1=Column 
+TraceDataContainer.columnNotFound2=\ not found
+GUITooltips.percentagesInFunctionList=When selected, percentages in the function list show share of the total load instead of the share of the selected threads/binaries
+GUITooltips.addSelectedToGraph=Add selected item(s) to the graph
+GUITooltips.addObyAndIby=Add an oby/iby file or binaries that you want to be used in ITT trace parsing
+GUITooltips.showTotalMemory=Show total memory usage
+GUITooltips.locationOfAnalyse.Exe=Location of the analyse.exe file in your filesystem
+GUITooltips.tempFilesFolder=Directory to store temporary files during serial transfer
+GUITooltips.MMCCardDriveLetter=Drive letter of the MMC card reader in your system
+GUITooltips.locationOfROMSymbolFile=Location of the symbol file of the rom image used
+GUITooltips.sortByCallerLoad=Sort the list according to caller load
+GUITooltips.clearsBinaryListSelections=Clears both visible and currently not visible selections from the binary list
+GUITooltips.closeTab=Close this analysis tab
+GUITooltips.toolConfiguration=Tool configuration
+GUITooltips.deeperKernelAnalyseButton=deeperKernelAnalyseButton
+GUITooltips.setEndTime=Set selection end time
+GUITooltips.combineTraceAndStreamFiles=Create a new analysis by combining separate trace files or stream output data with symbolic information
+GUITooltips.doSelectedFunctionAnalysis=Perform function analysis of all selected items
+GUITooltips.showHeapMemory=Show heap memory usage
+GUITooltips.useOnlyWithKRNFile=Use this only if you have KRN file loaded
+GUITooltips.useOnlyWithCallTrace=Use this only if function call trace is loaded
+GUITooltips.openExistingBapFile=Open an already created analysis (.bap file)
+GUITooltips.zoomIn=Zoom in
+GUITooltips.showSelection=Zoom to selection
+GUITooltips.openTraceFilesFromFileSystem=Open trace files from file system
+GUITooltips.openTraceFilesFromLocation=Open all available trace files from a location
+GUITooltips.openCustomTraceFile=Open Custom trace file, enables custom trace analysis option
+GUITooltips.openDSPTraceFile=Open DSP trace file
+GUITooltips.openCallTraceFile=Open function call trace file, enables linked function analysis option
+GUITooltips.openAddressThreadTraceFile=Open address/thread trace file (must be opened before opening other files)
+GUITooltips.openISAMapFile=Open ISA map file, enables function analysis of Single Chip ISA execution
+GUITooltips.openInstrTraceFile=Open dynamic binary support trace file, enables function analysis of ROFS/dynamic binaries
+GUITooltips.openMemoryPriorityTraceFile=Open memory / priority trace file, enables thread level memory analysis option
+GUITooltips.openTIPTraceFile=Open TIP trace file, enables TCP/IP trace analysis option
+GUITooltips.zoomOut=Zoom out
+GUITooltips.showGraph=Show whole trace
+GUITooltips.goBack=Go back to the previous selection
+GUITooltips.openTraceFilesFromMMCCard=Open all available trace files from the MMC card path (defined in config)
+GUITooltips.recolor=Recolor selected item(s)
+GUITooltips.sortByRecursiveLoad=Sort the list according to recursive load
+GUITooltips.removeSelectedFromGraph=Remove selected item(s) from the graph
+GUITooltips.removeSelectedFromList=Remove the selected file/oby/iby from the list
+GUITooltips.renameTab=Rename currently selected tab
+GUITooltips.generateReportForInterval=Generate report of selected time scope
+GUITooltips.configureInstrTrace=Configure settings for dynamic binary support trace (Dynamic binary/ROFS resolution)
+GUITooltips.saveAnalysis=Save this analysis so that it can be opened without .symbol file or binaries
+GUITooltips.saveConfiguration=Save the configuration
+GUITooltips.saveSettings=Save these settings. You can exit these settings by just closing this window
+GUITooltips.saveListScreenshot=Save a screenshot of the item list
+GUITooltips.saveGraphScreenshot=Save a screenshot of the graph
+GUITooltips.selectTimeInterval=Select defined time frame
+GUITooltips.createNewAnalysis=Open trace files and create a new analysis
+GUITooltips.getTracesViaSerialPort=Receive traces through serial port
+GUITooltips.selectAddressThreadItems=Select the items that were selected in the main GPP graph view
+GUITooltips.rootLetterOfEpoc32Folder=Set here the letter of your SW release root (that has \\epoc32 directory)
+GUITooltips.showSamplesAndStatistics=Show samples and statistics matching the selected time&threads&binaries
+GUITooltips.showStackMemory=Show stack memory usage
+GUITooltips.setStartTime=Set selection start time
+GUITooltips.selectThreads=Select a thread or threads with mouse
+GUITooltips.sortByTotalLoad=Sort the list according to total load
+GUITooltips.resolveByITTFirst=Resolve function names primarily by using ITT trace analysis, before using .symbol file
+GUITooltips.resolveBySymbolFileFirst=Resolve function names primarily by using .symbol file, before using ITT trace analysis
+GUITooltips.dragMouse=Drag mouse to make a selection
+GUITooltips.xminusDeepButton=xminusDeepButton
+GUITooltips.xplusDeepButton=xplusDeepButton
+GUITooltips.yminusButton=yminusButton
+GUITooltips.yminusDeepButton=yminusDeepButton
+GUITooltips.yminusminusButton=yminusminusButton
+GUITooltips.yplusButton=yplusButton
+GUITooltips.yplusDeepButton=yplusDeepButton
+GUITooltips.yplusplusButton=yplusplusButton
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/perspectives/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.perspectives;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.perspectives.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/perspectives/PiPerspectiveFactory.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.perspectives;
+
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+public class PiPerspectiveFactory implements IPerspectiveFactory {
+
+	private static final String PI_VIEW_ID =
+		"com.nokia.carbide.cpp.pi.views.PiView1"; //$NON-NLS-1$
+	
+	private static final String PACKAGE_EXPLORER_VIEW_ID =
+		"org.eclipse.jdt.ui.PackageExplorer"; //$NON-NLS-1$
+	
+	public void createInitialLayout(IPageLayout layout) {
+		// get the editor area
+		String editorArea = layout.getEditorArea();
+		
+		// put the Package Explorer view left of the editor area
+		layout.addView(
+				PACKAGE_EXPLORER_VIEW_ID,
+				IPageLayout.LEFT,
+				0.20f,
+				editorArea);
+		
+		// put the PI view above the editor area
+		IFolderLayout top =
+			layout.createFolder(
+					"top",  //$NON-NLS-1$
+					IPageLayout.TOP,
+					0.66f,
+					editorArea);
+		
+		top.addView(PI_VIEW_ID);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/AbstractPiPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+//Every user plug-in has to extend this class
+
+public abstract class AbstractPiPlugin extends AbstractUIPlugin
+{
+	protected String pluginName;
+	protected int pluginSystemId;
+	
+	private boolean initialised = false;
+	private boolean pluginSystemIdSet = false;
+	
+	public AbstractPiPlugin()
+	{}
+
+	public String getPluginName() 
+	{
+		return pluginName;
+	}
+
+	public boolean isInitialised() 
+	{
+		return initialised;
+	}
+	
+	public int getPluginSystemId()
+	{
+		if (pluginSystemIdSet)
+			return pluginSystemId;
+		else
+			return -1;
+	}
+	
+	//	plugin system id can be set only once for each plugin instances
+	public void setPluginSystemId(int id)
+	{
+		if (pluginSystemIdSet)
+			return;
+		this.pluginSystemId = id;
+		pluginSystemIdSet = true;
+	}
+	
+	public void initialise(String name)
+	{
+		this.pluginName = name;
+		this.initialised = true;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IAnalysisItem.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import org.eclipse.jface.action.Action;
+
+public interface IAnalysisItem extends IMenu
+{
+	public Action getAnalysisAction();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IAnalysisSpecificMenu.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+public abstract interface IAnalysisSpecificMenu extends IMenu 
+{
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IClassReplacer.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+public interface IClassReplacer 
+{
+	public Class getReplacedClass(String className);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IContextMenu.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.widgets.Menu;
+
+
+public interface IContextMenu extends IMenu
+{
+	public void addContextMenuItems(Menu menu, MouseEvent me);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IEventListener.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import org.eclipse.swt.widgets.Event;
+
+public interface IEventListener 
+{
+	public void receiveEvent(String action, Event event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IExportItem.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import org.eclipse.jface.action.Action;
+
+public interface IExportItem extends IAnalysisSpecificMenu
+{
+//	public JMenuItem getExportItem();
+	public Action getExportAction();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IFinalizeTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+/**
+ *
+ *	Any plugin that implement this interface can handle plugin specific
+ *	setup and tear down for PIPageEditor creation and disposal
+ *
+ */
+public interface IFinalizeTrace {
+	
+	/* this routine is run before editor UID is disposed */
+	public void runOnDispose();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IImportMenu.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import org.eclipse.jface.action.Action;
+
+
+public interface IImportMenu extends IMenu
+{
+//	public JMenuItem getImportMenuItem();
+	public Action getIncludeAction();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IImportableTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import java.io.File;
+
+public interface IImportableTrace extends ITrace
+{
+	public File getTraceFile();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IMenu.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+public abstract interface IMenu 
+{
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IOpenOtherMenu.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import org.eclipse.jface.action.Action;
+
+public interface IOpenOtherMenu extends IMenu
+{
+	public Action getOpenOtherAction();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IOpenOtherTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import java.io.File;
+
+public interface IOpenOtherTrace extends ITrace
+{
+	public File getTraceFile();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IRecordable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import java.io.Serializable;
+
+public interface IRecordable extends ITrace
+{
+/*	
+ * The Serializable object this method returns is saved in to the .bap file when
+ * analysis is saved. The Serializable object shouldn't contain plugins
+ * trace data since it is automatically saved through a different mechanism.
+ */
+	public Serializable getAdditionalData(); 
+								 
+/*
+ * AbstractPiPlugin receives the saved Serializable object via this method when .bap file is loaded.
+ */	
+	public void setAdditionalData(int graphIndex, Serializable data);
+	
+	public int getGraphCount();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IReportable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+import org.eclipse.jface.action.MenuManager;
+
+public interface IReportable extends ITrace
+{
+	/*
+	 * Hashtable key should contain an Object (e.g. an Integer representing thread id) and value a Vector which contains Strings
+	 */
+	public static final Boolean SORT_BY_NAME   = Boolean.TRUE;
+	public static final Boolean SORT_BY_NUMBER = Boolean.FALSE;
+	
+	public ArrayList<String>  getColumnNames(); // table column names
+	public ArrayList<Boolean> getColumnSortTypes(); // This gives feedback to the system whether column data strings should be sorted by name or the first number they may contain. 
+										// Boolean values SORT_BY_NAME and SORT_BY_NUMBER are meant to be used to indicate this information.
+	public Hashtable<Integer,Object> getSummaryTable(double startTime, double endTime);
+	public String getActiveInfo(Object key, double startTime, double endTime);
+	public String getGeneralInfo(); // this is reserved for future implementation and has no functionality at the moment
+
+	//	this menu allows plugin to control reporting within the report generator plugin's frame
+	//	public JMenu getReportMenu(Component parentComponent);
+	public MenuManager getReportGeneratorManager();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/ITrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import java.io.File;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
+
+
+public interface ITrace 
+{
+	public Class getTraceClass();
+	public void initialiseTrace(GenericTrace trace);
+	public String getTraceName();
+	public int getTraceId();
+	public ParsedTraceData parseTraceFile(File file /*, ProgressBar progressBar*/) throws Exception;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IViewMenu.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import org.eclipse.jface.action.MenuManager;
+
+public interface IViewMenu extends IAnalysisSpecificMenu
+{
+	public MenuManager getViewOptionManager();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/plugin/model/IVisualizable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.plugin.model;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.visual.GenericTraceGraph;
+import com.nokia.carbide.cpp.internal.pi.visual.GraphDrawRequest;
+
+
+public interface IVisualizable extends ITrace
+{
+	// return whether this plugin's editor pages have been created
+	public boolean arePagesCreated();
+	
+	// set whether this plugin's editor pages have been created
+	public void setPagesCreated(boolean pagesCreated);
+	
+	// the number of editor pages that this plugin will create
+	public int getCreatePageCount();
+	
+	// the index of each page that this plugin will create
+	// return AnalyseTab.NEXT_AVAILABLE_PAGE if you do not care
+	// if a page with that number has already been created, this page will replace it
+	public int getCreatePageIndex(int index);
+	
+	// page index actually assigned
+	// (usually for a page index of AnalyseTab.NEXT_AVAILABLE_PAGE)
+	public void setPageIndex(int index, int pageIndex);
+
+	// the next created page
+	public ProfileVisualiser createPage(int index);
+
+	// the number of graphs that this plugin will create
+	public int getGraphCount();
+	
+	// next graph
+	public GenericTraceGraph getTraceGraph(int graphIndex);
+	
+	// title of next graph
+	public String getGraphTitle(int graphIndex);
+	
+	// PI editor page to contain the graph
+	public int getPageNumber(int graphIndex);
+	
+	// time (in milliseconds) associated with the last sample
+	public Integer getLastSample(int graphIndex);
+	
+	/*
+	 * returns draw request if a graph must be drawn after/on top of another graph
+	 * (e.g. Button trace within CPU Load trace); otherwise, returns null
+	 */
+	public GraphDrawRequest getDrawRequest(int graphIndex);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/properties/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.properties;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.properties.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/properties/PIPropertyPage.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.properties;
+
+import java.io.BufferedInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.util.zip.GZIPInputStream;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IWorkbenchPropertyPage;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+import com.nokia.carbide.cpp.internal.pi.test.AnalysisInfoHandler;
+import com.nokia.carbide.cpp.internal.pi.test.PIAnalysisInfo;
+import com.nokia.carbide.cpp.internal.pi.test.BappeaAnalysisInfo;
+import com.nokia.carbide.cpp.internal.pi.utils.PluginClassLoader;
+
+
+public class PIPropertyPage extends PropertyPage implements
+		IWorkbenchPropertyPage {
+
+	@Override
+	protected Control createContents(Composite parent) {
+		noDefaultAndApplyButton();
+
+		// we will read the first object in the file and use it to
+		IAdaptable resource = this.getElement();
+
+		if (!(resource instanceof IFile))
+			return null;
+
+		IFile file = (IFile) resource;
+		InputStream input = null;
+		
+		// make sure we can open an input stream to the trace file
+		try {
+			input = file.getContents();
+		} catch (CoreException e) {
+			System.out.println(Messages.getString("PIPropertyPage.cannotReadFile") + file.getName()); //$NON-NLS-1$
+			return null;
+		}
+		
+		if (input == null)
+			return null;
+		
+		// the file contains Java objects that have been gziped
+		GZIPInputStream ziss = null;
+		try {
+			ziss = new GZIPInputStream(input);
+		} catch (IOException e) {
+			System.out.println(Messages.getString("PIPropertyPage.cannotReadFile") + file.getName()); //$NON-NLS-1$
+			return null;
+		}
+
+		BufferedInputStream bis = new BufferedInputStream(ziss);
+		ObjectInputStream ois = null;
+		Object ou = null;
+
+	    try {
+			ois = new ObjectInputStream(bis) {
+			    @SuppressWarnings("unchecked") //$NON-NLS-1$
+				protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+			    	// each object read must have a class corresponding to a plugin class
+			    	String name = desc.getName();
+					Class c = PluginInitialiser.getPluginClass(name);
+					
+					if (c == null) {
+						try {
+							c = Class.forName(name);
+						} catch (ClassNotFoundException e) {
+							// see if we have a replacement
+							PluginClassLoader pcl = (PluginClassLoader)PluginInitialiser.getPluginClassLoader();
+							// don't catch for class not found exception, they did it on purpose 
+							// to back out of this missing plugin that exist in data file
+							c = pcl.findClass(name);
+						}
+					}
+					
+			   		return c;
+			    }
+			};
+
+			//read the first object
+           	ou = ois.readObject();
+        }
+    	catch (ClassNotFoundException cnfe) {
+	    }
+	    catch(EOFException eof) {
+	    }
+	    catch (InvalidClassException ie) {
+	    }
+        catch (IOException e) {
+        }
+        catch (Exception eih) {
+        };
+	    
+	    // close the readers
+        if (ois != null)
+			try {
+				ois.close();
+			}
+        	catch (IOException e) {
+			}
+		
+		if (bis != null)
+			try {
+				bis.close();
+			}
+			catch (IOException e) {
+			}
+		
+		if (ziss != null)
+			try {
+				ziss.close();
+			}
+			catch (IOException e) {
+			}
+
+		AnalysisInfoHandler aih = new AnalysisInfoHandler();
+		
+		if (ou instanceof PIAnalysisInfo) {
+			aih.analysisDataReader((PIAnalysisInfo) ou);
+			aih.getAnalysisInfoLabels(parent);
+		} else if (ou instanceof BappeaAnalysisInfo) {
+			aih.analysisDataReader((BappeaAnalysisInfo) ou);
+			aih.getAnalysisInfoLabels(parent);
+		} else {
+			Label label = new Label(parent, SWT.WRAP);
+			label.setText(Messages.getString("PIPropertyPage.noPIinformation")); //$NON-NLS-1$
+		}
+
+		return null;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/properties/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2 @@
+PIPropertyPage.cannotReadFile=Cannot read file 
+PIPropertyPage.noPIinformation=Could not locate Performance Investigator information.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/resolvers/CachedFunctionResolver.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.resolvers;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Hashtable;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.internal.pi.model.FunctionResolver;
+
+
+// re-implement SymbolFileParser for supporting 
+// cached resolver with ROFS symbols
+
+public abstract class CachedFunctionResolver implements FunctionResolver {
+	
+	protected SymbolFileDllItem[] dllList = null;
+	
+	// cache
+	private int cacheSize = 0;
+	private long cacheAddressTable[] = new long[cacheSize];
+	private long mostPopularCache[] = new long[cacheSize];
+	private SymbolFileFunctionItem[] cacheOrderTable = new SymbolFileFunctionItem[cacheSize];
+	private SymbolFileFunctionItem[] mostPopularCacheTable = new SymbolFileFunctionItem[cacheSize];
+	//private int mostPopularHitCount[] = new int[cacheSize];
+	private int mostPopularTableIndex = 0;
+	private int cacheIndex = 0;
+	//private int cacheFoundPopular = 0;
+	//private int cacheFound = 0;
+	//private int cacheNotFound = 0;
+	
+	// whether the resolver has enough information to resolve anything
+	protected boolean ableToResolve = false;
+	
+	private Hashtable<String,Function> knownFunctions = new Hashtable<String,Function>();
+	private Hashtable<String,Binary> knownBinaries = new Hashtable<String,Binary>();
+	
+	protected static class SymbolFileFunctionItem
+	{
+		public String name;
+		public long address;
+	    public long length;
+	    public SymbolFileDllItem dll;
+
+	    public SymbolFileFunctionItem(String name, long address, long length, SymbolFileDllItem dll)
+	    {
+	    	this.name = name;
+	    	this.length = length;
+	    	this.address = address;
+	    	this.dll = dll;
+	    }
+	}
+	
+	protected static class SymbolFileDllItem
+	{
+		public String name;
+		public long start;
+	    public long end;
+	    public ArrayList<SymbolFileFunctionItem> data;
+	    public boolean uninitialised;
+
+	    public SymbolFileDllItem()
+	    {
+	      start = 0;
+	      end = 0;
+	      name = null;
+	      data = new ArrayList<SymbolFileFunctionItem>();
+	      uninitialised = true;
+	    }
+	}
+	
+	// must implement some way to form a DLL list e.g. read rom/rofs symbol file, read obyfile
+	public abstract void parseAndProcessSymbolFile(java.io.File symbolFile);
+	
+	public void addAllToDllList(Collection<SymbolFileDllItem> list) {
+		
+		// if the dll array is empty, create an array based on the input list
+		if (dllList == null) {
+			dllList = new SymbolFileDllItem[list.size()];
+			dllList = list.toArray(dllList);
+		} else {
+			// add the input list to the existing dll array
+			SymbolFileDllItem[] oldList = dllList;
+			Object[] objects = list.toArray();
+			
+			dllList = new SymbolFileDllItem[dllList.length + list.size()];
+			
+			int i = 0;
+			for (int j = 0; j < oldList.length; j++)
+				dllList[i++] = oldList[j];
+			
+			for (int j = 0; j < list.size(); j++)
+				dllList[i++] = (SymbolFileDllItem) objects[j];
+		}
+		
+		// sort the dll list
+		Arrays.sort(dllList, new Comparator<Object>() {
+			
+			public int compare(Object arg0, Object arg1)
+			{
+				return (int) (((SymbolFileDllItem)arg0).start - ((SymbolFileDllItem)arg1).start);
+			}
+		});	
+	}
+	
+	public void clearDllList()
+	{
+		dllList = null;
+	}
+	
+	public CachedFunctionResolver()
+	{
+		this.clearDllList();
+		this.initializeCache(250);
+	}
+
+	public Binary findBinaryForAddress(long address) {
+	  	SymbolFileDllItem item = this.getDllItemForAddress(address);
+	  	if (item != null)
+	  	{
+	  		Binary b = this.knownBinaries.get(item.name);
+	  		
+	  		if (b == null) {
+		  		b = new Binary(item.name);
+		  		b.length = (int)(item.end-item.start);
+		  		b.offsetToCodeStart = 0;
+		  		b.startAddress = item.start;
+				this.knownBinaries.put(item.name, b);
+	  		}
+	  		return b;
+	  	}
+	  	else
+	  		return null;
+//	  	{
+//	  		String bName = "Binary at 0x"+Long.toHexString(address)+" not found;
+//
+//	  		Binary b = this.knownBinaries.get(bName);
+//	  		
+//	  		if (b == null) {
+//		  		b = new Binary(bName);
+//		  		b.length = 0;
+//		  		b.offsetToCodeStart = 0;
+//		  		b.startAddress = address;
+//				this.knownBinaries.put(bName, b);
+//			}
+//	  		return b;
+//	  	}
+	}
+
+	public String findBinaryNameForAddress(long address) {
+	    SymbolFileDllItem foundDllItem = this.getDllItemForAddress(address);
+	    if (foundDllItem != null)
+	    	return foundDllItem.name;
+	    else
+	    	return Messages.getString("CachedFunctionResolver.dllForAddress")+Long.toHexString(address)+Messages.getString("CachedFunctionResolver.notFound");   //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	public Function findFunctionForAddress(long address) {
+	  	SymbolFileFunctionItem item = this.getFunctionItemForAddress(address);
+
+	  	if (item != null)
+	  	{
+	  		String search = item.name + item.dll.name;
+	 		Function f = this.knownFunctions.get(search);
+
+	  		if (f == null) {
+		  		f = new Function(item.name,new Long(item.address),item.dll.name);
+		  		f.offsetFromBinaryStart = item.address-item.dll.start;
+		  		f.length = item.length;
+		  		this.knownFunctions.put(search, f);
+	  		}
+	  		return f;
+	  	}
+	  	else
+	  	{
+	//System.out.println(Long.toHexString(address));
+	  		SymbolFileDllItem dllItem = this.getDllItemForAddress(address);
+	  	  	  		
+	  		if (dllItem != null)
+	  		{
+	  			String fName = Messages.getString("CachedFunctionResolver.functionNotFound1")+Long.toHexString(address)+Messages.getString("CachedFunctionResolver.functionNotFound2"); //$NON-NLS-1$ //$NON-NLS-2$
+	  			
+	  			Function f = this.knownFunctions.get(fName);
+
+	  	  		if (f == null ) {
+	  	  			f = new Function(fName, new Long(dllItem.start), dllItem.name);
+		  			f.offsetFromBinaryStart = address-dllItem.start;
+		  			f.length = 0;
+		  			this.knownFunctions.put(fName, f);
+	  	  		}
+
+	  	  		return f;
+	  		}
+	  		else
+	  			return null;
+//	  		{
+//	  			String fName = Messages.getString("CachedFunctionResolver.functionNotFound1")+Long.toHexString(address)+Messages.getString("CachedFunctionResolver.functionNotFound2"); //$NON-NLS-1$ //$NON-NLS-2$
+//	  			
+//	  			Function f = this.knownFunctions.get(fName);
+//
+//	  	  		if (f == null ) {
+//	  	  			f = new Function(fName, new Long(address),
+//	  	  							 "Binary at 0x" + 
+//									 Long.toHexString(address)+" not found");
+//	  	  			f.offsetFromBinaryStart = 0;
+//	  	  			this.knownFunctions.put(fName, f);
+//	  	  		}
+//
+//	  			return f;
+//	  		}
+	  	}
+	}
+
+	public String findFunctionNameForAddress(long address) {
+	  	SymbolFileFunctionItem item = this.getFunctionItemForAddress(address);
+	  	if (item != null)
+	  	{
+	  		return item.name;
+	  	}
+	  	else
+	  	{
+	  		return Messages.getString("CachedFunctionResolver.functionForAddress")+Long.toHexString(address)+Messages.getString("CachedFunctionResolver.notFound");   //$NON-NLS-1$ //$NON-NLS-2$
+	  	}
+	}
+
+	public String getResolverName() {
+		return Messages.getString("CachedFunctionResolver.symbol");  //$NON-NLS-1$
+	}
+
+	public String getResolverString() {
+	  	return Messages.getString("CachedFunctionResolver.symbolFile");  //$NON-NLS-1$
+	}
+
+	public SymbolFileDllItem getDllItemForAddress(long address)
+	{
+		if (dllList == null)
+			return null;
+		
+		for (int i=0; i < this.dllList.length; i++)
+		{
+			SymbolFileDllItem dllItem = this.dllList[i];
+			if (address >= dllItem.start && address < dllItem.end)
+			{
+				return dllItem;
+			}
+		}
+		return null;
+	}
+
+	private void initializeCache(int size)
+	{
+	    cacheSize = size;
+
+	    cacheAddressTable = new long[cacheSize];
+	    mostPopularCache = new long[cacheSize];
+	    cacheOrderTable = new SymbolFileFunctionItem[cacheSize];
+	    mostPopularCacheTable = new SymbolFileFunctionItem[cacheSize];
+//	    mostPopularHitCount = new int[cacheSize];
+	    mostPopularTableIndex = 0;
+
+	    for (int i=0;i<cacheSize;i++)
+	    {
+	      cacheAddressTable[i] = 0;
+	      mostPopularCache[i] = 0;
+
+	      cacheOrderTable[i] = null;
+	      mostPopularCacheTable[i] = null;
+
+//	      mostPopularHitCount[i] = 0;
+	    }
+	}
+	  
+	private SymbolFileFunctionItem getFunctionItemForAddress(long address)
+	{  	
+		SymbolFileFunctionItem cached = findFromCache(address);
+	    if (cached != null) return cached;
+
+	    SymbolFileDllItem foundDllItem = null;
+
+	    if (this.dllList != null)
+	    	for (int i=0; i < this.dllList.length; i++)
+		    {
+		    	SymbolFileDllItem dllItem = this.dllList[i];
+		    	if (address >= dllItem.start && address < dllItem.end)
+		    	{
+		    		foundDllItem = dllItem;
+		    		break;
+		    	}
+		    }
+
+	    if (foundDllItem != null)
+	    {
+	      int listSize = foundDllItem.data.size();
+	      SymbolFileFunctionItem functionItem;
+	      
+	      for (int i = 0; i + 1 < listSize; i++)
+	      {
+	        functionItem = (SymbolFileFunctionItem)foundDllItem.data.get(i);
+	       
+	        if (address >= functionItem.address && address < functionItem.address+functionItem.length)
+	        {
+	            addToCache(functionItem,address);
+	            return functionItem;
+	        }
+	      }
+	      
+	      // if last item is an entry for a static function area, ignore it
+	      functionItem = (SymbolFileFunctionItem)foundDllItem.data.get(listSize - 1);
+	      
+	      if (!functionItem.name.startsWith(Messages.getString("CachedFunctionResolver.possibleStaticFunction1"))) {	//$NON-NLS-1$
+	          addToCache(functionItem,address);
+	          return functionItem;
+	      }
+	    }
+	    
+	    return null;
+	}
+
+	  private SymbolFileFunctionItem findFromCache(long address)
+	  {
+	    SymbolFileFunctionItem item = null;
+
+	    item = findFromMostPopular(address);
+	    if (item!=null) return item;
+
+	    for (int i=0;i<cacheSize;i++)
+	    {
+	      if (cacheAddressTable[i] == address)
+	      {
+	        item = cacheOrderTable[i];
+	        //System.out.println("Found from cache,adding to most popular");
+//	        cacheFound++;
+	        addToMostPopular(item,address);
+	        break;
+	      }
+	    }
+//	    cacheNotFound++;
+	    //if (item == null) System.out.println("Not found from the cache!!");
+	    return item;
+	  }
+
+	  private void addToCache(SymbolFileFunctionItem item,long address)
+	  {
+	    if (cacheSize == 0) return;
+	    cacheOrderTable[cacheIndex] = item;
+	    cacheAddressTable[cacheIndex] = address;
+
+	    cacheIndex++;
+	    if (cacheIndex == cacheSize) cacheIndex = 0;
+	  }
+
+		/* internal test function : comment out so code coverage looks
+		 * good quantitatively
+	  public void printMostPopularFromCache(int amountToPrint)
+	  {
+	    if (amountToPrint > cacheSize) amountToPrint = cacheSize;
+	    System.out.println(Messages.getString("CachedFunctionResolver.mostPopularFromCache"));  //$NON-NLS-1$
+
+	    for (int i=0;i<amountToPrint;i++)
+	    {
+	      SymbolFileFunctionItem item = mostPopularCacheTable[i];
+	      if (item!=null) System.out.println(item.name+Messages.getString("CachedFunctionResolver.hits")+mostPopularHitCount[i]);  //$NON-NLS-1$
+	      else break;
+	    }
+	    System.out.println(Messages.getString("CachedFunctionResolver.stats"));  //$NON-NLS-1$
+	    int all = cacheFound+cacheFoundPopular+cacheNotFound;
+	    System.out.println(Messages.getString("CachedFunctionResolver.foundFromMostPopularCache")+(cacheFoundPopular*100f/all)+Messages.getString("CachedFunctionResolver.percentageSign"));   //$NON-NLS-1$ //$NON-NLS-2$
+	    System.out.println(Messages.getString("CachedFunctionResolver.foundFromCache")+(cacheFound*100f/all)+Messages.getString("CachedFunctionResolver.percentageSign"));   //$NON-NLS-1$ //$NON-NLS-2$
+	    System.out.println(Messages.getString("CachedFunctionResolver.notFoundFromCache")+(cacheNotFound*100f/all)+Messages.getString("CachedFunctionResolver.percentageSign"));   //$NON-NLS-1$ //$NON-NLS-2$
+
+	    System.out.println(Messages.getString("CachedFunctionResolver.end"));  //$NON-NLS-1$
+	  }
+	  *
+	  */
+
+	  private SymbolFileFunctionItem findFromMostPopular(long address)
+	  {
+	    SymbolFileFunctionItem item = null;
+
+	    int i = 0;
+	    
+	    // until there are a few entries in mostPopularCache[], it's faster not using a binary search
+	    if (mostPopularCache[4] == 0) {
+		    for (;i<cacheSize && mostPopularCache[i] > address;i++)
+		    	;
+	    } else {
+			// use a binary search to find the item
+			int lowerBound = 0;
+			int upperBound = cacheSize - 1;
+		    while (lowerBound <= upperBound) {
+		    	i = (lowerBound + upperBound)/2;
+				if (mostPopularCache[i] == address) {
+					item = mostPopularCacheTable[i];
+		            break;
+				} else if (address > mostPopularCache[i])
+		            upperBound = i - 1;
+		        else
+		        	lowerBound = i + 1;
+		    }
+
+//			// check binary search		    
+//		    int j = 0;
+//		    for (;j<cacheSize && mostPopularCache[j] > address;j++)
+//		    	;
+//		    if (j != i && mostPopularCache[j] > address)
+//		    	System.out.println("binary search failed");
+	    }
+	    
+        if (mostPopularCache[i] == address)
+        {
+          item = mostPopularCacheTable[i];
+//		  mostPopularHitCount[i]++;
+//		  cacheFoundPopular++;
+        }
+
+	    return item;
+	  }
+
+	  private void addToMostPopular(SymbolFileFunctionItem item, long address)
+	  {
+	    // most popular cache is full, delete 20%
+	    if (mostPopularTableIndex == cacheSize)
+	    {
+	       for (int i=(8*(cacheSize/10));i<cacheSize;i++)
+	       {
+	         mostPopularCache[i] = 0;
+	         mostPopularCacheTable[i] = null;
+//	         mostPopularHitCount[i] = 0;
+	       }
+	       mostPopularTableIndex = 8*(cacheSize/10);
+	       //System.out.println("Clearing most popular ");
+	    }
+	    
+	    // add the new item in descending address order, so that we can bail out during search
+	    int i = 0;
+	    
+	    for ( ; i < mostPopularTableIndex && mostPopularCache[i] > address; i++)
+	    	;
+	    
+	    for (int j = mostPopularTableIndex; j > i; j--)
+	    {
+	        mostPopularCacheTable[j] = mostPopularCacheTable[j-1];
+	        mostPopularCache[j] = mostPopularCache[j-1];
+//	        mostPopularHitCount[j] = mostPopularHitCount[j-1];
+	    }
+
+    	mostPopularCache[i] = address;
+    	mostPopularCacheTable[i] = item;
+//    	mostPopularHitCount[i] = 2;
+    	mostPopularTableIndex++;
+	  }
+	  
+	  public boolean canResolve() {
+		  return this.ableToResolve;
+	  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/resolvers/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.resolvers;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.resolvers.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/resolvers/RofsSymbolFileFunctionResolver.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.resolvers;
+
+import java.util.Hashtable;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+
+
+public class RofsSymbolFileFunctionResolver extends SymbolFileFunctionResolver {
+	
+	public Function findFunctionForAddress(long address) {
+		return super.findFunctionForAddress(address);
+	}
+	
+	public void adjustRuntimeBinary(Hashtable<String, Binary> hostNameToBinary) {
+		if (dllList == null)
+			return;
+		
+		for (SymbolFileDllItem dllItem : dllList) {
+			if (dllItem.name != null) {
+				Binary binary = hostNameToBinary.get(dllItem.name);
+				if (binary != null) {
+					dllItem.start += binary.startAddress;
+					dllItem.end += binary.startAddress;
+					for (SymbolFileFunctionItem funcItem : dllItem.data) {
+						funcItem.address += binary.startAddress;
+					}
+				}
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/resolvers/SymbolFileFunctionResolver.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.resolvers;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+public class SymbolFileFunctionResolver extends CachedFunctionResolver {
+	private boolean debug = false;
+	
+	@Override
+	public void parseAndProcessSymbolFile(File symbolFile) {
+	{
+		/*
+		 * From    \\epoc32\\release\\armv5\\urel\\foobar.exe
+		 * f80130b4    0000    __some_func                              k_entry_.o(.emb_text)
+		 * f8013e5c    0014    NKern::SomeFunc(unsigned long&, unsigned long&)  _reka2_ekern.in(.emb_text)
+		 * f9165ea8    0008    thunk{-4} to SomeClass::SomeFunc(CustType*, int(*)(const void*))  SVGEngine.in(.text)
+		 */
+		
+		Pattern binaryLinePattern  = Pattern.compile("From\\p{Blank}+(\\S.+)\\p{Blank}*");	//$NON-NLS-1$
+  		Pattern symbolLinePattern1 = Pattern.compile("(\\p{XDigit}+)\\p{Blank}+(\\p{XDigit}+)\\p{Blank}+((?!\\d)\\S.+)\\p{Blank}+(\\S.+)");	//$NON-NLS-1$
+ 
+		ArrayList<SymbolFileDllItem> dllTable = new ArrayList<SymbolFileDllItem>();
+		SymbolFileDllItem currentDll = null;
+
+	    BufferedReader br;
+		try {
+		    SymbolFileFunctionItem pendingItem = null;
+		    SymbolFileFunctionItem previousItem = null;
+		    
+		    Matcher symbolLineMatcher;
+		    
+			long lineNumber = 0;
+			br = new BufferedReader(new FileReader(symbolFile));
+			this.ableToResolve = true;
+
+			while(br.ready())
+		    {
+		    	String line = br.readLine();
+		    	++lineNumber;
+		    	if (line == null)
+		    		continue;
+		      
+		    	symbolLineMatcher = symbolLinePattern1.matcher(line);
+				
+				if (symbolLineMatcher.matches()) {
+					
+		            long address = Long.parseLong(symbolLineMatcher.group(1),16);
+		            long length = Long.parseLong(symbolLineMatcher.group(2),16);
+		            String name = symbolLineMatcher.group(3).trim();
+		            String section = symbolLineMatcher.group(4);
+		            
+		            if (skipSymbolFromSection(section, length)) {
+		            	continue;
+		            }
+		            
+		            if (currentDll.uninitialised == true)
+		            {
+		              currentDll.uninitialised = false;
+		              currentDll.start = address;
+		            }
+
+		            if ((address+length) <= (currentDll.start+(1024*1024*20)) 
+		            		&& (address+length) >= currentDll.end 
+		            		&& address != 0xffffffffL )
+		            {
+		            	if (pendingItem != null)
+		            	{
+		            		// the pending item has to be completed with the 
+		            		// address known about this function
+		            		long pendingLength = address-pendingItem.address;
+		           			pendingItem.length = pendingLength;
+		           			// the pending item could be completed, add it to the function list
+		           			currentDll.data.add(pendingItem);
+		            		
+		            		pendingItem = null;
+		            	}
+		            	
+		            	if (previousItem != null)
+		            	{
+		            		if (previousItem.address+previousItem.length < address)
+		            		{
+		            			long gapAddress = previousItem.address+previousItem.length;
+		            			long gapLength = address-previousItem.address-previousItem.length;
+		            			
+		           				String gapName = Messages.getString("SymbolFileFunctionResolver.possibleStaticFunction1")+(gapLength)+Messages.getString("SymbolFileFunctionResolver.possibleStaticFunction2")+ //$NON-NLS-1$ //$NON-NLS-2$
+											 	Long.toHexString(gapAddress)+Messages.getString("SymbolFileFunctionResolver.possibleStaticFunction3")+ //$NON-NLS-1$
+											 	Long.toHexString(address);
+		           				SymbolFileFunctionItem gapItem = new SymbolFileFunctionItem(gapName,gapAddress,gapLength,currentDll);
+		           			
+		           				currentDll.data.add(gapItem);
+		            		}
+		            		
+		            		else if (previousItem.address+previousItem.length > address)
+		            		{
+		            			//These overlaps happen in symbol files from some device's ROM
+		            			//and don't seems to be a problem in our code.
+		            			if (debug) {
+			            			String outString = Messages.getString("SymbolFileFunctionResolver.debugOverlap1")+ //$NON-NLS-1$
+	            					Long.toHexString(previousItem.address+previousItem.length)+
+									Messages.getString("SymbolFileFunctionResolver.debugOverlap2")+ //$NON-NLS-1$
+									Long.toHexString(address)+Messages.getString("SymbolFileFunctionResolver.debugOverlap3")+previousItem.name+Messages.getString("SymbolFileFunctionResolver.debugOverlap4")+name; //$NON-NLS-1$ //$NON-NLS-2$
+			            			//GeneralMessages.showWarningMessage(outString);
+		            				System.out.println(outString);
+		            			}
+		            		}
+		            	}
+		            	
+		        		if (length == 0)
+		                {
+		                	currentDll.end = address;
+		                	
+		        			// if the length of this function is not known,
+		        			// add it to be completed when the next function is parsed
+		        			// this assumes that the length of the function is the space
+		        			// between this function and the next function
+		                	pendingItem = new SymbolFileFunctionItem(name,address,length,currentDll);
+		                	
+		                	// update the previous item
+		                	previousItem = pendingItem;
+		                }
+		        		else
+		        		{
+		                	currentDll.end = address+length;
+		                    SymbolFileFunctionItem function = new SymbolFileFunctionItem(name,address,length,currentDll);
+		                    currentDll.data.add(function);
+		                    
+		                    // update the previous item
+		                    previousItem = function;
+		                    
+		                    // there is no pending item since the function was added here
+		                    pendingItem = null;
+		        		}
+		            }
+
+	            } else if (binaryLinePattern.matcher(line).matches()) {
+					
+		          	pendingItem = null;
+		          	previousItem = null;
+
+		            currentDll = new SymbolFileDllItem();
+		            if (line.indexOf('\\') != -1)
+		            {
+		            	currentDll.name = line.substring(line.indexOf('\\'),line.length());
+		            }
+		            else
+		            {
+		            	currentDll.name = line.substring(0,line.length());
+		            }
+		            dllTable.add(currentDll);
+		            
+				} else {
+						
+	            	if (debug) System.out.println(Messages.getString("SymbolFileFunctionResolver.skippingLine")+line); //$NON-NLS-1$
+				}
+		    }
+
+		    if (br != null)
+		    	br.close();
+		} catch (FileNotFoundException e) {
+			GeneralMessages.PiLog(Messages.getString("SymbolFileFunctionResolver.symbol.file1") +  symbolFile + Messages.getString("SymbolFileFunctionResolver.not.found"), GeneralMessages.ERROR); //$NON-NLS-1$ //$NON-NLS-2$
+		} catch (IOException e) {
+			String myMessage = Messages.getString("SymbolFileFunctionResolver.symbol.file2") +  symbolFile + Messages.getString("SymbolFileFunctionResolver.ioexception"); //$NON-NLS-1$ //$NON-NLS-2$
+			GeneralMessages.showErrorMessage(myMessage);
+			GeneralMessages.PiLog(myMessage, GeneralMessages.ERROR);
+		}
+
+	    // this breaks the symbol file parser, use for testing itt trace
+	    //dllTable.clear();
+	    
+	    if (debug) System.out.println(Messages.getString("SymbolFileFunctionResolver.dllCount")+dllTable.size()); //$NON-NLS-1$
+	    addAllToDllList(dllTable);
+	  }
+	}
+
+	private boolean skipSymbolFromSection(String section, long length) {
+        
+        if (section.endsWith("(.data)") || section.endsWith("(.bss)") || section.endsWith("(linker$$defined$$symbols)")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        	return true;
+        }
+        
+        if (length == 0 && section.endsWith("(.init_array)")) { //$NON-NLS-1$
+        	return true;
+        }
+        
+        if (section.contains("(.data_")) {	// (.data__ZZ33ifPowerTraceIdIsEnabledCallCbOncePFvPvES_mE9isPrinted) //$NON-NLS-1$
+        	return true;
+        }
+        
+		return false;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/resolvers/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,22 @@
+CachedFunctionResolver.notFound=\ not found
+CachedFunctionResolver.dllForAddress=Dll for address 0x
+CachedFunctionResolver.functionForAddress=Function for address 0x
+CachedFunctionResolver.symbol=Symbol
+CachedFunctionResolver.symbolFile=symbol file
+CachedFunctionResolver.functionNotFound1=Function at 0x
+CachedFunctionResolver.functionNotFound2=\ not found
+CachedFunctionResolver.possibleStaticFunction1=Possible static function with length of 
+SymbolFileFunctionResolver.possibleStaticFunction2=\ bytes at 0x
+SymbolFileFunctionResolver.possibleStaticFunction3=\ - 
+SymbolFileFunctionResolver.debugOverlap1=Problem in Symbol File: Overlapping functions 0x
+SymbolFileFunctionResolver.debugOverlap2=\ - 0x
+SymbolFileFunctionResolver.debugOverlap3=\ 
+SymbolFileFunctionResolver.debugOverlap4=\ and 
+SymbolFileFunctionResolver.skippingLine=Skipping line 
+SymbolFileFunctionResolver.symbol.file1=Symbol file 
+SymbolFileFunctionResolver.symbol.file2=Symbol file 
+SymbolFileFunctionResolver.ioexception=\ cannot be read properly, it throws IOException
+SymbolFileFunctionResolver.dllCount=Dll count 
+SymbolFileFunctionResolver.not.found=\ not found.
+SymbolFileFunctionResolver.possibleStaticFunction1=Possible static function with length of 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.save;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.save.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/SaveSamplesPage.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.save;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.IDialogPage;
+import org.eclipse.jface.viewers.DecoratingLabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
+
+import com.nokia.carbide.cpp.pi.ComNokiaCarbidePiHelpIDs;
+
+/**
+ * The SaveSamplesPage wizard page allows setting the containing workspace folder
+ * for the saved sample data as well as the file name. The page will only
+ * accept a file name without the extension OR with the extension .csv.
+ */
+
+public class SaveSamplesPage extends WizardPage {
+
+	// Provides all folders in the workspace
+	private class ProjectContentProvider
+	extends WorkbenchContentProvider
+	implements ITreeContentProvider
+	{
+		// local version just to prevent getChildren/hadChild getting stuck
+		// calling each other
+		private Object[] localGetChildren(Object arg0) {
+			ArrayList<Object> returnList = new ArrayList<Object>();
+			Object[] children = super.getChildren(arg0);
+			for (Object child: children) {
+				if (child instanceof IViewSite || 
+					child instanceof IWorkspaceRoot || 
+					child instanceof IFolder)
+				{
+					returnList.add(child);
+				} else if (child instanceof IProject) {
+					if (((IProject)child).isOpen()) {
+						returnList.add(child);
+					}
+				}
+			}
+			return returnList.toArray(new Object[returnList.size()]);
+		}
+
+		public Object[] getChildren(Object arg0) {
+			return localGetChildren(arg0);
+		}
+
+		public Object getParent(Object arg0) {
+			return super.getParent(arg0);
+		}
+
+		public boolean hasChildren(Object arg0) {
+			if (localGetChildren(arg0).length > 0) {
+				return true;
+			}
+			return false;
+		}
+
+		public Object[] getElements(Object arg0) {
+			return super.getElements(arg0);
+		}
+
+		public void dispose() {
+			super.dispose();
+		}
+
+		public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
+			super.inputChanged(arg0, arg1, arg2);
+		}
+	}
+
+//	private Text containerText;
+
+	private Text fileText;
+
+	private ISelection selection;
+	
+	private TreeViewer outputChooserTreeViewer;
+
+	/**
+	 * Constructor for SampleNewWizardPage.
+	 * 
+	 * @param pageName
+	 */
+	public SaveSamplesPage(ISelection selection) {
+		super("wizardPage"); //$NON-NLS-1$
+		setTitle(Messages.getString("SaveSamplesPage.CVSFileForData")); //$NON-NLS-1$
+		setDescription(Messages.getString("SaveSamplesPage.SpecifyFileWithCSVExtension")); //$NON-NLS-1$
+		this.selection = selection;
+	}
+
+	/**
+	 * @see IDialogPage#createControl(Composite)
+	 */
+	public void createControl(Composite parent) {
+		Composite container = new Composite(parent, SWT.NULL);
+		GridLayout layout = new GridLayout();
+		container.setLayout(layout);
+		layout.numColumns = 1;
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(container, ComNokiaCarbidePiHelpIDs.PI_SAVE_SAMPLES_WIZARD_PAGE);
+		createProjectComposite(container);
+		GridData gd;
+
+		Label fileLabel = new Label(container, SWT.NONE);
+		fileLabel.setText(Messages.getString("SaveSamplesPage.OutputFileName")); //$NON-NLS-1$
+		fileText = new Text(container, SWT.BORDER | SWT.SINGLE);
+		gd = new GridData(GridData.FILL_HORIZONTAL);
+		fileText.setLayoutData(gd);
+		fileText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				dialogChanged();
+			}
+		});
+
+		initialize();
+		dialogChanged();
+		setControl(container);
+	}
+
+	/**
+	 * Tests if the current workbench selection is a suitable container to use.
+	 */
+
+	private void initialize() {
+		if (selection != null && selection.isEmpty() == false
+				&& selection instanceof IStructuredSelection) {
+			IStructuredSelection ssel = (IStructuredSelection) selection;
+			if (ssel.size() > 1)
+				return;
+		}
+		fileText.setText("new_file.csv"); //$NON-NLS-1$
+	}
+
+	/**
+	 * Ensures that both text fields are set.
+	 */
+
+	private void dialogChanged() {
+		String fileName = getFileName();
+
+		if (outputChooserTreeViewer.getTree().getSelection().length < 1) {
+			updateStatus(ERROR, Messages.getString("SaveSamplesPage.ProjectFolderRequired")); //$NON-NLS-1$
+			return;
+		}
+
+		if (fileName.length() == 0) {
+			updateStatus(ERROR, Messages.getString("SaveSamplesPage.FileNameRequired")); //$NON-NLS-1$
+			return;
+		}
+		if (fileName.replace('\\', '/').indexOf('/', 1) > 0) {
+			updateStatus(ERROR, Messages.getString("SaveSamplesPage.FileNameMustBeValid")); //$NON-NLS-1$
+			return;
+		}
+		int dotLoc = fileName.lastIndexOf('.');
+		if (dotLoc != -1) {
+			String ext = fileName.substring(dotLoc + 1);
+			if (ext.equalsIgnoreCase("csv") == false) { //$NON-NLS-1$
+				updateStatus(ERROR, Messages.getString("SaveSamplesPage.FileExtensionMustBeCSV")); //$NON-NLS-1$
+				return;
+			}
+		}
+		
+		TreeSelection selection = (TreeSelection) outputChooserTreeViewer.getSelection();
+		if (   (selection != null)
+			&& (selection.getFirstElement() != null)
+			&& (selection.getFirstElement() instanceof IContainer)) {
+			IContainer container = (IContainer) selection.getFirstElement();
+			String file = fileName;
+			
+			if (dotLoc == -1)
+			{
+				file += ".csv"; //$NON-NLS-1$
+			}
+			if (container.getFile(new Path(file)).exists()) {
+				updateStatus(WARNING, Messages.getString("SaveSamplesPage.WarningFileExists")); //$NON-NLS-1$
+				return;
+			}
+		}
+
+		updateStatus(WARNING, null);
+	}
+
+	private void updateStatus(int messageType, String message) {
+		setMessage(message, messageType);
+		setPageComplete(messageType != ERROR);
+	}
+
+	public IPath getContainerName() {
+		
+		TreeSelection selection = (TreeSelection) outputChooserTreeViewer.getSelection();
+		if (   (selection != null)
+			&& (selection.getFirstElement() != null)
+			&& (selection.getFirstElement() instanceof IContainer)) {
+			IContainer container = (IContainer) selection.getFirstElement();
+			return container.getFullPath();
+		}
+		return null;
+	}
+
+	public String getFileName() {
+		return fileText.getText();
+	}
+	
+	/**
+	 * This method initializes projectComposite	
+	 *
+	 */
+	private void createProjectComposite(Composite container) {
+		GridLayout gridLayout2 = new GridLayout();
+		gridLayout2.numColumns = 2;
+		Composite projectComposite = new Composite(container, SWT.NONE);
+		projectComposite.setLayout(gridLayout2);
+		projectComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		outputChooserTreeViewer = new TreeViewer(projectComposite, SWT.BORDER);
+		outputChooserTreeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		outputChooserTreeViewer.setContentProvider(new ProjectContentProvider());
+		outputChooserTreeViewer.setLabelProvider(new DecoratingLabelProvider(
+								new WorkbenchLabelProvider(), 
+								PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator()));
+		outputChooserTreeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot());
+		outputChooserTreeViewer.getTree().addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				dialogChanged();
+			}
+		});
+
+		createButtonComposite(projectComposite);
+	}
+	
+	private void createButtonComposite(Composite projectComposite) {
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 1;
+		Composite buttonComposite = new Composite(projectComposite, SWT.NONE);
+		buttonComposite.setLayout(gridLayout);
+		buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
+		Button createButton = new Button(buttonComposite, SWT.PUSH);
+		createButton.setText(Messages.getString("SaveSamplesPage.CreateEmptyProject")); //$NON-NLS-1$
+		createButton.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				// get a standard Eclipse Wizard for creating folder
+				IWorkbenchWizard wizard = new BasicNewProjectResourceWizard();
+				wizard.init(PlatformUI.getWorkbench(), new TreeSelection());
+				WizardDialog dialog = new WizardDialog(getShell(), wizard);
+				dialog.open();
+				if (outputChooserTreeViewer.getTree().getItemCount() == 1) {
+					dialogChanged();
+				}
+			}
+		});
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/SaveSamplesWizard.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.save;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
+
+
+public class SaveSamplesWizard extends Wizard implements INewWizard {
+
+	private SaveSamplesPage page;
+	private ISelection selection;
+	private ISaveSamples saveSamples;
+	private String saveSamplesFileContents;
+	
+	private   boolean writeInProgress = false;
+	protected boolean canceled        = false;
+	private IFile file;
+
+	/**
+	 * Constructor for SampleNewWizard.
+	 */
+	public SaveSamplesWizard(ISaveSamples saveSamples) {
+		super();
+		this.saveSamples = saveSamples;
+		this.setWindowTitle(Messages.getString("SaveSamplesWizard.SavingSamples")); //$NON-NLS-1$
+		setNeedsProgressMonitor(true);
+	}
+	
+	/**
+	 * Adding the page to the wizard.
+	 */
+	public void addPages() {
+		this.page = new SaveSamplesPage(this.selection);
+		addPage(this.page);
+	}
+
+	/**
+	 * This method is called when 'Finish' button is pressed in
+	 * the wizard. We will create an operation and run it
+	 * using the wizard as execution context.
+	 */
+	public boolean performFinish() {
+		final IPath containerName = page.getContainerName();
+		String fileName = page.getFileName();
+
+		int dotLoc = fileName.lastIndexOf('.');
+		if (dotLoc == -1)
+		{
+			fileName += ".csv"; //$NON-NLS-1$
+		}
+		
+		final String fileNameFinal = fileName;
+
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		final IResource resource = root.findMember(containerName);
+
+		this.saveSamples.clear();
+		this.canceled = false;
+		this.file = null;
+
+		IRunnableWithProgress op = new IRunnableWithProgress() {
+			public void run(IProgressMonitor monitor)
+						throws InvocationTargetException, InterruptedException {
+				monitor.worked(1);
+				try {
+					// find the file path in the workspace
+					if (!resource.exists() || !(resource instanceof IContainer)) {
+						throwCoreException(Messages.getString("SaveSamplesWizard.ProjectFolder") + containerName + Messages.getString("SaveSamplesWizard.doesNotExist"));  //$NON-NLS-1$//$NON-NLS-2$
+					}
+					
+					IContainer container = (IContainer) resource;
+					file = container.getFile(new Path(fileNameFinal));
+
+					// save samples, several at a time, to the output file
+					writeInProgress = true;
+					while (writeInProgress) {
+						if (monitor.isCanceled()) {
+							canceled = true;
+							return;
+						}
+						writeOneSampleSet(monitor);
+					}
+					if (monitor.isCanceled()) {
+						canceled = true;
+						return;
+					}
+
+					// open the output file for editing
+					monitor.setTaskName(Messages.getString("SaveSamplesWizard.OpeningFileForEditing")); //$NON-NLS-1$
+					getShell().getDisplay().asyncExec(new Runnable() {
+						public void run() {
+							IWorkbenchPage page =
+								PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+							try {
+								IDE.openEditor(page, file, true);
+							} catch (PartInitException e) {
+							}
+						}
+					});
+					monitor.worked(1);
+				} catch (CoreException e) {
+					throw new InvocationTargetException(e);
+				}
+				if (monitor.isCanceled()) {
+					canceled = true;
+					return;
+				}
+			}
+		};
+		try {
+			getContainer().run(true, true, op);
+		} catch (InterruptedException e) {
+			canceled = true;
+		} catch (InvocationTargetException e) {
+			Throwable realException = e.getTargetException();
+			MessageDialog.openError(getShell(), Messages.getString("SaveSamplesWizard.Error"), realException.getLocalizedMessage()); //$NON-NLS-1$
+		}
+		
+		if (canceled && (file != null)) {
+			try {
+				file.delete(true, false, new NullProgressMonitor());
+			} catch (CoreException coreEx) {
+				MessageDialog.openError(getShell(), Messages.getString("SaveSamplesWizard.Error"), coreEx.getLocalizedMessage()); //$NON-NLS-1$
+			}
+		}
+
+		return true;
+	}
+		
+	private void writeOneSampleSet(IProgressMonitor monitor) throws CoreException {
+
+		InputStream stream;
+		
+		try {
+			if (saveSamples.getIndex() == 0) {
+				monitor.setTaskName(Messages.getString("SaveSamplesWizard.WritingSamples")); //$NON-NLS-1$
+				stream = openContentStream();
+				if (file.exists()) {
+					file.setContents(stream, true, true, monitor);
+				} else {
+					file.create(stream, true, monitor);
+				}
+				stream.close();
+			} else { 
+				stream = openContentStream();
+				if (stream == null) {
+					writeInProgress = false;
+					return;
+				}
+
+				String taskName = Messages.getString("SaveSamplesWizard.WritingSamples"); //$NON-NLS-1$
+				if (saveSamples.getIndex() > 0)
+					taskName += Messages.getString("SaveSamplesWizard.alreadyWrtten1") + saveSamples.getIndex() + Messages.getString("SaveSamplesWizard.alreadyWrtten2"); //$NON-NLS-1$ //$NON-NLS-2$
+				monitor.setTaskName(taskName);
+				file.appendContents(stream, true, false, monitor);
+				stream.close();
+			}
+		} catch (IOException e) {
+		}
+	}
+	
+	/**
+	 * We will initialize file contents with a sample text.
+	 */
+	private InputStream openContentStream() {
+		Display.getDefault().syncExec(new Runnable() {
+			public void run() {
+				saveSamplesFileContents = saveSamples.getData();
+			}
+		});
+		if (saveSamplesFileContents == null)
+			return null;
+		
+		return new ByteArrayInputStream(saveSamplesFileContents.getBytes());
+	}
+
+	private void throwCoreException(String message) throws CoreException {
+		IStatus status =
+			new Status(IStatus.ERROR, "junk", IStatus.OK, message, null); //$NON-NLS-1$
+		throw new CoreException(status);
+	}
+
+	/**
+	 * We will accept the selection in the workbench to see if
+	 * we can initialize from it.
+	 * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
+	 */
+	public void init(IWorkbench workbench, IStructuredSelection selection) {
+		this.selection = selection;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/SaveTableWizard.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.save;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveTable;
+
+public class SaveTableWizard extends Wizard implements INewWizard {
+
+	/**
+	 * This is a sample new wizard. Its role is to create a new file 
+	 * resource in the provided container. If the container resource
+	 * (a folder or a project) is selected in the workspace 
+	 * when the wizard is opened, it will accept it as the target
+	 * container. The wizard creates one file with the extension
+	 * "mpe". If a sample multi-page editor (also available
+	 * as a template) is registered for the same extension, it will
+	 * be able to open it.
+	 */
+
+	private SaveTableWizardPage page;
+	private ISelection selection;
+	private ISaveTable saveTable;
+	private String saveTableFileContents;
+
+	/**
+	 * Constructor for SampleNewWizard.
+	 */
+	public SaveTableWizard(ISaveTable saveTable) {
+		super();
+		this.saveTable = saveTable;
+		this.setWindowTitle(Messages.getString("SaveTableWizard.SavingTableData")); //$NON-NLS-1$
+		setNeedsProgressMonitor(true);
+	}
+	
+	/**
+	 * Adding the page to the wizard.
+	 */
+
+	public void addPages() {
+		page = new SaveTableWizardPage(selection);
+		addPage(page);
+	}
+
+	/**
+	 * This method is called when 'Finish' button is pressed in
+	 * the wizard. We will create an operation and run it
+	 * using wizard as execution context.
+	 */
+	public boolean performFinish() {
+		final IPath containerName = page.getContainerName();
+		final String fileName = page.getFileName();
+		IRunnableWithProgress op = new IRunnableWithProgress() {
+			public void run(IProgressMonitor monitor) throws InvocationTargetException {
+				try {
+					doFinish(containerName, fileName, monitor);
+				} catch (CoreException e) {
+					throw new InvocationTargetException(e);
+				} finally {
+					monitor.done();
+				}
+			}
+		};
+		try {
+			getContainer().run(true, false, op);
+		} catch (InterruptedException e) {
+			return false;
+		} catch (InvocationTargetException e) {
+			Throwable realException = e.getTargetException();
+			MessageDialog.openError(getShell(), Messages.getString("SaveTableWizard.Error"), realException.getMessage()); //$NON-NLS-1$
+			return false;
+		}
+		return true;
+	}
+	
+	/**
+	 * The worker method. It will find the container, create the
+	 * file if missing or just replace its contents, and open
+	 * the editor on the newly created file.
+	 */
+
+	private void doFinish(
+		IPath containerName,
+		String fileName,
+		IProgressMonitor monitor)
+		throws CoreException {
+		// create a sample file
+		monitor.beginTask(Messages.getString("SaveTableWizard.Creating") + fileName, 3); //$NON-NLS-1$
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IResource resource = root.findMember(containerName);
+		if (!resource.exists() || !(resource instanceof IContainer)) {
+			throwCoreException(Messages.getString("SaveTableWizard.ProjectFolder") + containerName + Messages.getString("SaveTableWizard.doesNotExist"));  //$NON-NLS-1$//$NON-NLS-2$
+		}
+		monitor.worked(1);
+		monitor.setTaskName(Messages.getString("SaveTableWizard.WritingTableData")); //$NON-NLS-1$
+		IContainer container = (IContainer) resource;
+		final IFile file = container.getFile(new Path(fileName));
+		try {
+			InputStream stream = openContentStream();
+			if (file.exists()) {
+				file.setContents(stream, true, true, monitor);
+			} else {
+				file.create(stream, true, monitor);
+			}
+			stream.close();
+		} catch (IOException e) {
+		}
+		monitor.worked(1);
+		monitor.setTaskName(Messages.getString("SaveTableWizard.OpeningFileForEditing")); //$NON-NLS-1$
+		getShell().getDisplay().asyncExec(new Runnable() {
+			public void run() {
+				IWorkbenchPage page =
+					PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+				try {
+					IDE.openEditor(page, file, true);
+				} catch (PartInitException e) {
+				}
+			}
+		});
+		monitor.worked(1);
+	}
+	
+	/**
+	 * We will initialize file contents with a sample text.
+	 */
+	private InputStream openContentStream() {
+		Display.getDefault().syncExec(new Runnable() {
+			public void run() {
+				saveTableFileContents = saveTable.getData();;
+			}
+		});
+		return new ByteArrayInputStream(saveTableFileContents.getBytes());
+	}
+
+	private void throwCoreException(String message) throws CoreException {
+		IStatus status =
+			new Status(IStatus.ERROR, "junk", IStatus.OK, message, null); //$NON-NLS-1$
+		throw new CoreException(status);
+	}
+
+	/**
+	 * We will accept the selection in the workbench to see if
+	 * we can initialize from it.
+	 * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
+	 */
+	public void init(IWorkbench workbench, IStructuredSelection selection) {
+		this.selection = selection;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/SaveTableWizardPage.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,481 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.save;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.IDialogPage;
+import org.eclipse.jface.viewers.DecoratingLabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
+
+import com.nokia.carbide.cpp.pi.ComNokiaCarbidePiHelpIDs;
+
+/**
+ * The SaveTableWizardPage wizard page allows setting the containing workspace folder
+ * for the saved table data as well as the file name. The page will only accept file
+ * name without the extension OR with the extension .csv.
+ */
+
+public class SaveTableWizardPage extends WizardPage {
+
+	// Provides all folders in the workspace
+	private class ProjectContentProvider
+	extends WorkbenchContentProvider
+	implements ITreeContentProvider
+	{
+		// local version just to prevent getChildren/hadChild getting stuck
+		// calling each other
+		private Object[] localGetChildren(Object arg0) {
+			ArrayList<Object> returnList = new ArrayList<Object>();
+			Object[] children = super.getChildren(arg0);
+			for (Object child: children) {
+				if (child instanceof IViewSite || 
+					child instanceof IWorkspaceRoot || 
+					child instanceof IFolder)
+				{
+					returnList.add(child);
+				} else if (child instanceof IProject) {
+					if (((IProject)child).isOpen()) {
+						returnList.add(child);
+					}
+				}
+			}
+			return returnList.toArray(new Object[returnList.size()]);
+		}
+
+		public Object[] getChildren(Object arg0) {
+			return localGetChildren(arg0);
+		}
+
+		public Object getParent(Object arg0) {
+			return super.getParent(arg0);
+		}
+
+		public boolean hasChildren(Object arg0) {
+			if (localGetChildren(arg0).length > 0) {
+				return true;
+			}
+			return false;
+		}
+
+		public Object[] getElements(Object arg0) {
+			return super.getElements(arg0);
+		}
+
+		public void dispose() {
+			super.dispose();
+		}
+
+		public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
+			super.inputChanged(arg0, arg1, arg2);
+		}
+	}
+
+//	private Text containerText;
+
+	private Text fileText;
+
+	private ISelection selection;
+	
+	private TreeViewer outputChooserTreeViewer;
+
+	/**
+	 * Constructor for SampleNewWizardPage.
+	 * 
+	 * @param pageName
+	 */
+	public SaveTableWizardPage(ISelection selection) {
+		super("wizardPage"); //$NON-NLS-1$
+		setTitle(Messages.getString("SaveTableWizardPage.CVSFileForTableData")); //$NON-NLS-1$
+		setDescription(Messages.getString("SaveTableWizardPage.SpecifyFileWithCSVExtension")); //$NON-NLS-1$
+		this.selection = selection;
+	}
+
+	/**
+	 * @see IDialogPage#createControl(Composite)
+	 */
+	public void createControl(Composite parent) {
+		Composite container = new Composite(parent, SWT.NULL);
+		GridLayout layout = new GridLayout();
+		container.setLayout(layout);
+		layout.numColumns = 1;
+//		layout.verticalSpacing = 9;
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(container, ComNokiaCarbidePiHelpIDs.PI_SAVE_TABLE_WIZARD_PAGE);
+		createProjectComposite(container);
+		GridData gd;
+
+		Label fileLabel = new Label(container, SWT.NONE);
+		fileLabel.setText(Messages.getString("SaveTableWizardPage.OutputFileName")); //$NON-NLS-1$
+		fileText = new Text(container, SWT.BORDER | SWT.SINGLE);
+		gd = new GridData(GridData.FILL_HORIZONTAL);
+		fileText.setLayoutData(gd);
+		fileText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				dialogChanged();
+			}
+		});
+
+		initialize();
+		dialogChanged();
+		setControl(container);
+	}
+
+	/**
+	 * Tests if the current workbench selection is a suitable container to use.
+	 */
+
+	private void initialize() {
+		if (selection != null && selection.isEmpty() == false
+				&& selection instanceof IStructuredSelection) {
+			IStructuredSelection ssel = (IStructuredSelection) selection;
+			if (ssel.size() > 1)
+				return;
+			Object obj = ssel.getFirstElement();
+			if (obj instanceof IResource) {
+				IContainer container;
+				if (obj instanceof IContainer)
+					container = (IContainer) obj;
+				else
+					container = ((IResource) obj).getParent();
+//				containerText.setText(container.getFullPath().toString());
+			}
+		}
+		fileText.setText("new_file.csv"); //$NON-NLS-1$
+	}
+
+	/**
+	 * Ensures that both text fields are set.
+	 */
+
+	private void dialogChanged() {
+//		IResource container = ResourcesPlugin.getWorkspace().getRoot()
+//				.findMember(new Path(getContainerName()));
+		String fileName = getFileName();
+
+		if (outputChooserTreeViewer.getTree().getSelection().length < 1) {
+//		if (getContainerName().length() == 0) {
+			updateStatus(ERROR, Messages.getString("SaveTableWizardPage.ProjectFolderRequired")); //$NON-NLS-1$
+			return;
+		}
+//		if (container == null
+//				|| (container.getType() & (IResource.PROJECT | IResource.FOLDER)) == 0) {
+//			updateStatus("File container must exist");
+//			return;
+//		}
+//		if (!container.isAccessible()) {
+//			updateStatus("Project must be writable");
+//			return;
+//		}
+		if (fileName.length() == 0) {
+			updateStatus(ERROR, Messages.getString("SaveTableWizardPage.FileNameRequired")); //$NON-NLS-1$
+			return;
+		}
+		if (fileName.replace('\\', '/').indexOf('/', 1) > 0) {
+			updateStatus(ERROR, Messages.getString("SaveTableWizardPage.FileNameMustBeValid")); //$NON-NLS-1$
+			return;
+		}
+		int dotLoc = fileName.lastIndexOf('.');
+		if (dotLoc != -1) {
+			String ext = fileName.substring(dotLoc + 1);
+			if (ext.equalsIgnoreCase("csv") == false) { //$NON-NLS-1$
+				updateStatus(ERROR, Messages.getString("SaveTableWizardPage.FileExtensionMustBeCSV")); //$NON-NLS-1$
+				return;
+			}
+		}
+		
+		TreeSelection selection = (TreeSelection) outputChooserTreeViewer.getSelection();
+		if (   (selection != null)
+			&& (selection.getFirstElement() != null)
+			&& (selection.getFirstElement() instanceof IContainer)) {
+			IContainer container = (IContainer) selection.getFirstElement();
+			String file = fileName;
+			
+			if (dotLoc == -1)
+			{
+				file += ".csv"; //$NON-NLS-1$
+			}
+			if (container.getFile(new Path(file)).exists()) {
+				updateStatus(WARNING, Messages.getString("SaveTableWizardPage.WarningFileExists")); //$NON-NLS-1$
+				return;
+			}
+		}
+
+		updateStatus(WARNING, null);
+	}
+
+	private void updateStatus(int messageType, String message) {
+		setMessage(message, messageType);
+		setPageComplete(messageType != ERROR);
+	}
+
+	public IPath getContainerName() {
+		
+		TreeSelection selection = (TreeSelection) outputChooserTreeViewer.getSelection();
+		if (   (selection != null)
+			&& (selection.getFirstElement() != null)
+			&& (selection.getFirstElement() instanceof IContainer)) {
+			IContainer container = (IContainer) selection.getFirstElement();
+			return container.getFullPath();
+		}
+		return null;
+	}
+
+	public String getFileName() {
+		return fileText.getText();
+	}
+
+//	/**
+//	 * Uses the standard container selection dialog to choose the new value for
+//	 * the container field.
+//	 */
+//
+//	private void handleBrowse() {
+//		ContainerSelectionDialog dialog = new ContainerSelectionDialog(
+//				getShell(), ResourcesPlugin.getWorkspace().getRoot(), false,
+//				"Select new file container");
+//		if (dialog.open() == ContainerSelectionDialog.OK) {
+//			Object[] result = dialog.getResult();
+//			if (result.length == 1) {
+//				containerText.setText(((Path) result[0]).toString());
+//			}
+//		}
+//	}
+
+//	private Composite composite = null;
+//	private Composite projectComposite = null;
+//	private Composite buttonComposite = null;
+//	private TreeViewer outputChooserTreeViewer = null;
+//	private Button createButton = null;
+//	private Label fileLabel = null;
+//	private Text outputText = null;
+//	
+//	public boolean validatePage() {
+//		// need to enable finish, setPageComplete eventually check global states
+////		if (outputText.getText().length() < 1 || outputChooserTreeViewer.getTree().getSelection().length < 1) {
+////			setErrorMessage(Messages.getString("NewPIWizardPageOutputTask.choose.output.project")); //$NON-NLS-1$
+////			setPageComplete(false);
+////			return true;
+////		}
+////		setErrorMessage(null);
+////		setPageComplete(true);
+//		return true;
+//	}
+	
+	/**
+	 * This method initializes projectComposite	
+	 *
+	 */
+	private void createProjectComposite(Composite container) {
+		GridLayout gridLayout2 = new GridLayout();
+		gridLayout2.numColumns = 2;
+		Composite projectComposite = new Composite(container, SWT.NONE);
+		projectComposite.setLayout(gridLayout2);
+		projectComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		outputChooserTreeViewer = new TreeViewer(projectComposite, SWT.BORDER);
+		outputChooserTreeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		outputChooserTreeViewer.setContentProvider(new ProjectContentProvider());
+		outputChooserTreeViewer.setLabelProvider(new DecoratingLabelProvider(
+								new WorkbenchLabelProvider(), 
+								PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator()));
+		outputChooserTreeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot());
+		outputChooserTreeViewer.getTree().addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				dialogChanged();
+			}
+		});
+
+		createButtonComposite(projectComposite);
+	}
+	
+	private void createButtonComposite(Composite projectComposite) {
+		GridLayout gridLayout = new GridLayout();
+		gridLayout.numColumns = 1;
+		Composite buttonComposite = new Composite(projectComposite, SWT.NONE);
+		buttonComposite.setLayout(gridLayout);
+		buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
+		Button createButton = new Button(buttonComposite, SWT.PUSH);
+		createButton.setText(Messages.getString("SaveTableWizardPage.CreateEmptyProject")); //$NON-NLS-1$
+		createButton.addSelectionListener(new SelectionListener() {
+
+			public void widgetDefaultSelected(SelectionEvent arg0) {
+			}
+
+			public void widgetSelected(SelectionEvent arg0) {
+				// get a standard Eclipse Wizard for creating folder
+				IWorkbenchWizard wizard = new BasicNewProjectResourceWizard();
+				wizard.init(PlatformUI.getWorkbench(), new TreeSelection());
+				WizardDialog dialog = new WizardDialog(getShell(), wizard);
+				dialog.open();
+				if (outputChooserTreeViewer.getTree().getItemCount() == 1) {
+					dialogChanged();
+				}
+			}
+		});
+	}
+//	
+//	private String generateNpiFileName() {	
+//		// prepare the container folder to look into
+//		TreeSelection selection = (TreeSelection) outputChooserTreeViewer.getSelection();
+//		if (selection == null)
+//			return "";
+//		if (selection.getFirstElement() == null)
+//			return "";
+//		if ((selection.getFirstElement() instanceof IContainer) == false)
+//			return "";
+//		IContainer container = (IContainer) selection.getFirstElement();
+//
+//		String sampleFilename = null;//new java.io.File(NewPIWizardSettings.getInstance().sampleFileName).getName();
+//		String initialFilename;
+//
+//		initialFilename = sampleFilename;
+//		
+//		int dot = initialFilename.lastIndexOf("."); //$NON-NLS-1$
+//		String noExtension;
+//		String baseName;
+//		String finalName;
+//		if (dot > 1) {
+//			noExtension = initialFilename.substring(0, initialFilename.lastIndexOf(".")); //$NON-NLS-1$
+//		} else {
+//			noExtension = initialFilename;
+//		}
+//
+//		Long suffixNumber = new Long(0);
+//		
+//		// just suffix _<number> if the name was derived from input sample name
+//		if (noExtension.lastIndexOf("_") > 1 &&		//$NON-NLS-1$
+//			initialFilename.equalsIgnoreCase(sampleFilename) == false
+//			//&&
+////			isPositiveLong(noExtension.substring(noExtension.lastIndexOf("_") + 1))
+//			) { //$NON-NLS-1$
+//			baseName = noExtension.substring(0, noExtension.lastIndexOf("_"));	//$NON-NLS-1$
+////			if (isPositiveLong(noExtension.substring(noExtension.lastIndexOf("_") + 1))) { //$NON-NLS-1$
+////				suffixNumber = Long.parseLong(noExtension.substring(noExtension.lastIndexOf("_") + 1)); //$NON-NLS-1$
+////			}
+//		} else {
+//			baseName = noExtension;
+//		}
+//		
+//		// check existing npi and bump number
+//		while (container.getFile(new Path(baseName + "_" + suffixNumber.toString() + DOT_CSV)).exists()) { //$NON-NLS-1$
+//			suffixNumber++;
+//		}
+//		
+//		finalName = baseName + "_" + suffixNumber.toString() + DOT_CSV; //$NON-NLS-1$
+//
+//		return finalName;
+//	}
+//
+//	public void setupPageFromFromNewPIWizardSettings() {
+//		outputText.setText(SaveTableWizardPage.DOT_CSV);
+//		outputChooserTreeViewer.getTree().deselectAll();
+//		IContainer outputContainer = null;
+//		if (outputChooserTreeViewer.getSelection() == null ||
+//			outputChooserTreeViewer.getSelection().isEmpty()) {
+//			// stupid eclipse guideline for default container when we found out how to do it
+//			outputContainer = findDefaultContainer();
+//		}
+//		if (outputContainer == null ) {
+//			// select it if it's the only one output project
+//			if (outputChooserTreeViewer.getTree().getItemCount() == 1) {
+//				outputChooserTreeViewer.setSelection(new StructuredSelection(outputChooserTreeViewer.getTree().getItem(0)));
+//			}
+//		} else {
+//			// highlight all items select by expanding to that level
+//			// restoring from file system persistent data could use this
+//			outputChooserTreeViewer.expandToLevel(outputContainer, 0);
+//			outputChooserTreeViewer.setSelection(new StructuredSelection(outputContainer));
+//		}
+//	}
+//
+//	private IContainer findDefaultContainer() {
+//		IContainer result = null;
+//		ISelection selection = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection();
+//		if (selection instanceof IStructuredSelection) {
+//			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+//			Object firstElement = structuredSelection.getFirstElement();
+//			if (firstElement instanceof IFile) {
+//				result = ((IFile)firstElement).getParent();
+//			} else if (firstElement instanceof IContainer) {
+//				result = (IContainer) firstElement;
+//			}
+//		}
+//		if (result == null) {
+//			try {
+//				IResource[] resources = ResourcesPlugin.getWorkspace().getRoot().members();
+//				for (IResource resource : resources) {
+//					if (resource instanceof IContainer) {
+//						result = (IContainer) resource;
+//						break;
+//					}
+//				}
+//			} catch (CoreException e) {
+//				e.printStackTrace();
+//			}
+//		}
+//		return result;
+//	}
+//
+//	public void writePageDataToNewPIWizardSettings() {
+//	}
+//
+//	public void setVisible(boolean visable) {
+//		super.setVisible(visable);
+//		if (visable) {
+//			outputText.setText(SaveTableWizardPage.DOT_CSV);
+//			validatePage();
+//		} else {
+//		}
+//	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/save/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+SaveTableWizard.SavingTableData=Saving Table Data
+SaveTableWizard.Error=Error
+SaveTableWizard.Creating=Creating 
+SaveTableWizard.doesNotExist=" does not exist.
+SaveTableWizard.ProjectFolder=Project folder "
+SaveTableWizard.WritingTableData=Writing table data...
+SaveTableWizard.OpeningFileForEditing=Opening file for editing...
+SaveTableWizardPage.OutputFileName=Output file name:
+SaveTableWizardPage.CVSFileForTableData=CSV File to Contain Table Data
+SaveTableWizardPage.SpecifyFileWithCSVExtension=Specify a *.csv file to contain table data.
+SaveTableWizardPage.ProjectFolderRequired=Project folder must be chosen.
+SaveTableWizardPage.FileNameRequired=File name must be specified.
+SaveTableWizardPage.FileNameMustBeValid=File name must be valid.
+SaveTableWizardPage.FileExtensionMustBeCSV=File extension must be "csv".
+SaveTableWizardPage.WarningFileExists=Warning: .csv file with that name exists in the chosen project folder.
+SaveTableWizardPage.CreateEmptyProject=Create Empty Project...
+SaveSamplesWizard.SavingSamples=Saving Selected Samples
+SaveSamplesWizard.Error=Error
+SaveSamplesWizard.doesNotExist=" does not exist.
+SaveSamplesWizard.ProjectFolder=Project folder "
+SaveSamplesWizard.WritingSamples=Writing samples...
+SaveSamplesWizard.alreadyWrtten1=\ (
+SaveSamplesWizard.alreadyWrtten2=\ written so far)
+SaveSamplesWizard.OpeningFileForEditing=Opening file for editing...
+SaveSamplesPage.OutputFileName=Output file name:
+SaveSamplesPage.CVSFileForData=CSV File to Contain Samples
+SaveSamplesPage.SpecifyFileWithCSVExtension=Specify a *.csv file to contain sample data.
+SaveSamplesPage.ProjectFolderRequired=Project folder must be chosen.
+SaveSamplesPage.FileNameRequired=File name must be specified.
+SaveSamplesPage.FileNameMustBeValid=File name must be valid.
+SaveSamplesPage.FileExtensionMustBeCSV=File extension must be "csv".
+SaveSamplesPage.WarningFileExists=Warning: .csv file with that name exists in the chosen project folder.
+SaveSamplesPage.CreateEmptyProject=Create Empty Project...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/AnalysisInfoHandler.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.test;
+
+import java.sql.Date;
+import java.sql.Time;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Vector;
+import java.util.Map.Entry;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+import com.nokia.carbide.cpp.internal.pi.manager.PluginRegisterer;
+import com.nokia.carbide.cpp.internal.pi.manager.PluginRegistry;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.ITrace;
+
+public class AnalysisInfoHandler
+{
+	private static String NOKIA_INTERNAL = Messages.getString("AnalysisInfoHandler.NokiaInternal"); //$NON-NLS-1$
+
+	private String pi_file_version;
+
+	//private Vector analysis_info;
+	private String profiler_version;
+	private String analyser_version;
+	private String profiling_date;
+	private String analysing_date;
+	private String additional_info_string = "";	//$NON-NLS-1$
+	private HashMap <Integer, Object> trace_additional_info = new HashMap <Integer, Object>();
+	private String defaultTimeScale = Messages.getString("AnalysisInfoHandler.defaultTimeScale"); //$NON-NLS-1$
+//	private ArrayList<EnabledTrace> traceList;
+
+	private PIAnalysisInfo info;
+
+	public AnalysisInfoHandler()
+	{
+		this.pi_file_version  = PIAnalyser.NPIFileFormat;
+		this.profiler_version = Messages.getString("AnalysisInfoHandler.defaultProfilerVersion"); //$NON-NLS-1$
+		this.analyser_version = PIAnalyser.version;
+		this.profiling_date   = Messages.getString("AnalysisInfoHandler.defaultProfilingDate"); //$NON-NLS-1$
+	    Time time = new Time(System.currentTimeMillis());
+	    Date date = new Date(System.currentTimeMillis());
+
+	    this.analysing_date = date.toString() + Messages.getString("AnalysisInfoHandler.space") + time.toString(); //$NON-NLS-1$
+	}
+
+	public void analysisDataReader(BappeaAnalysisInfo data)
+	{
+		// convert legacy class to PIAnalysisInfo
+		if (data != null)
+		{
+			String string;
+			String legacy_file_version = data.bappea_file_version;
+
+			if (   legacy_file_version.startsWith(Messages.getString("AnalysisInfoHandler.unknown")) //$NON-NLS-1$
+				|| legacy_file_version.startsWith(AnalysisInfoHandler.NOKIA_INTERNAL))
+			    this.pi_file_version = legacy_file_version;
+			else
+				this.pi_file_version = AnalysisInfoHandler.NOKIA_INTERNAL + legacy_file_version;
+
+			this.info = new PIAnalysisInfo();
+
+			if (   legacy_file_version.startsWith(Messages.getString("AnalysisInfoHandler.unknown")) //$NON-NLS-1$
+				|| legacy_file_version.startsWith(AnalysisInfoHandler.NOKIA_INTERNAL))
+				this.info.pi_file_version = legacy_file_version;
+			else
+				this.info.pi_file_version = AnalysisInfoHandler.NOKIA_INTERNAL + legacy_file_version;
+
+			this.info.analysis_info   = data.analysis_info;
+
+			string = (String) info.analysis_info.elementAt(0);
+			if ( !string.startsWith(Messages.getString("AnalysisInfoHandler.unknown")) && !string.startsWith(AnalysisInfoHandler.NOKIA_INTERNAL)) //$NON-NLS-1$
+				string = AnalysisInfoHandler.NOKIA_INTERNAL + string;
+			info.analysis_info.set(0, string);
+
+			string = (String) info.analysis_info.elementAt(1);
+			if ( !string.startsWith(Messages.getString("AnalysisInfoHandler.unknown")) && !string.startsWith(AnalysisInfoHandler.NOKIA_INTERNAL)) //$NON-NLS-1$
+				string = AnalysisInfoHandler.NOKIA_INTERNAL + string;
+			info.analysis_info.set(1, string);
+			
+			this.info.trace_info      = new Vector<Object>();
+		    this.info.additional_info = data.additional_info;
+
+		    loadVersionInfo();
+		    loadAdditionalInfoFromNPI();
+
+		    // create a trace list based on hard-coded ordering
+	  		info.trace_info.add(new EnabledTrace(0, Messages.getString("AnalysisInfoHandler.addressThread"))); //$NON-NLS-1$
+		    if ((data.trace_info.size() > 1) && ((Boolean)(data.trace_info.get(1))))
+		    	info.trace_info.add(new EnabledTrace(1, Messages.getString("AnalysisInfoHandler.call"))); //$NON-NLS-1$
+		    if ((data.trace_info.size() > 2) && ((Boolean)(data.trace_info.get(2))))
+		  		info.trace_info.add(new EnabledTrace(2, Messages.getString("AnalysisInfoHandler.memory"))); //$NON-NLS-1$
+		    if ((data.trace_info.size() > 3) && ((Boolean)(data.trace_info.get(3))))
+		  		info.trace_info.add(new EnabledTrace(3, Messages.getString("AnalysisInfoHandler.priority"))); //$NON-NLS-1$
+		    if ((data.trace_info.size() > 4) && ((Boolean)(data.trace_info.get(4))))
+		  		info.trace_info.add(new EnabledTrace(4, Messages.getString("AnalysisInfoHandler.DSP"))); //$NON-NLS-1$
+		    if ((data.trace_info.size() > 5) && ((Boolean)(data.trace_info.get(5))))
+		  		info.trace_info.add(new EnabledTrace(5, Messages.getString("AnalysisInfoHandler.instr"))); //$NON-NLS-1$
+		    if ((data.trace_info.size() > 6) && ((Boolean)(data.trace_info.get(6))))
+		  		info.trace_info.add(new EnabledTrace(6, Messages.getString("AnalysisInfoHandler.TCPIP"))); //$NON-NLS-1$
+		    if ((data.trace_info.size() > 7) && ((Boolean)(data.trace_info.get(7))))
+		  		info.trace_info.add(new EnabledTrace(7, Messages.getString("AnalysisInfoHandler.custom"))); //$NON-NLS-1$
+		    if ((data.trace_info.size() > 8) && ((Boolean)(data.trace_info.get(8))))
+		  		info.trace_info.add(new EnabledTrace(8, Messages.getString("AnalysisInfoHandler.map"))); //$NON-NLS-1$
+		    if ((data.trace_info.size() > 9) && ((Boolean)(data.trace_info.get(9))))
+		  		info.trace_info.add(new EnabledTrace(9, Messages.getString("AnalysisInfoHandler.IRQSWI"))); //$NON-NLS-1$
+		    if ((data.trace_info.size() > 10) && ((Boolean)(data.trace_info.get(10))))
+		  		info.trace_info.add(new EnabledTrace(10, Messages.getString("AnalysisInfoHandler.button"))); //$NON-NLS-1$
+		}
+		else
+		{
+		    this.analyser_version = Messages.getString("AnalysisInfoHandler.unknown"); //$NON-NLS-1$
+		    this.analysing_date   = Messages.getString("AnalysisInfoHandler.unknown"); //$NON-NLS-1$
+		    this.profiler_version = Messages.getString("AnalysisInfoHandler.unknown"); //$NON-NLS-1$
+		    this.pi_file_version  = Messages.getString("AnalysisInfoHandler.unknownFileVersion"); //$NON-NLS-1$
+		}
+	}
+
+	public void analysisDataReader(PIAnalysisInfo data)
+	{
+		if (data != null)
+		{
+		    this.info = data;
+		    this.pi_file_version = data.pi_file_version;
+		    loadVersionInfo();
+		    loadAdditionalInfoFromNPI();
+		}
+		else
+		{
+		    this.analyser_version = Messages.getString("AnalysisInfoHandler.unknown"); //$NON-NLS-1$
+		    this.analysing_date   = Messages.getString("AnalysisInfoHandler.unknown"); //$NON-NLS-1$
+		    this.profiler_version = Messages.getString("AnalysisInfoHandler.unknown"); //$NON-NLS-1$
+		    this.pi_file_version  = Messages.getString("AnalysisInfoHandler.unknownFileVersion"); //$NON-NLS-1$
+		    this.additional_info_string = Messages.getString("AnalysisInfoHandler.unknown"); //$NON-NLS-1$
+		}
+	}
+
+	public Vector getTraceInfo() {
+		if (this.info.trace_info == null)
+			this.info.trace_info = new Vector<Object>();
+
+		return this.info.trace_info;
+	}
+
+	private void loadVersionInfo()
+	{
+		this.profiler_version = (String) info.analysis_info.elementAt(0);
+		this.analyser_version = (String) info.analysis_info.elementAt(1);
+		this.profiling_date   = (String) info.analysis_info.elementAt(2);
+		this.analysing_date   = (String) info.analysis_info.elementAt(3);
+		if (info.analysis_info.size() > 4)  //file format version 1.2 or newer
+			this.defaultTimeScale = (String) info.analysis_info.elementAt(4);
+
+		// ignore info.additional_info, which only contains a single placeholder button trace comment
+	}
+	
+	private void loadAdditionalInfoFromNPI()
+	{
+		int additional_info_size = info.additional_info.size();
+		for (int i = 0; i < additional_info_size; i++) {
+			Object additional = info.additional_info.elementAt(i);
+			if (additional instanceof TraceAdditionalInfo) {
+				TraceAdditionalInfo traceInfo = (TraceAdditionalInfo)additional;
+				Set<Entry<Integer, Vector<Object>>> infoSet = traceInfo.getAdditionalInfoSet();
+				for (Entry<Integer, Vector<Object>> info : infoSet) {
+					// this code is clumsy because the plugin, not the trace, has the trace ID info
+					PluginRegisterer.registerAllPlugins();	// I do not agree this kind of laziness for loading, but what else can we do now
+					Enumeration<AbstractPiPlugin> enuPlugins = PluginRegistry.getInstance().getRegistryEntries(); //$NON-NLS-1$
+					while (enuPlugins.hasMoreElements()) {	// find plugin corresponding to this info and ask it to process
+						AbstractPiPlugin plugin = enuPlugins.nextElement();
+						if (!(plugin instanceof ITrace)) {
+							continue;
+						}
+						if (!info.getKey().equals(((ITrace)plugin).getTraceId())) {
+							continue;
+						}
+						if (plugin instanceof IProvideTraceAdditionalInfo) {
+							((IProvideTraceAdditionalInfo)plugin).additionalInfoToAnalysisInfoHandler(info.getValue(), this);
+							String displayString = ((IProvideTraceAdditionalInfo)plugin).InfoHandlerToDisplayString(this);
+							if (displayString.length() > 0) {
+								this.additional_info_string += ((ITrace)plugin).getTraceName() + ":\n"; //$NON-NLS-1$
+								this.additional_info_string += displayString + "\n"; //$NON-NLS-1$
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	public void setTraceDefinedInfo(int traceId, Object list) {
+		trace_additional_info.put(traceId, list);
+	}
+	
+	public Object getTraceDefinedInfo(int traceId) {
+		Object result = trace_additional_info.get(traceId);
+		return result;
+	}
+
+	public void setFileVersion(String pi_file_version)
+	{
+		this.pi_file_version = pi_file_version;
+	}
+
+	public String getFileVersion()
+	{
+		return this.pi_file_version;
+	}
+
+	public String getAnalysingDate()
+	{
+		return this.analysing_date;
+	}
+
+	public String getProfilingDate()
+	{
+		return this.profiling_date;
+	}
+ 
+	public String getAnalyserVersion()
+	{
+		return this.analyser_version;
+	}
+
+	public String getProfilerVersion()
+	{
+		return this.profiler_version;
+	}
+
+	public String getAdditional_info_string() {
+		return additional_info_string;
+	}
+
+	public void setPITimeScale(String scale)
+	{
+		this.defaultTimeScale = scale;
+	}
+  
+	public String getPITimeScaleString()
+	{
+		return this.defaultTimeScale;
+	}
+  
+	public float getPITimeScaleFloat()
+	{
+		if (this.defaultTimeScale.indexOf("-") != -1) //$NON-NLS-1$
+			return 1.025f;
+		else
+		    return Float.parseFloat(this.defaultTimeScale);
+	}
+  	  
+	//this is used to get data for storing into file system
+	public PIAnalysisInfo getAnalysisInfo()
+	{
+		PIAnalysisInfo info;
+		info = new PIAnalysisInfo();
+	    info.pi_file_version = this.pi_file_version;
+
+	    //creating version info
+	    info.analysis_info.add(this.profiler_version);
+	    info.analysis_info.add(this.analyser_version);
+	    info.analysis_info.add(this.profiling_date);
+	    info.analysis_info.add(this.analysing_date);
+	    info.analysis_info.add(this.defaultTimeScale);
+
+	    //creating the trace info vector
+	    info.trace_info.clear();
+
+	    return info;
+	}
+	
+	// internal test method
+	public void eraseTimeStamp () {
+		int count = analysing_date.length();
+		analysing_date = ""; //$NON-NLS-1$
+		
+		// replace with underscore
+		for (int i = 0; i < count; i++)
+			analysing_date += "_"; //$NON-NLS-1$
+	}
+
+	// return a table of analysis info
+	public Table getAnalysisInfoTable(Composite parent)
+	{
+		TableItem item;
+
+		// create a two column table - descriptions and values
+		Table table = new Table(parent, SWT.HIDE_SELECTION);
+		table.setRedraw(false);
+		table.setHeaderVisible(false);
+		table.setLinesVisible(false);
+		table.setBackground(parent.getBackground());
+
+		TableColumn col1 = new TableColumn(table, SWT.LEFT);
+		TableColumn col2 = new TableColumn(table, SWT.LEFT);
+
+		item = new TableItem(table, SWT.NONE);
+		item.setText(0, Messages.getString("AnalysisInfoHandler.analyzerVersion")); //$NON-NLS-1$
+		item.setText(1, this.getAnalyserVersion());
+		item = new TableItem(table, SWT.NONE);
+		item.setText(0, Messages.getString("AnalysisInfoHandler.analyzeFileFormat")); //$NON-NLS-1$
+		item.setText(1, this.pi_file_version);
+		item = new TableItem(table, SWT.NONE);
+		item.setText(0, Messages.getString("AnalysisInfoHandler.analyzeFileDate")); //$NON-NLS-1$
+		item.setText(1, this.getAnalysingDate());
+
+		item = new TableItem(table, SWT.NONE);
+		item.setText(0, Messages.getString("AnalysisInfoHandler.profilingDate")); //$NON-NLS-1$
+		item.setText(1, this.getProfilingDate());
+		item = new TableItem(table, SWT.NONE);
+
+		// sort by trace id number
+		boolean swapped = true;
+
+		while (swapped) {
+  			EnabledTrace a;
+  			EnabledTrace b;
+  			swapped = false;
+  			for (int i = 0; i < info.trace_info.size() - 1; i++) {
+  				a = (EnabledTrace) info.trace_info.get(i);
+  				b = (EnabledTrace) info.trace_info.get(i + 1);
+  				if (a.traceId > b.traceId) {
+  					info.trace_info.set(i, b);
+  					info.trace_info.set(i + 1, a);
+  					swapped = true;
+  				}
+  			}
+  		}
+
+		item = new TableItem(table, SWT.NONE);
+    	item.setText(0, Messages.getString("AnalysisInfoHandler.traces")); //$NON-NLS-1$
+
+		for (int i = 0; i < info.trace_info.size(); i++) {
+	    	EnabledTrace data = (EnabledTrace) info.trace_info.get(i);
+			item = new TableItem(table, SWT.NONE);
+	    	item.setText(0, Messages.getString("AnalysisInfoHandler.whitespace") + data.traceName); //$NON-NLS-1$
+		}
+		
+		if (additional_info_string != null) {
+			item = new TableItem(table, SWT.NONE);
+			item.setText(additional_info_string);			
+		}
+
+		col1.pack();
+		col2.pack();
+		table.setRedraw(true);
+		return table;
+	}
+
+	// return a table of analysis info
+	public void getAnalysisInfoLabels(Composite parent)
+	{
+		Label label;
+		String string;
+
+		label = new Label(parent, SWT.NONE);
+		string = Messages.getString("AnalysisInfoHandler.analyzerVersion2"); //$NON-NLS-1$
+		label.setText(string + this.getAnalyserVersion());
+		label = new Label(parent, SWT.NONE);
+		string = Messages.getString("AnalysisInfoHandler.analyzeFileFormat2"); //$NON-NLS-1$
+		label.setText(string + this.pi_file_version);
+		label = new Label(parent, SWT.NONE);
+		string = Messages.getString("AnalysisInfoHandler.analyzeFileDate2"); //$NON-NLS-1$
+		label.setText(string + this.getAnalysingDate());
+
+		label = new Label(parent, SWT.NONE);
+
+		// sort by trace id number
+		boolean swapped = true;
+
+		while (swapped) {
+  			EnabledTrace a;
+  			EnabledTrace b;
+  			swapped = false;
+  			for (int i = 0; i < info.trace_info.size() - 1; i++) {
+  				a = (EnabledTrace) info.trace_info.get(i);
+  				b = (EnabledTrace) info.trace_info.get(i + 1);
+  				if (a.traceId > b.traceId) {
+  					info.trace_info.set(i, b);
+  					info.trace_info.set(i + 1, a);
+  					swapped = true;
+  				}
+  			}
+  		}
+
+		label = new Label(parent, SWT.NONE);
+    	label.setText(Messages.getString("AnalysisInfoHandler.traces2")); //$NON-NLS-1$
+
+		for (int i = 0; i < info.trace_info.size(); i++) {
+	    	EnabledTrace data = (EnabledTrace) info.trace_info.get(i);
+			label = new Label(parent, SWT.NONE);
+	    	label.setText(Messages.getString("AnalysisInfoHandler.whitespace2") + data.traceName); //$NON-NLS-1$
+		}
+		
+		if (additional_info_string != null) {
+			label = new Label(parent, SWT.NONE);
+			label.setText(additional_info_string);			
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/BappeaAnalysisInfo.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.test;
+
+import java.io.Serializable;
+import java.util.Vector;
+
+public class BappeaAnalysisInfo implements Serializable
+{
+	private static final long serialVersionUID = -4724464175067752118L;
+
+    public String bappea_file_version;
+    public Vector<Object> analysis_info;
+    public Vector<Object> trace_info;
+    public Vector<Object> additional_info;
+
+	public BappeaAnalysisInfo()
+	{
+		bappea_file_version = Messages.getString("BappeaAnalysisInfo.notDefined"); //$NON-NLS-1$
+		analysis_info   = new Vector<Object>();
+		trace_info      = new Vector<Object>();
+		additional_info = new Vector<Object>();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/EnabledTrace.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.test;
+
+import java.io.Serializable;
+
+
+public class EnabledTrace implements Serializable {
+	private static final long serialVersionUID = -2362976448860231214L;
+
+	int     traceId;
+	String  traceName;
+	
+	public EnabledTrace(int traceId, String traceName) {
+		this.traceId   = traceId;
+		this.traceName = traceName;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/IProvideTraceAdditionalInfo.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.test;
+
+import java.util.Vector;
+
+/**
+ * 
+ * Trace specific support for additional info in NPI file.
+ * Additional info is saved as Vector<Object> in NPI file and loaded as
+ * AnalysisInfoHandler in NPI file during runtime. 
+ * -During load, additional info is transfer to AnalysisInfoHandler
+ * -During save, AnalysisInfoHandler is transfer to additional info
+ * -After import, AnalysisInfoHandler is set up (e.g. with sampleimporter 
+ * data or anything we figure out during import)
+ * -Any modification to additional info with an opened instance of NPI files are done
+ * on AnalysisInfoHandler, and mark the file dirty
+ * 
+ * These allow us to use common write route used by import and save as.
+ * 
+ * Plugins should define their own internal class to encapsulate runtime
+ * structure in AnalysisInfoHandler and use AnalysisInfoHandler.set/getTraceDefinedInfo
+ * to access their own share of additional when NPI file is loaded.
+ * 
+ *
+ */
+public interface IProvideTraceAdditionalInfo {
+	/**
+	 * Set up info handler right after loading .dat file, so we can commit those
+	 * from info handler to additional info with a common write route used by import 
+	 * and save as. Info can be extracted info from importer.
+	 * @param traceAdditionalInfos
+	 */
+	public void setupInfoHandler(AnalysisInfoHandler handler);
+	/**
+	 * Move info from additional info to info handler while loading a NPI file
+	 * @param additional_info
+	 * @param handler
+	 */
+	public void additionalInfoToAnalysisInfoHandler(Vector<Object> additional_info, AnalysisInfoHandler handler);
+	/**
+	 * Move info from info handler to additional info before writing to NPI file
+	 * @param info
+	 * @param handler
+	 */
+	public void analysisInfoHandlerToAdditonalInfo(TraceAdditionalInfo info, AnalysisInfoHandler handler);
+	/**
+	 * @return String representation for additional info used in property page
+	 */
+	public String InfoHandlerToDisplayString(AnalysisInfoHandler handler);	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.test;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.test.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/PIAnalyser.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.test;
+
+import java.awt.Frame;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+
+import com.nokia.carbide.cpp.internal.pi.manager.PluginRegisterer;
+import com.nokia.carbide.cpp.pi.core.SessionPreferences;
+
+
+public class PIAnalyser extends JFrame 
+{
+	private static final long serialVersionUID = 1L;
+
+	public static final String version = "1.1";  //$NON-NLS-1$	// version number is part of program logic, do not externalize
+	public static final String releaseDate = Messages.getString("PIAnalyser.date"); //$NON-NLS-1$
+	public static final String releaseYear = Messages.getString("PIAnalyser.year"); //$NON-NLS-1$
+	
+//	private static boolean disableAllPrintsInGUIRun = true;
+	
+	//this is used to identify changes in NPI file format
+	//update this when new traces are added or old ones modified
+//    public static final String NPIFileFormat = "1.1"; //Performance Investigator 1.0 framework  //$NON-NLS-1$ // version number is part of program logic, do not externalize
+//    public static final String NPIFileFormat = "1.2"; //Performance Investigator 2.0 M1 framework  //$NON-NLS-1$ // version number is part of program logic, do not externalize
+    public static final String NPIFileFormat = "1.3"; //Performance Investigator 2.0 framework  //$NON-NLS-1$ // version number is part of program logic, do not externalize
+    //public static String profilerVersion = "Unknown";
+	public final static boolean VIEWER_MODE = false;
+//	public final static boolean INCLUDE_PLUGINS = true; //if this is set dsp, perf framework
+														//and others are enabled
+	
+	//private TestGUI testGUI = null;
+	private String analyserName;
+//	private JFileChooser crashPreventingFileChooser;
+	
+	private static JFrame frame = null;
+	/**
+	 * This is the default constructor
+	 */
+	private static void setFrame(JFrame newFrame)
+	{
+		frame = newFrame;
+	}
+
+	public PIAnalyser() 
+	{
+        analyserName = Messages.getString("PIAnalyser.0") + PIAnalyser.version; //$NON-NLS-1$
+	    
+	    this.setTitle(analyserName);
+	    
+		initialize();
+		setFrame(this);
+	
+		Exception ex = null;
+		JFileChooser crashPreventingFileChooser;
+		for (int i=0;i<10;i++)
+		{
+			try
+			{
+				crashPreventingFileChooser = new JFileChooser();
+				if (crashPreventingFileChooser != null) break;
+				System.out.println(Messages.getString("PIAnalyser.ok")); //$NON-NLS-1$
+			}
+			catch (Exception e)
+			{
+				ex = e;
+			}
+		}
+		if (ex != null)
+		{
+			System.out.println(Messages.getString("PIAnalyser.cannotInitializeJFileChooser")); //$NON-NLS-1$
+			ex.printStackTrace();
+		}
+	}
+	/**
+	 * This method initializes this
+	 * 
+	 * @return void
+	 */
+	private void initialize() {
+		PluginRegisterer.registerAllPlugins(); //setting up static plugin registry before generating the GUI
+
+//		this.setContentPane(getJContentPane());
+//		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		//configData.loadData();
+
+		int width = SessionPreferences.getInstance().getWindowWidth();
+		int height = SessionPreferences.getInstance().getWindowHeight();
+
+		this.addCloseListener();
+		this.setSize(width, height);
+		this.setVisible(true);
+	}
+	
+	private void addCloseListener()
+	{
+	    this.addWindowListener(
+	        new WindowAdapter()
+	    {
+	      public void windowClosed(WindowEvent we)
+	      {
+	      	System.out.println(Messages.getString("PIAnalyser.closingAnalyser")); //$NON-NLS-1$
+	      	//ConfigurationPanel config = ConfigurationPanel.getInstance();
+	      	//config.saveConfig();
+	      	//JButton button = config.getJButton3();
+	      	//button.doClick();
+	      	
+			//configData.loadData();
+			int width = frame.getWidth();
+			int height = frame.getHeight();
+			SessionPreferences.getInstance().setWindowWidth(width);
+			SessionPreferences.getInstance().setWindowHeight(height);
+			try {
+//				configData.saveData();
+				throw new Exception(Messages.getString("PIAnalyser.fixException")); //$NON-NLS-1$
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+	      	
+	        System.exit(0);
+	      }
+	      public void windowClosing(WindowEvent we)
+		  {
+	      	((Frame)we.getSource()).dispose(); 
+	      }
+	    });
+
+	 }
+	
+	public static JFrame getFrame()
+	{
+	    return frame;
+	}
+	
+// 	public static void main(String args[])
+//	{
+// 	    if (args.length > 0)
+//        {
+// 	        System.out.println("Commandline parameter: "+args[0]);
+// 	        analyserNoGUI(args);
+//        }
+//        else
+//        {
+//    		try {
+//    			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+//    		} catch (Exception e) {
+//    			e.printStackTrace();
+//    		}
+//    		
+//    		// disable all debug prints in releases
+//    		if (PIAnalyser.disableAllPrintsInGUIRun)
+//    		{
+//    			PrintStream nullStream = new PrintStream(
+//    					new OutputStream()
+//    					{
+//    						public void write(){}
+//    						public void write(int i){}
+//    					});
+//    			System.setOut(nullStream);
+//    		}
+//    		
+//            new PIAnalyser();
+//        }
+//
+//        analyserNoGUI(args);
+//        
+//	}
+//    private static void analyserNoGUI(String args[])
+//    {
+//        if (args.length>2)
+//        {
+//            System.out.println("\n\n*********************************************");
+//            System.out.println("Performing scripted analysis");
+//            System.out.println("Symbol file: ("+args[0].toString()+") hmms");
+//            System.out.println("Stream file: "+args[1].toString());
+//            System.out.println("Output file: "+args[2].toString());
+//            System.out.println("*********************************************\n\n");
+//
+//            PluginRegisterer.registerAllPlugins(); //setting up plugin registry
+//            new AnalyseTab(args);
+//        }
+//        else
+//        {
+//            System.out.println("Guidelines: java -mx1200m -jar Analyser_v131.jar <symbol file> <stream file> <output file>");
+//            System.exit(0);
+//        }
+//    }
+    
+ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/PIAnalysisInfo.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.test;
+
+import java.io.Serializable;
+import java.util.Vector;
+
+
+public class PIAnalysisInfo implements Serializable {
+	
+	private static final long serialVersionUID = 7840137496875268566L;
+
+	public String pi_file_version;
+    public Vector<Object> analysis_info;
+    public Vector<Object> trace_info;
+    public Vector<Object> additional_info;
+
+	public PIAnalysisInfo()
+	{
+		pi_file_version = Messages.getString("PIAnalysisInfo.unknown"); //$NON-NLS-1$
+		analysis_info   = new Vector<Object>();
+		trace_info      = new Vector<Object>();
+		additional_info = new Vector<Object>();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/TraceAdditionalInfo.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.test;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Vector;
+import java.util.Map.Entry;
+
+/**
+ * Abstract class as boilerplate for plugins to define their additional info
+ * 
+ */
+public class TraceAdditionalInfo implements Serializable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -5759753038732844008L;
+	
+	private HashMap<Integer, Vector<Object>> additional_info = new HashMap<Integer, Vector<Object>>();
+	
+	public void addAdditionalInfo(int traceId, Vector<Object> additionalInfo) {
+		additional_info.put(new Integer(traceId), additionalInfo);
+	}
+	
+	public Set<Entry<Integer, Vector<Object>>> getAdditionalInfoSet() {
+		return additional_info.entrySet();
+	}
+
+	public int size() {
+		return additional_info.size();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/test/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,38 @@
+BappeaAnalysisInfo.notDefined=not_defined
+PIAnalyser.date=2 Apr 2009
+PIAnalyser.year=2009
+PIAnalyser.0=Performance Investigator Analyser v
+PIAnalyser.ok=Ok\!
+PIAnalyser.cannotInitializeJFileChooser=Could not initialize JFileChooser.. this may cause problems/crashing in file opening
+PIAnalyser.closingAnalyser=Closing Analyser
+PIAnalyser.fixException=SL: fix here
+PIAnalysisInfo.unknown=Unknown
+AnalysisInfoHandler.NokiaInternal=Nokia Internal 
+AnalysisInfoHandler.defaultTimeScale=~1% - 3%
+AnalysisInfoHandler.defaultProfilerVersion=Unknown
+AnalysisInfoHandler.defaultProfilingDate=in history
+AnalysisInfoHandler.space=\ \ 
+AnalysisInfoHandler.unknown=Unknown
+AnalysisInfoHandler.addressThread=Address/Thread
+AnalysisInfoHandler.profilingDate=Profiling date:  
+AnalysisInfoHandler.call=Function Call
+AnalysisInfoHandler.memory=Memory
+AnalysisInfoHandler.priority=Priority
+AnalysisInfoHandler.DSP=DSP
+AnalysisInfoHandler.instr=Dynamic Binary Support
+AnalysisInfoHandler.TCPIP=TCP/IP
+AnalysisInfoHandler.custom=Custom
+AnalysisInfoHandler.map=Map
+AnalysisInfoHandler.IRQSWI=IRQ/SWI
+AnalysisInfoHandler.button=Button
+AnalysisInfoHandler.unknownFileVersion=1.0 or earlier
+AnalysisInfoHandler.analyzerVersion=Analyzer version:  
+AnalysisInfoHandler.analyzeFileFormat=Analyzer file format:  
+AnalysisInfoHandler.analyzeFileDate=Analyzer file date:  
+AnalysisInfoHandler.traces=Available traces:  
+AnalysisInfoHandler.whitespace=\ \ \ \ \ 
+AnalysisInfoHandler.analyzerVersion2=Analyzer version:       
+AnalysisInfoHandler.analyzeFileFormat2=Analyzer file format:  
+AnalysisInfoHandler.analyzeFileDate2=Analyzer file date:     
+AnalysisInfoHandler.traces2=Available traces:  
+AnalysisInfoHandler.whitespace2=\ \ \ \ \ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/AlphabeticItem.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.utils;
+
+public abstract class AlphabeticItem
+{
+	private String s;
+	public int order;
+	
+	public AlphabeticItem(String s)
+	{
+		this.s = s;
+		this.order = 0;
+	}
+	
+	public AlphabeticItem()
+	{
+		this.s = ""; //$NON-NLS-1$
+		this.order = 0;
+	}
+	
+	public void setAlphabeticOrderString(String order)
+	{
+		this.s = order;
+	}
+	
+	public int getAlphabeticOrder()
+	{
+		return this.order;
+	}
+	
+	public void setAlphabeticOrder(int order)
+	{
+		this.order = order;
+	}
+		
+	public String toString()
+	{
+		return s;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/AlphabeticValueGenerator.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.utils;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class AlphabeticValueGenerator 
+{
+	public static void generateAlphabeticValues(Vector alphabeticItems)
+	{
+		ArrayList<Long> created = new ArrayList<Long>();
+		
+		Enumeration ae = alphabeticItems.elements();
+		while(ae.hasMoreElements())
+		{
+			AlphabeticItem ai = (AlphabeticItem)ae.nextElement();
+
+			Enumeration ae2 = alphabeticItems.elements();
+			int tempOrder = 0;
+			while(ae2.hasMoreElements())
+			{
+				AlphabeticItem ai2 = (AlphabeticItem)ae2.nextElement();
+				if (ai.toString().compareTo(ai2.toString()) > 0)
+				{
+					tempOrder+=1000;
+				}
+			}
+
+			while (created.contains(new Long(tempOrder)))
+			{
+				tempOrder++;
+			}
+			
+			created.add(new Long(tempOrder));
+			
+			ai.order = tempOrder;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/DebugDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: 
+ *
+ */
+
+/*
+ * DebugDialog.java
+ */
+package com.nokia.carbide.cpp.internal.pi.utils;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+public class DebugDialog extends JDialog 
+{
+	private static final long serialVersionUID = -7397509550206778612L;
+	private JPanel panel;
+	private JLabel freeMemory;
+	private JLabel totalMemory;
+	private JLabel usedMemory;
+	private static Runtime runtime;
+	private static long time4;
+	
+	private static void setTime4(long newTime) {
+		time4 = newTime;
+	}
+	
+	private static void setRuntime(Runtime newRuntime)
+	{
+		runtime = newRuntime;
+	}
+	
+	public DebugDialog()
+	{
+		setTime4(0);
+    	setRuntime(Runtime.getRuntime());
+		
+		freeMemory  = new JLabel(Messages.getString("DebugDialog.notInitialised")); //$NON-NLS-1$
+		totalMemory = new JLabel(Messages.getString("DebugDialog.notInitialised")); //$NON-NLS-1$
+		usedMemory  = new JLabel(Messages.getString("DebugDialog.notInitialised")); //$NON-NLS-1$
+    	
+		this.setTitle(Messages.getString("DebugDialog.debugDialog")); //$NON-NLS-1$
+		panel = (JPanel) this.getContentPane();
+		panel.setLayout(new BorderLayout());
+		panel.add(getMemoryPanel(), BorderLayout.CENTER);
+		panel.add(getButtonPanel(), BorderLayout.SOUTH);
+		this.pack();
+		panel.updateUI();
+	}
+	
+	private JPanel getButtonPanel() 
+	{
+		JPanel mp = new JPanel();
+		mp.add(getRefreshButton());
+		mp.add(getGarbageCollectionButton());
+		mp.add(getTestButton());
+		return mp;
+	}
+	
+	private JPanel getMemoryPanel() 
+	{
+		JPanel mp = new JPanel();
+		mp.setLayout(new GridLayout(3, 2));
+
+		mp.add(new JLabel(Messages.getString("DebugDialog.freeMemory"))); //$NON-NLS-1$
+		mp.add(freeMemory);
+		mp.add(new JLabel(Messages.getString("DebugDialog.totalMemory"))); //$NON-NLS-1$
+		mp.add(totalMemory);
+		mp.add(new JLabel(Messages.getString("DebugDialog.usedMemory"))); //$NON-NLS-1$
+		mp.add(usedMemory);
+//		refreshMemoryStatus();
+		return mp;
+	}
+	
+	public void refreshMemoryStatus()
+	{
+		long free = runtime.freeMemory() / 1000;
+		long total = runtime.totalMemory() / 1000;
+		long used = total - free;
+		
+		freeMemory.setText("" + free); //$NON-NLS-1$
+		totalMemory.setText("" + total); //$NON-NLS-1$
+		usedMemory.setText("" + used); //$NON-NLS-1$
+	}
+	
+	private JButton getRefreshButton() 
+	{
+		JButton refresh = new JButton(Messages.getString("DebugDialog.refresh")); //$NON-NLS-1$
+		refresh.addActionListener(new java.awt.event.ActionListener() 
+		{ 
+			public void actionPerformed(java.awt.event.ActionEvent e) 
+			{    
+				refreshMemoryStatus();
+			}
+		});
+		return refresh;
+	}
+
+	private JButton getGarbageCollectionButton() 
+	{
+		JButton garbage = new JButton(Messages.getString("DebugDialog.garbage")); //$NON-NLS-1$
+		garbage.addActionListener(new java.awt.event.ActionListener() 
+		{ 
+			public void actionPerformed(java.awt.event.ActionEvent e) 
+			{  
+				//runs garbage collection
+			    garbageCollection();
+			}
+		});
+		return garbage;
+	}
+	private JButton getTestButton() 
+	{
+		JButton refresh = new JButton(Messages.getString("DebugDialog.test")); //$NON-NLS-1$
+		refresh.addActionListener(new java.awt.event.ActionListener() 
+		{ 
+			public void actionPerformed(java.awt.event.ActionEvent e) 
+			{    
+				refreshMemoryStatus();
+			}
+		});
+		return refresh;
+	}
+	
+	public static void garbageCollection()
+	{
+	    long time1 = System.currentTimeMillis();
+	    //Time time = new Time(System.currentTimeMillis());
+	    runtime.runFinalization();
+	    runtime.gc();
+	    long time2 = System.currentTimeMillis();
+	    long time3 = time2 - time1;
+	    time4 = time4 + time3;
+	    System.out.println(Messages.getString("DebugDialog.garbageCollected1") + time3 + Messages.getString("DebugDialog.garbageCollected2") + time4 + Messages.getString("DebugDialog.garbageCollected3")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	    //Time time2 = new Time(System.currentTimeMillis());
+	}
+	
+	public static void printMemoryUsage()
+	{
+		//Runtime runtime = Runtime.getRuntime();
+	    
+		long free = runtime.freeMemory() / 1000;
+		long total = runtime.totalMemory() / 1000;
+		long used = total - free;
+		System.out.println(Messages.getString("DebugDialog.currentMemory") + used); //$NON-NLS-1$
+	}
+	
+	public static String getCurrentMemoryUsage()
+	{
+		long free = runtime.freeMemory() / 1000000;
+		long total = runtime.totalMemory() / 1000000;
+		long used = total - free;
+		return "" + used + "/" + total; //$NON-NLS-1$ //$NON-NLS-2$ 
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/JarClassLoader.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.utils;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+
+public class JarClassLoader extends URLClassLoader 
+{
+	public JarClassLoader(URL url) {
+		super(new URL[] { url });
+	}
+
+	public Object getInstace(String name)
+	{
+		Class c;
+		try {
+			c = loadClass(name);
+			try {
+				return c.newInstance();
+			} catch (InstantiationException e) {
+				e.printStackTrace();
+			} catch (IllegalAccessException e) {
+				e.printStackTrace();
+			}
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.utils;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.utils.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/PIFileFilter.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: 
+ *
+ */
+
+/*
+ * PIFileFilter.java
+ */
+package com.nokia.carbide.cpp.internal.pi.utils;
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+public class PIFileFilter extends FileFilter
+{
+	String myFilter;
+	public PIFileFilter(String filter)
+	{
+		this.myFilter = filter;
+	}
+	
+	public boolean accept(File f)
+	{
+		if (f.isDirectory())
+			return true;
+		
+		if (f.getName().endsWith(myFilter)) 
+			return true;
+		else
+			return false;
+	}
+	
+	public String getDescription()
+	{
+		if (this.myFilter.equals(Messages.getString("PIFileFilter.bapFilter"))) //$NON-NLS-1$
+		{
+			return Messages.getString("PIFileFilter.bapDescription");			 //$NON-NLS-1$
+		}
+		else if (this.myFilter.equals(Messages.getString("PIFileFilter.datFilter"))) //$NON-NLS-1$
+		{
+			return Messages.getString("PIFileFilter.datDescription"); //$NON-NLS-1$
+		}
+		else if (this.myFilter.equals(Messages.getString("PIFileFilter.csvFilter"))) //$NON-NLS-1$
+		{
+			return Messages.getString("PIFileFilter.csvDescription"); //$NON-NLS-1$
+		}
+		else if (this.myFilter.equals(Messages.getString("PIFileFilter.txtFilter"))) //$NON-NLS-1$
+		{
+			return Messages.getString("PIFileFilter.txtDescription"); //$NON-NLS-1$
+		}
+		else 
+		{
+			return Messages.getString("PIFileFilter.noDescription1") + myFilter + Messages.getString("PIFileFilter.noDescription2"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/PIUtilities.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.utils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+public abstract class PIUtilities
+{
+    private static String previous_path;
+	
+	//this is needed by createFileChooser method
+    private static String getPath(String fileName)
+    {
+		if (fileName.length() != 0)
+		{
+			File file = new File(fileName);
+			if (file.exists())
+			{
+				return fileName.substring(0,fileName.lastIndexOf(System.getProperty(Messages.getString("PIUtilities.fileSeparatorProperty")))); //$NON-NLS-1$
+			}
+		}
+		return ""; //$NON-NLS-1$
+    }
+
+	public static String selectAFile()
+	{
+		//file chooser
+		FileDialog fileDialog = new FileDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OPEN);
+
+		String tracefileName = fileDialog.open();
+
+	    File selected = new File(tracefileName);
+		
+		if ((selected != null) && selected.exists() && selected.isFile()) {
+			return selected.getAbsolutePath();
+		}
+		
+	    return null;
+	}
+	
+	public static String selectADirectory()
+	{
+		FileDialog fileDialog = new FileDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OPEN);
+
+		String tracefileName = fileDialog.open();
+
+	    File selected = new File(tracefileName);
+		
+		if ((selected != null) && selected.exists() && selected.isDirectory()) {
+			return selected.getAbsolutePath();
+		}
+		
+	    return null;
+	}
+	
+	/*************** stuff moved from profile reader *************/
+	
+	public static File getAFile(String filter) throws Exception
+	{
+	      
+	    return getAFile(false, filter);
+	}
+	  
+	//loads and saves a file, TestGUI import menu
+	public static File getAFile(boolean new_file, String filter) throws Exception
+	{
+		if (previous_path == null)
+		{
+	        previous_path = System.getProperty(Messages.getString("PIUtilities.userDirPropert")); //$NON-NLS-1$
+		}
+
+		// get a file via dialog
+		// For now, require a .pi or .bap file
+		FileDialog fileDialog;
+		
+		if (!new_file)
+		{
+			fileDialog = new FileDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.SAVE);
+		} else {
+			fileDialog = new FileDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OPEN);
+		}
+
+		fileDialog.setFilterPath(previous_path);
+		
+	  	if (filter != null && filter.length() != 0) {
+	  		PIFileFilter fileFilter = new PIFileFilter(filter);
+		    fileDialog.setFilterExtensions(new String[] { "." + filter }); //$NON-NLS-1$
+
+		    String fileFilterName = fileFilter.getDescription();
+		    if (fileFilterName != null) {
+		    	fileDialog.setFilterNames(new String[] { fileFilterName });
+		    }
+		}
+
+		String tracefileName = fileDialog.open();
+
+		File selected = null;
+
+		if (tracefileName != null) {
+			selected = new File(tracefileName);
+		
+			if ((selected != null) && selected.exists()) {
+	            if (!new_file)
+	            {
+		     		if (   (!tracefileName.endsWith(".dat")) //$NON-NLS-1$
+		     			&& (!tracefileName.endsWith("base64")) //$NON-NLS-1$
+		                && (!tracefileName.endsWith(".bap")) //$NON-NLS-1$
+		                && (!tracefileName.endsWith(".map")) //$NON-NLS-1$
+		            	   //performance framework files
+		                && (!tracefileName.endsWith(".csv")) //$NON-NLS-1$
+		                && (!tracefileName.endsWith(".txt"))) //$NON-NLS-1$
+		            {
+		            	System.out.println(Messages.getString("PIUtilities.notSupported1") + tracefileName + Messages.getString("PIUtilities.notSupported2")); //$NON-NLS-1$ //$NON-NLS-2$
+		            	throw new Exception(Messages.getString("PIUtilities.notSupported3") + tracefileName + Messages.getString("PIUtilities.notSupported4")); //$NON-NLS-1$ //$NON-NLS-2$
+		            }
+	            } else {
+	            	// new file
+		            if (filter == "jpg") //$NON-NLS-1$
+		            {
+		            	if (!selected.getName().endsWith(".jpg")) //$NON-NLS-1$
+		            	{
+		            		selected = new File(selected.getAbsolutePath() + ".jpg"); //$NON-NLS-1$
+		            	}
+		            }
+		            else if (filter == "bap") //$NON-NLS-1$
+		            {
+		            	if (!selected.getName().endsWith(".bap")) //$NON-NLS-1$
+		            	{
+		            		selected = new File(selected.getAbsolutePath() + ".bap"); //$NON-NLS-1$
+		            	}
+		            }
+		            else if (filter == "csv") //$NON-NLS-1$
+		            {
+		            	if (!selected.getName().endsWith(".csv")) //$NON-NLS-1$
+		            	{
+		            		selected = new File(selected.getAbsolutePath() + ".csv"); //$NON-NLS-1$
+		            	}
+		            }
+	            }
+			} else {
+				selected = null;
+			}
+		}
+		    
+	    if (selected != null) 
+	    {
+	    	/*config.setLastOpened(selected);*/
+	    	previous_path = getPath(selected.toString());
+	    }
+
+	    return selected;
+	}
+	
+	public static void saveCsvPrint(File f, String print) throws Exception
+	{
+		if (f == null)
+			return;
+		FileOutputStream fos = new FileOutputStream(f);
+		fos.write(print.getBytes(Messages.getString("PIUtilities.defaultCharacterSet"))); //$NON-NLS-1$
+		fos.flush();
+		fos.close();
+	}
+	
+	public static void saveFile(File f, String print_data) throws Exception
+	{
+		if (f == null)
+			return;
+		FileOutputStream fos = new FileOutputStream(f);
+		fos.write(print_data.getBytes(Messages.getString("PIUtilities.defaultCharacterSet"))); //$NON-NLS-1$
+		fos.flush();
+		fos.close();
+	    
+	}
+	
+    public static boolean isSymbolFileOk(String symbol_file)
+    {
+      if (symbol_file.endsWith("symbol")) //$NON-NLS-1$
+    	{
+    		GeneralMessages.showErrorMessage(Messages.getString("PIUtilities.cannotLoadSymbolFile")); //$NON-NLS-1$
+    		return false;
+    	}
+    	return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/PluginClassLoader.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+
+public class PluginClassLoader extends ClassLoader 
+{	
+	public ArrayList dirEntries;
+	public ArrayList jarEntries;
+	public Hashtable resolvedClasses;
+	
+	public PluginClassLoader(AbstractPiPlugin[] entries) 
+	{
+		super();
+		
+		dirEntries = new ArrayList();
+		jarEntries = new ArrayList();
+		resolvedClasses = new Hashtable();
+	}
+	
+	@SuppressWarnings("unchecked") //$NON-NLS-1$
+	public Class loadClass(String className) throws ClassNotFoundException
+	{
+		if (this.resolvedClasses.containsKey(className))
+		{
+			return (Class)this.resolvedClasses.get(className);
+		}
+		
+		try
+		{
+			Class c = super.loadClass(className);
+			return c;
+		}
+		catch(ClassNotFoundException e)
+		{
+			throw e;
+		}
+	}
+	
+	@SuppressWarnings("unchecked") //$NON-NLS-1$
+	public Class findClass(String className) throws ClassNotFoundException
+	{
+		if (this.resolvedClasses.containsKey(className))
+		{
+			return (Class)this.resolvedClasses.get(className);
+		}
+		else
+		{
+			byte[] classBytes = findClassBytes(className);
+			if (classBytes == null)
+			{
+				Class c = super.findLoadedClass(className);
+				if (c == null)
+					throw new ClassNotFoundException(className);
+				else
+					return c;
+			} 
+			else 
+			{
+				Class c = defineClass(className, classBytes, 0, classBytes.length);
+				this.resolvedClasses.put(className,c);
+				return c;
+			}
+		}
+	}
+	
+	public byte[] findClassBytes(String className)
+	{
+		Iterator i = this.dirEntries.iterator();
+		while(i.hasNext())
+		{
+			File f = (File)i.next();
+			byte[] b = this.findClassBytesDir(f,className);
+			if (b != null) return b;
+		}
+		
+		i = this.jarEntries.iterator();
+		while(i.hasNext())
+		{
+			File f = (File)i.next();
+			byte[] b = this.findClassBytesJar(f,className);
+			if (b != null) return b;
+		}
+		
+		return null;
+	}
+	
+	private byte[] findClassBytesJar(File jarFile, String className)
+	{
+		//System.out.println("Finding class bytes for "+className+" from "+jarFile.getName());
+		try
+		{
+			ZipInputStream zis = new ZipInputStream(new FileInputStream(jarFile));
+			ZipEntry ze = zis.getNextEntry();
+			
+			while(zis.available() == 1 && ze != null)
+			{
+				String entryName = ze.getName().replace('/','.');
+				
+				if (entryName.equals(className+Messages.getString("PluginClassLoader.classEntry"))) //$NON-NLS-1$
+				{
+					//System.out.println("FOUND!!!");
+					ArrayList<byte[]>  data    = new ArrayList<byte[]>();
+					ArrayList<Integer> amounts = new ArrayList<Integer>();
+					int totalAmount = 0;
+					while(true)
+					{
+						byte[] tempBytes = new byte[1024];
+						int amount = zis.read(tempBytes);
+						if (amount != -1) 
+						{
+							amounts.add(new Integer(amount));
+							totalAmount+=amount;
+							data.add(tempBytes);
+						}
+						else
+						{
+							break;	
+						}
+					}
+						
+					byte[] classBytes = new byte[totalAmount];
+						
+					Iterator<byte[]>  bI = data.iterator();
+					Iterator<Integer> aI = amounts.iterator();
+					int pos = 0;
+					while(bI.hasNext())
+					{
+						byte[] a = bI.next();
+						int am = aI.next().intValue();
+						System.arraycopy(a,0,classBytes,pos,am);
+						pos += am;
+					}
+
+					zis.closeEntry();
+					return classBytes;
+				}
+				zis.closeEntry();
+				ze = zis.getNextEntry();
+			}
+			zis.close();
+			return null;
+		}
+		catch (Exception e)
+		{
+			e.printStackTrace();
+			return null;
+		}
+	}
+	
+	private byte[] findClassBytesDir(File rootDir, String className) 
+	{	
+		try 
+		{
+			String pathName = rootDir.getAbsolutePath() + File.separatorChar
+					+ className.replace('.', File.separatorChar) + Messages.getString("PluginClassLoader.classEntry"); //$NON-NLS-1$
+
+			FileInputStream fis = new FileInputStream(pathName);
+			byte[] classBytes = new byte[fis.available()];
+			fis.read(classBytes);
+			fis.close();
+			return classBytes;
+		} 
+		catch (java.io.IOException ioEx)
+		{
+			return null;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/QuickSortImpl.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.utils;
+
+import java.util.Stack;
+import java.util.Vector;
+
+
+public class QuickSortImpl
+{
+	public static void sort(Sortable[] array)
+	{
+		quickSort(array,0,array.length-1);
+	}
+	
+	public static void sort(Vector sortables)
+	{
+		Sortable[] s = new Sortable[sortables.size()];
+		s = (Sortable[])sortables.toArray(s);
+		sort(s);
+		sortables.clear();
+		for (int i=0;i<s.length;i++)
+		{
+			sortables.add(s[i]);
+		}
+	}
+	
+	public static void sortReversed(Vector sortables)
+	{
+		Sortable[] s = new Sortable[sortables.size()];
+		s = (Sortable[])sortables.toArray(s);
+		sort(s);
+		sortables.clear();
+		for (int i=(s.length-1);i>=0;i--)
+		{
+			sortables.add(s[i]);
+		}
+	}
+		
+	public static void quickSort(Sortable[] a,int low, int high)
+	{
+		Stack stack = new Stack();
+		
+		//System.out.println("QS both sides "+low+" "+high);
+		int pivot;
+		/* Termination condition! */
+		if ( high > low )
+		{
+			while(high > low)
+			{
+				pivot = partition( a, low, high );
+				//System.out.println("QS left side is "+low+"-"+pivot+" right side is "+pivot+"-"+high);
+
+				//quickSort( a, low, pivot-1 );
+				stack.push(new Integer(pivot+1));
+				stack.push(new Integer(high));
+				//System.out.println("Pushed right side");
+				high = pivot-1;
+			}				
+			
+			while(!stack.isEmpty())
+			{
+				high = ((Integer)stack.pop()).intValue();
+				low = ((Integer)stack.pop()).intValue();
+				//System.out.println("Popping right side "+low+"-"+high);
+				quickSort( a, low, high );
+			}
+		}
+	}
+	
+	public static int partition(Sortable[] a,int low,int high)
+	{
+		int left, right;
+		int pivot;
+		
+		pivot = left = low;
+		right = high;
+		long pivotValue = a[pivot].valueOf();
+		Sortable pivotItem = a[pivot];
+		
+		while ( left < right ) 
+		{
+			// Move left while item < pivot 
+				//System.out.println("Starting left "+left);
+				while(a[left].valueOf() <= pivotValue ) 
+				{
+					//System.out.println(valueOf(a[left])+" < "+pivotValue);
+					left++;
+					//System.out.println("left ="+left);
+					if (left == a.length)
+						break;
+				}
+				//System.out.println("Final left = "+left);
+			// Move right while item > pivot
+			while( a[right].valueOf() > pivotValue ) 
+			{
+				right--;
+				//System.out.println("right ="+right);
+			}
+			if ( left < right )
+			{
+				//System.out.println("Swapping "+left+" and "+right);
+				Sortable tmp = a[left];
+				a[left] = a[right];
+				a[right] = tmp;
+				//SWAP(a,left,right);
+			}
+		}
+		// right is final position for the pivot
+		a[low] = a[right];
+		a[right] = pivotItem;
+		//System.out.println("Pivot is now "+right+" pivot value "+valueOf(a[right]));
+		return right;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/Sortable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.utils;
+
+public interface Sortable 
+{
+	public long valueOf();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,31 @@
+PIUtilities.fileSeparatorProperty=file.separator
+PIUtilities.userDirPropert=user.dir
+PIUtilities.notSupported1=File type of file 
+PIUtilities.notSupported2=\ is not supported
+PIUtilities.notSupported3=Type 
+PIUtilities.notSupported4=\ not supported
+PIUtilities.defaultCharacterSet=UTF-8
+PIUtilities.cannotLoadSymbolFile=Failed to load symbol file. Check configurations.
+PIFileFilter.bapFilter=bap
+PIFileFilter.datFilter=dat
+PIFileFilter.csvFilter=csv
+PIFileFilter.txtFilter=txt
+PIFileFilter.bapDescription=Saved old-style analysis file (.bap)
+PIFileFilter.datDescription=Profiler raw data file (.dat)
+PIFileFilter.csvDescription=Comma separated text file (.csv)
+PIFileFilter.txtDescription=Text file (.txt)
+PIFileFilter.noDescription1=No description for the file type (.
+PIFileFilter.noDescription2=)
+PluginClassLoader.classEntry=.class
+DebugDialog.notInitialised=Not initialised
+DebugDialog.debugDialog=Debug dialog
+DebugDialog.freeMemory=Free memory:
+DebugDialog.totalMemory=Total memory:
+DebugDialog.usedMemory=Used memory:
+DebugDialog.refresh=Refresh
+DebugDialog.garbage=Garbage
+DebugDialog.test=Test
+DebugDialog.garbageCollected1=Garbage collected, took: 
+DebugDialog.garbageCollected2=\ milli seconds (
+DebugDialog.garbageCollected3=)
+DebugDialog.currentMemory=Current used memory: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/AnalyserVisualState.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.visual;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Rectangle;
+
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledThread;
+
+
+public class AnalyserVisualState implements Serializable
+{
+	private static final long serialVersionUID = -826324357879880731L;
+	
+	private Hashtable<Integer,Color> colorInfo;
+	private Hashtable<Integer,Boolean> selectedInfo;
+	private int selectionStart;
+	private int selectionEnd;
+	private double zoomFactor;
+	private transient Rectangle viewRect1;
+	
+	public AnalyserVisualState(Enumeration threads, PICompositePanel bcp)
+	{
+		colorInfo    = new Hashtable<Integer,Color>();
+		selectedInfo = new Hashtable<Integer,Boolean>();
+		while (threads.hasMoreElements())
+		{
+			ProfiledThread pt = (ProfiledThread) threads.nextElement();
+			colorInfo.put(new Integer(pt.getThreadId()), pt.getColor());
+			// Could instead find  pt.isEnabled() for all pages - not just page 0
+			selectedInfo.put(new Integer(pt.getThreadId()), Boolean.valueOf(pt.isEnabled(0)));
+		}
+		
+		selectionStart = (int) bcp.getSelectionStart();
+		selectionEnd = (int) bcp.getSelectionEnd();
+		viewRect1 = bcp.getSashForm().getBounds();
+		zoomFactor = bcp.getScale();
+	}
+	
+	public Enumeration<ProfiledThread> resetThreadState(Enumeration<ProfiledThread> threads)
+	{
+		Vector<ProfiledThread> v = new Vector<ProfiledThread>();
+		Enumeration<ProfiledThread> temp = threads;
+		while (threads.hasMoreElements())
+		{
+			Object o = threads.nextElement();
+			if (o instanceof ProfiledThread)
+			{
+				ProfiledThread pt = (ProfiledThread) o;
+				Color c = (Color)colorInfo.get(new Integer(pt.getThreadId()));
+				Boolean b = (Boolean)selectedInfo.get(new Integer(pt.getThreadId()));
+				if ((c != null) && (b != null))
+				{
+					pt.setColor(c);
+					pt.setEnabled(0, b.booleanValue());
+					v.addElement(pt);
+				}
+				else
+				{
+					System.out.println(Messages.getString("AnalyserVisualState.noThreadInfo")); //$NON-NLS-1$
+					return temp;
+				}
+			}
+		}
+		return v.elements();
+	}
+
+	public int getSelectionEnd() 
+	{
+		return selectionEnd;
+	}
+
+	public int getSelectionStart() 
+	{
+		return selectionStart;
+	}
+
+	public double getZoomFactor() 
+	{
+		return zoomFactor;
+	}
+
+	public Rectangle getViewRect()
+	{
+		return viewRect1;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/AnalysisInfoPanel.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.visual;
+
+public class AnalysisInfoPanel
+{    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/Defines.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.visual;
+
+public class Defines {
+
+   
+    // what to show, based on the ordering of tables
+    // used as drawing mode and for determining table order
+    // The last item in a name is what is shown in the graph.
+    // E.g., THREADS_FUNCTIONS means show functions that match
+    // the selected threads in the selected graph area.
+    
+    // Threads
+	public static final int THREADS                    =  1;
+	// Threads -> Functions
+	public static final int THREADS_FUNCTIONS          =  2;
+	// Threads -> Functions -> Binaries
+	public static final int THREADS_FUNCTIONS_BINARIES =  3;
+	// Threads -> Binaries
+	public static final int THREADS_BINARIES           =  4;
+	// Threads -> Binaries -> Functions
+	public static final int THREADS_BINARIES_FUNCTIONS =  5;
+	// Binaries
+	public static final int BINARIES                   =  6;
+	// Binaries -> Threads
+	public static final int BINARIES_THREADS           =  7;
+	// Binaries -> Threads -> Functions
+	public static final int BINARIES_THREADS_FUNCTIONS =  8;
+	// Binaries -> Functions
+	public static final int BINARIES_FUNCTIONS         =  9;
+	// Binaries -> Functions -> Threads
+	public static final int BINARIES_FUNCTIONS_THREADS = 10;
+	// Functions
+	public static final int FUNCTIONS                  = 11;
+	// Functions -> Threads
+	public static final int FUNCTIONS_THREADS          = 12;
+	// Functions -> Threads -> Binaries
+	public static final int FUNCTIONS_THREADS_BINARIES = 13;
+	// Functions -> Binaries
+	public static final int FUNCTIONS_BINARIES         = 14;
+	// Functions -> Binaries -> Threads
+	public static final int FUNCTIONS_BINARIES_THREADS = 15;
+	
+	// In function analysis there are no graphs. Functions to
+	// examine are chosen by selecting threads then binaries,
+	// or binaries then threads.
+	
+	// In function analysis: Threads -> Binaries -> Functions
+	public static final int ANALYSIS_THREADS_BINARIES = 101;
+	// In function analysis: Binaries -> Threads -> Functions
+	public static final int ANALYSIS_BINARIES_THREADS = 102;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/GenericTable.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,697 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.visual;
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.PlatformUI;
+
+import com.nokia.carbide.cpp.internal.pi.actions.SaveSamples;
+import com.nokia.carbide.cpp.internal.pi.actions.SetThresholdsDialog;
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveSamples;
+import com.nokia.carbide.cpp.internal.pi.interfaces.ISaveTable;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.internal.pi.save.SaveTableWizard;
+
+
+public abstract class GenericTable
+{
+	// table column IDs in hopes it's quicker than comparing characters
+	protected static final int COLUMN_ID_THREAD         =  1;
+	protected static final int COLUMN_ID_BINARY         =  2;
+	protected static final int COLUMN_ID_FUNCTION       =  3;
+	protected static final int COLUMN_ID_SHOW           =  4;
+	protected static final int COLUMN_ID_PERCENT_LOAD   =  5;
+//	protected static final int COLUMN_ID_COLOR          =  6;
+	protected static final int COLUMN_ID_SAMPLE_COUNT   =  7;
+	protected static final int COLUMN_ID_PATH           =  8;
+	protected static final int COLUMN_ID_IN_BINARY      =  9;
+	protected static final int COLUMN_ID_IN_BINARY_PATH = 10;
+	protected static final int COLUMN_ID_START_ADDR     = 11;
+	protected static final int COLUMN_ID_PRIORITY       = 12;
+	
+	// these are never used as actual column headers - they indicate a double sort
+	protected static final int COLUMN_ID_FULL_PATH      = 13;
+	protected static final int COLUMN_ID_FULL_IN_PATH   = 14;
+
+	protected static final int COLOR_COLUMN_INDEX = 0;
+	
+	// table column headings
+	protected static final String COLUMN_HEAD_THREAD       = Messages.getString("GenericTable.thread"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_BINARY       = Messages.getString("GenericTable.binary"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_FUNCTION     = Messages.getString("GenericTable.function"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_SHOW         = Messages.getString("GenericTable.show");	// square root symbol used as check symbol //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_PERCENT_LOAD = Messages.getString("GenericTable.load"); //$NON-NLS-1$
+//	protected static final String COLUMN_HEAD_COLOR        = "Color";
+	public    static final String COLUMN_HEAD_SAMPLE_COUNT = Messages.getString("GenericTable.samples"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_PATH         = Messages.getString("GenericTable.path"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_IN_BINARY    = Messages.getString("GenericTable.inBinary"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_IN_BINARY_PATH = Messages.getString("GenericTable.pathOfBinary"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_START_ADDR   = Messages.getString("GenericTable.startAddr"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_PRIORITY     = Messages.getString("GenericTable.priority"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_MEMORY_CHUNKS = Messages.getString("GenericTable.chunks"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_MEMORY_STACK  = Messages.getString("GenericTable.stackHeap"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_MEMORY_TOTAL  = Messages.getString("GenericTable.memoryTotal"); //$NON-NLS-1$
+	protected static final String COLUMN_HEAD_MEMORY_NAME   = Messages.getString("GenericTable.threadProcess"); //$NON-NLS-1$
+
+	// table column widths
+	protected static final int COLUMN_WIDTH_SHOW           =  40;
+	protected static final int COLUMN_WIDTH_PERCENT_LOAD   =  52;
+//	protected static final int COLUMN_WIDTH_COLOR_MIN      =  22;
+//	protected static final int COLUMN_WIDTH_COLOR_MAX      =  60;
+    protected static final int COLUMN_WIDTH_THREAD_NAME    = 300;
+    protected static final int COLUMN_WIDTH_FUNCTION_NAME  = 300;
+    protected static final int COLUMN_WIDTH_BINARY_NAME    = 130;
+    protected static final int COLUMN_WIDTH_PATH           = 250;
+    protected static final int COLUMN_WIDTH_START_ADDRESS  =  80;
+    protected static final int COLUMN_WIDTH_SAMPLE_COUNT   =  84;
+    protected static final int COLUMN_WIDTH_HEAP           =  80;
+    protected static final int COLUMN_WIDTH_STACK          =  80;
+    protected static final int COLUMN_WIDTH_PRIORITY       =  85;
+    protected static final int COLUMN_WIDTH_IN_BINARY      =  65;
+    protected static final int COLUMN_WIDTH_IN_BINARY_PATH =  80;
+    protected static final int COLUMN_WIDTH_8_DIGIT_HEX    = 100;
+	protected static final int COLUMN_WIDTH_MEMORY_CHUNKS  =  80;
+	protected static final int COLUMN_WIDTH_MEMORY_STACK   =  80;
+	protected static final int COLUMN_WIDTH_MEMORY_TOTAL   =  80;
+	protected static final int COLUMN_WIDTH_MEMORY_NAME    = 300;
+    
+    // colors are now included with the checkbox column
+    protected static final int COLOR_COLUMN = 0;
+    
+	// NOTE: This text value must be unique to this column, but not
+	// discernible to the eye. It is used to find the checkbox column
+    // when you have a table item without its column number
+    protected static final String SHOW_ITEM_VALUE = Messages.getString("GenericTable.space"); //$NON-NLS-1$
+    
+    // type of checkbox column - none, just a checkbox, checkbox with visible text
+    protected static final int CHECKBOX_NONE    = 0;
+    protected static final int CHECKBOX_NO_TEXT = 1;
+    protected static final int CHECKBOX_TEXT    = 2;
+    
+    // create a CheckboxTableViewer, which contains a Table
+	protected CheckboxTableViewer tableViewer;
+    protected Table table;
+
+    protected Vector<ProfiledGeneric> tableItemData = new Vector<ProfiledGeneric>();
+    protected Vector<Object> columnData    = new Vector<Object>();
+    
+    // provide a routine for actions relating to the table
+    abstract public void action(String actionString);
+	
+	// pop-up menu for table
+	protected Menu contextMenu;
+	
+	// class for matching samples against checked items in an table
+	public class AllInclude {
+		public int totalItems;					// total number of threads, binaries, etc.
+		public ArrayList<Object> list = null;	// threads, binaries, etc. checked
+	}
+
+	//optimized for performance, grrr
+	Object[] finalValues = null;
+	public Object[] getSelectedValues()
+	{
+ 		Display.getDefault().syncExec(new Runnable(){
+			public void run(){
+				if ((table == null) || (table.isDisposed()))
+					finalValues = new Object[0];
+				else {
+					Object[] values = new Object[table.getSelectionCount()];
+					TableItem[] selectedItems = table.getSelection();
+					for (int i = 0; i < values.length; i++)
+					{
+					    values[i] = selectedItems[i].getData();
+					}
+					
+					finalValues = values;
+				}
+			}
+		});
+		return finalValues;
+	}
+    
+    //Only used in custom traces
+    public Object[] getSelectedValueString()
+	{
+		if (table == null)
+			return new Object[0];
+		
+		Object[] values = new Object[table.getSelectionCount()];
+		TableItem[] selectedItems = table.getSelection();
+		for (int i = 0; i < values.length; i++)
+		{
+			if (selectedItems[i].getData() instanceof ProfiledGeneric) {
+				values[i] = ((ProfiledGeneric)selectedItems[i].getData()).getNameString();
+			}
+		}
+		return values;
+	}
+    
+	public void setSelectedIndices(int[] indices)
+	{
+		if ((indices == null) || (table == null))
+			return;
+
+	    // only select the indicated indices
+        table.deselectAll();
+        for (int j = 0; j < indices.length; j++)
+        {
+            table.select(indices[j]);
+        }
+	}
+	
+	public void setSelectedIndicesXOR(int[] indices)
+	{
+		if ((indices == null) || (table == null))
+			return;
+
+		// reverse the selection status of the indicated indices
+        for (int j = 0; j < indices.length; j++)
+        {
+            if (table.isSelected(indices[j]))
+            {
+                table.deselect(indices[j]);
+            }
+            else
+            {
+                table.select(indices[j]);
+            }
+        }
+	}
+	
+	public Integer getIndex(Object anObject)
+	{
+		if (anObject == null)
+			return null;
+
+	    int counter = 0;
+	    Enumeration<ProfiledGeneric> e = tableItemData.elements();
+	    while (e.hasMoreElements())
+	    {
+	        if (e.nextElement().equals(anObject))
+	        {
+	            return new Integer(counter);
+	        }
+	        counter++;
+	    }
+	    return null;
+	}
+	
+	public int[] getIndices(Object[] objects)
+	{
+	    if (objects == null)
+	    	return null;
+	    
+	    int indexCount = 0;
+        int[] indices = new int[objects.length];
+	    for (int i = 0; i < objects.length; i++)
+	    {
+	        Integer index = getIndex(objects[i]);
+	        if (index != null)
+	        {
+	            indices[i] = index.intValue();
+	            indexCount++;
+	        }
+	    }
+	    if (indexCount != 0)
+	        return indices;
+	    else
+	        return null;
+	}
+	
+	public Menu getTablePopupMenu(Decorations parent, boolean enableSelected) {
+	    Menu tablePopupMenu = new Menu(parent, SWT.POP_UP);
+
+	    getCheckRows(tablePopupMenu, enableSelected);
+		new MenuItem(tablePopupMenu, SWT.SEPARATOR);
+		getRecolorItem(tablePopupMenu, Messages.getString("GenericTable.items"), enableSelected); //$NON-NLS-1$
+		new MenuItem(tablePopupMenu, SWT.SEPARATOR);
+		getChangeThresholds(tablePopupMenu);
+		tablePopupMenu.setVisible(true);
+
+		return tablePopupMenu;
+	}
+
+	public class TableKeyListener implements KeyListener {
+
+		// listener for ctrl-A (select all rows), ctrl-C (copy highlighted rows to clipboard), etc.
+		public void keyPressed(KeyEvent event) {
+			// check for exact match of CTRL-A/CTRL-C/etc. (do not match CTRL-SHIFT-A, for example)
+			if (event.stateMask == SWT.CTRL) {
+				if (event.character == 1) { // Ctrl-A
+					action("selectAll"); //$NON-NLS-1$
+				} else if (event.character == 3) { // Ctrl-C
+					action("copy"); //$NON-NLS-1$
+				}
+			}
+		}
+
+		public void keyReleased(KeyEvent event) {
+		}
+		
+	}
+
+	protected MenuItem getSortFullPathItem(Menu menu, boolean enabled) {
+	    MenuItem fullPathItem = new MenuItem(menu, SWT.PUSH);
+
+	    fullPathItem.setText(Messages.getString("GenericTable.sortByPath")); //$NON-NLS-1$
+		fullPathItem.setEnabled(enabled);
+
+		if (enabled) {
+			fullPathItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("sortfullpath"); //$NON-NLS-1$
+				}
+			});
+		}
+
+		return fullPathItem;
+	}
+
+	protected MenuItem getSortInFullPathItem(Menu menu, boolean enabled) {
+	    MenuItem fullPathItem = new MenuItem(menu, SWT.PUSH);
+
+		fullPathItem.setText(Messages.getString("GenericTable.sortByInPath")); //$NON-NLS-1$
+		fullPathItem.setEnabled(enabled);
+		
+		if (enabled) {
+			fullPathItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("sortinfullpath"); //$NON-NLS-1$
+				}
+			});
+		}
+
+		return fullPathItem;
+	}
+
+	protected MenuItem getSelectAllItem(Menu menu, boolean enabled) {
+	    MenuItem selectAllItem = new MenuItem(menu, SWT.PUSH);
+	    
+		selectAllItem.setText(Messages.getString("GenericTable.selectAll")); //$NON-NLS-1$
+		selectAllItem.setEnabled(enabled);
+		
+		if (enabled) {
+			selectAllItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("selectAll"); //$NON-NLS-1$
+				}
+			});
+		}
+		
+		return selectAllItem;
+	}
+
+	protected MenuItem getCopyItem(Menu menu, boolean enabled) {
+	    MenuItem copyItem = new MenuItem(menu, SWT.PUSH);
+	    
+		copyItem.setText(Messages.getString("GenericTable.copy")); //$NON-NLS-1$
+		copyItem.setEnabled(enabled);
+		
+		if (enabled) {
+			copyItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("copy"); //$NON-NLS-1$
+				}
+			});
+		}
+		
+		return copyItem;
+	}
+
+	protected MenuItem getCopyTableItem(Menu menu, boolean enabled) {
+	    MenuItem copyTableItem = new MenuItem(menu, SWT.PUSH);
+
+		copyTableItem.setText(Messages.getString("GenericTable.copyTable")); //$NON-NLS-1$
+		copyTableItem.setEnabled(enabled);
+		
+		if (enabled) {
+			copyTableItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+					action("copyTable"); //$NON-NLS-1$
+				}
+			});
+		}
+	
+		return copyTableItem;
+	}
+	
+	protected MenuItem getSaveTableItem(Menu menu, boolean enabled) {
+	    MenuItem saveTableItem = new MenuItem(menu, SWT.PUSH);
+
+		saveTableItem.setText(Messages.getString("GenericTable.saveTable")); //$NON-NLS-1$
+		saveTableItem.setEnabled(enabled);
+		
+		if (enabled) {
+			saveTableItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+					action("saveTable"); //$NON-NLS-1$
+				}
+			});
+		}
+	
+		return saveTableItem;
+	}
+
+	private MenuItem getAddRows(Menu menu, boolean enabled) {
+	    MenuItem addRows = new MenuItem(menu, SWT.PUSH);
+	    
+		addRows.setText(Messages.getString("GenericTable.checkHighlighted")); //$NON-NLS-1$
+		addRows.setEnabled(enabled);
+
+		if (enabled) {
+			addRows.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("add"); //$NON-NLS-1$
+				}
+			});
+		}
+
+		return addRows;
+	}
+
+	private MenuItem getRemoveRows(Menu menu, boolean enabled) {
+	    MenuItem removeRows = new MenuItem(menu, SWT.PUSH);
+	    
+		removeRows.setText(Messages.getString("GenericTable.uncheckHighlighted")); //$NON-NLS-1$
+		removeRows.setEnabled(enabled);
+		
+		if (enabled) {
+			removeRows.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("remove"); //$NON-NLS-1$
+				}
+			});
+		}
+
+		return removeRows;
+	}
+
+	private MenuItem getAddAllRows(Menu menu) {
+	    MenuItem addAllRows = new MenuItem(menu, SWT.PUSH);
+	    
+		addAllRows.setText(Messages.getString("GenericTable.checkAll")); //$NON-NLS-1$
+		addAllRows.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("addall"); //$NON-NLS-1$
+			}
+		});
+		return addAllRows;
+	}
+
+	private MenuItem getRemoveAllRows(Menu menu) {
+	    MenuItem removeAllRows = new MenuItem(menu, SWT.PUSH);
+
+		removeAllRows.setText(Messages.getString("GenericTable.uncheckAll")); //$NON-NLS-1$
+		removeAllRows.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("removeall"); //$NON-NLS-1$
+			}
+		});
+		return removeAllRows;
+	}
+
+	public void getCheckRows(Menu menu, boolean enableSelected) {
+		// check highlighted items
+		getAddRows(menu, enableSelected);
+		
+		// uncheck highlighted items
+		getRemoveRows(menu, enableSelected);
+		
+		// check all rows
+		getAddAllRows(menu);
+		
+		// uncheck all rows
+		getRemoveAllRows(menu);
+	}
+	
+	protected MenuItem getRecolorItem(Menu menu, String itemType, boolean enabled) {
+	    MenuItem recolorItem = new MenuItem(menu, SWT.PUSH);
+
+	    recolorItem.setText(Messages.getString("GenericTable.recolor1") + itemType + Messages.getString("GenericTable.recolor2")); //$NON-NLS-1$ //$NON-NLS-2$
+	    recolorItem.setEnabled(enabled);
+	    
+	    if (enabled) {
+	    	recolorItem.addSelectionListener(new SelectionAdapter() { 
+				public void widgetSelected(SelectionEvent e) {
+				    action("recolor"); //$NON-NLS-1$
+				}
+			});
+	    }
+
+	    return recolorItem;
+	}
+
+	protected MenuItem getChangeThresholds(Menu menu) {
+	    MenuItem thresholdItem = new MenuItem(menu, SWT.PUSH);
+
+		thresholdItem.setText(Messages.getString("GenericTable.changeThresholds")); //$NON-NLS-1$
+		thresholdItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+				// get the original thresholds
+				// get the new thresholds
+				new SetThresholdsDialog(e.display);
+			}
+		});
+		return thresholdItem;
+	}
+
+	protected MenuItem getSourceLookUpItem(Menu menu, String itemType) {
+	    MenuItem sourceLookupItem = new MenuItem(menu, SWT.PUSH);
+
+	    sourceLookupItem.setText(Messages.getString("GenericTable.sourcelookup"));	//$NON-NLS-1$
+		sourceLookupItem.addSelectionListener(new SelectionAdapter() { 
+			public void widgetSelected(SelectionEvent e) {
+			    action("sourceLookup"); //$NON-NLS-1$
+			}
+		});
+		return sourceLookupItem;
+	}	
+
+	protected MenuItem getDisabledSourceLookUpItem(Menu menu, String itemType) {
+	    MenuItem disabledSourceLookupItem = new MenuItem(menu, SWT.PUSH);
+
+	    disabledSourceLookupItem.setText(Messages.getString("GenericTable.sourcelookup"));	//$NON-NLS-1$
+		disabledSourceLookupItem.setEnabled(false);
+		return disabledSourceLookupItem;
+	}
+	
+	
+	protected String copyHeading(Table table, int checkboxType, String separator, String ending)
+	{
+		String copyString = ""; //$NON-NLS-1$
+		String addString;
+		int[] columnOrder = table.getColumnOrder();
+		
+		for (int i = 0; i < table.getColumnCount(); i++) {
+			TableColumn tableColumn = table.getColumn(columnOrder[i]);
+			if (i > 0)
+				copyString += separator;
+			
+			// Note: this code assumes that the original column 0 has the checkbox
+			if (columnOrder[i] == 0 && checkboxType != CHECKBOX_NONE) {
+				copyString += Messages.getString("GenericTable.checked");  //$NON-NLS-1$
+				if (checkboxType == CHECKBOX_TEXT) {
+					copyString += separator;
+					addString = tableColumn.getText();
+					if (addString.indexOf(separator) == -1)
+						copyString += addString;
+					else
+						copyString += "\"" + addString + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+			else {
+				copyString += tableColumn.getText();
+			}
+		}
+		
+		return copyString + ending;
+	}
+
+	protected String copySelected(Table table, int checkboxType, String separator, String ending)
+	{
+		String copyString = ""; //$NON-NLS-1$
+		int[] columnOrder = table.getColumnOrder();
+		boolean[] isHex   = (boolean[]) table.getData("isHex"); //$NON-NLS-1$
+
+		int selectionCount = table.getSelectionCount();
+		
+		for (int i = 0; (selectionCount > 0) && i < table.getItemCount(); i++)
+		{
+			if (table.isSelected(i))
+			{
+				selectionCount--;
+				copyString += copyRow(isHex, table.getItem(i), checkboxType, table.getColumnCount(), columnOrder, separator) + ending;
+			}
+		}
+		
+		return copyString;
+	}
+
+	protected String copyTable(Table table, int checkboxType, String separator, String ending)
+	{
+		String copyString = ""; //$NON-NLS-1$
+		int[] columnOrder = table.getColumnOrder();
+		boolean[] isHex   = (boolean[]) table.getData("isHex"); //$NON-NLS-1$
+
+		for (int i = 0; i < table.getItemCount(); i++)
+			copyString += copyRow(isHex, table.getItem(i), checkboxType, table.getColumnCount(), columnOrder, separator) + ending;
+		
+		return copyString;
+	}
+	
+	protected String copyRow(boolean[] isHex, TableItem item, int checkboxType, int columnCount, int[] columnOrder, String separator)
+	{
+		String copyString = ""; //$NON-NLS-1$
+		String addString;
+		for (int i = 0; i < columnCount; i++) {
+			if (i > 0)
+				copyString += separator;
+			
+			int realColumn = columnOrder[i];
+			
+			// Note: this code assumes that the original column 0 has the checkbox
+			if (realColumn == 0 && checkboxType != CHECKBOX_NONE) {
+				copyString += item.getChecked() ? Messages.getString("GenericTable.true") : Messages.getString("GenericTable.false"); //$NON-NLS-1$ //$NON-NLS-2$
+				if (checkboxType == CHECKBOX_TEXT) {
+					copyString += separator;
+					addString = item.getText(realColumn);
+					if ((isHex != null) && (isHex.length > realColumn) && isHex[realColumn] && addString.length() > 0) {
+						String string = "00000000" + addString; //$NON-NLS-1$
+						copyString += "0x" + string.substring(string.length() - 8); //$NON-NLS-1$
+					}
+					else {
+						if (addString.indexOf(separator) == -1)
+							copyString += addString;
+						else
+							copyString += "\"" + addString + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+					}
+				}
+			}
+			else {
+				addString = item.getText(realColumn);
+				if ((isHex != null) && (isHex.length > realColumn) && isHex[realColumn] && addString.length() > 0) {
+					String string = "00000000" + addString; //$NON-NLS-1$
+					copyString += "0x" + string.substring(string.length() - 8); //$NON-NLS-1$
+				}
+				else {
+					if (addString.indexOf(separator) == -1)
+						copyString += addString;
+					else
+						copyString += "\"" + addString + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+		}
+		
+		return copyString;
+	}
+
+	public CheckboxTableViewer getTableViewer() {
+		return this.tableViewer;
+	}
+
+	public Table getTable() {
+		return this.table;
+	}
+
+    protected void actionSelectAll()
+    {
+        this.table.selectAll();
+        this.table.redraw();
+    }
+    
+    public String getCopyString(Table table, int checkboxType, boolean copyTable, String separator, String ending)
+    {
+		// copy all (copyTable == true) or part of a single table to the clipboard or to a file
+        String copyString;
+
+		// copy the column headings, followed by the desired table rows
+		if (copyTable) {
+			copyString = copyHeading(table, checkboxType, separator, ending);
+			copyString += copyTable(table, checkboxType, separator, ending);
+		}
+		else
+			copyString = copySelected(table, checkboxType, separator, ending);
+		
+		return copyString;
+    }
+    
+    // class to pass table to the save wizard
+    public class SaveTableString implements ISaveTable {
+    	private Table table;
+    	private int checkboxType;
+    	private String separator;
+    	private String ending;
+    	
+    	public SaveTableString(Table table, int checkboxType, String separator, String ending) {
+    		this.table        = table;
+    		this.checkboxType = checkboxType;
+    		this.separator    = separator;
+    		this.ending       = ending;
+		}
+
+    	public String getData() {
+			return getCopyString(table, checkboxType, true, separator, ending);
+		}
+    }
+
+	protected void actionCopyOrSave(boolean doCopy, Table table, int checkboxType, boolean copyTable, String separator, String ending)
+	{
+		// copy all (copyTable == true) or part of a single table to the clipboard or to a file
+		if (doCopy) {
+			// change the clipboard contents
+	        Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
+	        String copyString = getCopyString(table, checkboxType, copyTable, separator, ending);
+			StringSelection contents = new StringSelection(copyString);
+	        cb.setContents(contents, contents);
+		} else {
+			// save to a file
+			SaveTableString getString = new SaveTableString(table, checkboxType, separator, ending);
+			WizardDialog dialog;
+			Wizard wizard = new SaveTableWizard(getString);
+			dialog = new WizardDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), wizard);
+	    	dialog.open();
+		}
+	}
+
+	protected void actionSaveSamples(ISaveSamples saveSamples)
+	{
+		new SaveSamples(saveSamples);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/GenericTraceGraph.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,947 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: GenericTraceGraph.java 
+ *
+ */
+
+package com.nokia.carbide.cpp.internal.pi.visual;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Panel;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.model.ProfiledGeneric;
+import com.nokia.carbide.cpp.pi.util.ColorPalette;
+
+
+public abstract class GenericTraceGraph
+{
+	protected int graphIndex = 0;
+	private static final int ALPHA_UNSELECTED = 175;
+	private static final int SELECTION_BAR_WIDTH = 2;
+	
+	// amount of space at left of graph to contain y-axis units
+	public static final int yLegendWidth = 50;
+
+    // fill selection flags
+    private double timeOffset = 0; 
+    protected boolean debug = false;
+    
+    // PI time scale multiplier
+    private float piTimeScale = 1;
+    private boolean timescalingEnabled = false;
+    
+    private int visibleAreaIdentifier = 0; //is used to detect changes in drawing area
+    private boolean updatePolylinesIsNeeded = true;
+    public boolean updateCumulativeThreadTableIsNeeded = true;
+    
+	public boolean fillFlag = false;	 //fill items is selected, all or selected?
+	public boolean fillSelected = false; //fill selected items
+	
+    private int visibleRightBorder; //these are updated when the visible area changes / polylines need to be updated
+    private int visibleLeftBorder;
+    
+	private int sizeX = 0;
+	private int sizeY = 0;
+
+	private int visualSizeX = 0;
+	private int visualSizeY = 0;
+	
+	private int preferredSizeX = 0;
+	private int preferredSizeY = 0;
+
+	private double selectionStart = -1;
+	private double selectionEnd = -1;
+   
+//	private double scaleX = 10;	 //default when creating a new analysis
+	private double scaleY = 100; //default for percentages
+	
+	private double scale = 0;
+    private boolean highResolution = true;
+	
+	public PICompositePanel parentComponent;
+
+	private GenericTrace myTrace;
+	
+	private Vector<GenericTraceGraph> graphSubComponents;
+	
+	private Image graphImage = null;
+	private boolean graphImageChanged = true;
+
+	public GenericTraceGraph(GenericTrace data)
+	{
+		this.graphSubComponents = new Vector<GenericTraceGraph>();
+		this.myTrace = data;
+	}
+	
+	public GenericTrace getTrace()
+	{
+		return this.myTrace;
+	}
+    
+    public void setTimeOffset(double offset)
+    {
+        this.timeOffset = offset;
+    }
+
+    public double getTimeOffset()
+    {
+        return this.timeOffset;
+    }
+	
+	public void addSubGraphComponent(GenericTraceGraph subGraph)
+	{
+		this.graphSubComponents.add(subGraph);
+	}
+	
+	public Enumeration getGraphSubComponents()
+	{
+		return graphSubComponents.elements();
+	}
+	
+	public void importParentComponent(PICompositePanel parent)
+	{
+		this.parentComponent = parent;
+	}
+	
+	public void setCurrentInfoComponent(Component infoComponent)
+	{
+		if (parentComponent instanceof PICompositePanel)
+		{
+			((PICompositePanel)parentComponent).
+				setCurrentInfoComponent(infoComponent);
+		}
+	}
+	
+	public PIVisualSharedData getSharedDataInstance()
+	{
+		if (parentComponent instanceof PICompositePanel)
+		{
+			return ((PICompositePanel)parentComponent).getSharedData();
+		}
+		else
+			return null;
+	}
+	
+	// a rectangle that describes visible area fo the draw 2D graphics so we paint only that
+	public Rectangle getVisibleArea(Graphics graphics) {
+		return graphics.getClip(new org.eclipse.draw2d.geometry.Rectangle());
+	}
+	
+	public abstract void paint(Panel panel, Graphics graphics);
+	
+	public abstract void paintLeftLegend(FigureCanvas figureCanvas, GC gc);
+	
+	// call all subcomponents' repaint methods
+	public abstract void repaint();
+	
+	public abstract void refreshDataFromTrace();
+	
+	public abstract void action(String action);
+	
+	public void setSize(int x, int y)
+	{
+		this.sizeY = y;
+		this.sizeX = x;
+	}
+	
+	public void setPITimeScale(float scale)
+	{
+	    System.out.println(Messages.getString("GenericTraceGraph.setTimeScaleTo") + scale); //$NON-NLS-1$
+	    this.piTimeScale = scale;
+	    
+	    Enumeration sc = this.getGraphSubComponents();
+	    while (sc.hasMoreElements())
+	    {
+	    	GenericTraceGraph gtc = (GenericTraceGraph)sc.nextElement();
+	    	gtc.setPITimeScale(scale);
+	    }
+	}
+	
+	public void setTimescalingEnabled(boolean flag)
+	{
+	    this.timescalingEnabled = flag;
+	    
+	    Enumeration sc = this.getGraphSubComponents();
+	    while (sc.hasMoreElements())
+	    {
+	    	GenericTraceGraph gtc = (GenericTraceGraph)sc.nextElement();
+	    	gtc.setTimescalingEnabled(flag);
+	    }
+	}
+	
+	public float getPITimeScale()
+	{
+	    if (this.timescalingEnabled)
+	        return this.piTimeScale;
+	    else
+	        return 1f;
+	}
+	
+	public Dimension getSize()
+	{
+		return new Dimension(this.sizeX, this.sizeY);
+	}
+	
+	public void setVisualSize(int x, int y)
+	{
+		this.visualSizeX = x;
+		this.visualSizeY = y;
+		
+	    Enumeration sc = this.getGraphSubComponents();
+	    while (sc.hasMoreElements())
+	    {
+	    	GenericTraceGraph gtc = (GenericTraceGraph)sc.nextElement();
+	    	gtc.setVisualSize(x, y);
+	    }
+	}
+	
+	public Dimension getVisualSize()
+	{
+		return new Dimension(this.visualSizeX, this.visualSizeY);
+	}
+	
+	public Dimension getPreferredSize()
+	{
+		return new Dimension(this.preferredSizeX, this.preferredSizeY);
+	}
+	
+	public void setSelectionStart(double start)
+	{
+        if (highResolution)
+            selectionStart = start;
+        else
+            selectionStart = (int) (start / 100 + 0.5) * 100;
+		
+	    Enumeration sc = this.getGraphSubComponents();
+	    while (sc.hasMoreElements())
+	    {
+	    	GenericTraceGraph gtc = (GenericTraceGraph)sc.nextElement();
+	    	gtc.setSelectionStart(selectionStart);
+	    }
+	}
+
+	public void setSelectionEnd(double end)
+	{
+        if (highResolution)
+            this.selectionEnd = end;
+        else
+            selectionEnd = (int) (end / 100 + 0.5) * 100;
+
+	    Enumeration sc = this.getGraphSubComponents();
+	    while (sc.hasMoreElements())
+	    {
+	    	GenericTraceGraph gtc = (GenericTraceGraph)sc.nextElement();
+	    	gtc.setSelectionEnd(selectionEnd);
+	    }
+	}
+    
+    public void setHighResolution(boolean flag)
+    {
+        this.highResolution = flag;
+    }
+    
+	public double getSelectionStart()
+	{
+		return this.selectionStart;
+	}
+
+	public double getSelectionEnd()
+	{
+		return this.selectionEnd;
+	}
+	
+	public void setScale(double scaleX, double scaleY)
+	{
+//	    if (scaleX > 0)
+//	        this.scaleX = scaleX;
+	    if (scaleY > 0)
+	        this.scaleY = scaleY;
+	    
+	    Enumeration sc = this.getGraphSubComponents();
+	    while (sc.hasMoreElements())
+	    {
+	    	GenericTraceGraph gtc = (GenericTraceGraph)sc.nextElement();
+	    	gtc.setScale(scaleX, scaleY);
+	    }
+	}
+	
+	public double getScale()
+	{
+		return this.scale;
+	}
+	
+	public void setScale(double scale)
+	{
+        this.scale = scale;
+		
+	    Enumeration sc = this.getGraphSubComponents();
+	    while (sc.hasMoreElements())
+	    {
+	    	GenericTraceGraph gtc = (GenericTraceGraph)sc.nextElement();
+	    	gtc.setScale(scale);
+	    }
+	}
+	
+	public void setToolTipText(String text)
+	{
+		this.parentComponent.setToolTipTextForGraphComponent(this, text);
+	}
+	
+	public PICompositePanel getCompositePanel()
+	{
+		return this.parentComponent;
+	}
+	
+	//new generic method to draw background
+	public void drawDottedLineBackground(Graphics graphics, int yLegendSpace)
+	{
+		Rectangle visibleArea = getVisibleArea(graphics);
+		int visY = this.getVisualSize().height;
+		float visYfloat = visY - yLegendSpace;
+
+		// draw the dotted lines
+		graphics.setForegroundColor(ColorPalette.getColor(new RGB(200, 200, 200)));
+
+		// vertical lines
+		// float values will be slightly smaller than the actual result
+		// and they will be incremented by one, since rounding to int
+		// discards the remaining decimals
+		int k = 0;
+		for (float y = 0; k <= 10; y += visYfloat * 10000f / 100001f, k++)
+		{
+			for (int x = visibleArea.x; x <= visibleArea.x + visibleArea.width; x += 5)
+			{
+				if ((x / 5) % 2 == 0) graphics.drawLine(x, ((int)y) + 1, x + 5, ((int)y) + 1);
+			}
+		}
+
+		// horizontal lines
+		if (visibleArea.width > 0)
+		{
+			for (int x = visibleArea.x; x <= visibleArea.x + visibleArea.width; x += 50)
+			{
+				if (x % 100 == 0)
+					graphics.setForegroundColor(ColorPalette.getColor(new RGB(100, 100, 100)));
+				else
+					graphics.setForegroundColor(ColorPalette.getColor(new RGB(200, 200, 200)));
+				
+				for (int y = 0; y < visY; y += 5)
+				{
+					if ((y / 5) % 2 == 0)
+						graphics.drawLine(x, y, x, y + 5);
+				}
+			}
+		}
+
+		// draw the line indices
+		graphics.setForegroundColor(ColorPalette.getColor(new RGB(100, 100, 100)));
+		graphics.setBackgroundColor(ColorPalette.getColor(new RGB(255, 255, 255)));
+		for (int x = visibleArea.x; x <= visibleArea.x + visibleArea.width; x += 50)
+		{
+			double time = (double) x;
+			time = time * this.getScale();
+            time += this.timeOffset;
+			time = time / 1000;
+
+			String stringTime = String.valueOf(time);
+			if (stringTime.length() > 4)
+			{
+				int i;
+				for (i = 0; i < stringTime.length(); i++)
+					if (stringTime.charAt(i) == '.')
+						break;
+					
+				if (i + 4 < stringTime.length())
+					stringTime = stringTime.substring(0, i + 4);
+			}
+			graphics.drawString(stringTime + Messages.getString("GenericTraceGraph.seconds"), x + 5, visY - 13); //$NON-NLS-1$
+	    }
+	}
+	
+	public void drawSelectionSection(Graphics graphics, int yLegendSpace)
+	{
+        //draws the new selection
+        this.drawSelection(graphics, selectionStart, selectionEnd, yLegendSpace);
+ 	}
+    
+    protected void drawSelection(Graphics graphics, double start, double end, int yLegendSpace)
+    {
+    	if (start > end) {
+    		double tmp = end;
+    		end = start;
+    		start = tmp;
+    	}
+
+        double scale = getScale();
+
+        int savedAlpha   = graphics.getAlpha();
+		Color savedColor = graphics.getForegroundColor();
+		
+		// shade unselected area with a fixed alpha of darker gray
+		Color selectColor = ColorPalette.getColor(new RGB(170, 170, 170));
+		graphics.setBackgroundColor(selectColor);
+		graphics.setAlpha(ALPHA_UNSELECTED);
+		
+		Point origin = this.parentComponent.getScrolledOrigin();
+        
+		int visX = this.getVisualSizeX();
+		int visY = this.getVisualSizeY()- yLegendSpace;
+
+		if (start != -1 && end != -1)
+        {
+            // mask with alpha adjusted the unselected area before the indicators
+			if (origin.x < (start / scale) - SELECTION_BAR_WIDTH)
+				graphics.fillRectangle(origin.x, 0,
+						(int)(start / scale) - SELECTION_BAR_WIDTH - origin.x, visY);
+
+			// mask with alpha adjusted the unselected area after the indicators
+			if ((int)(end/scale + SELECTION_BAR_WIDTH) < origin.x + visX)
+	           	graphics.fillRectangle((int)(end / scale + SELECTION_BAR_WIDTH), 0,
+	           			origin.x + visX - (int)(end / scale + SELECTION_BAR_WIDTH), visY);
+
+            // draw two indicators		
+            graphics.setForegroundColor(ColorPalette.getColor(new RGB(255, 255, 0)));
+            for (int i = 0; i < SELECTION_BAR_WIDTH; i++) {
+            	graphics.drawLine((int)(start/scale) - i, 0, (int)(start/scale) - i, visY);
+            	graphics.drawLine((int)(end/scale)   + i, 0, (int)(end/scale)   + i, visY);
+            }
+        }
+		else
+		{
+            // mask the entire visible area with alpha adjusted
+			graphics.fillRectangle(origin.x, 0, visX, visY);
+		}
+
+		//restore proper alpha
+		graphics.setBackgroundColor(savedColor);
+		graphics.setAlpha(savedAlpha);
+	}
+	
+	protected void drawThreadMarks(ProfiledGeneric pg, int visY, Graphics graphics)
+	{
+		Rectangle visibleArea = getVisibleArea(graphics);
+		int firstSample = (int)(pg.getFirstSample() / this.getScale());
+		int lastSample  = (int)(pg.getLastSample()  / this.getScale());
+		
+		// Thread start mark
+		if (firstSample >= visibleArea.x && firstSample <= visibleArea.x + visibleArea.width) {
+			graphics.drawLine(firstSample,     (visY - 50), firstSample,     (visY - 40));
+			graphics.drawLine(firstSample + 1, (visY - 50), firstSample + 1, (visY - 40));
+			graphics.drawLine(firstSample - 1, (visY - 50), firstSample - 1, (visY - 40));
+			graphics.drawLine(firstSample,(visY - 40), firstSample + 10, (visY - 40));
+			graphics.drawLine(firstSample,(visY - 41), firstSample + 10, (visY - 41));
+			graphics.drawLine(firstSample,(visY - 39), firstSample + 10, (visY - 39));
+	
+		}
+		
+		// Thread end mark
+		if (lastSample >= visibleArea.x && lastSample <= visibleArea.x + visibleArea.width) {
+			graphics.drawLine(lastSample,      (visY - 50), lastSample,      (visY - 40));
+			graphics.drawLine(lastSample  + 1, (visY - 50), lastSample  + 1, (visY - 40));
+			graphics.drawLine(lastSample  - 1, (visY - 50), lastSample  - 1, (visY - 40));
+			graphics.drawLine(lastSample, (visY - 40), lastSample  - 10, (visY - 40));
+			graphics.drawLine(lastSample, (visY - 41), lastSample  - 10, (visY - 41));
+			graphics.drawLine(lastSample, (visY - 39), lastSample  - 10, (visY - 39));
+		}
+	}
+	
+	public void updateVisibleBorders()
+	{
+	    SashForm rect = this.parentComponent.getSashForm();	    
+	    int scale = (int) this.getScale();
+	    int correctionValue = 10;
+
+	    // calculate display overscan to remove graphical glitches
+        if (scale >= 10)
+            correctionValue = 10;
+        else if (scale < 10 && scale > 1)
+	        correctionValue = 100 - (scale * 10);
+	    else if ( scale <= 1 && scale > 0.3)
+	        correctionValue = 200;
+        else if ( scale <= 0.3)
+            correctionValue = 800;
+
+        Point origin = this.parentComponent.getScrolledOrigin();
+
+		visibleLeftBorder  = origin.x - (int)(correctionValue * 1.2);
+		visibleRightBorder = origin.x + rect.getBounds().width + (int)(correctionValue * 1.1);
+	}
+	
+	public void genericRefreshCumulativeThreadTable()
+	{
+	    updateCumulativeThreadTableIsNeeded = true;
+	}
+	
+	protected void genericRefreshCumulativeThreadTable(Enumeration<ProfiledGeneric> threads)
+	{	
+	  	int[] cumulativePerc = null;
+
+	  	while (threads.hasMoreElements())
+	  	{		
+			ProfiledGeneric pg = threads.nextElement();
+
+			// go through all samples
+	        if (pg.isEnabled(graphIndex))   
+	        {
+	        	// zero this profiled generic's cumulative values
+	            pg.setupCumulativeList(graphIndex);
+
+				// Note: getSampleList() and getActivityList() create the lists
+				int[] samples = pg.getSampleList();
+				int[] values  = pg.getActivityList();
+
+				if (samples == null || values == null || samples.length == 0)
+				    return;
+				
+			  	if (cumulativePerc == null)
+			  	{
+			  		// create a zeroed array of cumulative values
+			  		cumulativePerc = new int[samples.length];
+			  	}
+
+				for (int sampIndx = 0; sampIndx < samples.length; sampIndx++)
+				{
+					// get this profiled generic's sample count in each chunk of samples
+					int thisValue = values[sampIndx];
+				  	
+					int oldCumValue = cumulativePerc[sampIndx];
+							
+					// add the percentage to the current cumulative value
+					cumulativePerc[sampIndx] += thisValue;
+
+					// set the profiled generic's cumulative value for this bucket
+					pg.setCumulativeValue(graphIndex, sampIndx, oldCumValue);
+				}
+	        }
+	  	}
+	  	updatePolylinesIsNeeded = true;
+	  	updateCumulativeThreadTableIsNeeded = false;
+  	}
+	
+    private void updatePolyLinesGeneric(Enumeration enumer)
+    {
+        // updatePolylinesIsNeeded will be true if refreshCumulativeThreadTable has been invoked
+	    /******************************************************************/
+		if (!updatePolylinesIsNeeded)
+		{
+		    int visY = this.getVisualSize().height;
+		    int newVisibleAreaIdentifier;
+		    SashForm rect = this.parentComponent.getSashForm();	    
+		    Point point = this.parentComponent.getScrolledOrigin();
+		    int scale = (int) this.getScale();
+		    
+			int visibleLeft  = point.x;
+			int visibleRight = point.x + rect.getBounds().width;
+		    
+			newVisibleAreaIdentifier = scale * 13 + visibleLeft + visibleRight * 2 + visY * 3;
+	
+			if (!(visibleAreaIdentifier == newVisibleAreaIdentifier))
+			    updatePolylinesIsNeeded = true;
+			
+			visibleAreaIdentifier = newVisibleAreaIdentifier;
+		}
+		/**********************************************************/
+
+		if (updatePolylinesIsNeeded)
+			this.updatePolyLinesGeneric(enumer, (int) this.scaleY);
+    }
+	  
+	private void updatePolyLinesGeneric(Enumeration enumer, int heightDivider)
+	{
+	    if (!updatePolylinesIsNeeded)
+	        return;
+	    
+	    this.updateVisibleBorders();
+		int visY = this.getVisualSize().height;
+	  	
+	  	float xscale;
+	  	if (this.timescalingEnabled)
+	  	    xscale = this.piTimeScale;
+	  	else
+	  	    xscale = 1;
+	  	
+	  	// draw one thread/binary/function at a time
+	  	ProfiledGeneric pg = null;
+	  	while (enumer.hasMoreElements())
+	  	{
+  	        pg = (ProfiledGeneric ) enumer.nextElement();
+	  
+	  		if (pg.isEnabled(graphIndex)) //is visualised
+		  	{
+	  		    if (debug)
+	  		        System.out.println(Messages.getString("GenericTraceGraph.debug")+pg.getNameString()); //$NON-NLS-1$
+	  		    
+			  	// get samples and their corresponding values
+			  	int[] samples = pg.getSampleList();  //time stamps
+			  	int[] values = pg.getActivityList(); //percentage values
+			  	
+			  	// if a ProfiledGeneric has a null cumulative list, give
+			  	// it a list of zeros
+			  	if (pg.getCumulativeList(graphIndex) == null) {
+			  		pg.setupCumulativeList(graphIndex);
+			  	}
+
+			  	int[] cumulatives = pg.getCumulativeList(graphIndex);
+
+		  	    pg.resetPolyline(graphIndex);
+			  	    
+			  	double tmpScale = this.getScale();
+			  	    
+			  	// go through all samples
+        
+	            int thisSample, x, cumValue, thisValue;
+	            int y = visY - 50;
+	            
+			    for (int sampIndx = 0; sampIndx < samples.length; sampIndx++)
+				{
+		            // the x value in thisSample is the timestamp
+		            thisSample = samples[sampIndx];
+		            x = (int)(thisSample / tmpScale / xscale);
+
+		            // the y value is the percentage
+		            thisValue = values[sampIndx];	
+		            cumValue = cumulatives[sampIndx];
+		            y = ((thisValue + cumValue) * (visY - 50)) / heightDivider;
+
+                    pg.addPointToPolyline(graphIndex, x, (visY - 50) - y);
+				} // for
+	  		} //if (pg.isenabled)
+	  	}//while (enum.hasmoreElements)
+	  	updatePolylinesIsNeeded = false;
+	}
+	
+	public void drawGraphsGeneric(Vector<ProfiledGeneric> profiledGenerics, Graphics graphics, Object[] selection)
+	{
+	    if (profiledGenerics.elements() == null)
+	       return;
+	    
+	    // update cumulative thread table
+	    if (this.updateCumulativeThreadTableIsNeeded)
+	       this.genericRefreshCumulativeThreadTable(profiledGenerics.elements());
+	    
+	    // update polylines based on cumulative thread table
+        this.updatePolyLinesGeneric(profiledGenerics.elements());
+	    
+	  	boolean threadIsSelected = false;
+	  	int visY = this.getVisualSize().height;
+	  	ProfiledGeneric pg;
+
+  		GC gc = null;
+  		boolean useImage = false;
+  		int width = sizeX;
+  		int height= sizeY;
+  		// if image < 16KB and image can be allocated, use a pre drawn image instead of
+  		// painting on draw2D graphics, scrolling and repaint from coming into focus
+  		// are faster
+  		if (width * height * 4 <= 16777216){	// 16KB image under 32bit color
+  			if (getGraphImageChanged()) {
+  			  	if (graphImage != null) {
+  	  		  		graphImage.dispose();
+  	  		  	}
+  			  	try {
+  			  		graphImage = new Image(Display.getDefault(), width, height);
+  			  		gc = new GC(this.graphImage);
+  			  		useImage = true;
+  			  	} catch (SWTError e) {
+  			  		// we cannot allocate any more image, stick to slow draw2D
+  			  	}
+  		  	} else {
+  		  		useImage = true;
+  		  	}
+  		} else {
+  			if (graphImage != null) {
+  	  		  	graphImage.dispose();	// don't need this anymore, use draw2D
+  	  		}
+  		}
+	  	
+		if (useImage == false || getGraphImageChanged() == true) { // using graphics for paint or image needs update
+		  	// draw one thread/binary/function at a time
+		  	for (int i = profiledGenerics.size() - 1; i >= 0; i--)
+		  	{
+	  	        pg = profiledGenerics.get(i);
+			  
+		  		if (pg.isEnabled(this.graphIndex)) //is visualised
+			  	{
+				  	// get samples and their corresponding values
+				  	int[] samples = pg.getSampleList();   //time stamps
+				  	int[] values  = pg.getActivityList(); //percentage values
+				  	int[] cumulatives = pg.getCumulativeList(this.graphIndex);
+
+				  	if (this.fillSelected)  //selected items are filled, not all of them
+				  	{
+				  		threadIsSelected = selection.length > 0;
+				  	}
+				  	
+					if (gc != null) {
+						gc.setForeground(pg.getColor());
+						gc.setBackground(pg.getColor());
+					} else {
+						graphics.setForegroundColor(pg.getColor());
+			  			graphics.setBackgroundColor(pg.getColor());
+					}
+		  			drawGraph(pg, threadIsSelected, visY, graphics, gc, cumulatives, samples, values);			
+		  		} //if (pg.isenabled)
+		  	}//while (enum.hasmoreElements)
+		}
+	  	
+	  	if (gc != null) {
+	  		gc.dispose();
+	  	}
+	  	if (useImage) {
+	  		graphics.drawImage(this.graphImage, 0, 0);
+	  		setGraphImageChanged(false);
+	  	}
+	  	
+	  	for (int i = profiledGenerics.size() - 1; i >= 0; i--) {
+	  		pg = profiledGenerics.get(i);
+	  		if (pg.isEnabled(this.graphIndex)) //is visualised
+		  	{
+	  			graphics.setForegroundColor(pg.getColor());
+	  			graphics.setBackgroundColor(pg.getColor());
+		  		drawThreadMarks(pg, visY, graphics);	
+		  	}
+	  	}
+	}
+	
+	public boolean getGraphImageChanged() {
+		return graphImageChanged;
+	}
+	
+	public void setGraphImageChanged(boolean status) {
+		graphImageChanged = status;
+	}
+
+	private int searchSortedPointListForX(PointList list, int xValue, boolean firstLowerIfNoMatch) {
+		// bin search for now
+		if (list.getFirstPoint().x == xValue) {
+			return 0;
+		}
+		if (list.getLastPoint().x == xValue) {
+			return list.size() - 1;
+		}
+		int start = 0;
+		int end = list.size() - 1;
+		int match = 0;
+		while (match == 0) {
+			// no match
+			if (start + 1 == end) {
+				if (firstLowerIfNoMatch) {
+					return start;
+				} else {
+					return end;
+				}
+			}
+			int middle = (start + end) / 2;
+			int middleX = list.getPoint(middle).x;
+			if (middleX == xValue) {
+				match = middle;
+			} else {
+				if (middleX < xValue) {
+					start = middle;
+				} else {
+					end = middle;
+				}
+			}
+		}
+		return match;
+	}
+	
+	/*
+	 *  this method draws a polyline or a polygon in the graph
+	 *  
+	 *  Note: it assumes all polylines have the same number of points 
+	 */
+	private void drawGraph(ProfiledGeneric pg, boolean threadIsSelected, int visY, Graphics graphics, GC gc,
+	        int[] cumulatives, int[] samples, int[] values)
+	{
+		int pointCount = pg.getPointList(this.graphIndex).size();
+		Rectangle drawArea;
+		
+		if (gc != null) {
+			// draw one big picture including non-visible when drawing on image
+			drawArea = new Rectangle(0, 0, sizeX, this.getVisibleArea(graphics).height);
+		} else {
+			drawArea = this.getVisibleArea(graphics);
+		}
+		
+		if (pointCount < 2)	// these lusers really want to see a two pixel wide chart? what's wrong with them
+			return;
+
+		PointList allPointList = pg.getPointList(graphIndex);
+		int xIndex = searchSortedPointListForX(allPointList, drawArea.x, true);
+		PointList visiblePointList = new PointList();
+		
+		Point currentPoint = allPointList.getPoint(xIndex++);
+		visiblePointList.addPoint(currentPoint);
+		
+		currentPoint = allPointList.getPoint(xIndex++);
+		visiblePointList.addPoint(currentPoint);
+		
+		Point peakPointInVertical = null;
+		Point troughPointInVertical = null;
+		Point lastPointInVertical = null;
+		
+		while (xIndex < allPointList.size()) {
+			// only draw visible area
+			if (currentPoint.x >= drawArea.x + drawArea.width) {
+				break;
+			}
+			int lastX = currentPoint.x;
+			currentPoint = allPointList.getPoint(xIndex++);
+			//optimized polyline and draw slighly inaccurate graph for those pixel fine movement, 
+			//only account for peak/valley if x doesn't move(e.g. vertical lines)
+			
+			if (lastX == currentPoint.x) {
+				if (lastPointInVertical == null) {
+					// seen first point in the vertical line 
+					peakPointInVertical = troughPointInVertical = visiblePointList.getLastPoint();
+				}
+				if (troughPointInVertical.y > currentPoint.y) {
+					troughPointInVertical = currentPoint;
+				} else if (peakPointInVertical.y < currentPoint.y) {
+					peakPointInVertical = currentPoint;
+				}
+				lastPointInVertical = currentPoint;
+			}
+			else {
+				// we just write two points of peak and trough of the vertical line if needed and the last
+				// if we seen peak and trough, this way we can render the conceptually inaccurate graph
+				// we less point, but still show the same vertical line on screen
+				if (lastPointInVertical != null) {
+					boolean seenPeakOrTrough = false;
+					if (lastPointInVertical.y != peakPointInVertical.y) {
+						visiblePointList.addPoint(peakPointInVertical);
+						seenPeakOrTrough = true;
+					}
+					if (lastPointInVertical.y != troughPointInVertical.y) {
+						visiblePointList.addPoint(troughPointInVertical);
+						seenPeakOrTrough = true;
+					}
+					if (seenPeakOrTrough) {
+						visiblePointList.addPoint(lastPointInVertical);
+					}
+					peakPointInVertical = null;
+					troughPointInVertical = null;
+					lastPointInVertical = null;
+				}
+				visiblePointList.addPoint(currentPoint);
+			}
+		}
+
+		if (fillFlag)
+		{
+			// close the bottom parameter
+			visiblePointList.addPoint(new Point(visiblePointList.getLastPoint().x, visY - 50));
+			visiblePointList.addPoint(new Point(visiblePointList.getFirstPoint().x, visY - 50));
+
+			if (gc != null) {
+				gc.fillPolygon(visiblePointList.toIntArray());
+			} else {
+				graphics.fillPolygon(visiblePointList.toIntArray());
+			}
+		}
+		else
+		{
+			if (gc != null) {
+				gc.drawPolyline(visiblePointList.toIntArray());
+			} else {
+				graphics.drawPolyline(visiblePointList.toIntArray());
+			}
+		}
+		
+		//creates the first polyListX and polyListY
+		if (fillFlag && (!threadIsSelected && this.fillSelected))
+	  	{
+		    this.resetPolyList(pg, visY, samples, values, cumulatives);
+	  	}
+	}		
+
+	//this method is used to reset the list of points
+	private void resetPolyList(ProfiledGeneric pg, int visY, int[] samples, int[] values, int[] cumulatives)
+	{
+		pg.resetPolyline(graphIndex);
+			
+		int thisValue, cumValue, thisSample, x;
+		int y = (visY - 50);
+		double tmpScale = this.getScale();
+		for (int sampIndx = 0; sampIndx < samples.length; sampIndx++)
+		{
+		  	// the x value in thisSample is the timestamp
+		  	thisSample = samples[sampIndx];
+		  	x = (int)(thisSample / tmpScale);
+												
+            if (x > visibleLeftBorder && x < visibleRightBorder) //draws only visible stuff
+            {
+   			  	// the y value is the percentage
+   			  	thisValue = values[sampIndx];	
+   			  	cumValue = cumulatives[sampIndx];
+   			  	y = ((thisValue + cumValue) * (visY - 50)) / 100;
+	    			  	
+                pg.addPointToPolyline(graphIndex, x, (visY - 50) - y);
+            }
+            else if (x >= visibleRightBorder)  //optimises end drawing
+            {
+                pg.addPointToPolyline(graphIndex, x, visY - 50);
+                sampIndx = samples.length; //breaks the for loop
+            }
+		} // for
+	}
+	
+	public void updateIfNeeded(Vector<ProfiledGeneric> profiledGenerics)
+	{
+	    // updates cumulative thread table
+	    if (this.updateCumulativeThreadTableIsNeeded)
+	       this.genericRefreshCumulativeThreadTable(profiledGenerics.elements());
+	    
+	    // updates polylines based on cumulative thread table
+        this.updatePolyLinesGeneric(profiledGenerics.elements());
+	}
+	
+	public int getVisibleRightBorder()
+	{
+		return this.visibleRightBorder;
+	}
+
+	public int getVisibleLeftBorder()
+	{
+		return this.visibleLeftBorder;
+	}
+
+	public int getVisualSizeX()
+	{
+		return this.visualSizeX;
+	}
+
+	public int getVisualSizeY()
+	{
+		return this.visualSizeY;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/GraphComposite.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.visual;
+
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+
+/**
+ *
+ * A GraphComposite is added to the SashForm for a tab.
+ * 
+ * A GraphComposite has an option centered title, a left area to contain the y-axis
+ * legend, and a scrollable area containing the graph and the x-axis legend.
+ */
+public class GraphComposite extends Composite
+{
+	public FigureCanvas leftLegend;
+	public FigureCanvas figureCanvas;
+
+	public GraphComposite(Composite parent, int style, String titleString)
+	{
+		super(parent, style);
+		this.setLayout(new FormLayout());
+
+       	FormData formData;
+    	Label title = null;
+
+       	if (titleString != null) {
+			title = new Label(this, SWT.CENTER);
+			title.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_CYAN));
+			title.setFont(PIPageEditor.helvetica_8);
+			title.setText(titleString);
+
+			formData = new FormData();
+    		formData.top    = new FormAttachment(0);
+    		formData.left   = new FormAttachment(0);
+    		formData.right  = new FormAttachment(100);
+    		title.setLayoutData(formData);
+		}
+
+		leftLegend   = new FigureCanvas(this);
+       	figureCanvas = new FigureCanvas(this);
+
+		formData = new FormData();
+		if (titleString != null)
+    		formData.top = new FormAttachment(title, 0, SWT.BOTTOM);
+		else
+			formData.top = new FormAttachment(0);
+		formData.bottom = new FormAttachment(100);
+		formData.left   = new FormAttachment(0);
+		formData.width  = GenericTraceGraph.yLegendWidth;
+		leftLegend.setLayoutData(formData);
+
+		formData = new FormData();
+		if (titleString != null)
+    		formData.top = new FormAttachment(title, 0, SWT.BOTTOM);
+		else
+			formData.top = new FormAttachment(0);
+		formData.bottom = new FormAttachment(100);
+		formData.left   = new FormAttachment(leftLegend, 0, SWT.RIGHT);
+		formData.right  = new FormAttachment(100);
+		figureCanvas.setLayoutData(formData);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/GraphDrawRequest.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.visual;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+
+
+public class GraphDrawRequest 
+{
+	/*
+	 * GraphDrawRequest contains data on how the graph should be drawn
+	 * to the composite panel
+	 * 
+	 * Example: 
+	 * draw always ON top of GPP and IRQ traces
+	 * 
+	 * GraphDrawRequest request = new GraphDrawRequest()
+	 * request.addParentGraph(0, "com.nokia.carbide.cpp.pi.address.AddressPlugin", DRAW_TO_ALL_AVAILABLE, 0);
+	 * request.addParentGraph(0, "com.nokia.carbide.cpp.pi.irq.IrqPlugin", DRAW_TO_ALL_AVAILABLE, 0);
+	 * 
+	 * Example:
+	 * draw always on MEM trace, plus additionally, primarily on 
+	 * GPP trace and secondarily on IRQ trace, but not both
+	 * 
+	 * GraphDrawRequest request = new GraphDrawRequest()
+ 	 * request.addParentGraph(0, "com.nokia.carbide.cpp.pi.memory.MemPlugin", DRAW_TO_ALL_AVAILABLE, 0);
+	 * request.addParentGraph(0, "com.nokia.carbide.cpp.pi.address.AddressPlugin", DRAW_TO_MOST_IMPORTANT_AVAILABLE, 1);
+	 * request.addParentGraph(0, "com.nokia.carbide.cpp.pi.irq.IrqPlugin", DRAW_TO_MOST_IMPORTANT_AVAILABLE, 0);
+	 * 
+	 */
+	
+	public static final int DRAW_TO_ALL_AVAILABLE = 1;
+	public static final int DRAW_TO_MOST_IMPORTANT_AVAILABLE = 2;
+	
+	private ArrayList<GraphEntry> internalData;
+	
+	public GraphDrawRequest()
+	{
+		this.internalData = new ArrayList<GraphEntry>();
+	}
+	
+	private static class GraphEntry
+	{
+		protected int editorPage;
+		protected String pluginName;
+		protected int mode;
+		protected int importance;
+	}
+	
+	public void addParentGraph(int editorPage, String pluginName, int mode, int importance)
+	{
+		GraphEntry ge = new GraphEntry();
+		ge.editorPage = editorPage;
+		ge.pluginName = pluginName;
+		ge.mode = mode;
+		ge.importance = importance;
+		this.internalData.add(ge);
+	}
+	
+	protected ArrayList getGraphClassToDraw(int editorPage)
+	{
+		ArrayList<String> finalResult = new ArrayList<String>();
+		
+		int currentMostImportantImportance  = Integer.MIN_VALUE;
+		String currentMostImportantName = null;
+		
+		for (int i = 0; i < internalData.size(); i++)
+		{
+			GraphEntry ge = (GraphEntry)internalData.get(i);
+			if (ge.editorPage == editorPage)
+			{
+				if (ge.mode == GraphDrawRequest.DRAW_TO_ALL_AVAILABLE)
+				{
+					Enumeration plugins = 
+						PluginInitialiser.getPluginInstances(
+								NpiInstanceRepository.getInstance().activeUid(),"com.nokia.carbide.cpp.internal.pi.plugin.model.Plugin"); //$NON-NLS-1$
+					
+					while (plugins.hasMoreElements()) 
+					{
+						Object o = plugins.nextElement();
+						if (o.getClass().getName().equals(ge.pluginName))
+						{
+							finalResult.add(ge.pluginName);
+						}
+					}
+				}
+				
+				if (ge.mode == GraphDrawRequest.DRAW_TO_MOST_IMPORTANT_AVAILABLE)
+				{
+					if (ge.importance > currentMostImportantImportance)
+					{
+						currentMostImportantName = ge.pluginName;
+						currentMostImportantImportance = ge.importance;
+					}
+				}
+			}
+		}
+
+		if (currentMostImportantName != null)
+		{
+			finalResult.add(currentMostImportantName);
+		}
+		
+		return finalResult;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.visual;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.internal.pi.visual.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/PICompositePanel.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,1381 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.visual;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import javax.swing.JDialog;
+
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.FlowLayout;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.MouseMotionListener;
+import org.eclipse.draw2d.Panel;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Slider;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.analyser.TestGUI;
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IContextMenu;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+import com.nokia.carbide.cpp.pi.editors.PIPageEditor;
+import com.nokia.carbide.cpp.pi.util.ColorPalette;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+public class PICompositePanel implements ActionListener, PIEventListener {
+	private SashForm sashForm;
+	private Slider slider = null;
+
+	private static final long serialVersionUID = -6350043592270317606L;
+
+	private static final int MOUSE_DOWN = 0;
+	private static final int MOUSE_MOVE = 1;
+	private static final int MOUSE_DOUBLECLICK = 2;
+
+	private ArrayList<GraphComponentWrapper> graphComponents;
+	private ProfileVisualiser profVisu;
+
+	public int lastSampleX = 0;
+	private int sizeX = 0;
+	private int sizeY = 450;
+	private int preferredSizeX = 100000;
+	private int preferredSizeY = 0; // this is constant!
+
+	private double selectionStart = -1;
+	private double selectionEnd = -1;
+
+	private boolean buttonDown = false;
+	private boolean dragOn = false;
+	private double origStart = 0;
+	private double scale = 10;
+	private double previousScale = 10;
+
+	private PIVisualSharedData sharedData;
+
+	JDialog dialog = null;
+
+	SynchroniseDialog dialogPanel = null;
+	private GenericTraceGraph activeGraph = null;
+
+	// create a ScrollComposite, with a horizontal scrollbar, containing a
+	// sashForm without a scrollbar
+	public PICompositePanel(Composite parent,
+			ProfileVisualiser profileVisualiser) {
+		// all graphs will go into a vertical SashForm
+		this.sashForm = new SashForm(parent, SWT.VERTICAL);
+		this.sashForm.SASH_WIDTH = 5; // 5 pixel wide sash
+		this.sashForm.setLayout(new FillLayout());
+
+		// this.scrolled.setContent(this.sashForm);
+		//		
+		// // listen for when the horizontal scroll bar is selected
+		// final ScrollBar horizontalBar = this.scrolled.getHorizontalBar();
+		//
+		// horizontalBar.addSelectionListener(new SelectionListener() {
+		// public void widgetSelected(SelectionEvent e) {
+		// // since other pages associated with the GppTraceGraph scroll when
+		// this page scrolls,
+		// // also let listening plugins know
+		// int ai = AnalysisIdentifier.getIdentifier();
+		//        		Enumeration enu = PluginInitialiser.getPluginInstances(ai, "com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+		// if (enu != null) {
+		// Event event = new Event();
+		// event.x = scrolled.getOrigin().x;
+		// event.y = scrolled.getOrigin().y;
+		//        			event.data = "FigureCanvas"; //$NON-NLS-1$
+		//        			
+		// while (enu.hasMoreElements())
+		// {
+		// IEventListener plugin = (IEventListener)enu.nextElement();
+		//            			plugin.receiveEvent("scroll", event); //$NON-NLS-1$
+		// }
+		// }
+		// }
+		//
+		// public void widgetDefaultSelected(SelectionEvent e) {
+		// widgetSelected(e);
+		// }
+		// });
+		//
+		// // minor scroll is 10 pixels
+		// horizontalBar.setIncrement(10);
+		//
+		// // major scroll is the width of the window
+		// horizontalBar.setPageIncrement(this.scrolled.getBounds().width);
+		// this.scrolled.addControlListener(new ControlAdapter()
+		// {
+		// public void controlResized(ControlEvent e) {
+		// horizontalBar.setPageIncrement(scrolled.getBounds().width);
+		// }
+		// });
+
+		this.graphComponents = new ArrayList<GraphComponentWrapper>();
+		this.profVisu = profileVisualiser;
+		this.sharedData = new PIVisualSharedData();
+	}
+
+	public SashForm getSashForm() {
+		return this.sashForm;
+	}
+
+	// returns true if the graph needs to be updated (it is either
+	// active or visible)
+	public boolean hasToBeUpdated(GenericTraceGraph graph) {
+		if (graph.getVisualSize().height > 0)
+			return true;
+		else if (graph.equals(this.getActiveGraph()))
+			return true;
+		else
+			return false;
+	}
+
+	// this method adds listeners to graph selections
+	private void addMouseListeners(final GraphComponentWrapper wrap,
+			FigureCanvas graphCanvas) {
+		if (wrap.panel == null)
+			return;
+
+		if (wrap.graphComponent instanceof MouseMotionListener) {
+			wrap.panel
+					.addMouseMotionListener((MouseMotionListener) wrap.graphComponent);
+		}
+
+		if (wrap.graphComponent instanceof MouseMoveListener) {
+			if (graphCanvas != null)
+				graphCanvas
+						.addMouseMoveListener((MouseMoveListener) wrap.graphComponent);
+		}
+
+		if (wrap.graphComponent instanceof MouseListener) {
+			if (graphCanvas != null)
+				graphCanvas
+						.addMouseListener((MouseListener) wrap.graphComponent);
+		}
+
+		if (graphCanvas == null)
+			return;
+
+		final FigureCanvas graphCanvasFinal = graphCanvas;
+		graphCanvas.addMouseListener(new MouseListener() {
+			public void mouseDown(MouseEvent me) {
+				// for button 3, show the popup context menu
+				if (me.button == 3) // button 3
+				{
+					final int x = me.x; // don't worry about me.x, this is
+										// always a valid coordinate within the
+										// panel
+					final int y = me.y;
+					final MouseEvent meFinal = me;
+					Display.getDefault().syncExec(new Runnable() {
+						public void run() {
+							Menu menu = TestGUI.getInstance()
+									.getGraphPopupMenu(
+											profVisu.getContentPane()
+													.getShell(), true);
+
+							// add submenu items
+							addSubGraphMenuItems(menu, meFinal);
+							menu.setLocation(graphCanvasFinal.toDisplay(x, y));
+						}
+					});
+					return;
+				}
+
+				/*
+				 * for other buttons, we may be deleting the current graph
+				 * selection or, by dragging, creating a new selection
+				 */
+				buttonDown = true;
+				dragOn = false;
+
+				// me.x will always be a valid coordinate within the Widget,
+				// rounded to the nearest millisecond
+				// since this is the FigureCanvas, not the Panel, adjust x
+				selectionStart = (int) ((me.x + getScrolledOrigin().x) * scale + .0005);
+
+				origStart = selectionStart;
+
+				// send the message to the component under the mouse
+				if (me.getSource() instanceof GraphComponentWrapper) {
+					GenericTraceGraph source = ((GraphComponentWrapper) me
+							.getSource()).getGraphComponent();
+					if (source instanceof PIEventListener
+							&& hasToBeUpdated(source)) {
+						PIEventListener lis = (PIEventListener) source;
+
+						for (int i = 0; i < graphComponents.size(); i++) {
+							GenericTraceGraph possible = (GenericTraceGraph) graphComponents
+									.get(i).graphComponent;
+							if (possible.equals(source)) {
+								PIEvent be = new PIEvent(source,
+										PIEvent.MOUSE_PRESSED);
+								lis.piEventReceived(be);
+							}
+						}
+					}
+				}
+			}
+
+			public void mouseUp(MouseEvent me) {
+				// ignore releases of button 3 (context menu button)
+				if (me.button == 3) // button 3
+					return;
+
+				// otherwise, either remove the current selection or replace it
+				// with a new one
+				buttonDown = false;
+
+				if (dragOn) // if dragging was done
+				{
+					if (selectionStart == selectionEnd) {
+						// no range is selected
+						selectionStart = -1;
+						selectionEnd = -1;
+					}
+					if (selectionStart < 0 && selectionStart != -1) {
+						selectionStart = 0;
+					}
+
+					double maxEndTime = PIPageEditor.currentPageEditor()
+							.getMaxEndTime() * 1000;
+					if (selectionStart > maxEndTime) {
+						// no range is selected
+						selectionStart = 0;
+						selectionEnd = 0;
+						profVisu.getTimeString().setText(
+								ProfileVisualiser.getTimeInterval(
+										selectionStart / 1000,
+										selectionEnd / 1000));
+					} else if (selectionEnd > maxEndTime) {
+						selectionEnd = maxEndTime + .0005;
+						profVisu.getTimeString().setText(
+								ProfileVisualiser.getTimeInterval(
+										selectionStart / 1000,
+										selectionEnd / 1000));
+					}
+
+					setSelectionFields();
+
+					// inform all subcomponents that the selection area has
+					// changed
+					PIEvent be = new PIEvent(new double[] { selectionStart,
+							selectionEnd }, PIEvent.SELECTION_AREA_CHANGED);
+					sendEventToSubComponents(be);
+					repaintComponent();
+
+					// since some pages that depend on the selection start and
+					// end times may not have
+					// graph components (e.g., the function call plugin page),
+					// also let listening plugins know
+					Enumeration e = PluginInitialiser
+							.getPluginInstances(NpiInstanceRepository
+									.getInstance().activeUid(),
+									"com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+					if (e != null) {
+						Event event = new Event();
+						event.start = (int) selectionStart;
+						event.end = (int) selectionEnd;
+
+						while (e.hasMoreElements()) {
+							IEventListener plugin = (IEventListener) e
+									.nextElement();
+							plugin.receiveEvent("changeSelection", event); //$NON-NLS-1$
+						}
+					}
+
+					dragOn = false;
+				}
+			}
+
+			public void mouseDoubleClick(MouseEvent me) {
+				sendEventToSubGraphs(PICompositePanel.MOUSE_DOUBLECLICK, me);
+				buttonDown = false;
+			}
+		});
+
+		graphCanvas.addMouseMoveListener(new MouseMoveListener() {
+			public void mouseMove(MouseEvent me) {
+
+				int xOrigin = getScrolledOrigin().x;
+
+				me.x += xOrigin;
+
+				if (!buttonDown) {
+					sendEventToSubGraphs(PICompositePanel.MOUSE_MOVE, me);
+					return;
+				}
+
+				// dragging is moving the mouse while a button (other than
+				// button 3) is down
+				dragOn = true;
+
+				// round to the nearest millisecond
+				selectionEnd = (int) (me.x * scale + .0005);
+
+				// mouse event may return out of range X, that may
+				// crash when we use it to index data array
+				selectionEnd = selectionEnd >= 0 ? selectionEnd : 0;
+
+				if (me.x >= xOrigin + sashForm.getBounds().width) {
+					selectionEnd = ((int) ((xOrigin
+							+ sashForm.getBounds().width - 1)
+							* scale + .0005));
+				}
+
+				if (selectionEnd < origStart) // if selection is drawn from
+				// right to left
+				{
+					selectionStart = selectionEnd;
+					selectionEnd = origStart;
+				} else if (selectionEnd > origStart) {
+					selectionStart = origStart;
+				}
+
+				setSelectionFields();
+
+				PIPageEditor.currentPageEditor().setLocalTime(
+						selectionStart / 1000, selectionEnd / 1000);
+
+				// until mouse button is released, change the time interval
+				// display only on this page
+				profVisu.getTimeString().setText(
+						ProfileVisualiser.getTimeInterval(
+								selectionStart / 1000, selectionEnd / 1000));
+
+				drawSelectionRect(me);
+				repaintComponent();
+
+				// why is this not in repaintComponent?
+				wrap.panel.repaint();
+			}
+		});
+	}
+
+	private void drawSelectionRect(MouseEvent me) {
+		if ((me.getSource() == null)
+				|| !(me.getSource() instanceof Control/* Panel */))
+			return;
+
+		// do not use scrolled.getContent().getBounds() because that is the
+		// whole
+		// length, not the visable one
+		Rectangle rect = this.sashForm.getBounds();
+		Point origin = getScrolledOrigin();
+
+		int newX;
+		int tmpMeX = me.x;
+
+		// mouse event may return out of range X, that may
+		// crash when we use it to index data array
+		tmpMeX = tmpMeX >= 0 ? tmpMeX : 0;
+		if (tmpMeX >= origin.x + sashForm.getBounds().width) {
+			tmpMeX = origin.x + sashForm.getBounds().width - 1;
+		}
+
+		if (tmpMeX - origin.x < 20) {
+			newX = tmpMeX - 20;
+			if (newX < 0)
+				newX = 0;
+		} else {
+			newX = tmpMeX + 20;
+		}
+
+		boolean changeOrigin = false;
+
+		// Scroll each of the windows in the ScrolledComposite so that the
+		// rectangle is visible
+		if (newX < origin.x) {
+			// scroll to the left
+			this.setScrolledOrigin(newX, origin.y);
+			changeOrigin = true;
+		} else if (newX > origin.x + rect.width) {
+			// scroll to the right
+			this.setScrolledOrigin(newX - rect.width, origin.y);
+			changeOrigin = true;
+		}
+
+		if (changeOrigin) {
+			// since other pages associated with the GppTraceGraph scroll when
+			// this page scrolls,
+			// also let listening plugins know
+			Enumeration enu = PluginInitialiser
+					.getPluginInstances(NpiInstanceRepository.getInstance()
+							.activeUid(),
+							"com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+			if (enu != null) {
+				origin = getScrolledOrigin();
+				Event event = new Event();
+				event.x = origin.x;
+				event.y = origin.y;
+				event.data = "FigureCanvas"; //$NON-NLS-1$
+
+				while (enu.hasMoreElements()) {
+					IEventListener plugin = (IEventListener) enu.nextElement();
+					plugin.receiveEvent("scroll", event); //$NON-NLS-1$
+				}
+			}
+		}
+	}
+
+	public PIVisualSharedData getSharedData() {
+		return this.sharedData;
+	}
+
+	public void setToolTipTextForGraphComponent(GenericTraceGraph graph,
+			String text) {
+		if (this.graphComponents != null) {
+			for (int i = 0; i < graphComponents.size(); i++) {
+				GraphComponentWrapper wrap = graphComponents.get(i);
+				if (wrap.graphComponent.equals(graph)) {
+					wrap.figureCanvas.setToolTipText(text);
+				}
+			}
+		}
+	}
+
+	public void setScrolledOrigin(int x, int y) {
+		if (this.graphComponents != null) {
+			for (int i = 0; i < graphComponents.size(); i++) {
+				FigureCanvas figureCanvas = graphComponents.get(i).figureCanvas;
+
+				if (figureCanvas == null)
+					continue;
+
+				figureCanvas.getViewport().setViewLocation(x, y);
+				if (figureCanvas.getViewport().getViewLocation().x != x) {
+					// force the viewport to accept the new value
+					figureCanvas.getViewport().getHorizontalRangeModel()
+							.setMaximum(this.sizeX);
+					figureCanvas.getViewport().setViewLocation(x, y);
+				}
+			}
+		}
+	}
+
+	public Point getScrolledOrigin() {
+		// this assumes that setScrolledOrigin() is keeping all graphs scrolled
+		// the same amount
+		if (this.graphComponents == null)
+			return null;
+		else
+			return graphComponents.get(0).figureCanvas.getViewport()
+					.getViewLocation();
+	}
+
+	public void setCurrentInfoComponent(Component currentComponent) {
+		this.profVisu.vPanelRepaint(currentComponent);
+	}
+
+	private void sendEventToSubGraphs(int type, MouseEvent me) {
+		FigureCanvas figureCanvas;
+		GraphComponentWrapper component = null;
+
+		if (!(me.getSource() instanceof FigureCanvas))
+			return;
+
+		figureCanvas = (FigureCanvas) me.getSource();
+
+		// find the component whose FigureCanvas this is
+		for (int i = 0; i < this.graphComponents.size(); i++)
+			if (this.graphComponents.get(i).figureCanvas == figureCanvas) {
+				component = this.graphComponents.get(i);
+				break;
+			}
+
+		if (component == null)
+			return;
+
+		// loop through the subcomponents, finding listeners
+		for (int i = 0; i < component.subGraphs.size(); i++) {
+			GraphComponentWrapper subComponents = component.subGraphs.get(i);
+			Object subgraphComponent = subComponents.getGraphComponent();
+			if (subgraphComponent instanceof MouseListener) {
+				MouseListener listener = (MouseListener) subgraphComponent;
+				if (type == PICompositePanel.MOUSE_DOUBLECLICK)
+					listener.mouseDoubleClick(me);
+				else if (type == PICompositePanel.MOUSE_DOWN)
+					listener.mouseDown(me);
+			}
+			if (subgraphComponent instanceof MouseMoveListener) {
+				MouseMoveListener listener = (MouseMoveListener) subgraphComponent;
+				if (type == PICompositePanel.MOUSE_MOVE)
+					listener.mouseMove(me);
+			}
+		}
+	}
+
+	private void addSubGraphMenuItems(Menu menu, MouseEvent me) {
+		FigureCanvas figureCanvas;
+		GraphComponentWrapper component = null;
+
+		if (!(me.getSource() instanceof FigureCanvas))
+			return;
+
+		figureCanvas = (FigureCanvas) me.getSource();
+
+		// find the component whose FigureCanvas this is
+		for (int i = 0; i < this.graphComponents.size(); i++)
+			if (this.graphComponents.get(i).figureCanvas == figureCanvas) {
+				component = this.graphComponents.get(i);
+				break;
+			}
+
+		if (component == null)
+			return;
+
+		// find this component's context menu items
+		if (component.graphComponent instanceof IContextMenu) {
+			((IContextMenu) component.graphComponent).addContextMenuItems(menu,
+					me);
+		}
+
+		// loop through the subcomponents, finding context menu items
+		for (int i = 0; i < component.subGraphs.size(); i++) {
+			GraphComponentWrapper subComponents = component.subGraphs.get(i);
+			Object subgraphComponent = subComponents.getGraphComponent();
+			if (subgraphComponent instanceof IContextMenu) {
+				((IContextMenu) subgraphComponent)
+						.addContextMenuItems(menu, me);
+			}
+		}
+	}
+
+	private void sendEventToSubComponents(Object event) {
+		for (int i = 0; i < graphComponents.size(); i++) {
+			GenericTraceGraph component = graphComponents.get(i)
+					.getGraphComponent();
+
+			// forward the events only if the component has height
+			// which means that it is not hidden, or if the component is
+			// the currently active component
+			if (hasToBeUpdated(component)) {
+				if (event instanceof ActionEvent
+						&& component instanceof ActionListener) {
+					((ActionListener) component)
+							.actionPerformed((ActionEvent) event);
+				}
+				if (event instanceof PIEvent
+						&& component instanceof PIEventListener) {
+					((PIEventListener) component)
+							.piEventReceived((PIEvent) event);
+				}
+				if (event instanceof FocusEvent
+						&& component instanceof FocusListener) {
+					FocusEvent fe = (FocusEvent) event;
+					if (fe.getID() == FocusEvent.FOCUS_GAINED) {
+						((FocusListener) component).focusGained(fe);
+					} else if (fe.getID() == FocusEvent.FOCUS_LOST) {
+						((FocusListener) component).focusLost(fe);
+					}
+				}
+			}
+		}
+	}
+
+	private void sendEventToActiveSubComponent(Object event) {
+		Object component = this.getActiveGraph();
+
+		if (event instanceof ActionEvent && component instanceof ActionListener) {
+			((ActionListener) component).actionPerformed((ActionEvent) event);
+		}
+		if (event instanceof PIEvent && component instanceof PIEventListener) {
+			((PIEventListener) component).piEventReceived((PIEvent) event);
+		}
+		if (event instanceof FocusEvent && component instanceof FocusListener) {
+			FocusEvent fe = (FocusEvent) event;
+			if (fe.getID() == FocusEvent.FOCUS_GAINED) {
+				((FocusListener) component).focusGained(fe);
+			} else if (fe.getID() == FocusEvent.FOCUS_LOST) {
+				((FocusListener) component).focusLost(fe);
+			}
+		}
+	}
+
+	public void piEventReceived(PIEvent be) {
+		this.sendEventToSubComponents(be);
+	}
+
+	public void selectionChanged() {
+		this.selectFrame();
+		PIEvent be = new PIEvent(new double[] { selectionStart, selectionEnd },
+				PIEvent.SELECTION_AREA_CHANGED);
+		this.sendEventToSubComponents(be);
+	}
+
+	public void actionPerformed(ActionEvent ae) {
+		this.sendEventToSubComponents(ae);
+		if ((ae.getActionCommand() == "start") //$NON-NLS-1$
+				|| (ae.getActionCommand() == "end")) //$NON-NLS-1$
+		{
+			this.selectFrame();
+			PIEvent be = new PIEvent(new double[] { selectionStart,
+					selectionEnd }, PIEvent.SELECTION_AREA_CHANGED);
+			this.sendEventToSubComponents(be);
+		}
+	}
+
+	public void focusGained(FocusEvent fe) {
+	}
+
+	public void paintComponent(PaintEvent paintEvent) {
+		this.refreshSubcomponentValues();
+	}
+
+	public void repaintComponent() {
+		this.refreshSubcomponentValues();
+	}
+
+	public void paintLeftLegend() {
+		if (this.graphComponents != null) {
+			// for each graph component set updated values
+			for (int i = 0; i < graphComponents.size(); i++) {
+				GraphComponentWrapper wrap = graphComponents.get(i);
+				if (wrap.leftLegend != null) {
+					wrap.leftLegend.redraw();
+				}
+			}
+		}
+	}
+
+	private void refreshSubcomponentValues() {
+		if (this.graphComponents != null) {
+			// for each graph component set updated values
+			for (int i = 0; i < graphComponents.size(); i++) {
+				GraphComponentWrapper wrap = graphComponents.get(i);
+				GenericTraceGraph component = wrap.getGraphComponent();
+				component.setSize(this.sizeX, this.sizeY);
+				component.setScale(this.scale);
+				component.setSelectionEnd(this.selectionEnd);
+				component.setSelectionStart(this.selectionStart);
+				if (wrap.figureCanvas != null) {
+					component.setVisualSize(
+							wrap.figureCanvas.getClientArea().width,
+							wrap.figureCanvas.getClientArea().height);
+					wrap.figureCanvas.redraw();
+					wrap.leftLegend.redraw();
+				}
+			}
+		}
+	}
+
+	public void addGraphComponent(GenericTraceGraph component, String title,
+			Class pluginClass, GraphDrawRequest request) {
+		// insert CompositePanel into wrapper and put it into top part of the
+		// splitpane
+		component.importParentComponent(this);
+
+		GraphComponentWrapper wrap;
+
+		// add the wrapper to the SashForm
+		wrap = new GraphComponentWrapper(this, component, request, pluginClass
+				.getName());
+		this.graphComponents.add(wrap);
+
+		FigureCanvas graphCanvas = null;
+
+		// This treats all getGraphClassToDraw editor pages the same
+		if (request == null
+				|| request.getGraphClassToDraw(component.graphIndex).size() == 0) {
+			graphCanvas = wrap.setCanvas(component, title, this.sashForm,
+					SWT.NONE);
+		}
+
+		// add any mouse listeners from the base class
+		this.addMouseListeners(wrap, graphCanvas);
+		repaintComponent();
+
+		for (int i = 0; i < graphComponents.size(); i++) {
+			wrap = graphComponents.get(i);
+			wrap.newPluginAdded();
+		}
+	}
+
+	public void setSelectionFields(int selectionStart, int selectionEnd) {
+		this.selectionStart = selectionStart;
+		this.selectionEnd = selectionEnd;
+		setSelectionFields();
+	}
+
+	private void setSelectionFields() {
+		if (selectionStart == -1 || selectionEnd == -1) {
+			this.profVisu.setTimeInterval(0, 0);
+			this.selectionStart = -1;
+			this.selectionEnd = -1;
+		} else {
+			double start = selectionStart / 1000;
+			double end = selectionEnd / 1000;
+
+			if ((PIPageEditor.currentPageEditor().getStartTime() != start)
+					|| (PIPageEditor.currentPageEditor().getEndTime() != end)) {
+				this.profVisu.setTimeInterval(start, end);
+				this.profVisu.action("changeInterval"); //$NON-NLS-1$
+			}
+		}
+	}
+
+	public double getSelectionStart() {
+		return this.selectionStart;
+	}
+
+	public double getSelectionEnd() {
+		return this.selectionEnd;
+	}
+
+	/*
+	 * Check the current page editor's start and end times
+	 */
+	public boolean validInterval() {
+		if ((PIPageEditor.currentPageEditor().getStartTime() < 0.0f)
+				|| (PIPageEditor.currentPageEditor().getEndTime() < 0.0f))
+			return false;
+
+		int start = (int) (PIPageEditor.currentPageEditor().getStartTime() * 1000);
+		int end = (int) (PIPageEditor.currentPageEditor().getEndTime() * 1000);
+
+		if (start > this.lastSampleX)
+			start = this.lastSampleX;
+
+		if (end > this.lastSampleX)
+			end = this.lastSampleX;
+
+		if ((start >= end) || (start < 0))
+			return false;
+
+		return true;
+	}
+
+	/*
+	 * Based on the current page editor's start and end times, set this
+	 * PICompositePanel's start and end times.
+	 */
+	private void selectFrame() {
+		if ((PIPageEditor.currentPageEditor().getStartTime() < 0.0f)
+				|| (PIPageEditor.currentPageEditor().getEndTime() < 0.0f))
+			return;
+
+		double start = PIPageEditor.currentPageEditor().getStartTime();
+		double end = PIPageEditor.currentPageEditor().getEndTime();
+
+		selectionStart = start * 1000;
+		selectionEnd = end * 1000;
+
+		if (selectionStart > (double) this.lastSampleX)
+			selectionStart = (double) this.lastSampleX;
+
+		if (selectionEnd > (double) this.lastSampleX)
+			selectionEnd = (double) this.lastSampleX;
+
+		if ((selectionEnd - selectionStart) <= 0.5) {
+			selectionStart = -1;
+			selectionEnd = -1;
+		}
+
+		if (selectionStart < 0 && selectionStart != -1) {
+			selectionStart = 0;
+		}
+
+		setSelectionFields();
+		repaintComponent();
+
+		for (int i = 0; i < graphComponents.size(); i++) {
+			FigureCanvas figureCanvas = graphComponents.get(i).figureCanvas;
+			if (figureCanvas != null)
+				figureCanvas.update();
+		}
+	}
+
+	public void zoomTo(double start, double end) {
+		this.scale = 10;
+		this.setSizeX(false);
+
+		// Window size
+		Composite parent = NpiInstanceRepository.getInstance()
+				.activeUidGetParentComposite();
+		if (parent == null) {
+			// no parent composite is only for temp instance used by non-GUI
+			// importer
+			GeneralMessages.showErrorMessage(Messages
+					.getString("PICompositePanel.0")); //$NON-NLS-1$
+			return;
+		}
+
+		Rectangle window = parent.getBounds();
+
+		// it shouldn't be, but it happened
+		if (window.width <= 0)
+			return;
+
+		// Set new scale
+		int windowLength = window.width;
+		double traceLength = end - start;
+		double dFactor = ((double) traceLength / (double) windowLength) * 10;
+
+		this.scale = dFactor;
+
+		// Snap to next Zoom out factor unless it fits exactly
+		if (this.scale != nextScale(nextScale(this.scale, true), false))
+			this.scale = nextScale(this.scale, true);
+
+		// inform all subcomponents
+		PIEvent be = new PIEvent(new Double(scale), PIEvent.SCALE_CHANGED);
+		this.sendEventToSubComponents(be);
+
+		this.setSizeX(false);
+		repaintComponent();
+	}
+
+	public void forceSizeX() {
+
+	}
+
+	public void setSizeX(boolean forceUpdate) {
+		double sample = this.lastSampleX;
+		int prefSize = (int) (sample / scale);
+
+		if ((this.preferredSizeX == prefSize)
+				&& (this.sizeX == this.preferredSizeX) && !forceUpdate)
+			return;
+
+		this.preferredSizeX = prefSize;
+		this.sizeX = this.preferredSizeX;
+
+		// make sure all graphs of this sashForm get the new width
+		Control[] controls = this.sashForm.getChildren();
+
+		for (int i = 0; i < controls.length; i++) {
+			if (!(controls[i] instanceof GraphComposite))
+				continue;
+
+			GraphComposite composite = (GraphComposite) controls[i];
+			FigureCanvas figureCanvas = composite.figureCanvas;
+			Panel panel = (Panel) figureCanvas.getContents();
+
+			panel.setPreferredSize(prefSize, this.preferredSizeY);
+			if (prefSize >= figureCanvas.getClientArea().width) {
+				panel.setSize(prefSize, this.preferredSizeY);
+			}
+
+		}
+
+		this.sashForm.layout();
+		this.sashForm.redraw();
+	}
+
+	public void setActive(GenericTraceGraph graph) {
+		activeGraph = graph;
+	}
+
+	public GenericTraceGraph getActiveGraph() {
+		return activeGraph;
+	}
+
+	public void setSelectionCenter() {
+		if (selectionStart == -1 && selectionEnd == -1) {
+			this.updateVisibleCenter();
+			return;
+		}
+		previousScale = scale;
+
+		Rectangle window = this.sashForm.getBounds();
+
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+		if (window.width == 0) {
+			// use the width from the active page
+			int currentPage = PIPageEditor.currentPageEditor().getCurrentPage();
+			window = NpiInstanceRepository.getInstance().getProfilePage(uid,
+					currentPage).getTopComposite().getSashForm().getBounds();
+		}
+
+		// Whole trace
+		double selectionLength = selectionEnd - selectionStart;
+		double selectionMiddle = selectionStart + (selectionLength / 2);
+		int windowLength = (int) (window.width * (this.scale / 10));
+		int newPositionX = (int) ((selectionMiddle / 10) - ((double) windowLength / 2));
+
+		newPositionX = (int) ((double) newPositionX / (this.scale / 10));
+
+		if (newPositionX < 0) {
+			newPositionX = 0;
+		}
+
+		this.setScrolledOrigin(newPositionX, 0);
+		repaintComponent();
+	}
+
+	private void updateVisibleCenter() {
+		double centerPosition = getSelection()
+				+ (this.sashForm.getBounds().width / 2);
+
+		if (scale < previousScale)
+			centerPosition = centerPosition * previousScale / scale;
+		else if (scale > previousScale)
+			centerPosition = centerPosition * scale / previousScale;
+
+		previousScale = scale;
+
+		centerPosition = centerPosition - this.sashForm.getBounds().width / 2;
+
+		setOrigin((int) centerPosition, 0);
+		repaintComponent();
+	}
+
+	private int getSelection() {
+		if (this.slider == null)
+			return 0;
+		else
+			return this.slider.getSelection();
+	}
+
+	private void setOrigin(int originX, int originY) {
+		// for all components in the sashForm, except the one with the slider,
+		// adjust the graphs
+	}
+
+	public void performSynchronise() {
+		if (dialog == null) {
+			// dialog = new JFrame();
+			dialog = new JDialog();
+			dialog.setTitle("Syncronise"); //$NON-NLS-1$
+			dialogPanel = new SynchroniseDialog(this);
+			dialog.setContentPane(dialogPanel);
+			dialog.setSize(200, 100);
+			dialog.setLocation(50, 50);
+			dialog.setResizable(false);
+			dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+		}
+		dialog.setVisible(true);
+	}
+
+	public void synchroniseOk() {
+		dialog.dispose();
+		String synchString = dialogPanel.getGppFileName();
+		Double synchValue = new Double(synchString);
+		PIEvent be = new PIEvent(synchValue, PIEvent.SYNCHRONISE);
+		this.sendEventToActiveSubComponent(be);
+		repaintComponent();
+	}
+
+	public void synchroniseCancel() {
+		dialog.dispose();
+	}
+
+	/**
+	 * using log10 to extract the first digit in decimal and make any number
+	 * fall into buckets to promote/demote to scale of ..., 0.1, 0.2, 0.5, 1, 2,
+	 * 5 ...
+	 */
+	private double nextScale(double scale, boolean bigger) {
+		double logScale = Math.log10(scale);
+		double floorLogScale = Math.floor(Math.log10(scale));
+		double mostSignificantDigit = Math.rint(Math.pow(10,
+				(logScale - floorLogScale)));
+		double powerOfTen = Math.pow(10, floorLogScale);
+
+		if (bigger) {
+			if (mostSignificantDigit < 2) {
+				mostSignificantDigit = 2;
+			} else if (mostSignificantDigit < 5) {
+				mostSignificantDigit = 5;
+			} else {
+				mostSignificantDigit = 10;
+			}
+		} else {
+			if (mostSignificantDigit > 5) {
+				mostSignificantDigit = 5;
+			} else if (mostSignificantDigit > 2) {
+				mostSignificantDigit = 2;
+			} else if (mostSignificantDigit > 1) {
+				mostSignificantDigit = 1;
+			} else {
+				mostSignificantDigit = 0.5;
+			}
+		}
+
+		double result = mostSignificantDigit * powerOfTen;
+
+		if (result < 0.1)
+			result = 0.1;
+
+		return result;
+	}
+
+	public void performZoomCommand(String zoomCommand) {
+		// only apply when the currently visible page has a graph
+		if (getActiveGraph() == null)
+			return;
+
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+
+		if (zoomCommand.equals("changeInterval")) { //$NON-NLS-1$
+			// just use a refresh because drag select uses this too
+			// we keep this update here instead of in ProfileVisualiser
+			// to consolidate all screen related calls to be in this file
+			getSashForm().update();
+			return;
+		}
+
+		// the rest are all real zoom command that need repaint on of the image
+		for (int i = 0; i < graphComponents.size(); i++) {
+			GraphComponentWrapper wrap = graphComponents.get(i);
+			GenericTraceGraph component = wrap.getGraphComponent();
+			component.setGraphImageChanged(true);
+		}
+
+		// zoom out
+		if (zoomCommand.equals("+")) //$NON-NLS-1$
+		{
+			PICompositePanel visibleComposite = NpiInstanceRepository
+					.getInstance().getProfilePage(uid,
+							PIPageEditor.currentPageIndex()).getTopComposite();
+			Composite parent = NpiInstanceRepository.getInstance()
+					.activeUidGetParentComposite();
+			if (parent == null) {
+				// no parent composite is only for temp instance used by non-GUI
+				// importer
+				GeneralMessages.showErrorMessage(Messages
+						.getString("PICompositePanel.1")); //$NON-NLS-1$
+				return;
+			}
+
+			// bail out if we already made the whole graph visible
+			if (visibleComposite.lastSampleX / scale <= parent.getBounds().width) // TODO
+																					// visibleComposite
+				return;
+
+			// if the scale will not change, do not redraw
+			if (scale == nextScale(scale, true))
+				return;
+
+			scale = nextScale(scale, true);
+
+			PIEvent be = new PIEvent(new Double(scale), PIEvent.SCALE_CHANGED);
+			this.sendEventToSubComponents(be);
+
+			this.setSizeX(false);
+			this.setSelectionCenter();
+		}
+		// zoom in
+		else if (zoomCommand.equals("-")) //$NON-NLS-1$
+		{
+			// if the scale will not change, do not redraw
+			if (scale <= 0)
+				return;
+
+			if (scale == nextScale(scale, false))
+				return;
+
+			scale = nextScale(scale, false);
+
+			PIEvent be = new PIEvent(new Double(scale), PIEvent.SCALE_CHANGED);
+			this.sendEventToSubComponents(be);
+
+			this.setSizeX(false);
+			this.setSelectionCenter();
+		}
+		// show whole graph
+		else if (zoomCommand.equals("++")) //$NON-NLS-1$
+		{
+			PICompositePanel visibleComposite = NpiInstanceRepository
+					.getInstance().getProfilePage(uid,
+							PIPageEditor.currentPageIndex()).getTopComposite();
+
+			performZoomToGraph(visibleComposite,
+					NpiInstanceRepository.getInstance()
+							.activeUidGetParentComposite().getBounds().width);
+		}
+		// zoom to selected time interval
+		else if (zoomCommand.equals("--")) //$NON-NLS-1$
+		{
+			selectFrame();
+			if (selectionStart != -1 && selectionEnd != -1) {
+				zoomTo(selectionStart / 10, selectionEnd / 10);
+				setSelectionCenter();
+			} else {
+				GeneralMessages
+						.showErrorMessage(Messages
+								.getString("PICompositePanel.selectNonEmptyTimeInterval")); //$NON-NLS-1$
+			}
+		}
+	}
+
+	public void performZoomToGraph(PICompositePanel visibleComposite, int width) {
+		// left margin is not available for painting
+		int availableWidth = width - GenericTraceGraph.yLegendWidth;
+		// NOTE: assumes tabs without graphs have sample == 0
+		if (visibleComposite.lastSampleX <= 0)
+			return;
+
+		double new_scale = scale;
+
+		// first zoom in until it is too big to fit
+		while (visibleComposite.lastSampleX / new_scale <= availableWidth)
+			new_scale = nextScale(new_scale, false);
+
+		// now zoom out until it just fits
+		while (visibleComposite.lastSampleX / new_scale > availableWidth)
+			new_scale = nextScale(new_scale, true);
+
+		if (new_scale == scale)
+			return;
+
+		scale = new_scale;
+
+		PIEvent be = new PIEvent(new Double(scale), PIEvent.SCALE_CHANGED);
+		this.sendEventToSubComponents(be);
+
+		this.setSizeX(false);
+		this.setSelectionCenter();
+	}
+
+	public class GraphComponentWrapper {
+		public GenericTraceGraph graphComponent;
+		public FigureCanvas leftLegend;
+		public FigureCanvas figureCanvas;
+		public Panel panel = null;
+		public ArrayList<GraphComponentWrapper> subGraphs;
+		private GraphDrawRequest howToDraw;
+		private String myPluginName;
+		private PICompositePanel compositePanel;
+
+		public GraphComponentWrapper(PICompositePanel compositePanel,
+				GenericTraceGraph graph, GraphDrawRequest howToDraw,
+				String myPluginName) {
+			this.compositePanel = compositePanel;
+			this.graphComponent = graph;
+			this.howToDraw = howToDraw;
+			this.myPluginName = myPluginName;
+
+			this.subGraphs = new ArrayList<GraphComponentWrapper>();
+		}
+
+		public FigureCanvas setCanvas(GenericTraceGraph component,
+				String title, Composite parent, int style) {
+			final GenericTraceGraph componentFinal = component;
+			final ArrayList<GraphComponentWrapper> subGraphsFinal = this.subGraphs;
+			final GraphComponentWrapper wrapFinal = this;
+			final PICompositePanel compositePanelFinal = this.compositePanel;
+
+			GraphComposite composite = new GraphComposite(parent, style, title);
+			this.leftLegend = composite.leftLegend;
+			this.figureCanvas = composite.figureCanvas;
+
+			this.leftLegend.setBackground(ColorPalette.getColor(new RGB(255,
+					255, 255)));
+			final FigureCanvas leftLegendFinal = leftLegend;
+			leftLegend.addControlListener(new ControlAdapter() {
+				public void controlResized(ControlEvent e) {
+					leftLegendFinal.setSize(GenericTraceGraph.yLegendWidth,
+							leftLegendFinal.getSize().y);
+					componentFinal.paintLeftLegend(leftLegendFinal, null);
+				}
+			});
+
+			leftLegend.addPaintListener(new PaintListener() {
+				public void paintControl(PaintEvent e) {
+					// draw only if the graph is visible
+					if (compositePanelFinal.hasToBeUpdated(componentFinal))
+						componentFinal.paintLeftLegend(leftLegendFinal, e.gc);
+				}
+			});
+
+			this.figureCanvas.setBackground(ColorPalette.getColor(new RGB(255,
+					255, 255)));
+
+			if (this.panel == null) {
+				this.panel = new Panel() {
+					public void paint(Graphics graphics) {
+						// draw only if the graph is visible
+						if (compositePanelFinal.hasToBeUpdated(componentFinal)) {
+							componentFinal.paint(this, graphics);
+
+							for (int i = 0; i < subGraphsFinal.size(); i++) {
+								GraphComponentWrapper wrap = subGraphsFinal
+										.get(i);
+								wrap.setVisualParametersFrom(wrapFinal);
+								wrap.graphComponent.paint(panel, graphics);
+							}
+						}
+					}
+				};
+			}
+			panel.setLayoutManager(new FlowLayout());
+			figureCanvas.setContents(panel);
+
+			// listen for when the horizontal scroll bar is selected
+			final ScrollBar horizontalBar = figureCanvas.getHorizontalBar();
+
+			horizontalBar.addSelectionListener(new SelectionListener() {
+				public void widgetSelected(SelectionEvent e) {
+					// since other pages associated with the GppTraceGraph
+					// scroll when this page scrolls,
+					// also let listening plugins know
+					Enumeration enu = PluginInitialiser
+							.getPluginInstances(NpiInstanceRepository
+									.getInstance().activeUid(),
+									"com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+					if (enu != null) {
+						Event event = new Event();
+						event.x = figureCanvas.getViewport().getViewLocation().x;
+						event.y = figureCanvas.getViewport().getViewLocation().y;
+						event.data = "FigureCanvas"; //$NON-NLS-1$
+
+						while (enu.hasMoreElements()) {
+							IEventListener plugin = (IEventListener) enu
+									.nextElement();
+							plugin.receiveEvent("scroll", event); //$NON-NLS-1$
+						}
+					}
+				}
+
+				public void widgetDefaultSelected(SelectionEvent e) {
+					widgetSelected(e);
+				}
+			});
+
+			// minor scroll is 10 pixels
+			horizontalBar.setIncrement(10);
+
+			// major scroll is the width of the window
+			horizontalBar.setPageIncrement(figureCanvas.getBounds().width);
+			figureCanvas.addControlListener(new ControlAdapter() {
+				public void controlResized(ControlEvent e) {
+					horizontalBar
+							.setPageIncrement(figureCanvas.getBounds().width);
+					graphComponent.setGraphImageChanged(true);
+					graphComponent.repaint();
+				}
+			});
+
+			return this.figureCanvas;
+		}
+
+		public void setVisualParametersFrom(GraphComponentWrapper parent) {
+			if (graphComponent == null)
+				return;
+
+			GenericTraceGraph gtg = parent.getGraphComponent();
+			this.graphComponent.setScale(gtg.getScale());
+			this.graphComponent.setVisualSize(gtg.getVisualSizeX(), gtg
+					.getVisualSizeY());
+		}
+
+		public void newPluginAdded()// ArrayList<GraphComponentWrapper>
+									// graphComponents)
+		{
+			if (this.myPluginName == null)
+				return;
+
+			this.subGraphs.clear();
+
+			for (int i = 0; i < graphComponents.size(); i++) {
+				GraphComponentWrapper wrap = graphComponents.get(i);
+				if (wrap.howToDraw != null) {
+					// This treats all getGraphClassToDraw editor pages the same
+					ArrayList e2 = wrap.howToDraw
+							.getGraphClassToDraw(wrap.graphComponent.graphIndex);
+					for (int j = 0; j < e2.size(); j++) {
+						String s = (String) e2.get(j);
+						if (this.myPluginName.equals(s)) {
+							this.subGraphs.add(wrap);
+						}
+					}
+				}
+			}
+		}
+
+		public GenericTraceGraph getGraphComponent() {
+			return this.graphComponent;
+		}
+	}
+
+	public double getScale() {
+		return scale;
+	}
+
+	public ProfileVisualiser getVisualiser() {
+		return this.profVisu;
+	}
+
+	public void selectWholeGraph() {
+
+		// Get visible composite
+		int uid = NpiInstanceRepository.getInstance().activeUid();
+		PICompositePanel visibleComposite = NpiInstanceRepository.getInstance()
+				.getProfilePage(uid, PIPageEditor.currentPageIndex())
+				.getTopComposite();
+
+		// Set selectionStart and selectionEnd
+		selectionStart = 0;
+		selectionEnd = visibleComposite.lastSampleX;
+		setSelectionFields();
+
+		// inform all subcomponents that the selection area has changed
+		PIEvent be = new PIEvent(new double[] { selectionStart, selectionEnd },
+				PIEvent.SELECTION_AREA_CHANGED);
+		sendEventToSubComponents(be);
+		repaintComponent();
+
+		// since some pages that depend on the selection start and end times may
+		// not have
+		// graph components (e.g., the function call plugin page), also let
+		// listening plugins know
+		Enumeration e = PluginInitialiser
+				.getPluginInstances(NpiInstanceRepository.getInstance()
+						.activeUid(),
+						"com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+		if (e != null) {
+			Event event = new Event();
+			event.start = (int) selectionStart;
+			event.end = (int) selectionEnd;
+
+			while (e.hasMoreElements()) {
+				IEventListener plugin = (IEventListener) e.nextElement();
+				plugin.receiveEvent("changeSelection", event); //$NON-NLS-1$
+			}
+		}
+		//
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/PIEvent.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: PIEvent.java 
+ *
+ */
+
+package com.nokia.carbide.cpp.internal.pi.visual;
+
+public class PIEvent 
+{
+	public static final int SELECTION_AREA_CHANGED = 0; 
+	// event should contain an int[2] object, 
+	// where selection start = object[0] and end = object[1]
+
+	public static final int SELECTION_AREA_CHANGED2 = 1; 
+	// event should contain an int[2] object, 
+	// where selection start = object[0] and end = object[1]
+
+	public static final int SELECTION_AREA_CHANGED3 = 20; 
+	// event should contain an int[2] object, 
+	// where selection start = object[0] and end = object[1]
+
+	public static final int SCALE_CHANGED = 2;
+	// event should contain a Double object, 
+	// containing the new scale value
+	
+	public static final int SET_FILL_ALL_THREADS = 3; 
+	// no value object required
+	
+	public static final int SET_FILL_OFF = 4;
+	// no value object required
+	
+	public static final int SET_FILL_SELECTED_THREAD = 5; 
+	// no value object required
+	
+	public static final int CHANGED_THREAD_TABLE  = 6;
+	// no value object required
+	
+	public static final int CHANGED_BINARY_TABLE = 7;
+	// no value object required
+	
+	public static final int CHANGED_FUNCTION_TABLE = 8;
+	// no value object required
+	
+	public static final int SYNCHRONISE = 9;
+	// value object is the number of seconds added/reduced
+	
+	public static final int DSP_SET_FILL_ALL_THREADS = 10; 
+	// no value object required
+	
+	public static final int DSP_SET_FILL_OFF = 11;
+	// no value object required
+	
+	public static final int DSP_SET_FILL_SELECTED_THREAD = 12; 
+	// no value object required
+	
+	public static final int DSP_RESOLUTION_CHANGED = 13;
+	// event should contain a Double object, 
+	// containing the new DSP resolution value
+	
+	public static final int PF_LIST_VALUE_CHANGED = 14;
+	// event should contain a Double object, 
+	// containing the new DSP resolution value
+	
+	public static final int TIME_SCALE_CHANGED = 15;
+	// event should contain a Double object, 
+	// containing the new DSP resolution value	
+
+	public static final int SUBGRAPH_INSERTED = 16;
+	// event contains a reference to the subcomponent
+	
+	public static final int GPP_SET_BAR_GRAPH_ON = 17;
+	// set bar graph mode in GPP trace visualisation
+	
+	public static final int GPP_SET_BAR_GRAPH_OFF = 18;
+	// set normal mode in GPP trace visualisation
+	
+	public static final int MOUSE_PRESSED = 19;
+	// value object is the source object of the click
+
+	public static final int THRESHOLD_THREAD_CHANGED   = 20;
+	public static final int THRESHOLD_BINARY_CHANGED   = 21;
+	public static final int THRESHOLD_FUNCTION_CHANGED = 22;
+	// no value object because we can use the global value
+	
+	public static final int POWER_GRAPH_AVG_ON     = 23;
+	public static final int POWER_GRAPH_AVG_OFF    = 24;
+	public static final int POWER_INTERVAL_AVG_ON  = 25;
+	public static final int POWER_INTERVAL_AVG_OFF = 26;
+	public static final int POWER_SHOW_AVG_ON      = 27;
+	public static final int POWER_SHOW_AVG_OFF     = 28;
+	// no value object required
+
+	public static final int CHANGED_MEMORY_TABLE = 29;
+	// no value object required
+	
+	public static final int SCROLLED = 30;
+	// event should contain an org.eclipse.swt.widgets.Event
+	// with the new origin in its x and y
+
+	public static final int PLUGIN_STRING_MESSAGE = 100;
+	// event should contain a Double object, 
+	// containing the new DSP resolution value
+
+	private Object valueObject;
+	private int type;
+	
+	public PIEvent(Object valueObject, int type)
+	{
+		this.valueObject = valueObject;
+		this.type = type;
+	}
+	
+	public Object getValueObject()
+	{
+		return this.valueObject;
+	}
+	
+	public int getType()
+	{
+		return this.type;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/PIEventListener.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: PIEventListener.java 
+ *
+ */
+
+package com.nokia.carbide.cpp.internal.pi.visual;
+
+public interface PIEventListener 
+{
+	public void piEventReceived(PIEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/PIVisualSharedData.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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: PIVisualSharedData.java
+ *
+ */
+
+package com.nokia.carbide.cpp.internal.pi.visual;
+
+public class PIVisualSharedData 
+{
+	// add only basic object types such as
+	// String, Integer, Long, etc.
+	// Do not add instances of any application specific class
+	
+	public String[] GPP_SelectedThreadNames;
+	public String[] GPP_SelectedBinaryNames;
+	public String[] GPP_SelectedFunctionNames;
+	public int[] GPP_SelectedThreadIndicies;
+	public int[] GPP_SelectedBinariesIndicies;
+	public int[] GPP_SelectedFunctionIndicies;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/SynchroniseDialog.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.internal.pi.visual;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+public class SynchroniseDialog extends JPanel
+{
+	private static final long serialVersionUID = -7841684215277143128L;
+	private JPanel buttonPanel = null;
+    private JPanel gppPanel = null;
+    private JLabel gppLabel = null;
+    private JTextField gppField = null;
+    private JButton okButton = null;
+    private JButton cancelButton = null;
+    private PICompositePanel composite = null;
+
+    /**
+     * This is the default constructor
+     */
+    public SynchroniseDialog(PICompositePanel aComposite)
+    {
+        super();
+        try {
+        	composite = aComposite;
+	        ButtonListener cbl = new ButtonListener();
+	        initialize();
+
+	        getOkButton().addActionListener(cbl);
+	        getCancelButton().addActionListener(cbl);
+        }
+        catch(Exception ex) {
+          ex.printStackTrace();
+        }
+    }
+    
+    public String getGppFileName()
+    {
+    	if (gppField.isEnabled())
+    		return gppField.getText();
+    	else
+    		return ""; //$NON-NLS-1$
+    }
+    
+    /**
+     * This method initializes jButton2
+     * 
+     * @return javax.swing.JButton
+     */
+    private JButton getOkButton()
+    {
+        if (okButton == null)
+        {
+        	okButton = new JButton();
+        	okButton.setText(Messages.getString("SynchroniseDialog.ok")); //$NON-NLS-1$
+        	okButton.setActionCommand("ok"); //$NON-NLS-1$
+        }
+        return okButton;
+    }
+    
+    /**
+     * This method initializes jButton2
+     * 
+     * @return javax.swing.JButton
+     */
+    private JButton getCancelButton()
+    {
+        if (cancelButton == null)
+        {
+        	cancelButton = new JButton();
+        	cancelButton.setText(Messages.getString("SynchroniseDialog.cancel")); //$NON-NLS-1$
+        	cancelButton.setActionCommand("cancel"); //$NON-NLS-1$
+        }
+        return cancelButton;
+    }
+    
+    /**
+     * This method initializes this
+     * 
+     * @return void
+     */
+    private void initialize()
+    {
+        java.awt.GridLayout gridLayout = new GridLayout(2, 1);
+        this.setLayout(gridLayout);
+        this.add(getGppPanel(), null);
+        this.add(getButtonPanel(), null);
+    }
+    
+    private JPanel getGppPanel()
+    {
+        if (gppPanel == null)
+        {
+        	gppPanel = new JPanel();
+        	gppLabel = new JLabel();
+        	gppField = new JTextField();
+        	
+        	gppPanel.setLayout(new BorderLayout());
+            gppLabel.setText(Messages.getString("SynchroniseDialog.value")); //$NON-NLS-1$
+            gppPanel.setBorder(javax.swing.BorderFactory
+                            .createEtchedBorder(javax.swing.border.EtchedBorder.RAISED));
+            gppPanel.add(gppLabel, java.awt.BorderLayout.NORTH);
+            gppPanel.add(gppField, java.awt.BorderLayout.CENTER);
+        }
+        return gppPanel;
+    }
+    
+    
+    /**
+     * This method initializes jPanel2
+     * 
+     * @return javax.swing.JPanel
+     */
+    private JPanel getButtonPanel()
+    {
+        if (buttonPanel == null)
+        {
+            buttonPanel = new JPanel();
+            buttonPanel.setBorder(javax.swing.BorderFactory
+                            .createEtchedBorder(javax.swing.border.EtchedBorder.RAISED));
+            buttonPanel.add(getOkButton(), java.awt.BorderLayout.CENTER);
+            buttonPanel.add(getCancelButton(), java.awt.BorderLayout.EAST);
+        }
+        return buttonPanel;
+    }
+
+    class ButtonListener implements ActionListener
+    {
+        public void actionPerformed(ActionEvent ae)
+        {
+            if (ae.getActionCommand().equals("ok")) //$NON-NLS-1$
+            {
+            	composite.synchroniseOk();
+            }
+            else if (ae.getActionCommand().equals("cancel")) //$NON-NLS-1$
+            {
+            	composite.synchroniseCancel();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/visual/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,44 @@
+PICompositePanel.selectNonEmptyTimeInterval=Select a portion of the graph before attempting to zoom to the graphed data.
+AnalyserVisualState.noThreadInfo=Thread info can not be retrieved\!
+GenericTraceGraph.setTimeScaleTo=Time scale set to: 
+GenericTable.pathOfBinary=Path of Binary
+GenericTable.threadProcess=Thread/Chunk
+GenericTable.sortByInPath=Sort by Binary Path, then Binary Name
+GenericTable.checkHighlighted=Check Highlighted Rows
+GenericTable.uncheckHighlighted=Uncheck Highlighted Rows
+GenericTable.changeThresholds=Change Threshold Limits...
+GenericTraceGraph.seconds=s
+GenericTable.function=Function
+GenericTable.samples=Samples
+GenericTable.inBinary=In Binary
+GenericTable.startAddr=Function Start
+GenericTable.stackHeap=Stack/Heap
+GenericTable.selectAll=Select All\tCtrl+A
+GenericTable.priority=Priority List
+GenericTable.sortByPath=Sort by Binary Path, then Binary Name
+GenericTable.checkAll=Check All Rows
+GenericTable.copyTable=Copy Table
+GenericTable.saveTable=Save Table...
+GenericTable.checked=Checked
+GenericTable.uncheckAll=Uncheck All Rows
+GenericTable.memoryTotal=Memory Total
+GenericTable.recolor1=Recolor Highlighted 
+GenericTable.recolor2=...
+GenericTraceGraph.debug=Debug: 
+GenericTable.thread=Thread
+GenericTable.binary=Binary
+GenericTable.chunks=Chunks
+GenericTable.show=
+GenericTable.load=% Load
+GenericTable.path=Path
+GenericTable.copy=Copy\tCtrl+C
+GenericTable.true=true
+GenericTable.space=\ 
+GenericTable.items=Items
+GenericTable.false=false
+GenericTable.sourcelookup=Open source for function
+SynchroniseDialog.ok=\ \ \ OK   
+SynchroniseDialog.cancel=Cancel
+SynchroniseDialog.value=Synchronise value (milliseconds)
+PICompositePanel.0=Zoom command failed to locate UI associated with the command
+PICompositePanel.1=Zoom command failed to locate UI associated with the command
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/ComNokiaCarbidePiHelpIDs.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi;
+
+public class ComNokiaCarbidePiHelpIDs {
+	private static final String PI_PLUGIN_ID = "com.nokia.carbide.cpp.pi"; //$NON-NLS-1$
+	
+	// see com.nokia.carbide.cpp.pi.help/html/context_help/org_eclipse_ui.xml
+	public static final String PI_SAVE_TABLE_WIZARD_PAGE = PI_PLUGIN_ID + "." + "save_table_page_context"; //$NON-NLS-1$ //$NON-NLS-2$
+	public static final String PI_SAVE_SAMPLES_WIZARD_PAGE = PI_PLUGIN_ID + "." + "save_address_samples_page_context"; //$NON-NLS-1$ //$NON-NLS-2$
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/PiPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.osgi.framework.BundleContext;
+
+import com.nokia.carbide.cpp.internal.pi.model.Binary;
+import com.nokia.carbide.cpp.internal.pi.model.CusSample;
+import com.nokia.carbide.cpp.internal.pi.model.Function;
+import com.nokia.carbide.cpp.internal.pi.model.GenericEvent;
+import com.nokia.carbide.cpp.internal.pi.model.GenericEventTrace;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSample;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampleWithFunctions;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTrace;
+import com.nokia.carbide.cpp.internal.pi.model.GenericSampledTraceWithFunctions;
+import com.nokia.carbide.cpp.internal.pi.model.GenericThread;
+import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IClassReplacer;
+import com.nokia.carbide.cpp.internal.pi.test.EnabledTrace;
+import com.nokia.carbide.cpp.internal.pi.test.PIAnalysisInfo;
+import com.nokia.carbide.cpp.internal.pi.test.BappeaAnalysisInfo;
+import com.nokia.carbide.cpp.internal.pi.test.TraceAdditionalInfo;
+import com.nokia.carbide.cpp.internal.pi.visual.AnalyserVisualState;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class PiPlugin extends AbstractPiPlugin {
+
+	//The shared instance.
+	private static PiPlugin plugin;
+	
+	private static void setPlugin(PiPlugin localPlugin) {
+		plugin = localPlugin;
+	}
+
+	/**
+	 * The constructor.
+	 */
+	public PiPlugin() {
+		setPlugin(this);
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		setPlugin(null);
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static PiPlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractPiPlugin.imageDescriptorFromPlugin("com.nokia.carbide.cpp.pi", path); //$NON-NLS-1$
+	}
+
+	public static Class getReplacedClass(String className) {
+        // handle legacy PI analysis file class names
+    	if (!className.startsWith("fi.")) //$NON-NLS-1$
+    		return null;
+    	
+    	if (className.equals("fi.vtt.bappea.model.GenericSample")) //$NON-NLS-1$
+    		return GenericSample.class;
+    	
+        if (className.equals("fi.vtt.bappea.model.GenericSampledTrace")) { //$NON-NLS-1$
+        	return GenericSampledTrace.class;
+        }
+        
+        if (className.equals("fi.vtt.bappea.model.GenericEventTrace")) { //$NON-NLS-1$
+        	return GenericEventTrace.class;
+        }
+        
+        if (className.equals("fi.vtt.bappea.model.GenericEvent")) { //$NON-NLS-1$
+        	return GenericEvent.class;
+        }
+        
+        if (className.equals("fi.vtt.bappea.model.GenericTrace")) { //$NON-NLS-1$
+        	return GenericTrace.class;
+        }
+        
+        if (className.equals("fi.vtt.bappea.model.GenericThread")) { //$NON-NLS-1$
+        	return GenericThread.class;
+        }
+        
+        if (className.equals("fi.vtt.bappea.model.GenericSampledTraceWithFunctions")) { //$NON-NLS-1$
+        	return GenericSampledTraceWithFunctions.class;
+        }
+        
+        if (className.equals("fi.vtt.bappea.model.GenericSampleWithFunctions")) { //$NON-NLS-1$
+        	return GenericSampleWithFunctions.class;
+        }
+        
+        if (className.equals("fi.vtt.bappea.model.Function")) { //$NON-NLS-1$
+        	return Function.class;
+        }
+        
+        if (className.equals("fi.vtt.bappea.model.Binary")) { //$NON-NLS-1$
+        	return Binary.class;
+        }
+        
+        if (className.equals("fi.vtt.bappea.model.CusSample")) { //$NON-NLS-1$
+        	return CusSample.class;
+        }
+
+        if (className.equals("fi.vtt.bappea.test.PIAnalysisInfo")) { //$NON-NLS-1$
+        	return PIAnalysisInfo.class;
+        }
+
+        if (className.equals("fi.vtt.bappea.test.EnabledTrace")) { //$NON-NLS-1$
+        	return EnabledTrace.class;
+        }
+
+        if (className.equals("fi.vtt.bappea.test.TraceAdditionalInfo")) { //$NON-NLS-1$
+        	return TraceAdditionalInfo.class;
+        }
+
+        if (className.equals("fi.vtt.bappea.test.BappeaAnalysisInfo")) { //$NON-NLS-1$
+        	return BappeaAnalysisInfo.class;
+        }
+
+        if (className.equals("fi.vtt.bappea.visual.AnalyserVisualState")) { //$NON-NLS-1$
+        	return AnalyserVisualState.class;
+        }
+
+		return null;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/PiReturnPlugin.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi;
+
+import com.nokia.carbide.cpp.internal.pi.interfaces.IReturnPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+
+
+
+public class PiReturnPlugin implements IReturnPlugin {
+	public AbstractPiPlugin getPlugin() {
+		return PiPlugin.getDefault();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/editors/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.editors;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.editors.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/editors/PIPageEditor.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,1000 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.editors;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+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.resource.ImageDescriptor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.IURIEditorInput;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.dialogs.SaveAsDialog;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.part.MultiPageEditorPart;
+import org.osgi.framework.Bundle;
+
+import com.nokia.carbide.cpp.internal.featureTracker.FeatureUseTrackerConsts;
+import com.nokia.carbide.cpp.internal.pi.actions.TimeSetDialog;
+import com.nokia.carbide.cpp.internal.pi.analyser.AnalyserDataProcessor;
+import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
+import com.nokia.carbide.cpp.internal.pi.analyser.PIChangeEvent;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileReader;
+import com.nokia.carbide.cpp.internal.pi.analyser.ProfileVisualiser;
+import com.nokia.carbide.cpp.internal.pi.interfaces.IToolBarActionListener;
+import com.nokia.carbide.cpp.internal.pi.manager.PluginInitialiser;
+import com.nokia.carbide.cpp.internal.pi.manager.PluginRegisterer;
+import com.nokia.carbide.cpp.internal.pi.model.GUITooltips;
+import com.nokia.carbide.cpp.internal.pi.model.TraceDataRepository;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener;
+import com.nokia.carbide.cpp.internal.pi.plugin.model.IFinalizeTrace;
+import com.nokia.carbide.cpp.pi.core.SessionPreferences;
+import com.nokia.carbide.cpp.pi.importer.SampleImporter;
+
+
+public class PIPageEditor extends MultiPageEditorPart implements IResourceChangeListener
+{
+	public static final String PI_ID = "com.nokia.carbide.cpp.pi"; //$NON-NLS-1$
+
+	// PI menu groups for adding plug-in specific actions/menu items
+	public static final String includeFilesGroup = "includeFile";	//$NON-NLS-1$
+	public static final String reportsGroup      = "reports";		//$NON-NLS-1$
+	public static final String viewOptionsGroup  = "viewOptions";	//$NON-NLS-1$
+	public static final String exportsGroup      = "exports";		//$NON-NLS-1$
+	public static final String additionsGroup    = "additions";		//$NON-NLS-1$
+	
+	// PI menu identifier
+	public static final String menuID = "com.nokia.carbide.cpp.pi.menuID"; //$NON-NLS-1$
+	
+	// indices of the three standard pages that have graphs
+	public static final int THREADS_PAGE   = 0;
+	public static final int BINARIES_PAGE  = 1;
+	public static final int FUNCTIONS_PAGE = 2;
+	public static final int NEXT_AVAILABLE_PAGE = -1;
+	
+	public static Font helvetica_8;
+	public static Font helvetica_9;
+	public static Font helvetica_10;
+	public static Font helvetica_12;
+	public static Font helvetica_14;
+	
+	// menu manager to which plugin's can add their actions
+	private static IMenuManager menuManager;
+	private static MenuManager currentManager;
+	private static MenuManager includeManager;
+
+	// info related to the current page editor and its pages
+	private static int          currentPageIndex;
+	private static PIPageEditor currentPageEditor;
+	private static int			currentUid;
+	
+	private static boolean openingFile = false; 
+	
+	private static boolean isCanceled = false;
+	private boolean isErrorPage = false;
+	
+	private static boolean startedPlugins = false;
+	
+	// actions available to all pages
+	
+	// toolbar actions for zooming
+	private static Action zoomInAction;
+	private static Action zoomOutAction;
+	private static Action zoomToSelectionAction;
+	private static Action zoomToTraceAction;
+	
+	// toolbar start and end times
+	private static Action selectTimeAction;
+	
+	// UID for this page
+	private int uid;
+
+	private double maxEndTime = Double.MAX_VALUE;
+	private double startTime = -1;
+	private double endTime   = -1;
+
+	private boolean tooltipsEnabled = true;
+	private int activePageIndex = -1;
+	
+	private static IActionBars actionBars;
+	
+	private boolean dirty = false;
+
+	private IPartListener partListener;
+
+	// full path name of the NPI file, so we can make all open copies of the file dirty
+	// or clean at the same time
+//	private String fullPath;
+
+	/**
+	 * Creates a multi-page editor.
+	 */
+	public PIPageEditor() {
+		super();
+		
+		// initialize the current page editor
+		setCurrentPageEditor(this);
+		ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
+	}
+	
+	protected static void createFonts(Display display) {
+		if (helvetica_8 == null) {
+			helvetica_8  = new Font(display, "Helvetica",  8, SWT.NORMAL); //$NON-NLS-1$
+			helvetica_9  = new Font(display, "Helvetica",  9, SWT.NORMAL); //$NON-NLS-1$
+			helvetica_10 = new Font(display, "Helvetica", 10, SWT.NORMAL); //$NON-NLS-1$
+			helvetica_12 = new Font(display, "Helvetica", 12, SWT.NORMAL); //$NON-NLS-1$
+			helvetica_14 = new Font(display, "Helvetica", 14, SWT.NORMAL); //$NON-NLS-1$
+		}
+	}
+	
+	protected void createBlankPage() {
+		Composite container = new Composite(getContainer(), SWT.NULL);
+		GridLayout layout = new GridLayout();
+		container.setLayout(layout);
+		layout.numColumns = 1;
+		layout.verticalSpacing = 9;
+		Label message = new Label(container, SWT.NONE);
+		//addPage(container);
+		setIsErrorPage(false);
+	}
+	
+	protected void createDummyErrorPage(String msg) {
+		Composite container = new Composite(getContainer(), SWT.NULL);
+		GridLayout layout = new GridLayout();
+		container.setLayout(layout);
+		layout.numColumns = 1;
+		layout.verticalSpacing = 9;
+		Label message = new Label(container, SWT.NONE);
+		message.setText(msg);
+		addPage(container);
+		setIsErrorPage(true);
+	}
+	
+	private void createErrorPageForException() {
+		IFileEditorInput editorInput = (IFileEditorInput)getEditorInput();
+		String message = Messages.getString("PIPageEditor.invalidPiFile") + editorInput.getName() + "\n" ; //$NON-NLS-1$ //$NON-NLS-2$
+		Throwable e = AnalyserDataProcessor.getInstance().getLastException();
+		if (e != null) {
+			if (e instanceof InvocationTargetException) {
+				if (e.getMessage() != null) {
+					message += e.getMessage() + "\n";	//$NON-NLS-1$
+				}
+				e = ((InvocationTargetException)e).getTargetException();
+			}
+			message += "\n" + Messages.getString("PIPageEditor.bugReport") + "\n\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			message += e.getClass().toString() + "\n"; //$NON-NLS-1$
+			if (e.getMessage() != null) {
+				message += e.getMessage() + "\n"; //$NON-NLS-1$
+			}
+			if (e.getStackTrace() != null) {
+				StackTraceElement [] wholeStack = e.getStackTrace();
+				for (StackTraceElement element: wholeStack) {
+					String className = element.getClassName();
+					if (className.toString().contains("fi.vtt.") || className.toString().contains("com.nokia.")) { //$NON-NLS-1$ //$NON-NLS-2$
+						message += Messages.getString("PIPageEditor.CarbideCPlusPlusSource") + element.getFileName() + ":" + element.getLineNumber() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+					}
+					else {
+						message += element.toString() + "\n"; //$NON-NLS-1$
+					}
+				}
+			}
+		}
+		createDummyErrorPage(message);
+
+	}
+
+	/**
+	 * Creates the pages of the multi-page editor.
+	 */
+	protected void createPages() {
+		IURIEditorInput editorInput = (IURIEditorInput)getEditorInput();
+		
+		// Kludge because of the way Eclipse opens files: disable ability of page.addFocusListener().focusGained() to change
+		// current editor and tab info
+		openingFile = true;
+
+		// make sure we can open an input stream to the trace file
+		
+		InputStream inputStream;
+		try {
+			inputStream = editorInput.getURI().toURL().openStream();
+			inputStream.read();
+			inputStream.close();
+		} catch (MalformedURLException e) {
+			System.out.println(Messages.getString("PIPageEditor.MalformedURL1") + editorInput.getURI().toString());  //$NON-NLS-1$
+			createDummyErrorPage(Messages.getString("PIPageEditor.MalformedURL2") + editorInput.getURI().toString());  //$NON-NLS-1$
+			openingFile = false;
+			return;
+			
+		} catch (IOException e) {
+			System.out.println(Messages.getString("PIPageEditor.cannotReadFile") + editorInput.getName()); //$NON-NLS-1$
+			// something is wrong, print a dummy page
+			createDummyErrorPage(Messages.getString("PIPageEditor.cannotReadFile") + editorInput.getName()); //$NON-NLS-1$
+			openingFile = false;
+			return;
+		}
+		
+		try {
+			if (SampleImporter.getInstance().isStrippingTimeStamp()) {	
+				uid = NpiInstanceRepository.getInstance().register(getContainer());
+				AnalyserDataProcessor.getInstance().importForStrippingTimeStamp(getContainer());
+				openingFile = false;
+				return;
+			}
+			
+			if (AnalyserDataProcessor.getInstance().getState() == AnalyserDataProcessor.STATE_IMPORTING) {
+				uid = NpiInstanceRepository.getInstance().activeUid();
+				NpiInstanceRepository.getInstance().setParentComposite(uid, getContainer());
+			} else {
+				// register this editor and ask repository to prepare per instance data
+				uid = NpiInstanceRepository.getInstance().register(getContainer());
+				NpiInstanceRepository.getInstance().switchActiveUid(uid);
+			}
+			AnalyserDataProcessor.getInstance().openNpiForPIPageEditor(editorInput.getURI(), getContainer(), uid);
+			
+			if (AnalyserDataProcessor.getInstance().getState() != AnalyserDataProcessor.STATE_OK) {
+				openingFile = false;
+				
+				// user may have canceled, print a dummy page
+				// if we deleted the importer file, then don't create a dummy page
+				if (AnalyserDataProcessor.getInstance().getState() == AnalyserDataProcessor.STATE_CANCELED) {
+					createDummyErrorPage(Messages.getString("PIPageEditor.userCancelled") + editorInput.getName()); //$NON-NLS-1$
+				} else {
+					createErrorPageForException();
+				}
+
+				return;
+			}
+		} catch (Exception ex) {
+			openingFile = false;
+					
+			// user may have canceled, print a dummy page
+			// if we deleted the importer file, then don't create a dummy page
+			if (AnalyserDataProcessor.getInstance().getState() == AnalyserDataProcessor.STATE_CANCELED) {
+				createDummyErrorPage(Messages.getString("PIPageEditor.userCancelled") + editorInput.getName()); //$NON-NLS-1$
+			} else {
+				createErrorPageForException();
+			}
+
+			return;	
+		}
+		
+		// add to the editor tab all pages create by AnalyseTab 
+	  	ArrayList<ProfileVisualiser> pages = NpiInstanceRepository.getInstance().activeUidGetProfilePages();
+	  	
+	  	int index = -1;
+	  	for (Iterator<ProfileVisualiser> i = pages.iterator();i.hasNext();) {
+	  		ProfileVisualiser myPv = i.next();
+	  		final Composite page = myPv.getContentPane();
+	  		
+	  		index = addPage(page);
+	  		setPageText(index, myPv.getPageName());
+	  		
+	  		// set the composite page's data to its page number
+	  		page.setData("pageIndex", new Integer(index)); //$NON-NLS-1$
+	  		page.setData("pageEditor", this); //$NON-NLS-1$
+	  		page.setData("pageUID", new Integer(uid)); //$NON-NLS-1$
+
+	  		page.addFocusListener(new FocusAdapter() {
+
+				public void focusGained(FocusEvent e) {
+					Object data;
+					int          nextPageIndex;
+					PIPageEditor nextPageEditor;
+					Integer			nextUIDInteger;
+					
+					data = page.getData("pageIndex"); //$NON-NLS-1$
+					if ((data != null) && (data instanceof Integer))
+						nextPageIndex = ((Integer) data).intValue();
+					else
+						nextPageIndex = -1;
+					
+					data = page.getData("pageEditor"); //$NON-NLS-1$
+					if ((data != null) && (data instanceof PIPageEditor))
+						nextPageEditor = (PIPageEditor) data;
+					else
+						nextPageEditor = null;
+					
+					data = page.getData("pageUID"); //$NON-NLS-1$
+					if ((data != null) && (data instanceof Integer))
+						nextUIDInteger = (Integer) data;
+					else
+						nextUIDInteger = null;
+					
+					// add the new tab's menu items
+					if ((nextUIDInteger != null) && (nextUIDInteger != NpiInstanceRepository.getInstance().activeUid())) {
+						/* Note: some items are tab-specific and some are page-specific
+						 *       (check for the current tab when they are called)
+						 */
+						addTabMenuItems(nextUIDInteger.intValue());
+					}
+					
+					// show the new page editor's start and end times
+					if ((nextPageEditor != null) && (nextPageEditor != currentPageEditor)) {
+						double start = nextPageEditor.getStartTime();
+						double end   = nextPageEditor.getEndTime();
+						PIPageEditor.setTime(start, end);
+					}
+
+					if (!PIPageEditor.isOpeningFile()) {
+						setCurrentPageIndex(nextPageIndex);
+						setCurrentPageEditor(nextPageEditor);
+						setCurrentUid(nextUIDInteger);
+					}
+				}
+	  		});
+	  	}
+	  	
+	  	if (!pages.isEmpty()) {
+	  		currentPageIndex = 0;
+	  		setActivePage(0);
+	  	} else {
+			new Composite(getContainer(), SWT.NONE);
+	  	}
+	  	currentPageEditor = this;
+		openingFile = false;
+	}
+
+	public static int currentPageIndex() {
+		return currentPageIndex;
+	}
+	
+	public static PIPageEditor currentPageEditor() {
+		return currentPageEditor;
+	}
+	
+	public static boolean isOpeningFile() {
+		return openingFile;
+	}
+	
+	public static MenuManager currentMenuManager() {
+		return currentManager;
+	}
+	
+	public static void startPlugins() {
+		startedPlugins = true;
+	}
+	
+	public static boolean arePluginsStarted() {
+		return startedPlugins;
+	}
+
+	// set the overall menu manager for PI
+	public static void setPIMenuManager(MenuManager piManager) {
+		if (piManager == null)
+			return;
+		
+		currentManager = piManager;
+		
+		// Force an update because Eclipse hides empty menus.
+		currentManager.addMenuListener(new IMenuListener() {
+			 public void menuAboutToShow(IMenuManager menuManager) {
+				 menuManager.updateAll(true);
+			 }
+		 });
+
+		initialiseMenuManager();
+	}
+
+	// start with a fresh overall menu manager, to which you add contribution items
+	public static void initialiseMenuManager() {
+		if (currentManager == null)
+			return;
+		
+		// This currentManager can only be modified in UI thread if the menu ever gets called by user
+		Display.getDefault().syncExec( new Runnable() {
+			public void run() {
+				currentManager.removeAll();
+				
+				/* 
+				 * A typical menu hierarchy might look like:
+				 * 
+				 * ... PI ...
+				 * 		Include Other Profile File ->
+				 * 		-----------------------------
+				 * 		Profile File Summary
+				 *		Profile File Report
+				 *		-----------------------------
+				 *		CPU Load Graph			   ->
+				 *		-----------------------------
+				 */
+				currentManager.add(new Separator(PIPageEditor.includeFilesGroup));
+				currentManager.add(new Separator(PIPageEditor.reportsGroup));
+				currentManager.add(new Separator(PIPageEditor.viewOptionsGroup));
+				currentManager.add(new Separator(PIPageEditor.exportsGroup));
+				currentManager.add(new Separator(PIPageEditor.additionsGroup));
+
+			}			
+		});
+	}
+
+	public static void addExportAction(IAction action) {
+		if (action == null)
+			return;
+		
+		currentManager.appendToGroup(PIPageEditor.exportsGroup, action);
+	}
+
+	public static void addIncludeAction(IAction action) {
+		if (action == null)
+			return;
+		
+		if (currentManager.find(menuID + Messages.getString("PIPageEditor.includeActionEnding")) == null) { //$NON-NLS-1$
+			includeManager = new MenuManager(Messages.getString("PIPageEditor.includeOtherFile"), menuID + Messages.getString("PIPageEditor.includeActionEnding")); //$NON-NLS-1$ //$NON-NLS-2$
+			currentManager.add(includeManager);
+		}
+			
+		includeManager.add(action);
+	}
+
+	public static void addReportAction(IAction action) {
+		if (action == null)
+			return;
+		
+		currentManager.appendToGroup(PIPageEditor.reportsGroup, action);
+	}
+
+	public static void addReportManager(IMenuManager menuManager) {
+		if (menuManager == null)
+			return;
+		
+		currentManager.appendToGroup(PIPageEditor.reportsGroup, menuManager);
+	}
+
+	public static void addViewOptionManager(IMenuManager menuManager) {
+		if (menuManager == null)
+			return;
+		
+		if (menuManager == currentManager)
+			return;
+		
+		currentManager.appendToGroup(PIPageEditor.viewOptionsGroup, menuManager);
+	}
+
+	/**
+	 * The <code>MultiPageEditorPart</code> implementation of this 
+	 * <code>IWorkbenchPart</code> method disposes all nested editors.
+	 * Subclasses may extend.
+	 */
+	public void dispose() {
+		getSite().getPage().removePartListener(partListener);
+		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+		ArrayList<AbstractPiPlugin> plugins = NpiInstanceRepository.getInstance().getPlugins(uid);
+		for (AbstractPiPlugin plugin : plugins) {
+			if (plugin instanceof IFinalizeTrace) {
+				((IFinalizeTrace)plugin).runOnDispose();
+			}
+		}
+
+		NpiInstanceRepository.getInstance().unregister(uid);
+		if (NpiInstanceRepository.getInstance().size() == 0) {
+			// free up the current file's items
+			setCurrentPageEditor(null);
+			setCurrentUid(0);
+			if (NpiInstanceRepository.getInstance().activeUid() == uid) {
+				NpiInstanceRepository.getInstance().switchActiveUid(NpiInstanceRepository.DISPOSED_UID);
+			}
+			TraceDataRepository.getInstance().removeAll();
+			PluginInitialiser.removeAllTraceInstances();
+
+			// stop using the feature
+			com.nokia.carbide.cpp.internal.featureTracker.FeatureUseTrackerPlugin.getFeatureUseProxy().stopUsingFeature(FeatureUseTrackerConsts.CARBIDE_PROFILER);
+		}
+		super.dispose();
+		System.gc();
+	}
+
+	/**
+	 * Saves the multi-page editor's document.
+	 */
+	public void doSave(IProgressMonitor monitor) {
+		final IFileEditorInput newInput= new FileEditorInput(((IFileEditorInput)getEditorInput()).getFile());
+		saveDocument(newInput);
+	}
+	
+	/**
+	 * Saves the multi-page editor's document as another file.
+	 * Also updates the text for page 0's tab, and updates this multi-page editor's input
+	 * to correspond to the nested editor's.
+	 */
+	public void doSaveAs() {
+		SaveAsDialog dialog = new SaveAsDialog(getSite().getShell());
+		
+		dialog.open();
+		IPath filePath = dialog.getResult();
+		
+		if (filePath == null)
+			return;
+		if (filePath.getFileExtension() == null || filePath.getFileExtension().equals("npi") == false) { //$NON-NLS-1$
+			MessageBox errorMessage = new MessageBox(getSite().getShell(), SWT.PRIMARY_MODAL | SWT.ICON_ERROR);
+			errorMessage.setText(Messages.getString("PIPageEditor.error")); //$NON-NLS-1$
+			errorMessage.setMessage(Messages.getString("PIPageEditor.mustBeNpi")); //$NON-NLS-1$
+			errorMessage.open();
+			return;
+		}
+		
+		IWorkspaceRoot workspaceRoot= ResourcesPlugin.getWorkspace().getRoot();
+		IFile file= workspaceRoot.getFile(filePath);
+		final IFileEditorInput newInput= new FileEditorInput(file);
+
+		saveDocument(newInput);
+		
+		dialog.close();
+	}
+	
+	public boolean isSaveAsAllowed() {
+		return true;
+	}
+	
+	public boolean isDirty() {
+		return dirty;
+	}
+	
+	public boolean isSaveOnCloseNeeded() {
+		return true;
+	}
+	
+	public void setDirty() {
+		dirty = true;
+		this.firePropertyChange(PROP_DIRTY);
+		
+//		for (int i = 0; i < pageEditorList.size(); i++) {
+//			if (   (pageEditorList.get(i) != this)
+//				&& (pageEditorList.get(i).getFullPath().equals(this.getFullPath())))
+//				pageEditorList.get(i).setDirtyOnce();
+//		}
+	}
+	
+	public void setDirtyOnce() {
+		dirty = true;
+		this.firePropertyChange(PROP_DIRTY);
+	}
+
+	public void resetDirty() {
+		dirty = false;
+		this.firePropertyChange(PROP_DIRTY);
+		
+//		for (int i = 0; i < pageEditorList.size(); i++) {
+//			if (   (pageEditorList.get(i) != this)
+//				&& (pageEditorList.get(i).getFullPath().equals(this.getFullPath())))
+//				pageEditorList.get(i).resetDirtyOnce();
+//		}
+	}
+
+	public void resetDirtyOnce() {
+		dirty = false;
+		this.firePropertyChange(PROP_DIRTY);
+	}
+	
+	// Try to get close to saveDocument in IDocumentProvider in case we do rewrite
+	// see JDT CompilationUnitEditor.java for reference
+	public void saveDocument(IFileEditorInput newInput) {
+		// this block would be getDocumentProvider().saveDocument() in rewrite
+		IFile newFile = newInput.getFile();
+//		IFile oldFile = ((IFileEditorInput)getEditorInput()).getFile();
+		
+		
+		try {
+			// the Dialog already asked the user if they want to overwrite
+			// grant them the wish and remove the file
+			if(!newFile.exists()) {
+				newFile.create(new ByteArrayInputStream("".getBytes()), false, null);	//$NON-NLS-1$
+				newFile.refreshLocal(0, null);
+			}
+			AnalyserDataProcessor.getInstance().saveAnalysis(newFile.getLocation().toString(), uid);			
+			newFile.refreshLocal(0, null);
+			setInput(newInput);
+			setPartName(newInput.getName());
+			resetDirty();
+		} catch (CoreException e) {
+			e.printStackTrace();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}	
+	}
+	
+	public void gotoMarker(IMarker marker) {
+		setActivePage(0);
+		IDE.gotoMarker(getEditor(0), marker);
+	}
+	
+	/**
+	 * The <code>MultiPageEditorExample</code> implementation of this method
+	 * checks that the input is an instance of <code>IFileEditorInput</code>.
+	 */
+	public void init(IEditorSite site, IEditorInput editorInput)
+		throws PartInitException {
+		if (!(editorInput instanceof IURIEditorInput))
+			throw new PartInitException(Messages.getString("PIPageEditor.mustBeIURIEditorInput")); //$NON-NLS-1$
+
+		// store the full path
+//		this.fullPath = ((FileEditorInput)editorInput).getPath().toFile().getAbsolutePath();
+
+		super.init(site, editorInput);
+
+		// now the site is initialized, so start using the feature
+		com.nokia.carbide.cpp.internal.featureTracker.FeatureUseTrackerPlugin.getFeatureUseProxy().startUsingFeature(FeatureUseTrackerConsts.CARBIDE_PROFILER);
+
+		// allocate a few fonts
+		createFonts(getEditorSite().getShell().getDisplay());
+		site.getPage().addPartListener(partListener = new IPartListener(){
+			
+			private void setMenus(IWorkbenchPart part) {
+				if (!(part instanceof PIPageEditor) || isErrorPage)
+					return;
+				
+				PIPageEditor editor = (PIPageEditor) part;
+				currentPageEditor.setActiveActions(false);
+				currentPageEditor = editor;
+				
+				setTime(editor.getStartTime(),editor.getEndTime());
+				NpiInstanceRepository.getInstance().switchActiveUid(currentPageEditor().uid);
+				addTabMenuItems(currentPageEditor().uid);
+				currentPageEditor.setActiveActions(true);
+			}
+
+			public void partActivated(IWorkbenchPart part) {
+				setMenus(part);
+			}
+
+			public void partBroughtToTop(IWorkbenchPart part) {
+				setMenus(part);
+			}
+
+			public void partClosed(IWorkbenchPart part) {
+			}
+
+			public void partDeactivated(IWorkbenchPart part) {
+			}
+
+			public void partOpened(IWorkbenchPart part) {
+			}
+		});
+
+		setSite(site);
+		setInput(editorInput);
+		this.setPartName(editorInput.getName());
+
+		// set up registry of PI plugins
+		PluginRegisterer.registerAllPlugins();
+	}
+	
+//	public String getFullPath() {
+//		return this.fullPath;
+//	}
+
+	public static void setTime(double start, double end) {
+		// set the visible time
+//		PIPageEditorContributor.getTimeSet().setTime(start, end);
+
+		// set the local copy of the time
+		if (currentPageEditor != null)
+			currentPageEditor.setLocalTime(start, end);
+	}
+
+	public void setLocalTime(double start, double end) {
+		this.startTime = start;
+		this.endTime   = end;
+	}
+
+	protected void setLocalStartTime(double start) {
+		this.startTime = start;
+	}
+
+	protected void setLocalEndTime(double end) {
+		this.endTime   = end;
+	}
+	
+	public void setMaxEndTime(double maxEndTime) {
+		this.maxEndTime = maxEndTime;
+	}
+
+	public double getStartTime() {
+		return startTime;
+	}
+
+	public double getEndTime() {
+		return endTime;
+	}
+
+	public double getMaxEndTime() {
+		return maxEndTime;
+	}
+	
+	public static void createActions() {
+		URL url;
+		ImageDescriptor createFromURL;
+		
+		Bundle piBundle = Platform.getBundle("com.nokia.carbide.cpp.pi"); //$NON-NLS-1$
+		if (piBundle == null)
+			return;
+		
+		zoomInAction = new Action(Messages.getString("PIPageEditor.zoomIn")) { //$NON-NLS-1$
+			public void run() {
+				PIChangeEvent.action("-"); //$NON-NLS-1$
+			}
+		};
+		zoomInAction.setToolTipText(Messages.getString("PIPageEditor.zoomIn")); //$NON-NLS-1$
+		url = Platform.find(piBundle, new Path(Messages.getString("PIPageEditorContributor.zoomInIcon"))); //$NON-NLS-1$
+		if (url != null) {
+			createFromURL = ImageDescriptor.createFromURL(url);
+			zoomInAction.setImageDescriptor(createFromURL);
+		}
+
+		zoomOutAction = new Action(Messages.getString("PIPageEditor.zoomOut")) { //$NON-NLS-1$
+			public void run() {
+				PIChangeEvent.action("+"); //$NON-NLS-1$
+			}
+		};
+		zoomOutAction.setToolTipText(Messages.getString("PIPageEditor.zoomOut"));  //$NON-NLS-1$
+		url = Platform.find(piBundle, new Path(Messages.getString("PIPageEditor.PIPageEditorContributor.zoomOutIcon"))); //$NON-NLS-1$
+		if (url != null) {
+			createFromURL = ImageDescriptor.createFromURL(url);
+			zoomOutAction.setImageDescriptor(createFromURL);
+		}
+
+		zoomToTraceAction = new Action(Messages.getString("PIPageEditor.showEntireGraph")) { //$NON-NLS-1$
+			public void run() {
+				PIChangeEvent.action("++"); //$NON-NLS-1$
+			}
+		};
+		zoomToTraceAction.setToolTipText(Messages.getString("PIPageEditor.showEntireGraph"));  //$NON-NLS-1$
+		url = Platform.find(piBundle, new Path(Messages.getString("PIPageEditor.PIPageEditorContributor.showEntireGraphIcon"))); //$NON-NLS-1$
+		if (url != null) {
+			createFromURL = ImageDescriptor.createFromURL(url);
+			zoomToTraceAction.setImageDescriptor(createFromURL);
+		}
+
+		zoomToSelectionAction = new Action(Messages.getString("PIPageEditor.zoomToInterval")) { //$NON-NLS-1$
+			public void run() {
+				PIChangeEvent.action("--"); //$NON-NLS-1$
+			}
+		};
+		zoomToSelectionAction.setToolTipText(Messages.getString("PIPageEditor.zoomToInterval"));  //$NON-NLS-1$
+		url = Platform.find(piBundle, new Path(Messages.getString("PIPageEditor.PIPageEditorContributor.ZoomToIntervalIcon"))); //$NON-NLS-1$
+		if (url != null) {
+			createFromURL = ImageDescriptor.createFromURL(url);
+			zoomToSelectionAction.setImageDescriptor(createFromURL);
+		}
+
+		selectTimeAction = new Action(Messages.getString("PIPageEditor.selectInterval")) { //$NON-NLS-1$
+			public void run() {
+				// remember the old time interval
+				double startTime = PIPageEditor.currentPageEditor().getStartTime();
+				double endTime   = PIPageEditor.currentPageEditor().getEndTime();
+				
+				// get the new time interval
+				new TimeSetDialog(
+						PIPageEditor.currentPageEditor.getSite().getShell().getDisplay(),
+						startTime, endTime);
+				
+				if (   (startTime == PIPageEditor.currentPageEditor().getStartTime())
+					&& (endTime   == PIPageEditor.currentPageEditor().getEndTime()))
+					return;
+				
+				// propagate the new time interval
+				PIChangeEvent.action("changeInterval"); //$NON-NLS-1$
+				
+				// after the graphs have been updated, notify plugins that might have tables but no graphs
+        		Enumeration enu = PluginInitialiser.getPluginInstances(
+        									"com.nokia.carbide.cpp.internal.pi.plugin.model.IEventListener"); //$NON-NLS-1$
+        		if (enu != null) {
+        			Event event = new Event();
+        			Double[] times = new Double[2];
+           			times[0] = PIPageEditor.currentPageEditor().getStartTime();
+           			times[1] = PIPageEditor.currentPageEditor().getEndTime();
+           			event.data = times;
+        			
+            		while (enu.hasMoreElements())
+            		{
+            			IEventListener plugin = (IEventListener)enu.nextElement();
+            			plugin.receiveEvent("changeInterval", event); //$NON-NLS-1$
+            		}
+        		}
+			}
+		};
+		selectTimeAction.setToolTipText(Messages.getString("PIPageEditor.selectInterval"));  //$NON-NLS-1$
+		url = Platform.find(piBundle, new Path(Messages.getString("PIPageEditor.PIPageEditorContributor.selectIntervalIcon"))); //$NON-NLS-1$
+		if (url != null) {
+			createFromURL = ImageDescriptor.createFromURL(url);
+			selectTimeAction.setImageDescriptor(createFromURL);
+		}
+	}
+
+	
+	public static Action getZoomInAction() {
+		return zoomInAction;
+	}
+	
+	public static Action getZoomOutAction() {
+		return zoomOutAction;
+	}
+	
+	public static Action getZoomToSelectionAction() {
+		return zoomToSelectionAction;
+	}
+	
+	public static Action getZoomToTraceAction() {
+		return zoomToTraceAction;
+	}
+
+	public static Action getSelectTimeAction() {
+		return selectTimeAction;
+	}
+
+	/**
+	 * Closes all project files on project close.
+	 */
+	public void resourceChanged(final IResourceChangeEvent event){
+		IResourceDelta delta = event.getDelta();
+
+		if (delta == null)
+			return;
+
+		if (delta.getKind() == IResourceDelta.CHANGED) {
+			IPath editorPath = ((IFileEditorInput)getEditorInput()).getFile().getFullPath();
+			// see if current change event is relevant to this Editor
+			delta = delta.findMember(editorPath);
+			if (delta != null) {
+				int deltaKind = delta.getKind();
+				switch(deltaKind) {
+				case IResourceDelta.REMOVED:
+				case IResourceDelta.REMOVED_PHANTOM:
+					Display.getDefault().syncExec(new Runnable() {
+						public void run() {
+								PIPageEditor.this.getSite().getPage().closeEditor(PIPageEditor.this, false);
+						}
+					});
+					break;
+				}
+			}
+		}
+	}
+	
+	protected void pageChange(int newPageIndex) {
+		// on a page change, set the current page's leaving actions and the new pages' entering action
+		if (this.activePageIndex != -1)
+			setActions(false, this.activePageIndex);
+		super.pageChange(newPageIndex);
+		setCurrentPageIndex(newPageIndex);
+		setActions(true, newPageIndex);
+		this.activePageIndex = newPageIndex;
+	}
+	
+	// set the actions on entering or leaving the current page
+	public void setActiveActions(boolean entering) {
+		if (this.activePageIndex != -1)
+			setActions(entering, this.activePageIndex);
+	}
+	
+	private void setActions(boolean entering, int pageIndex) {
+		Enumeration enu;
+		AbstractPiPlugin plugin;
+
+		enu = PluginInitialiser.getPluginInstances(uid, "com.nokia.carbide.cpp.internal.pi.interfaces.IToolBarActionListener"); //$NON-NLS-1$
+		while (enu.hasMoreElements())
+		{
+			// can only set actions if the plugin is associated with this tab
+			plugin = (AbstractPiPlugin)enu.nextElement();
+			if (   (plugin instanceof IToolBarActionListener)
+				&& (NpiInstanceRepository.getInstance().getPlugins(uid) != null)
+				&& (NpiInstanceRepository.getInstance().getPlugins(uid).indexOf(plugin) >= 0)) {
+				((IToolBarActionListener)plugin).setActions(entering, pageIndex);
+			}
+		}
+	}
+	
+	public int getCurrentPage() {
+		return getActivePage();
+	}
+	
+	// whether tooltips are enabled for this file
+	public boolean getTooltipsEnabled() {
+		return this.tooltipsEnabled;
+	}
+	
+	public void setTooltipsEnabled(boolean tooltipsEnabled) {
+		SessionPreferences.getInstance().setToolTipsEnabled(tooltipsEnabled);
+    	GUITooltips.setTooltipsOn(tooltipsEnabled);
+		this.tooltipsEnabled = tooltipsEnabled;
+	}
+	
+	// menu bar changes let tables and graphs change IDE menu items when focus changes
+	public static void setMenuManager(IMenuManager menuManager) {
+		PIPageEditor.menuManager = menuManager;
+	}
+	
+	public static IMenuManager getMenuManager() {
+		return PIPageEditor.menuManager;
+	}
+	
+	// action bar changes let tables and graphs change IDE menu items when focus changes
+	public static void setActionBars(IActionBars actionBars) {
+		PIPageEditor.actionBars = actionBars;
+	}
+	
+	public static IActionBars getActionBars() {
+		return PIPageEditor.actionBars;
+	}
+
+	private static void setCurrentPageIndex(int pageIndex)
+	{
+		currentPageIndex = pageIndex;
+	}
+
+	private static void setCurrentPageEditor(PIPageEditor pageEditor)
+	{
+		currentPageEditor = pageEditor;
+	}
+	
+	private static void setCurrentUid(int uid)
+	{
+		currentUid = uid;
+	}
+
+	private void setIsErrorPage(boolean isIt)
+	{
+		isErrorPage = isIt;
+	}
+	
+	private static void addTabMenuItems(int uid) {
+		ProfileReader.getInstance().setTraceMenus(NpiInstanceRepository.getInstance().getPlugins(uid), uid);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/editors/PIPageEditorContributor.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.editors;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
+
+/**
+ * Manages the installation/deinstallation of global actions for multi-page editors.
+ * Responsible for the redirection of global actions to the active editor.
+ * Multi-page contributor replaces the contributors for the individual editors in the multi-page editor.
+ */
+public class PIPageEditorContributor extends MultiPageEditorActionBarContributor {
+	
+	private MenuManager piManager;
+
+	/**
+	 * Creates a multi-page contributor.
+	 */
+	public PIPageEditorContributor() {
+		super();
+		PIPageEditor.createActions();
+	}
+
+	public void setActivePage(IEditorPart part) {
+	}
+
+	public void contributeToMenu(IMenuManager manager) {
+		// record the ActionBars object
+		PIPageEditor.setMenuManager(manager);
+
+		// record the ActionBars object
+		if (getActionBars() != null)
+			PIPageEditor.setActionBars(getActionBars());
+
+		// create a top-level menu manager for PIPageEditor
+		if (piManager != null) {
+			piManager.dispose();
+		}
+		piManager = new MenuManager(Messages.getString("PIPageEditorContributor.PerformanceInvestigator"), PIPageEditor.menuID); //$NON-NLS-1$
+		manager.prependToGroup(IWorkbenchActionConstants.MB_ADDITIONS, piManager);
+		PIPageEditor.setPIMenuManager(piManager);
+	}
+	
+	public void contributeToToolBar(IToolBarManager manager) {
+		// add the created actions to the tool bar
+		manager.add(new Separator("piEditorGroup1")); //$NON-NLS-1$
+		manager.add(PIPageEditor.getSelectTimeAction());
+		manager.add(new Separator("piEditorGroup2")); //$NON-NLS-1$
+		manager.add(PIPageEditor.getZoomInAction());
+		manager.add(PIPageEditor.getZoomOutAction());
+		manager.add(PIPageEditor.getZoomToSelectionAction());
+		manager.add(PIPageEditor.getZoomToTraceAction());
+	}
+	
+	public void init(IActionBars bars) {
+		super.init(bars);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/editors/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,23 @@
+PIPageEditor.bugReport=Call stack dump for bug report:
+PIPageEditor.CarbideCPlusPlusSource=(Carbide.c++ source) 
+PIPageEditor.cannotReadFile=Cannot read file: 
+PIPageEditor.zoomToInterval=Zoom to Selected Time Interval
+PIPageEditor.selectInterval=Select Time Interval
+PIPageEditor.showEntireGraph=Show Entire Graph
+PIPageEditor.zoomIn=Zoom In
+PIPageEditor.zoomOut=Zoom Out
+PIPageEditor.includeOtherFile=Include other Profiler file 
+PIPageEditor.mustBeNpi=File extension must be "npi"
+PIPageEditorContributor.zoomInIcon=/icons/zoom_in.png
+PIPageEditor.mustBeIURIEditorInput=Invalid input: must be IURIEditorInput
+PIPageEditor.includeActionEnding=.includeID
+PIPageEditorContributor.PerformanceInvestigator=Investigator
+PIPageEditor.PIPageEditorContributor.zoomOutIcon=/icons/zoom_out.png
+PIPageEditor.PIPageEditorContributor.showEntireGraphIcon=/icons/show_entire_graph.png
+PIPageEditor.PIPageEditorContributor.ZoomToIntervalIcon=/icons/zoom_to_time_interval.png
+PIPageEditor.PIPageEditorContributor.selectIntervalIcon=/icons/Set_current_time_interval.png
+PIPageEditor.error=error
+PIPageEditor.userCancelled=User cancelled opening 
+PIPageEditor.invalidPiFile=Invalid profiler file 
+PIPageEditor.MalformedURL1=Cannot form URL from URI: 
+PIPageEditor.MalformedURL2=Cannot form URL from URI: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/importer/Messages.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.importer;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+	private static final String BUNDLE_NAME = "com.nokia.carbide.cpp.pi.importer.messages"; //$NON-NLS-1$
+
+	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+			.getBundle(BUNDLE_NAME);
+
+	private Messages() {
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/importer/SampleImporter.java	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "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.carbide.cpp.pi.importer;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+
+import com.nokia.carbide.cpp.internal.pi.analyser.AnalyserDataProcessor;
+import com.nokia.carbide.cpp.pi.util.GeneralMessages;
+
+
+public class SampleImporter {
+	private static SampleImporter instance;
+	
+	// location of input .dat file
+	private String datFileName;
+	// location of output project
+	private String outputContainerName;
+	// location of output .pi file
+	private String piFileName;
+	// workspace resource .npi file
+	private IFile piFile;
+	// PKG file and their SDK_ID or EPOCROOT
+	public static class PkgObyFile {
+		public String fileAbsolutePath;
+		public String epocRoot;
+		PkgObyFile(String epocRoot, String fileAbsolutePath) {
+			this.fileAbsolutePath = fileAbsolutePath;
+			this.epocRoot = epocRoot;
+		}
+	}
+	private ArrayList<PkgObyFile> pkgObyFileList = new ArrayList<PkgObyFile>();
+	
+	private boolean importStripTimeStamp = false;	// importer is just doing dummy import for stripping time stamp for diffing
+	
+	// ROM related stuff
+	private String romEpocroot;
+	private String romSymbolFile;
+	private String romObyFile;
+	private ArrayList<String> rofsSymbolFileList = new ArrayList<String>();
+	private ArrayList<String> rofsObyFileList = new ArrayList<String>();
+	
+	// Custom sample
+	private String custAbsolutePath;
+	private boolean custIsValueBased;
+	private String custDelimitor;
+	
+	// Bup sample
+	private String bupMapProfileId;
+	private String bupMapSymbianSDKId;
+	private boolean bupMapIsBuiltIn;
+	private boolean bupMapIsWorkspace;
+	
+	private SampleImporter() {
+		clear();
+		// singleton
+	}
+	
+	public static SampleImporter getInstance() {
+		if (instance == null) {
+			instance = new SampleImporter();
+		}
+		
+		return instance;
+	}
+	
+	public Object clone() throws CloneNotSupportedException {
+		throw new CloneNotSupportedException();
+	}
+
+	public String getDatFileName () {
+		return datFileName;
+	}
+
+	public void setDatFileName (String file) {
+		datFileName = file;
+	}
+
+	public void clearDatFileName () {
+		setDatFileName(""); //$NON-NLS-1$
+	}
+
+	public String getProjectName () {
+		return outputContainerName;
+	}
+
+	public void setProjectName (String file) {
+		outputContainerName = file;
+	}
+
+	public void clearProjectName () {
+		setProjectName(""); //$NON-NLS-1$
+	}
+	
+	public String getPiFileName () {
+		return piFileName;
+	}
+
+	public void setPiFileName (String file) {
+		piFileName = file;
+	}
+	
+	public void clearPiFileName () {
+		setPiFileName(""); //$NON-NLS-1$
+	}
+	
+	public IFile getPiFile() {
+		return this.piFile;
+	}
+	
+	public void setPiFile(IFile piFile) {
+		this.piFile = piFile;
+	}
+	
+	public void setStripTimeStampActive () {
+		this.importStripTimeStamp = true;
+	}
+	
+	public void setStripTimeStampDone() {
+		this.importStripTimeStamp = false;
+	}
+	
+	public boolean isStrippingTimeStamp() {
+		return this.importStripTimeStamp;
+	}
+
+	public PkgObyFile[] getPkgObyFilesList () {
+		ArrayList<PkgObyFile> result = new ArrayList<PkgObyFile>();
+		// round up all ROM OBY and app PKG
+		if (romObyFile != null && romObyFile.length() > 0) {
+			PkgObyFile romObyEntry = new PkgObyFile(romEpocroot, romObyFile);
+			result.add(romObyEntry);
+		}
+		for (String rofsObyFile : rofsObyFileList) {
+			PkgObyFile rofsObyEntry = new PkgObyFile(romEpocroot, rofsObyFile);
+			result.add(rofsObyEntry);
+		}
+		result.addAll(pkgObyFileList);
+		return result.toArray(new PkgObyFile[result.size()]);
+	}
+
+	public void addPkgObyFile (String epocroot, String filePath) {
+		pkgObyFileList.add(new PkgObyFile(epocroot, filePath));
+	}
+	
+	public void clearPkgObyFileList () {
+		pkgObyFileList.clear();
+	}
+
+	public String getRomEpocroot () {
+		return romEpocroot;
+	}
+	
+	public void setRomEpocroot (String epocroot) {
+		romEpocroot = epocroot;
+	}
+
+	public void clearRomEpocroot () {
+		setRomEpocroot(""); //$NON-NLS-1$
+	}
+
+	public String getRomSymbolFile () {
+		return romSymbolFile;
+	}
+	
+	public void setRomSymbolFile (String filename) {
+		romSymbolFile = filename;
+	}
+
+	public void clearRomSymbolFile () {
+		setRomSymbolFile(""); //$NON-NLS-1$
+	}
+	
+	public String getRomObyFile () {
+		return romObyFile;
+	}
+	
+	public void setRomObyFile (String filename) {
+		romObyFile = filename;
+	}
+	
+	public void clearRomObyFile () {
+		setRomObyFile(""); //$NON-NLS-1$
+	}
+
+	public String[] getRofsSymbolFileList () {
+		return rofsSymbolFileList.toArray(new String[rofsSymbolFileList.size()]);
+	}
+	
+	public void addRofsSymbolFile (String filename) {
+		rofsSymbolFileList.add(filename);
+	}
+
+	public void clearRofsSymbolFileList () {
+		rofsSymbolFileList.clear();
+	}
+
+	public String[] getRofsObyFileList () {
+		return rofsObyFileList.toArray(new String[rofsObyFileList.size()]);
+	}
+	
+	public void addRofsObyFile (String filename) {
+		rofsObyFileList.add(filename);
+	}
+
+	public void clearRofsObyFileList () {
+		rofsObyFileList.clear();
+	}
+
+	public String getCustAbsolutePath () {
+		return custAbsolutePath;
+	}
+	
+	public void setCustAbsolutePath (String pathName) {
+		custAbsolutePath = pathName;
+	}
+
+	public void clearCustAbsolutePath () {
+		setCustAbsolutePath(""); //$NON-NLS-1$
+	}
+
+	public boolean getCustIsValueBased () {
+		return custIsValueBased;
+	}
+	
+	public void setCustIsValueBased (boolean value) {
+		custIsValueBased = value;
+	}
+
+	public void clearCustIsValueBased () {
+		setCustIsValueBased(true);
+	}
+	
+	public String getCustDelimitor () {
+		return custDelimitor;
+	}
+	
+	public void setCustDelimitor (String delimitor) {
+		custDelimitor = delimitor;
+	}
+
+	public void clearCustDelimitor () {
+		setCustDelimitor(""); //$NON-NLS-1$
+	}
+	
+	public String getBupMapProfileId() {
+		return bupMapProfileId;
+	}
+
+	public void setBupMapProfileId(String bupMapProfileId) {
+		this.bupMapProfileId = bupMapProfileId;
+	}
+	
+	public void clearBupMapProfileId() {
+		setBupMapProfileId("");	//$NON-NLS-1$
+	}
+
+	public String getBupMapSymbianSDKId() {
+		return bupMapSymbianSDKId;
+	}
+
+	public void setBupMapSymbianSDKId(String bupMapSymbianSDKId) {
+		this.bupMapSymbianSDKId = bupMapSymbianSDKId != null ? bupMapSymbianSDKId : "";	//$NON-NLS-1$
+	}
+	
+	public void clearBupMapSymbianSDKId() {
+		setBupMapSymbianSDKId("");	//$NON-NLS-1$
+	}
+
+	public boolean isBupMapIsBuiltIn() {
+		return bupMapIsBuiltIn;
+	}
+
+	public void setBupMapIsBuiltIn(boolean bupMapIsBuiltIn) {
+		this.bupMapIsBuiltIn = bupMapIsBuiltIn;
+	}
+	
+	public void clearBupMapIsBuiltIn() {
+		setBupMapIsBuiltIn(false);
+	}
+
+	public boolean isBupMapIsWorkspace() {
+		return bupMapIsWorkspace;
+	}
+
+	public void setBupMapIsWorkspace(boolean bupMapIsWorkspace) {
+		this.bupMapIsWorkspace = bupMapIsWorkspace;
+	}
+
+	public void clearBupMapIsWorkspace() {
+		setBupMapIsWorkspace(false);
+	}
+
+	public void clear() {
+		clearDatFileName ();
+		clearProjectName ();
+		clearPiFileName ();
+		clearPkgObyFileList ();
+		clearRomEpocroot ();
+		clearRomSymbolFile ();
+		clearRomObyFile ();
+		clearRofsSymbolFileList ();
+		clearRofsObyFileList ();
+		clearCustAbsolutePath ();
+		clearCustIsValueBased ();
+		clearCustDelimitor ();
+		clearBupMapProfileId ();
+		clearBupMapSymbianSDKId ();
+		clearBupMapIsBuiltIn ();
+		clearBupMapIsWorkspace ();
+	}
+	
+	public boolean validate () {
+		if (getDatFileName().equals("")) { //$NON-NLS-1$
+			return false;
+		} else if (new java.io.File(getDatFileName()).exists() == false) {
+			return false;
+		}
+		
+		if (getProjectName().equals("")) {	//$NON-NLS-1$
+			return false;
+		}
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IResource resource = root.findMember(getProjectName());
+		if (resource.exists() == false) {
+			return false;
+		}
+		
+		if (getPiFileName().equals("")) {	//$NON-NLS-1$
+			return false;
+		}
+		
+		if (getRomEpocroot().equals("") != false) {	//$NON-NLS-1$
+			if (getRomSymbolFile().equals("") == false) { 	//$NON-NLS-1$
+				if (new java.io.File(getRomSymbolFile()).exists() == false) {
+					return false;
+				}
+			}
+			
+			if (getRomObyFile().equals("") == false) { 	//$NON-NLS-1$
+				if (new java.io.File(getRomObyFile()).exists() == false) {
+					return false;
+				}
+			}
+			
+			for (String fileName : getRofsObyFileList()) {
+				if (fileName.equals("") == false) {	//$NON-NLS-1$
+					if (new java.io.File(fileName).exists() == false) {
+						return false;
+					}
+				}	
+			}			
+		}
+		
+		if (pkgObyFileList.size() < 0) {
+			return false;
+		}
+		
+		return true;
+	}
+
+	public void importSamples(boolean pollTillNpiSaved) {
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IResource resource = root.findMember(getProjectName());
+		
+		IContainer piContainer;
+		if (resource instanceof IContainer) {
+			piContainer = (IContainer) resource;
+		} else {
+			return;
+		}
+		
+		// empty file if there is no symbol file specified, or analyser would crash
+		java.io.File dummySymbol = null;
+		if (getRomSymbolFile() == null || getRomSymbolFile().length() <= 0) {
+			try {
+				dummySymbol = java.io.File.createTempFile("dummySymbol", ".symbol");	//$NON-NLS-1$ //$NON-NLS-2$
+				setRomSymbolFile(dummySymbol.getAbsolutePath());
+			} catch (Exception e) {
+				e.printStackTrace();
+				return;
+			}
+		}
+
+		try {	
+			// import the new project according to wizard
+			piFile = piContainer.getFile(new Path(getPiFileName()));
+
+			if (piFile.exists())
+			{
+				piFile.delete(true, null);
+			}
+		} catch (CoreException e) {
+			GeneralMessages.showErrorMessage(com.nokia.carbide.cpp.pi.importer.Messages.getString("SampleImporter.importerInternalError"));  //$NON-NLS-1$
+			GeneralMessages.PiLog(com.nokia.carbide.cpp.pi.importer.Messages.getString("SampleImporter.importerCoreException"), GeneralMessages.ERROR);  //$NON-NLS-1$
+			return;
+		}
+		
+		// import and save the file as npi
+		AnalyserDataProcessor.getInstance().importSaveAndOpen(piFile, pollTillNpiSaved);
+		
+		if (dummySymbol != null) {
+			dummySymbol.delete();
+		}
+
+	}
+	
+	// support for removing timestamp to support test
+	public void stripeTimestamp(final String sourceFilePath, final String dstFilePath) {
+		IWorkspace workspace = ResourcesPlugin.getWorkspace();
+		final IProject piProjectHandle = ResourcesPlugin.getWorkspace().getRoot().getProject("pifilecompartor_temp"); //$NON-NLS-1$
+		final IProjectDescription description = workspace.newProjectDescription(piProjectHandle.getName());
+		SampleImporter sampleImporter = SampleImporter.getInstance();
+
+		// strip first file of timestamp by importer like trick
+		sampleImporter.setDatFileName(sourceFilePath);
+		sampleImporter.setPiFileName(dstFilePath);
+
+		setStripTimeStampActive();
+		
+		try {
+			if (!piProjectHandle.exists()) {
+				piProjectHandle.create(description, null);
+				piProjectHandle.open(null);
+			} else {
+				piProjectHandle.open(null);
+			}
+			
+			// import the new project according to wizard
+			IFile piFile = piProjectHandle.getFile("temp.npi"); //$NON-NLS-1$
+
+			if (piFile.exists())
+			{
+				piFile.delete(true, null);
+			}
+			// create the .pi on the project so IDE.openEditor works
+			piFile.create(new ByteArrayInputStream("".getBytes()), false, null); //$NON-NLS-1$
+
+			IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() , piFile, true);
+			// take out stalled temp.npi window
+			PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeAllEditors(true);
+
+		} catch (CoreException e) {
+			e.printStackTrace();
+		}
+		setStripTimeStampDone();
+	}
+		
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/pi/importer/messages.properties	Thu Feb 11 15:32:31 2010 +0200
@@ -0,0 +1,2 @@
+SampleImporter.importerInternalError=Importer internal error
+SampleImporter.importerCoreException=Importer CoreException